diff --git a/.DS_Store b/.DS_Store
new file mode 100644
index 0000000..5008ddf
Binary files /dev/null and b/.DS_Store differ
diff --git a/.hbuilderx/launch.json b/.hbuilderx/launch.json
new file mode 100644
index 0000000..32f4dc5
--- /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": [{
+ "default" :
+ {
+ "launchtype" : "local"
+ },
+ "h5" :
+ {
+ "launchtype" : "local"
+ },
+ "mp-weixin" :
+ {
+ "launchtype" : "local"
+ },
+ "type" : "uniCloud"
+ }
+ ]
+}
diff --git a/App.vue b/App.vue
new file mode 100644
index 0000000..62fcb32
--- /dev/null
+++ b/App.vue
@@ -0,0 +1,728 @@
+
+
+
diff --git a/common/http/index.js b/common/http/index.js
new file mode 100644
index 0000000..9c6008e
--- /dev/null
+++ b/common/http/index.js
@@ -0,0 +1,18 @@
+import http from './interface'
+
+/**
+ * 将业务所有接口统一起来便于维护
+ * 如果项目很大可以将 url 独立成文件,接口分成不同的模块
+ *
+ */
+export const doGet = (url,data) => {
+ return http.get(url,data);
+}
+export const doPost = (url,data) => {
+ return http.post(url,data);
+}
+// 默认全部导出 import api from '@/common/http/'
+export default {
+ doGet,
+ doPost
+}
\ No newline at end of file
diff --git a/common/http/interface.js b/common/http/interface.js
new file mode 100644
index 0000000..9ffc6cb
--- /dev/null
+++ b/common/http/interface.js
@@ -0,0 +1,244 @@
+/**
+ * 通用uni-app网络请求
+ * 基于 Promise 对象实现更简单的 request 使用方式,支持请求和响应拦截
+ */
+import config from '@/utils/config.js';
+import md5 from '@/utils/md5.js';
+import constant from "@/utils/constant"; //常量
+/*
+// 开放的接口
+import http from './interface'
+
+http.config.baseUrl = "http://localhost:8080/api/"
+
+http.request(url:'user/list',method:'GET').then((res)=>{
+ console.log(JSON.stringify(res))
+})
+http.get('user/list').then((res)=>{
+ console.log(JSON.stringify(res))
+})
+http.get('user/list', {status: 1}).then((res)=>{
+ console.log(JSON.stringify(res))
+})
+http.post('user', {id:1, status: 1}).then((res)=>{
+ console.log(JSON.stringify(res))
+})
+http.put('user/1', {status: 2}).then((res)=>{
+ console.log(JSON.stringify(res))
+})
+http.delete('user/1').then((res)=>{
+ console.log(JSON.stringify(res))
+})
+*/
+let requestList = {} //api请求记录
+// 将当前请求的api记录起来
+function addRequestKey(key) {
+ requestList[key] = true
+}
+// 将请求完成的api从记录中移除
+
+function removeRequestKey(key) {
+ delete requestList[key]
+}
+//当前请求的api是否已有记录
+function hitRequestKey(key) {
+ return requestList[key];
+}
+// 获取串行请求的key,方便记录
+function getLockRequestKey(url, data) {
+ let lockKey = url;
+ try {
+ if (data) {
+ lockKey += JSON.stringify(data)
+ }
+ } catch (e) {}
+ return lockKey;
+}
+//签名函数处理
+function getSign(jsondata) {
+ let arr = [];
+ for (let key in jsondata) {
+ if (key !== "sign") {
+ arr.push(key + "=" + jsondata[key]);
+ }
+ }
+ arr.sort();
+ let sign = decodeURIComponent(arr.join("") + "guagua");
+ return md5.md5(sign);
+}
+let that = null,lockKeyData = null;
+export default {
+ config: {
+ isWaiting: true,
+ baseUrl:config.baseUrl,
+ header: {
+ "Content-Type":"application/x-www-form-urlencoded"
+ },
+ data: {},
+ method: "GET",
+ dataType: "json",
+ /* 如设为json,会对返回的数据做一次 JSON.parse */
+ responseType: "text",
+ success(res) {
+ that.config.isWaiting && uni.hideLoading();
+ },
+ fail(res) {
+ that.config.isWaiting && uni.hideLoading();
+ },
+ complete() {
+
+ }
+ },
+ interceptor: {
+ request: null,
+ response: null
+ },
+ request(options) {
+ that = this;
+ if (!options) {
+ options = {}
+ }
+ options.baseUrl = options.baseUrl || this.config.baseUrl;
+ options.dataType = options.dataType || this.config.dataType;
+ options.url = options.baseUrl + options.url;
+ options.data = options.data || {};
+ options.method = options.method || this.config.method;
+ //添加参数自定义参数
+ lockKeyData = getLockRequestKey(options.url, options.data);
+ if (hitRequestKey(lockKeyData)) {
+ console.log(requestList)
+ return false;
+ }
+ addRequestKey(lockKeyData);
+ let isWaiting = true;
+ if (options.data && options.data.isWaiting === false) {
+ isWaiting = false;
+ delete options.data.isWaiting;
+ }
+ isWaiting && uni.showLoading({
+ title: '加载中',
+ mask: true
+ });
+ //TODO 加密数据
+ //TODO 数据签名
+
+ let loginInfo = uni.getStorageSync(constant.LOGIN_INFO) || {};
+ options.data.time = parseInt(new Date().getTime() / 1000);
+ if(loginInfo && loginInfo.UserId){
+ options.data.UserId = loginInfo.UserId;//用户id
+ }
+ this.config.header.loginTicket = loginInfo.loginTicket || ""; //防止数据串改
+ options.data.sign = getSign(options.data);
+
+ return new Promise((resolve, reject) => {
+ let _config = null;
+ options.complete = (response) => {
+ let statusCode = response.statusCode;
+ response.config = _config;
+ if (process.env.NODE_ENV === 'development') {
+ if (statusCode === 200) {
+ //console.log("【" + _config.requestId + "】 结果:" + JSON.stringify(response.data))
+ }
+ }
+ if (this.interceptor.response) {
+ let newResponse = this.interceptor.response(response);
+ if (newResponse) {
+ response = newResponse;
+ }
+ }
+ // 统一的响应日志记录
+ _reslog(response);
+ if (statusCode === 200) { //成功
+ resolve(response);
+ } else {
+ reject(response);
+ }
+ }
+ _config = Object.assign({}, this.config, options);
+ _config.requestId = new Date().getTime();
+
+ if (this.interceptor.request) {
+ this.interceptor.request(_config);
+ }
+ // 统一的请求日志记录
+ _reqlog(_config);
+ uni.request(_config);
+ });
+ },
+ get(url, data, options) {
+ if (!options) {
+ options = {}
+ }
+ options.url = url
+ options.data = data
+ options.method = 'GET'
+ return this.request(options)
+ },
+ post(url, data, options) {
+ if (!options) {
+ options = {}
+ }
+ options.url = url
+ options.data = data
+ options.method = 'POST'
+ return this.request(options)
+ },
+ put(url, data, options) {
+ if (!options) {
+ options = {}
+ }
+ options.url = url
+ options.data = data
+ options.method = 'PUT'
+ return this.request(options)
+ },
+ delete(url, data, options) {
+ if (!options) {
+ options = {}
+ }
+ options.url = url
+ options.data = data
+ options.method = 'DELETE'
+ return this.request(options)
+ }
+}
+
+
+/**
+ * 请求接口日志记录
+ */
+function _reqlog(req) {
+ removeRequestKey(lockKeyData); //删除请求的key
+ if (process.env.NODE_ENV === 'development') {
+ //console.log("【" + req.requestId + "】 地址:" + req.url)
+ if (req.data) {
+ console.log("【" + req.requestId + "】 请求参数:" + JSON.stringify(req.data))
+ }
+ }
+ //TODO 调接口异步写入日志数据库
+}
+
+/**
+ * 响应接口日志记录
+ */
+function _reslog(res) {
+ let _statusCode = res.statusCode;
+ if (process.env.NODE_ENV === 'development') {
+ //console.log("【" + res.config.requestId + "】 地址:" + res.config.url)
+ if (res.config.data) {
+ console.log("【" + res.config.requestId + "】 响应参数:" + JSON.stringify(res.config.data))
+ }
+ //console.log("【" + res.config.requestId + "】 响应结果:" + JSON.stringify(res))
+ }
+ //TODO 除了接口服务错误外,其他日志调接口异步写入日志数据库
+ switch (_statusCode) {
+ case 200:
+ break;
+ case 401:
+ break;
+ case 404:
+ break;
+ default:
+ break;
+ }
+}
diff --git a/common/index.scss b/common/index.scss
new file mode 100644
index 0000000..81109f3
--- /dev/null
+++ b/common/index.scss
@@ -0,0 +1,91 @@
+/**
+ * 单文件样式
+ * 请勿使用
+ */
+
+.u-dropdown__menu__item:last-child {
+ margin-right: 21rpx;
+ margin-left: 143rpx;
+ background-color: #eeeeee;
+ border-radius: 26rpx;
+ height: 55rpx;
+ width: 144rpx;
+ font-size: 28rpx;
+ // background-image: url('https://niangao.oss-cn-hangzhou.aliyuncs.com/ouhai_xcx/public/icon-map.png');
+
+ // background-size: 38rpx 38rpx;
+ background-repeat: no-repeat;
+ background-size: contain;
+ margin-top: 10rpx;
+ box-shadow: 0 3rpx 10rpx rgba(0,0,0,0.3);
+ .u-dropdown__menu__item__text{
+ margin-left: 50rpx;
+ }
+ .u-icon__icon {
+ display: none;
+ }
+}
+
+.title-container {
+ height: 35rpx;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+
+ .content {
+ display: flex;
+ align-items: center;
+
+ .title {
+ color: #2a2a2a;
+ font-weight: bold;
+ font-size: 36rpx;
+ font-family: PingFang SC;
+ }
+
+ .level {
+ text-align: center;
+ width: 58rpx;
+ height: 33rpx;
+ background: #fff1eb;
+ border-radius: 4rpx;
+ font-size: 22rpx;
+ font-family: DIN;
+ font-weight: bold;
+ color: #ff540b;
+ margin-left: 10rpx;
+ }
+ }
+}
+
+.price-container {
+ font-family: DIN;
+ font-weight: bold;
+ color: #ff540b;
+ .name {
+ font-size: 24rpx;
+ font-family: PingFang SC;
+ color: #333333;
+ margin-right: 11rpx;
+ }
+
+ .symbol {
+ margin-right: 5rpx;
+ }
+
+ .price {
+ font-size: 42rpx;
+ }
+
+ .qi {
+ color: #666666;
+ font-size: 20rpx;
+ margin-left: 10rpx;
+ }
+}
+.oldPrice {
+ text-decoration: line-through;
+ color: #979797;
+ font-size: 24rpx;
+ font-weight: 400;
+}
diff --git a/components/countdown-timer/countdown-timer.vue b/components/countdown-timer/countdown-timer.vue
new file mode 100644
index 0000000..1ad32de
--- /dev/null
+++ b/components/countdown-timer/countdown-timer.vue
@@ -0,0 +1,99 @@
+
+
+
+
+
diff --git a/components/css/animate.min.css b/components/css/animate.min.css
new file mode 100644
index 0000000..06b3100
--- /dev/null
+++ b/components/css/animate.min.css
@@ -0,0 +1,3492 @@
+@charset "UTF-8";
+
+/*!
+Animate.css - http://daneden.me/animate
+Licensed under the MIT license - http://opensource.org/licenses/MIT
+
+Copyright (c) 2015 Daniel Eden
+*/
+.animated {
+ -webkit-animation-duration: 1s;
+ animation-duration: 1s;
+ -webkit-animation-fill-mode: both;
+ animation-fill-mode: both
+}
+
+.animated.infinite {
+ -webkit-animation-iteration-count: infinite;
+ animation-iteration-count: infinite
+}
+
+.animated.hinge {
+ -webkit-animation-duration: 2s;
+ animation-duration: 2s
+}
+
+@-webkit-keyframes bounce {
+
+ 0%,
+ 100%,
+ 20%,
+ 53%,
+ 80% {
+ -webkit-transition-timing-function: cubic-bezier(0.215, .61, .355, 1);
+ transition-timing-function: cubic-bezier(0.215, .61, .355, 1);
+ -webkit-transform: translate3d(0, 0, 0);
+ transform: translate3d(0, 0, 0)
+ }
+
+ 40%,
+ 43% {
+ -webkit-transition-timing-function: cubic-bezier(0.755, .050, .855, .060);
+ transition-timing-function: cubic-bezier(0.755, .050, .855, .060);
+ -webkit-transform: translate3d(0, -30px, 0);
+ transform: translate3d(0, -30px, 0)
+ }
+
+ 70% {
+ -webkit-transition-timing-function: cubic-bezier(0.755, .050, .855, .060);
+ transition-timing-function: cubic-bezier(0.755, .050, .855, .060);
+ -webkit-transform: translate3d(0, -15px, 0);
+ transform: translate3d(0, -15px, 0)
+ }
+
+ 90% {
+ -webkit-transform: translate3d(0, -4px, 0);
+ transform: translate3d(0, -4px, 0)
+ }
+}
+
+@keyframes bounce {
+
+ 0%,
+ 100%,
+ 20%,
+ 53%,
+ 80% {
+ -webkit-transition-timing-function: cubic-bezier(0.215, .61, .355, 1);
+ transition-timing-function: cubic-bezier(0.215, .61, .355, 1);
+ -webkit-transform: translate3d(0, 0, 0);
+ -ms-transform: translate3d(0, 0, 0);
+ transform: translate3d(0, 0, 0)
+ }
+
+ 40%,
+ 43% {
+ -webkit-transition-timing-function: cubic-bezier(0.755, .050, .855, .060);
+ transition-timing-function: cubic-bezier(0.755, .050, .855, .060);
+ -webkit-transform: translate3d(0, -30px, 0);
+ -ms-transform: translate3d(0, -30px, 0);
+ transform: translate3d(0, -30px, 0)
+ }
+
+ 70% {
+ -webkit-transition-timing-function: cubic-bezier(0.755, .050, .855, .060);
+ transition-timing-function: cubic-bezier(0.755, .050, .855, .060);
+ -webkit-transform: translate3d(0, -15px, 0);
+ -ms-transform: translate3d(0, -15px, 0);
+ transform: translate3d(0, -15px, 0)
+ }
+
+ 90% {
+ -webkit-transform: translate3d(0, -4px, 0);
+ -ms-transform: translate3d(0, -4px, 0);
+ transform: translate3d(0, -4px, 0)
+ }
+}
+
+.bounce {
+ -webkit-animation-name: bounce;
+ animation-name: bounce;
+ -webkit-transform-origin: center bottom;
+ -ms-transform-origin: center bottom;
+ transform-origin: center bottom
+}
+
+@-webkit-keyframes flash {
+
+ 0%,
+ 100%,
+ 50% {
+ opacity: 1
+ }
+
+ 25%,
+ 75% {
+ opacity: 0
+ }
+}
+
+@keyframes flash {
+
+ 0%,
+ 100%,
+ 50% {
+ opacity: 1
+ }
+
+ 25%,
+ 75% {
+ opacity: 0
+ }
+}
+
+.flash {
+ -webkit-animation-name: flash;
+ animation-name: flash
+}
+
+@-webkit-keyframes pulse {
+ 0% {
+ -webkit-transform: scale3d(1, 1, 1);
+ transform: scale3d(1, 1, 1)
+ }
+
+ 50% {
+ -webkit-transform: scale3d(1.05, 1.05, 1.05);
+ transform: scale3d(1.05, 1.05, 1.05)
+ }
+
+ 100% {
+ -webkit-transform: scale3d(1, 1, 1);
+ transform: scale3d(1, 1, 1)
+ }
+}
+
+@keyframes pulse {
+ 0% {
+ -webkit-transform: scale3d(1, 1, 1);
+ -ms-transform: scale3d(1, 1, 1);
+ transform: scale3d(1, 1, 1)
+ }
+
+ 50% {
+ -webkit-transform: scale3d(1.05, 1.05, 1.05);
+ -ms-transform: scale3d(1.05, 1.05, 1.05);
+ transform: scale3d(1.05, 1.05, 1.05)
+ }
+
+ 100% {
+ -webkit-transform: scale3d(1, 1, 1);
+ -ms-transform: scale3d(1, 1, 1);
+ transform: scale3d(1, 1, 1)
+ }
+}
+
+.pulse {
+ -webkit-animation-name: pulse;
+ animation-name: pulse
+}
+
+@-webkit-keyframes rubberBand {
+ 0% {
+ -webkit-transform: scale3d(1, 1, 1);
+ transform: scale3d(1, 1, 1)
+ }
+
+ 30% {
+ -webkit-transform: scale3d(1.25, .75, 1);
+ transform: scale3d(1.25, .75, 1)
+ }
+
+ 40% {
+ -webkit-transform: scale3d(0.75, 1.25, 1);
+ transform: scale3d(0.75, 1.25, 1)
+ }
+
+ 50% {
+ -webkit-transform: scale3d(1.15, .85, 1);
+ transform: scale3d(1.15, .85, 1)
+ }
+
+ 65% {
+ -webkit-transform: scale3d(.95, 1.05, 1);
+ transform: scale3d(.95, 1.05, 1)
+ }
+
+ 75% {
+ -webkit-transform: scale3d(1.05, .95, 1);
+ transform: scale3d(1.05, .95, 1)
+ }
+
+ 100% {
+ -webkit-transform: scale3d(1, 1, 1);
+ transform: scale3d(1, 1, 1)
+ }
+}
+
+@keyframes rubberBand {
+ 0% {
+ -webkit-transform: scale3d(1, 1, 1);
+ -ms-transform: scale3d(1, 1, 1);
+ transform: scale3d(1, 1, 1)
+ }
+
+ 30% {
+ -webkit-transform: scale3d(1.25, .75, 1);
+ -ms-transform: scale3d(1.25, .75, 1);
+ transform: scale3d(1.25, .75, 1)
+ }
+
+ 40% {
+ -webkit-transform: scale3d(0.75, 1.25, 1);
+ -ms-transform: scale3d(0.75, 1.25, 1);
+ transform: scale3d(0.75, 1.25, 1)
+ }
+
+ 50% {
+ -webkit-transform: scale3d(1.15, .85, 1);
+ -ms-transform: scale3d(1.15, .85, 1);
+ transform: scale3d(1.15, .85, 1)
+ }
+
+ 65% {
+ -webkit-transform: scale3d(.95, 1.05, 1);
+ -ms-transform: scale3d(.95, 1.05, 1);
+ transform: scale3d(.95, 1.05, 1)
+ }
+
+ 75% {
+ -webkit-transform: scale3d(1.05, .95, 1);
+ -ms-transform: scale3d(1.05, .95, 1);
+ transform: scale3d(1.05, .95, 1)
+ }
+
+ 100% {
+ -webkit-transform: scale3d(1, 1, 1);
+ -ms-transform: scale3d(1, 1, 1);
+ transform: scale3d(1, 1, 1)
+ }
+}
+
+.rubberBand {
+ -webkit-animation-name: rubberBand;
+ animation-name: rubberBand
+}
+
+@-webkit-keyframes shake {
+
+ 0%,
+ 100% {
+ -webkit-transform: translate3d(0, 0, 0);
+ transform: translate3d(0, 0, 0)
+ }
+
+ 10%,
+ 30%,
+ 50%,
+ 70%,
+ 90% {
+ -webkit-transform: translate3d(-10px, 0, 0);
+ transform: translate3d(-10px, 0, 0)
+ }
+
+ 20%,
+ 40%,
+ 60%,
+ 80% {
+ -webkit-transform: translate3d(10px, 0, 0);
+ transform: translate3d(10px, 0, 0)
+ }
+}
+
+@keyframes shake {
+
+ 0%,
+ 100% {
+ -webkit-transform: translate3d(0, 0, 0);
+ -ms-transform: translate3d(0, 0, 0);
+ transform: translate3d(0, 0, 0)
+ }
+
+ 10%,
+ 30%,
+ 50%,
+ 70%,
+ 90% {
+ -webkit-transform: translate3d(-10px, 0, 0);
+ -ms-transform: translate3d(-10px, 0, 0);
+ transform: translate3d(-10px, 0, 0)
+ }
+
+ 20%,
+ 40%,
+ 60%,
+ 80% {
+ -webkit-transform: translate3d(10px, 0, 0);
+ -ms-transform: translate3d(10px, 0, 0);
+ transform: translate3d(10px, 0, 0)
+ }
+}
+
+.shake {
+ -webkit-animation-name: shake;
+ animation-name: shake
+}
+
+@-webkit-keyframes swing {
+ 20% {
+ -webkit-transform: rotate3d(0, 0, 1, 15deg);
+ transform: rotate3d(0, 0, 1, 15deg)
+ }
+
+ 40% {
+ -webkit-transform: rotate3d(0, 0, 1, -10deg);
+ transform: rotate3d(0, 0, 1, -10deg)
+ }
+
+ 60% {
+ -webkit-transform: rotate3d(0, 0, 1, 5deg);
+ transform: rotate3d(0, 0, 1, 5deg)
+ }
+
+ 80% {
+ -webkit-transform: rotate3d(0, 0, 1, -5deg);
+ transform: rotate3d(0, 0, 1, -5deg)
+ }
+
+ 100% {
+ -webkit-transform: rotate3d(0, 0, 1, 0deg);
+ transform: rotate3d(0, 0, 1, 0deg)
+ }
+}
+
+@keyframes swing {
+ 20% {
+ -webkit-transform: rotate3d(0, 0, 1, 15deg);
+ -ms-transform: rotate3d(0, 0, 1, 15deg);
+ transform: rotate3d(0, 0, 1, 15deg)
+ }
+
+ 40% {
+ -webkit-transform: rotate3d(0, 0, 1, -10deg);
+ -ms-transform: rotate3d(0, 0, 1, -10deg);
+ transform: rotate3d(0, 0, 1, -10deg)
+ }
+
+ 60% {
+ -webkit-transform: rotate3d(0, 0, 1, 5deg);
+ -ms-transform: rotate3d(0, 0, 1, 5deg);
+ transform: rotate3d(0, 0, 1, 5deg)
+ }
+
+ 80% {
+ -webkit-transform: rotate3d(0, 0, 1, -5deg);
+ -ms-transform: rotate3d(0, 0, 1, -5deg);
+ transform: rotate3d(0, 0, 1, -5deg)
+ }
+
+ 100% {
+ -webkit-transform: rotate3d(0, 0, 1, 0deg);
+ -ms-transform: rotate3d(0, 0, 1, 0deg);
+ transform: rotate3d(0, 0, 1, 0deg)
+ }
+}
+
+.swing {
+ -webkit-transform-origin: top center;
+ -ms-transform-origin: top center;
+ transform-origin: top center;
+ -webkit-animation-name: swing;
+ animation-name: swing
+}
+
+@-webkit-keyframes tada {
+ 0% {
+ -webkit-transform: scale3d(1, 1, 1);
+ transform: scale3d(1, 1, 1)
+ }
+
+ 10%,
+ 20% {
+ -webkit-transform: scale3d(.9, .9, .9) rotate3d(0, 0, 1, -3deg);
+ transform: scale3d(.9, .9, .9) rotate3d(0, 0, 1, -3deg)
+ }
+
+ 30%,
+ 50%,
+ 70%,
+ 90% {
+ -webkit-transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg);
+ transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg)
+ }
+
+ 40%,
+ 60%,
+ 80% {
+ -webkit-transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg);
+ transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg)
+ }
+
+ 100% {
+ -webkit-transform: scale3d(1, 1, 1);
+ transform: scale3d(1, 1, 1)
+ }
+}
+
+@keyframes tada {
+ 0% {
+ -webkit-transform: scale3d(1, 1, 1);
+ -ms-transform: scale3d(1, 1, 1);
+ transform: scale3d(1, 1, 1)
+ }
+
+ 10%,
+ 20% {
+ -webkit-transform: scale3d(.9, .9, .9) rotate3d(0, 0, 1, -3deg);
+ -ms-transform: scale3d(.9, .9, .9) rotate3d(0, 0, 1, -3deg);
+ transform: scale3d(.9, .9, .9) rotate3d(0, 0, 1, -3deg)
+ }
+
+ 30%,
+ 50%,
+ 70%,
+ 90% {
+ -webkit-transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg);
+ -ms-transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg);
+ transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg)
+ }
+
+ 40%,
+ 60%,
+ 80% {
+ -webkit-transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg);
+ -ms-transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg);
+ transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg)
+ }
+
+ 100% {
+ -webkit-transform: scale3d(1, 1, 1);
+ -ms-transform: scale3d(1, 1, 1);
+ transform: scale3d(1, 1, 1)
+ }
+}
+
+.tada {
+ -webkit-animation-name: tada;
+ animation-name: tada
+}
+
+@-webkit-keyframes wobble {
+ 0% {
+ -webkit-transform: none;
+ transform: none
+ }
+
+ 15% {
+ -webkit-transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg);
+ transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg)
+ }
+
+ 30% {
+ -webkit-transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg);
+ transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg)
+ }
+
+ 45% {
+ -webkit-transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg);
+ transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg)
+ }
+
+ 60% {
+ -webkit-transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg);
+ transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg)
+ }
+
+ 75% {
+ -webkit-transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg);
+ transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg)
+ }
+
+ 100% {
+ -webkit-transform: none;
+ transform: none
+ }
+}
+
+@keyframes wobble {
+ 0% {
+ -webkit-transform: none;
+ -ms-transform: none;
+ transform: none
+ }
+
+ 15% {
+ -webkit-transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg);
+ -ms-transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg);
+ transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg)
+ }
+
+ 30% {
+ -webkit-transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg);
+ -ms-transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg);
+ transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg)
+ }
+
+ 45% {
+ -webkit-transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg);
+ -ms-transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg);
+ transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg)
+ }
+
+ 60% {
+ -webkit-transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg);
+ -ms-transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg);
+ transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg)
+ }
+
+ 75% {
+ -webkit-transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg);
+ -ms-transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg);
+ transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg)
+ }
+
+ 100% {
+ -webkit-transform: none;
+ -ms-transform: none;
+ transform: none
+ }
+}
+
+.wobble {
+ -webkit-animation-name: wobble;
+ animation-name: wobble
+}
+
+@-webkit-keyframes bounceIn {
+
+ 0%,
+ 100%,
+ 20%,
+ 40%,
+ 60%,
+ 80% {
+ -webkit-transition-timing-function: cubic-bezier(0.215, .61, .355, 1);
+ transition-timing-function: cubic-bezier(0.215, .61, .355, 1)
+ }
+
+ 0% {
+ opacity: 0;
+ -webkit-transform: scale3d(.3, .3, .3);
+ transform: scale3d(.3, .3, .3)
+ }
+
+ 20% {
+ -webkit-transform: scale3d(1.1, 1.1, 1.1);
+ transform: scale3d(1.1, 1.1, 1.1)
+ }
+
+ 40% {
+ -webkit-transform: scale3d(.9, .9, .9);
+ transform: scale3d(.9, .9, .9)
+ }
+
+ 60% {
+ opacity: 1;
+ -webkit-transform: scale3d(1.03, 1.03, 1.03);
+ transform: scale3d(1.03, 1.03, 1.03)
+ }
+
+ 80% {
+ -webkit-transform: scale3d(.97, .97, .97);
+ transform: scale3d(.97, .97, .97)
+ }
+
+ 100% {
+ opacity: 1;
+ -webkit-transform: scale3d(1, 1, 1);
+ transform: scale3d(1, 1, 1)
+ }
+}
+
+@keyframes bounceIn {
+
+ 0%,
+ 100%,
+ 20%,
+ 40%,
+ 60%,
+ 80% {
+ -webkit-transition-timing-function: cubic-bezier(0.215, .61, .355, 1);
+ transition-timing-function: cubic-bezier(0.215, .61, .355, 1)
+ }
+
+ 0% {
+ opacity: 0;
+ -webkit-transform: scale3d(.3, .3, .3);
+ -ms-transform: scale3d(.3, .3, .3);
+ transform: scale3d(.3, .3, .3)
+ }
+
+ 20% {
+ -webkit-transform: scale3d(1.1, 1.1, 1.1);
+ -ms-transform: scale3d(1.1, 1.1, 1.1);
+ transform: scale3d(1.1, 1.1, 1.1)
+ }
+
+ 40% {
+ -webkit-transform: scale3d(.9, .9, .9);
+ -ms-transform: scale3d(.9, .9, .9);
+ transform: scale3d(.9, .9, .9)
+ }
+
+ 60% {
+ opacity: 1;
+ -webkit-transform: scale3d(1.03, 1.03, 1.03);
+ -ms-transform: scale3d(1.03, 1.03, 1.03);
+ transform: scale3d(1.03, 1.03, 1.03)
+ }
+
+ 80% {
+ -webkit-transform: scale3d(.97, .97, .97);
+ -ms-transform: scale3d(.97, .97, .97);
+ transform: scale3d(.97, .97, .97)
+ }
+
+ 100% {
+ opacity: 1;
+ -webkit-transform: scale3d(1, 1, 1);
+ -ms-transform: scale3d(1, 1, 1);
+ transform: scale3d(1, 1, 1)
+ }
+}
+
+.bounceIn {
+ -webkit-animation-name: bounceIn;
+ animation-name: bounceIn;
+ -webkit-animation-duration: .75s;
+ animation-duration: .75s
+}
+
+@-webkit-keyframes bounceInDown {
+
+ 0%,
+ 100%,
+ 60%,
+ 75%,
+ 90% {
+ -webkit-transition-timing-function: cubic-bezier(0.215, .61, .355, 1);
+ transition-timing-function: cubic-bezier(0.215, .61, .355, 1)
+ }
+
+ 0% {
+ opacity: 0;
+ -webkit-transform: translate3d(0, -3000px, 0);
+ transform: translate3d(0, -3000px, 0)
+ }
+
+ 60% {
+ opacity: 1;
+ -webkit-transform: translate3d(0, 25px, 0);
+ transform: translate3d(0, 25px, 0)
+ }
+
+ 75% {
+ -webkit-transform: translate3d(0, -10px, 0);
+ transform: translate3d(0, -10px, 0)
+ }
+
+ 90% {
+ -webkit-transform: translate3d(0, 5px, 0);
+ transform: translate3d(0, 5px, 0)
+ }
+
+ 100% {
+ -webkit-transform: none;
+ transform: none
+ }
+}
+
+@keyframes bounceInDown {
+
+ 0%,
+ 100%,
+ 60%,
+ 75%,
+ 90% {
+ -webkit-transition-timing-function: cubic-bezier(0.215, .61, .355, 1);
+ transition-timing-function: cubic-bezier(0.215, .61, .355, 1)
+ }
+
+ 0% {
+ opacity: 0;
+ -webkit-transform: translate3d(0, -3000px, 0);
+ -ms-transform: translate3d(0, -3000px, 0);
+ transform: translate3d(0, -3000px, 0)
+ }
+
+ 60% {
+ opacity: 1;
+ -webkit-transform: translate3d(0, 25px, 0);
+ -ms-transform: translate3d(0, 25px, 0);
+ transform: translate3d(0, 25px, 0)
+ }
+
+ 75% {
+ -webkit-transform: translate3d(0, -10px, 0);
+ -ms-transform: translate3d(0, -10px, 0);
+ transform: translate3d(0, -10px, 0)
+ }
+
+ 90% {
+ -webkit-transform: translate3d(0, 5px, 0);
+ -ms-transform: translate3d(0, 5px, 0);
+ transform: translate3d(0, 5px, 0)
+ }
+
+ 100% {
+ -webkit-transform: none;
+ -ms-transform: none;
+ transform: none
+ }
+}
+
+.bounceInDown {
+ -webkit-animation-name: bounceInDown;
+ animation-name: bounceInDown
+}
+
+@-webkit-keyframes bounceInLeft {
+
+ 0%,
+ 100%,
+ 60%,
+ 75%,
+ 90% {
+ -webkit-transition-timing-function: cubic-bezier(0.215, .61, .355, 1);
+ transition-timing-function: cubic-bezier(0.215, .61, .355, 1)
+ }
+
+ 0% {
+ opacity: 0;
+ -webkit-transform: translate3d(-3000px, 0, 0);
+ transform: translate3d(-3000px, 0, 0)
+ }
+
+ 60% {
+ opacity: 1;
+ -webkit-transform: translate3d(25px, 0, 0);
+ transform: translate3d(25px, 0, 0)
+ }
+
+ 75% {
+ -webkit-transform: translate3d(-10px, 0, 0);
+ transform: translate3d(-10px, 0, 0)
+ }
+
+ 90% {
+ -webkit-transform: translate3d(5px, 0, 0);
+ transform: translate3d(5px, 0, 0)
+ }
+
+ 100% {
+ -webkit-transform: none;
+ transform: none
+ }
+}
+
+@keyframes bounceInLeft {
+
+ 0%,
+ 100%,
+ 60%,
+ 75%,
+ 90% {
+ -webkit-transition-timing-function: cubic-bezier(0.215, .61, .355, 1);
+ transition-timing-function: cubic-bezier(0.215, .61, .355, 1)
+ }
+
+ 0% {
+ opacity: 0;
+ -webkit-transform: translate3d(-3000px, 0, 0);
+ -ms-transform: translate3d(-3000px, 0, 0);
+ transform: translate3d(-3000px, 0, 0)
+ }
+
+ 60% {
+ opacity: 1;
+ -webkit-transform: translate3d(25px, 0, 0);
+ -ms-transform: translate3d(25px, 0, 0);
+ transform: translate3d(25px, 0, 0)
+ }
+
+ 75% {
+ -webkit-transform: translate3d(-10px, 0, 0);
+ -ms-transform: translate3d(-10px, 0, 0);
+ transform: translate3d(-10px, 0, 0)
+ }
+
+ 90% {
+ -webkit-transform: translate3d(5px, 0, 0);
+ -ms-transform: translate3d(5px, 0, 0);
+ transform: translate3d(5px, 0, 0)
+ }
+
+ 100% {
+ -webkit-transform: none;
+ -ms-transform: none;
+ transform: none
+ }
+}
+
+.bounceInLeft {
+ -webkit-animation-name: bounceInLeft;
+ animation-name: bounceInLeft
+}
+
+@-webkit-keyframes bounceInRight {
+
+ 0%,
+ 100%,
+ 60%,
+ 75%,
+ 90% {
+ -webkit-transition-timing-function: cubic-bezier(0.215, .61, .355, 1);
+ transition-timing-function: cubic-bezier(0.215, .61, .355, 1)
+ }
+
+ 0% {
+ opacity: 0;
+ -webkit-transform: translate3d(3000px, 0, 0);
+ transform: translate3d(3000px, 0, 0)
+ }
+
+ 60% {
+ opacity: 1;
+ -webkit-transform: translate3d(-25px, 0, 0);
+ transform: translate3d(-25px, 0, 0)
+ }
+
+ 75% {
+ -webkit-transform: translate3d(10px, 0, 0);
+ transform: translate3d(10px, 0, 0)
+ }
+
+ 90% {
+ -webkit-transform: translate3d(-5px, 0, 0);
+ transform: translate3d(-5px, 0, 0)
+ }
+
+ 100% {
+ -webkit-transform: none;
+ transform: none
+ }
+}
+
+@keyframes bounceInRight {
+
+ 0%,
+ 100%,
+ 60%,
+ 75%,
+ 90% {
+ -webkit-transition-timing-function: cubic-bezier(0.215, .61, .355, 1);
+ transition-timing-function: cubic-bezier(0.215, .61, .355, 1)
+ }
+
+ 0% {
+ opacity: 0;
+ -webkit-transform: translate3d(3000px, 0, 0);
+ -ms-transform: translate3d(3000px, 0, 0);
+ transform: translate3d(3000px, 0, 0)
+ }
+
+ 60% {
+ opacity: 1;
+ -webkit-transform: translate3d(-25px, 0, 0);
+ -ms-transform: translate3d(-25px, 0, 0);
+ transform: translate3d(-25px, 0, 0)
+ }
+
+ 75% {
+ -webkit-transform: translate3d(10px, 0, 0);
+ -ms-transform: translate3d(10px, 0, 0);
+ transform: translate3d(10px, 0, 0)
+ }
+
+ 90% {
+ -webkit-transform: translate3d(-5px, 0, 0);
+ -ms-transform: translate3d(-5px, 0, 0);
+ transform: translate3d(-5px, 0, 0)
+ }
+
+ 100% {
+ -webkit-transform: none;
+ -ms-transform: none;
+ transform: none
+ }
+}
+
+.bounceInRight {
+ -webkit-animation-name: bounceInRight;
+ animation-name: bounceInRight
+}
+
+@-webkit-keyframes bounceInUp {
+
+ 0%,
+ 100%,
+ 60%,
+ 75%,
+ 90% {
+ -webkit-transition-timing-function: cubic-bezier(0.215, .61, .355, 1);
+ transition-timing-function: cubic-bezier(0.215, .61, .355, 1)
+ }
+
+ 0% {
+ opacity: 0;
+ -webkit-transform: translate3d(0, 3000px, 0);
+ transform: translate3d(0, 3000px, 0)
+ }
+
+ 60% {
+ opacity: 1;
+ -webkit-transform: translate3d(0, -20px, 0);
+ transform: translate3d(0, -20px, 0)
+ }
+
+ 75% {
+ -webkit-transform: translate3d(0, 10px, 0);
+ transform: translate3d(0, 10px, 0)
+ }
+
+ 90% {
+ -webkit-transform: translate3d(0, -5px, 0);
+ transform: translate3d(0, -5px, 0)
+ }
+
+ 100% {
+ -webkit-transform: translate3d(0, 0, 0);
+ transform: translate3d(0, 0, 0)
+ }
+}
+
+@keyframes bounceInUp {
+
+ 0%,
+ 100%,
+ 60%,
+ 75%,
+ 90% {
+ -webkit-transition-timing-function: cubic-bezier(0.215, .61, .355, 1);
+ transition-timing-function: cubic-bezier(0.215, .61, .355, 1)
+ }
+
+ 0% {
+ opacity: 0;
+ -webkit-transform: translate3d(0, 3000px, 0);
+ -ms-transform: translate3d(0, 3000px, 0);
+ transform: translate3d(0, 3000px, 0)
+ }
+
+ 60% {
+ opacity: 1;
+ -webkit-transform: translate3d(0, -20px, 0);
+ -ms-transform: translate3d(0, -20px, 0);
+ transform: translate3d(0, -20px, 0)
+ }
+
+ 75% {
+ -webkit-transform: translate3d(0, 10px, 0);
+ -ms-transform: translate3d(0, 10px, 0);
+ transform: translate3d(0, 10px, 0)
+ }
+
+ 90% {
+ -webkit-transform: translate3d(0, -5px, 0);
+ -ms-transform: translate3d(0, -5px, 0);
+ transform: translate3d(0, -5px, 0)
+ }
+
+ 100% {
+ -webkit-transform: translate3d(0, 0, 0);
+ -ms-transform: translate3d(0, 0, 0);
+ transform: translate3d(0, 0, 0)
+ }
+}
+
+.bounceInUp {
+ -webkit-animation-name: bounceInUp;
+ animation-name: bounceInUp
+}
+
+@-webkit-keyframes bounceOut {
+ 20% {
+ -webkit-transform: scale3d(.9, .9, .9);
+ transform: scale3d(.9, .9, .9)
+ }
+
+ 50%,
+ 55% {
+ opacity: 1;
+ -webkit-transform: scale3d(1.1, 1.1, 1.1);
+ transform: scale3d(1.1, 1.1, 1.1)
+ }
+
+ 100% {
+ opacity: 0;
+ -webkit-transform: scale3d(.3, .3, .3);
+ transform: scale3d(.3, .3, .3)
+ }
+}
+
+@keyframes bounceOut {
+ 20% {
+ -webkit-transform: scale3d(.9, .9, .9);
+ -ms-transform: scale3d(.9, .9, .9);
+ transform: scale3d(.9, .9, .9)
+ }
+
+ 50%,
+ 55% {
+ opacity: 1;
+ -webkit-transform: scale3d(1.1, 1.1, 1.1);
+ -ms-transform: scale3d(1.1, 1.1, 1.1);
+ transform: scale3d(1.1, 1.1, 1.1)
+ }
+
+ 100% {
+ opacity: 0;
+ -webkit-transform: scale3d(.3, .3, .3);
+ -ms-transform: scale3d(.3, .3, .3);
+ transform: scale3d(.3, .3, .3)
+ }
+}
+
+.bounceOut {
+ -webkit-animation-name: bounceOut;
+ animation-name: bounceOut;
+ -webkit-animation-duration: .75s;
+ animation-duration: .75s
+}
+
+@-webkit-keyframes bounceOutDown {
+ 20% {
+ -webkit-transform: translate3d(0, 10px, 0);
+ transform: translate3d(0, 10px, 0)
+ }
+
+ 40%,
+ 45% {
+ opacity: 1;
+ -webkit-transform: translate3d(0, -20px, 0);
+ transform: translate3d(0, -20px, 0)
+ }
+
+ 100% {
+ opacity: 0;
+ -webkit-transform: translate3d(0, 2000px, 0);
+ transform: translate3d(0, 2000px, 0)
+ }
+}
+
+@keyframes bounceOutDown {
+ 20% {
+ -webkit-transform: translate3d(0, 10px, 0);
+ -ms-transform: translate3d(0, 10px, 0);
+ transform: translate3d(0, 10px, 0)
+ }
+
+ 40%,
+ 45% {
+ opacity: 1;
+ -webkit-transform: translate3d(0, -20px, 0);
+ -ms-transform: translate3d(0, -20px, 0);
+ transform: translate3d(0, -20px, 0)
+ }
+
+ 100% {
+ opacity: 0;
+ -webkit-transform: translate3d(0, 2000px, 0);
+ -ms-transform: translate3d(0, 2000px, 0);
+ transform: translate3d(0, 2000px, 0)
+ }
+}
+
+.bounceOutDown {
+ -webkit-animation-name: bounceOutDown;
+ animation-name: bounceOutDown
+}
+
+@-webkit-keyframes bounceOutLeft {
+ 20% {
+ opacity: 1;
+ -webkit-transform: translate3d(20px, 0, 0);
+ transform: translate3d(20px, 0, 0)
+ }
+
+ 100% {
+ opacity: 0;
+ -webkit-transform: translate3d(-2000px, 0, 0);
+ transform: translate3d(-2000px, 0, 0)
+ }
+}
+
+@keyframes bounceOutLeft {
+ 20% {
+ opacity: 1;
+ -webkit-transform: translate3d(20px, 0, 0);
+ -ms-transform: translate3d(20px, 0, 0);
+ transform: translate3d(20px, 0, 0)
+ }
+
+ 100% {
+ opacity: 0;
+ -webkit-transform: translate3d(-2000px, 0, 0);
+ -ms-transform: translate3d(-2000px, 0, 0);
+ transform: translate3d(-2000px, 0, 0)
+ }
+}
+
+.bounceOutLeft {
+ -webkit-animation-name: bounceOutLeft;
+ animation-name: bounceOutLeft
+}
+
+@-webkit-keyframes bounceOutRight {
+ 20% {
+ opacity: 1;
+ -webkit-transform: translate3d(-20px, 0, 0);
+ transform: translate3d(-20px, 0, 0)
+ }
+
+ 100% {
+ opacity: 0;
+ -webkit-transform: translate3d(2000px, 0, 0);
+ transform: translate3d(2000px, 0, 0)
+ }
+}
+
+@keyframes bounceOutRight {
+ 20% {
+ opacity: 1;
+ -webkit-transform: translate3d(-20px, 0, 0);
+ -ms-transform: translate3d(-20px, 0, 0);
+ transform: translate3d(-20px, 0, 0)
+ }
+
+ 100% {
+ opacity: 0;
+ -webkit-transform: translate3d(2000px, 0, 0);
+ -ms-transform: translate3d(2000px, 0, 0);
+ transform: translate3d(2000px, 0, 0)
+ }
+}
+
+.bounceOutRight {
+ -webkit-animation-name: bounceOutRight;
+ animation-name: bounceOutRight
+}
+
+@-webkit-keyframes bounceOutUp {
+ 20% {
+ -webkit-transform: translate3d(0, -10px, 0);
+ transform: translate3d(0, -10px, 0)
+ }
+
+ 40%,
+ 45% {
+ opacity: 1;
+ -webkit-transform: translate3d(0, 20px, 0);
+ transform: translate3d(0, 20px, 0)
+ }
+
+ 100% {
+ opacity: 0;
+ -webkit-transform: translate3d(0, -2000px, 0);
+ transform: translate3d(0, -2000px, 0)
+ }
+}
+
+@keyframes bounceOutUp {
+ 20% {
+ -webkit-transform: translate3d(0, -10px, 0);
+ -ms-transform: translate3d(0, -10px, 0);
+ transform: translate3d(0, -10px, 0)
+ }
+
+ 40%,
+ 45% {
+ opacity: 1;
+ -webkit-transform: translate3d(0, 20px, 0);
+ -ms-transform: translate3d(0, 20px, 0);
+ transform: translate3d(0, 20px, 0)
+ }
+
+ 100% {
+ opacity: 0;
+ -webkit-transform: translate3d(0, -2000px, 0);
+ -ms-transform: translate3d(0, -2000px, 0);
+ transform: translate3d(0, -2000px, 0)
+ }
+}
+
+.bounceOutUp {
+ -webkit-animation-name: bounceOutUp;
+ animation-name: bounceOutUp
+}
+
+@-webkit-keyframes fadeIn {
+ 0% {
+ opacity: 0
+ }
+
+ 100% {
+ opacity: 1
+ }
+}
+
+@keyframes fadeIn {
+ 0% {
+ opacity: 0
+ }
+
+ 100% {
+ opacity: 1
+ }
+}
+
+.fadeIn {
+ -webkit-animation-name: fadeIn;
+ animation-name: fadeIn
+}
+
+@-webkit-keyframes fadeInDown {
+ 0% {
+ opacity: 0;
+ -webkit-transform: translate3d(0, -100%, 0);
+ transform: translate3d(0, -100%, 0)
+ }
+
+ 100% {
+ opacity: 1;
+ -webkit-transform: none;
+ transform: none
+ }
+}
+
+@keyframes fadeInDown {
+ 0% {
+ opacity: 0;
+ -webkit-transform: translate3d(0, -100%, 0);
+ -ms-transform: translate3d(0, -100%, 0);
+ transform: translate3d(0, -100%, 0)
+ }
+
+ 100% {
+ opacity: 1;
+ -webkit-transform: none;
+ -ms-transform: none;
+ transform: none
+ }
+}
+
+.fadeInDown {
+ -webkit-animation-name: fadeInDown;
+ animation-name: fadeInDown
+}
+
+@-webkit-keyframes fadeInDownBig {
+ 0% {
+ opacity: 0;
+ -webkit-transform: translate3d(0, -2000px, 0);
+ transform: translate3d(0, -2000px, 0)
+ }
+
+ 100% {
+ opacity: 1;
+ -webkit-transform: none;
+ transform: none
+ }
+}
+
+@keyframes fadeInDownBig {
+ 0% {
+ opacity: 0;
+ -webkit-transform: translate3d(0, -2000px, 0);
+ -ms-transform: translate3d(0, -2000px, 0);
+ transform: translate3d(0, -2000px, 0)
+ }
+
+ 100% {
+ opacity: 1;
+ -webkit-transform: none;
+ -ms-transform: none;
+ transform: none
+ }
+}
+
+.fadeInDownBig {
+ -webkit-animation-name: fadeInDownBig;
+ animation-name: fadeInDownBig
+}
+
+@-webkit-keyframes fadeInLeft {
+ 0% {
+ opacity: 0;
+ -webkit-transform: translate3d(-100%, 0, 0);
+ transform: translate3d(-100%, 0, 0)
+ }
+
+ 100% {
+ opacity: 1;
+ -webkit-transform: none;
+ transform: none
+ }
+}
+
+@keyframes fadeInLeft {
+ 0% {
+ opacity: 0;
+ -webkit-transform: translate3d(-100%, 0, 0);
+ -ms-transform: translate3d(-100%, 0, 0);
+ transform: translate3d(-100%, 0, 0)
+ }
+
+ 100% {
+ opacity: 1;
+ -webkit-transform: none;
+ -ms-transform: none;
+ transform: none
+ }
+}
+
+.fadeInLeft {
+ -webkit-animation-name: fadeInLeft;
+ animation-name: fadeInLeft
+}
+
+@-webkit-keyframes fadeInLeftBig {
+ 0% {
+ opacity: 0;
+ -webkit-transform: translate3d(-2000px, 0, 0);
+ transform: translate3d(-2000px, 0, 0)
+ }
+
+ 100% {
+ opacity: 1;
+ -webkit-transform: none;
+ transform: none
+ }
+}
+
+@keyframes fadeInLeftBig {
+ 0% {
+ opacity: 0;
+ -webkit-transform: translate3d(-2000px, 0, 0);
+ -ms-transform: translate3d(-2000px, 0, 0);
+ transform: translate3d(-2000px, 0, 0)
+ }
+
+ 100% {
+ opacity: 1;
+ -webkit-transform: none;
+ -ms-transform: none;
+ transform: none
+ }
+}
+
+.fadeInLeftBig {
+ -webkit-animation-name: fadeInLeftBig;
+ animation-name: fadeInLeftBig
+}
+
+@-webkit-keyframes fadeInRight {
+ 0% {
+ opacity: 0;
+ -webkit-transform: translate3d(100%, 0, 0);
+ transform: translate3d(100%, 0, 0)
+ }
+
+ 100% {
+ opacity: 1;
+ -webkit-transform: none;
+ transform: none
+ }
+}
+
+@keyframes fadeInRight {
+ 0% {
+ opacity: 0;
+ -webkit-transform: translate3d(100%, 0, 0);
+ -ms-transform: translate3d(100%, 0, 0);
+ transform: translate3d(100%, 0, 0)
+ }
+
+ 100% {
+ opacity: 1;
+ -webkit-transform: none;
+ -ms-transform: none;
+ transform: none
+ }
+}
+
+.fadeInRight {
+ -webkit-animation-name: fadeInRight;
+ animation-name: fadeInRight
+}
+
+@-webkit-keyframes fadeInRightBig {
+ 0% {
+ opacity: 0;
+ -webkit-transform: translate3d(2000px, 0, 0);
+ transform: translate3d(2000px, 0, 0)
+ }
+
+ 100% {
+ opacity: 1;
+ -webkit-transform: none;
+ transform: none
+ }
+}
+
+@keyframes fadeInRightBig {
+ 0% {
+ opacity: 0;
+ -webkit-transform: translate3d(2000px, 0, 0);
+ -ms-transform: translate3d(2000px, 0, 0);
+ transform: translate3d(2000px, 0, 0)
+ }
+
+ 100% {
+ opacity: 1;
+ -webkit-transform: none;
+ -ms-transform: none;
+ transform: none
+ }
+}
+
+.fadeInRightBig {
+ -webkit-animation-name: fadeInRightBig;
+ animation-name: fadeInRightBig
+}
+
+@-webkit-keyframes fadeInUp {
+ 0% {
+ opacity: 0;
+ -webkit-transform: translate3d(0, 100%, 0);
+ transform: translate3d(0, 100%, 0)
+ }
+
+ 100% {
+ opacity: 1;
+ -webkit-transform: none;
+ transform: none
+ }
+}
+
+@keyframes fadeInUp {
+ 0% {
+ opacity: 0;
+ -webkit-transform: translate3d(0, 100%, 0);
+ -ms-transform: translate3d(0, 100%, 0);
+ transform: translate3d(0, 100%, 0)
+ }
+
+ 100% {
+ opacity: 1;
+ -webkit-transform: none;
+ -ms-transform: none;
+ transform: none
+ }
+}
+
+.fadeInUp {
+ -webkit-animation-name: fadeInUp;
+ animation-name: fadeInUp
+}
+
+@-webkit-keyframes fadeInUpBig {
+ 0% {
+ opacity: 0;
+ -webkit-transform: translate3d(0, 2000px, 0);
+ transform: translate3d(0, 2000px, 0)
+ }
+
+ 100% {
+ opacity: 1;
+ -webkit-transform: none;
+ transform: none
+ }
+}
+
+@keyframes fadeInUpBig {
+ 0% {
+ opacity: 0;
+ -webkit-transform: translate3d(0, 2000px, 0);
+ -ms-transform: translate3d(0, 2000px, 0);
+ transform: translate3d(0, 2000px, 0)
+ }
+
+ 100% {
+ opacity: 1;
+ -webkit-transform: none;
+ -ms-transform: none;
+ transform: none
+ }
+}
+
+.fadeInUpBig {
+ -webkit-animation-name: fadeInUpBig;
+ animation-name: fadeInUpBig
+}
+
+@-webkit-keyframes fadeOut {
+ 0% {
+ opacity: 1
+ }
+
+ 100% {
+ opacity: 0
+ }
+}
+
+@keyframes fadeOut {
+ 0% {
+ opacity: 1
+ }
+
+ 100% {
+ opacity: 0
+ }
+}
+
+.fadeOut {
+ -webkit-animation-name: fadeOut;
+ animation-name: fadeOut
+}
+
+@-webkit-keyframes fadeOutDown {
+ 0% {
+ opacity: 1
+ }
+
+ 100% {
+ opacity: 0;
+ -webkit-transform: translate3d(0, 100%, 0);
+ transform: translate3d(0, 100%, 0)
+ }
+}
+
+@keyframes fadeOutDown {
+ 0% {
+ opacity: 1
+ }
+
+ 100% {
+ opacity: 0;
+ -webkit-transform: translate3d(0, 100%, 0);
+ -ms-transform: translate3d(0, 100%, 0);
+ transform: translate3d(0, 100%, 0)
+ }
+}
+
+.fadeOutDown {
+ -webkit-animation-name: fadeOutDown;
+ animation-name: fadeOutDown
+}
+
+@-webkit-keyframes fadeOutDownBig {
+ 0% {
+ opacity: 1
+ }
+
+ 100% {
+ opacity: 0;
+ -webkit-transform: translate3d(0, 2000px, 0);
+ transform: translate3d(0, 2000px, 0)
+ }
+}
+
+@keyframes fadeOutDownBig {
+ 0% {
+ opacity: 1
+ }
+
+ 100% {
+ opacity: 0;
+ -webkit-transform: translate3d(0, 2000px, 0);
+ -ms-transform: translate3d(0, 2000px, 0);
+ transform: translate3d(0, 2000px, 0)
+ }
+}
+
+.fadeOutDownBig {
+ -webkit-animation-name: fadeOutDownBig;
+ animation-name: fadeOutDownBig
+}
+
+@-webkit-keyframes fadeOutLeft {
+ 0% {
+ opacity: 1
+ }
+
+ 100% {
+ opacity: 0;
+ -webkit-transform: translate3d(-100%, 0, 0);
+ transform: translate3d(-100%, 0, 0)
+ }
+}
+
+@keyframes fadeOutLeft {
+ 0% {
+ opacity: 1
+ }
+
+ 100% {
+ opacity: 0;
+ -webkit-transform: translate3d(-100%, 0, 0);
+ -ms-transform: translate3d(-100%, 0, 0);
+ transform: translate3d(-100%, 0, 0)
+ }
+}
+
+.fadeOutLeft {
+ -webkit-animation-name: fadeOutLeft;
+ animation-name: fadeOutLeft
+}
+
+@-webkit-keyframes fadeOutLeftBig {
+ 0% {
+ opacity: 1
+ }
+
+ 100% {
+ opacity: 0;
+ -webkit-transform: translate3d(-2000px, 0, 0);
+ transform: translate3d(-2000px, 0, 0)
+ }
+}
+
+@keyframes fadeOutLeftBig {
+ 0% {
+ opacity: 1
+ }
+
+ 100% {
+ opacity: 0;
+ -webkit-transform: translate3d(-2000px, 0, 0);
+ -ms-transform: translate3d(-2000px, 0, 0);
+ transform: translate3d(-2000px, 0, 0)
+ }
+}
+
+.fadeOutLeftBig {
+ -webkit-animation-name: fadeOutLeftBig;
+ animation-name: fadeOutLeftBig
+}
+
+@-webkit-keyframes fadeOutRight {
+ 0% {
+ opacity: 1
+ }
+
+ 100% {
+ opacity: 0;
+ -webkit-transform: translate3d(100%, 0, 0);
+ transform: translate3d(100%, 0, 0)
+ }
+}
+
+@keyframes fadeOutRight {
+ 0% {
+ opacity: 1
+ }
+
+ 100% {
+ opacity: 0;
+ -webkit-transform: translate3d(100%, 0, 0);
+ -ms-transform: translate3d(100%, 0, 0);
+ transform: translate3d(100%, 0, 0)
+ }
+}
+
+.fadeOutRight {
+ -webkit-animation-name: fadeOutRight;
+ animation-name: fadeOutRight
+}
+
+@-webkit-keyframes fadeOutRightBig {
+ 0% {
+ opacity: 1
+ }
+
+ 100% {
+ opacity: 0;
+ -webkit-transform: translate3d(2000px, 0, 0);
+ transform: translate3d(2000px, 0, 0)
+ }
+}
+
+@keyframes fadeOutRightBig {
+ 0% {
+ opacity: 1
+ }
+
+ 100% {
+ opacity: 0;
+ -webkit-transform: translate3d(2000px, 0, 0);
+ -ms-transform: translate3d(2000px, 0, 0);
+ transform: translate3d(2000px, 0, 0)
+ }
+}
+
+.fadeOutRightBig {
+ -webkit-animation-name: fadeOutRightBig;
+ animation-name: fadeOutRightBig
+}
+
+@-webkit-keyframes fadeOutUp {
+ 0% {
+ opacity: 1
+ }
+
+ 100% {
+ opacity: 0;
+ -webkit-transform: translate3d(0, -100%, 0);
+ transform: translate3d(0, -100%, 0)
+ }
+}
+
+@keyframes fadeOutUp {
+ 0% {
+ opacity: 1
+ }
+
+ 100% {
+ opacity: 0;
+ -webkit-transform: translate3d(0, -100%, 0);
+ -ms-transform: translate3d(0, -100%, 0);
+ transform: translate3d(0, -100%, 0)
+ }
+}
+
+.fadeOutUp {
+ -webkit-animation-name: fadeOutUp;
+ animation-name: fadeOutUp
+}
+
+@-webkit-keyframes fadeOutUpBig {
+ 0% {
+ opacity: 1
+ }
+
+ 100% {
+ opacity: 0;
+ -webkit-transform: translate3d(0, -2000px, 0);
+ transform: translate3d(0, -2000px, 0)
+ }
+}
+
+@keyframes fadeOutUpBig {
+ 0% {
+ opacity: 1
+ }
+
+ 100% {
+ opacity: 0;
+ -webkit-transform: translate3d(0, -2000px, 0);
+ -ms-transform: translate3d(0, -2000px, 0);
+ transform: translate3d(0, -2000px, 0)
+ }
+}
+
+.fadeOutUpBig {
+ -webkit-animation-name: fadeOutUpBig;
+ animation-name: fadeOutUpBig
+}
+
+@-webkit-keyframes flip {
+ 0% {
+ -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -360deg);
+ transform: perspective(400px) rotate3d(0, 1, 0, -360deg);
+ -webkit-animation-timing-function: ease-out;
+ animation-timing-function: ease-out
+ }
+
+ 40% {
+ -webkit-transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -190deg);
+ transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -190deg);
+ -webkit-animation-timing-function: ease-out;
+ animation-timing-function: ease-out
+ }
+
+ 50% {
+ -webkit-transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -170deg);
+ transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -170deg);
+ -webkit-animation-timing-function: ease-in;
+ animation-timing-function: ease-in
+ }
+
+ 80% {
+ -webkit-transform: perspective(400px) scale3d(.95, .95, .95);
+ transform: perspective(400px) scale3d(.95, .95, .95);
+ -webkit-animation-timing-function: ease-in;
+ animation-timing-function: ease-in
+ }
+
+ 100% {
+ -webkit-transform: perspective(400px);
+ transform: perspective(400px);
+ -webkit-animation-timing-function: ease-in;
+ animation-timing-function: ease-in
+ }
+}
+
+@keyframes flip {
+ 0% {
+ -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -360deg);
+ -ms-transform: perspective(400px) rotate3d(0, 1, 0, -360deg);
+ transform: perspective(400px) rotate3d(0, 1, 0, -360deg);
+ -webkit-animation-timing-function: ease-out;
+ animation-timing-function: ease-out
+ }
+
+ 40% {
+ -webkit-transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -190deg);
+ -ms-transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -190deg);
+ transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -190deg);
+ -webkit-animation-timing-function: ease-out;
+ animation-timing-function: ease-out
+ }
+
+ 50% {
+ -webkit-transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -170deg);
+ -ms-transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -170deg);
+ transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -170deg);
+ -webkit-animation-timing-function: ease-in;
+ animation-timing-function: ease-in
+ }
+
+ 80% {
+ -webkit-transform: perspective(400px) scale3d(.95, .95, .95);
+ -ms-transform: perspective(400px) scale3d(.95, .95, .95);
+ transform: perspective(400px) scale3d(.95, .95, .95);
+ -webkit-animation-timing-function: ease-in;
+ animation-timing-function: ease-in
+ }
+
+ 100% {
+ -webkit-transform: perspective(400px);
+ -ms-transform: perspective(400px);
+ transform: perspective(400px);
+ -webkit-animation-timing-function: ease-in;
+ animation-timing-function: ease-in
+ }
+}
+
+.animated.flip {
+ -webkit-backface-visibility: visible;
+ -ms-backface-visibility: visible;
+ backface-visibility: visible;
+ -webkit-animation-name: flip;
+ animation-name: flip
+}
+
+@-webkit-keyframes flipInX {
+ 0% {
+ -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
+ transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
+ -webkit-transition-timing-function: ease-in;
+ transition-timing-function: ease-in;
+ opacity: 0
+ }
+
+ 40% {
+ -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
+ transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
+ -webkit-transition-timing-function: ease-in;
+ transition-timing-function: ease-in
+ }
+
+ 60% {
+ -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 10deg);
+ transform: perspective(400px) rotate3d(1, 0, 0, 10deg);
+ opacity: 1
+ }
+
+ 80% {
+ -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -5deg);
+ transform: perspective(400px) rotate3d(1, 0, 0, -5deg)
+ }
+
+ 100% {
+ -webkit-transform: perspective(400px);
+ transform: perspective(400px)
+ }
+}
+
+@keyframes flipInX {
+ 0% {
+ -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
+ -ms-transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
+ transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
+ -webkit-transition-timing-function: ease-in;
+ transition-timing-function: ease-in;
+ opacity: 0
+ }
+
+ 40% {
+ -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
+ -ms-transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
+ transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
+ -webkit-transition-timing-function: ease-in;
+ transition-timing-function: ease-in
+ }
+
+ 60% {
+ -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 10deg);
+ -ms-transform: perspective(400px) rotate3d(1, 0, 0, 10deg);
+ transform: perspective(400px) rotate3d(1, 0, 0, 10deg);
+ opacity: 1
+ }
+
+ 80% {
+ -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -5deg);
+ -ms-transform: perspective(400px) rotate3d(1, 0, 0, -5deg);
+ transform: perspective(400px) rotate3d(1, 0, 0, -5deg)
+ }
+
+ 100% {
+ -webkit-transform: perspective(400px);
+ -ms-transform: perspective(400px);
+ transform: perspective(400px)
+ }
+}
+
+.flipInX {
+ -webkit-backface-visibility: visible !important;
+ -ms-backface-visibility: visible !important;
+ backface-visibility: visible !important;
+ -webkit-animation-name: flipInX;
+ animation-name: flipInX
+}
+
+@-webkit-keyframes flipInY {
+ 0% {
+ -webkit-transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
+ transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
+ -webkit-transition-timing-function: ease-in;
+ transition-timing-function: ease-in;
+ opacity: 0
+ }
+
+ 40% {
+ -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -20deg);
+ transform: perspective(400px) rotate3d(0, 1, 0, -20deg);
+ -webkit-transition-timing-function: ease-in;
+ transition-timing-function: ease-in
+ }
+
+ 60% {
+ -webkit-transform: perspective(400px) rotate3d(0, 1, 0, 10deg);
+ transform: perspective(400px) rotate3d(0, 1, 0, 10deg);
+ opacity: 1
+ }
+
+ 80% {
+ -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -5deg);
+ transform: perspective(400px) rotate3d(0, 1, 0, -5deg)
+ }
+
+ 100% {
+ -webkit-transform: perspective(400px);
+ transform: perspective(400px)
+ }
+}
+
+@keyframes flipInY {
+ 0% {
+ -webkit-transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
+ -ms-transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
+ transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
+ -webkit-transition-timing-function: ease-in;
+ transition-timing-function: ease-in;
+ opacity: 0
+ }
+
+ 40% {
+ -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -20deg);
+ -ms-transform: perspective(400px) rotate3d(0, 1, 0, -20deg);
+ transform: perspective(400px) rotate3d(0, 1, 0, -20deg);
+ -webkit-transition-timing-function: ease-in;
+ transition-timing-function: ease-in
+ }
+
+ 60% {
+ -webkit-transform: perspective(400px) rotate3d(0, 1, 0, 10deg);
+ -ms-transform: perspective(400px) rotate3d(0, 1, 0, 10deg);
+ transform: perspective(400px) rotate3d(0, 1, 0, 10deg);
+ opacity: 1
+ }
+
+ 80% {
+ -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -5deg);
+ -ms-transform: perspective(400px) rotate3d(0, 1, 0, -5deg);
+ transform: perspective(400px) rotate3d(0, 1, 0, -5deg)
+ }
+
+ 100% {
+ -webkit-transform: perspective(400px);
+ -ms-transform: perspective(400px);
+ transform: perspective(400px)
+ }
+}
+
+.flipInY {
+ -webkit-backface-visibility: visible !important;
+ -ms-backface-visibility: visible !important;
+ backface-visibility: visible !important;
+ -webkit-animation-name: flipInY;
+ animation-name: flipInY
+}
+
+@-webkit-keyframes flipOutX {
+ 0% {
+ -webkit-transform: perspective(400px);
+ transform: perspective(400px)
+ }
+
+ 30% {
+ -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
+ transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
+ opacity: 1
+ }
+
+ 100% {
+ -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
+ transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
+ opacity: 0
+ }
+}
+
+@keyframes flipOutX {
+ 0% {
+ -webkit-transform: perspective(400px);
+ -ms-transform: perspective(400px);
+ transform: perspective(400px)
+ }
+
+ 30% {
+ -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
+ -ms-transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
+ transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
+ opacity: 1
+ }
+
+ 100% {
+ -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
+ -ms-transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
+ transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
+ opacity: 0
+ }
+}
+
+.flipOutX {
+ -webkit-animation-name: flipOutX;
+ animation-name: flipOutX;
+ -webkit-animation-duration: .75s;
+ animation-duration: .75s;
+ -webkit-backface-visibility: visible !important;
+ -ms-backface-visibility: visible !important;
+ backface-visibility: visible !important
+}
+
+@-webkit-keyframes flipOutY {
+ 0% {
+ -webkit-transform: perspective(400px);
+ transform: perspective(400px)
+ }
+
+ 30% {
+ -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -15deg);
+ transform: perspective(400px) rotate3d(0, 1, 0, -15deg);
+ opacity: 1
+ }
+
+ 100% {
+ -webkit-transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
+ transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
+ opacity: 0
+ }
+}
+
+@keyframes flipOutY {
+ 0% {
+ -webkit-transform: perspective(400px);
+ -ms-transform: perspective(400px);
+ transform: perspective(400px)
+ }
+
+ 30% {
+ -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -15deg);
+ -ms-transform: perspective(400px) rotate3d(0, 1, 0, -15deg);
+ transform: perspective(400px) rotate3d(0, 1, 0, -15deg);
+ opacity: 1
+ }
+
+ 100% {
+ -webkit-transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
+ -ms-transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
+ transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
+ opacity: 0
+ }
+}
+
+.flipOutY {
+ -webkit-backface-visibility: visible !important;
+ -ms-backface-visibility: visible !important;
+ backface-visibility: visible !important;
+ -webkit-animation-name: flipOutY;
+ animation-name: flipOutY;
+ -webkit-animation-duration: .75s;
+ animation-duration: .75s
+}
+
+@-webkit-keyframes lightSpeedIn {
+ 0% {
+ -webkit-transform: translate3d(100%, 0, 0) skewX(-30deg);
+ transform: translate3d(100%, 0, 0) skewX(-30deg);
+ opacity: 0
+ }
+
+ 60% {
+ -webkit-transform: skewX(20deg);
+ transform: skewX(20deg);
+ opacity: 1
+ }
+
+ 80% {
+ -webkit-transform: skewX(-5deg);
+ transform: skewX(-5deg);
+ opacity: 1
+ }
+
+ 100% {
+ -webkit-transform: none;
+ transform: none;
+ opacity: 1
+ }
+}
+
+@keyframes lightSpeedIn {
+ 0% {
+ -webkit-transform: translate3d(100%, 0, 0) skewX(-30deg);
+ -ms-transform: translate3d(100%, 0, 0) skewX(-30deg);
+ transform: translate3d(100%, 0, 0) skewX(-30deg);
+ opacity: 0
+ }
+
+ 60% {
+ -webkit-transform: skewX(20deg);
+ -ms-transform: skewX(20deg);
+ transform: skewX(20deg);
+ opacity: 1
+ }
+
+ 80% {
+ -webkit-transform: skewX(-5deg);
+ -ms-transform: skewX(-5deg);
+ transform: skewX(-5deg);
+ opacity: 1
+ }
+
+ 100% {
+ -webkit-transform: none;
+ -ms-transform: none;
+ transform: none;
+ opacity: 1
+ }
+}
+
+.lightSpeedIn {
+ -webkit-animation-name: lightSpeedIn;
+ animation-name: lightSpeedIn;
+ -webkit-animation-timing-function: ease-out;
+ animation-timing-function: ease-out
+}
+
+@-webkit-keyframes lightSpeedOut {
+ 0% {
+ opacity: 1
+ }
+
+ 100% {
+ -webkit-transform: translate3d(100%, 0, 0) skewX(30deg);
+ transform: translate3d(100%, 0, 0) skewX(30deg);
+ opacity: 0
+ }
+}
+
+@keyframes lightSpeedOut {
+ 0% {
+ opacity: 1
+ }
+
+ 100% {
+ -webkit-transform: translate3d(100%, 0, 0) skewX(30deg);
+ -ms-transform: translate3d(100%, 0, 0) skewX(30deg);
+ transform: translate3d(100%, 0, 0) skewX(30deg);
+ opacity: 0
+ }
+}
+
+.lightSpeedOut {
+ -webkit-animation-name: lightSpeedOut;
+ animation-name: lightSpeedOut;
+ -webkit-animation-timing-function: ease-in;
+ animation-timing-function: ease-in
+}
+
+@-webkit-keyframes rotateIn {
+ 0% {
+ -webkit-transform-origin: center;
+ transform-origin: center;
+ -webkit-transform: rotate3d(0, 0, 1, -200deg);
+ transform: rotate3d(0, 0, 1, -200deg);
+ opacity: 0
+ }
+
+ 100% {
+ -webkit-transform-origin: center;
+ transform-origin: center;
+ -webkit-transform: none;
+ transform: none;
+ opacity: 1
+ }
+}
+
+@keyframes rotateIn {
+ 0% {
+ -webkit-transform-origin: center;
+ -ms-transform-origin: center;
+ transform-origin: center;
+ -webkit-transform: rotate3d(0, 0, 1, -200deg);
+ -ms-transform: rotate3d(0, 0, 1, -200deg);
+ transform: rotate3d(0, 0, 1, -200deg);
+ opacity: 0
+ }
+
+ 100% {
+ -webkit-transform-origin: center;
+ -ms-transform-origin: center;
+ transform-origin: center;
+ -webkit-transform: none;
+ -ms-transform: none;
+ transform: none;
+ opacity: 1
+ }
+}
+
+.rotateIn {
+ -webkit-animation-name: rotateIn;
+ animation-name: rotateIn
+}
+
+@-webkit-keyframes rotateInDownLeft {
+ 0% {
+ -webkit-transform-origin: left bottom;
+ transform-origin: left bottom;
+ -webkit-transform: rotate3d(0, 0, 1, -45deg);
+ transform: rotate3d(0, 0, 1, -45deg);
+ opacity: 0
+ }
+
+ 100% {
+ -webkit-transform-origin: left bottom;
+ transform-origin: left bottom;
+ -webkit-transform: none;
+ transform: none;
+ opacity: 1
+ }
+}
+
+@keyframes rotateInDownLeft {
+ 0% {
+ -webkit-transform-origin: left bottom;
+ -ms-transform-origin: left bottom;
+ transform-origin: left bottom;
+ -webkit-transform: rotate3d(0, 0, 1, -45deg);
+ -ms-transform: rotate3d(0, 0, 1, -45deg);
+ transform: rotate3d(0, 0, 1, -45deg);
+ opacity: 0
+ }
+
+ 100% {
+ -webkit-transform-origin: left bottom;
+ -ms-transform-origin: left bottom;
+ transform-origin: left bottom;
+ -webkit-transform: none;
+ -ms-transform: none;
+ transform: none;
+ opacity: 1
+ }
+}
+
+.rotateInDownLeft {
+ -webkit-animation-name: rotateInDownLeft;
+ animation-name: rotateInDownLeft
+}
+
+@-webkit-keyframes rotateInDownRight {
+ 0% {
+ -webkit-transform-origin: right bottom;
+ transform-origin: right bottom;
+ -webkit-transform: rotate3d(0, 0, 1, 45deg);
+ transform: rotate3d(0, 0, 1, 45deg);
+ opacity: 0
+ }
+
+ 100% {
+ -webkit-transform-origin: right bottom;
+ transform-origin: right bottom;
+ -webkit-transform: none;
+ transform: none;
+ opacity: 1
+ }
+}
+
+@keyframes rotateInDownRight {
+ 0% {
+ -webkit-transform-origin: right bottom;
+ -ms-transform-origin: right bottom;
+ transform-origin: right bottom;
+ -webkit-transform: rotate3d(0, 0, 1, 45deg);
+ -ms-transform: rotate3d(0, 0, 1, 45deg);
+ transform: rotate3d(0, 0, 1, 45deg);
+ opacity: 0
+ }
+
+ 100% {
+ -webkit-transform-origin: right bottom;
+ -ms-transform-origin: right bottom;
+ transform-origin: right bottom;
+ -webkit-transform: none;
+ -ms-transform: none;
+ transform: none;
+ opacity: 1
+ }
+}
+
+.rotateInDownRight {
+ -webkit-animation-name: rotateInDownRight;
+ animation-name: rotateInDownRight
+}
+
+@-webkit-keyframes rotateInUpLeft {
+ 0% {
+ -webkit-transform-origin: left bottom;
+ transform-origin: left bottom;
+ -webkit-transform: rotate3d(0, 0, 1, 45deg);
+ transform: rotate3d(0, 0, 1, 45deg);
+ opacity: 0
+ }
+
+ 100% {
+ -webkit-transform-origin: left bottom;
+ transform-origin: left bottom;
+ -webkit-transform: none;
+ transform: none;
+ opacity: 1
+ }
+}
+
+@keyframes rotateInUpLeft {
+ 0% {
+ -webkit-transform-origin: left bottom;
+ -ms-transform-origin: left bottom;
+ transform-origin: left bottom;
+ -webkit-transform: rotate3d(0, 0, 1, 45deg);
+ -ms-transform: rotate3d(0, 0, 1, 45deg);
+ transform: rotate3d(0, 0, 1, 45deg);
+ opacity: 0
+ }
+
+ 100% {
+ -webkit-transform-origin: left bottom;
+ -ms-transform-origin: left bottom;
+ transform-origin: left bottom;
+ -webkit-transform: none;
+ -ms-transform: none;
+ transform: none;
+ opacity: 1
+ }
+}
+
+.rotateInUpLeft {
+ -webkit-animation-name: rotateInUpLeft;
+ animation-name: rotateInUpLeft
+}
+
+@-webkit-keyframes rotateInUpRight {
+ 0% {
+ -webkit-transform-origin: right bottom;
+ transform-origin: right bottom;
+ -webkit-transform: rotate3d(0, 0, 1, -90deg);
+ transform: rotate3d(0, 0, 1, -90deg);
+ opacity: 0
+ }
+
+ 100% {
+ -webkit-transform-origin: right bottom;
+ transform-origin: right bottom;
+ -webkit-transform: none;
+ transform: none;
+ opacity: 1
+ }
+}
+
+@keyframes rotateInUpRight {
+ 0% {
+ -webkit-transform-origin: right bottom;
+ -ms-transform-origin: right bottom;
+ transform-origin: right bottom;
+ -webkit-transform: rotate3d(0, 0, 1, -90deg);
+ -ms-transform: rotate3d(0, 0, 1, -90deg);
+ transform: rotate3d(0, 0, 1, -90deg);
+ opacity: 0
+ }
+
+ 100% {
+ -webkit-transform-origin: right bottom;
+ -ms-transform-origin: right bottom;
+ transform-origin: right bottom;
+ -webkit-transform: none;
+ -ms-transform: none;
+ transform: none;
+ opacity: 1
+ }
+}
+
+.rotateInUpRight {
+ -webkit-animation-name: rotateInUpRight;
+ animation-name: rotateInUpRight
+}
+
+@-webkit-keyframes rotateOut {
+ 0% {
+ -webkit-transform-origin: center;
+ transform-origin: center;
+ opacity: 1
+ }
+
+ 100% {
+ -webkit-transform-origin: center;
+ transform-origin: center;
+ -webkit-transform: rotate3d(0, 0, 1, 200deg);
+ transform: rotate3d(0, 0, 1, 200deg);
+ opacity: 0
+ }
+}
+
+@keyframes rotateOut {
+ 0% {
+ -webkit-transform-origin: center;
+ -ms-transform-origin: center;
+ transform-origin: center;
+ opacity: 1
+ }
+
+ 100% {
+ -webkit-transform-origin: center;
+ -ms-transform-origin: center;
+ transform-origin: center;
+ -webkit-transform: rotate3d(0, 0, 1, 200deg);
+ -ms-transform: rotate3d(0, 0, 1, 200deg);
+ transform: rotate3d(0, 0, 1, 200deg);
+ opacity: 0
+ }
+}
+
+.rotateOut {
+ -webkit-animation-name: rotateOut;
+ animation-name: rotateOut
+}
+
+@-webkit-keyframes rotateOutDownLeft {
+ 0% {
+ -webkit-transform-origin: left bottom;
+ transform-origin: left bottom;
+ opacity: 1
+ }
+
+ 100% {
+ -webkit-transform-origin: left bottom;
+ transform-origin: left bottom;
+ -webkit-transform: rotate3d(0, 0, 1, 45deg);
+ transform: rotate3d(0, 0, 1, 45deg);
+ opacity: 0
+ }
+}
+
+@keyframes rotateOutDownLeft {
+ 0% {
+ -webkit-transform-origin: left bottom;
+ -ms-transform-origin: left bottom;
+ transform-origin: left bottom;
+ opacity: 1
+ }
+
+ 100% {
+ -webkit-transform-origin: left bottom;
+ -ms-transform-origin: left bottom;
+ transform-origin: left bottom;
+ -webkit-transform: rotate3d(0, 0, 1, 45deg);
+ -ms-transform: rotate3d(0, 0, 1, 45deg);
+ transform: rotate3d(0, 0, 1, 45deg);
+ opacity: 0
+ }
+}
+
+.rotateOutDownLeft {
+ -webkit-animation-name: rotateOutDownLeft;
+ animation-name: rotateOutDownLeft
+}
+
+@-webkit-keyframes rotateOutDownRight {
+ 0% {
+ -webkit-transform-origin: right bottom;
+ transform-origin: right bottom;
+ opacity: 1
+ }
+
+ 100% {
+ -webkit-transform-origin: right bottom;
+ transform-origin: right bottom;
+ -webkit-transform: rotate3d(0, 0, 1, -45deg);
+ transform: rotate3d(0, 0, 1, -45deg);
+ opacity: 0
+ }
+}
+
+@keyframes rotateOutDownRight {
+ 0% {
+ -webkit-transform-origin: right bottom;
+ -ms-transform-origin: right bottom;
+ transform-origin: right bottom;
+ opacity: 1
+ }
+
+ 100% {
+ -webkit-transform-origin: right bottom;
+ -ms-transform-origin: right bottom;
+ transform-origin: right bottom;
+ -webkit-transform: rotate3d(0, 0, 1, -45deg);
+ -ms-transform: rotate3d(0, 0, 1, -45deg);
+ transform: rotate3d(0, 0, 1, -45deg);
+ opacity: 0
+ }
+}
+
+.rotateOutDownRight {
+ -webkit-animation-name: rotateOutDownRight;
+ animation-name: rotateOutDownRight
+}
+
+@-webkit-keyframes rotateOutUpLeft {
+ 0% {
+ -webkit-transform-origin: left bottom;
+ transform-origin: left bottom;
+ opacity: 1
+ }
+
+ 100% {
+ -webkit-transform-origin: left bottom;
+ transform-origin: left bottom;
+ -webkit-transform: rotate3d(0, 0, 1, -45deg);
+ transform: rotate3d(0, 0, 1, -45deg);
+ opacity: 0
+ }
+}
+
+@keyframes rotateOutUpLeft {
+ 0% {
+ -webkit-transform-origin: left bottom;
+ -ms-transform-origin: left bottom;
+ transform-origin: left bottom;
+ opacity: 1
+ }
+
+ 100% {
+ -webkit-transform-origin: left bottom;
+ -ms-transform-origin: left bottom;
+ transform-origin: left bottom;
+ -webkit-transform: rotate3d(0, 0, 1, -45deg);
+ -ms-transform: rotate3d(0, 0, 1, -45deg);
+ transform: rotate3d(0, 0, 1, -45deg);
+ opacity: 0
+ }
+}
+
+.rotateOutUpLeft {
+ -webkit-animation-name: rotateOutUpLeft;
+ animation-name: rotateOutUpLeft
+}
+
+@-webkit-keyframes rotateOutUpRight {
+ 0% {
+ -webkit-transform-origin: right bottom;
+ transform-origin: right bottom;
+ opacity: 1
+ }
+
+ 100% {
+ -webkit-transform-origin: right bottom;
+ transform-origin: right bottom;
+ -webkit-transform: rotate3d(0, 0, 1, 90deg);
+ transform: rotate3d(0, 0, 1, 90deg);
+ opacity: 0
+ }
+}
+
+@keyframes rotateOutUpRight {
+ 0% {
+ -webkit-transform-origin: right bottom;
+ -ms-transform-origin: right bottom;
+ transform-origin: right bottom;
+ opacity: 1
+ }
+
+ 100% {
+ -webkit-transform-origin: right bottom;
+ -ms-transform-origin: right bottom;
+ transform-origin: right bottom;
+ -webkit-transform: rotate3d(0, 0, 1, 90deg);
+ -ms-transform: rotate3d(0, 0, 1, 90deg);
+ transform: rotate3d(0, 0, 1, 90deg);
+ opacity: 0
+ }
+}
+
+.rotateOutUpRight {
+ -webkit-animation-name: rotateOutUpRight;
+ animation-name: rotateOutUpRight
+}
+
+@-webkit-keyframes hinge {
+ 0% {
+ -webkit-transform-origin: top left;
+ transform-origin: top left;
+ -webkit-animation-timing-function: ease-in-out;
+ animation-timing-function: ease-in-out
+ }
+
+ 20%,
+ 60% {
+ -webkit-transform: rotate3d(0, 0, 1, 80deg);
+ transform: rotate3d(0, 0, 1, 80deg);
+ -webkit-transform-origin: top left;
+ transform-origin: top left;
+ -webkit-animation-timing-function: ease-in-out;
+ animation-timing-function: ease-in-out
+ }
+
+ 40%,
+ 80% {
+ -webkit-transform: rotate3d(0, 0, 1, 60deg);
+ transform: rotate3d(0, 0, 1, 60deg);
+ -webkit-transform-origin: top left;
+ transform-origin: top left;
+ -webkit-animation-timing-function: ease-in-out;
+ animation-timing-function: ease-in-out;
+ opacity: 1
+ }
+
+ 100% {
+ -webkit-transform: translate3d(0, 700px, 0);
+ transform: translate3d(0, 700px, 0);
+ opacity: 0
+ }
+}
+
+@keyframes hinge {
+ 0% {
+ -webkit-transform-origin: top left;
+ -ms-transform-origin: top left;
+ transform-origin: top left;
+ -webkit-animation-timing-function: ease-in-out;
+ animation-timing-function: ease-in-out
+ }
+
+ 20%,
+ 60% {
+ -webkit-transform: rotate3d(0, 0, 1, 80deg);
+ -ms-transform: rotate3d(0, 0, 1, 80deg);
+ transform: rotate3d(0, 0, 1, 80deg);
+ -webkit-transform-origin: top left;
+ -ms-transform-origin: top left;
+ transform-origin: top left;
+ -webkit-animation-timing-function: ease-in-out;
+ animation-timing-function: ease-in-out
+ }
+
+ 40%,
+ 80% {
+ -webkit-transform: rotate3d(0, 0, 1, 60deg);
+ -ms-transform: rotate3d(0, 0, 1, 60deg);
+ transform: rotate3d(0, 0, 1, 60deg);
+ -webkit-transform-origin: top left;
+ -ms-transform-origin: top left;
+ transform-origin: top left;
+ -webkit-animation-timing-function: ease-in-out;
+ animation-timing-function: ease-in-out;
+ opacity: 1
+ }
+
+ 100% {
+ -webkit-transform: translate3d(0, 700px, 0);
+ -ms-transform: translate3d(0, 700px, 0);
+ transform: translate3d(0, 700px, 0);
+ opacity: 0
+ }
+}
+
+.hinge {
+ -webkit-animation-name: hinge;
+ animation-name: hinge
+}
+
+@-webkit-keyframes rollIn {
+ 0% {
+ opacity: 0;
+ -webkit-transform: translate3d(-100%, 0, 0) rotate3d(0, 0, 1, -120deg);
+ transform: translate3d(-100%, 0, 0) rotate3d(0, 0, 1, -120deg)
+ }
+
+ 100% {
+ opacity: 1;
+ -webkit-transform: none;
+ transform: none
+ }
+}
+
+@keyframes rollIn {
+ 0% {
+ opacity: 0;
+ -webkit-transform: translate3d(-100%, 0, 0) rotate3d(0, 0, 1, -120deg);
+ -ms-transform: translate3d(-100%, 0, 0) rotate3d(0, 0, 1, -120deg);
+ transform: translate3d(-100%, 0, 0) rotate3d(0, 0, 1, -120deg)
+ }
+
+ 100% {
+ opacity: 1;
+ -webkit-transform: none;
+ -ms-transform: none;
+ transform: none
+ }
+}
+
+.rollIn {
+ -webkit-animation-name: rollIn;
+ animation-name: rollIn
+}
+
+@-webkit-keyframes rollOut {
+ 0% {
+ opacity: 1
+ }
+
+ 100% {
+ opacity: 0;
+ -webkit-transform: translate3d(100%, 0, 0) rotate3d(0, 0, 1, 120deg);
+ transform: translate3d(100%, 0, 0) rotate3d(0, 0, 1, 120deg)
+ }
+}
+
+@keyframes rollOut {
+ 0% {
+ opacity: 1
+ }
+
+ 100% {
+ opacity: 0;
+ -webkit-transform: translate3d(100%, 0, 0) rotate3d(0, 0, 1, 120deg);
+ -ms-transform: translate3d(100%, 0, 0) rotate3d(0, 0, 1, 120deg);
+ transform: translate3d(100%, 0, 0) rotate3d(0, 0, 1, 120deg)
+ }
+}
+
+.rollOut {
+ -webkit-animation-name: rollOut;
+ animation-name: rollOut
+}
+
+@-webkit-keyframes zoomIn {
+ 0% {
+ opacity: 0;
+ -webkit-transform: scale3d(.3, .3, .3);
+ transform: scale3d(.3, .3, .3)
+ }
+
+ 50% {
+ opacity: 1
+ }
+}
+
+@keyframes zoomIn {
+ 0% {
+ opacity: 0;
+ -webkit-transform: scale3d(.3, .3, .3);
+ -ms-transform: scale3d(.3, .3, .3);
+ transform: scale3d(.3, .3, .3)
+ }
+
+ 50% {
+ opacity: 1
+ }
+}
+
+.zoomIn {
+ -webkit-animation-name: zoomIn;
+ animation-name: zoomIn
+}
+
+@-webkit-keyframes zoomInDown {
+ 0% {
+ opacity: 0;
+ -webkit-transform: scale3d(.1, .1, .1) translate3d(0, -1000px, 0);
+ transform: scale3d(.1, .1, .1) translate3d(0, -1000px, 0);
+ -webkit-animation-timing-function: cubic-bezier(0.55, .055, .675, .19);
+ animation-timing-function: cubic-bezier(0.55, .055, .675, .19)
+ }
+
+ 60% {
+ opacity: 1;
+ -webkit-transform: scale3d(.475, .475, .475) translate3d(0, 60px, 0);
+ transform: scale3d(.475, .475, .475) translate3d(0, 60px, 0);
+ -webkit-animation-timing-function: cubic-bezier(0.175, .885, .32, 1);
+ animation-timing-function: cubic-bezier(0.175, .885, .32, 1)
+ }
+}
+
+@keyframes zoomInDown {
+ 0% {
+ opacity: 0;
+ -webkit-transform: scale3d(.1, .1, .1) translate3d(0, -1000px, 0);
+ -ms-transform: scale3d(.1, .1, .1) translate3d(0, -1000px, 0);
+ transform: scale3d(.1, .1, .1) translate3d(0, -1000px, 0);
+ -webkit-animation-timing-function: cubic-bezier(0.55, .055, .675, .19);
+ animation-timing-function: cubic-bezier(0.55, .055, .675, .19)
+ }
+
+ 60% {
+ opacity: 1;
+ -webkit-transform: scale3d(.475, .475, .475) translate3d(0, 60px, 0);
+ -ms-transform: scale3d(.475, .475, .475) translate3d(0, 60px, 0);
+ transform: scale3d(.475, .475, .475) translate3d(0, 60px, 0);
+ -webkit-animation-timing-function: cubic-bezier(0.175, .885, .32, 1);
+ animation-timing-function: cubic-bezier(0.175, .885, .32, 1)
+ }
+}
+
+.zoomInDown {
+ -webkit-animation-name: zoomInDown;
+ animation-name: zoomInDown
+}
+
+@-webkit-keyframes zoomInLeft {
+ 0% {
+ opacity: 0;
+ -webkit-transform: scale3d(.1, .1, .1) translate3d(-1000px, 0, 0);
+ transform: scale3d(.1, .1, .1) translate3d(-1000px, 0, 0);
+ -webkit-animation-timing-function: cubic-bezier(0.55, .055, .675, .19);
+ animation-timing-function: cubic-bezier(0.55, .055, .675, .19)
+ }
+
+ 60% {
+ opacity: 1;
+ -webkit-transform: scale3d(.475, .475, .475) translate3d(10px, 0, 0);
+ transform: scale3d(.475, .475, .475) translate3d(10px, 0, 0);
+ -webkit-animation-timing-function: cubic-bezier(0.175, .885, .32, 1);
+ animation-timing-function: cubic-bezier(0.175, .885, .32, 1)
+ }
+}
+
+@keyframes zoomInLeft {
+ 0% {
+ opacity: 0;
+ -webkit-transform: scale3d(.1, .1, .1) translate3d(-1000px, 0, 0);
+ -ms-transform: scale3d(.1, .1, .1) translate3d(-1000px, 0, 0);
+ transform: scale3d(.1, .1, .1) translate3d(-1000px, 0, 0);
+ -webkit-animation-timing-function: cubic-bezier(0.55, .055, .675, .19);
+ animation-timing-function: cubic-bezier(0.55, .055, .675, .19)
+ }
+
+ 60% {
+ opacity: 1;
+ -webkit-transform: scale3d(.475, .475, .475) translate3d(10px, 0, 0);
+ -ms-transform: scale3d(.475, .475, .475) translate3d(10px, 0, 0);
+ transform: scale3d(.475, .475, .475) translate3d(10px, 0, 0);
+ -webkit-animation-timing-function: cubic-bezier(0.175, .885, .32, 1);
+ animation-timing-function: cubic-bezier(0.175, .885, .32, 1)
+ }
+}
+
+.zoomInLeft {
+ -webkit-animation-name: zoomInLeft;
+ animation-name: zoomInLeft
+}
+
+@-webkit-keyframes zoomInRight {
+ 0% {
+ opacity: 0;
+ -webkit-transform: scale3d(.1, .1, .1) translate3d(1000px, 0, 0);
+ transform: scale3d(.1, .1, .1) translate3d(1000px, 0, 0);
+ -webkit-animation-timing-function: cubic-bezier(0.55, .055, .675, .19);
+ animation-timing-function: cubic-bezier(0.55, .055, .675, .19)
+ }
+
+ 60% {
+ opacity: 1;
+ -webkit-transform: scale3d(.475, .475, .475) translate3d(-10px, 0, 0);
+ transform: scale3d(.475, .475, .475) translate3d(-10px, 0, 0);
+ -webkit-animation-timing-function: cubic-bezier(0.175, .885, .32, 1);
+ animation-timing-function: cubic-bezier(0.175, .885, .32, 1)
+ }
+}
+
+@keyframes zoomInRight {
+ 0% {
+ opacity: 0;
+ -webkit-transform: scale3d(.1, .1, .1) translate3d(1000px, 0, 0);
+ -ms-transform: scale3d(.1, .1, .1) translate3d(1000px, 0, 0);
+ transform: scale3d(.1, .1, .1) translate3d(1000px, 0, 0);
+ -webkit-animation-timing-function: cubic-bezier(0.55, .055, .675, .19);
+ animation-timing-function: cubic-bezier(0.55, .055, .675, .19)
+ }
+
+ 60% {
+ opacity: 1;
+ -webkit-transform: scale3d(.475, .475, .475) translate3d(-10px, 0, 0);
+ -ms-transform: scale3d(.475, .475, .475) translate3d(-10px, 0, 0);
+ transform: scale3d(.475, .475, .475) translate3d(-10px, 0, 0);
+ -webkit-animation-timing-function: cubic-bezier(0.175, .885, .32, 1);
+ animation-timing-function: cubic-bezier(0.175, .885, .32, 1)
+ }
+}
+
+.zoomInRight {
+ -webkit-animation-name: zoomInRight;
+ animation-name: zoomInRight
+}
+
+@-webkit-keyframes zoomInUp {
+ 0% {
+ opacity: 0;
+ -webkit-transform: scale3d(.1, .1, .1) translate3d(0, 1000px, 0);
+ transform: scale3d(.1, .1, .1) translate3d(0, 1000px, 0);
+ -webkit-animation-timing-function: cubic-bezier(0.55, .055, .675, .19);
+ animation-timing-function: cubic-bezier(0.55, .055, .675, .19)
+ }
+
+ 60% {
+ opacity: 1;
+ -webkit-transform: scale3d(.475, .475, .475) translate3d(0, -60px, 0);
+ transform: scale3d(.475, .475, .475) translate3d(0, -60px, 0);
+ -webkit-animation-timing-function: cubic-bezier(0.175, .885, .32, 1);
+ animation-timing-function: cubic-bezier(0.175, .885, .32, 1)
+ }
+}
+
+@keyframes zoomInUp {
+ 0% {
+ opacity: 0;
+ -webkit-transform: scale3d(.1, .1, .1) translate3d(0, 1000px, 0);
+ -ms-transform: scale3d(.1, .1, .1) translate3d(0, 1000px, 0);
+ transform: scale3d(.1, .1, .1) translate3d(0, 1000px, 0);
+ -webkit-animation-timing-function: cubic-bezier(0.55, .055, .675, .19);
+ animation-timing-function: cubic-bezier(0.55, .055, .675, .19)
+ }
+
+ 60% {
+ opacity: 1;
+ -webkit-transform: scale3d(.475, .475, .475) translate3d(0, -60px, 0);
+ -ms-transform: scale3d(.475, .475, .475) translate3d(0, -60px, 0);
+ transform: scale3d(.475, .475, .475) translate3d(0, -60px, 0);
+ -webkit-animation-timing-function: cubic-bezier(0.175, .885, .32, 1);
+ animation-timing-function: cubic-bezier(0.175, .885, .32, 1)
+ }
+}
+
+.zoomInUp {
+ -webkit-animation-name: zoomInUp;
+ animation-name: zoomInUp
+}
+
+@-webkit-keyframes zoomOut {
+ 0% {
+ opacity: 1
+ }
+
+ 50% {
+ opacity: 0;
+ -webkit-transform: scale3d(.3, .3, .3);
+ transform: scale3d(.3, .3, .3)
+ }
+
+ 100% {
+ opacity: 0
+ }
+}
+
+@keyframes zoomOut {
+ 0% {
+ opacity: 1
+ }
+
+ 50% {
+ opacity: 0;
+ -webkit-transform: scale3d(.3, .3, .3);
+ -ms-transform: scale3d(.3, .3, .3);
+ transform: scale3d(.3, .3, .3)
+ }
+
+ 100% {
+ opacity: 0
+ }
+}
+
+.zoomOut {
+ -webkit-animation-name: zoomOut;
+ animation-name: zoomOut
+}
+
+@-webkit-keyframes zoomOutDown {
+ 40% {
+ opacity: 1;
+ -webkit-transform: scale3d(.475, .475, .475) translate3d(0, -60px, 0);
+ transform: scale3d(.475, .475, .475) translate3d(0, -60px, 0);
+ -webkit-animation-timing-function: cubic-bezier(0.55, .055, .675, .19);
+ animation-timing-function: cubic-bezier(0.55, .055, .675, .19)
+ }
+
+ 100% {
+ opacity: 0;
+ -webkit-transform: scale3d(.1, .1, .1) translate3d(0, 2000px, 0);
+ transform: scale3d(.1, .1, .1) translate3d(0, 2000px, 0);
+ -webkit-transform-origin: center bottom;
+ transform-origin: center bottom;
+ -webkit-animation-timing-function: cubic-bezier(0.175, .885, .32, 1);
+ animation-timing-function: cubic-bezier(0.175, .885, .32, 1)
+ }
+}
+
+@keyframes zoomOutDown {
+ 40% {
+ opacity: 1;
+ -webkit-transform: scale3d(.475, .475, .475) translate3d(0, -60px, 0);
+ -ms-transform: scale3d(.475, .475, .475) translate3d(0, -60px, 0);
+ transform: scale3d(.475, .475, .475) translate3d(0, -60px, 0);
+ -webkit-animation-timing-function: cubic-bezier(0.55, .055, .675, .19);
+ animation-timing-function: cubic-bezier(0.55, .055, .675, .19)
+ }
+
+ 100% {
+ opacity: 0;
+ -webkit-transform: scale3d(.1, .1, .1) translate3d(0, 2000px, 0);
+ -ms-transform: scale3d(.1, .1, .1) translate3d(0, 2000px, 0);
+ transform: scale3d(.1, .1, .1) translate3d(0, 2000px, 0);
+ -webkit-transform-origin: center bottom;
+ -ms-transform-origin: center bottom;
+ transform-origin: center bottom;
+ -webkit-animation-timing-function: cubic-bezier(0.175, .885, .32, 1);
+ animation-timing-function: cubic-bezier(0.175, .885, .32, 1)
+ }
+}
+
+.zoomOutDown {
+ -webkit-animation-name: zoomOutDown;
+ animation-name: zoomOutDown
+}
+
+@-webkit-keyframes zoomOutLeft {
+ 40% {
+ opacity: 1;
+ -webkit-transform: scale3d(.475, .475, .475) translate3d(42px, 0, 0);
+ transform: scale3d(.475, .475, .475) translate3d(42px, 0, 0)
+ }
+
+ 100% {
+ opacity: 0;
+ -webkit-transform: scale(.1) translate3d(-2000px, 0, 0);
+ transform: scale(.1) translate3d(-2000px, 0, 0);
+ -webkit-transform-origin: left center;
+ transform-origin: left center
+ }
+}
+
+@keyframes zoomOutLeft {
+ 40% {
+ opacity: 1;
+ -webkit-transform: scale3d(.475, .475, .475) translate3d(42px, 0, 0);
+ -ms-transform: scale3d(.475, .475, .475) translate3d(42px, 0, 0);
+ transform: scale3d(.475, .475, .475) translate3d(42px, 0, 0)
+ }
+
+ 100% {
+ opacity: 0;
+ -webkit-transform: scale(.1) translate3d(-2000px, 0, 0);
+ -ms-transform: scale(.1) translate3d(-2000px, 0, 0);
+ transform: scale(.1) translate3d(-2000px, 0, 0);
+ -webkit-transform-origin: left center;
+ -ms-transform-origin: left center;
+ transform-origin: left center
+ }
+}
+
+.zoomOutLeft {
+ -webkit-animation-name: zoomOutLeft;
+ animation-name: zoomOutLeft
+}
+
+@-webkit-keyframes zoomOutRight {
+ 40% {
+ opacity: 1;
+ -webkit-transform: scale3d(.475, .475, .475) translate3d(-42px, 0, 0);
+ transform: scale3d(.475, .475, .475) translate3d(-42px, 0, 0)
+ }
+
+ 100% {
+ opacity: 0;
+ -webkit-transform: scale(.1) translate3d(2000px, 0, 0);
+ transform: scale(.1) translate3d(2000px, 0, 0);
+ -webkit-transform-origin: right center;
+ transform-origin: right center
+ }
+}
+
+@keyframes zoomOutRight {
+ 40% {
+ opacity: 1;
+ -webkit-transform: scale3d(.475, .475, .475) translate3d(-42px, 0, 0);
+ -ms-transform: scale3d(.475, .475, .475) translate3d(-42px, 0, 0);
+ transform: scale3d(.475, .475, .475) translate3d(-42px, 0, 0)
+ }
+
+ 100% {
+ opacity: 0;
+ -webkit-transform: scale(.1) translate3d(2000px, 0, 0);
+ -ms-transform: scale(.1) translate3d(2000px, 0, 0);
+ transform: scale(.1) translate3d(2000px, 0, 0);
+ -webkit-transform-origin: right center;
+ -ms-transform-origin: right center;
+ transform-origin: right center
+ }
+}
+
+.zoomOutRight {
+ -webkit-animation-name: zoomOutRight;
+ animation-name: zoomOutRight
+}
+
+@-webkit-keyframes zoomOutUp {
+ 40% {
+ opacity: 1;
+ -webkit-transform: scale3d(.475, .475, .475) translate3d(0, 60px, 0);
+ transform: scale3d(.475, .475, .475) translate3d(0, 60px, 0);
+ -webkit-animation-timing-function: cubic-bezier(0.55, .055, .675, .19);
+ animation-timing-function: cubic-bezier(0.55, .055, .675, .19)
+ }
+
+ 100% {
+ opacity: 0;
+ -webkit-transform: scale3d(.1, .1, .1) translate3d(0, -2000px, 0);
+ transform: scale3d(.1, .1, .1) translate3d(0, -2000px, 0);
+ -webkit-transform-origin: center bottom;
+ transform-origin: center bottom;
+ -webkit-animation-timing-function: cubic-bezier(0.175, .885, .32, 1);
+ animation-timing-function: cubic-bezier(0.175, .885, .32, 1)
+ }
+}
+
+@keyframes zoomOutUp {
+ 40% {
+ opacity: 1;
+ -webkit-transform: scale3d(.475, .475, .475) translate3d(0, 60px, 0);
+ -ms-transform: scale3d(.475, .475, .475) translate3d(0, 60px, 0);
+ transform: scale3d(.475, .475, .475) translate3d(0, 60px, 0);
+ -webkit-animation-timing-function: cubic-bezier(0.55, .055, .675, .19);
+ animation-timing-function: cubic-bezier(0.55, .055, .675, .19)
+ }
+
+ 100% {
+ opacity: 0;
+ -webkit-transform: scale3d(.1, .1, .1) translate3d(0, -2000px, 0);
+ -ms-transform: scale3d(.1, .1, .1) translate3d(0, -2000px, 0);
+ transform: scale3d(.1, .1, .1) translate3d(0, -2000px, 0);
+ -webkit-transform-origin: center bottom;
+ -ms-transform-origin: center bottom;
+ transform-origin: center bottom;
+ -webkit-animation-timing-function: cubic-bezier(0.175, .885, .32, 1);
+ animation-timing-function: cubic-bezier(0.175, .885, .32, 1)
+ }
+}
+
+.zoomOutUp {
+ -webkit-animation-name: zoomOutUp;
+ animation-name: zoomOutUp
+}
+
+@-webkit-keyframes slideInDown {
+ 0% {
+ -webkit-transform: translateY(-100%);
+ transform: translateY(-100%);
+ visibility: visible
+ }
+
+ 100% {
+ -webkit-transform: translateY(0);
+ transform: translateY(0)
+ }
+}
+
+@keyframes slideInDown {
+ 0% {
+ -webkit-transform: translateY(-100%);
+ -ms-transform: translateY(-100%);
+ transform: translateY(-100%);
+ visibility: visible
+ }
+
+ 100% {
+ -webkit-transform: translateY(0);
+ -ms-transform: translateY(0);
+ transform: translateY(0)
+ }
+}
+
+.slideInDown {
+ -webkit-animation-name: slideInDown;
+ animation-name: slideInDown
+}
+
+@-webkit-keyframes slideInLeft {
+ 0% {
+ -webkit-transform: translateX(-100%);
+ transform: translateX(-100%);
+ visibility: visible
+ }
+
+ 100% {
+ -webkit-transform: translateX(0);
+ transform: translateX(0)
+ }
+}
+
+@keyframes slideInLeft {
+ 0% {
+ -webkit-transform: translateX(-100%);
+ -ms-transform: translateX(-100%);
+ transform: translateX(-100%);
+ visibility: visible
+ }
+
+ 100% {
+ -webkit-transform: translateX(0);
+ -ms-transform: translateX(0);
+ transform: translateX(0)
+ }
+}
+
+.slideInLeft {
+ -webkit-animation-name: slideInLeft;
+ animation-name: slideInLeft
+}
+
+@-webkit-keyframes slideInRight {
+ 0% {
+ -webkit-transform: translateX(100%);
+ transform: translateX(100%);
+ visibility: visible
+ }
+
+ 100% {
+ -webkit-transform: translateX(0);
+ transform: translateX(0)
+ }
+}
+
+@keyframes slideInRight {
+ 0% {
+ -webkit-transform: translateX(100%);
+ -ms-transform: translateX(100%);
+ transform: translateX(100%);
+ visibility: visible
+ }
+
+ 100% {
+ -webkit-transform: translateX(0);
+ -ms-transform: translateX(0);
+ transform: translateX(0)
+ }
+}
+
+.slideInRight {
+ -webkit-animation-name: slideInRight;
+ animation-name: slideInRight
+}
+
+@-webkit-keyframes slideInUp {
+ 0% {
+ -webkit-transform: translateY(100%);
+ transform: translateY(100%);
+ visibility: visible
+ }
+
+ 100% {
+ -webkit-transform: translateY(0);
+ transform: translateY(0)
+ }
+}
+
+@keyframes slideInUp {
+ 0% {
+ -webkit-transform: translateY(100%);
+ -ms-transform: translateY(100%);
+ transform: translateY(100%);
+ visibility: visible
+ }
+
+ 100% {
+ -webkit-transform: translateY(0);
+ -ms-transform: translateY(0);
+ transform: translateY(0)
+ }
+}
+
+.slideInUp {
+ -webkit-animation-name: slideInUp;
+ animation-name: slideInUp
+}
+
+@-webkit-keyframes slideOutDown {
+ 0% {
+ -webkit-transform: translateY(0);
+ transform: translateY(0)
+ }
+
+ 100% {
+ visibility: hidden;
+ -webkit-transform: translateY(100%);
+ transform: translateY(100%)
+ }
+}
+
+@keyframes slideOutDown {
+ 0% {
+ -webkit-transform: translateY(0);
+ -ms-transform: translateY(0);
+ transform: translateY(0)
+ }
+
+ 100% {
+ visibility: hidden;
+ -webkit-transform: translateY(100%);
+ -ms-transform: translateY(100%);
+ transform: translateY(100%)
+ }
+}
+
+.slideOutDown {
+ -webkit-animation-name: slideOutDown;
+ animation-name: slideOutDown
+}
+
+@-webkit-keyframes slideOutLeft {
+ 0% {
+ -webkit-transform: translateX(0);
+ transform: translateX(0)
+ }
+
+ 100% {
+ visibility: hidden;
+ -webkit-transform: translateX(-100%);
+ transform: translateX(-100%)
+ }
+}
+
+@keyframes slideOutLeft {
+ 0% {
+ -webkit-transform: translateX(0);
+ -ms-transform: translateX(0);
+ transform: translateX(0)
+ }
+
+ 100% {
+ visibility: hidden;
+ -webkit-transform: translateX(-100%);
+ -ms-transform: translateX(-100%);
+ transform: translateX(-100%)
+ }
+}
+
+.slideOutLeft {
+ -webkit-animation-name: slideOutLeft;
+ animation-name: slideOutLeft
+}
+
+@-webkit-keyframes slideOutRight {
+ 0% {
+ -webkit-transform: translateX(0);
+ transform: translateX(0)
+ }
+
+ 100% {
+ visibility: hidden;
+ -webkit-transform: translateX(100%);
+ transform: translateX(100%)
+ }
+}
+
+@keyframes slideOutRight {
+ 0% {
+ -webkit-transform: translateX(0);
+ -ms-transform: translateX(0);
+ transform: translateX(0)
+ }
+
+ 100% {
+ visibility: hidden;
+ -webkit-transform: translateX(100%);
+ -ms-transform: translateX(100%);
+ transform: translateX(100%)
+ }
+}
+
+.slideOutRight {
+ -webkit-animation-name: slideOutRight;
+ animation-name: slideOutRight
+}
+
+@-webkit-keyframes slideOutUp {
+ 0% {
+ -webkit-transform: translateY(0);
+ transform: translateY(0)
+ }
+
+ 100% {
+ visibility: hidden;
+ -webkit-transform: translateY(-100%);
+ transform: translateY(-100%)
+ }
+}
+
+@keyframes slideOutUp {
+ 0% {
+ -webkit-transform: translateY(0);
+ -ms-transform: translateY(0);
+ transform: translateY(0)
+ }
+
+ 100% {
+ visibility: hidden;
+ -webkit-transform: translateY(-100%);
+ -ms-transform: translateY(-100%);
+ transform: translateY(-100%)
+ }
+}
+
+.slideOutUp {
+ -webkit-animation-name: slideOutUp;
+ animation-name: slideOutUp
+}
diff --git a/components/css/iconfont.css b/components/css/iconfont.css
new file mode 100644
index 0000000..f4a3f66
--- /dev/null
+++ b/components/css/iconfont.css
@@ -0,0 +1,23 @@
+@font-face {
+ font-family: 'iconfont';
+ src: url('https://at.alicdn.com/t/font_2248773_lp8msxycly.eot');
+ src: url('https://at.alicdn.com/t/font_2248773_lp8msxycly.eot?#iefix') format('embedded-opentype'),
+ url('https://at.alicdn.com/t/font_2248773_lp8msxycly.woff2') format('woff2'),
+ url('https://at.alicdn.com/t/font_2248773_lp8msxycly.woff') format('woff'),
+ url('https://at.alicdn.com/t/font_2248773_lp8msxycly.ttf') format('truetype'),
+ url('https://at.alicdn.com/t/font_2248773_lp8msxycly.svg#iconfont') format('svg');
+}
+
+.iconfont {
+ font-family: "iconfont" !important;
+ font-size: 28rpx;
+ font-style: normal;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+ color: #666;
+ margin-left: 15rpx;
+}
+
+.icon-iconfront::before {
+ content: "\ue69c";
+}
diff --git a/components/get-phone/index.vue b/components/get-phone/index.vue
new file mode 100644
index 0000000..7e4d527
--- /dev/null
+++ b/components/get-phone/index.vue
@@ -0,0 +1,138 @@
+
+
+
+
+
+
+
+ 常熟小程序
+ 微信授权获取手机号码
+
+
+
+
+
+
+
+
+
+
diff --git a/components/html/AI.vue b/components/html/AI.vue
new file mode 100644
index 0000000..a6e9295
--- /dev/null
+++ b/components/html/AI.vue
@@ -0,0 +1,66 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/components/html/back.vue b/components/html/back.vue
new file mode 100644
index 0000000..47103c2
--- /dev/null
+++ b/components/html/back.vue
@@ -0,0 +1,163 @@
+
+
+
+
+
+
+ {{title}}
+
+
+
+
+
+
+
+
+
+
diff --git a/components/html/listnav.vue b/components/html/listnav.vue
new file mode 100644
index 0000000..cdb4842
--- /dev/null
+++ b/components/html/listnav.vue
@@ -0,0 +1,103 @@
+
+
+
+
+ {{el.name}}
+
+
+
+
+
+
+
+
+
+
diff --git a/components/html/tabBar.vue b/components/html/tabBar.vue
new file mode 100644
index 0000000..8790b48
--- /dev/null
+++ b/components/html/tabBar.vue
@@ -0,0 +1,99 @@
+
+
+
+
+ {{el.text}}
+
+
+
+
+
+
+
diff --git a/components/invinbg-image-cropper/.DS_Store b/components/invinbg-image-cropper/.DS_Store
new file mode 100644
index 0000000..5008ddf
Binary files /dev/null and b/components/invinbg-image-cropper/.DS_Store differ
diff --git a/components/invinbg-image-cropper/invinbg-image-cropper.vue b/components/invinbg-image-cropper/invinbg-image-cropper.vue
new file mode 100644
index 0000000..00d5277
--- /dev/null
+++ b/components/invinbg-image-cropper/invinbg-image-cropper.vue
@@ -0,0 +1,759 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 取消
+ 确定
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/components/lb-picker/README.md b/components/lb-picker/README.md
new file mode 100644
index 0000000..4541bb6
--- /dev/null
+++ b/components/lb-picker/README.md
@@ -0,0 +1,488 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+插件市场里面的 picker 选择器不满足自己的需求,所以自己写了一个简单的 picker 选择器,可扩展、可自定义,一般满足日常需要。
+Github:[uni-lb-picker](https://github.com/liub1934/uni-lb-picker)
+插件市场:[uni-lb-picker](https://ext.dcloud.net.cn/plugin?id=1111)
+H5 Demo:[点击预览](https://github.liubing.me/uni-lb-picker)
+
+> 如果问题最好去 github 反馈,插件市场评论区留下五星好评即可,[点我去反馈](https://github.com/liub1934/uni-lb-picker/issues/new)
+
+> **由于之前`cancel`拼写失误,写成了`cancle`,`v1.08`现已修正,如果之前版本有使用`cancel`事件的,更新后请及时修正。**
+
+## 兼容性
+
+App + Nvue + H5 + 各平台小程序(快应用及 360 未测试)
+
+## 功能
+
+1、单选
+2、多级联动,非多级联动,理论支持任意级数
+3、省市区选择,基于多级联动
+4、自定义选择器头部确定取消按钮颜色及插槽支持
+5、选择器可视区自定义滚动个数
+6、自定义数据字段,满足不同人的需求
+7、自定义选择器样式
+8、formatter 格式化自定义显示
+9、单选及非联动选择支持扁平化的简单数据,如下形式:
+
+```javascript
+// 单选列表
+list1: ['选项1', '选项2', '选项2'],
+// 非联动选择列表
+list2: [
+ ['选项1', '选项2', '选项3'],
+ ['选项11', '选项22', '选项33'],
+ ['选项111', '选项222', '选项333']
+]
+```
+
+## 引入插件
+
+单独引入,在需要使用的页面上 import 引入即可
+
+```html
+
+
+
+
+
+
+
+```
+
+全局引入,`main.js`中 import 引入并注册即可全局使用
+
+```jsvascript
+import LbPicker from '@/components/lb-picker'
+Vue.component("lb-picker", LbPicker)
+```
+
+easycom 引入
+
+`pages.json`加上如下配置:
+
+```json
+"easycom": {
+ "autoscan": true,
+ "custom": {
+ "lb-picker": "@/components/lb-picker/index.vue"
+ }
+}
+```
+
+npm 安装引入:
+
+```shell
+npm install uni-lb-picker
+```
+
+```jsvascript
+import LbPicker from 'uni-lb-picker'
+```
+
+## 选择器数据格式
+
+### 单选
+
+常规数据
+
+```javascript
+list: [
+ {
+ label: '选项1',
+ value: '1'
+ },
+ {
+ label: '选项2',
+ value: '2'
+ }
+]
+```
+
+扁平化简单数据
+
+```javascript
+list: ['选项1', '选项2']
+```
+
+### 多级联动
+
+```javascript
+list: [
+ {
+ label: '选项1',
+ value: '1',
+ children: [
+ {
+ label: '选项1-1',
+ value: '1-1',
+ children: [
+ {
+ label: '选项1-1-1',
+ value: '1-1-1'
+ }
+ ]
+ }
+ ]
+ }
+]
+```
+
+### 非联动选择
+
+常规数据
+
+```javascript
+list: [
+ [
+ { label: '选项1', value: '1' },
+ { label: '选项2', value: '2' },
+ { label: '选项3', value: '3' }
+ ],
+ [
+ { label: '选项11', value: '11' },
+ { label: '选项22', value: '22' },
+ { label: '选项33', value: '33' }
+ ],
+ [
+ { label: '选项111', value: '111' },
+ { label: '选项222', value: '222' },
+ { label: '选项333', value: '333' }
+ ]
+]
+```
+
+扁平化简单数据
+
+```javascript
+list: [
+ ['选项1', '选项2', '选项3'],
+ ['选项11', '选项22', '选项33'],
+ ['选项111', '选项222', '选项333']
+]
+```
+
+## 调用显示选择器
+
+通过`ref`形式手动调用`show`方法显示,隐藏同理调用`hide`
+
+```html
+
+```
+
+```javascript
+this.$refs.picker.show() // 显示
+this.$refs.picker.hide() // 隐藏
+```
+
+`v1.1.3`新增,将需要点击的元素包裹在`lb-picker`中即可。
+
+```html
+
+
+
+```
+
+## 绑定值及设置默认值
+
+支持 vue 中`v-model`写法绑定值,无需自己维护选中值的索引。
+
+```javascript
+
+
+
+data () {
+ return {
+ value1: '' // 单选
+ value2: [] // 多列联动选择
+ }
+}
+```
+
+## 多个选择器
+
+通过设置不同的`ref`,然后调用即可
+
+```javascript
+
+
+
+this.$refs.picker1.show() // picker1显示
+this.$refs.picker2.show() // picker2显示
+```
+
+## 省市区选择
+
+省市区选择是基于多列联动选择,数据来源:[https://github.com/modood/Administrative-divisions-of-China](https://github.com/modood/Administrative-divisions-of-China),
+省市区文件位于`/pages/demos/area-data-min.js`,自行引入即可,可参考`demo3省市区选择`,
+也可使用自己已有的省市区数据,如果数据字段不一样,也可以自定义,参考下方自定义数据字段。
+
+## 自定义数据字段
+
+为了满足不同人的需求,插件支持自定义数据字段名称, 插件默认的数据字段如下形式:
+
+```javascript
+list: [
+ {
+ label: '选择1',
+ value: 1,
+ children: []
+ },
+ {
+ label: '选择1',
+ value: 1,
+ children: []
+ }
+]
+```
+
+如果你的数据字段和上面不一样,如下形式:
+
+```javascript
+list: [
+ {
+ text: '选择1',
+ id: 1,
+ child: []
+ },
+ {
+ text: '选择1',
+ id: 1,
+ child: []
+ }
+]
+```
+
+通过设置参数中的`props`即可,如下所示:
+
+```javascript
+
+
+data () {
+ return {
+ myProps: {
+ label: 'text',
+ value: 'id',
+ children: 'child'
+ }
+ }
+}
+```
+
+## 插槽使用
+
+选择器支持一些可自定义化的插槽,如选择器的取消和确定文字按钮,如果需要对其自定义处理的话,比如加个 icon 图标之类的,可使用插槽,使用方法如下:
+
+```html
+
+ 我是自定义取消
+ 我是自定义确定
+
+```
+
+也可参考示例中的`demo5`,自定义插槽元素样式交给开发者自由调整,插槽仅提供预留位置。
+
+其他插槽见下。
+
+## 参数及事件
+
+### Props
+
+| 参数 | 说明 | 类型 | 可选值 | 默认值 |
+| :--------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------- | :--------------------------------------------------------------- | :------------------------------------------------ |
+| value/v-model | 绑定值,联动选择为 Array 类型 | String/Number/Array | - | - |
+| mode | 选择器类型,支持单列,多列联动 | String | selector 单选/multiSelector 多级联动/unlinkedSelector 多级非联动 | selector |
+| list | 选择器数据(v1.0.7 单选及非联动多选支持扁平数据:['选项 1', '选项 2']) | Array | - | - |
+| level | 多列联动层级,仅 mode 为 multiSelector 有效 | Number | - | 1 |
+| props | 自定义数据字段 | Object | - | {label:'label',value:'value',children:'children'} |
+| cancel-text | 取消文字 | String | - | 取消 |
+| cancel-color | 取消文字颜色 | String | - | #999 |
+| confirm-text | 确定文字 | String | - | 确定 |
+| confirm-color | 确定文字颜色 | String | - | #007aff |
+| empty-text | `(v1.0.7 新增)`选择器列表为空的时候显示的文字 | String | - | 暂无数据 |
+| empty-color | `(v1.0.7 新增)`暂无数据文字颜色 | String | - | #999 |
+| column-num | 可视滚动区域内滚动个数,最好设置奇数值 | Number | - | 5 |
+| radius | 选择器顶部圆角,支持 rpx,如 radius="10rpx" | String | - | - |
+| column-style | `(v1.1.6 重新新增)`选择器默认样式,仅`nvue`支持,其他端见下`选择器自定义样式`说明 | Object | - | - |
+| active-column-style | `(v1.1.6 重新新增)`选择器选中样式,仅`nvue`支持,其他端见下`选择器自定义样式`说明 | Object | - | - |
+| loading | 选择器是否显示加载中,可使用 loading 插槽自定义加载效果 | Boolean | - | - |
+| mask-color | 遮罩层颜色 | String | - | rgba(0, 0, 0, 0.4) |
+| show-mask | `(v1.1.0 新增)`是否显示遮罩层 | Boolean | true/false | true |
+| close-on-click-mask | 点击遮罩层是否关闭选择器 | Boolean | true/false | true |
+| ~~change-on-init~~ | ~~(v1.0.7 已弃用)初始化时是否触发 change 事件~~ | Boolean | true/false | - |
+| dataset | `(v1.0.7 新增)`可以向组件中传递任意的自定义的数据(对象形式数据),如`:dataset="{name:'test'}"`,在`confirm`或`change`事件中可以取到 | Object | - | - |
+| show-header | `(v1.0.8 新增)`是否显示选择器头部 | Boolean | - | true |
+| inline | `(v1.0.8 新增)`inline 模式,开启后默认显示选择器,无需点击弹出,可以配合`show-header`一起使用 | Boolean | - | - |
+| z-index | `(v1.0.9 新增)`选择器层级,遮罩层默认-1 | Number | - | 999 |
+| safe-area-inset-bottom | `(v1.1.4 新增)`是否留出底部安全距离(nvue 无效) | Boolean | true/false | true |
+| disabled | `(v1.1.4 新增)`是否禁用选择器,禁用后无法弹出选择器 | Boolean | - | - |
+| align | `(v1.1.6 新增)`选择器中文字对齐方式,默认居中 | String | left/center/right | center |
+| press-enable | `(v1.1.6 新增)`是否开启长按选择器数据`showtoast`弹出`label`提示,部分情况下选择器数据文字过长会显示省略号,如需查看完整的文字内容,可开启此选项,长按后会`showtoast`弹出完整的文字内容,默认不开启(支付宝小程序暂不支持[详情](https://ask.dcloud.net.cn/question/106237)) | Boolean | - | - |
+| press-time | `(v1.1.6 新增)`长按触发时间,单位毫秒 ms | Number | - | 500 |
+| formatter | `(v1.1.7 新增)`格式化自定义选择器文字内容,`Function`类型,`return`一个字符串(仅`app` `nvue` `h5`支持),`item`当前项信息,`rowIndex`当前数据所在行数,`columnIndex`当前数据所在列数,写法参考[demo14](https://github.com/liub1934/uni-lb-picker/blob/master/pages/demos/demo14/demo14.vue#L206) | Function({ item, rowIndex, columnIndex }) | - | - |
+
+### 方法
+
+| 方法名 | 说明 | 参数 | 返回值 |
+| :------------- | :------------------------------------- | :-------------- | :----------------------------------------------------------------------------------------------------------- |
+| show | 打开选择器 | - | |
+| hide | 关闭选择器 | - | |
+| getColumnsInfo | (v1.1.0 新增)根据 value 获取选择器信息 | 绑定值的`value` | 同`change` `confirm`回调参数,如果传入的`value`获取不到信息则只返回一个含有`dataset`的对象,具体自行打印查看 |
+
+### Events
+
+| 事件名称 | 说明 | 回调参数 |
+| :------- | :--------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| show | 选择器打开时触发 | - |
+| hide | 选择器隐藏时触发 | - |
+| change | 选择器滚动时触发,此时不会改变绑定的值 | `{ index, item, value, change }` `index`触发滚动后新的索引,单选时是具体的索引值,多列联动选择时为数组。`item`触发滚动后新的的完整内容,包括`label`、`value`等,单选时为对象,多列选择时为数组对象。`value`触发滚动后新的 value 值,单列选择时为具体值,多列联动选择时为数组。`change`触发事件的类型,详情参考下面的 change 事件备注 |
+| confirm | 点击选择器确定时触发,此时会改变绑定的值 | 同上`change`事件说明 |
+| cancel | 点击选择器取消时触发 | 同上`change`事件说明 |
+
+### `change` 事件备注
+
+如果绑定的值是空的,`change`触发后里面的内容都是列表的第一项。
+`change`事件会在以下情况触发:
+
+- 初始化
+- 绑定值 value 变化
+- 选择器 list 列表变化
+- 滚动选择器
+
+以上情况会在回调函数中都可以取到`change`变化的类型,对应上面的情况包括以下:
+
+- `init`
+- `value`
+- `list`
+- `scroll`
+
+根据这些类型大家可以在`change`的时候按需处理自己的业务逻辑,`init`现在指挥在调用选择器弹出的时候触发。
+下面的说明情况已失效,如需要在页面显示的时候根据`value`的值显示相应的中文,调用`v1.10`新增的方法`getColumnsInfo`,传入绑定的值即可获取到你想要的所有信息。
+~~比如一种常见的情况,有默认值的时候需要显示默认值的文字,此时可以`change`事件中判断`change`的类型是否是`init`,如果是的话可以取事件回调中的`item`进行显示绑定值对应的文字信息。~~
+
+```javascript
+handleChange (e) {
+ if (e.change === 'init') {
+ console.log(e.item.label) // 单选 选项1
+ console.log(e.item.map(item => item.label).join('-')) // 多选 选项1-选项11
+ }
+}
+```
+
+### 插槽
+
+| 插槽名 | 说明 |
+| :------------ | :--------------------- |
+| cancel-text | 选择器取消文字插槽 |
+| action-center | 选择器顶部中间插槽 |
+| confirm-text | 选择器确定文字插槽 |
+| loading | 选择器 loading 插槽 |
+| empty | 选择器 空数据 插槽 |
+| header-top | 选择器头部顶部插槽 |
+| header-bottom | 选择器头部底部插槽 |
+| picker-top | 选择器滚动部分顶部插槽 |
+| picker-bottom | 选择器滚动部分底部插槽 |
+
+### 选择器自定义样式
+
+> nvue 专属写法,需要定义`column-style`和`active-column-style`,写法如下:
+
+```html
+
+```
+
+```javascript
+data () {
+ return {
+ // 默认样式
+ columnStyle: {
+ color: '#f0ad4e'
+ },
+ // 选择样式
+ activeColumnStyle: {
+ color: '#007aff',
+ fontWeight: 700
+ }
+ }
+}
+```
+
+> 其他端写法,覆盖默认样式即可。
+
+```css
+
+```
+
+完整代码可以参考`demo9`。
+
+### 获取选中值的文字
+
+`@confirm`事件中可以拿到:
+
+单选:
+
+```javascript
+handleConfirm (e) {
+ console.log(e.item.label) // 选项1
+}
+```
+
+联动选择:
+
+```javascript
+handleConfirm (e) {
+ console.log(e.item.map(item => item.label).join('-')) // 选项1-选项11
+}
+```
+
+## Tips
+
+微信小程序端,滚动时在 iOS 自带振动反馈,可在系统设置 -> 声音与触感 -> 系统触感反馈中关闭
+
+## 其他
+
+其他功能参考示例 Demo 代码。
diff --git a/components/lb-picker/index.vue b/components/lb-picker/index.vue
new file mode 100644
index 0000000..13b3e9f
--- /dev/null
+++ b/components/lb-picker/index.vue
@@ -0,0 +1,392 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ emptyText }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/lb-picker/mixins/index.js b/components/lb-picker/mixins/index.js
new file mode 100644
index 0000000..adb35fb
--- /dev/null
+++ b/components/lb-picker/mixins/index.js
@@ -0,0 +1,93 @@
+import { getColumns, isObject, isFunction } from '../utils'
+export const commonMixin = {
+ data () {
+ return {
+ isConfirmChange: false,
+ indicatorStyle: `height: 34px`,
+ pressTimeout: null
+ }
+ },
+ created () {
+ this.init('init')
+ },
+ methods: {
+ init (changeType) {
+ if (this.list && this.list.length) {
+ const column = getColumns({
+ value: this.value,
+ list: this.list,
+ mode: this.mode,
+ props: this.props,
+ level: this.level
+ })
+ const { columns, value, item, index } = column
+ this.selectValue = value
+ this.selectItem = item
+ this.pickerColumns = columns
+ this.pickerValue = index
+ this.$emit('change', {
+ value: this.selectValue,
+ item: this.selectItem,
+ index: this.pickerValue,
+ change: changeType
+ })
+ }
+ },
+ touchstart (e) {
+ if (!this.pressEnable) return
+ clearTimeout(this.pressTimeout)
+ this.pressTimeout = setTimeout(() => {
+ let item = {}
+ let toastTitle = ''
+ // #ifdef APP-NVUE
+ item = e.target.dataset.item
+ // #endif
+
+ // #ifdef H5
+ item = JSON.parse(e.currentTarget.dataset.item)
+ // #endif
+
+ // #ifndef APP-NVUE || H5
+ item = e.currentTarget.dataset.item
+ // #endif
+
+ // #ifdef APP-PLUS || H5
+ toastTitle = this.getLabel(item)
+ // #endif
+
+ // #ifndef APP-PLUS || H5
+ toastTitle = item[this.props.label] || item
+ // #endif
+ uni.showToast({
+ title: toastTitle,
+ icon: 'none'
+ })
+ }, this.pressTime)
+ },
+ touchmove () {
+ if (!this.pressEnable) return
+ clearTimeout(this.pressTimeout)
+ },
+ touchend () {
+ if (!this.pressEnable) return
+ clearTimeout(this.pressTimeout)
+ },
+ getLabel (item, rowIndex, columnIndex) {
+ if (this.formatter && isFunction(this.formatter)) {
+ return this.formatter({ item, rowIndex, columnIndex })
+ } else {
+ return item[this.props.label] || item
+ }
+ }
+ },
+ watch: {
+ value () {
+ if (!this.isConfirmChange) {
+ this.init('value')
+ }
+ },
+ list () {
+ this.init('list')
+ }
+ }
+}
diff --git a/components/lb-picker/pickers/multi-selector-picker.vue b/components/lb-picker/pickers/multi-selector-picker.vue
new file mode 100644
index 0000000..97df459
--- /dev/null
+++ b/components/lb-picker/pickers/multi-selector-picker.vue
@@ -0,0 +1,135 @@
+
+
+
+
+
+
+
+
+
+
+
+ {{ getLabel(item, i, index) }}
+
+
+
+ {{ item[props.label] || item }}
+
+
+
+
+
+
+
+
+
+
diff --git a/components/lb-picker/pickers/selector-picker.vue b/components/lb-picker/pickers/selector-picker.vue
new file mode 100644
index 0000000..0a0fda9
--- /dev/null
+++ b/components/lb-picker/pickers/selector-picker.vue
@@ -0,0 +1,113 @@
+
+
+
+
+
+
+
+
+
+
+
+ {{ getLabel(item, i, 0) }}
+
+
+
+ {{ item[props.label] || item }}
+
+
+
+
+
+
+
+
+
+
diff --git a/components/lb-picker/pickers/unlinked-selector-picker.vue b/components/lb-picker/pickers/unlinked-selector-picker.vue
new file mode 100644
index 0000000..05d8098
--- /dev/null
+++ b/components/lb-picker/pickers/unlinked-selector-picker.vue
@@ -0,0 +1,116 @@
+
+
+
+
+
+
+
+
+
+
+
+ {{ getLabel(item, i, index) }}
+
+
+
+ {{ item[props.label] || item }}
+
+
+
+
+
+
+
+
+
+
diff --git a/components/lb-picker/style/picker-item.scss b/components/lb-picker/style/picker-item.scss
new file mode 100644
index 0000000..15d6e39
--- /dev/null
+++ b/components/lb-picker/style/picker-item.scss
@@ -0,0 +1,40 @@
+.lb-picker-column {
+ height: 34px;
+ padding: 0 10px;
+ /* #ifndef APP-NVUE */
+ display: flex;
+ box-sizing: border-box;
+ white-space: nowrap;
+ overflow: hidden;
+ /* #endif */
+ flex-direction: row;
+ align-items: center;
+}
+
+.lb-picker-column-label {
+ font-size: 16px;
+ text-align: center;
+ flex: 1;
+ /* #ifdef APP-NVUE */
+ lines: 1;
+ /* #endif */
+ text-overflow: ellipsis;
+ transition-property: color;
+ transition-duration: 0.3s;
+ /* #ifndef APP-NVUE */
+ overflow: hidden;
+ white-space: nowrap;
+ /* #endif */
+}
+
+.lb-picker-column-label-left {
+ text-align: left;
+}
+
+.lb-picker-column-label-center {
+ text-align: center;
+}
+
+.lb-picker-column-label-right {
+ text-align: right;
+}
\ No newline at end of file
diff --git a/components/lb-picker/style/picker.scss b/components/lb-picker/style/picker.scss
new file mode 100644
index 0000000..a4744e7
--- /dev/null
+++ b/components/lb-picker/style/picker.scss
@@ -0,0 +1,176 @@
+.lb-picker {
+ position: relative;
+}
+
+.lb-picker-mask {
+ background-color: rgba(0, 0, 0, 0.0);
+ position: fixed;
+ top: 0;
+ right: 0;
+ left: 0;
+ bottom: 0;
+}
+
+.lb-picker-mask-animation {
+ transition-property: background-color;
+ transition-duration: 0.3s;
+}
+
+.lb-picker-container {
+ position: relative;
+}
+
+.lb-picker-container-fixed {
+ position: fixed;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ transform: translateY(100%);
+ /* #ifndef APP-NVUE */
+ overflow: hidden;
+ /* #endif */
+}
+
+.lb-picker-container-animation {
+ transition-property: transform;
+ transition-duration: 0.3s;
+}
+
+.lb-picker-container-show {
+ transform: translateY(0);
+}
+
+.lb-picker-header {
+ position: relative;
+ background-color: #fff;
+ /* #ifdef APP-NVUE */
+ border-bottom-width: 1px;
+ border-bottom-style: solid;
+ border-bottom-color: #e5e5e5;
+ border-top-width: 1px;
+ border-top-style: solid;
+ border-top-color: #e5e5e5;
+ /* #endif */
+ /* #ifndef APP-NVUE */
+ box-sizing: border-box;
+ /* #endif */
+
+}
+
+/* #ifndef APP-NVUE */
+.lb-picker-header::before {
+ content: "";
+ position: absolute;
+ left: 0;
+ top: 0;
+ right: 0;
+ height: 1px;
+ clear: both;
+ border-bottom: 1px solid #e5e5e5;
+ color: #e5e5e5;
+ transform-origin: 0 100%;
+ transform: scaleY(0.5);
+}
+
+.lb-picker-header::after {
+ content: "";
+ position: absolute;
+ left: 0;
+ bottom: 0;
+ right: 0;
+ height: 1px;
+ clear: both;
+ border-bottom: 1px solid #e5e5e5;
+ color: #e5e5e5;
+ transform-origin: 0 100%;
+ transform: scaleY(0.5);
+}
+
+/* #endif */
+
+.lb-picker-header-actions {
+ height: 45px;
+ /* #ifndef APP-NVUE */
+ box-sizing: border-box;
+ display: flex;
+ /* #endif */
+ flex-direction: row;
+ justify-content: space-between;
+ flex-wrap: nowrap;
+}
+
+.lb-picker-action {
+ padding-left: 10px;
+ padding-right: 10px;
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: row;
+ align-items: center;
+ justify-content: center;
+}
+
+.lb-picker-action-cancel-text {
+ font-size: 16px;
+}
+
+.lb-picker-action-confirm-text {
+ font-size: 16px;
+}
+
+.lb-picker-content {
+ position: relative;
+ background-color: #fff;
+}
+
+/* #ifndef APP-PLUS */
+.lb-picker-content-safe-buttom {
+ padding-bottom: 0;
+ padding-bottom: constant(safe-area-inset-bottom);
+ padding-bottom: env(safe-area-inset-bottom);
+}
+
+/* #endif */
+
+.lb-picker-content-main {
+ position: relative;
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ justify-content: center;
+ flex-direction: column;
+}
+
+.lb-picker-loading,
+.lb-picker-empty {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ justify-content: center;
+ align-items: center;
+}
+
+.lb-picker-empty-text {
+ font-size: 16px;
+}
+
+.lb-picker-loading-img {
+ width: 25px;
+ height: 25px;
+ /* #ifndef APP-NVUE */
+ animation: rotating 2s linear infinite;
+ /* #endif */
+}
+
+/* #ifndef APP-NVUE */
+@keyframes rotating {
+ 0% {
+ transform: rotate(0deg)
+ }
+
+ 100% {
+ transform: rotate(1turn)
+ }
+}
+
+/* #endif */
\ No newline at end of file
diff --git a/components/lb-picker/utils.js b/components/lb-picker/utils.js
new file mode 100644
index 0000000..716d011
--- /dev/null
+++ b/components/lb-picker/utils.js
@@ -0,0 +1,121 @@
+/**
+ * 判断是否是对象
+ *
+ * @export
+ * @param {*} val
+ * @returns true/false
+ */
+export function isObject (val) {
+ return Object.prototype.toString.call(val) === '[object Object]'
+}
+
+/**
+ * 判断是否是Function
+ *
+ * @export
+ * @param {*} val
+ * @returns true/false
+ */
+export function isFunction (val) {
+ return Object.prototype.toString.call(val) === '[object Function]'
+}
+
+/**
+ * 根据value获取columns信息
+ *
+ * @export
+ * @param {*} { value, list, mode, props, level }
+ * @param {number} [type=2] 查询不到value数据返回数据类型 1空值null 2默认第一个选项
+ * @returns
+ */
+export function getColumns ({ value, list, mode, props, level }, type = 2) {
+ let pickerValue = []
+ let pickerColumns = []
+ let selectValue = []
+ let selectItem = []
+ let columnsInfo = null
+ switch (mode) {
+ case 'selector':
+ let index = list.findIndex(item => {
+ return isObject(item) ? item[props.value] === value : item === value
+ })
+ if (index === -1 && type === 1) {
+ columnsInfo = null
+ } else {
+ index = index > -1 ? index : 0
+ selectItem = list[index]
+ selectValue = isObject(selectItem)
+ ? selectItem[props.value]
+ : selectItem
+ pickerColumns = list
+ pickerValue = [index]
+ columnsInfo = {
+ index: pickerValue,
+ value: selectValue,
+ item: selectItem,
+ columns: pickerColumns
+ }
+ }
+ break
+ case 'multiSelector':
+ const setPickerItems = (data = [], index = 0) => {
+ if (!data.length) return
+ const defaultValue = value || []
+ if (index < level) {
+ const value = defaultValue[index] || ''
+ let i = data.findIndex(item => item[props.value] === value)
+ if (i === -1 && type === 1) return
+ i = i > -1 ? i : 0
+ pickerValue[index] = i
+ pickerColumns[index] = data
+ if (data[i]) {
+ selectValue[index] = data[i][props.value]
+ selectItem[index] = data[i]
+ setPickerItems(data[i][props.children] || [], index + 1)
+ }
+ }
+ }
+ setPickerItems(list)
+ if (!selectValue.length && type === 1) {
+ columnsInfo = null
+ } else {
+ columnsInfo = {
+ index: pickerValue,
+ value: selectValue,
+ item: selectItem,
+ columns: pickerColumns
+ }
+ }
+ break
+ case 'unlinkedSelector':
+ list.forEach((item, i) => {
+ let index = item.findIndex(item => {
+ return isObject(item)
+ ? item[props.value] === value[i]
+ : item === value[i]
+ })
+ if (index === -1 && type === 1) return
+ index = index > -1 ? index : 0
+ const columnItem = list[i][index]
+ const valueItem = isObject(columnItem)
+ ? columnItem[props.value]
+ : columnItem
+ pickerValue[i] = index
+ selectValue[i] = valueItem
+ selectItem[i] = columnItem
+ })
+ pickerColumns = list
+ if (!selectValue.length && type === 1) {
+ columnsInfo = null
+ } else {
+ columnsInfo = {
+ index: pickerValue,
+ value: selectValue,
+ item: selectItem,
+ columns: pickerColumns
+ }
+ }
+ break
+ }
+ return columnsInfo
+}
diff --git a/components/luch-audio/luch-audio.vue b/components/luch-audio/luch-audio.vue
new file mode 100644
index 0000000..147f869
--- /dev/null
+++ b/components/luch-audio/luch-audio.vue
@@ -0,0 +1,278 @@
+
+
+
+
+
+
+
+
+ {{ name }}
+
+ {{ audioTimeUpdate }}
+
+
+
+
+
+
+
+
+
+
diff --git a/components/luch-audio/readme.md b/components/luch-audio/readme.md
new file mode 100644
index 0000000..b584ec4
--- /dev/null
+++ b/components/luch-audio/readme.md
@@ -0,0 +1,65 @@
+**插件使用说明**
+
+- 基于 uni.createInnerAudioContext() 封装audio音频组件(样式同原生audio组件)
+- 支持双向绑定
+- 支持自定义修改样式
+
+
+**Example**
+---
+
+``` javascript
+
+
+// 控制变量audioPlay ,如果true音频会播放,否则暂停
+```
+
+**Attributes**
+--
+
+参数|说明|类型|可选值|默认值|required
+--|:-
+play|是否播放,双向绑定,需加 ` .sync `|Boolean| — | — |true
+src|资源路径|String| — | — | —
+poster|封面图片路径|String| — | — | —
+name|音频名称|String| — | 未知音频 | —
+author|作者名字|String| — | 未知作者 | —
+autoplay|是否自动开始播放|Boolean| — | false | —
+loop|是否循环播放|Boolean| — | false | —
+obeyMuteSwitch|是否遵循系统静音开关,当此参数为 false 时,即使用户打开了静音开关,也能继续发出声音|Boolean| — | true | —
+
+其他api 可在组件内 ` contextInit ` 函数初始化时自定义添加
+
+**平台支持度**
+--
+
+5+App|H5|微信小程序|支付宝小程序|百度小程序|头条小程序
+--|:-
+yes|yes|yes|no|yes|yes
+
+**注意:**以上平台支持度为uni-app 对` uni.createInnerAudioContext() ` api 的支持度,本组件的支持度本人只在微信小程序使用过,其他平台*未做测试*
+
+**使用**
+--
+
+下载后把该文件放至 components 文件夹或 特定平台组件 文件夹即可
+
+**更新**
+--
+
+- v0.0.1 组件
+
+**可扩展性**
+--
+
+api 增加参考 ` https://uniapp.dcloud.io/api/media/audio-context?id=createinneraudiocontext `
+
+组件内的播放暂停图标本人因为要发布组件,所以使用了base64,大家可自行替换;
+
+实例获取可以通过ref 获取组件内的 ` innerAudioContext ` (未实验,只是估计 0.0)
+
+**说明**
+--
+
+切换src 或者切换页面都会销毁实例
+写本组件的原因就是原生audio组件无法修改宽度,导致某些情况下显示不全,本组件是100%自适应布局;
diff --git a/components/mescroll-uni/components/mescroll-down.css b/components/mescroll-uni/components/mescroll-down.css
new file mode 100644
index 0000000..72bf106
--- /dev/null
+++ b/components/mescroll-uni/components/mescroll-down.css
@@ -0,0 +1,55 @@
+/* 下拉刷新区域 */
+.mescroll-downwarp {
+ position: absolute;
+ top: -100%;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ text-align: center;
+}
+
+/* 下拉刷新--内容区,定位于区域底部 */
+.mescroll-downwarp .downwarp-content {
+ position: absolute;
+ left: 0;
+ bottom: 0;
+ width: 100%;
+ min-height: 60rpx;
+ padding: 20rpx 0;
+ text-align: center;
+}
+
+/* 下拉刷新--提示文本 */
+.mescroll-downwarp .downwarp-tip {
+ display: inline-block;
+ font-size: 28rpx;
+ vertical-align: middle;
+ margin-left: 16rpx;
+ /* color: gray; 已在style设置color,此处删去*/
+}
+
+/* 下拉刷新--旋转进度条 */
+.mescroll-downwarp .downwarp-progress {
+ display: inline-block;
+ width: 32rpx;
+ height: 32rpx;
+ border-radius: 50%;
+ border: 2rpx solid gray;
+ border-bottom-color: transparent !important; /*已在style设置border-color,此处需加 !important*/
+ vertical-align: middle;
+}
+
+/* 旋转动画 */
+.mescroll-downwarp .mescroll-rotate {
+ animation: mescrollDownRotate 0.6s linear infinite;
+}
+
+@keyframes mescrollDownRotate {
+ 0% {
+ transform: rotate(0deg);
+ }
+
+ 100% {
+ transform: rotate(360deg);
+ }
+}
\ No newline at end of file
diff --git a/components/mescroll-uni/components/mescroll-down.vue b/components/mescroll-uni/components/mescroll-down.vue
new file mode 100644
index 0000000..9fd1567
--- /dev/null
+++ b/components/mescroll-uni/components/mescroll-down.vue
@@ -0,0 +1,47 @@
+
+
+
+
+
+ {{downText}}
+
+
+
+
+
+
+
diff --git a/components/mescroll-uni/components/mescroll-empty.vue b/components/mescroll-uni/components/mescroll-empty.vue
new file mode 100644
index 0000000..ff0c01c
--- /dev/null
+++ b/components/mescroll-uni/components/mescroll-empty.vue
@@ -0,0 +1,90 @@
+
+
+
+
+ {{ tip }}
+ {{ option.btnText }}
+
+
+
+
+
+
diff --git a/components/mescroll-uni/components/mescroll-top.vue b/components/mescroll-uni/components/mescroll-top.vue
new file mode 100644
index 0000000..5115fd8
--- /dev/null
+++ b/components/mescroll-uni/components/mescroll-top.vue
@@ -0,0 +1,83 @@
+
+
+
+
+
+
+
+
diff --git a/components/mescroll-uni/components/mescroll-up.css b/components/mescroll-uni/components/mescroll-up.css
new file mode 100644
index 0000000..cbf48cd
--- /dev/null
+++ b/components/mescroll-uni/components/mescroll-up.css
@@ -0,0 +1,47 @@
+/* 上拉加载区域 */
+.mescroll-upwarp {
+ box-sizing: border-box;
+ min-height: 110rpx;
+ padding: 30rpx 0;
+ text-align: center;
+ clear: both;
+}
+
+/*提示文本 */
+.mescroll-upwarp .upwarp-tip,
+.mescroll-upwarp .upwarp-nodata {
+ display: inline-block;
+ font-size: 28rpx;
+ vertical-align: middle;
+ /* color: gray; 已在style设置color,此处删去*/
+}
+
+.mescroll-upwarp .upwarp-tip {
+ margin-left: 16rpx;
+}
+
+/*旋转进度条 */
+.mescroll-upwarp .upwarp-progress {
+ display: inline-block;
+ width: 32rpx;
+ height: 32rpx;
+ border-radius: 50%;
+ border: 2rpx solid gray;
+ border-bottom-color: transparent !important; /*已在style设置border-color,此处需加 !important*/
+ vertical-align: middle;
+}
+
+/* 旋转动画 */
+.mescroll-upwarp .mescroll-rotate {
+ animation: mescrollUpRotate 0.6s linear infinite;
+}
+
+@keyframes mescrollUpRotate {
+ 0% {
+ transform: rotate(0deg);
+ }
+
+ 100% {
+ transform: rotate(360deg);
+ }
+}
\ No newline at end of file
diff --git a/components/mescroll-uni/components/mescroll-up.vue b/components/mescroll-uni/components/mescroll-up.vue
new file mode 100644
index 0000000..11c2e1f
--- /dev/null
+++ b/components/mescroll-uni/components/mescroll-up.vue
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+ {{ mOption.textLoading }}
+
+
+ {{ mOption.textNoMore }}
+
+
+
+
+
+
diff --git a/components/mescroll-uni/mescroll-body.css b/components/mescroll-uni/mescroll-body.css
new file mode 100644
index 0000000..1107710
--- /dev/null
+++ b/components/mescroll-uni/mescroll-body.css
@@ -0,0 +1,19 @@
+.mescroll-body {
+ position: relative; /* 下拉刷新区域相对自身定位 */
+ height: auto; /* 不可固定高度,否则overflow:hidden导致无法滑动; 同时使设置的最小高生效,实现列表不满屏仍可下拉*/
+ overflow: hidden; /* 当有元素写在mescroll-body标签前面时,可遮住下拉刷新区域 */
+ box-sizing: border-box; /* 避免设置padding出现双滚动条的问题 */
+}
+
+/* 使sticky生效: 父元素不能overflow:hidden或者overflow:auto属性 */
+.mescroll-body.mescorll-sticky{
+ overflow: unset !important
+}
+
+/* 适配 iPhoneX */
+@supports (bottom: constant(safe-area-inset-bottom)) or (bottom: env(safe-area-inset-bottom)) {
+ .mescroll-safearea {
+ padding-bottom: constant(safe-area-inset-bottom);
+ padding-bottom: env(safe-area-inset-bottom);
+ }
+}
\ No newline at end of file
diff --git a/components/mescroll-uni/mescroll-body.vue b/components/mescroll-uni/mescroll-body.vue
new file mode 100644
index 0000000..3bb4297
--- /dev/null
+++ b/components/mescroll-uni/mescroll-body.vue
@@ -0,0 +1,344 @@
+
+
+
+
+
+
+
+
+
+
+
+ {{downText}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ mescroll.optUp.textLoading }}
+
+
+ {{ mescroll.optUp.textNoMore }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/mescroll-uni/mescroll-mixins.js b/components/mescroll-uni/mescroll-mixins.js
new file mode 100644
index 0000000..a379739
--- /dev/null
+++ b/components/mescroll-uni/mescroll-mixins.js
@@ -0,0 +1,65 @@
+// mescroll-body 和 mescroll-uni 通用
+
+// import MescrollUni from "./mescroll-uni.vue";
+// import MescrollBody from "./mescroll-body.vue";
+
+const MescrollMixin = {
+ // components: { // 非H5端无法通过mixin注册组件, 只能在main.js中注册全局组件或具体界面中注册
+ // MescrollUni,
+ // MescrollBody
+ // },
+ data() {
+ return {
+ mescroll: null //mescroll实例对象
+ }
+ },
+ // 注册系统自带的下拉刷新 (配置down.native为true时生效, 还需在pages配置enablePullDownRefresh:true;详请参考mescroll-native的案例)
+ onPullDownRefresh(){
+ this.mescroll && this.mescroll.onPullDownRefresh();
+ },
+ // 注册列表滚动事件,用于判定在顶部可下拉刷新,在指定位置可显示隐藏回到顶部按钮 (此方法为页面生命周期,无法在子组件中触发, 仅在mescroll-body生效)
+ onPageScroll(e) {
+ this.mescroll && this.mescroll.onPageScroll(e);
+ },
+ // 注册滚动到底部的事件,用于上拉加载 (此方法为页面生命周期,无法在子组件中触发, 仅在mescroll-body生效)
+ onReachBottom() {
+ this.mescroll && this.mescroll.onReachBottom();
+ },
+ methods: {
+ // mescroll组件初始化的回调,可获取到mescroll对象
+ mescrollInit(mescroll) {
+ this.mescroll = mescroll;
+ this.mescrollInitByRef(); // 兼容字节跳动小程序
+ },
+ // 以ref的方式初始化mescroll对象 (兼容字节跳动小程序: http://www.mescroll.com/qa.html?v=20200107#q26)
+ mescrollInitByRef() {
+ if(!this.mescroll || !this.mescroll.resetUpScroll){
+ let mescrollRef = this.$refs.mescrollRef;
+ if(mescrollRef) this.mescroll = mescrollRef.mescroll
+ }
+ },
+ // 下拉刷新的回调 (mixin默认resetUpScroll)
+ downCallback() {
+ if(this.mescroll.optUp.use){
+ this.mescroll.resetUpScroll()
+ }else{
+ setTimeout(()=>{
+ this.mescroll.endSuccess();
+ }, 500)
+ }
+ },
+ // 上拉加载的回调
+ upCallback() {
+ // mixin默认延时500自动结束加载
+ setTimeout(()=>{
+ this.mescroll.endErr();
+ }, 500)
+ }
+ },
+ mounted() {
+ this.mescrollInitByRef(); // 兼容字节跳动小程序, 避免未设置@init或@init此时未能取到ref的情况
+ }
+
+}
+
+export default MescrollMixin;
diff --git a/components/mescroll-uni/mescroll-uni-option.js b/components/mescroll-uni/mescroll-uni-option.js
new file mode 100644
index 0000000..467ea28
--- /dev/null
+++ b/components/mescroll-uni/mescroll-uni-option.js
@@ -0,0 +1,33 @@
+// 全局配置
+// mescroll-body 和 mescroll-uni 通用
+const GlobalOption = {
+ down: {
+ // 其他down的配置参数也可以写,这里只展示了常用的配置:
+ textInOffset: '下拉刷新', // 下拉的距离在offset范围内的提示文本
+ textOutOffset: '释放更新', // 下拉的距离大于offset范围的提示文本
+ textLoading: '加载中 ...', // 加载中的提示文本
+ offset: 120, // 在列表顶部,下拉大于80px,松手即可触发下拉刷新的回调
+ native: false // 是否使用系统自带的下拉刷新; 默认false; 仅在mescroll-body生效 (值为true时,还需在pages配置enablePullDownRefresh:true;详请参考mescroll-native的案例)
+ },
+ up: {
+ // 其他up的配置参数也可以写,这里只展示了常用的配置:
+ textLoading: '加载中 ...', // 加载中的提示文本
+ textNoMore: '~ 没有更多数据了 ~', // 没有更多数据的提示文本
+ offset: 80, // 距底部多远时,触发upCallback
+ toTop: {
+ // 回到顶部按钮,需配置src才显示
+ src: "http://www.mescroll.com/img/mescroll-totop.png?v=1", // 图片路径 (建议放入static目录, 如 /static/img/mescroll-totop.png )
+ offset: 1000, // 列表滚动多少距离才显示回到顶部按钮,默认1000px
+ right: 20, // 到右边的距离, 默认20 (支持"20rpx", "20px", "20%"格式的值, 纯数字则默认单位rpx)
+ bottom: 120, // 到底部的距离, 默认120 (支持"20rpx", "20px", "20%"格式的值, 纯数字则默认单位rpx)
+ width: 72 // 回到顶部图标的宽度, 默认72 (支持"20rpx", "20px", "20%"格式的值, 纯数字则默认单位rpx)
+ },
+ empty: {
+ use: true, // 是否显示空布局
+ icon: "http://www.mescroll.com/img/mescroll-empty.png?v=1", // 图标路径 (建议放入static目录, 如 /static/img/mescroll-empty.png )
+ tip: '~ 暂无数据 ~' // 提示
+ }
+ }
+}
+
+export default GlobalOption
diff --git a/components/mescroll-uni/mescroll-uni.css b/components/mescroll-uni/mescroll-uni.css
new file mode 100644
index 0000000..39438cd
--- /dev/null
+++ b/components/mescroll-uni/mescroll-uni.css
@@ -0,0 +1,36 @@
+.mescroll-uni-warp{
+ height: 100%;
+}
+
+.mescroll-uni-content{
+ height: 100%;
+}
+
+.mescroll-uni {
+ position: relative;
+ width: 100%;
+ height: 100%;
+ min-height: 200rpx;
+ overflow-y: auto;
+ box-sizing: border-box; /* 避免设置padding出现双滚动条的问题 */
+}
+
+/* 定位的方式固定高度 */
+.mescroll-uni-fixed{
+ z-index: 1;
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ width: auto; /* 使right生效 */
+ height: auto; /* 使bottom生效 */
+}
+
+/* 适配 iPhoneX */
+@supports (bottom: constant(safe-area-inset-bottom)) or (bottom: env(safe-area-inset-bottom)) {
+ .mescroll-safearea {
+ padding-bottom: constant(safe-area-inset-bottom);
+ padding-bottom: env(safe-area-inset-bottom);
+ }
+}
diff --git a/components/mescroll-uni/mescroll-uni.js b/components/mescroll-uni/mescroll-uni.js
new file mode 100644
index 0000000..b8743c9
--- /dev/null
+++ b/components/mescroll-uni/mescroll-uni.js
@@ -0,0 +1,788 @@
+/* mescroll
+ * version 1.3.2
+ * 2020-08-05 wenju
+ * http://www.mescroll.com
+ */
+
+export default function MeScroll(options, isScrollBody) {
+ let me = this;
+ me.version = '1.3.2'; // mescroll版本号
+ me.options = options || {}; // 配置
+ me.isScrollBody = isScrollBody || false; // 滚动区域是否为原生页面滚动; 默认为scroll-view
+
+ me.isDownScrolling = false; // 是否在执行下拉刷新的回调
+ me.isUpScrolling = false; // 是否在执行上拉加载的回调
+ let hasDownCallback = me.options.down && me.options.down.callback; // 是否配置了down的callback
+
+ // 初始化下拉刷新
+ me.initDownScroll();
+ // 初始化上拉加载,则初始化
+ me.initUpScroll();
+
+ // 自动加载
+ setTimeout(function() { // 待主线程执行完毕再执行,避免new MeScroll未初始化,在回调获取不到mescroll的实例
+ // 自动触发下拉刷新 (只有配置了down的callback才自动触发下拉刷新)
+ if ((me.optDown.use || me.optDown.native) && me.optDown.auto && hasDownCallback) {
+ if (me.optDown.autoShowLoading) {
+ me.triggerDownScroll(); // 显示下拉进度,执行下拉回调
+ } else {
+ me.optDown.callback && me.optDown.callback(me); // 不显示下拉进度,直接执行下拉回调
+ }
+ }
+ // 自动触发上拉加载
+ if(!me.isUpAutoLoad){ // 部分小程序(头条小程序)emit是异步, 会导致isUpAutoLoad判断有误, 先延时确保先执行down的callback,再执行up的callback
+ setTimeout(function(){
+ me.optUp.use && me.optUp.auto && !me.isUpAutoLoad && me.triggerUpScroll();
+ },100)
+ }
+ }, 30); // 需让me.optDown.inited和me.optUp.inited先执行
+}
+
+/* 配置参数:下拉刷新 */
+MeScroll.prototype.extendDownScroll = function(optDown) {
+ // 下拉刷新的配置
+ MeScroll.extend(optDown, {
+ use: true, // 是否启用下拉刷新; 默认true
+ auto: true, // 是否在初始化完毕之后自动执行下拉刷新的回调; 默认true
+ native: false, // 是否使用系统自带的下拉刷新; 默认false; 仅mescroll-body生效 (值为true时,还需在pages配置enablePullDownRefresh:true;详请参考mescroll-native的案例)
+ autoShowLoading: false, // 如果设置auto=true(在初始化完毕之后自动执行下拉刷新的回调),那么是否显示下拉刷新的进度; 默认false
+ isLock: false, // 是否锁定下拉刷新,默认false;
+ offset: 120, // 在列表顶部,下拉大于80px,松手即可触发下拉刷新的回调
+ startTop: 100, // scroll-view快速滚动到顶部时,此时的scroll-top可能大于0, 此值用于控制最大的误差
+ inOffsetRate: 1, // 在列表顶部,下拉的距离小于offset时,改变下拉区域高度比例;值小于1且越接近0,高度变化越小,表现为越往下越难拉
+ outOffsetRate: 0.2, // 在列表顶部,下拉的距离大于offset时,改变下拉区域高度比例;值小于1且越接近0,高度变化越小,表现为越往下越难拉
+ bottomOffset: 20, // 当手指touchmove位置在距离body底部20px范围内的时候结束上拉刷新,避免Webview嵌套导致touchend事件不执行
+ minAngle: 45, // 向下滑动最少偏移的角度,取值区间 [0,90];默认45度,即向下滑动的角度大于45度则触发下拉;而小于45度,将不触发下拉,避免与左右滑动的轮播等组件冲突;
+ textInOffset: '下拉刷新', // 下拉的距离在offset范围内的提示文本
+ textOutOffset: '释放更新', // 下拉的距离大于offset范围的提示文本
+ textLoading: '加载中 ...', // 加载中的提示文本
+ bgColor: "transparent", // 背景颜色 (建议在pages.json中再设置一下backgroundColorTop)
+ textColor: "gray", // 文本颜色 (当bgColor配置了颜色,而textColor未配置时,则textColor会默认为白色)
+ inited: null, // 下拉刷新初始化完毕的回调
+ inOffset: null, // 下拉的距离进入offset范围内那一刻的回调
+ outOffset: null, // 下拉的距离大于offset那一刻的回调
+ onMoving: null, // 下拉过程中的回调,滑动过程一直在执行; rate下拉区域当前高度与指定距离的比值(inOffset: rate<1; outOffset: rate>=1); downHight当前下拉区域的高度
+ beforeLoading: null, // 准备触发下拉刷新的回调: 如果return true,将不触发showLoading和callback回调; 常用来完全自定义下拉刷新, 参考案例【淘宝 v6.8.0】
+ showLoading: null, // 显示下拉刷新进度的回调
+ afterLoading: null, // 显示下拉刷新进度的回调之后,马上要执行的代码 (如: 在wxs中使用)
+ beforeEndDownScroll: null, // 准备结束下拉的回调. 返回结束下拉的延时执行时间,默认0ms; 常用于结束下拉之前再显示另外一小段动画,才去隐藏下拉刷新的场景, 参考案例【dotJump】
+ endDownScroll: null, // 结束下拉刷新的回调
+ afterEndDownScroll: null, // 结束下拉刷新的回调,马上要执行的代码 (如: 在wxs中使用)
+ callback: function(mescroll) {
+ // 下拉刷新的回调;默认重置上拉加载列表为第一页
+ mescroll.resetUpScroll();
+ }
+ })
+}
+
+/* 配置参数:上拉加载 */
+MeScroll.prototype.extendUpScroll = function(optUp) {
+ // 上拉加载的配置
+ MeScroll.extend(optUp, {
+ use: true, // 是否启用上拉加载; 默认true
+ auto: true, // 是否在初始化完毕之后自动执行上拉加载的回调; 默认true
+ isLock: false, // 是否锁定上拉加载,默认false;
+ isBoth: true, // 上拉加载时,如果滑动到列表顶部是否可以同时触发下拉刷新;默认true,两者可同时触发;
+ callback: null, // 上拉加载的回调;function(page,mescroll){ }
+ page: {
+ num: 0, // 当前页码,默认0,回调之前会加1,即callback(page)会从1开始
+ size: 10, // 每页数据的数量
+ time: null // 加载第一页数据服务器返回的时间; 防止用户翻页时,后台新增了数据从而导致下一页数据重复;
+ },
+ noMoreSize: 1, // 如果列表已无数据,可设置列表的总数量要大于等于5条才显示无更多数据;避免列表数据过少(比如只有一条数据),显示无更多数据会不好看
+ offset: 80, // 距底部多远时,触发upCallback
+ textLoading: '加载中 ...', // 加载中的提示文本
+ textNoMore: '-- END --', // 没有更多数据的提示文本
+ bgColor: "transparent", // 背景颜色 (建议在pages.json中再设置一下backgroundColorBottom)
+ textColor: "gray", // 文本颜色 (当bgColor配置了颜色,而textColor未配置时,则textColor会默认为白色)
+ inited: null, // 初始化完毕的回调
+ showLoading: null, // 显示加载中的回调
+ showNoMore: null, // 显示无更多数据的回调
+ hideUpScroll: null, // 隐藏上拉加载的回调
+ errDistance: 60, // endErr的时候需往上滑动一段距离,使其往下滑动时再次触发onReachBottom,仅mescroll-body生效
+ toTop: {
+ // 回到顶部按钮,需配置src才显示
+ src: null, // 图片路径,默认null (绝对路径或网络图)
+ offset: 1000, // 列表滚动多少距离才显示回到顶部按钮,默认1000
+ duration: 300, // 回到顶部的动画时长,默认300ms (当值为0或300则使用系统自带回到顶部,更流畅; 其他值则通过step模拟,部分机型可能不够流畅,所以非特殊情况不建议修改此项)
+ btnClick: null, // 点击按钮的回调
+ onShow: null, // 是否显示的回调
+ zIndex: 9990, // fixed定位z-index值
+ left: null, // 到左边的距离, 默认null. 此项有值时,right不生效. (支持20, "20rpx", "20px", "20%"格式的值, 其中纯数字则默认单位rpx)
+ right: 20, // 到右边的距离, 默认20 (支持20, "20rpx", "20px", "20%"格式的值, 其中纯数字则默认单位rpx)
+ bottom: 120, // 到底部的距离, 默认120 (支持20, "20rpx", "20px", "20%"格式的值, 其中纯数字则默认单位rpx)
+ safearea: false, // bottom的偏移量是否加上底部安全区的距离, 默认false, 需要适配iPhoneX时使用 (具体的界面如果不配置此项,则取本vue的safearea值)
+ width: 72, // 回到顶部图标的宽度, 默认72 (支持20, "20rpx", "20px", "20%"格式的值, 其中纯数字则默认单位rpx)
+ radius: "50%" // 圆角, 默认"50%" (支持20, "20rpx", "20px", "20%"格式的值, 其中纯数字则默认单位rpx)
+ },
+ empty: {
+ use: true, // 是否显示空布局
+ icon: null, // 图标路径
+ tip: '~ 暂无相关数据 ~', // 提示
+ btnText: '', // 按钮
+ btnClick: null, // 点击按钮的回调
+ onShow: null, // 是否显示的回调
+ fixed: false, // 是否使用fixed定位,默认false; 配置fixed为true,以下的top和zIndex才生效 (transform会使fixed失效,最终会降级为absolute)
+ top: "100rpx", // fixed定位的top值 (完整的单位值,如 "10%"; "100rpx")
+ zIndex: 99 // fixed定位z-index值
+ },
+ onScroll: false // 是否监听滚动事件
+ })
+}
+
+/* 配置参数 */
+MeScroll.extend = function(userOption, defaultOption) {
+ if (!userOption) return defaultOption;
+ for (let key in defaultOption) {
+ if (userOption[key] == null) {
+ let def = defaultOption[key];
+ if (def != null && typeof def === 'object') {
+ userOption[key] = MeScroll.extend({}, def); // 深度匹配
+ } else {
+ userOption[key] = def;
+ }
+ } else if (typeof userOption[key] === 'object') {
+ MeScroll.extend(userOption[key], defaultOption[key]); // 深度匹配
+ }
+ }
+ return userOption;
+}
+
+/* 简单判断是否配置了颜色 (非透明,非白色) */
+MeScroll.prototype.hasColor = function(color) {
+ if(!color) return false;
+ let c = color.toLowerCase();
+ return c != "#fff" && c != "#ffffff" && c != "transparent" && c != "white"
+}
+
+/* -------初始化下拉刷新------- */
+MeScroll.prototype.initDownScroll = function() {
+ let me = this;
+ // 配置参数
+ me.optDown = me.options.down || {};
+ if(!me.optDown.textColor && me.hasColor(me.optDown.bgColor)) me.optDown.textColor = "#fff"; // 当bgColor有值且textColor未设置,则textColor默认白色
+ me.extendDownScroll(me.optDown);
+
+ // 如果是mescroll-body且配置了native,则禁止自定义的下拉刷新
+ if(me.isScrollBody && me.optDown.native){
+ me.optDown.use = false
+ }else{
+ me.optDown.native = false // 仅mescroll-body支持,mescroll-uni不支持
+ }
+
+ me.downHight = 0; // 下拉区域的高度
+
+ // 在页面中加入下拉布局
+ if (me.optDown.use && me.optDown.inited) {
+ // 初始化完毕的回调
+ setTimeout(function() { // 待主线程执行完毕再执行,避免new MeScroll未初始化,在回调获取不到mescroll的实例
+ me.optDown.inited(me);
+ }, 0)
+ }
+}
+
+/* 列表touchstart事件 */
+MeScroll.prototype.touchstartEvent = function(e) {
+ if (!this.optDown.use) return;
+
+ this.startPoint = this.getPoint(e); // 记录起点
+ this.startTop = this.getScrollTop(); // 记录此时的滚动条位置
+ this.startAngle = 0; // 初始角度
+ this.lastPoint = this.startPoint; // 重置上次move的点
+ this.maxTouchmoveY = this.getBodyHeight() - this.optDown.bottomOffset; // 手指触摸的最大范围(写在touchstart避免body获取高度为0的情况)
+ this.inTouchend = false; // 标记不是touchend
+}
+
+/* 列表touchmove事件 */
+MeScroll.prototype.touchmoveEvent = function(e) {
+ if (!this.optDown.use) return;
+ let me = this;
+
+ let scrollTop = me.getScrollTop(); // 当前滚动条的距离
+ let curPoint = me.getPoint(e); // 当前点
+
+ let moveY = curPoint.y - me.startPoint.y; // 和起点比,移动的距离,大于0向下拉,小于0向上拉
+
+ // 向下拉 && 在顶部
+ // mescroll-body,直接判定在顶部即可
+ // scroll-view在滚动时不会触发touchmove,当触顶/底/左/右时,才会触发touchmove
+ // scroll-view滚动到顶部时,scrollTop不一定为0,也有可能大于0; 在iOS的APP中scrollTop可能为负数,不一定和startTop相等
+ if (moveY > 0 && (
+ (me.isScrollBody && scrollTop <= 0)
+ ||
+ (!me.isScrollBody && (scrollTop <= 0 || (scrollTop <= me.optDown.startTop && scrollTop === me.startTop)) )
+ )) {
+ // 可下拉的条件
+ if (!me.inTouchend && !me.isDownScrolling && !me.optDown.isLock && (!me.isUpScrolling || (me.isUpScrolling &&
+ me.optUp.isBoth))) {
+
+ // 下拉的初始角度是否在配置的范围内
+ if(!me.startAngle) me.startAngle = me.getAngle(me.lastPoint, curPoint); // 两点之间的角度,区间 [0,90]
+ if (me.startAngle < me.optDown.minAngle) return; // 如果小于配置的角度,则不往下执行下拉刷新
+
+ // 如果手指的位置超过配置的距离,则提前结束下拉,避免Webview嵌套导致touchend无法触发
+ if (me.maxTouchmoveY > 0 && curPoint.y >= me.maxTouchmoveY) {
+ me.inTouchend = true; // 标记执行touchend
+ me.touchendEvent(); // 提前触发touchend
+ return;
+ }
+
+ me.preventDefault(e); // 阻止默认事件
+
+ let diff = curPoint.y - me.lastPoint.y; // 和上次比,移动的距离 (大于0向下,小于0向上)
+
+ // 下拉距离 < 指定距离
+ if (me.downHight < me.optDown.offset) {
+ if (me.movetype !== 1) {
+ me.movetype = 1; // 加入标记,保证只执行一次
+ me.optDown.inOffset && me.optDown.inOffset(me); // 进入指定距离范围内那一刻的回调,只执行一次
+ me.isMoveDown = true; // 标记下拉区域高度改变,在touchend重置回来
+ }
+ me.downHight += diff * me.optDown.inOffsetRate; // 越往下,高度变化越小
+
+ // 指定距离 <= 下拉距离
+ } else {
+ if (me.movetype !== 2) {
+ me.movetype = 2; // 加入标记,保证只执行一次
+ me.optDown.outOffset && me.optDown.outOffset(me); // 下拉超过指定距离那一刻的回调,只执行一次
+ me.isMoveDown = true; // 标记下拉区域高度改变,在touchend重置回来
+ }
+ if (diff > 0) { // 向下拉
+ me.downHight += diff * me.optDown.outOffsetRate; // 越往下,高度变化越小
+ } else { // 向上收
+ me.downHight += diff; // 向上收回高度,则向上滑多少收多少高度
+ }
+ }
+
+ me.downHight = Math.round(me.downHight) // 取整
+ let rate = me.downHight / me.optDown.offset; // 下拉区域当前高度与指定距离的比值
+ me.optDown.onMoving && me.optDown.onMoving(me, rate, me.downHight); // 下拉过程中的回调,一直在执行
+ }
+ }
+
+ me.lastPoint = curPoint; // 记录本次移动的点
+}
+
+/* 列表touchend事件 */
+MeScroll.prototype.touchendEvent = function(e) {
+ if (!this.optDown.use) return;
+ // 如果下拉区域高度已改变,则需重置回来
+ if (this.isMoveDown) {
+ if (this.downHight >= this.optDown.offset) {
+ // 符合触发刷新的条件
+ this.triggerDownScroll();
+ } else {
+ // 不符合的话 则重置
+ this.downHight = 0;
+ this.endDownScrollCall(this);
+ }
+ this.movetype = 0;
+ this.isMoveDown = false;
+ } else if (!this.isScrollBody && this.getScrollTop() === this.startTop) { // scroll-view到顶/左/右/底的滑动事件
+ let isScrollUp = this.getPoint(e).y - this.startPoint.y < 0; // 和起点比,移动的距离,大于0向下拉,小于0向上拉
+ // 上滑
+ if (isScrollUp) {
+ // 需检查滑动的角度
+ let angle = this.getAngle(this.getPoint(e), this.startPoint); // 两点之间的角度,区间 [0,90]
+ if (angle > 80) {
+ // 检查并触发上拉
+ this.triggerUpScroll(true);
+ }
+ }
+ }
+}
+
+/* 根据点击滑动事件获取第一个手指的坐标 */
+MeScroll.prototype.getPoint = function(e) {
+ if (!e) {
+ return {
+ x: 0,
+ y: 0
+ }
+ }
+ if (e.touches && e.touches[0]) {
+ return {
+ x: e.touches[0].pageX,
+ y: e.touches[0].pageY
+ }
+ } else if (e.changedTouches && e.changedTouches[0]) {
+ return {
+ x: e.changedTouches[0].pageX,
+ y: e.changedTouches[0].pageY
+ }
+ } else {
+ return {
+ x: e.clientX,
+ y: e.clientY
+ }
+ }
+}
+
+/* 计算两点之间的角度: 区间 [0,90]*/
+MeScroll.prototype.getAngle = function(p1, p2) {
+ let x = Math.abs(p1.x - p2.x);
+ let y = Math.abs(p1.y - p2.y);
+ let z = Math.sqrt(x * x + y * y);
+ let angle = 0;
+ if (z !== 0) {
+ angle = Math.asin(y / z) / Math.PI * 180;
+ }
+ return angle
+}
+
+/* 触发下拉刷新 */
+MeScroll.prototype.triggerDownScroll = function() {
+ if (this.optDown.beforeLoading && this.optDown.beforeLoading(this)) {
+ //return true则处于完全自定义状态
+ } else {
+ this.showDownScroll(); // 下拉刷新中...
+ !this.optDown.native && this.optDown.callback && this.optDown.callback(this); // 执行回调,联网加载数据
+ }
+}
+
+/* 显示下拉进度布局 */
+MeScroll.prototype.showDownScroll = function() {
+ this.isDownScrolling = true; // 标记下拉中
+ if (this.optDown.native) {
+ uni.startPullDownRefresh(); // 系统自带的下拉刷新
+ this.showDownLoadingCall(0); // 仍触发showLoading,因为上拉加载用到
+ } else{
+ this.downHight = this.optDown.offset; // 更新下拉区域高度
+ this.showDownLoadingCall(this.downHight); // 下拉刷新中...
+ }
+}
+
+MeScroll.prototype.showDownLoadingCall = function(downHight) {
+ this.optDown.showLoading && this.optDown.showLoading(this, downHight); // 下拉刷新中...
+ this.optDown.afterLoading && this.optDown.afterLoading(this, downHight); // 下拉刷新中...触发之后马上要执行的代码
+}
+
+/* 显示系统自带的下拉刷新时需要处理的业务 */
+MeScroll.prototype.onPullDownRefresh = function() {
+ this.isDownScrolling = true; // 标记下拉中
+ this.showDownLoadingCall(0); // 仍触发showLoading,因为上拉加载用到
+ this.optDown.callback && this.optDown.callback(this); // 执行回调,联网加载数据
+}
+
+/* 结束下拉刷新 */
+MeScroll.prototype.endDownScroll = function() {
+ if (this.optDown.native) { // 结束原生下拉刷新
+ this.isDownScrolling = false;
+ this.endDownScrollCall(this);
+ uni.stopPullDownRefresh();
+ return
+ }
+ let me = this;
+ // 结束下拉刷新的方法
+ let endScroll = function() {
+ me.downHight = 0;
+ me.isDownScrolling = false;
+ me.endDownScrollCall(me);
+ if(!me.isScrollBody){
+ me.setScrollHeight(0) // scroll-view重置滚动区域,使数据不满屏时仍可检查触发翻页
+ me.scrollTo(0,0) // scroll-view需重置滚动条到顶部,避免startTop大于0时,对下拉刷新的影响
+ }
+ }
+ // 结束下拉刷新时的回调
+ let delay = 0;
+ if (me.optDown.beforeEndDownScroll) delay = me.optDown.beforeEndDownScroll(me); // 结束下拉刷新的延时,单位ms
+ if (typeof delay === 'number' && delay > 0) {
+ setTimeout(endScroll, delay);
+ } else {
+ endScroll();
+ }
+}
+
+MeScroll.prototype.endDownScrollCall = function() {
+ this.optDown.endDownScroll && this.optDown.endDownScroll(this);
+ this.optDown.afterEndDownScroll && this.optDown.afterEndDownScroll(this);
+}
+
+/* 锁定下拉刷新:isLock=ture,null锁定;isLock=false解锁 */
+MeScroll.prototype.lockDownScroll = function(isLock) {
+ if (isLock == null) isLock = true;
+ this.optDown.isLock = isLock;
+}
+
+/* 锁定上拉加载:isLock=ture,null锁定;isLock=false解锁 */
+MeScroll.prototype.lockUpScroll = function(isLock) {
+ if (isLock == null) isLock = true;
+ this.optUp.isLock = isLock;
+}
+
+/* -------初始化上拉加载------- */
+MeScroll.prototype.initUpScroll = function() {
+ let me = this;
+ // 配置参数
+ me.optUp = me.options.up || {use: false}
+ if(!me.optUp.textColor && me.hasColor(me.optUp.bgColor)) me.optUp.textColor = "#fff"; // 当bgColor有值且textColor未设置,则textColor默认白色
+ me.extendUpScroll(me.optUp);
+
+ if (me.optUp.use === false) return; // 配置不使用上拉加载时,则不初始化上拉布局
+ me.optUp.hasNext = true; // 如果使用上拉,则默认有下一页
+ me.startNum = me.optUp.page.num + 1; // 记录page开始的页码
+
+ // 初始化完毕的回调
+ if (me.optUp.inited) {
+ setTimeout(function() { // 待主线程执行完毕再执行,避免new MeScroll未初始化,在回调获取不到mescroll的实例
+ me.optUp.inited(me);
+ }, 0)
+ }
+}
+
+/*滚动到底部的事件 (仅mescroll-body生效)*/
+MeScroll.prototype.onReachBottom = function() {
+ if (this.isScrollBody && !this.isUpScrolling) { // 只能支持下拉刷新的时候同时可以触发上拉加载,否则滚动到底部就需要上滑一点才能触发onReachBottom
+ if (!this.optUp.isLock && this.optUp.hasNext) {
+ this.triggerUpScroll();
+ }
+ }
+}
+
+/*列表滚动事件 (仅mescroll-body生效)*/
+MeScroll.prototype.onPageScroll = function(e) {
+ if (!this.isScrollBody) return;
+
+ // 更新滚动条的位置 (主要用于判断下拉刷新时,滚动条是否在顶部)
+ this.setScrollTop(e.scrollTop);
+
+ // 顶部按钮的显示隐藏
+ if (e.scrollTop >= this.optUp.toTop.offset) {
+ this.showTopBtn();
+ } else {
+ this.hideTopBtn();
+ }
+}
+
+/*列表滚动事件*/
+MeScroll.prototype.scroll = function(e, onScroll) {
+ // 更新滚动条的位置
+ this.setScrollTop(e.scrollTop);
+ // 更新滚动内容高度
+ this.setScrollHeight(e.scrollHeight);
+
+ // 向上滑还是向下滑动
+ if (this.preScrollY == null) this.preScrollY = 0;
+ this.isScrollUp = e.scrollTop - this.preScrollY > 0;
+ this.preScrollY = e.scrollTop;
+
+ // 上滑 && 检查并触发上拉
+ this.isScrollUp && this.triggerUpScroll(true);
+
+ // 顶部按钮的显示隐藏
+ if (e.scrollTop >= this.optUp.toTop.offset) {
+ this.showTopBtn();
+ } else {
+ this.hideTopBtn();
+ }
+
+ // 滑动监听
+ this.optUp.onScroll && onScroll && onScroll()
+}
+
+/* 触发上拉加载 */
+MeScroll.prototype.triggerUpScroll = function(isCheck) {
+ if (!this.isUpScrolling && this.optUp.use && this.optUp.callback) {
+ // 是否校验在底部; 默认不校验
+ if (isCheck === true) {
+ let canUp = false;
+ // 还有下一页 && 没有锁定 && 不在下拉中
+ if (this.optUp.hasNext && !this.optUp.isLock && !this.isDownScrolling) {
+ if (this.getScrollBottom() <= this.optUp.offset) { // 到底部
+ canUp = true; // 标记可上拉
+ }
+ }
+ if (canUp === false) return;
+ }
+ this.showUpScroll(); // 上拉加载中...
+ this.optUp.page.num++; // 预先加一页,如果失败则减回
+ this.isUpAutoLoad = true; // 标记上拉已经自动执行过,避免初始化时多次触发上拉回调
+ this.num = this.optUp.page.num; // 把最新的页数赋值在mescroll上,避免对page的影响
+ this.size = this.optUp.page.size; // 把最新的页码赋值在mescroll上,避免对page的影响
+ this.time = this.optUp.page.time; // 把最新的页码赋值在mescroll上,避免对page的影响
+ this.optUp.callback(this); // 执行回调,联网加载数据
+ }
+}
+
+/* 显示上拉加载中 */
+MeScroll.prototype.showUpScroll = function() {
+ this.isUpScrolling = true; // 标记上拉加载中
+ this.optUp.showLoading && this.optUp.showLoading(this); // 回调
+}
+
+/* 显示上拉无更多数据 */
+MeScroll.prototype.showNoMore = function() {
+ this.optUp.hasNext = false; // 标记无更多数据
+ this.optUp.showNoMore && this.optUp.showNoMore(this); // 回调
+}
+
+/* 隐藏上拉区域**/
+MeScroll.prototype.hideUpScroll = function() {
+ this.optUp.hideUpScroll && this.optUp.hideUpScroll(this); // 回调
+}
+
+/* 结束上拉加载 */
+MeScroll.prototype.endUpScroll = function(isShowNoMore) {
+ if (isShowNoMore != null) { // isShowNoMore=null,不处理下拉状态,下拉刷新的时候调用
+ if (isShowNoMore) {
+ this.showNoMore(); // isShowNoMore=true,显示无更多数据
+ } else {
+ this.hideUpScroll(); // isShowNoMore=false,隐藏上拉加载
+ }
+ }
+ this.isUpScrolling = false; // 标记结束上拉加载
+}
+
+/* 重置上拉加载列表为第一页
+ *isShowLoading 是否显示进度布局;
+ * 1.默认null,不传参,则显示上拉加载的进度布局
+ * 2.传参true, 则显示下拉刷新的进度布局
+ * 3.传参false,则不显示上拉和下拉的进度 (常用于静默更新列表数据)
+ */
+MeScroll.prototype.resetUpScroll = function(isShowLoading) {
+ if (this.optUp && this.optUp.use) {
+ let page = this.optUp.page;
+ this.prePageNum = page.num; // 缓存重置前的页码,加载失败可退回
+ this.prePageTime = page.time; // 缓存重置前的时间,加载失败可退回
+ page.num = this.startNum; // 重置为第一页
+ page.time = null; // 重置时间为空
+ if (!this.isDownScrolling && isShowLoading !== false) { // 如果不是下拉刷新触发的resetUpScroll并且不配置列表静默更新,则显示进度;
+ if (isShowLoading == null) {
+ this.removeEmpty(); // 移除空布局
+ this.showUpScroll(); // 不传参,默认显示上拉加载的进度布局
+ } else {
+ this.showDownScroll(); // 传true,显示下拉刷新的进度布局,不清空列表
+ }
+ }
+ this.isUpAutoLoad = true; // 标记上拉已经自动执行过,避免初始化时多次触发上拉回调
+ this.num = page.num; // 把最新的页数赋值在mescroll上,避免对page的影响
+ this.size = page.size; // 把最新的页码赋值在mescroll上,避免对page的影响
+ this.time = page.time; // 把最新的页码赋值在mescroll上,避免对page的影响
+ this.optUp.callback && this.optUp.callback(this); // 执行上拉回调
+ }
+}
+
+/* 设置page.num的值 */
+MeScroll.prototype.setPageNum = function(num) {
+ this.optUp.page.num = num - 1;
+}
+
+/* 设置page.size的值 */
+MeScroll.prototype.setPageSize = function(size) {
+ this.optUp.page.size = size;
+}
+
+/* 联网回调成功,结束下拉刷新和上拉加载
+ * dataSize: 当前页的数据量(必传)
+ * totalPage: 总页数(必传)
+ * systime: 服务器时间 (可空)
+ */
+MeScroll.prototype.endByPage = function(dataSize, totalPage, systime) {
+ let hasNext;
+ if (this.optUp.use && totalPage != null) hasNext = this.optUp.page.num < totalPage; // 是否还有下一页
+ this.endSuccess(dataSize, hasNext, systime);
+}
+
+/* 联网回调成功,结束下拉刷新和上拉加载
+ * dataSize: 当前页的数据量(必传)
+ * totalSize: 列表所有数据总数量(必传)
+ * systime: 服务器时间 (可空)
+ */
+MeScroll.prototype.endBySize = function(dataSize, totalSize, systime) {
+ let hasNext;
+ if (this.optUp.use && totalSize != null) {
+ let loadSize = (this.optUp.page.num - 1) * this.optUp.page.size + dataSize; // 已加载的数据总数
+ hasNext = loadSize < totalSize; // 是否还有下一页
+ }
+ this.endSuccess(dataSize, hasNext, systime);
+}
+
+/* 联网回调成功,结束下拉刷新和上拉加载
+ * dataSize: 当前页的数据个数(不是所有页的数据总和),用于上拉加载判断是否还有下一页.如果不传,则会判断还有下一页
+ * hasNext: 是否还有下一页,布尔类型;用来解决这个小问题:比如列表共有20条数据,每页加载10条,共2页.如果只根据dataSize判断,则需翻到第三页才会知道无更多数据,如果传了hasNext,则翻到第二页即可显示无更多数据.
+ * systime: 服务器时间(可空);用来解决这个小问题:当准备翻下一页时,数据库新增了几条记录,此时翻下一页,前面的几条数据会和上一页的重复;这里传入了systime,那么upCallback的page.time就会有值,把page.time传给服务器,让后台过滤新加入的那几条记录
+ */
+MeScroll.prototype.endSuccess = function(dataSize, hasNext, systime) {
+ let me = this;
+ // 结束下拉刷新
+ if (me.isDownScrolling) me.endDownScroll();
+
+ // 结束上拉加载
+ if (me.optUp.use) {
+ let isShowNoMore; // 是否已无更多数据
+ if (dataSize != null) {
+ let pageNum = me.optUp.page.num; // 当前页码
+ let pageSize = me.optUp.page.size; // 每页长度
+ // 如果是第一页
+ if (pageNum === 1) {
+ if (systime) me.optUp.page.time = systime; // 设置加载列表数据第一页的时间
+ }
+ if (dataSize < pageSize || hasNext === false) {
+ // 返回的数据不满一页时,则说明已无更多数据
+ me.optUp.hasNext = false;
+ if (dataSize === 0 && pageNum === 1) {
+ // 如果第一页无任何数据且配置了空布局
+ isShowNoMore = false;
+ me.showEmpty();
+ } else {
+ // 总列表数少于配置的数量,则不显示无更多数据
+ let allDataSize = (pageNum - 1) * pageSize + dataSize;
+ if (allDataSize < me.optUp.noMoreSize) {
+ isShowNoMore = false;
+ } else {
+ isShowNoMore = true;
+ }
+ me.removeEmpty(); // 移除空布局
+ }
+ } else {
+ // 还有下一页
+ isShowNoMore = false;
+ me.optUp.hasNext = true;
+ me.removeEmpty(); // 移除空布局
+ }
+ }
+
+ // 隐藏上拉
+ me.endUpScroll(isShowNoMore);
+ }
+}
+
+/* 回调失败,结束下拉刷新和上拉加载 */
+MeScroll.prototype.endErr = function(errDistance) {
+ // 结束下拉,回调失败重置回原来的页码和时间
+ if (this.isDownScrolling) {
+ let page = this.optUp.page;
+ if (page && this.prePageNum) {
+ page.num = this.prePageNum;
+ page.time = this.prePageTime;
+ }
+ this.endDownScroll();
+ }
+ // 结束上拉,回调失败重置回原来的页码
+ if (this.isUpScrolling) {
+ this.optUp.page.num--;
+ this.endUpScroll(false);
+ // 如果是mescroll-body,则需往回滚一定距离
+ if(this.isScrollBody && errDistance !== 0){ // 不处理0
+ if(!errDistance) errDistance = this.optUp.errDistance; // 不传,则取默认
+ this.scrollTo(this.getScrollTop() - errDistance, 0) // 往上回滚的距离
+ }
+ }
+}
+
+/* 显示空布局 */
+MeScroll.prototype.showEmpty = function() {
+ this.optUp.empty.use && this.optUp.empty.onShow && this.optUp.empty.onShow(true)
+}
+
+/* 移除空布局 */
+MeScroll.prototype.removeEmpty = function() {
+ this.optUp.empty.use && this.optUp.empty.onShow && this.optUp.empty.onShow(false)
+}
+
+/* 显示回到顶部的按钮 */
+MeScroll.prototype.showTopBtn = function() {
+ if (!this.topBtnShow) {
+ this.topBtnShow = true;
+ this.optUp.toTop.onShow && this.optUp.toTop.onShow(true);
+ }
+}
+
+/* 隐藏回到顶部的按钮 */
+MeScroll.prototype.hideTopBtn = function() {
+ if (this.topBtnShow) {
+ this.topBtnShow = false;
+ this.optUp.toTop.onShow && this.optUp.toTop.onShow(false);
+ }
+}
+
+/* 获取滚动条的位置 */
+MeScroll.prototype.getScrollTop = function() {
+ return this.scrollTop || 0
+}
+
+/* 记录滚动条的位置 */
+MeScroll.prototype.setScrollTop = function(y) {
+ this.scrollTop = y;
+}
+
+/* 滚动到指定位置 */
+MeScroll.prototype.scrollTo = function(y, t) {
+ this.myScrollTo && this.myScrollTo(y, t) // scrollview需自定义回到顶部方法
+}
+
+/* 自定义scrollTo */
+MeScroll.prototype.resetScrollTo = function(myScrollTo) {
+ this.myScrollTo = myScrollTo
+}
+
+/* 滚动条到底部的距离 */
+MeScroll.prototype.getScrollBottom = function() {
+ return this.getScrollHeight() - this.getClientHeight() - this.getScrollTop()
+}
+
+/* 计步器
+ star: 开始值
+ end: 结束值
+ callback(step,timer): 回调step值,计步器timer,可自行通过window.clearInterval(timer)结束计步器;
+ t: 计步时长,传0则直接回调end值;不传则默认300ms
+ rate: 周期;不传则默认30ms计步一次
+ * */
+MeScroll.prototype.getStep = function(star, end, callback, t, rate) {
+ let diff = end - star; // 差值
+ if (t === 0 || diff === 0) {
+ callback && callback(end);
+ return;
+ }
+ t = t || 300; // 时长 300ms
+ rate = rate || 30; // 周期 30ms
+ let count = t / rate; // 次数
+ let step = diff / count; // 步长
+ let i = 0; // 计数
+ let timer = setInterval(function() {
+ if (i < count - 1) {
+ star += step;
+ callback && callback(star, timer);
+ i++;
+ } else {
+ callback && callback(end, timer); // 最后一次直接设置end,避免计算误差
+ clearInterval(timer);
+ }
+ }, rate);
+}
+
+/* 滚动容器的高度 */
+MeScroll.prototype.getClientHeight = function(isReal) {
+ let h = this.clientHeight || 0
+ if (h === 0 && isReal !== true) { // 未获取到容器的高度,可临时取body的高度 (可能会有误差)
+ h = this.getBodyHeight()
+ }
+ return h
+}
+MeScroll.prototype.setClientHeight = function(h) {
+ this.clientHeight = h;
+}
+
+/* 滚动内容的高度 */
+MeScroll.prototype.getScrollHeight = function() {
+ return this.scrollHeight || 0;
+}
+MeScroll.prototype.setScrollHeight = function(h) {
+ this.scrollHeight = h;
+}
+
+/* body的高度 */
+MeScroll.prototype.getBodyHeight = function() {
+ return this.bodyHeight || 0;
+}
+MeScroll.prototype.setBodyHeight = function(h) {
+ this.bodyHeight = h;
+}
+
+/* 阻止浏览器默认滚动事件 */
+MeScroll.prototype.preventDefault = function(e) {
+ // 小程序不支持e.preventDefault, 已在wxs中禁止
+ // app的bounce只能通过配置pages.json的style.app-plus.bounce为"none"来禁止, 或使用renderjs禁止
+ // cancelable:是否可以被禁用; defaultPrevented:是否已经被禁用
+ if (e && e.cancelable && !e.defaultPrevented) e.preventDefault()
+}
\ No newline at end of file
diff --git a/components/mescroll-uni/mescroll-uni.vue b/components/mescroll-uni/mescroll-uni.vue
new file mode 100644
index 0000000..7dff375
--- /dev/null
+++ b/components/mescroll-uni/mescroll-uni.vue
@@ -0,0 +1,420 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{downText}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ mescroll.optUp.textLoading }}
+
+
+ {{ mescroll.optUp.textNoMore }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/mescroll-uni/mixins/mescroll-comp.js b/components/mescroll-uni/mixins/mescroll-comp.js
new file mode 100644
index 0000000..6aea07b
--- /dev/null
+++ b/components/mescroll-uni/mixins/mescroll-comp.js
@@ -0,0 +1,50 @@
+/**
+ * mescroll-body写在子组件时,需通过mescroll的mixins补充子组件缺少的生命周期:
+ * 当一个页面只有一个mescroll-body写在子组件时, 则使用mescroll-comp.js (参考 mescroll-comp 案例)
+ * 当一个页面有多个mescroll-body写在子组件时, 则使用mescroll-more.js (参考 mescroll-more 案例)
+ */
+const MescrollCompMixin = {
+ // 因为子组件无onPageScroll和onReachBottom的页面生命周期,需在页面传递进到子组件 (一级)
+ onPageScroll(e) {
+ this.handlePageScroll(e)
+ },
+ onReachBottom() {
+ this.handleReachBottom()
+ },
+ // 当down的native: true时, 还需传递此方法进到子组件
+ onPullDownRefresh(){
+ this.handlePullDownRefresh()
+ },
+ // mescroll-body写在子子子...组件的情况 (多级)
+ data() {
+ return {
+ mescroll: {
+ onPageScroll: e=>{
+ this.handlePageScroll(e)
+ },
+ onReachBottom: ()=>{
+ this.handleReachBottom()
+ },
+ onPullDownRefresh: ()=>{
+ this.handlePullDownRefresh()
+ }
+ }
+ }
+ },
+ methods:{
+ handlePageScroll(e){
+ let item = this.$refs["mescrollItem"];
+ if(item && item.mescroll) item.mescroll.onPageScroll(e);
+ },
+ handleReachBottom(){
+ let item = this.$refs["mescrollItem"];
+ if(item && item.mescroll) item.mescroll.onReachBottom();
+ },
+ handlePullDownRefresh(){
+ let item = this.$refs["mescrollItem"];
+ if(item && item.mescroll) item.mescroll.onPullDownRefresh();
+ }
+ }
+}
+
+export default MescrollCompMixin;
diff --git a/components/mescroll-uni/mixins/mescroll-more-item.js b/components/mescroll-uni/mixins/mescroll-more-item.js
new file mode 100644
index 0000000..ce89fa2
--- /dev/null
+++ b/components/mescroll-uni/mixins/mescroll-more-item.js
@@ -0,0 +1,51 @@
+/**
+ * mescroll-more-item的mixins, 仅在多个 mescroll-body 写在子组件时使用 (参考 mescroll-more 案例)
+ */
+const MescrollMoreItemMixin = {
+ // 支付宝小程序不支持props的mixin,需写在具体的页面中
+ // #ifndef MP-ALIPAY || MP-DINGTALK
+ props:{
+ i: Number, // 每个tab页的专属下标
+ index: { // 当前tab的下标
+ type: Number,
+ default(){
+ return 0
+ }
+ }
+ },
+ // #endif
+ data() {
+ return {
+ downOption:{
+ auto:false // 不自动加载
+ },
+ upOption:{
+ auto:false // 不自动加载
+ },
+ isInit: false // 当前tab是否已初始化
+ }
+ },
+ watch:{
+ // 监听下标的变化
+ index(val){
+ if (this.i === val && !this.isInit) {
+ this.isInit = true; // 标记为true
+ this.mescroll && this.mescroll.triggerDownScroll();
+ }
+ }
+ },
+ methods: {
+ // mescroll组件初始化的回调,可获取到mescroll对象 (覆盖mescroll-mixins.js的mescrollInit, 为了标记isInit)
+ mescrollInit(mescroll) {
+ this.mescroll = mescroll;
+ this.mescrollInitByRef && this.mescrollInitByRef(); // 兼容字节跳动小程序
+ // 自动加载当前tab的数据
+ if(this.i === this.index){
+ this.isInit = true; // 标记为true
+ this.mescroll.triggerDownScroll();
+ }
+ },
+ }
+}
+
+export default MescrollMoreItemMixin;
diff --git a/components/mescroll-uni/mixins/mescroll-more.js b/components/mescroll-uni/mixins/mescroll-more.js
new file mode 100644
index 0000000..142aa75
--- /dev/null
+++ b/components/mescroll-uni/mixins/mescroll-more.js
@@ -0,0 +1,56 @@
+/**
+ * mescroll-body写在子组件时,需通过mescroll的mixins补充子组件缺少的生命周期:
+ * 当一个页面只有一个mescroll-body写在子组件时, 则使用mescroll-comp.js (参考 mescroll-comp 案例)
+ * 当一个页面有多个mescroll-body写在子组件时, 则使用mescroll-more.js (参考 mescroll-more 案例)
+ */
+const MescrollMoreMixin = {
+ data() {
+ return {
+ tabIndex: 0 // 当前tab下标
+ }
+ },
+ // 因为子组件无onPageScroll和onReachBottom的页面生命周期,需在页面传递进到子组件
+ onPageScroll(e) {
+ let mescroll = this.getMescroll(this.tabIndex);
+ mescroll && mescroll.onPageScroll(e);
+ },
+ onReachBottom() {
+ let mescroll = this.getMescroll(this.tabIndex);
+ mescroll && mescroll.onReachBottom();
+ },
+ // 当down的native: true时, 还需传递此方法进到子组件
+ onPullDownRefresh(){
+ let mescroll = this.getMescroll(this.tabIndex);
+ mescroll && mescroll.onPullDownRefresh();
+ },
+ methods:{
+ // 根据下标获取对应子组件的mescroll
+ getMescroll(i){
+ if(!this.mescrollItems) this.mescrollItems = [];
+ if(!this.mescrollItems[i]) {
+ // v-for中的refs
+ let vForItem = this.$refs["mescrollItem"];
+ if(vForItem){
+ this.mescrollItems[i] = vForItem[i]
+ }else{
+ // 普通的refs,不可重复
+ this.mescrollItems[i] = this.$refs["mescrollItem"+i];
+ }
+ }
+ let item = this.mescrollItems[i]
+ return item ? item.mescroll : null
+ },
+ // 切换tab,恢复滚动条位置
+ tabChange(i){
+ let mescroll = this.getMescroll(i);
+ if(mescroll){
+ // 延时(比$nextTick靠谱一些),确保元素已渲染
+ setTimeout(()=>{
+ mescroll.scrollTo(mescroll.getScrollTop(),0)
+ },30)
+ }
+ }
+ }
+}
+
+export default MescrollMoreMixin;
diff --git a/components/mescroll-uni/wxs/mixins.js b/components/mescroll-uni/wxs/mixins.js
new file mode 100644
index 0000000..d1f4267
--- /dev/null
+++ b/components/mescroll-uni/wxs/mixins.js
@@ -0,0 +1,102 @@
+// 定义在wxs (含renderjs) 逻辑层的数据和方法, 与视图层相互通信
+const WxsMixin = {
+ data() {
+ return {
+ // 传入wxs视图层的数据 (响应式)
+ wxsProp: {
+ optDown:{}, // 下拉刷新的配置
+ scrollTop:0, // 滚动条的距离
+ bodyHeight:0, // body的高度
+ isDownScrolling:false, // 是否正在下拉刷新中
+ isUpScrolling:false, // 是否正在上拉加载中
+ isScrollBody:true, // 是否为mescroll-body滚动
+ isUpBoth:true, // 上拉加载时,是否同时可以下拉刷新
+ t: 0 // 数据更新的标记 (只有数据更新了,才会触发wxs的Observer)
+ },
+
+ // 标记调用wxs视图层的方法
+ callProp: {
+ callType: '', // 方法名
+ t: 0 // 数据更新的标记 (只有数据更新了,才会触发wxs的Observer)
+ },
+
+ // 不用wxs的平台使用此处的wxsBiz对象,抹平wxs的写法 (微信小程序和APP使用的wxsBiz对象是./wxs/wxs.wxs)
+ // #ifndef MP-WEIXIN || MP-QQ || APP-PLUS || H5
+ wxsBiz: {
+ //注册列表touchstart事件,用于下拉刷新
+ touchstartEvent: e=> {
+ this.mescroll.touchstartEvent(e);
+ },
+ //注册列表touchmove事件,用于下拉刷新
+ touchmoveEvent: e=> {
+ this.mescroll.touchmoveEvent(e);
+ },
+ //注册列表touchend事件,用于下拉刷新
+ touchendEvent: e=> {
+ this.mescroll.touchendEvent(e);
+ },
+ propObserver(){}, // 抹平wxs的写法
+ callObserver(){} // 抹平wxs的写法
+ },
+ // #endif
+
+ // 不用renderjs的平台使用此处的renderBiz对象,抹平renderjs的写法 (app 和 h5 使用的renderBiz对象是./wxs/renderjs.js)
+ // #ifndef APP-PLUS || H5
+ renderBiz: {
+ propObserver(){} // 抹平renderjs的写法
+ }
+ // #endif
+ }
+ },
+ methods: {
+ // wxs视图层调用逻辑层的回调
+ wxsCall(msg){
+ if(msg.type === 'setWxsProp'){
+ // 更新wxsProp数据 (值改变才触发更新)
+ this.wxsProp = {
+ optDown: this.mescroll.optDown,
+ scrollTop: this.mescroll.getScrollTop(),
+ bodyHeight: this.mescroll.getBodyHeight(),
+ isDownScrolling: this.mescroll.isDownScrolling,
+ isUpScrolling: this.mescroll.isUpScrolling,
+ isUpBoth: this.mescroll.optUp.isBoth,
+ isScrollBody:this.mescroll.isScrollBody,
+ t: Date.now()
+ }
+ }else if(msg.type === 'setLoadType'){
+ // 设置inOffset,outOffset的状态
+ this.downLoadType = msg.downLoadType
+ }else if(msg.type === 'triggerDownScroll'){
+ // 主动触发下拉刷新
+ this.mescroll.triggerDownScroll();
+ }else if(msg.type === 'endDownScroll'){
+ // 结束下拉刷新
+ this.mescroll.endDownScroll();
+ }else if(msg.type === 'triggerUpScroll'){
+ // 主动触发上拉加载
+ this.mescroll.triggerUpScroll(true);
+ }
+ }
+ },
+ mounted() {
+ // #ifdef MP-WEIXIN || MP-QQ || APP-PLUS || H5
+ // 配置主动触发wxs显示加载进度的回调
+ this.mescroll.optDown.afterLoading = ()=>{
+ this.callProp = {callType: "showLoading", t: Date.now()} // 触发wxs的方法 (值改变才触发更新)
+ }
+ // 配置主动触发wxs隐藏加载进度的回调
+ this.mescroll.optDown.afterEndDownScroll = ()=>{
+ this.callProp = {callType: "endDownScroll", t: Date.now()} // 触发wxs的方法 (值改变才触发更新)
+ setTimeout(()=>{
+ if(this.downLoadType === 4 || this.downLoadType === 0){
+ this.callProp = {callType: "clearTransform", t: Date.now()} // 触发wxs的方法 (值改变才触发更新)
+ }
+ },320)
+ }
+ // 初始化wxs的数据
+ this.wxsCall({type: 'setWxsProp'})
+ // #endif
+ }
+}
+
+export default WxsMixin;
diff --git a/components/mescroll-uni/wxs/renderjs.js b/components/mescroll-uni/wxs/renderjs.js
new file mode 100644
index 0000000..207f388
--- /dev/null
+++ b/components/mescroll-uni/wxs/renderjs.js
@@ -0,0 +1,92 @@
+// 使用renderjs直接操作window对象,实现动态控制app和h5的bounce
+// bounce: iOS橡皮筋,Android半月弧,h5浏览器下拉背景等效果 (下拉刷新时禁止)
+// https://uniapp.dcloud.io/frame?id=renderjs
+
+// 与wxs的me实例一致
+var me = {}
+
+// 初始化window对象的touch事件 (仅初始化一次)
+if(window && !window.$mescrollRenderInit){
+ window.$mescrollRenderInit = true
+
+
+ window.addEventListener('touchstart', function(e){
+ if (me.disabled()) return;
+ me.startPoint = me.getPoint(e); // 记录起点
+ }, {passive: true})
+
+
+ window.addEventListener('touchmove', function(e){
+ if (me.disabled()) return;
+ if (me.getScrollTop() > 0) return; // 需在顶部下拉,才禁止bounce
+
+ var curPoint = me.getPoint(e); // 当前点
+ var moveY = curPoint.y - me.startPoint.y; // 和起点比,移动的距离,大于0向下拉,小于0向上拉
+ // 向下拉
+ if (moveY > 0) {
+ // 可下拉的条件
+ if (!me.isDownScrolling && !me.optDown.isLock && (!me.isUpScrolling || (me.isUpScrolling && me.isUpBoth))) {
+
+ // 只有touch在mescroll的view上面,才禁止bounce
+ var el = e.target;
+ var isMescrollTouch = false;
+ while (el && el.tagName && el.tagName !== 'UNI-PAGE-BODY' && el.tagName != "BODY") {
+ var cls = el.classList;
+ if (cls && cls.contains('mescroll-render-touch')) {
+ isMescrollTouch = true
+ break;
+ }
+ el = el.parentNode; // 继续检查其父元素
+ }
+ // 禁止bounce (不会对swiper和iOS侧滑返回造成影响)
+ if (isMescrollTouch && e.cancelable && !e.defaultPrevented) e.preventDefault();
+ }
+ }
+ }, {passive: false})
+}
+
+/* 获取滚动条的位置 */
+me.getScrollTop = function() {
+ return me.scrollTop || 0
+}
+
+/* 是否禁用下拉刷新 */
+me.disabled = function(){
+ return !me.optDown || !me.optDown.use || me.optDown.native
+}
+
+/* 根据点击滑动事件获取第一个手指的坐标 */
+me.getPoint = function(e) {
+ if (!e) {
+ return {x: 0,y: 0}
+ }
+ if (e.touches && e.touches[0]) {
+ return {x: e.touches[0].pageX,y: e.touches[0].pageY}
+ } else if (e.changedTouches && e.changedTouches[0]) {
+ return {x: e.changedTouches[0].pageX,y: e.changedTouches[0].pageY}
+ } else {
+ return {x: e.clientX,y: e.clientY}
+ }
+}
+
+/**
+ * 监听逻辑层数据的变化 (实时更新数据)
+ */
+function propObserver(wxsProp) {
+ me.optDown = wxsProp.optDown
+ me.scrollTop = wxsProp.scrollTop
+ me.isDownScrolling = wxsProp.isDownScrolling
+ me.isUpScrolling = wxsProp.isUpScrolling
+ me.isUpBoth = wxsProp.isUpBoth
+}
+
+/* 导出模块 */
+const renderBiz = {
+ data() {
+ return {
+ propObserver: propObserver,
+ }
+ }
+}
+
+export default renderBiz;
\ No newline at end of file
diff --git a/components/mescroll-uni/wxs/wxs.wxs b/components/mescroll-uni/wxs/wxs.wxs
new file mode 100644
index 0000000..3fb4ad9
--- /dev/null
+++ b/components/mescroll-uni/wxs/wxs.wxs
@@ -0,0 +1,268 @@
+// 使用wxs处理交互动画, 提高性能, 同时避免小程序bounce对下拉刷新的影响
+// https://uniapp.dcloud.io/frame?id=wxs
+// https://developers.weixin.qq.com/miniprogram/dev/framework/view/interactive-animation.html
+
+// 模拟mescroll实例, 与mescroll.js的写法尽量保持一致
+var me = {}
+
+// ------ 自定义下拉刷新动画 start ------
+
+/* 下拉过程中的回调,滑动过程一直在执行 (rate<1为inOffset; rate>1为outOffset) */
+me.onMoving = function (ins, rate, downHight){
+ ins.requestAnimationFrame(function () {
+ ins.selectComponent('.mescroll-wxs-content').setStyle({
+ 'will-change': 'transform', // 可解决下拉过程中, image和swiper脱离文档流的问题
+ 'transform': 'translateY(' + downHight + 'px)',
+ 'transition': ''
+ })
+ // 环形进度条
+ var progress = ins.selectComponent('.mescroll-wxs-progress')
+ progress && progress.setStyle({transform: 'rotate(' + 360 * rate + 'deg)'})
+ })
+}
+
+/* 显示下拉刷新进度 */
+me.showLoading = function (ins){
+ me.downHight = me.optDown.offset
+ ins.requestAnimationFrame(function () {
+ ins.selectComponent('.mescroll-wxs-content').setStyle({
+ 'will-change': 'auto',
+ 'transform': 'translateY(' + me.downHight + 'px)',
+ 'transition': 'transform 300ms'
+ })
+ })
+}
+
+/* 结束下拉 */
+me.endDownScroll = function (ins){
+ me.downHight = 0;
+ me.isDownScrolling = false;
+ ins.requestAnimationFrame(function () {
+ ins.selectComponent('.mescroll-wxs-content').setStyle({
+ 'will-change': 'auto',
+ 'transform': 'translateY(0)', // 不可以写空串,否则scroll-view渲染不完整 (延时350ms会调clearTransform置空)
+ 'transition': 'transform 300ms'
+ })
+ })
+}
+
+/* 结束下拉动画执行完毕后, 清除transform和transition, 避免对列表内容样式造成影响, 如: h5的list-msg示例下拉进度条漏出来等 */
+me.clearTransform = function (ins){
+ ins.requestAnimationFrame(function () {
+ ins.selectComponent('.mescroll-wxs-content').setStyle({
+ 'will-change': '',
+ 'transform': '',
+ 'transition': ''
+ })
+ })
+}
+
+// ------ 自定义下拉刷新动画 end ------
+
+/**
+ * 监听逻辑层数据的变化 (实时更新数据)
+ */
+function propObserver(wxsProp) {
+ me.optDown = wxsProp.optDown
+ me.scrollTop = wxsProp.scrollTop
+ me.bodyHeight = wxsProp.bodyHeight
+ me.isDownScrolling = wxsProp.isDownScrolling
+ me.isUpScrolling = wxsProp.isUpScrolling
+ me.isUpBoth = wxsProp.isUpBoth
+ me.isScrollBody = wxsProp.isScrollBody
+ me.startTop = wxsProp.scrollTop // 及时更新touchstart触发的startTop, 避免scroll-view快速惯性滚动到顶部取值不准确
+}
+
+/**
+ * 监听逻辑层数据的变化 (调用wxs的方法)
+ */
+function callObserver(callProp, oldValue, ins) {
+ if (me.disabled()) return;
+ if(callProp.callType){
+ // 逻辑层(App Service)的style已失效,需在视图层(Webview)设置style
+ if(callProp.callType === 'showLoading'){
+ me.showLoading(ins)
+ }else if(callProp.callType === 'endDownScroll'){
+ me.endDownScroll(ins)
+ }else if(callProp.callType === 'clearTransform'){
+ me.clearTransform(ins)
+ }
+ }
+}
+
+/**
+ * touch事件
+ */
+function touchstartEvent(e, ins) {
+ me.downHight = 0; // 下拉的距离
+ me.startPoint = me.getPoint(e); // 记录起点
+ me.startTop = me.getScrollTop(); // 记录此时的滚动条位置
+ me.startAngle = 0; // 初始角度
+ me.lastPoint = me.startPoint; // 重置上次move的点
+ me.maxTouchmoveY = me.getBodyHeight() - me.optDown.bottomOffset; // 手指触摸的最大范围(写在touchstart避免body获取高度为0的情况)
+ me.inTouchend = false; // 标记不是touchend
+
+ me.callMethod(ins, {type: 'setWxsProp'}) // 同步更新wxsProp的数据 (小程序是异步的,可能touchmove先执行,才到propObserver; h5和app是同步)
+}
+
+function touchmoveEvent(e, ins) {
+ var isPrevent = true // false表示不往上冒泡,相当于调用了同时调用了stopPropagation和preventDefault (对小程序生效, h5和app无效)
+
+ if (me.disabled()) return isPrevent;
+
+ var scrollTop = me.getScrollTop(); // 当前滚动条的距离
+ var curPoint = me.getPoint(e); // 当前点
+
+ var moveY = curPoint.y - me.startPoint.y; // 和起点比,移动的距离,大于0向下拉,小于0向上拉
+
+ // 向下拉 && 在顶部
+ // mescroll-body,直接判定在顶部即可
+ // scroll-view在滚动时不会触发touchmove,当触顶/底/左/右时,才会触发touchmove
+ // scroll-view滚动到顶部时,scrollTop不一定为0,也有可能大于0; 在iOS的APP中scrollTop可能为负数,不一定和startTop相等
+ if (moveY > 0 && (
+ (me.isScrollBody && scrollTop <= 0)
+ ||
+ (!me.isScrollBody && (scrollTop <= 0 || (scrollTop <= me.optDown.startTop && scrollTop === me.startTop)) )
+ )) {
+ // 可下拉的条件
+ if (!me.inTouchend && !me.isDownScrolling && !me.optDown.isLock && (!me.isUpScrolling || (me.isUpScrolling &&
+ me.isUpBoth))) {
+
+ // 下拉的角度是否在配置的范围内
+ if(!me.startAngle) me.startAngle = me.getAngle(me.lastPoint, curPoint); // 两点之间的角度,区间 [0,90]
+ if (me.startAngle < me.optDown.minAngle) return isPrevent; // 如果小于配置的角度,则不往下执行下拉刷新
+
+ // 如果手指的位置超过配置的距离,则提前结束下拉,避免Webview嵌套导致touchend无法触发
+ if (me.maxTouchmoveY > 0 && curPoint.y >= me.maxTouchmoveY) {
+ me.inTouchend = true; // 标记执行touchend
+ touchendEvent(e, ins); // 提前触发touchend
+ return isPrevent;
+ }
+
+ isPrevent = false // 小程序是return false
+
+ var diff = curPoint.y - me.lastPoint.y; // 和上次比,移动的距离 (大于0向下,小于0向上)
+
+ // 下拉距离 < 指定距离
+ if (me.downHight < me.optDown.offset) {
+ if (me.movetype !== 1) {
+ me.movetype = 1; // 加入标记,保证只执行一次
+ // me.optDown.inOffset && me.optDown.inOffset(me); // 进入指定距离范围内那一刻的回调,只执行一次
+ me.callMethod(ins, {type: 'setLoadType', downLoadType: 1})
+ me.isMoveDown = true; // 标记下拉区域高度改变,在touchend重置回来
+ }
+ me.downHight += diff * me.optDown.inOffsetRate; // 越往下,高度变化越小
+
+ // 指定距离 <= 下拉距离
+ } else {
+ if (me.movetype !== 2) {
+ me.movetype = 2; // 加入标记,保证只执行一次
+ // me.optDown.outOffset && me.optDown.outOffset(me); // 下拉超过指定距离那一刻的回调,只执行一次
+ me.callMethod(ins, {type: 'setLoadType', downLoadType: 2})
+ me.isMoveDown = true; // 标记下拉区域高度改变,在touchend重置回来
+ }
+ if (diff > 0) { // 向下拉
+ me.downHight += diff * me.optDown.outOffsetRate; // 越往下,高度变化越小
+ } else { // 向上收
+ me.downHight += diff; // 向上收回高度,则向上滑多少收多少高度
+ }
+ }
+
+ me.downHight = Math.round(me.downHight) // 取整
+ var rate = me.downHight / me.optDown.offset; // 下拉区域当前高度与指定距离的比值
+ // me.optDown.onMoving && me.optDown.onMoving(me, rate, me.downHight); // 下拉过程中的回调,一直在执行
+ me.onMoving(ins, rate, me.downHight)
+ }
+ }
+
+ me.lastPoint = curPoint; // 记录本次移动的点
+
+ return isPrevent // false表示不往上冒泡,相当于调用了同时调用了stopPropagation和preventDefault (对小程序生效, h5和app无效)
+}
+
+function touchendEvent(e, ins) {
+ // 如果下拉区域高度已改变,则需重置回来
+ if (me.isMoveDown) {
+ if (me.downHight >= me.optDown.offset) {
+ // 符合触发刷新的条件
+ me.downHight = me.optDown.offset; // 更新下拉区域高度
+ // me.triggerDownScroll();
+ me.callMethod(ins, {type: 'triggerDownScroll'})
+ } else {
+ // 不符合的话 则重置
+ me.downHight = 0;
+ // me.optDown.endDownScroll && me.optDown.endDownScroll(me);
+ me.callMethod(ins, {type: 'endDownScroll'})
+ }
+ me.movetype = 0;
+ me.isMoveDown = false;
+ } else if (!me.isScrollBody && me.getScrollTop() === me.startTop) { // scroll-view到顶/左/右/底的滑动事件
+ var isScrollUp = me.getPoint(e).y - me.startPoint.y < 0; // 和起点比,移动的距离,大于0向下拉,小于0向上拉
+ // 上滑
+ if (isScrollUp) {
+ // 需检查滑动的角度
+ var angle = me.getAngle(me.getPoint(e), me.startPoint); // 两点之间的角度,区间 [0,90]
+ if (angle > 80) {
+ // 检查并触发上拉
+ // me.triggerUpScroll(true);
+ me.callMethod(ins, {type: 'triggerUpScroll'})
+ }
+ }
+ }
+ me.callMethod(ins, {type: 'setWxsProp'}) // 同步更新wxsProp的数据 (小程序是异步的,可能touchmove先执行,才到propObserver; h5和app是同步)
+}
+
+/* 是否禁用下拉刷新 */
+me.disabled = function(){
+ return !me.optDown || !me.optDown.use || me.optDown.native
+}
+
+/* 根据点击滑动事件获取第一个手指的坐标 */
+me.getPoint = function(e) {
+ if (!e) {
+ return {x: 0,y: 0}
+ }
+ if (e.touches && e.touches[0]) {
+ return {x: e.touches[0].pageX,y: e.touches[0].pageY}
+ } else if (e.changedTouches && e.changedTouches[0]) {
+ return {x: e.changedTouches[0].pageX,y: e.changedTouches[0].pageY}
+ } else {
+ return {x: e.clientX,y: e.clientY}
+ }
+}
+
+/* 计算两点之间的角度: 区间 [0,90]*/
+me.getAngle = function (p1, p2) {
+ var x = Math.abs(p1.x - p2.x);
+ var y = Math.abs(p1.y - p2.y);
+ var z = Math.sqrt(x * x + y * y);
+ var angle = 0;
+ if (z !== 0) {
+ angle = Math.asin(y / z) / Math.PI * 180;
+ }
+ return angle
+}
+
+/* 获取滚动条的位置 */
+me.getScrollTop = function() {
+ return me.scrollTop || 0
+}
+
+/* 获取body的高度 */
+me.getBodyHeight = function() {
+ return me.bodyHeight || 0;
+}
+
+/* 调用逻辑层的方法 */
+me.callMethod = function(ins, param) {
+ if(ins) ins.callMethod('wxsCall', param)
+}
+
+/* 导出模块 */
+module.exports = {
+ propObserver: propObserver,
+ callObserver: callObserver,
+ touchstartEvent: touchstartEvent,
+ touchmoveEvent: touchmoveEvent,
+ touchendEvent: touchendEvent
+}
\ No newline at end of file
diff --git a/components/mx-datepicker/mx-datepicker.vue b/components/mx-datepicker/mx-datepicker.vue
new file mode 100644
index 0000000..e4a3701
--- /dev/null
+++ b/components/mx-datepicker/mx-datepicker.vue
@@ -0,0 +1,819 @@
+
+
+
+
+
+
+
+
+ {{week}}
+
+
+
+
+
+
+ {{date.title}}
+
+
+
+
+ {{date.tips}}
+
+
+
+
+
+
+
+
+
+
+
+ {{i<10?'0'+i:i}}时
+
+
+ {{i<10?'0'+i:i}}分
+
+
+ {{i<10?'0'+i:i}}秒
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/mx-datepicker/uni-pagination.vue b/components/mx-datepicker/uni-pagination.vue
new file mode 100644
index 0000000..4aee52a
--- /dev/null
+++ b/components/mx-datepicker/uni-pagination.vue
@@ -0,0 +1,218 @@
+
+
+
+
+
+
+
diff --git a/components/prompt/README.md b/components/prompt/README.md
new file mode 100644
index 0000000..d940b60
--- /dev/null
+++ b/components/prompt/README.md
@@ -0,0 +1,37 @@
+# Prompt
+
+## 说明
+
+一个可以输入内容并返回的prompt组件, 支持一个默认slot放入中间.
+
+## 用法
+
+**父组件**
+
+template中
+```html
+
+
+
+```
+
+```js
+import Prompt from '@/components/prompt/index.vue'
+
+export default {
+ data() {
+ return {
+ // 控制弹框输入框显示
+ promptVisible: false,
+ }
+ },
+ methods: {
+ /**
+ * 点击弹出输入框确定
+ */
+ clickPromptConfirm(val) {
+ console.log(val)
+ },
+ }
+}
+```
\ No newline at end of file
diff --git a/components/prompt/index.vue b/components/prompt/index.vue
new file mode 100644
index 0000000..c2870fb
--- /dev/null
+++ b/components/prompt/index.vue
@@ -0,0 +1,158 @@
+
+
+
+
+ {{title}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/tags-list.vue b/components/tags-list.vue
new file mode 100644
index 0000000..f53e6a9
--- /dev/null
+++ b/components/tags-list.vue
@@ -0,0 +1,54 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/components/utils/amap-wx.js b/components/utils/amap-wx.js
new file mode 100644
index 0000000..eb969c3
--- /dev/null
+++ b/components/utils/amap-wx.js
@@ -0,0 +1 @@
+function AMapWX(a){this.key=a.key,this.requestConfig={key:a.key,s:"rsx",platform:"WXJS",appname:a.key,sdkversion:"1.2.0",logversion:"2.0"}}AMapWX.prototype.getWxLocation=function(a,b){wx.getLocation({type:"gcj02",success:function(a){var c=a.longitude+","+a.latitude;wx.setStorage({key:"userLocation",data:c}),b(c)},fail:function(c){wx.getStorage({key:"userLocation",success:function(a){a.data&&b(a.data)}}),a.fail({errCode:"0",errMsg:c.errMsg||""})}})},AMapWX.prototype.getRegeo=function(a){function c(c){var d=b.requestConfig;wx.request({url:"https://restapi.amap.com/v3/geocode/regeo",data:{key:b.key,location:c,extensions:"all",s:d.s,platform:d.platform,appname:b.key,sdkversion:d.sdkversion,logversion:d.logversion},method:"GET",header:{"content-type":"application/json"},success:function(b){var d,e,f,g,h,i,j,k,l;b.data.status&&"1"==b.data.status?(d=b.data.regeocode,e=d.addressComponent,f=[],g="",d&&d.roads[0]&&d.roads[0].name&&(g=d.roads[0].name+"附近"),h=c.split(",")[0],i=c.split(",")[1],d.pois&&d.pois[0]&&(g=d.pois[0].name+"附近",j=d.pois[0].location,j&&(h=parseFloat(j.split(",")[0]),i=parseFloat(j.split(",")[1]))),e.provice&&f.push(e.provice),e.city&&f.push(e.city),e.district&&f.push(e.district),e.streetNumber&&e.streetNumber.street&&e.streetNumber.number?(f.push(e.streetNumber.street),f.push(e.streetNumber.number)):(k="",d&&d.roads[0]&&d.roads[0].name&&(k=d.roads[0].name),f.push(k)),f=f.join(""),l=[{iconPath:a.iconPath,width:a.iconWidth,height:a.iconHeight,name:f,desc:g,longitude:h,latitude:i,id:0,regeocodeData:d}],a.success(l)):a.fail({errCode:b.data.infocode,errMsg:b.data.info})},fail:function(b){a.fail({errCode:"0",errMsg:b.errMsg||""})}})}var b=this;a.location?c(a.location):b.getWxLocation(a,function(a){c(a)})},AMapWX.prototype.getWeather=function(a){function d(d){var e="base";a.type&&"forecast"==a.type&&(e="all"),wx.request({url:"https://restapi.amap.com/v3/weather/weatherInfo",data:{key:b.key,city:d,extensions:e,s:c.s,platform:c.platform,appname:b.key,sdkversion:c.sdkversion,logversion:c.logversion},method:"GET",header:{"content-type":"application/json"},success:function(b){function c(a){var b={city:{text:"城市",data:a.city},weather:{text:"天气",data:a.weather},temperature:{text:"温度",data:a.temperature},winddirection:{text:"风向",data:a.winddirection+"风"},windpower:{text:"风力",data:a.windpower+"级"},humidity:{text:"湿度",data:a.humidity+"%"}};return b}var d,e;b.data.status&&"1"==b.data.status?b.data.lives?(d=b.data.lives,d&&d.length>0&&(d=d[0],e=c(d),e["liveData"]=d,a.success(e))):b.data.forecasts&&b.data.forecasts[0]&&a.success({forecast:b.data.forecasts[0]}):a.fail({errCode:b.data.infocode,errMsg:b.data.info})},fail:function(b){a.fail({errCode:"0",errMsg:b.errMsg||""})}})}function e(e){wx.request({url:"https://restapi.amap.com/v3/geocode/regeo",data:{key:b.key,location:e,extensions:"all",s:c.s,platform:c.platform,appname:b.key,sdkversion:c.sdkversion,logversion:c.logversion},method:"GET",header:{"content-type":"application/json"},success:function(b){var c,e;b.data.status&&"1"==b.data.status?(e=b.data.regeocode,e.addressComponent?c=e.addressComponent.adcode:e.aois&&e.aois.length>0&&(c=e.aois[0].adcode),d(c)):a.fail({errCode:b.data.infocode,errMsg:b.data.info})},fail:function(b){a.fail({errCode:"0",errMsg:b.errMsg||""})}})}var b=this,c=b.requestConfig;a.city?d(a.city):b.getWxLocation(a,function(a){e(a)})},AMapWX.prototype.getPoiAround=function(a){function d(d){var e={key:b.key,location:d,s:c.s,platform:c.platform,appname:b.key,sdkversion:c.sdkversion,logversion:c.logversion};a.querytypes&&(e["types"]=a.querytypes),a.querykeywords&&(e["keywords"]=a.querykeywords),wx.request({url:"https://restapi.amap.com/v3/place/around",data:e,method:"GET",header:{"content-type":"application/json"},success:function(b){var c,d,e,f;if(b.data.status&&"1"==b.data.status){if(b=b.data,b&&b.pois){for(c=[],d=0;dview{
+}
+.point_one .point_one_box .point_one_1{width: 50px;}
+.point_one .point_one_box .point_one_2{width: 30px;margin: 0 8px 0 0;font-size: 12px;text-align: center;}
+.point_one .point_one_box .point_one_2 img{width: 100%;}
+.point_one .point_one_box .point_one_3{width: 100%;background: rgba(245, 245, 245, 1);height: 7px;line-height: 7px;margin: auto;border-radius: 10px;overflow: hidden;}
+.point_two{
+ padding:16px 10px;
+}
+.point_two1 .pf_star{
+ text-align: center;
+}
+.point_two1 .pf_star .pf_star_img{
+ float: none;
+ height: 35px;
+ display: inline-block;
+}
+.point_one>view{
+ height: 20px;
+ line-height: 20px;
+ font-size: 14px;
+ display: flex;
+ width: 100%;
+}
+.doPoint P {
+ color: #363942;
+ padding:10px 0 10px 0;
+ text-align: center;
+ font-size: 19px;
+}
+.doPoint2 P {
+ color: #363942;
+ padding:10px 0 10px 0;
+ text-align:left;
+ font-size: 22px;
+}
+.pf_star{
+ width:100%;
+ /* height: 34px; */
+ margin-bottom: 15px;
+ font-size: 14px;
+ color: rgba(51, 51, 51, 1);
+}
+.pf_star label{
+ width: 20%;
+ float: left;
+ display: inline-block;
+}
+.pf_star_ind{
+ width: 45%;
+ display: inline-block;
+}
+.pf_star_img{
+ float: left;
+ width: 35px!important;
+}
+.pf_star_img2{
+ width: 18px !important;
+ height: 18px;
+ display: flex;
+ justify-content: space-evenly;
+ margin-right: 10px;
+}
+.hint{
+ padding: 0 0 0 10px;
+ display: none;
+}
+.hintxin{
+ padding: 0 0 0 10px;
+ font-size: 16px !important;
+ font-family:Microsoft YaHei;
+ font-weight:400;
+ color: rgba(255,153,0,1) !important;
+}
+.hintxin2{
+ padding: 0 0 0 5%;
+ width: 30%;
+ font-size: 14px !important;
+ display: inline-block;
+ margin-top: -3px;
+}
+.point_one .pf_star_img img{
+ /* padding: 20px 0 0 0; */
+ width: 12px;
+}
+.pf_star_img img{
+ /* padding: 20px 0 0 0; */
+ width: 24px;
+}
+.point_two .pf_star_img img{
+ width: 24px;
+}
+.point_two .pf_star_img2 img{
+ width: 18px;
+ height: 18px;
+}
+.pj_con,.ni_ming{
+ padding:20px 20px;
+}
+.ni_ming_1,.ni_ming_2{
+ margin-bottom:10px;
+ color: rgba(153, 153, 153, 1);
+}
+.ni_ming_1 label{
+ height: 30px;
+ margin-left: 10%;
+}
+.ni_ming_1 input{
+ width: 20px;
+ height: 20px;
+}
+.zui-check {
+ position: absolute;
+ z-index: 1;
+ opacity: 0;
+}
+
+.zui-icon-1 {
+ width: 20px;
+ height: 20px;
+ position: absolute;
+ background: url(http://luci.tour-ma.com/r/cms/www/default/newxt/img/lcimg/icon-dianpinggouxuan1.png) no-repeat;
+ background-size: 100%;
+}
+.zui-icon-2 {
+ width: 20px;
+ height: 20px;
+ position: absolute;
+ background: url(http://luci.tour-ma.com/r/cms/www/default/newxt/img/lcimg/icon-dianpinggouxuan0.png) no-repeat;
+ background-size: 100%;
+}
+
+.ni_ming_2 label{
+ height: 30px;
+ display: inline-block;
+ width: 20%;
+}
+.ni_ming_2 input{
+ height: 30px;
+ margin-left: 5%;
+ width: 75%;
+ display: inline-block;
+ border: none;
+}
+.pj_con label{
+ display:block;
+ color: #363942;
+}
+.pj_con textarea{
+ width: 90%;
+ background: RGBA(247, 244, 248, 1);
+ border-radius: 10px;
+ padding: 5%;
+ color: rgba(153, 153, 153, 1);
+ border: none;
+ font-size: 16px;
+}
+.pj_con textarea:focus{
+ outline: none;
+}
+.pj_con textarea::-webkit-input-placeholder {
+ color: rgba(204, 204, 204, 1);
+}
+.tijiao-btn {
+ text-align: center;
+ padding: 30px 0;
+}
+.tijiao-btn .btn{
+ width: 90%;
+ height: 40px;
+ line-height: 40px;
+ text-align: center;
+ background-color: RGBA(53, 109, 242, 1);
+ border: 0px;
+ border-radius: 20px;
+ color: #fff;
+ font-size: 18px;
+}
diff --git a/components/utils/date.js b/components/utils/date.js
new file mode 100644
index 0000000..6cb729d
--- /dev/null
+++ b/components/utils/date.js
@@ -0,0 +1,185 @@
+function formatTime2(date) {
+ var year = date.getFullYear()
+ var month = date.getMonth() + 1
+ var day = date.getDate()
+ var hour = date.getHours()
+ var minute = date.getMinutes()
+ var second = date.getSeconds()
+
+
+ return [year, month, day].map(formatNumber).join('/') + ' ' + [hour, minute, second].map(formatNumber).join(':')
+}
+
+function formatTime(time) {
+ if (typeof time !== 'number' || time < 0) {
+ return time
+ }
+
+ var hour = parseInt(time / 3600)
+ time = time % 3600
+ var minute = parseInt(time / 60)
+ time = time % 60
+ var second = time
+
+ return ([hour, minute, second]).map(function(n) {
+ n = n.toString()
+ return n[1] ? n : '0' + n
+ }).join(':')
+}
+
+function formatLocation(longitude, latitude) {
+ if (typeof longitude === 'string' && typeof latitude === 'string') {
+ longitude = parseFloat(longitude)
+ latitude = parseFloat(latitude)
+ }
+
+ longitude = longitude.toFixed(2)
+ latitude = latitude.toFixed(2)
+
+ return {
+ longitude: longitude.toString().split('.'),
+ latitude: latitude.toString().split('.')
+ }
+}
+
+function formatDate(date) {
+ var year = date.getFullYear()
+ var month = date.getMonth() + 1
+ var day = date.getDate()
+
+ if (date.getHours() >= 24) {
+ day = day + 1;
+ }
+
+ return [year, month, day].map(formatNumber).join('-')
+}
+
+function formatNumber(n) {
+ n = n.toString()
+ return n[1] ? n : '0' + n
+}
+function formatDates(date) {
+ var year = date.getFullYear()
+ var month = date.getMonth() + 1
+ var day = date.getDate() + 1
+
+ if (date.getHours() >= 24) {
+ day = day + 1;
+ }
+
+ return [year, month, day].map(formatNumber).join('-')
+}
+function formatDatess(date) {
+ var year = date.getFullYear()
+ var month = date.getMonth() + 1
+ var day = date.getDate() + 19
+
+ if (date.getHours() >= 24) {
+ day = day + 1;
+ }
+
+ return [year, month, day].map(formatNumber).join('-')
+}
+function formatDatessz(date) {
+ var year = date.getFullYear()
+ var month = date.getMonth() + 1
+ var day = date.getDate() + 18
+
+ if (date.getHours() >= 24) {
+ day = day + 1;
+ }
+
+ return [year, month, day].map(formatNumber).join('-')
+}
+function stringToTime(string) {
+ var f = string.split(' ', 2);
+ var d = (f[0] ? f[0] : '').split('-', 3);
+ var t = (f[1] ? f[1] : '').split(':', 3);
+ return (new Date(
+ parseInt(d[0], 10) || null,
+ (parseInt(d[1], 10) || 1) - 1,
+ parseInt(d[2], 10) || null,
+ parseInt(t[0], 10) || null,
+ parseInt(t[1], 10) || null,
+ parseInt(t[2], 10) || null)).getTime();
+}
+function dateAddDays(dataStr, dayCount) {
+ var strdate = dataStr; //日期字符串
+ var isdate = new Date(strdate.replace(/-/g, "/")); //把日期字符串转换成日期格式
+ isdate = new Date((isdate / 1000 + (86400 * dayCount)) * 1000); //日期加1天
+ var pdate = isdate.getFullYear() + "-" + (isdate.getMonth() + 1) + "-" + (isdate.getDate()); //把日期格式转换成字符串
+
+ return pdate;
+}
+function dateAddDayz(dataStr, dayCount) {
+ var strdate = dataStr; //日期字符串
+ var isdate = new Date(strdate.replace(/-/g, "/")); //把日期字符串转换成日期格式
+ isdate = new Date((isdate / 1000 - (86400 * dayCount)) * 1000); //日期加1天
+ var pdate = isdate.getFullYear() + "-" + (isdate.getMonth() + 1) + "-" + (isdate.getDate()); //把日期格式转换成字符串
+
+ return pdate;
+}
+//获取当前时间‘年-月-日 时:分’
+function getNowTime() {
+ var now = new Date();
+ var year = now.getFullYear();
+ var month = now.getMonth() + 1;
+ var day = now.getDate();
+ if (month < 10) {
+ month = '0' + month;
+ };
+ if (day < 10) {
+ day = '0' + day;
+ };
+ //如果需要时分秒,就放开
+ var h = now.getHours();
+ var m = now.getMinutes();
+ var s = now.getSeconds();
+ var formatDate = h+':'+m;
+ return formatDate;
+}
+function haveSomeMinutesTime(n) {
+ if (n == null) {
+ n = 0;
+ }
+ // 时间
+ var newDate = new Date()
+ // var timeStamp = newDate.getTime(); //获取时间戳
+ var date = newDate.setMinutes(newDate.getMinutes() + n);
+ newDate = new Date(date);
+ var year = newDate.getFullYear();
+ var month = newDate.getMonth() + 1;
+ var day = newDate.getDate();
+ var h = newDate.getHours();
+ var m = newDate.getMinutes();
+ var s = newDate.getSeconds();
+ if (month < 10) {
+ month = '0' + month;
+ };
+ if (day < 10) {
+ day = '0' + day;
+ };
+ if (h < 10) {
+ h = '0' + h;
+ };
+ if (m < 10) {
+ m = '0' + m;
+ };
+ if (s < 10) {
+ s = '0' + s;
+ };
+ var time = h + ':' + m;
+ return time;
+}
+module.exports = {
+ haveSomeMinutesTime: haveSomeMinutesTime,
+ getNowTime: getNowTime,
+ formatTime: formatTime,
+ formatDate: formatDate,
+ formatDates: formatDates,
+ stringToTime: stringToTime,
+ formatDatess: formatDatess,
+ dateAddDays: dateAddDays,
+ dateAddDayz: dateAddDayz,
+ formatDatessz: formatDatessz
+}
\ No newline at end of file
diff --git a/components/utils/erweima.js b/components/utils/erweima.js
new file mode 100644
index 0000000..2573eaa
--- /dev/null
+++ b/components/utils/erweima.js
@@ -0,0 +1,1123 @@
+// Core code comes from https://github.com/davidshimjs/qrcodejs
+var QRCode;
+
+(function() {
+ /**
+ * Get the type by string length
+ *
+ * @private
+ * @param {String} sText
+ * @param {Number} nCorrectLevel
+ * @return {Number} type
+ */
+ function _getTypeNumber(sText, nCorrectLevel) {
+ var nType = 1;
+ var length = _getUTF8Length(sText);
+
+ for (var i = 0, len = QRCodeLimitLength.length; i <= len; i++) {
+ var nLimit = 0;
+
+ switch (nCorrectLevel) {
+ case QRErrorCorrectLevel.L:
+ nLimit = QRCodeLimitLength[i][0];
+ break;
+ case QRErrorCorrectLevel.M:
+ nLimit = QRCodeLimitLength[i][1];
+ break;
+ case QRErrorCorrectLevel.Q:
+ nLimit = QRCodeLimitLength[i][2];
+ break;
+ case QRErrorCorrectLevel.H:
+ nLimit = QRCodeLimitLength[i][3];
+ break;
+ }
+
+ if (length <= nLimit) {
+ break;
+ } else {
+ nType++;
+ }
+ }
+
+ if (nType > QRCodeLimitLength.length) {
+ throw new Error("Too long data");
+ }
+
+ return nType;
+ }
+
+ function _getUTF8Length(sText) {
+ var replacedText = encodeURI(sText).toString().replace(/\%[0-9a-fA-F]{2}/g, 'a');
+ return replacedText.length + (replacedText.length != sText ? 3 : 0);
+ }
+
+ function QR8bitByte(data) {
+ this.mode = QRMode.MODE_8BIT_BYTE;
+ this.data = data;
+ this.parsedData = [];
+
+ // Added to support UTF-8 Characters
+ for (var i = 0, l = this.data.length; i < l; i++) {
+ var byteArray = [];
+ var code = this.data.charCodeAt(i);
+
+ if (code > 0x10000) {
+ byteArray[0] = 0xF0 | ((code & 0x1C0000) >>> 18);
+ byteArray[1] = 0x80 | ((code & 0x3F000) >>> 12);
+ byteArray[2] = 0x80 | ((code & 0xFC0) >>> 6);
+ byteArray[3] = 0x80 | (code & 0x3F);
+ } else if (code > 0x800) {
+ byteArray[0] = 0xE0 | ((code & 0xF000) >>> 12);
+ byteArray[1] = 0x80 | ((code & 0xFC0) >>> 6);
+ byteArray[2] = 0x80 | (code & 0x3F);
+ } else if (code > 0x80) {
+ byteArray[0] = 0xC0 | ((code & 0x7C0) >>> 6);
+ byteArray[1] = 0x80 | (code & 0x3F);
+ } else {
+ byteArray[0] = code;
+ }
+
+ this.parsedData.push(byteArray);
+ }
+
+ this.parsedData = Array.prototype.concat.apply([], this.parsedData);
+
+ if (this.parsedData.length != this.data.length) {
+ this.parsedData.unshift(191);
+ this.parsedData.unshift(187);
+ this.parsedData.unshift(239);
+ }
+ }
+
+ QR8bitByte.prototype = {
+ getLength: function(buffer) {
+ return this.parsedData.length;
+ },
+ write: function(buffer) {
+ for (var i = 0, l = this.parsedData.length; i < l; i++) {
+ buffer.put(this.parsedData[i], 8);
+ }
+ }
+ };
+
+
+ // QRCodeModel
+ function QRCodeModel(typeNumber, errorCorrectLevel) {
+ this.typeNumber = typeNumber;
+ this.errorCorrectLevel = errorCorrectLevel;
+ this.modules = null;
+ this.moduleCount = 0;
+ this.dataCache = null;
+ this.dataList = [];
+ }
+ QRCodeModel.prototype = {
+ addData: function(data) {
+ var newData = new QR8bitByte(data);
+ this.dataList.push(newData);
+ this.dataCache = null;
+ },
+ isDark: function(row, col) {
+ if (row < 0 || this.moduleCount <= row || col < 0 || this.moduleCount <= col) {
+ throw new Error(row + "," + col);
+ }
+ return this.modules[row][col];
+ },
+ getModuleCount: function() {
+ return this.moduleCount;
+ },
+ make: function() {
+ this.makeImpl(false, this.getBestMaskPattern());
+ },
+ makeImpl: function(test, maskPattern) {
+ this.moduleCount = this.typeNumber * 4 + 17;
+ this.modules = new Array(this.moduleCount);
+ for (var row = 0; row < this.moduleCount; row++) {
+ this.modules[row] = new Array(this.moduleCount);
+ for (var col = 0; col < this.moduleCount; col++) {
+ this.modules[row][col] = null;
+ }
+ }
+ this.setupPositionProbePattern(0, 0);
+ this.setupPositionProbePattern(this.moduleCount - 7, 0);
+ this.setupPositionProbePattern(0, this.moduleCount - 7);
+ this.setupPositionAdjustPattern();
+ this.setupTimingPattern();
+ this.setupTypeInfo(test, maskPattern);
+ if (this.typeNumber >= 7) {
+ this.setupTypeNumber(test);
+ }
+ if (this.dataCache == null) {
+ this.dataCache = QRCodeModel.createData(this.typeNumber, this.errorCorrectLevel, this.dataList);
+ }
+ this.mapData(this.dataCache, maskPattern);
+ },
+ setupPositionProbePattern: function(row, col) {
+ for (var r = -1; r <= 7; r++) {
+ if (row + r <= -1 || this.moduleCount <= row + r) continue;
+ for (var c = -1; c <= 7; c++) {
+ if (col + c <= -1 || this.moduleCount <= col + c) continue;
+ if ((0 <= r && r <= 6 && (c == 0 || c == 6)) || (0 <= c && c <= 6 && (r == 0 || r == 6)) || (2 <= r && r <= 4 &&
+ 2 <= c && c <= 4)) {
+ this.modules[row + r][col + c] = true;
+ } else {
+ this.modules[row + r][col + c] = false;
+ }
+ }
+ }
+ },
+ getBestMaskPattern: function() {
+ var minLostPoint = 0;
+ var pattern = 0;
+ for (var i = 0; i < 8; i++) {
+ this.makeImpl(true, i);
+ var lostPoint = QRUtil.getLostPoint(this);
+ if (i == 0 || minLostPoint > lostPoint) {
+ minLostPoint = lostPoint;
+ pattern = i;
+ }
+ }
+ return pattern;
+ },
+ createMovieClip: function(target_mc, instance_name, depth) {
+ var qr_mc = target_mc.createEmptyMovieClip(instance_name, depth);
+ var cs = 1;
+ this.make();
+ for (var row = 0; row < this.modules.length; row++) {
+ var y = row * cs;
+ for (var col = 0; col < this.modules[row].length; col++) {
+ var x = col * cs;
+ var dark = this.modules[row][col];
+ if (dark) {
+ qr_mc.beginFill(0, 100);
+ qr_mc.moveTo(x, y);
+ qr_mc.lineTo(x + cs, y);
+ qr_mc.lineTo(x + cs, y + cs);
+ qr_mc.lineTo(x, y + cs);
+ qr_mc.endFill();
+ }
+ }
+ }
+ return qr_mc;
+ },
+ setupTimingPattern: function() {
+ for (var r = 8; r < this.moduleCount - 8; r++) {
+ if (this.modules[r][6] != null) {
+ continue;
+ }
+ this.modules[r][6] = (r % 2 == 0);
+ }
+ for (var c = 8; c < this.moduleCount - 8; c++) {
+ if (this.modules[6][c] != null) {
+ continue;
+ }
+ this.modules[6][c] = (c % 2 == 0);
+ }
+ },
+ setupPositionAdjustPattern: function() {
+ var pos = QRUtil.getPatternPosition(this.typeNumber);
+ for (var i = 0; i < pos.length; i++) {
+ for (var j = 0; j < pos.length; j++) {
+ var row = pos[i];
+ var col = pos[j];
+ if (this.modules[row][col] != null) {
+ continue;
+ }
+ for (var r = -2; r <= 2; r++) {
+ for (var c = -2; c <= 2; c++) {
+ if (r == -2 || r == 2 || c == -2 || c == 2 || (r == 0 && c == 0)) {
+ this.modules[row + r][col + c] = true;
+ } else {
+ this.modules[row + r][col + c] = false;
+ }
+ }
+ }
+ }
+ }
+ },
+ setupTypeNumber: function(test) {
+ var bits = QRUtil.getBCHTypeNumber(this.typeNumber);
+ for (var i = 0; i < 18; i++) {
+ var mod = (!test && ((bits >> i) & 1) == 1);
+ this.modules[Math.floor(i / 3)][i % 3 + this.moduleCount - 8 - 3] = mod;
+ }
+ for (var i = 0; i < 18; i++) {
+ var mod = (!test && ((bits >> i) & 1) == 1);
+ this.modules[i % 3 + this.moduleCount - 8 - 3][Math.floor(i / 3)] = mod;
+ }
+ },
+ setupTypeInfo: function(test, maskPattern) {
+ var data = (this.errorCorrectLevel << 3) | maskPattern;
+ var bits = QRUtil.getBCHTypeInfo(data);
+ for (var i = 0; i < 15; i++) {
+ var mod = (!test && ((bits >> i) & 1) == 1);
+ if (i < 6) {
+ this.modules[i][8] = mod;
+ } else if (i < 8) {
+ this.modules[i + 1][8] = mod;
+ } else {
+ this.modules[this.moduleCount - 15 + i][8] = mod;
+ }
+ }
+ for (var i = 0; i < 15; i++) {
+ var mod = (!test && ((bits >> i) & 1) == 1);
+ if (i < 8) {
+ this.modules[8][this.moduleCount - i - 1] = mod;
+ } else if (i < 9) {
+ this.modules[8][15 - i - 1 + 1] = mod;
+ } else {
+ this.modules[8][15 - i - 1] = mod;
+ }
+ }
+ this.modules[this.moduleCount - 8][8] = (!test);
+ },
+ mapData: function(data, maskPattern) {
+ var inc = -1;
+ var row = this.moduleCount - 1;
+ var bitIndex = 7;
+ var byteIndex = 0;
+ for (var col = this.moduleCount - 1; col > 0; col -= 2) {
+ if (col == 6) col--;
+ while (true) {
+ for (var c = 0; c < 2; c++) {
+ if (this.modules[row][col - c] == null) {
+ var dark = false;
+ if (byteIndex < data.length) {
+ dark = (((data[byteIndex] >>> bitIndex) & 1) == 1);
+ }
+ var mask = QRUtil.getMask(maskPattern, row, col - c);
+ if (mask) {
+ dark = !dark;
+ }
+ this.modules[row][col - c] = dark;
+ bitIndex--;
+ if (bitIndex == -1) {
+ byteIndex++;
+ bitIndex = 7;
+ }
+ }
+ }
+ row += inc;
+ if (row < 0 || this.moduleCount <= row) {
+ row -= inc;
+ inc = -inc;
+ break;
+ }
+ }
+ }
+ }
+ };
+ QRCodeModel.PAD0 = 0xEC;
+ QRCodeModel.PAD1 = 0x11;
+ QRCodeModel.createData = function(typeNumber, errorCorrectLevel, dataList) {
+ var rsBlocks = QRRSBlock.getRSBlocks(typeNumber, errorCorrectLevel);
+ var buffer = new QRBitBuffer();
+ for (var i = 0; i < dataList.length; i++) {
+ var data = dataList[i];
+ buffer.put(data.mode, 4);
+ buffer.put(data.getLength(), QRUtil.getLengthInBits(data.mode, typeNumber));
+ data.write(buffer);
+ }
+ var totalDataCount = 0;
+ for (var i = 0; i < rsBlocks.length; i++) {
+ totalDataCount += rsBlocks[i].dataCount;
+ }
+ if (buffer.getLengthInBits() > totalDataCount * 8) {
+ throw new Error("code length overflow. (" +
+ buffer.getLengthInBits() +
+ ">" +
+ totalDataCount * 8 +
+ ")");
+ }
+ if (buffer.getLengthInBits() + 4 <= totalDataCount * 8) {
+ buffer.put(0, 4);
+ }
+ while (buffer.getLengthInBits() % 8 != 0) {
+ buffer.putBit(false);
+ }
+ while (true) {
+ if (buffer.getLengthInBits() >= totalDataCount * 8) {
+ break;
+ }
+ buffer.put(QRCodeModel.PAD0, 8);
+ if (buffer.getLengthInBits() >= totalDataCount * 8) {
+ break;
+ }
+ buffer.put(QRCodeModel.PAD1, 8);
+ }
+ return QRCodeModel.createBytes(buffer, rsBlocks);
+ };
+ QRCodeModel.createBytes = function(buffer, rsBlocks) {
+ var offset = 0;
+ var maxDcCount = 0;
+ var maxEcCount = 0;
+ var dcdata = new Array(rsBlocks.length);
+ var ecdata = new Array(rsBlocks.length);
+ for (var r = 0; r < rsBlocks.length; r++) {
+ var dcCount = rsBlocks[r].dataCount;
+ var ecCount = rsBlocks[r].totalCount - dcCount;
+ maxDcCount = Math.max(maxDcCount, dcCount);
+ maxEcCount = Math.max(maxEcCount, ecCount);
+ dcdata[r] = new Array(dcCount);
+ for (var i = 0; i < dcdata[r].length; i++) {
+ dcdata[r][i] = 0xff & buffer.buffer[i + offset];
+ }
+ offset += dcCount;
+ var rsPoly = QRUtil.getErrorCorrectPolynomial(ecCount);
+ var rawPoly = new QRPolynomial(dcdata[r], rsPoly.getLength() - 1);
+ var modPoly = rawPoly.mod(rsPoly);
+ ecdata[r] = new Array(rsPoly.getLength() - 1);
+ for (var i = 0; i < ecdata[r].length; i++) {
+ var modIndex = i + modPoly.getLength() - ecdata[r].length;
+ ecdata[r][i] = (modIndex >= 0) ? modPoly.get(modIndex) : 0;
+ }
+ }
+ var totalCodeCount = 0;
+ for (var i = 0; i < rsBlocks.length; i++) {
+ totalCodeCount += rsBlocks[i].totalCount;
+ }
+ var data = new Array(totalCodeCount);
+ var index = 0;
+ for (var i = 0; i < maxDcCount; i++) {
+ for (var r = 0; r < rsBlocks.length; r++) {
+ if (i < dcdata[r].length) {
+ data[index++] = dcdata[r][i];
+ }
+ }
+ }
+ for (var i = 0; i < maxEcCount; i++) {
+ for (var r = 0; r < rsBlocks.length; r++) {
+ if (i < ecdata[r].length) {
+ data[index++] = ecdata[r][i];
+ }
+ }
+ }
+ return data;
+ };
+ var QRMode = {
+ MODE_NUMBER: 1 << 0,
+ MODE_ALPHA_NUM: 1 << 1,
+ MODE_8BIT_BYTE: 1 << 2,
+ MODE_KANJI: 1 << 3
+ };
+ var QRErrorCorrectLevel = {
+ L: 1,
+ M: 0,
+ Q: 3,
+ H: 2
+ };
+ var QRMaskPattern = {
+ PATTERN000: 0,
+ PATTERN001: 1,
+ PATTERN010: 2,
+ PATTERN011: 3,
+ PATTERN100: 4,
+ PATTERN101: 5,
+ PATTERN110: 6,
+ PATTERN111: 7
+ };
+ var QRUtil = {
+ PATTERN_POSITION_TABLE: [
+ [],
+ [6, 18],
+ [6, 22],
+ [6, 26],
+ [6, 30],
+ [6, 34],
+ [6, 22, 38],
+ [6, 24, 42],
+ [6, 26, 46],
+ [6, 28, 50],
+ [6, 30, 54],
+ [6, 32, 58],
+ [6, 34, 62],
+ [6, 26, 46, 66],
+ [6, 26, 48, 70],
+ [6, 26, 50, 74],
+ [6, 30, 54, 78],
+ [6, 30, 56, 82],
+ [6, 30, 58, 86],
+ [6, 34, 62, 90],
+ [6, 28, 50, 72, 94],
+ [6, 26, 50, 74, 98],
+ [6, 30, 54, 78, 102],
+ [6, 28, 54, 80, 106],
+ [6, 32, 58, 84, 110],
+ [6, 30, 58, 86, 114],
+ [6, 34, 62, 90, 118],
+ [6, 26, 50, 74, 98, 122],
+ [6, 30, 54, 78, 102, 126],
+ [6, 26, 52, 78, 104, 130],
+ [6, 30, 56, 82, 108, 134],
+ [6, 34, 60, 86, 112, 138],
+ [6, 30, 58, 86, 114, 142],
+ [6, 34, 62, 90, 118, 146],
+ [6, 30, 54, 78, 102, 126, 150],
+ [6, 24, 50, 76, 102, 128, 154],
+ [6, 28, 54, 80, 106, 132, 158],
+ [6, 32, 58, 84, 110, 136, 162],
+ [6, 26, 54, 82, 110, 138, 166],
+ [6, 30, 58, 86, 114, 142, 170]
+ ],
+ G15: (1 << 10) | (1 << 8) | (1 << 5) | (1 << 4) | (1 << 2) | (1 << 1) | (1 << 0),
+ G18: (1 << 12) | (1 << 11) | (1 << 10) | (1 << 9) | (1 << 8) | (1 << 5) | (1 << 2) | (1 << 0),
+ G15_MASK: (1 << 14) | (1 << 12) | (1 << 10) | (1 << 4) | (1 << 1),
+ getBCHTypeInfo: function(data) {
+ var d = data << 10;
+ while (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G15) >= 0) {
+ d ^= (QRUtil.G15 << (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G15)));
+ }
+ return ((data << 10) | d) ^ QRUtil.G15_MASK;
+ },
+ getBCHTypeNumber: function(data) {
+ var d = data << 12;
+ while (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G18) >= 0) {
+ d ^= (QRUtil.G18 << (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G18)));
+ }
+ return (data << 12) | d;
+ },
+ getBCHDigit: function(data) {
+ var digit = 0;
+ while (data != 0) {
+ digit++;
+ data >>>= 1;
+ }
+ return digit;
+ },
+ getPatternPosition: function(typeNumber) {
+ return QRUtil.PATTERN_POSITION_TABLE[typeNumber - 1];
+ },
+ getMask: function(maskPattern, i, j) {
+ switch (maskPattern) {
+ case QRMaskPattern.PATTERN000:
+ return (i + j) % 2 == 0;
+ case QRMaskPattern.PATTERN001:
+ return i % 2 == 0;
+ case QRMaskPattern.PATTERN010:
+ return j % 3 == 0;
+ case QRMaskPattern.PATTERN011:
+ return (i + j) % 3 == 0;
+ case QRMaskPattern.PATTERN100:
+ return (Math.floor(i / 2) + Math.floor(j / 3)) % 2 == 0;
+ case QRMaskPattern.PATTERN101:
+ return (i * j) % 2 + (i * j) % 3 == 0;
+ case QRMaskPattern.PATTERN110:
+ return ((i * j) % 2 + (i * j) % 3) % 2 == 0;
+ case QRMaskPattern.PATTERN111:
+ return ((i * j) % 3 + (i + j) % 2) % 2 == 0;
+ default:
+ throw new Error("bad maskPattern:" + maskPattern);
+ }
+ },
+ getErrorCorrectPolynomial: function(errorCorrectLength) {
+ var a = new QRPolynomial([1], 0);
+ for (var i = 0; i < errorCorrectLength; i++) {
+ a = a.multiply(new QRPolynomial([1, QRMath.gexp(i)], 0));
+ }
+ return a;
+ },
+ getLengthInBits: function(mode, type) {
+ if (1 <= type && type < 10) {
+ switch (mode) {
+ case QRMode.MODE_NUMBER:
+ return 10;
+ case QRMode.MODE_ALPHA_NUM:
+ return 9;
+ case QRMode.MODE_8BIT_BYTE:
+ return 8;
+ case QRMode.MODE_KANJI:
+ return 8;
+ default:
+ throw new Error("mode:" + mode);
+ }
+ } else if (type < 27) {
+ switch (mode) {
+ case QRMode.MODE_NUMBER:
+ return 12;
+ case QRMode.MODE_ALPHA_NUM:
+ return 11;
+ case QRMode.MODE_8BIT_BYTE:
+ return 16;
+ case QRMode.MODE_KANJI:
+ return 10;
+ default:
+ throw new Error("mode:" + mode);
+ }
+ } else if (type < 41) {
+ switch (mode) {
+ case QRMode.MODE_NUMBER:
+ return 14;
+ case QRMode.MODE_ALPHA_NUM:
+ return 13;
+ case QRMode.MODE_8BIT_BYTE:
+ return 16;
+ case QRMode.MODE_KANJI:
+ return 12;
+ default:
+ throw new Error("mode:" + mode);
+ }
+ } else {
+ throw new Error("type:" + type);
+ }
+ },
+ getLostPoint: function(qrCode) {
+ var moduleCount = qrCode.getModuleCount();
+ var lostPoint = 0;
+ for (var row = 0; row < moduleCount; row++) {
+ for (var col = 0; col < moduleCount; col++) {
+ var sameCount = 0;
+ var dark = qrCode.isDark(row, col);
+ for (var r = -1; r <= 1; r++) {
+ if (row + r < 0 || moduleCount <= row + r) {
+ continue;
+ }
+ for (var c = -1; c <= 1; c++) {
+ if (col + c < 0 || moduleCount <= col + c) {
+ continue;
+ }
+ if (r == 0 && c == 0) {
+ continue;
+ }
+ if (dark == qrCode.isDark(row + r, col + c)) {
+ sameCount++;
+ }
+ }
+ }
+ if (sameCount > 5) {
+ lostPoint += (3 + sameCount - 5);
+ }
+ }
+ }
+ for (var row = 0; row < moduleCount - 1; row++) {
+ for (var col = 0; col < moduleCount - 1; col++) {
+ var count = 0;
+ if (qrCode.isDark(row, col)) count++;
+ if (qrCode.isDark(row + 1, col)) count++;
+ if (qrCode.isDark(row, col + 1)) count++;
+ if (qrCode.isDark(row + 1, col + 1)) count++;
+ if (count == 0 || count == 4) {
+ lostPoint += 3;
+ }
+ }
+ }
+ for (var row = 0; row < moduleCount; row++) {
+ for (var col = 0; col < moduleCount - 6; col++) {
+ if (qrCode.isDark(row, col) && !qrCode.isDark(row, col + 1) && qrCode.isDark(row, col + 2) && qrCode.isDark(row,
+ col + 3) && qrCode.isDark(row, col + 4) && !qrCode.isDark(row, col + 5) && qrCode.isDark(row, col + 6)) {
+ lostPoint += 40;
+ }
+ }
+ }
+ for (var col = 0; col < moduleCount; col++) {
+ for (var row = 0; row < moduleCount - 6; row++) {
+ if (qrCode.isDark(row, col) && !qrCode.isDark(row + 1, col) && qrCode.isDark(row + 2, col) && qrCode.isDark(row +
+ 3, col) && qrCode.isDark(row + 4, col) && !qrCode.isDark(row + 5, col) && qrCode.isDark(row + 6, col)) {
+ lostPoint += 40;
+ }
+ }
+ }
+ var darkCount = 0;
+ for (var col = 0; col < moduleCount; col++) {
+ for (var row = 0; row < moduleCount; row++) {
+ if (qrCode.isDark(row, col)) {
+ darkCount++;
+ }
+ }
+ }
+ var ratio = Math.abs(100 * darkCount / moduleCount / moduleCount - 50) / 5;
+ lostPoint += ratio * 10;
+ return lostPoint;
+ }
+ };
+ var QRMath = {
+ glog: function(n) {
+ if (n < 1) {
+ throw new Error("glog(" + n + ")");
+ }
+ return QRMath.LOG_TABLE[n];
+ },
+ gexp: function(n) {
+ while (n < 0) {
+ n += 255;
+ }
+ while (n >= 256) {
+ n -= 255;
+ }
+ return QRMath.EXP_TABLE[n];
+ },
+ EXP_TABLE: new Array(256),
+ LOG_TABLE: new Array(256)
+ };
+ for (var i = 0; i < 8; i++) {
+ QRMath.EXP_TABLE[i] = 1 << i;
+ }
+ for (var i = 8; i < 256; i++) {
+ QRMath.EXP_TABLE[i] = QRMath.EXP_TABLE[i - 4] ^ QRMath.EXP_TABLE[i - 5] ^ QRMath.EXP_TABLE[i - 6] ^ QRMath.EXP_TABLE[
+ i - 8];
+ }
+ for (var i = 0; i < 255; i++) {
+ QRMath.LOG_TABLE[QRMath.EXP_TABLE[i]] = i;
+ }
+
+ function QRPolynomial(num, shift) {
+ if (num.length == undefined) {
+ throw new Error(num.length + "/" + shift);
+ }
+ var offset = 0;
+ while (offset < num.length && num[offset] == 0) {
+ offset++;
+ }
+ this.num = new Array(num.length - offset + shift);
+ for (var i = 0; i < num.length - offset; i++) {
+ this.num[i] = num[i + offset];
+ }
+ }
+ QRPolynomial.prototype = {
+ get: function(index) {
+ return this.num[index];
+ },
+ getLength: function() {
+ return this.num.length;
+ },
+ multiply: function(e) {
+ var num = new Array(this.getLength() + e.getLength() - 1);
+ for (var i = 0; i < this.getLength(); i++) {
+ for (var j = 0; j < e.getLength(); j++) {
+ num[i + j] ^= QRMath.gexp(QRMath.glog(this.get(i)) + QRMath.glog(e.get(j)));
+ }
+ }
+ return new QRPolynomial(num, 0);
+ },
+ mod: function(e) {
+ if (this.getLength() - e.getLength() < 0) {
+ return this;
+ }
+ var ratio = QRMath.glog(this.get(0)) - QRMath.glog(e.get(0));
+ var num = new Array(this.getLength());
+ for (var i = 0; i < this.getLength(); i++) {
+ num[i] = this.get(i);
+ }
+ for (var i = 0; i < e.getLength(); i++) {
+ num[i] ^= QRMath.gexp(QRMath.glog(e.get(i)) + ratio);
+ }
+ return new QRPolynomial(num, 0).mod(e);
+ }
+ };
+
+ function QRRSBlock(totalCount, dataCount) {
+ this.totalCount = totalCount;
+ this.dataCount = dataCount;
+ }
+ QRRSBlock.RS_BLOCK_TABLE = [
+ [1, 26, 19],
+ [1, 26, 16],
+ [1, 26, 13],
+ [1, 26, 9],
+ [1, 44, 34],
+ [1, 44, 28],
+ [1, 44, 22],
+ [1, 44, 16],
+ [1, 70, 55],
+ [1, 70, 44],
+ [2, 35, 17],
+ [2, 35, 13],
+ [1, 100, 80],
+ [2, 50, 32],
+ [2, 50, 24],
+ [4, 25, 9],
+ [1, 134, 108],
+ [2, 67, 43],
+ [2, 33, 15, 2, 34, 16],
+ [2, 33, 11, 2, 34, 12],
+ [2, 86, 68],
+ [4, 43, 27],
+ [4, 43, 19],
+ [4, 43, 15],
+ [2, 98, 78],
+ [4, 49, 31],
+ [2, 32, 14, 4, 33, 15],
+ [4, 39, 13, 1, 40, 14],
+ [2, 121, 97],
+ [2, 60, 38, 2, 61, 39],
+ [4, 40, 18, 2, 41, 19],
+ [4, 40, 14, 2, 41, 15],
+ [2, 146, 116],
+ [3, 58, 36, 2, 59, 37],
+ [4, 36, 16, 4, 37, 17],
+ [4, 36, 12, 4, 37, 13],
+ [2, 86, 68, 2, 87, 69],
+ [4, 69, 43, 1, 70, 44],
+ [6, 43, 19, 2, 44, 20],
+ [6, 43, 15, 2, 44, 16],
+ [4, 101, 81],
+ [1, 80, 50, 4, 81, 51],
+ [4, 50, 22, 4, 51, 23],
+ [3, 36, 12, 8, 37, 13],
+ [2, 116, 92, 2, 117, 93],
+ [6, 58, 36, 2, 59, 37],
+ [4, 46, 20, 6, 47, 21],
+ [7, 42, 14, 4, 43, 15],
+ [4, 133, 107],
+ [8, 59, 37, 1, 60, 38],
+ [8, 44, 20, 4, 45, 21],
+ [12, 33, 11, 4, 34, 12],
+ [3, 145, 115, 1, 146, 116],
+ [4, 64, 40, 5, 65, 41],
+ [11, 36, 16, 5, 37, 17],
+ [11, 36, 12, 5, 37, 13],
+ [5, 109, 87, 1, 110, 88],
+ [5, 65, 41, 5, 66, 42],
+ [5, 54, 24, 7, 55, 25],
+ [11, 36, 12],
+ [5, 122, 98, 1, 123, 99],
+ [7, 73, 45, 3, 74, 46],
+ [15, 43, 19, 2, 44, 20],
+ [3, 45, 15, 13, 46, 16],
+ [1, 135, 107, 5, 136, 108],
+ [10, 74, 46, 1, 75, 47],
+ [1, 50, 22, 15, 51, 23],
+ [2, 42, 14, 17, 43, 15],
+ [5, 150, 120, 1, 151, 121],
+ [9, 69, 43, 4, 70, 44],
+ [17, 50, 22, 1, 51, 23],
+ [2, 42, 14, 19, 43, 15],
+ [3, 141, 113, 4, 142, 114],
+ [3, 70, 44, 11, 71, 45],
+ [17, 47, 21, 4, 48, 22],
+ [9, 39, 13, 16, 40, 14],
+ [3, 135, 107, 5, 136, 108],
+ [3, 67, 41, 13, 68, 42],
+ [15, 54, 24, 5, 55, 25],
+ [15, 43, 15, 10, 44, 16],
+ [4, 144, 116, 4, 145, 117],
+ [17, 68, 42],
+ [17, 50, 22, 6, 51, 23],
+ [19, 46, 16, 6, 47, 17],
+ [2, 139, 111, 7, 140, 112],
+ [17, 74, 46],
+ [7, 54, 24, 16, 55, 25],
+ [34, 37, 13],
+ [4, 151, 121, 5, 152, 122],
+ [4, 75, 47, 14, 76, 48],
+ [11, 54, 24, 14, 55, 25],
+ [16, 45, 15, 14, 46, 16],
+ [6, 147, 117, 4, 148, 118],
+ [6, 73, 45, 14, 74, 46],
+ [11, 54, 24, 16, 55, 25],
+ [30, 46, 16, 2, 47, 17],
+ [8, 132, 106, 4, 133, 107],
+ [8, 75, 47, 13, 76, 48],
+ [7, 54, 24, 22, 55, 25],
+ [22, 45, 15, 13, 46, 16],
+ [10, 142, 114, 2, 143, 115],
+ [19, 74, 46, 4, 75, 47],
+ [28, 50, 22, 6, 51, 23],
+ [33, 46, 16, 4, 47, 17],
+ [8, 152, 122, 4, 153, 123],
+ [22, 73, 45, 3, 74, 46],
+ [8, 53, 23, 26, 54, 24],
+ [12, 45, 15, 28, 46, 16],
+ [3, 147, 117, 10, 148, 118],
+ [3, 73, 45, 23, 74, 46],
+ [4, 54, 24, 31, 55, 25],
+ [11, 45, 15, 31, 46, 16],
+ [7, 146, 116, 7, 147, 117],
+ [21, 73, 45, 7, 74, 46],
+ [1, 53, 23, 37, 54, 24],
+ [19, 45, 15, 26, 46, 16],
+ [5, 145, 115, 10, 146, 116],
+ [19, 75, 47, 10, 76, 48],
+ [15, 54, 24, 25, 55, 25],
+ [23, 45, 15, 25, 46, 16],
+ [13, 145, 115, 3, 146, 116],
+ [2, 74, 46, 29, 75, 47],
+ [42, 54, 24, 1, 55, 25],
+ [23, 45, 15, 28, 46, 16],
+ [17, 145, 115],
+ [10, 74, 46, 23, 75, 47],
+ [10, 54, 24, 35, 55, 25],
+ [19, 45, 15, 35, 46, 16],
+ [17, 145, 115, 1, 146, 116],
+ [14, 74, 46, 21, 75, 47],
+ [29, 54, 24, 19, 55, 25],
+ [11, 45, 15, 46, 46, 16],
+ [13, 145, 115, 6, 146, 116],
+ [14, 74, 46, 23, 75, 47],
+ [44, 54, 24, 7, 55, 25],
+ [59, 46, 16, 1, 47, 17],
+ [12, 151, 121, 7, 152, 122],
+ [12, 75, 47, 26, 76, 48],
+ [39, 54, 24, 14, 55, 25],
+ [22, 45, 15, 41, 46, 16],
+ [6, 151, 121, 14, 152, 122],
+ [6, 75, 47, 34, 76, 48],
+ [46, 54, 24, 10, 55, 25],
+ [2, 45, 15, 64, 46, 16],
+ [17, 152, 122, 4, 153, 123],
+ [29, 74, 46, 14, 75, 47],
+ [49, 54, 24, 10, 55, 25],
+ [24, 45, 15, 46, 46, 16],
+ [4, 152, 122, 18, 153, 123],
+ [13, 74, 46, 32, 75, 47],
+ [48, 54, 24, 14, 55, 25],
+ [42, 45, 15, 32, 46, 16],
+ [20, 147, 117, 4, 148, 118],
+ [40, 75, 47, 7, 76, 48],
+ [43, 54, 24, 22, 55, 25],
+ [10, 45, 15, 67, 46, 16],
+ [19, 148, 118, 6, 149, 119],
+ [18, 75, 47, 31, 76, 48],
+ [34, 54, 24, 34, 55, 25],
+ [20, 45, 15, 61, 46, 16]
+ ];
+ QRRSBlock.getRSBlocks = function(typeNumber, errorCorrectLevel) {
+ var rsBlock = QRRSBlock.getRsBlockTable(typeNumber, errorCorrectLevel);
+ if (rsBlock == undefined) {
+ throw new Error("bad rs block @ typeNumber:" + typeNumber + "/errorCorrectLevel:" + errorCorrectLevel);
+ }
+ var length = rsBlock.length / 3;
+ var list = [];
+ for (var i = 0; i < length; i++) {
+ var count = rsBlock[i * 3 + 0];
+ var totalCount = rsBlock[i * 3 + 1];
+ var dataCount = rsBlock[i * 3 + 2];
+ for (var j = 0; j < count; j++) {
+ list.push(new QRRSBlock(totalCount, dataCount));
+ }
+ }
+ return list;
+ };
+ QRRSBlock.getRsBlockTable = function(typeNumber, errorCorrectLevel) {
+ switch (errorCorrectLevel) {
+ case QRErrorCorrectLevel.L:
+ return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 0];
+ case QRErrorCorrectLevel.M:
+ return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 1];
+ case QRErrorCorrectLevel.Q:
+ return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 2];
+ case QRErrorCorrectLevel.H:
+ return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 3];
+ default:
+ return undefined;
+ }
+ };
+
+ function QRBitBuffer() {
+ this.buffer = [];
+ this.length = 0;
+ }
+ QRBitBuffer.prototype = {
+ get: function(index) {
+ var bufIndex = Math.floor(index / 8);
+ return ((this.buffer[bufIndex] >>> (7 - index % 8)) & 1) == 1;
+ },
+ put: function(num, length) {
+ for (var i = 0; i < length; i++) {
+ this.putBit(((num >>> (length - i - 1)) & 1) == 1);
+ }
+ },
+ getLengthInBits: function() {
+ return this.length;
+ },
+ putBit: function(bit) {
+ var bufIndex = Math.floor(this.length / 8);
+ if (this.buffer.length <= bufIndex) {
+ this.buffer.push(0);
+ }
+ if (bit) {
+ this.buffer[bufIndex] |= (0x80 >>> (this.length % 8));
+ }
+ this.length++;
+ }
+ };
+ var QRCodeLimitLength = [
+ [17, 14, 11, 7],
+ [32, 26, 20, 14],
+ [53, 42, 32, 24],
+ [78, 62, 46, 34],
+ [106, 84, 60, 44],
+ [134, 106, 74, 58],
+ [154, 122, 86, 64],
+ [192, 152, 108, 84],
+ [230, 180, 130, 98],
+ [271, 213, 151, 119],
+ [321, 251, 177, 137],
+ [367, 287, 203, 155],
+ [425, 331, 241, 177],
+ [458, 362, 258, 194],
+ [520, 412, 292, 220],
+ [586, 450, 322, 250],
+ [644, 504, 364, 280],
+ [718, 560, 394, 310],
+ [792, 624, 442, 338],
+ [858, 666, 482, 382],
+ [929, 711, 509, 403],
+ [1003, 779, 565, 439],
+ [1091, 857, 611, 461],
+ [1171, 911, 661, 511],
+ [1273, 997, 715, 535],
+ [1367, 1059, 751, 593],
+ [1465, 1125, 805, 625],
+ [1528, 1190, 868, 658],
+ [1628, 1264, 908, 698],
+ [1732, 1370, 982, 742],
+ [1840, 1452, 1030, 790],
+ [1952, 1538, 1112, 842],
+ [2068, 1628, 1168, 898],
+ [2188, 1722, 1228, 958],
+ [2303, 1809, 1283, 983],
+ [2431, 1911, 1351, 1051],
+ [2563, 1989, 1423, 1093],
+ [2699, 2099, 1499, 1139],
+ [2809, 2213, 1579, 1219],
+ [2953, 2331, 1663, 1273]
+ ];
+
+ // QRCode object
+ QRCode = function(canvasId, vOption) {
+ this._htOption = {
+ width: 256,
+ height: 256,
+ typeNumber: 4,
+ colorDark: "#000000",
+ colorLight: "#ffffff",
+ correctLevel: QRErrorCorrectLevel.H
+ };
+
+ if (typeof vOption === 'string') {
+ vOption = {
+ text: vOption
+ };
+ }
+
+ // Overwrites options
+ if (vOption) {
+ for (var i in vOption) {
+ this._htOption[i] = vOption[i];
+ }
+ }
+
+ this._oQRCode = null;
+ this.canvasId = canvasId
+
+ if (this._htOption.text && this.canvasId) {
+ this.makeCode(this._htOption.text);
+ }
+ };
+
+ QRCode.prototype.makeCode = function(sText) {
+ this._oQRCode = new QRCodeModel(_getTypeNumber(sText, this._htOption.correctLevel), this._htOption.correctLevel);
+ this._oQRCode.addData(sText);
+ this._oQRCode.make();
+ this.makeImage();
+ };
+
+ QRCode.prototype.makeImage = function() {
+ var _oContext
+ if (this._htOption.usingIn) {
+ _oContext = uni.createCanvasContext(this.canvasId, this._htOption.usingIn)
+ } else {
+ _oContext = uni.createCanvasContext(this.canvasId)
+ }
+ var _htOption = this._htOption;
+ var oQRCode = this._oQRCode
+
+ var nCount = oQRCode.getModuleCount();
+ var nWidth = _htOption.padding ? (_htOption.width - 2 * _htOption.padding) / nCount : _htOption.width / nCount;
+ var nHeight = _htOption.padding ? (_htOption.height - 2 * _htOption.padding) / nCount : _htOption.height / nCount;
+ var nRoundedHeight = Math.round(nHeight);
+ var nRoundedWidth = Math.round(nWidth);
+
+ if (_htOption.image && _htOption.image != '') {
+ _oContext.drawImage(_htOption.image, 0, 0, _htOption.width, _htOption.height)
+ }
+ _oContext.setFillStyle('#fff')
+ _oContext.fillRect(0, 0, _htOption.width, _htOption.height)
+ _oContext.save()
+ for (var row = 0; row < nCount; row++) {
+ for (var col = 0; col < nCount; col++) {
+ var bIsDark = oQRCode.isDark(row, col);
+ var nLeft = _htOption.padding ? col * nWidth + _htOption.padding : col * nWidth;
+ var nTop = _htOption.padding ? row * nHeight + _htOption.padding : row * nHeight;
+ _oContext.setStrokeStyle(bIsDark ? _htOption.colorDark : _htOption.colorLight)
+ // _oContext.setStrokeStyle('red')
+ _oContext.setLineWidth(1)
+ _oContext.setFillStyle(bIsDark ? _htOption.colorDark : _htOption.colorLight)
+ // _oContext.setFillStyle('red')
+ // if (bIsDark) {
+ _oContext.fillRect(nLeft, nTop, nWidth, nHeight);
+ // }
+
+ // 안티 앨리어싱 방지 처리
+ // if (bIsDark) {
+ _oContext.strokeRect(
+ Math.floor(nLeft) + 0.5,
+ Math.floor(nTop) + 0.5,
+ nRoundedHeight
+ );
+
+ _oContext.strokeRect(
+ Math.ceil(nLeft) - 0.5,
+ Math.ceil(nTop) - 0.5,
+ nRoundedWidth,
+ nRoundedHeight
+ );
+ // }
+ // _oContext.fillRect(
+ // Math.floor(nLeft) + 0.5,
+ // Math.floor(nTop) + 0.5,
+ // nRoundedWidth,
+ // nRoundedHeight
+ // );
+ // _oContext.fillRect(
+ // Math.ceil(nLeft) - 0.5,
+ // Math.ceil(nTop) - 0.5,
+ // nRoundedWidth,
+ // nRoundedHeight
+ // );
+ // _oContext.clearRect(
+ // Math.floor(nLeft) + 0.5,
+ // Math.floor(nTop) + 0.5,
+ // nRoundedWidth,
+ // nRoundedHeight
+ // );
+ // _oContext.clearRect(
+ // Math.ceil(nLeft) - 0.5,
+ // Math.ceil(nTop) - 0.5,
+ // nRoundedWidth,
+ // nRoundedHeight
+ // );
+ }
+ }
+
+ _oContext.draw(false, () => {
+ setTimeout(() => {
+ this.exportImage()
+ }, 800)
+ })
+ };
+
+ // 保存为图片,将临时路径传给回调
+ QRCode.prototype.exportImage = function(callback) {
+ if (this._htOption.callback && typeof this._htOption.callback === 'function') {
+ uni.canvasToTempFilePath({
+ x: 0,
+ y: 0,
+ width: this._htOption.width,
+ height: this._htOption.height,
+ destWidth: this._htOption.width,
+ destHeight: this._htOption.height,
+ canvasId: this.canvasId,
+ success: (res) => {
+ console.log(res)
+ this._htOption.callback({
+ path: res.tempFilePath
+ })
+ }
+ },this._htOption.usingIn)
+ }
+ }
+
+ QRCode.CorrectLevel = QRErrorCorrectLevel;
+})();
+
+module.exports = QRCode
diff --git a/components/utils/gwpingjia.vue b/components/utils/gwpingjia.vue
new file mode 100644
index 0000000..010fd0d
--- /dev/null
+++ b/components/utils/gwpingjia.vue
@@ -0,0 +1,180 @@
+
+
+
+ 游友点评
+
+ {{totalNumber}}条评论
+
+
+
+
+
+
+
+ {{el.name}}
+ {{el.avg}}分
+
+ {{el.createTime}}
+
+
+ {{el.des}}
+
+
+
+ 查看全部评价
+
+
+
+
+
+
+
diff --git a/components/utils/request.js b/components/utils/request.js
new file mode 100644
index 0000000..f00a821
--- /dev/null
+++ b/components/utils/request.js
@@ -0,0 +1,419 @@
+//!!!!!!!!!此处不该这样写,只是临时方案。参照纯函数编程以及ES6的Promise
+
+//封装的网络请求方法
+var wxurl = 'https://cs.tour-ma.com/';
+// var wxurl = '';
+// var wxurl = 'https://cs.tour-ma.com/';
+// var wxurl = 'http://120.92.133.72/'
+var wxtitle = '';
+
+function loginUser(para, callbs, callbf) {
+ uni.login({ //1.请求微信登录
+ provider: 'weixin',
+ success: function(res) {
+ //通过微信code,从服务器请求session
+ var url = 'minapps/login.jspx';
+ var code = res.code;
+ uni.request({
+ url: wxurl + url, //拿code请求服务器
+ data: {
+ code: code,
+ },
+ success: function(res) {
+ if (res.data.status == 200) {
+ typeof callbs == "function" && callbs(res); //获取key成功
+ //getUser(); //回调微信用户
+ } else if (res.data.status == 2002) {
+ //无用户状态,跳转绑定页面
+ } else {
+ var error = {
+ msg: '与服务器换取session失败,请稍后重试!jy',
+ errormsg: res
+ }
+ typeof callbf == "function" && callbf(error); //获取key失败
+ }
+ },
+ fail: function(e) {
+ var error = {
+ msg: '与服务器换取session失败。请稍后重试!jy',
+ errormsg: e
+ }
+ typeof callbf == "function" && callbf(error); //获取key失败
+ }
+ })
+ //通过微信code,从服务器请求session。 end//
+ }
+ })
+}
+
+function httpPostai(that, murl, mpara, callbs, callbf) {
+ // #ifdef MP-WEIXIN
+ mpara.wx = 'wx';
+ // #endif
+ uni.request({
+ url: murl, //用户信息交换接口
+ method: 'POST',
+ data: JSON.stringify(mpara),
+ header: {
+ "Content-Type": "text/html;charset=UTF-8"
+ },
+ success: function(res) {
+ if (res.data.status == 200) {
+ typeof callbs == "function" && callbs(res);
+ }
+ },
+ fail: function(e) {
+ var error = {
+ msg: '获取数据失败,请稍后重试!jy',
+ errormsg: e
+ }
+ typeof callbf == "function" && callbf(error);
+ }
+ });
+}
+
+//post请求,参数分别为:当前页面、url、参数对象、成功回调、失败回调
+function httpPost(that, murl, mpara, callbs, callbf) {
+ var pages = getCurrentPages();
+ if(pages.length>0){
+ var page = pages[pages.length - 1].route;
+ }
+ //此时key应该有值,无值说明用户未给权限
+ var key = '';
+ try {
+ key = uni.getStorageSync('session');
+ } catch (e) {
+
+ }
+ console.log('获取key'+key)
+ mpara.wx = 'wx';
+ mpara.lng=that.$store.getters.lon==''?0:that.$store.getters.lon;
+ mpara.lat=that.$store.getters.lat==''?0:that.$store.getters.lat;
+ uni.request({
+ url: wxurl + murl, //用户信息交换接口
+ method: 'POST',
+ data: JSON.stringify(mpara),
+ header: {
+ "Content-Type": "text/html;charset=UTF-8",
+ 'Cookie': 'WXSESSIONID=' + key
+ },
+ success: function(res) {
+ if (res.data.status == 200) {
+ typeof callbs == "function" && callbs(res);
+ } else if (res.data.status == 2001) {
+ //未登录状态
+ uni.removeStorageSync('session')
+ try {
+ if (page == 'pages/my/my') {
+ typeof callbs == "function" && callbs(res);
+ return
+ }
+ uni.showModal({
+ title: '',
+ content: '未登录,是否登录',
+ showCancel: true,
+ cancelText: '否',
+ confirmText: '是',
+ success: res => {
+ if (res.confirm) {
+ uni.navigateTo({
+ url: '/pages/login/index'
+ });
+ } else {
+ uni.navigateBack({
+ delta: 1
+ });
+ }
+ }
+ });
+ } catch (e) {
+ var error = {
+ msg: '删除KEY失败,请稍后重试!wx',
+ errormsg: e
+ }
+ typeof callbf == "function" && callbf(error);
+ }
+ } else if (res.data.status == 2002) {
+ //无用户状态,跳转绑定页面
+ //uni.redirectTo({ url: "/pages/user/mobile/mobile" });
+ } else {
+ var error = {
+ msg: 'jy出错:' + res.data.message,
+ errormsg: res
+ }
+ typeof callbs == "function" && callbs(res);
+ }
+ },
+ fail: function(e) {
+ var error = {
+ msg: '获取数据失败,请稍后重试!jy',
+ errormsg: e
+ }
+ typeof callbf == "function" && callbf(error);
+ }
+ });
+
+}
+
+//post请求,参数分别为:当前页面、url、参数对象、成功回调、失败回调
+function httpPostxin(that, murl, mpara, callbs, callbf) {
+ var pages = getCurrentPages();
+ if(pages.length>0){
+ var page = pages[pages.length - 1].route;
+ }
+ //此时key应该有值,无值说明用户未给权限
+ var key = '';
+ try {
+ key = uni.getStorageSync('session');
+ } catch (e) {
+
+ }
+ console.log('获取key'+key)
+ // mpara.wx = 'wx';
+ // mpara.lng=that.$store.getters.lon==''?0:that.$store.getters.lon;
+ // mpara.lat=that.$store.getters.lat==''?0:that.$store.getters.lat;
+ uni.request({
+ url: murl, //用户信息交换接口
+ method: 'POST',
+ data: JSON.stringify(mpara),
+ header: {
+ "Content-Type": "application/json;charset=UTF-8"
+ // 'Cookie': 'WXSESSIONID=' + key
+ },
+ success: function(res) {
+ if (res.data.status == 200) {
+ typeof callbs == "function" && callbs(res);
+ } else if (res.data.status == 2001) {
+ //未登录状态
+ uni.removeStorageSync('session')
+ try {
+ if (page == 'pages/my/my') {
+ typeof callbs == "function" && callbs(res);
+ return
+ }
+ uni.showModal({
+ title: '',
+ content: '未登录,是否登录',
+ showCancel: true,
+ cancelText: '否',
+ confirmText: '是',
+ success: res => {
+ if (res.confirm) {
+ uni.navigateTo({
+ url: '/pages/login/index'
+ });
+ } else {
+ uni.navigateBack({
+ delta: 1
+ });
+ }
+ }
+ });
+ } catch (e) {
+ var error = {
+ msg: '删除KEY失败,请稍后重试!wx',
+ errormsg: e
+ }
+ typeof callbf == "function" && callbf(error);
+ }
+ } else if (res.data.status == 2002) {
+ //无用户状态,跳转绑定页面
+ //uni.redirectTo({ url: "/pages/user/mobile/mobile" });
+ } else {
+ var error = {
+ msg: 'jy出错:' + res.data.message,
+ errormsg: res
+ }
+ typeof callbs == "function" && callbs(res);
+ }
+ },
+ fail: function(e) {
+ var error = {
+ msg: '获取数据失败,请稍后重试!jy',
+ errormsg: e
+ }
+ typeof callbf == "function" && callbf(error);
+ }
+ });
+
+}
+
+//post请求,参数分别为:当前页面、url、参数对象、成功回调、失败回调
+function httpGet(that, murl, mpara, callbs, callbf) {
+ var key = '';
+ try {
+ key = uni.getStorageSync('session');
+ } catch (e) {
+ console.log(e);
+ }
+ // #ifndef APP-PLUS
+ mpara.wx = 'wx';
+ // #endif
+ uni.request({
+ url: wxurl + murl, //用户信息交换接口
+ method: 'POST',
+ data: JSON.stringify(mpara),
+ header: {
+ "Content-Type": "text/html;charset=UTF-8",
+ 'Cookie': 'WXSESSIONID=' + key
+ },
+ success: function(res) {
+ if (res.data.status == 200) {
+ typeof callbs == "function" && callbs(res);
+ } else {
+ var error = {
+ msg: 'jy出错:' + res.data.message,
+ errormsg: res
+ }
+ typeof callbs == "function" && callbs(res);
+ }
+ },
+ fail: function(e) {
+ var error = {
+ msg: '获取数据失败,请稍后重试!jy',
+ errormsg: e
+ }
+ typeof callbf == "function" && callbf(error);
+ }
+ });
+}
+//post请求,参数分别为:当前页面、url、参数对象、成功回调、失败回调
+function httpGetxin(that, murl, mpara, callbs, callbf) {
+ var key = '';
+ try {
+ key = uni.getStorageSync('session');
+ } catch (e) {
+ console.log(e);
+ }
+ // #ifndef APP-PLUS
+ mpara.wx = 'wx';
+ // #endif
+ uni.request({
+ url: murl, //用户信息交换接口
+ method: 'GET',
+ data: JSON.stringify(mpara),
+ header: {
+ "Content-Type": "text/html;charset=UTF-8",
+ 'Cookie': 'WXSESSIONID=' + key
+ },
+ success: function(res) {
+ if (res.data.status == 200) {
+ typeof callbs == "function" && callbs(res);
+ } else {
+ var error = {
+ msg: 'jy出错:' + res.data.message,
+ errormsg: res
+ }
+ typeof callbs == "function" && callbs(res);
+ }
+ },
+ fail: function(e) {
+ var error = {
+ msg: '获取数据失败,请稍后重试!jy',
+ errormsg: e
+ }
+ typeof callbf == "function" && callbf(error);
+ }
+ });
+}
+function httpGetg(that, murl, mpara, callbs, callbf) {
+ var url = wxurl + murl;
+ var len = 0;
+ for (var key in mpara) {
+ if (len == 0) {
+ url += '?' + key + '=' + mpara[key];
+ } else {
+ url += '&' + key + '=' + mpara[key];
+ }
+ len++
+ }
+ uni.request({
+ url: url, //用户信息交换接口
+ method: 'GET',
+ header: {
+ "Content-Type": "text/html;charset=UTF-8"
+ },
+ success: function(res) {
+ if (res.data.status == 200) {
+ typeof callbs == "function" && callbs(res);
+ } else {
+ var error = {
+ msg: 'jy出错:' + res.data.message,
+ errormsg: res
+ }
+ typeof callbs == "function" && callbs(res);
+ }
+ },
+ fail: function(e) {
+ var error = {
+ msg: '获取数据失败,请稍后重试!jy',
+ errormsg: e
+ }
+ typeof callbf == "function" && callbf(error);
+ }
+ });
+}
+
+function httpGejqr(that, murl, mpara, callbs, callbf) {
+ var url = wxurl + murl;
+ uni.request({
+ url: url, //用户信息交换接口
+ method: 'GET',
+ header: {
+ "Content-Type": "text/html;charset=UTF-8"
+ },
+ success: function(res) {
+ if (res.data.status == 200) {
+ typeof callbs == "function" && callbs(res);
+ } else {
+ var error = {
+ msg: 'jy出错:' + res.data.message,
+ errormsg: res
+ }
+ typeof callbs == "function" && callbs(res);
+ }
+ },
+ fail: function(e) {
+ var error = {
+ msg: '获取数据失败,请稍后重试!jy',
+ errormsg: e
+ }
+ typeof callbf == "function" && callbf(error);
+ }
+ });
+}
+
+function getWeek(date) {
+ var week;
+ if (date.getDay() == 0) week = "周日"
+ if (date.getDay() == 1) week = "周一"
+ if (date.getDay() == 2) week = "周二"
+ if (date.getDay() == 3) week = "周三"
+ if (date.getDay() == 4) week = "周四"
+ if (date.getDay() == 5) week = "周五"
+ if (date.getDay() == 6) week = "周六"
+ return week;
+}
+// 计算两地距离
+function distance(la1, lo1, la2, lo2) {
+ var La1 = la1 * Math.PI / 180.0;
+ var La2 = la2 * Math.PI / 180.0;
+ var La3 = La1 - La2;
+ var Lb3 = lo1 * Math.PI / 180.0 - lo2 * Math.PI / 180.0;
+ var s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(La3 / 2), 2) + Math.cos(La1) * Math.cos(La2) * Math.pow(Math.sin(
+ Lb3 / 2), 2)));
+ s = s * 6378.137;
+ s = Math.round(s * 10000) / 10000;
+ s = s.toFixed(2);
+ return s;
+}
+module.exports.httpGetg = httpGetg;
+module.exports.loginUser = loginUser;
+module.exports.httpPost = httpPost;
+module.exports.httpGet = httpGet;
+module.exports.httpPostai = httpPostai;
+module.exports.httpGejqr = httpGejqr;
+module.exports.getWeek = getWeek;
+module.exports.distance=distance;
+module.exports.httpGetxin = httpGetxin;
+module.exports.httpPostxin = httpPostxin;
\ No newline at end of file
diff --git a/components/utils/u-charts.js b/components/utils/u-charts.js
new file mode 100644
index 0000000..06d190b
--- /dev/null
+++ b/components/utils/u-charts.js
@@ -0,0 +1,5662 @@
+/*
+ * uCharts v1.9.4.20200331
+ * uni-app平台高性能跨全端图表,支持H5、APP、小程序(微信/支付宝/百度/头条/QQ/360)
+ * Copyright (c) 2019 QIUN秋云 https://www.ucharts.cn All rights reserved.
+ * Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
+ *
+ * uCharts官方网站
+ * https://www.uCharts.cn
+ *
+ * 开源地址:
+ * https://gitee.com/uCharts/uCharts
+ *
+ * uni-app插件市场地址:
+ * http://ext.dcloud.net.cn/plugin?id=271
+ *
+ */
+
+'use strict';
+
+var config = {
+ yAxisWidth: 15,
+ yAxisSplit: 5,
+ xAxisHeight: 15,
+ xAxisLineHeight: 15,
+ legendHeight: 15,
+ yAxisTitleWidth: 15,
+ padding: [10, 10, 10, 10],
+ pixelRatio: 1,
+ rotate: false,
+ columePadding: 3,
+ fontSize: 13,
+ //dataPointShape: ['diamond', 'circle', 'triangle', 'rect'],
+ dataPointShape: ['circle', 'circle', 'circle', 'circle'],
+ colors: ['#1890ff', '#2fc25b', '#facc14', '#f04864', '#8543e0', '#90ed7d'],
+ pieChartLinePadding: 15,
+ pieChartTextPadding: 5,
+ xAxisTextPadding: 3,
+ titleColor: '#333333',
+ titleFontSize: 20,
+ subtitleColor: '#999999',
+ subtitleFontSize: 15,
+ toolTipPadding: 3,
+ toolTipBackground: '#000000',
+ toolTipOpacity: 0.7,
+ toolTipLineHeight: 20,
+ radarLabelTextMargin: 15,
+ gaugeLabelTextMargin: 15
+};
+
+let assign = function (target, ...varArgs) {
+ if (target == null) {
+ throw new TypeError('Cannot convert undefined or null to object');
+ }
+ if (!varArgs || varArgs.length <= 0) {
+ return target;
+ }
+ // 深度合并对象
+ function deepAssign(obj1, obj2) {
+ for (let key in obj2) {
+ obj1[key] = obj1[key] && obj1[key].toString() === "[object Object]" ?
+ deepAssign(obj1[key], obj2[key]) : obj1[key] = obj2[key];
+ }
+ return obj1;
+ }
+
+ varArgs.forEach(val => {
+ target = deepAssign(target, val);
+ });
+ return target;
+};
+
+var util = {
+ toFixed: function toFixed(num, limit) {
+ limit = limit || 2;
+ if (this.isFloat(num)) {
+ num = num.toFixed(limit);
+ }
+ return num;
+ },
+ isFloat: function isFloat(num) {
+ return num % 1 !== 0;
+ },
+ approximatelyEqual: function approximatelyEqual(num1, num2) {
+ return Math.abs(num1 - num2) < 1e-10;
+ },
+ isSameSign: function isSameSign(num1, num2) {
+ return Math.abs(num1) === num1 && Math.abs(num2) === num2 || Math.abs(num1) !== num1 && Math.abs(num2) !== num2;
+ },
+ isSameXCoordinateArea: function isSameXCoordinateArea(p1, p2) {
+ return this.isSameSign(p1.x, p2.x);
+ },
+ isCollision: function isCollision(obj1, obj2) {
+ obj1.end = {};
+ obj1.end.x = obj1.start.x + obj1.width;
+ obj1.end.y = obj1.start.y - obj1.height;
+ obj2.end = {};
+ obj2.end.x = obj2.start.x + obj2.width;
+ obj2.end.y = obj2.start.y - obj2.height;
+ var flag = obj2.start.x > obj1.end.x || obj2.end.x < obj1.start.x || obj2.end.y > obj1.start.y || obj2.start.y < obj1.end.y;
+ return !flag;
+ }
+};
+
+//兼容H5点击事件
+function getH5Offset(e) {
+ e.mp = {
+ changedTouches: []
+ };
+ e.mp.changedTouches.push({
+ x: e.offsetX,
+ y: e.offsetY
+ });
+ return e;
+}
+
+// hex 转 rgba
+function hexToRgb(hexValue, opc) {
+ var rgx = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
+ var hex = hexValue.replace(rgx, function(m, r, g, b) {
+ return r + r + g + g + b + b;
+ });
+ var rgb = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
+ var r = parseInt(rgb[1], 16);
+ var g = parseInt(rgb[2], 16);
+ var b = parseInt(rgb[3], 16);
+ return 'rgba(' + r + ',' + g + ',' + b + ',' + opc + ')';
+}
+
+function findRange(num, type, limit) {
+ if (isNaN(num)) {
+ throw new Error('[uCharts] unvalid series data!');
+ }
+ limit = limit || 10;
+ type = type ? type : 'upper';
+ var multiple = 1;
+ while (limit < 1) {
+ limit *= 10;
+ multiple *= 10;
+ }
+ if (type === 'upper') {
+ num = Math.ceil(num * multiple);
+ } else {
+ num = Math.floor(num * multiple);
+ }
+ while (num % limit !== 0) {
+ if (type === 'upper') {
+ num++;
+ } else {
+ num--;
+ }
+ }
+ return num / multiple;
+}
+
+function calCandleMA(dayArr, nameArr, colorArr, kdata) {
+ let seriesTemp = [];
+ for (let k = 0; k < dayArr.length; k++) {
+ let seriesItem = {
+ data: [],
+ name: nameArr[k],
+ color: colorArr[k]
+ };
+ for (let i = 0, len = kdata.length; i < len; i++) {
+ if (i < dayArr[k]) {
+ seriesItem.data.push(null);
+ continue;
+ }
+ let sum = 0;
+ for (let j = 0; j < dayArr[k]; j++) {
+ sum += kdata[i - j][1];
+ }
+ seriesItem.data.push(+(sum / dayArr[k]).toFixed(3));
+ }
+ seriesTemp.push(seriesItem);
+ }
+ return seriesTemp;
+}
+
+function calValidDistance(self,distance, chartData, config, opts) {
+ var dataChartAreaWidth = opts.width - opts.area[1] - opts.area[3];
+ var dataChartWidth = chartData.eachSpacing * (opts.chartData.xAxisData.xAxisPoints.length-1);
+ var validDistance = distance;
+ if (distance >= 0) {
+ validDistance = 0;
+ self.event.trigger('scrollLeft');
+ } else if (Math.abs(distance) >= dataChartWidth - dataChartAreaWidth) {
+ validDistance = dataChartAreaWidth - dataChartWidth;
+ self.event.trigger('scrollRight');
+ }
+ return validDistance;
+}
+
+function isInAngleRange(angle, startAngle, endAngle) {
+ function adjust(angle) {
+ while (angle < 0) {
+ angle += 2 * Math.PI;
+ }
+ while (angle > 2 * Math.PI) {
+ angle -= 2 * Math.PI;
+ }
+ return angle;
+ }
+ angle = adjust(angle);
+ startAngle = adjust(startAngle);
+ endAngle = adjust(endAngle);
+ if (startAngle > endAngle) {
+ endAngle += 2 * Math.PI;
+ if (angle < startAngle) {
+ angle += 2 * Math.PI;
+ }
+ }
+ return angle >= startAngle && angle <= endAngle;
+}
+
+function calRotateTranslate(x, y, h) {
+ var xv = x;
+ var yv = h - y;
+ var transX = xv + (h - yv - xv) / Math.sqrt(2);
+ transX *= -1;
+ var transY = (h - yv) * (Math.sqrt(2) - 1) - (h - yv - xv) / Math.sqrt(2);
+ return {
+ transX: transX,
+ transY: transY
+ };
+}
+
+function createCurveControlPoints(points, i) {
+
+ function isNotMiddlePoint(points, i) {
+ if (points[i - 1] && points[i + 1]) {
+ return points[i].y >= Math.max(points[i - 1].y, points[i + 1].y) || points[i].y <= Math.min(points[i - 1].y,points[i + 1].y);
+ } else {
+ return false;
+ }
+ }
+ function isNotMiddlePointX(points, i) {
+ if (points[i - 1] && points[i + 1]) {
+ return points[i].x >= Math.max(points[i - 1].x, points[i + 1].x) || points[i].x <= Math.min(points[i - 1].x,points[i + 1].x);
+ } else {
+ return false;
+ }
+ }
+ var a = 0.2;
+ var b = 0.2;
+ var pAx = null;
+ var pAy = null;
+ var pBx = null;
+ var pBy = null;
+ if (i < 1) {
+ pAx = points[0].x + (points[1].x - points[0].x) * a;
+ pAy = points[0].y + (points[1].y - points[0].y) * a;
+ } else {
+ pAx = points[i].x + (points[i + 1].x - points[i - 1].x) * a;
+ pAy = points[i].y + (points[i + 1].y - points[i - 1].y) * a;
+ }
+
+ if (i > points.length - 3) {
+ var last = points.length - 1;
+ pBx = points[last].x - (points[last].x - points[last - 1].x) * b;
+ pBy = points[last].y - (points[last].y - points[last - 1].y) * b;
+ } else {
+ pBx = points[i + 1].x - (points[i + 2].x - points[i].x) * b;
+ pBy = points[i + 1].y - (points[i + 2].y - points[i].y) * b;
+ }
+ if (isNotMiddlePoint(points, i + 1)) {
+ pBy = points[i + 1].y;
+ }
+ if (isNotMiddlePoint(points, i)) {
+ pAy = points[i].y;
+ }
+ if (isNotMiddlePointX(points, i + 1)) {
+ pBx = points[i + 1].x;
+ }
+ if (isNotMiddlePointX(points, i)) {
+ pAx = points[i].x;
+ }
+ if (pAy >= Math.max(points[i].y, points[i + 1].y) || pAy <= Math.min(points[i].y, points[i + 1].y)) {
+ pAy = points[i].y;
+ }
+ if (pBy >= Math.max(points[i].y, points[i + 1].y) || pBy <= Math.min(points[i].y, points[i + 1].y)) {
+ pBy = points[i + 1].y;
+ }
+ if (pAx >= Math.max(points[i].x, points[i + 1].x) || pAx <= Math.min(points[i].x, points[i + 1].x)) {
+ pAx = points[i].x;
+ }
+ if (pBx >= Math.max(points[i].x, points[i + 1].x) || pBx <= Math.min(points[i].x, points[i + 1].x)) {
+ pBx = points[i + 1].x;
+ }
+ return {
+ ctrA: {
+ x: pAx,
+ y: pAy
+ },
+ ctrB: {
+ x: pBx,
+ y: pBy
+ }
+ };
+}
+
+function convertCoordinateOrigin(x, y, center) {
+ return {
+ x: center.x + x,
+ y: center.y - y
+ };
+}
+
+function avoidCollision(obj, target) {
+ if (target) {
+ // is collision test
+ while (util.isCollision(obj, target)) {
+ if (obj.start.x > 0) {
+ obj.start.y--;
+ } else if (obj.start.x < 0) {
+ obj.start.y++;
+ } else {
+ if (obj.start.y > 0) {
+ obj.start.y++;
+ } else {
+ obj.start.y--;
+ }
+ }
+ }
+ }
+ return obj;
+}
+
+function fillSeries(series, opts, config) {
+ var index = 0;
+ return series.map(function(item) {
+ if (!item.color) {
+ item.color = config.colors[index];
+ index = (index + 1) % config.colors.length;
+ }
+ if (!item.index) {
+ item.index = 0;
+ }
+ if (!item.type) {
+ item.type = opts.type;
+ }
+ if (typeof item.show == "undefined") {
+ item.show = true;
+ }
+ if (!item.type) {
+ item.type = opts.type;
+ }
+ if (!item.pointShape) {
+ item.pointShape = "circle";
+ }
+ if (!item.legendShape) {
+ switch (item.type) {
+ case 'line':
+ item.legendShape = "line";
+ break;
+ case 'column':
+ item.legendShape = "rect";
+ break;
+ case 'area':
+ item.legendShape = "triangle";
+ break;
+ default:
+ item.legendShape = "circle";
+ }
+ }
+ return item;
+ });
+}
+
+function getDataRange(minData, maxData) {
+ var limit = 0;
+ var range = maxData - minData;
+ if (range >= 10000) {
+ limit = 1000;
+ } else if (range >= 1000) {
+ limit = 100;
+ } else if (range >= 100) {
+ limit = 10;
+ } else if (range >= 10) {
+ limit = 5;
+ } else if (range >= 1) {
+ limit = 1;
+ } else if (range >= 0.1) {
+ limit = 0.1;
+ } else if (range >= 0.01) {
+ limit = 0.01;
+ } else if (range >= 0.001) {
+ limit = 0.001;
+ } else if (range >= 0.0001) {
+ limit = 0.0001;
+ } else if (range >= 0.00001) {
+ limit = 0.00001;
+ } else {
+ limit = 0.000001;
+ }
+ return {
+ minRange: findRange(minData, 'lower', limit),
+ maxRange: findRange(maxData, 'upper', limit)
+ };
+}
+
+function measureText(text) {
+ var fontSize = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : config.fontSize;
+ text = String(text);
+ var text = text.split('');
+ var width = 0;
+ for (let i = 0; i < text.length; i++) {
+ let item = text[i];
+ if (/[a-zA-Z]/.test(item)) {
+ width += 7;
+ } else if (/[0-9]/.test(item)) {
+ width += 5.5;
+ } else if (/\./.test(item)) {
+ width += 2.7;
+ } else if (/-/.test(item)) {
+ width += 3.25;
+ } else if (/[\u4e00-\u9fa5]/.test(item)) {
+ width += 10;
+ } else if (/\(|\)/.test(item)) {
+ width += 3.73;
+ } else if (/\s/.test(item)) {
+ width += 2.5;
+ } else if (/%/.test(item)) {
+ width += 8;
+ } else {
+ width += 10;
+ }
+ }
+ return width * fontSize / 10;
+}
+
+function dataCombine(series) {
+ return series.reduce(function(a, b) {
+ return (a.data ? a.data : a).concat(b.data);
+ }, []);
+}
+
+function dataCombineStack(series, len) {
+ var sum = new Array(len);
+ for (var j = 0; j < sum.length; j++) {
+ sum[j] = 0;
+ }
+ for (var i = 0; i < series.length; i++) {
+ for (var j = 0; j < sum.length; j++) {
+ sum[j] += series[i].data[j];
+ }
+ }
+ return series.reduce(function(a, b) {
+ return (a.data ? a.data : a).concat(b.data).concat(sum);
+ }, []);
+}
+
+function getTouches(touches, opts, e) {
+ let x, y;
+ if (touches.clientX) {
+ if (opts.rotate) {
+ y = opts.height - touches.clientX * opts.pixelRatio;
+ x = (touches.pageY - e.currentTarget.offsetTop - (opts.height / opts.pixelRatio / 2) * (opts.pixelRatio - 1)) *
+ opts.pixelRatio;
+ } else {
+ x = touches.clientX * opts.pixelRatio;
+ y = (touches.pageY - e.currentTarget.offsetTop - (opts.height / opts.pixelRatio / 2) * (opts.pixelRatio - 1)) *
+ opts.pixelRatio;
+ }
+ } else {
+ if (opts.rotate) {
+ y = opts.height - touches.x * opts.pixelRatio;
+ x = touches.y * opts.pixelRatio;
+ } else {
+ x = touches.x * opts.pixelRatio;
+ y = touches.y * opts.pixelRatio;
+ }
+ }
+ return {
+ x: x,
+ y: y
+ }
+}
+
+function getSeriesDataItem(series, index) {
+ var data = [];
+ for (let i = 0; i < series.length; i++) {
+ let item = series[i];
+ if (item.data[index] !== null && typeof item.data[index] !== 'undefined' && item.show) {
+ let seriesItem = {};
+ seriesItem.color = item.color;
+ seriesItem.type = item.type;
+ seriesItem.style = item.style;
+ seriesItem.pointShape = item.pointShape;
+ seriesItem.disableLegend = item.disableLegend;
+ seriesItem.name = item.name;
+ seriesItem.show = item.show;
+ seriesItem.data = item.format ? item.format(item.data[index]) : item.data[index];
+ data.push(seriesItem);
+ }
+ }
+ return data;
+}
+
+function getMaxTextListLength(list) {
+ var lengthList = list.map(function(item) {
+ return measureText(item);
+ });
+ return Math.max.apply(null, lengthList);
+}
+
+function getRadarCoordinateSeries(length) {
+ var eachAngle = 2 * Math.PI / length;
+ var CoordinateSeries = [];
+ for (var i = 0; i < length; i++) {
+ CoordinateSeries.push(eachAngle * i);
+ }
+
+ return CoordinateSeries.map(function(item) {
+ return -1 * item + Math.PI / 2;
+ });
+}
+
+function getToolTipData(seriesData, calPoints, index, categories) {
+ var option = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};
+
+ var textList = seriesData.map(function(item) {
+ let titleText=[];
+ if(categories){
+ titleText=categories;
+ }else{
+ titleText=item.data;
+ }
+ return {
+ text: option.format ? option.format(item, titleText[index]) : item.name + ': ' + item.data,
+ color: item.color
+ };
+ });
+ var validCalPoints = [];
+ var offset = {
+ x: 0,
+ y: 0
+ };
+ for (let i = 0; i < calPoints.length; i++) {
+ let points = calPoints[i];
+ if (typeof points[index] !== 'undefined' && points[index] !== null) {
+ validCalPoints.push(points[index]);
+ }
+ }
+ for (let i = 0; i < validCalPoints.length; i++) {
+ let item = validCalPoints[i];
+ offset.x = Math.round(item.x);
+ offset.y += item.y;
+ }
+ offset.y /= validCalPoints.length;
+ return {
+ textList: textList,
+ offset: offset
+ };
+}
+
+function getMixToolTipData(seriesData, calPoints, index, categories) {
+ var option = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};
+ var textList = seriesData.map(function(item) {
+ return {
+ text: option.format ? option.format(item, categories[index]) : item.name + ': ' + item.data,
+ color: item.color,
+ disableLegend: item.disableLegend ? true : false
+ };
+ });
+ textList = textList.filter(function(item) {
+ if (item.disableLegend !== true) {
+ return item;
+ }
+ });
+ var validCalPoints = [];
+ var offset = {
+ x: 0,
+ y: 0
+ };
+ for (let i = 0; i < calPoints.length; i++) {
+ let points = calPoints[i];
+ if (typeof points[index] !== 'undefined' && points[index] !== null) {
+ validCalPoints.push(points[index]);
+ }
+ }
+ for (let i = 0; i < validCalPoints.length; i++) {
+ let item = validCalPoints[i];
+ offset.x = Math.round(item.x);
+ offset.y += item.y;
+ }
+ offset.y /= validCalPoints.length;
+ return {
+ textList: textList,
+ offset: offset
+ };
+}
+
+function getCandleToolTipData(series, seriesData, calPoints, index, categories, extra) {
+ var option = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : {};
+ let upColor = extra.color.upFill;
+ let downColor = extra.color.downFill;
+ //颜色顺序为开盘,收盘,最低,最高
+ let color = [upColor, upColor, downColor, upColor];
+ var textList = [];
+ let text0 = {
+ text: categories[index],
+ color: null
+ };
+ textList.push(text0);
+ seriesData.map(function(item) {
+ if (index == 0) {
+ if(item.data[1] - item.data[0] < 0){
+ color[1] = downColor;
+ }else{
+ color[1] = upColor;
+ }
+ } else {
+ if (item.data[0] < series[index - 1][1]) {
+ color[0] = downColor;
+ }
+ if (item.data[1] < item.data[0]) {
+ color[1] = downColor;
+ }
+ if (item.data[2] > series[index - 1][1]) {
+ color[2] = upColor;
+ }
+ if (item.data[3] < series[index - 1][1]) {
+ color[3] = downColor;
+ }
+ }
+ let text1 = {
+ text: '开盘:' + item.data[0],
+ color: color[0]
+ };
+ let text2 = {
+ text: '收盘:' + item.data[1],
+ color: color[1]
+ };
+ let text3 = {
+ text: '最低:' + item.data[2],
+ color: color[2]
+ };
+ let text4 = {
+ text: '最高:' + item.data[3],
+ color: color[3]
+ };
+ textList.push(text1, text2, text3, text4);
+ });
+ var validCalPoints = [];
+ var offset = {
+ x: 0,
+ y: 0
+ };
+ for (let i = 0; i < calPoints.length; i++) {
+ let points = calPoints[i];
+ if (typeof points[index] !== 'undefined' && points[index] !== null) {
+ validCalPoints.push(points[index]);
+ }
+ }
+ offset.x = Math.round(validCalPoints[0][0].x);
+ return {
+ textList: textList,
+ offset: offset
+ };
+}
+
+function filterSeries(series) {
+ let tempSeries = [];
+ for (let i = 0; i < series.length; i++) {
+ if (series[i].show == true) {
+ tempSeries.push(series[i])
+ }
+ }
+ return tempSeries;
+}
+
+function findCurrentIndex(currentPoints, calPoints, opts, config) {
+ var offset = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 0;
+ var currentIndex = -1;
+ var spacing = opts.chartData.eachSpacing/2;
+ let xAxisPoints=[];
+ if(calPoints.length>0){
+ if(opts.type=='candle'){
+ for(let i=0;i item) {
+ currentIndex = index;
+ }
+ });
+ }
+ }
+ return currentIndex;
+}
+
+function findLegendIndex(currentPoints, legendData, opts) {
+ let currentIndex = -1;
+ if (isInExactLegendArea(currentPoints, legendData.area)) {
+ let points = legendData.points;
+ let index = -1;
+ for (let i = 0, len = points.length; i < len; i++) {
+ let item = points[i];
+ for (let j = 0; j < item.length; j++) {
+ index += 1;
+ let area = item[j]['area'];
+ if (currentPoints.x > area[0] && currentPoints.x < area[2] && currentPoints.y > area[1] && currentPoints.y < area[3]) {
+ currentIndex = index;
+ break;
+ }
+ }
+ }
+ return currentIndex;
+ }
+ return currentIndex;
+}
+
+function isInExactLegendArea(currentPoints, area) {
+ return currentPoints.x > area.start.x && currentPoints.x < area.end.x && currentPoints.y > area.start.y &&
+ currentPoints.y < area.end.y;
+}
+
+function isInExactChartArea(currentPoints, opts, config) {
+ return currentPoints.x <= opts.width - opts.area[1] + 10 && currentPoints.x >= opts.area[3] -10 && currentPoints.y >= opts.area[0] && currentPoints.y <= opts.height - opts.area[2];
+}
+
+function findRadarChartCurrentIndex(currentPoints, radarData, count) {
+ var eachAngleArea = 2 * Math.PI / count;
+ var currentIndex = -1;
+ if (isInExactPieChartArea(currentPoints, radarData.center, radarData.radius)) {
+ var fixAngle = function fixAngle(angle) {
+ if (angle < 0) {
+ angle += 2 * Math.PI;
+ }
+ if (angle > 2 * Math.PI) {
+ angle -= 2 * Math.PI;
+ }
+ return angle;
+ };
+
+ var angle = Math.atan2(radarData.center.y - currentPoints.y, currentPoints.x - radarData.center.x);
+ angle = -1 * angle;
+ if (angle < 0) {
+ angle += 2 * Math.PI;
+ }
+
+ var angleList = radarData.angleList.map(function(item) {
+ item = fixAngle(-1 * item);
+
+ return item;
+ });
+
+ angleList.forEach(function(item, index) {
+ var rangeStart = fixAngle(item - eachAngleArea / 2);
+ var rangeEnd = fixAngle(item + eachAngleArea / 2);
+ if (rangeEnd < rangeStart) {
+ rangeEnd += 2 * Math.PI;
+ }
+ if (angle >= rangeStart && angle <= rangeEnd || angle + 2 * Math.PI >= rangeStart && angle + 2 * Math.PI <=
+ rangeEnd) {
+ currentIndex = index;
+ }
+ });
+ }
+
+ return currentIndex;
+}
+
+function findFunnelChartCurrentIndex(currentPoints, funnelData) {
+ var currentIndex = -1;
+ for (var i = 0, len = funnelData.series.length; i < len; i++) {
+ var item = funnelData.series[i];
+ if (currentPoints.x > item.funnelArea[0] && currentPoints.x < item.funnelArea[2] && currentPoints.y > item.funnelArea[1] && currentPoints.y < item.funnelArea[3]) {
+ currentIndex = i;
+ break;
+ }
+ }
+ return currentIndex;
+}
+
+function findWordChartCurrentIndex(currentPoints, wordData) {
+ var currentIndex = -1;
+ for (var i = 0, len = wordData.length; i < len; i++) {
+ var item = wordData[i];
+ if (currentPoints.x > item.area[0] && currentPoints.x < item.area[2] && currentPoints.y > item.area[1] && currentPoints.y < item.area[3]) {
+ currentIndex = i;
+ break;
+ }
+ }
+ return currentIndex;
+}
+
+function findMapChartCurrentIndex(currentPoints, opts) {
+ var currentIndex = -1;
+ var cData=opts.chartData.mapData;
+ var data=opts.series;
+ var tmp=pointToCoordinate(currentPoints.y, currentPoints.x,cData.bounds,cData.scale,cData.xoffset,cData.yoffset);
+ var poi=[tmp.x, tmp.y];
+ for (var i = 0, len = data.length; i < len; i++) {
+ var item = data[i].geometry.coordinates;
+ if(isPoiWithinPoly(poi,item)){
+ currentIndex = i;
+ break;
+ }
+ }
+ return currentIndex;
+}
+
+function findPieChartCurrentIndex(currentPoints, pieData) {
+ var currentIndex = -1;
+ if (isInExactPieChartArea(currentPoints, pieData.center, pieData.radius)) {
+ var angle = Math.atan2(pieData.center.y - currentPoints.y, currentPoints.x - pieData.center.x);
+ angle = -angle;
+ for (var i = 0, len = pieData.series.length; i < len; i++) {
+ var item = pieData.series[i];
+ if (isInAngleRange(angle, item._start_, item._start_ + item._proportion_ * 2 * Math.PI)) {
+ currentIndex = i;
+ break;
+ }
+ }
+ }
+
+ return currentIndex;
+}
+
+function isInExactPieChartArea(currentPoints, center, radius) {
+ return Math.pow(currentPoints.x - center.x, 2) + Math.pow(currentPoints.y - center.y, 2) <= Math.pow(radius, 2);
+}
+
+function splitPoints(points) {
+ var newPoints = [];
+ var items = [];
+ points.forEach(function(item, index) {
+ if (item !== null) {
+ items.push(item);
+ } else {
+ if (items.length) {
+ newPoints.push(items);
+ }
+ items = [];
+ }
+ });
+ if (items.length) {
+ newPoints.push(items);
+ }
+
+ return newPoints;
+}
+
+function calLegendData(series, opts, config, chartData) {
+ let legendData = {
+ area: {
+ start: {
+ x: 0,
+ y: 0
+ },
+ end: {
+ x: 0,
+ y: 0
+ },
+ width: 0,
+ height: 0,
+ wholeWidth: 0,
+ wholeHeight: 0
+ },
+ points: [],
+ widthArr: [],
+ heightArr: []
+ };
+ if (opts.legend.show === false) {
+ chartData.legendData = legendData;
+ return legendData;
+ }
+
+ let padding = opts.legend.padding;
+ let margin = opts.legend.margin;
+ let fontSize = opts.legend.fontSize;
+ let shapeWidth = 15 * opts.pixelRatio;
+ let shapeRight = 5 * opts.pixelRatio;
+ let lineHeight = Math.max(opts.legend.lineHeight * opts.pixelRatio, fontSize);
+ if (opts.legend.position == 'top' || opts.legend.position == 'bottom') {
+ let legendList = [];
+ let widthCount = 0;
+ let widthCountArr = [];
+ let currentRow = [];
+ for (let i = 0; i < series.length; i++) {
+ let item = series[i];
+ let itemWidth = shapeWidth + shapeRight + measureText(item.name || 'undefined', fontSize) + opts.legend.itemGap;
+ if (widthCount + itemWidth > opts.width - opts.padding[1] - opts.padding[3]) {
+ legendList.push(currentRow);
+ widthCountArr.push(widthCount - opts.legend.itemGap);
+ widthCount = itemWidth;
+ currentRow = [item];
+ } else {
+ widthCount += itemWidth;
+ currentRow.push(item);
+ }
+ }
+ if (currentRow.length) {
+ legendList.push(currentRow);
+ widthCountArr.push(widthCount - opts.legend.itemGap);
+ legendData.widthArr = widthCountArr;
+ let legendWidth = Math.max.apply(null, widthCountArr);
+ switch (opts.legend.float) {
+ case 'left':
+ legendData.area.start.x = opts.padding[3];
+ legendData.area.end.x = opts.padding[3] + 2 * padding;
+ break;
+ case 'right':
+ legendData.area.start.x = opts.width - opts.padding[1] - legendWidth - 2 * padding;
+ legendData.area.end.x = opts.width - opts.padding[1];
+ break;
+ default:
+ legendData.area.start.x = (opts.width - legendWidth) / 2 - padding;
+ legendData.area.end.x = (opts.width + legendWidth) / 2 + padding;
+ }
+ legendData.area.width = legendWidth + 2 * padding;
+ legendData.area.wholeWidth = legendWidth + 2 * padding;
+ legendData.area.height = legendList.length * lineHeight + 2 * padding;
+ legendData.area.wholeHeight = legendList.length * lineHeight + 2 * padding + 2 * margin;
+ legendData.points = legendList;
+ }
+ } else {
+ let len = series.length;
+ let maxHeight = opts.height - opts.padding[0] - opts.padding[2] - 2 * margin - 2 * padding;
+ let maxLength = Math.min(Math.floor(maxHeight / lineHeight), len);
+ legendData.area.height = maxLength * lineHeight + padding * 2;
+ legendData.area.wholeHeight = maxLength * lineHeight + padding * 2;
+ switch (opts.legend.float) {
+ case 'top':
+ legendData.area.start.y = opts.padding[0] + margin;
+ legendData.area.end.y = opts.padding[0] + margin + legendData.area.height;
+ break;
+ case 'bottom':
+ legendData.area.start.y = opts.height - opts.padding[2] - margin - legendData.area.height;
+ legendData.area.end.y = opts.height - opts.padding[2] - margin;
+ break;
+ default:
+ legendData.area.start.y = (opts.height - legendData.area.height) / 2;
+ legendData.area.end.y = (opts.height + legendData.area.height) / 2;
+ }
+ let lineNum = len % maxLength === 0 ? len / maxLength : Math.floor((len / maxLength) + 1);
+ let currentRow = [];
+ for (let i = 0; i < lineNum; i++) {
+ let temp = series.slice(i * maxLength, i * maxLength + maxLength);
+ currentRow.push(temp);
+ }
+
+ legendData.points = currentRow;
+
+ if (currentRow.length) {
+ for (let i = 0; i < currentRow.length; i++) {
+ let item = currentRow[i];
+ let maxWidth = 0;
+ for (let j = 0; j < item.length; j++) {
+ let itemWidth = shapeWidth + shapeRight + measureText(item[j].name || 'undefined', fontSize) + opts.legend.itemGap;
+ if (itemWidth > maxWidth) {
+ maxWidth = itemWidth;
+ }
+ }
+ legendData.widthArr.push(maxWidth);
+ legendData.heightArr.push(item.length * lineHeight + padding * 2);
+ }
+ let legendWidth = 0
+ for (let i = 0; i < legendData.widthArr.length; i++) {
+ legendWidth += legendData.widthArr[i];
+ }
+ legendData.area.width = legendWidth - opts.legend.itemGap + 2 * padding;
+ legendData.area.wholeWidth = legendData.area.width + padding;
+ }
+ }
+
+ switch (opts.legend.position) {
+ case 'top':
+ legendData.area.start.y = opts.padding[0] + margin;
+ legendData.area.end.y = opts.padding[0] + margin + legendData.area.height;
+ break;
+ case 'bottom':
+ legendData.area.start.y = opts.height - opts.padding[2] - legendData.area.height - margin;
+ legendData.area.end.y = opts.height - opts.padding[2] - margin;
+ break;
+ case 'left':
+ legendData.area.start.x = opts.padding[3];
+ legendData.area.end.x = opts.padding[3] + legendData.area.width;
+ break;
+ case 'right':
+ legendData.area.start.x = opts.width - opts.padding[1] - legendData.area.width;
+ legendData.area.end.x = opts.width - opts.padding[1];
+ break;
+ }
+ chartData.legendData = legendData;
+ return legendData;
+}
+
+function calCategoriesData(categories, opts, config, eachSpacing) {
+ var result = {
+ angle: 0,
+ xAxisHeight: config.xAxisHeight
+ };
+ var categoriesTextLenth = categories.map(function(item) {
+ return measureText(item,opts.xAxis.fontSize||config.fontSize);
+ });
+ var maxTextLength = Math.max.apply(this, categoriesTextLenth);
+
+ if (opts.xAxis.rotateLabel == true && maxTextLength + 2 * config.xAxisTextPadding > eachSpacing) {
+ result.angle = 45 * Math.PI / 180;
+ result.xAxisHeight = 2 * config.xAxisTextPadding + maxTextLength * Math.sin(result.angle);
+ }
+ return result;
+}
+
+function getXAxisTextList(series, opts, config) {
+ var index = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : -1;
+ var data = dataCombine(series);
+ var sorted = [];
+ // remove null from data
+ data = data.filter(function(item) {
+ //return item !== null;
+ if (typeof item === 'object' && item !== null) {
+ if (item.constructor.toString().indexOf('Array')>-1) {
+ return item !== null;
+ } else {
+ return item.value !== null;
+ }
+ } else {
+ return item !== null;
+ }
+ });
+ data.map(function(item) {
+ if (typeof item === 'object') {
+ if (item.constructor.toString().indexOf('Array')>-1) {
+ if(opts.type=='candle'){
+ item.map(function(subitem) {
+ sorted.push(subitem);
+ })
+ }else{
+ sorted.push(item[0]);
+ }
+ } else {
+ sorted.push(item.value);
+ }
+ } else {
+ sorted.push(item);
+ }
+ })
+
+ var minData = 0;
+ var maxData = 0;
+ if (sorted.length > 0) {
+ minData = Math.min.apply(this, sorted);
+ maxData = Math.max.apply(this, sorted);
+ }
+ //为了兼容v1.9.0之前的项目
+ if(index>-1){
+ if (typeof opts.xAxis.data[index].min === 'number') {
+ minData = Math.min(opts.xAxis.data[index].min, minData);
+ }
+ if (typeof opts.xAxis.data[index].max === 'number') {
+ maxData = Math.max(opts.xAxis.data[index].max, maxData);
+ }
+ }else{
+ if (typeof opts.xAxis.min === 'number') {
+ minData = Math.min(opts.xAxis.min, minData);
+ }
+ if (typeof opts.xAxis.max === 'number') {
+ maxData = Math.max(opts.xAxis.max, maxData);
+ }
+ }
+
+
+ if (minData === maxData) {
+ var rangeSpan = maxData || 10;
+ maxData += rangeSpan;
+ }
+
+ //var dataRange = getDataRange(minData, maxData);
+ var minRange = minData;
+ var maxRange = maxData;
+
+ var range = [];
+ var eachRange = (maxRange - minRange) / opts.xAxis.splitNumber;
+
+ for (var i = 0; i <= opts.xAxis.splitNumber; i++) {
+ range.push(minRange + eachRange * i);
+ }
+ return range;
+}
+
+function calXAxisData(series, opts, config){
+ var result = {
+ angle: 0,
+ xAxisHeight: config.xAxisHeight
+ };
+
+ result.ranges = getXAxisTextList(series, opts, config);
+ result.rangesFormat = result.ranges.map(function(item){
+ item = opts.xAxis.format? opts.xAxis.format(item):util.toFixed(item, 2);
+ return item;
+ });
+
+ var xAxisScaleValues = result.ranges.map(function (item) {
+ // 如果刻度值是浮点数,则保留两位小数
+ item = util.toFixed(item, 2);
+ // 若有自定义格式则调用自定义的格式化函数
+ item = opts.xAxis.format ? opts.xAxis.format(Number(item)) : item;
+ return item;
+ });
+
+ result = Object.assign(result,getXAxisPoints(xAxisScaleValues, opts, config));
+ // 计算X轴刻度的属性譬如每个刻度的间隔,刻度的起始点\结束点以及总长
+ var eachSpacing = result.eachSpacing;
+
+ var textLength = xAxisScaleValues.map(function (item) {
+ return measureText(item);
+ });
+
+ // get max length of categories text
+ var maxTextLength = Math.max.apply(this, textLength);
+
+ // 如果刻度值文本内容过长,则将其逆时针旋转45°
+ if (maxTextLength + 2 * config.xAxisTextPadding > eachSpacing) {
+ result.angle = 45 * Math.PI / 180;
+ result.xAxisHeight = 2 * config.xAxisTextPadding + maxTextLength * Math.sin(result.angle);
+ }
+
+ if (opts.xAxis.disabled === true) {
+ result.xAxisHeight = 0;
+ }
+
+ return result;
+}
+
+function getRadarDataPoints(angleList, center, radius, series, opts) {
+ var process = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 1;
+
+ var radarOption = opts.extra.radar || {};
+ radarOption.max = radarOption.max || 0;
+ var maxData = Math.max(radarOption.max, Math.max.apply(null, dataCombine(series)));
+
+ var data = [];
+ for (let i = 0; i < series.length; i++) {
+ let each = series[i];
+ let listItem = {};
+ listItem.color = each.color;
+ listItem.legendShape = each.legendShape;
+ listItem.pointShape = each.pointShape;
+ listItem.data = [];
+ each.data.forEach(function(item, index) {
+ let tmp = {};
+ tmp.angle = angleList[index];
+
+ tmp.proportion = item / maxData;
+ tmp.position = convertCoordinateOrigin(radius * tmp.proportion * process * Math.cos(tmp.angle), radius * tmp.proportion *
+ process * Math.sin(tmp.angle), center);
+ listItem.data.push(tmp);
+ });
+
+ data.push(listItem);
+ }
+
+ return data;
+}
+
+function getPieDataPoints(series, radius) {
+ var process = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1;
+
+ var count = 0;
+ var _start_ = 0;
+ for (let i = 0; i < series.length; i++) {
+ let item = series[i];
+ item.data = item.data === null ? 0 : item.data;
+ count += item.data;
+ }
+ for (let i = 0; i < series.length; i++) {
+ let item = series[i];
+ item.data = item.data === null ? 0 : item.data;
+ if (count === 0) {
+ item._proportion_ = 1 / series.length * process;
+ } else {
+ item._proportion_ = item.data / count * process;
+ }
+ item._radius_ = radius;
+ }
+ for (let i = 0; i < series.length; i++) {
+ let item = series[i];
+ item._start_ = _start_;
+ _start_ += 2 * item._proportion_ * Math.PI;
+ }
+
+ return series;
+}
+
+function getFunnelDataPoints(series, radius) {
+ var process = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1;
+ series = series.sort(function(a,b){return parseInt(b.data)-parseInt(a.data);});
+ for (let i = 0; i < series.length; i++) {
+ series[i].radius = series[i].data/series[0].data*radius*process;
+ series[i]._proportion_ = series[i].data/series[0].data;
+ }
+ return series.reverse();
+}
+
+function getRoseDataPoints(series, type, minRadius, radius) {
+ var process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1;
+ var count = 0;
+ var _start_ = 0;
+
+ var dataArr = [];
+ for (let i = 0; i < series.length; i++) {
+ let item = series[i];
+ item.data = item.data === null ? 0 : item.data;
+ count += item.data;
+ dataArr.push(item.data);
+ }
+
+ var minData = Math.min.apply(null, dataArr);
+ var maxData = Math.max.apply(null, dataArr);
+ var radiusLength = radius - minRadius;
+
+ for (let i = 0; i < series.length; i++) {
+ let item = series[i];
+ item.data = item.data === null ? 0 : item.data;
+ if (count === 0 || type == 'area') {
+ item._proportion_ = item.data / count * process;
+ item._rose_proportion_ = 1 / series.length * process;
+ } else {
+ item._proportion_ = item.data / count * process;
+ item._rose_proportion_ = item.data / count * process;
+ }
+ item._radius_ = minRadius + radiusLength * ((item.data - minData) / (maxData - minData));
+ }
+ for (let i = 0; i < series.length; i++) {
+ let item = series[i];
+ item._start_ = _start_;
+ _start_ += 2 * item._rose_proportion_ * Math.PI;
+ }
+
+ return series;
+}
+
+function getArcbarDataPoints(series, arcbarOption) {
+ var process = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1;
+ if (process == 1) {
+ process = 0.999999;
+ }
+ for (let i = 0; i < series.length; i++) {
+ let item = series[i];
+ item.data = item.data === null ? 0 : item.data;
+ let totalAngle;
+ if (arcbarOption.type == 'circle') {
+ totalAngle = 2;
+ } else {
+ if (arcbarOption.endAngle < arcbarOption.startAngle) {
+ totalAngle = 2 + arcbarOption.endAngle - arcbarOption.startAngle;
+ } else{
+ totalAngle = arcbarOption.startAngle - arcbarOption.endAngle;
+ }
+ }
+ item._proportion_ = totalAngle * item.data * process + arcbarOption.startAngle;
+ if (item._proportion_ >= 2) {
+ item._proportion_ = item._proportion_ % 2;
+ }
+ }
+ return series;
+}
+
+function getGaugeAxisPoints(categories, startAngle, endAngle) {
+ let totalAngle = startAngle - endAngle + 1;
+ let tempStartAngle = startAngle;
+ for (let i = 0; i < categories.length; i++) {
+ categories[i].value = categories[i].value === null ? 0 : categories[i].value;
+ categories[i]._startAngle_ = tempStartAngle;
+ categories[i]._endAngle_ = totalAngle * categories[i].value + startAngle;
+ if (categories[i]._endAngle_ >= 2) {
+ categories[i]._endAngle_ = categories[i]._endAngle_ % 2;
+ }
+ tempStartAngle = categories[i]._endAngle_;
+ }
+ return categories;
+}
+
+function getGaugeDataPoints(series, categories, gaugeOption) {
+ let process = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 1;
+ for (let i = 0; i < series.length; i++) {
+ let item = series[i];
+ item.data = item.data === null ? 0 : item.data;
+ if (gaugeOption.pointer.color == 'auto') {
+ for (let i = 0; i < categories.length; i++) {
+ if (item.data <= categories[i].value) {
+ item.color = categories[i].color;
+ break;
+ }
+ }
+ } else {
+ item.color = gaugeOption.pointer.color;
+ }
+ let totalAngle = gaugeOption.startAngle - gaugeOption.endAngle + 1;
+ item._endAngle_ = totalAngle * item.data + gaugeOption.startAngle;
+ item._oldAngle_ = gaugeOption.oldAngle;
+ if (gaugeOption.oldAngle < gaugeOption.endAngle) {
+ item._oldAngle_ += 2;
+ }
+ if (item.data >= gaugeOption.oldData) {
+ item._proportion_ = (item._endAngle_ - item._oldAngle_) * process + gaugeOption.oldAngle;
+ } else {
+ item._proportion_ = item._oldAngle_ - (item._oldAngle_ - item._endAngle_) * process;
+ }
+ if (item._proportion_ >= 2) {
+ item._proportion_ = item._proportion_ % 2;
+ }
+ }
+ return series;
+}
+
+function getPieTextMaxLength(series) {
+ series = getPieDataPoints(series);
+ let maxLength = 0;
+ for (let i = 0; i < series.length; i++) {
+ let item = series[i];
+ let text = item.format ? item.format(+item._proportion_.toFixed(2)) : util.toFixed(item._proportion_ * 100) + '%';
+ maxLength = Math.max(maxLength, measureText(text));
+ }
+
+ return maxLength;
+}
+
+function fixColumeData(points, eachSpacing, columnLen, index, config, opts) {
+ return points.map(function(item) {
+ if (item === null) {
+ return null;
+ }
+ item.width = Math.ceil((eachSpacing - 2 * config.columePadding) / columnLen);
+
+ if (opts.extra.column && opts.extra.column.width && +opts.extra.column.width > 0) {
+ item.width = Math.min(item.width, +opts.extra.column.width);
+ }
+ if (item.width <= 0) {
+ item.width = 1;
+ }
+ item.x += (index + 0.5 - columnLen / 2) * item.width;
+ return item;
+ });
+}
+
+function fixColumeMeterData(points, eachSpacing, columnLen, index, config, opts, border) {
+ return points.map(function(item) {
+ if (item === null) {
+ return null;
+ }
+ item.width = Math.ceil((eachSpacing - 2 * config.columePadding) / 2);
+
+ if (opts.extra.column && opts.extra.column.width && +opts.extra.column.width > 0) {
+ item.width = Math.min(item.width, +opts.extra.column.width);
+ }
+
+ if (index > 0) {
+ item.width -= 2 * border;
+ }
+ return item;
+ });
+}
+
+function fixColumeStackData(points, eachSpacing, columnLen, index, config, opts, series) {
+
+ return points.map(function(item, indexn) {
+
+ if (item === null) {
+ return null;
+ }
+ item.width = Math.ceil((eachSpacing - 2 * config.columePadding) / 2);
+
+ if (opts.extra.column && opts.extra.column.width && +opts.extra.column.width > 0) {
+ item.width = Math.min(item.width, +opts.extra.column.width);
+ }
+ return item;
+ });
+}
+
+function getXAxisPoints(categories, opts, config) {
+ var spacingValid = opts.width - opts.area[1] - opts.area[3];
+ var dataCount = opts.enableScroll ? Math.min(opts.xAxis.itemCount, categories.length) : categories.length;
+ if((opts.type=='line' || opts.type=='area') && dataCount>1 && opts.xAxis.boundaryGap=='justify'){
+ dataCount -=1;
+ }
+ var eachSpacing = spacingValid / dataCount;
+
+ var xAxisPoints = [];
+ var startX = opts.area[3];
+ var endX = opts.width - opts.area[1];
+ categories.forEach(function(item, index) {
+ xAxisPoints.push(startX + index * eachSpacing);
+ });
+ if(opts.xAxis.boundaryGap !=='justify'){
+ if (opts.enableScroll === true) {
+ xAxisPoints.push(startX + categories.length * eachSpacing);
+ } else {
+ xAxisPoints.push(endX);
+ }
+ }
+ return {
+ xAxisPoints: xAxisPoints,
+ startX: startX,
+ endX: endX,
+ eachSpacing: eachSpacing
+ };
+}
+
+function getCandleDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config) {
+ var process = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : 1;
+ var points = [];
+ var validHeight = opts.height - opts.area[0] - opts.area[2];
+ data.forEach(function(item, index) {
+ if (item === null) {
+ points.push(null);
+ } else {
+ var cPoints = [];
+ item.forEach(function(items, indexs) {
+ var point = {};
+ point.x = xAxisPoints[index] + Math.round(eachSpacing / 2);
+ var value = items.value || items;
+ var height = validHeight * (value - minRange) / (maxRange - minRange);
+ height *= process;
+ point.y = opts.height - Math.round(height) - opts.area[2];
+ cPoints.push(point);
+ });
+ points.push(cPoints);
+ }
+ });
+
+ return points;
+}
+
+function getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config) {
+ var process = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : 1;
+ var boundaryGap='center';
+ if (opts.type == 'line'||opts.type == 'area'){
+ boundaryGap=opts.xAxis.boundaryGap;
+ }
+ var points = [];
+ var validHeight = opts.height - opts.area[0] - opts.area[2];
+ var validWidth = opts.width - opts.area[1] - opts.area[3];
+ data.forEach(function(item, index) {
+ if (item === null) {
+ points.push(null);
+ } else {
+ var point = {};
+ point.color = item.color;
+ point.x = xAxisPoints[index];
+ var value = item;
+ if (typeof item === 'object' && item !== null) {
+ if (item.constructor.toString().indexOf('Array')>-1) {
+ let xranges,xminRange,xmaxRange;
+ xranges = [].concat(opts.chartData.xAxisData.ranges);
+ xminRange = xranges.shift();
+ xmaxRange = xranges.pop();
+ value = item[1];
+ point.x = opts.area[3]+ validWidth * (item[0] - xminRange) / (xmaxRange - xminRange);
+ } else {
+ value = item.value;
+ }
+ }
+ if(boundaryGap=='center'){
+ point.x += Math.round(eachSpacing / 2);
+ }
+ var height = validHeight * (value - minRange) / (maxRange - minRange);
+ height *= process;
+ point.y = opts.height - Math.round(height) - opts.area[2];
+ points.push(point);
+ }
+ });
+
+ return points;
+}
+
+function getStackDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, seriesIndex, stackSeries) {
+ var process = arguments.length > 9 && arguments[9] !== undefined ? arguments[9] : 1;
+ var points = [];
+ var validHeight = opts.height - opts.area[0] - opts.area[2];
+
+ data.forEach(function(item, index) {
+ if (item === null) {
+ points.push(null);
+ } else {
+ var point = {};
+ point.color = item.color;
+ point.x = xAxisPoints[index] + Math.round(eachSpacing / 2);
+
+ if (seriesIndex > 0) {
+ var value = 0;
+ for (let i = 0; i <= seriesIndex; i++) {
+ value += stackSeries[i].data[index];
+ }
+ var value0 = value - item;
+ var height = validHeight * (value - minRange) / (maxRange - minRange);
+ var height0 = validHeight * (value0 - minRange) / (maxRange - minRange);
+ } else {
+ var value = item;
+ var height = validHeight * (value - minRange) / (maxRange - minRange);
+ var height0 = 0;
+ }
+ var heightc = height0;
+ height *= process;
+ heightc *= process;
+ point.y = opts.height - Math.round(height) - opts.area[2];
+ point.y0 = opts.height - Math.round(heightc) - opts.area[2];
+ points.push(point);
+ }
+ });
+
+ return points;
+}
+
+function getYAxisTextList(series, opts, config, stack) {
+ var index = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : -1;
+ var data;
+ if (stack == 'stack') {
+ data = dataCombineStack(series, opts.categories.length);
+ } else {
+ data = dataCombine(series);
+ }
+ var sorted = [];
+ // remove null from data
+ data = data.filter(function(item) {
+ //return item !== null;
+ if (typeof item === 'object' && item !== null) {
+ if (item.constructor.toString().indexOf('Array')>-1) {
+ return item !== null;
+ } else {
+ return item.value !== null;
+ }
+ } else {
+ return item !== null;
+ }
+ });
+ data.map(function(item) {
+ if (typeof item === 'object') {
+ if (item.constructor.toString().indexOf('Array')>-1) {
+ if(opts.type=='candle'){
+ item.map(function(subitem) {
+ sorted.push(subitem);
+ })
+ }else{
+ sorted.push(item[1]);
+ }
+ } else {
+ sorted.push(item.value);
+ }
+ } else {
+ sorted.push(item);
+ }
+ })
+
+ var minData = 0;
+ var maxData = 0;
+ if (sorted.length > 0) {
+ minData = Math.min.apply(this, sorted);
+ maxData = Math.max.apply(this, sorted);
+ }
+ //为了兼容v1.9.0之前的项目
+ if(index>-1){
+ if (typeof opts.yAxis.data[index].min === 'number') {
+ minData = Math.min(opts.yAxis.data[index].min, minData);
+ }
+ if (typeof opts.yAxis.data[index].max === 'number') {
+ maxData = Math.max(opts.yAxis.data[index].max, maxData);
+ }
+ }else{
+ if (typeof opts.yAxis.min === 'number') {
+ minData = Math.min(opts.yAxis.min, minData);
+ }
+ if (typeof opts.yAxis.max === 'number') {
+ maxData = Math.max(opts.yAxis.max, maxData);
+ }
+ }
+
+
+ if (minData === maxData) {
+ var rangeSpan = maxData || 10;
+ maxData += rangeSpan;
+ }
+
+ var dataRange = getDataRange(minData, maxData);
+ var minRange = dataRange.minRange;
+ var maxRange = dataRange.maxRange;
+
+ var range = [];
+ var eachRange = (maxRange - minRange) / opts.yAxis.splitNumber;
+
+ for (var i = 0; i <= opts.yAxis.splitNumber; i++) {
+ range.push(minRange + eachRange * i);
+ }
+ return range.reverse();
+}
+
+function calYAxisData(series, opts, config) {
+ //堆叠图重算Y轴
+ var columnstyle = assign({}, {
+ type: ""
+ }, opts.extra.column);
+ //如果是多Y轴,重新计算
+ var YLength = opts.yAxis.data.length;
+ var newSeries=new Array(YLength);
+ if(YLength>0){
+ for(let i=0;i= 2) {
+ nowAngle = nowAngle % 2;
+ }
+ nowNumber += splitNumber;
+ }
+
+}
+
+function drawRadarLabel(angleList, radius, centerPosition, opts, config, context) {
+ var radarOption = opts.extra.radar || {};
+ radius += config.radarLabelTextMargin;
+
+ angleList.forEach(function(angle, index) {
+ var pos = {
+ x: radius * Math.cos(angle),
+ y: radius * Math.sin(angle)
+ };
+ var posRelativeCanvas = convertCoordinateOrigin(pos.x, pos.y, centerPosition);
+ var startX = posRelativeCanvas.x;
+ var startY = posRelativeCanvas.y;
+ if (util.approximatelyEqual(pos.x, 0)) {
+ startX -= measureText(opts.categories[index] || '') / 2;
+ } else if (pos.x < 0) {
+ startX -= measureText(opts.categories[index] || '');
+ }
+ context.beginPath();
+ context.setFontSize(config.fontSize);
+ context.setFillStyle(radarOption.labelColor || '#666666');
+ context.fillText(opts.categories[index] || '', startX, startY + config.fontSize / 2);
+ context.closePath();
+ context.stroke();
+ });
+
+}
+
+function drawPieText(series, opts, config, context, radius, center) {
+ var lineRadius = config.pieChartLinePadding;
+ var textObjectCollection = [];
+ var lastTextObject = null;
+
+ var seriesConvert = series.map(function(item) {
+ var text = item.format ? item.format(+item._proportion_.toFixed(2)) : util.toFixed(item._proportion_.toFixed(4) * 100) +'%';
+ if(item._rose_proportion_) item._proportion_=item._rose_proportion_;
+ var arc = 2 * Math.PI - (item._start_ + 2 * Math.PI * item._proportion_ / 2);
+ var color = item.color;
+ var radius = item._radius_;
+ return {
+ arc: arc,
+ text: text,
+ color: color,
+ radius: radius,
+ textColor: item.textColor,
+ textSize: item.textSize,
+ };
+ });
+ for (let i = 0; i < seriesConvert.length; i++) {
+ let item = seriesConvert[i];
+ // line end
+ let orginX1 = Math.cos(item.arc) * (item.radius + lineRadius);
+ let orginY1 = Math.sin(item.arc) * (item.radius + lineRadius);
+
+ // line start
+ let orginX2 = Math.cos(item.arc) * item.radius;
+ let orginY2 = Math.sin(item.arc) * item.radius;
+
+ // text start
+ let orginX3 = orginX1 >= 0 ? orginX1 + config.pieChartTextPadding : orginX1 - config.pieChartTextPadding;
+ let orginY3 = orginY1;
+ let textWidth = measureText(item.text,item.textSize||config.fontSize);
+ let startY = orginY3;
+
+ if (lastTextObject && util.isSameXCoordinateArea(lastTextObject.start, {
+ x: orginX3
+ })) {
+ if (orginX3 > 0) {
+ startY = Math.min(orginY3, lastTextObject.start.y);
+ } else if (orginX1 < 0) {
+ startY = Math.max(orginY3, lastTextObject.start.y);
+ } else {
+ if (orginY3 > 0) {
+ startY = Math.max(orginY3, lastTextObject.start.y);
+ } else {
+ startY = Math.min(orginY3, lastTextObject.start.y);
+ }
+ }
+ }
+ if (orginX3 < 0) {
+ orginX3 -= textWidth;
+ }
+
+ let textObject = {
+ lineStart: {
+ x: orginX2,
+ y: orginY2
+ },
+ lineEnd: {
+ x: orginX1,
+ y: orginY1
+ },
+ start: {
+ x: orginX3,
+ y: startY
+ },
+ width: textWidth,
+ height: config.fontSize,
+ text: item.text,
+ color: item.color,
+ textColor: item.textColor,
+ textSize: item.textSize
+ };
+ lastTextObject = avoidCollision(textObject, lastTextObject);
+ textObjectCollection.push(lastTextObject);
+ }
+
+ for (let i = 0; i < textObjectCollection.length; i++) {
+ let item = textObjectCollection[i];
+ let lineStartPoistion = convertCoordinateOrigin(item.lineStart.x, item.lineStart.y, center);
+ let lineEndPoistion = convertCoordinateOrigin(item.lineEnd.x, item.lineEnd.y, center);
+ let textPosition = convertCoordinateOrigin(item.start.x, item.start.y, center);
+ context.setLineWidth(1 * opts.pixelRatio);
+ context.setFontSize(config.fontSize);
+ context.beginPath();
+ context.setStrokeStyle(item.color);
+ context.setFillStyle(item.color);
+ context.moveTo(lineStartPoistion.x, lineStartPoistion.y);
+ let curveStartX = item.start.x < 0 ? textPosition.x + item.width : textPosition.x;
+ let textStartX = item.start.x < 0 ? textPosition.x - 5 : textPosition.x + 5;
+ context.quadraticCurveTo(lineEndPoistion.x, lineEndPoistion.y, curveStartX, textPosition.y);
+ context.moveTo(lineStartPoistion.x, lineStartPoistion.y);
+ context.stroke();
+ context.closePath();
+ context.beginPath();
+ context.moveTo(textPosition.x + item.width, textPosition.y);
+ context.arc(curveStartX, textPosition.y, 2, 0, 2 * Math.PI);
+ context.closePath();
+ context.fill();
+ context.beginPath();
+ context.setFontSize(item.textSize || config.fontSize);
+ context.setFillStyle(item.textColor || '#666666');
+ context.fillText(item.text, textStartX, textPosition.y + 3);
+ context.closePath();
+ context.stroke();
+ context.closePath();
+ }
+}
+
+function drawToolTipSplitLine(offsetX, opts, config, context) {
+ var toolTipOption = opts.extra.tooltip || {};
+ toolTipOption.gridType = toolTipOption.gridType == undefined ? 'solid' : toolTipOption.gridType;
+ toolTipOption.dashLength = toolTipOption.dashLength == undefined ? 4 : toolTipOption.dashLength;
+ var startY = opts.area[0];
+ var endY = opts.height - opts.area[2];
+
+ if (toolTipOption.gridType == 'dash') {
+ context.setLineDash([toolTipOption.dashLength, toolTipOption.dashLength]);
+ }
+ context.setStrokeStyle(toolTipOption.gridColor || '#cccccc');
+ context.setLineWidth(1 * opts.pixelRatio);
+ context.beginPath();
+ context.moveTo(offsetX, startY);
+ context.lineTo(offsetX, endY);
+ context.stroke();
+ context.setLineDash([]);
+
+ if (toolTipOption.xAxisLabel) {
+ let labelText = opts.categories[opts.tooltip.index];
+ context.setFontSize(config.fontSize);
+ let textWidth = measureText(labelText, config.fontSize);
+
+ let textX = offsetX - 0.5 * textWidth;
+ let textY = endY;
+ context.beginPath();
+ context.setFillStyle(hexToRgb(toolTipOption.labelBgColor || config.toolTipBackground, toolTipOption.labelBgOpacity || config.toolTipOpacity));
+ context.setStrokeStyle(toolTipOption.labelBgColor || config.toolTipBackground);
+ context.setLineWidth(1 * opts.pixelRatio);
+ context.rect(textX - config.toolTipPadding, textY, textWidth + 2 * config.toolTipPadding, config.fontSize + 2 * config.toolTipPadding);
+ context.closePath();
+ context.stroke();
+ context.fill();
+
+ context.beginPath();
+ context.setFontSize(config.fontSize);
+ context.setFillStyle(toolTipOption.labelFontColor || config.fontColor);
+ context.fillText(String(labelText), textX, textY + config.toolTipPadding + config.fontSize);
+ context.closePath();
+ context.stroke();
+ }
+}
+
+function drawMarkLine(opts, config, context) {
+ let markLineOption = assign({}, {
+ type: 'solid',
+ dashLength: 4,
+ data: []
+ }, opts.extra.markLine);
+ let startX = opts.area[3];
+ let endX = opts.width - opts.area[1];
+ let points = calMarkLineData(markLineOption.data, opts);
+
+ for (let i = 0; i < points.length; i++) {
+ let item = assign({}, {
+ lineColor: '#DE4A42',
+ showLabel: false,
+ labelFontColor: '#666666',
+ labelBgColor: '#DFE8FF',
+ labelBgOpacity: 0.8,
+ yAxisIndex: 0
+ }, points[i]);
+
+ if (markLineOption.type == 'dash') {
+ context.setLineDash([markLineOption.dashLength, markLineOption.dashLength]);
+ }
+ context.setStrokeStyle(item.lineColor);
+ context.setLineWidth(1 * opts.pixelRatio);
+ context.beginPath();
+ context.moveTo(startX, item.y);
+ context.lineTo(endX, item.y);
+ context.stroke();
+ context.setLineDash([]);
+ if (item.showLabel) {
+ let labelText = opts.yAxis.format ? opts.yAxis.format(Number(item.value)) : item.value;
+ context.setFontSize(config.fontSize);
+ let textWidth = measureText(labelText, config.fontSize);
+ let bgStartX = opts.padding[3] + config.yAxisTitleWidth - config.toolTipPadding;
+ let bgEndX = Math.max(opts.area[3], textWidth + config.toolTipPadding * 2);
+ let bgWidth = bgEndX - bgStartX;
+
+ let textX = bgStartX + (bgWidth - textWidth) / 2;
+ let textY = item.y;
+ context.setFillStyle(hexToRgb(item.labelBgColor, item.labelBgOpacity));
+ context.setStrokeStyle(item.labelBgColor);
+ context.setLineWidth(1 * opts.pixelRatio);
+ context.beginPath();
+ context.rect(bgStartX, textY - 0.5 * config.fontSize - config.toolTipPadding, bgWidth, config.fontSize + 2 * config.toolTipPadding);
+ context.closePath();
+ context.stroke();
+ context.fill();
+
+ context.beginPath();
+ context.setFontSize(config.fontSize);
+ context.setFillStyle(item.labelFontColor);
+ context.fillText(String(labelText), textX, textY + 0.5 * config.fontSize);
+ context.stroke();
+ }
+ }
+}
+
+function drawToolTipHorizentalLine(opts, config, context, eachSpacing, xAxisPoints) {
+ var toolTipOption = assign({}, {
+ gridType: 'solid',
+ dashLength: 4
+ }, opts.extra.tooltip);
+
+ var startX = opts.area[3];
+ var endX = opts.width - opts.area[1];
+
+ if (toolTipOption.gridType == 'dash') {
+ context.setLineDash([toolTipOption.dashLength, toolTipOption.dashLength]);
+ }
+ context.setStrokeStyle(toolTipOption.gridColor || '#cccccc');
+ context.setLineWidth(1 * opts.pixelRatio);
+ context.beginPath();
+ context.moveTo(startX, opts.tooltip.offset.y);
+ context.lineTo(endX, opts.tooltip.offset.y);
+ context.stroke();
+ context.setLineDash([]);
+
+ if (toolTipOption.yAxisLabel) {
+ let labelText = calTooltipYAxisData(opts.tooltip.offset.y, opts.series, opts, config, eachSpacing);
+ let widthArr = opts.chartData.yAxisData.yAxisWidth;
+ let tStartLeft=opts.area[3];
+ let tStartRight=opts.width-opts.area[1];
+ for(let i=0;i opts.width) {
+ isOverRightBorder = true;
+ }
+ if (toolTipHeight + offset.y > opts.height) {
+ offset.y = opts.height - toolTipHeight;
+ }
+ // draw background rect
+ context.beginPath();
+ context.setFillStyle(hexToRgb(toolTipOption.bgColor || config.toolTipBackground, toolTipOption.bgOpacity || config.toolTipOpacity));
+ if (isOverRightBorder) {
+ context.moveTo(offset.x, offset.y + 10 * opts.pixelRatio);
+ context.lineTo(offset.x - arrowWidth, offset.y + 10 * opts.pixelRatio - 5 * opts.pixelRatio);
+ context.lineTo(offset.x - arrowWidth, offset.y);
+ context.lineTo(offset.x - arrowWidth - Math.round(toolTipWidth), offset.y);
+ context.lineTo(offset.x - arrowWidth - Math.round(toolTipWidth), offset.y + toolTipHeight);
+ context.lineTo(offset.x - arrowWidth, offset.y + toolTipHeight);
+ context.lineTo(offset.x - arrowWidth, offset.y + 10 * opts.pixelRatio + 5 * opts.pixelRatio);
+ context.lineTo(offset.x, offset.y + 10 * opts.pixelRatio);
+ } else {
+ context.moveTo(offset.x, offset.y + 10 * opts.pixelRatio);
+ context.lineTo(offset.x + arrowWidth, offset.y + 10 * opts.pixelRatio - 5 * opts.pixelRatio);
+ context.lineTo(offset.x + arrowWidth, offset.y);
+ context.lineTo(offset.x + arrowWidth + Math.round(toolTipWidth), offset.y);
+ context.lineTo(offset.x + arrowWidth + Math.round(toolTipWidth), offset.y + toolTipHeight);
+ context.lineTo(offset.x + arrowWidth, offset.y + toolTipHeight);
+ context.lineTo(offset.x + arrowWidth, offset.y + 10 * opts.pixelRatio + 5 * opts.pixelRatio);
+ context.lineTo(offset.x, offset.y + 10 * opts.pixelRatio);
+ }
+
+ context.closePath();
+ context.fill();
+
+ // draw legend
+ textList.forEach(function(item, index) {
+ if (item.color !== null) {
+ context.beginPath();
+ context.setFillStyle(item.color);
+ var startX = offset.x + arrowWidth + 2 * config.toolTipPadding;
+ var startY = offset.y + (config.toolTipLineHeight - config.fontSize) / 2 + config.toolTipLineHeight * index +
+ config.toolTipPadding + 1;
+ if (isOverRightBorder) {
+ startX = offset.x - toolTipWidth - arrowWidth + 2 * config.toolTipPadding;
+ }
+ context.fillRect(startX, startY, legendWidth, config.fontSize);
+ context.closePath();
+ }
+ });
+
+ // draw text list
+
+ textList.forEach(function(item, index) {
+ var startX = offset.x + arrowWidth + 2 * config.toolTipPadding + legendWidth + legendMarginRight;
+ if (isOverRightBorder) {
+ startX = offset.x - toolTipWidth - arrowWidth + 2 * config.toolTipPadding + +legendWidth + legendMarginRight;
+ }
+ var startY = offset.y + (config.toolTipLineHeight - config.fontSize) / 2 + config.toolTipLineHeight * index +
+ config.toolTipPadding;
+ context.beginPath();
+ context.setFontSize(config.fontSize);
+ context.setFillStyle(toolTipOption.fontColor);
+ context.fillText(item.text, startX, startY + config.fontSize);
+ context.closePath();
+ context.stroke();
+ });
+}
+
+function drawYAxisTitle(title, opts, config, context) {
+ var startX = config.xAxisHeight + (opts.height - config.xAxisHeight - measureText(title)) / 2;
+ context.save();
+ context.beginPath();
+ context.setFontSize(config.fontSize);
+ context.setFillStyle(opts.yAxis.titleFontColor || '#333333');
+ context.translate(0, opts.height);
+ context.rotate(-90 * Math.PI / 180);
+ context.fillText(title, startX, opts.padding[3] + 0.5 * config.fontSize);
+ context.closePath();
+ context.stroke();
+ context.restore();
+}
+
+function drawColumnDataPoints(series, opts, config, context) {
+ let process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1;
+ let xAxisData = opts.chartData.xAxisData,
+ xAxisPoints = xAxisData.xAxisPoints,
+ eachSpacing = xAxisData.eachSpacing;
+ let columnOption = assign({}, {
+ type: 'group',
+ width: eachSpacing / 2,
+ meter: {
+ border: 4,
+ fillColor: '#FFFFFF'
+ }
+ }, opts.extra.column);
+
+ let calPoints = [];
+ context.save();
+
+ let leftNum=-2;
+ let rightNum=xAxisPoints.length+2;
+
+ if (opts._scrollDistance_ && opts._scrollDistance_ !== 0 && opts.enableScroll === true) {
+ context.translate(opts._scrollDistance_, 0);
+ leftNum=Math.floor(-opts._scrollDistance_/eachSpacing)-2;
+ rightNum=leftNum+opts.xAxis.itemCount+4;
+ }
+ if (opts.tooltip && opts.tooltip.textList && opts.tooltip.textList.length && process === 1) {
+ drawToolTipSplitArea(opts.tooltip.offset.x, opts, config, context, eachSpacing);
+ }
+
+ series.forEach(function(eachSeries, seriesIndex) {
+ let ranges,minRange,maxRange;
+ ranges = [].concat(opts.chartData.yAxisData.ranges[eachSeries.index]);
+ minRange = ranges.pop();
+ maxRange = ranges.shift();
+
+ var data = eachSeries.data;
+ switch (columnOption.type) {
+ case 'group':
+ var points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process);
+ var tooltipPoints = getStackDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, seriesIndex, series, process);
+ calPoints.push(tooltipPoints);
+ points = fixColumeData(points, eachSpacing, series.length, seriesIndex, config, opts);
+ for(let i=0;ileftNum && ileftNum && i 0) {
+ height -= height0;
+ }
+ context.moveTo(startX, item.y);
+ context.fillRect(startX, item.y, item.width - 2, height);
+ context.closePath();
+ context.fill();
+ }
+ };
+ break;
+ case 'meter':
+ // 绘制温度计数据图
+ var points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process);
+ calPoints.push(points);
+ points = fixColumeMeterData(points, eachSpacing, series.length, seriesIndex, config, opts, columnOption.meter.border);
+ if (seriesIndex == 0) {
+ for(let i=0;ileftNum && i 0) {
+ context.beginPath();
+ context.setStrokeStyle(eachSeries.color);
+ context.setLineWidth(columnOption.meter.border * opts.pixelRatio);
+ context.moveTo(startX + columnOption.meter.border * 0.5, item.y + height);
+ context.lineTo(startX + columnOption.meter.border * 0.5, item.y + columnOption.meter.border * 0.5);
+ context.lineTo(startX + item.width - columnOption.meter.border * 0.5, item.y + columnOption.meter.border * 0.5);
+ context.lineTo(startX + item.width - columnOption.meter.border * 0.5, item.y + height);
+ context.stroke();
+ }
+ }
+ };
+ } else {
+ for(let i=0;ileftNum && i 5 && arguments[5] !== undefined ? arguments[5] : 1;
+ var candleOption = assign({}, {
+ color: {},
+ average: {}
+ }, opts.extra.candle);
+ candleOption.color = assign({}, {
+ upLine: '#f04864',
+ upFill: '#f04864',
+ downLine: '#2fc25b',
+ downFill: '#2fc25b'
+ }, candleOption.color);
+ candleOption.average = assign({}, {
+ show: false,
+ name: [],
+ day: [],
+ color: config.colors
+ }, candleOption.average);
+ opts.extra.candle = candleOption;
+
+ let xAxisData = opts.chartData.xAxisData,
+ xAxisPoints = xAxisData.xAxisPoints,
+ eachSpacing = xAxisData.eachSpacing;
+
+ let calPoints = [];
+
+ context.save();
+
+ let leftNum=-2;
+ let rightNum=xAxisPoints.length+2;
+ let leftSpace=0;
+ let rightSpace=opts.width+eachSpacing;
+
+ if (opts._scrollDistance_ && opts._scrollDistance_ !== 0 && opts.enableScroll === true) {
+ context.translate(opts._scrollDistance_, 0);
+ leftNum=Math.floor(-opts._scrollDistance_/eachSpacing)-2;
+ rightNum=leftNum+opts.xAxis.itemCount+4;
+ leftSpace=-opts._scrollDistance_-eachSpacing+opts.area[3];
+ rightSpace=leftSpace+(opts.xAxis.itemCount+4)*eachSpacing;
+ }
+
+ //画均线
+ if (candleOption.average.show) {
+ seriesMA.forEach(function(eachSeries, seriesIndex) {
+ let ranges,minRange,maxRange;
+ ranges = [].concat(opts.chartData.yAxisData.ranges[eachSeries.index]);
+ minRange = ranges.pop();
+ maxRange = ranges.shift();
+
+ var data = eachSeries.data;
+ var points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process);
+ var splitPointList = splitPoints(points);
+
+ for(let i=0;i leftSpace){
+ context.moveTo(item.x, item.y);
+ startPoint=1;
+ }
+ if (j > 0 && item.x > leftSpace && item.x < rightSpace) {
+ var ctrlPoint = createCurveControlPoints(points, j - 1);
+ context.bezierCurveTo(ctrlPoint.ctrA.x, ctrlPoint.ctrA.y, ctrlPoint.ctrB.x, ctrlPoint.ctrB.y,item.x, item.y);
+ }
+ }
+ context.moveTo(points[0].x, points[0].y);
+ }
+ context.closePath();
+ context.stroke();
+ }
+ });
+ }
+ //画K线
+ series.forEach(function(eachSeries, seriesIndex) {
+ let ranges,minRange,maxRange;
+ ranges = [].concat(opts.chartData.yAxisData.ranges[eachSeries.index]);
+ minRange = ranges.pop();
+ maxRange = ranges.shift();
+ var data = eachSeries.data;
+ var points = getCandleDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process);
+ calPoints.push(points);
+ var splitPointList = splitPoints(points);
+
+ for(let i=0;ileftNum && i 0) {
+ context.setStrokeStyle(candleOption.color.upLine);
+ context.setFillStyle(candleOption.color.upFill);
+ context.setLineWidth(1 * opts.pixelRatio);
+ context.moveTo(item[3].x, item[3].y); //顶点
+ context.lineTo(item[1].x, item[1].y); //收盘中间点
+ context.lineTo(item[1].x - eachSpacing / 4, item[1].y); //收盘左侧点
+ context.lineTo(item[0].x - eachSpacing / 4, item[0].y); //开盘左侧点
+ context.lineTo(item[0].x, item[0].y); //开盘中间点
+ context.lineTo(item[2].x, item[2].y); //底点
+ context.lineTo(item[0].x, item[0].y); //开盘中间点
+ context.lineTo(item[0].x + eachSpacing / 4, item[0].y); //开盘右侧点
+ context.lineTo(item[1].x + eachSpacing / 4, item[1].y); //收盘右侧点
+ context.lineTo(item[1].x, item[1].y); //收盘中间点
+ context.moveTo(item[3].x, item[3].y); //顶点
+ } else {
+ context.setStrokeStyle(candleOption.color.downLine);
+ context.setFillStyle(candleOption.color.downFill);
+ context.setLineWidth(1 * opts.pixelRatio);
+ context.moveTo(item[3].x, item[3].y); //顶点
+ context.lineTo(item[0].x, item[0].y); //开盘中间点
+ context.lineTo(item[0].x - eachSpacing / 4, item[0].y); //开盘左侧点
+ context.lineTo(item[1].x - eachSpacing / 4, item[1].y); //收盘左侧点
+ context.lineTo(item[1].x, item[1].y); //收盘中间点
+ context.lineTo(item[2].x, item[2].y); //底点
+ context.lineTo(item[1].x, item[1].y); //收盘中间点
+ context.lineTo(item[1].x + eachSpacing / 4, item[1].y); //收盘右侧点
+ context.lineTo(item[0].x + eachSpacing / 4, item[0].y); //开盘右侧点
+ context.lineTo(item[0].x, item[0].y); //开盘中间点
+ context.moveTo(item[3].x, item[3].y); //顶点
+ }
+ context.closePath();
+ context.fill();
+ context.stroke();
+ }
+ }
+ });
+
+ context.restore();
+
+ return {
+ xAxisPoints: xAxisPoints,
+ calPoints: calPoints,
+ eachSpacing: eachSpacing
+ };
+}
+
+function drawAreaDataPoints(series, opts, config, context) {
+ var process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1;
+ var areaOption = assign({},{
+ type: 'straight',
+ opacity: 0.2,
+ addLine: false,
+ width: 2,
+ gradient:false
+ },opts.extra.area);
+
+ let xAxisData = opts.chartData.xAxisData,
+ xAxisPoints = xAxisData.xAxisPoints,
+ eachSpacing = xAxisData.eachSpacing;
+
+ let endY = opts.height - opts.area[2];
+ let calPoints = [];
+
+ context.save();
+ let leftSpace=0;
+ let rightSpace=opts.width+eachSpacing;
+ if (opts._scrollDistance_ && opts._scrollDistance_ !== 0 && opts.enableScroll === true) {
+ context.translate(opts._scrollDistance_, 0);
+ leftSpace=-opts._scrollDistance_-eachSpacing+opts.area[3];
+ rightSpace=leftSpace+(opts.xAxis.itemCount+4)*eachSpacing;
+ }
+
+ series.forEach(function(eachSeries, seriesIndex) {
+ let ranges,minRange,maxRange;
+ ranges = [].concat(opts.chartData.yAxisData.ranges[eachSeries.index]);
+ minRange = ranges.pop();
+ maxRange = ranges.shift();
+ let data = eachSeries.data;
+ let points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process);
+ calPoints.push(points);
+
+ let splitPointList = splitPoints(points);
+ for (let i = 0; i < splitPointList.length; i++) {
+ let points = splitPointList[i];
+ // 绘制区域数
+ context.beginPath();
+ context.setStrokeStyle(hexToRgb(eachSeries.color, areaOption.opacity));
+ if(areaOption.gradient){
+ let gradient = context.createLinearGradient(0, opts.area[0], 0, opts.height-opts.area[2]);
+ gradient.addColorStop('0', hexToRgb(eachSeries.color, areaOption.opacity));
+ gradient.addColorStop('1.0',hexToRgb("#FFFFFF", 0.1));
+ context.setFillStyle(gradient);
+ }else{
+ context.setFillStyle(hexToRgb(eachSeries.color, areaOption.opacity));
+ }
+ context.setLineWidth(areaOption.width * opts.pixelRatio);
+ if (points.length > 1) {
+ let firstPoint = points[0];
+ let lastPoint = points[points.length - 1];
+ context.moveTo(firstPoint.x, firstPoint.y);
+ let startPoint=0;
+ if (areaOption.type === 'curve') {
+ for(let j=0;j leftSpace){
+ context.moveTo(item.x, item.y);
+ startPoint=1;
+ }
+ if (j > 0 && item.x > leftSpace && item.x < rightSpace) {
+ let ctrlPoint = createCurveControlPoints(points, j - 1);
+ context.bezierCurveTo(ctrlPoint.ctrA.x, ctrlPoint.ctrA.y, ctrlPoint.ctrB.x, ctrlPoint.ctrB.y,item.x, item.y);
+ }
+ };
+ } else {
+ for(let j=0;j leftSpace){
+ context.moveTo(item.x, item.y);
+ startPoint=1;
+ }
+ if (j > 0 && item.x > leftSpace && item.x < rightSpace) {
+ context.lineTo(item.x, item.y);
+ }
+ };
+ }
+
+ context.lineTo(lastPoint.x, endY);
+ context.lineTo(firstPoint.x, endY);
+ context.lineTo(firstPoint.x, firstPoint.y);
+ } else {
+ let item = points[0];
+ context.moveTo(item.x - eachSpacing / 2, item.y);
+ context.lineTo(item.x + eachSpacing / 2, item.y);
+ context.lineTo(item.x + eachSpacing / 2, endY);
+ context.lineTo(item.x - eachSpacing / 2, endY);
+ context.moveTo(item.x - eachSpacing / 2, item.y);
+ }
+ context.closePath();
+ context.fill();
+
+ //画连线
+ if (areaOption.addLine) {
+ if (eachSeries.lineType == 'dash') {
+ let dashLength = eachSeries.dashLength?eachSeries.dashLength:8;
+ dashLength *= opts.pixelRatio;
+ context.setLineDash([dashLength, dashLength]);
+ }
+ context.beginPath();
+ context.setStrokeStyle(eachSeries.color);
+ context.setLineWidth(areaOption.width * opts.pixelRatio);
+ if (points.length === 1) {
+ context.moveTo(points[0].x, points[0].y);
+ context.arc(points[0].x, points[0].y, 1, 0, 2 * Math.PI);
+ } else {
+ context.moveTo(points[0].x, points[0].y);
+ let startPoint=0;
+ if (areaOption.type === 'curve') {
+ for(let j=0;j leftSpace){
+ context.moveTo(item.x, item.y);
+ startPoint=1;
+ }
+ if (j > 0 && item.x > leftSpace && item.x < rightSpace) {
+ let ctrlPoint = createCurveControlPoints(points, j - 1);
+ context.bezierCurveTo(ctrlPoint.ctrA.x, ctrlPoint.ctrA.y, ctrlPoint.ctrB.x, ctrlPoint.ctrB.y,item.x,item.y);
+ }
+ };
+ } else {
+ for(let j=0;j leftSpace){
+ context.moveTo(item.x, item.y);
+ startPoint=1;
+ }
+ if (j > 0 && item.x > leftSpace && item.x < rightSpace) {
+ context.lineTo(item.x, item.y);
+ }
+ };
+ }
+ context.moveTo(points[0].x, points[0].y);
+ }
+ context.stroke();
+ context.setLineDash([]);
+ }
+ }
+
+ //画点
+ if (opts.dataPointShape !== false) {
+ drawPointShape(points, eachSeries.color, eachSeries.pointShape, context, opts);
+ }
+
+ });
+
+ if (opts.dataLabel !== false && process === 1) {
+ series.forEach(function(eachSeries, seriesIndex) {
+ let ranges,minRange,maxRange;
+ ranges = [].concat(opts.chartData.yAxisData.ranges[eachSeries.index]);
+ minRange = ranges.pop();
+ maxRange = ranges.shift();
+ var data = eachSeries.data;
+ var points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process);
+ drawPointText(points, eachSeries, config, context);
+ });
+ }
+
+ context.restore();
+
+ return {
+ xAxisPoints: xAxisPoints,
+ calPoints: calPoints,
+ eachSpacing: eachSpacing
+ };
+}
+
+function drawLineDataPoints(series, opts, config, context) {
+ var process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1;
+ var lineOption = assign({},{
+ type: 'straight',
+ width: 2
+ },opts.extra.line);
+ lineOption.width *=opts.pixelRatio;
+
+ let xAxisData = opts.chartData.xAxisData,
+ xAxisPoints = xAxisData.xAxisPoints,
+ eachSpacing = xAxisData.eachSpacing;
+ var calPoints = [];
+
+ context.save();
+ let leftSpace=0;
+ let rightSpace=opts.width+eachSpacing;
+ if (opts._scrollDistance_ && opts._scrollDistance_ !== 0 && opts.enableScroll === true) {
+ context.translate(opts._scrollDistance_, 0);
+ leftSpace=-opts._scrollDistance_-eachSpacing+opts.area[3];
+ rightSpace=leftSpace+(opts.xAxis.itemCount+4)*eachSpacing;
+ }
+
+ series.forEach(function(eachSeries, seriesIndex) {
+ let ranges,minRange,maxRange;
+ ranges = [].concat(opts.chartData.yAxisData.ranges[eachSeries.index]);
+ minRange = ranges.pop();
+ maxRange = ranges.shift();
+ var data = eachSeries.data;
+ var points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process);
+ calPoints.push(points);
+ var splitPointList = splitPoints(points);
+
+ if (eachSeries.lineType == 'dash') {
+ let dashLength = eachSeries.dashLength?eachSeries.dashLength:8;
+ dashLength *= opts.pixelRatio;
+ context.setLineDash([dashLength, dashLength]);
+ }
+ context.beginPath();
+ context.setStrokeStyle(eachSeries.color);
+ context.setLineWidth(lineOption.width);
+
+ splitPointList.forEach(function(points, index) {
+
+ if (points.length === 1) {
+ context.moveTo(points[0].x, points[0].y);
+ context.arc(points[0].x, points[0].y, 1, 0, 2 * Math.PI);
+ } else {
+ context.moveTo(points[0].x, points[0].y);
+ let startPoint=0;
+ if (lineOption.type === 'curve') {
+ for(let j=0;j leftSpace){
+ context.moveTo(item.x, item.y);
+ startPoint=1;
+ }
+ if (j > 0 && item.x > leftSpace && item.x < rightSpace) {
+ var ctrlPoint = createCurveControlPoints(points, j - 1);
+ context.bezierCurveTo(ctrlPoint.ctrA.x, ctrlPoint.ctrA.y, ctrlPoint.ctrB.x, ctrlPoint.ctrB.y,item.x, item.y);
+ }
+ };
+ } else {
+ for(let j=0;j leftSpace){
+ context.moveTo(item.x, item.y);
+ startPoint=1;
+ }
+ if (j > 0 && item.x > leftSpace && item.x < rightSpace) {
+ context.lineTo(item.x, item.y);
+ }
+ };
+ }
+ context.moveTo(points[0].x, points[0].y);
+ }
+
+ });
+
+ context.stroke();
+ context.setLineDash([]);
+
+ if (opts.dataPointShape !== false) {
+ drawPointShape(points, eachSeries.color, eachSeries.pointShape, context, opts);
+ }
+ });
+
+ if (opts.dataLabel !== false && process === 1) {
+ series.forEach(function(eachSeries, seriesIndex) {
+ let ranges,minRange,maxRange;
+ ranges = [].concat(opts.chartData.yAxisData.ranges[eachSeries.index]);
+ minRange = ranges.pop();
+ maxRange = ranges.shift();
+ var data = eachSeries.data;
+ var points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process);
+ drawPointText(points, eachSeries, config, context);
+ });
+ }
+
+ context.restore();
+
+ return {
+ xAxisPoints: xAxisPoints,
+ calPoints: calPoints,
+ eachSpacing: eachSpacing
+ };
+}
+
+function drawMixDataPoints(series, opts, config, context) {
+ let process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1;
+
+ let xAxisData = opts.chartData.xAxisData,
+ xAxisPoints = xAxisData.xAxisPoints,
+ eachSpacing = xAxisData.eachSpacing;
+
+ let endY = opts.height - opts.area[2];
+ let calPoints = [];
+
+ var columnIndex = 0;
+ var columnLength = 0;
+ series.forEach(function(eachSeries, seriesIndex) {
+ if (eachSeries.type == 'column') {
+ columnLength += 1;
+ }
+ });
+ context.save();
+ let leftNum=-2;
+ let rightNum=xAxisPoints.length+2;
+ let leftSpace=0;
+ let rightSpace=opts.width+eachSpacing;
+ if (opts._scrollDistance_ && opts._scrollDistance_ !== 0 && opts.enableScroll === true) {
+ context.translate(opts._scrollDistance_, 0);
+ leftNum=Math.floor(-opts._scrollDistance_/eachSpacing)-2;
+ rightNum=leftNum+opts.xAxis.itemCount+4;
+ leftSpace=-opts._scrollDistance_-eachSpacing+opts.area[3];
+ rightSpace=leftSpace+(opts.xAxis.itemCount+4)*eachSpacing;
+ }
+
+ series.forEach(function(eachSeries, seriesIndex) {
+ let ranges,minRange,maxRange;
+
+ ranges = [].concat(opts.chartData.yAxisData.ranges[eachSeries.index]);
+ minRange = ranges.pop();
+ maxRange = ranges.shift();
+
+ var data = eachSeries.data;
+ var points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process);
+ calPoints.push(points);
+
+ // 绘制柱状数据图
+ if (eachSeries.type == 'column') {
+ points = fixColumeData(points, eachSpacing, columnLength, columnIndex, config, opts);
+ for(let i=0;ileftNum && i 1) {
+ var firstPoint = points[0];
+ let lastPoint = points[points.length - 1];
+ context.moveTo(firstPoint.x, firstPoint.y);
+ let startPoint=0;
+ if (eachSeries.style === 'curve') {
+ for(let j=0;j leftSpace){
+ context.moveTo(item.x, item.y);
+ startPoint=1;
+ }
+ if (j > 0 && item.x > leftSpace && item.x < rightSpace) {
+ var ctrlPoint = createCurveControlPoints(points, j - 1);
+ context.bezierCurveTo(ctrlPoint.ctrA.x, ctrlPoint.ctrA.y, ctrlPoint.ctrB.x, ctrlPoint.ctrB.y, item.x, item.y);
+ }
+ };
+ } else {
+ for(let j=0;j leftSpace){
+ context.moveTo(item.x, item.y);
+ startPoint=1;
+ }
+ if (j > 0 && item.x > leftSpace && item.x < rightSpace) {
+ context.lineTo(item.x, item.y);
+ }
+ };
+ }
+ context.lineTo(lastPoint.x, endY);
+ context.lineTo(firstPoint.x, endY);
+ context.lineTo(firstPoint.x, firstPoint.y);
+ } else {
+ let item = points[0];
+ context.moveTo(item.x - eachSpacing / 2, item.y);
+ context.lineTo(item.x + eachSpacing / 2, item.y);
+ context.lineTo(item.x + eachSpacing / 2, endY);
+ context.lineTo(item.x - eachSpacing / 2, endY);
+ context.moveTo(item.x - eachSpacing / 2, item.y);
+ }
+ context.closePath();
+ context.fill();
+ }
+ }
+
+ // 绘制折线数据图
+ if (eachSeries.type == 'line') {
+ var splitPointList = splitPoints(points);
+ splitPointList.forEach(function(points, index) {
+ if (eachSeries.lineType == 'dash') {
+ let dashLength = eachSeries.dashLength?eachSeries.dashLength:8;
+ dashLength *= opts.pixelRatio;
+ context.setLineDash([dashLength, dashLength]);
+ }
+ context.beginPath();
+ context.setStrokeStyle(eachSeries.color);
+ context.setLineWidth(2 * opts.pixelRatio);
+ if (points.length === 1) {
+ context.moveTo(points[0].x, points[0].y);
+ context.arc(points[0].x, points[0].y, 1, 0, 2 * Math.PI);
+ } else {
+ context.moveTo(points[0].x, points[0].y);
+ let startPoint=0;
+ if (eachSeries.style == 'curve') {
+ for(let j=0;j leftSpace){
+ context.moveTo(item.x, item.y);
+ startPoint=1;
+ }
+ if (j > 0 && item.x > leftSpace && item.x < rightSpace) {
+ var ctrlPoint = createCurveControlPoints(points, j - 1);
+ context.bezierCurveTo(ctrlPoint.ctrA.x, ctrlPoint.ctrA.y, ctrlPoint.ctrB.x, ctrlPoint.ctrB.y,item.x,item.y);
+ }
+ }
+ } else {
+ for(let j=0;j leftSpace){
+ context.moveTo(item.x, item.y);
+ startPoint=1;
+ }
+ if (j > 0 && item.x > leftSpace && item.x < rightSpace) {
+ context.lineTo(item.x, item.y);
+ }
+ }
+ }
+ context.moveTo(points[0].x, points[0].y);
+ }
+ context.stroke();
+ context.setLineDash([]);
+ });
+ }
+
+ // 绘制点数据图
+ if (eachSeries.type == 'point') {
+ eachSeries.addPoint = true;
+ }
+
+ if (eachSeries.addPoint == true && eachSeries.type !== 'column' ) {
+ drawPointShape(points, eachSeries.color, eachSeries.pointShape, context, opts);
+ }
+ });
+ if (opts.dataLabel !== false && process === 1) {
+ var columnIndex = 0;
+ series.forEach(function(eachSeries, seriesIndex) {
+ let ranges,minRange,maxRange;
+
+ ranges = [].concat(opts.chartData.yAxisData.ranges[eachSeries.index]);
+ minRange = ranges.pop();
+ maxRange = ranges.shift();
+
+ var data = eachSeries.data;
+ var points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process);
+ if (eachSeries.type !== 'column') {
+ drawPointText(points, eachSeries, config, context);
+ } else {
+ points = fixColumeData(points, eachSpacing, columnLength, columnIndex, config, opts);
+ drawPointText(points, eachSeries, config, context);
+ columnIndex += 1;
+ }
+
+ });
+ }
+
+ context.restore();
+
+ return {
+ xAxisPoints: xAxisPoints,
+ calPoints: calPoints,
+ eachSpacing: eachSpacing,
+ }
+}
+
+function drawToolTipBridge(opts, config, context, process, eachSpacing, xAxisPoints) {
+ var toolTipOption = opts.extra.tooltip || {};
+ if (toolTipOption.horizentalLine && opts.tooltip && process === 1 && (opts.type == 'line' || opts.type == 'area' || opts.type == 'column' || opts.type == 'candle' || opts.type == 'mix')) {
+ drawToolTipHorizentalLine(opts, config, context, eachSpacing, xAxisPoints)
+ }
+ context.save();
+ if (opts._scrollDistance_ && opts._scrollDistance_ !== 0 && opts.enableScroll === true) {
+ context.translate(opts._scrollDistance_, 0);
+ }
+ if (opts.tooltip && opts.tooltip.textList && opts.tooltip.textList.length && process === 1) {
+ drawToolTip(opts.tooltip.textList, opts.tooltip.offset, opts, config, context, eachSpacing, xAxisPoints);
+ }
+ context.restore();
+
+}
+
+function drawXAxis(categories, opts, config, context) {
+
+ let xAxisData = opts.chartData.xAxisData,
+ xAxisPoints = xAxisData.xAxisPoints,
+ startX = xAxisData.startX,
+ endX = xAxisData.endX,
+ eachSpacing = xAxisData.eachSpacing;
+ var boundaryGap='center';
+ if (opts.type == 'line'||opts.type == 'area'){
+ boundaryGap=opts.xAxis.boundaryGap;
+ }
+ var startY = opts.height - opts.area[2];
+ var endY = opts.area[0];
+
+ //绘制滚动条
+ if (opts.enableScroll && opts.xAxis.scrollShow) {
+ var scrollY = opts.height - opts.area[2] + config.xAxisHeight;
+ var scrollScreenWidth = endX - startX;
+ var scrollTotalWidth = eachSpacing * (xAxisPoints.length - 1);
+ var scrollWidth = scrollScreenWidth * scrollScreenWidth / scrollTotalWidth;
+ var scrollLeft = 0;
+ if (opts._scrollDistance_) {
+ scrollLeft = -opts._scrollDistance_ * (scrollScreenWidth) / scrollTotalWidth;
+ }
+ context.beginPath();
+ context.setLineCap('round');
+ context.setLineWidth(6 * opts.pixelRatio);
+ context.setStrokeStyle(opts.xAxis.scrollBackgroundColor || "#EFEBEF");
+ context.moveTo(startX, scrollY);
+ context.lineTo(endX, scrollY);
+ context.stroke();
+ context.closePath();
+ context.beginPath();
+ context.setLineCap('round');
+ context.setLineWidth(6 * opts.pixelRatio);
+ context.setStrokeStyle(opts.xAxis.scrollColor || "#A6A6A6");
+ context.moveTo(startX + scrollLeft, scrollY);
+ context.lineTo(startX + scrollLeft + scrollWidth, scrollY);
+ context.stroke();
+ context.closePath();
+ context.setLineCap('butt');
+ }
+
+ context.save();
+
+ if (opts._scrollDistance_ && opts._scrollDistance_ !== 0) {
+ context.translate(opts._scrollDistance_, 0);
+ }
+
+ //绘制X轴刻度线
+ if (opts.xAxis.calibration === true) {
+ context.setStrokeStyle(opts.xAxis.gridColor || "#cccccc");
+ context.setLineCap('butt');
+ context.setLineWidth(1 * opts.pixelRatio);
+ xAxisPoints.forEach(function(item, index) {
+ if (index > 0) {
+ context.beginPath();
+ context.moveTo(item - eachSpacing / 2, startY);
+ context.lineTo(item - eachSpacing / 2, startY + 3 * opts.pixelRatio);
+ context.closePath();
+ context.stroke();
+ }
+ });
+ }
+ //绘制X轴网格
+ if (opts.xAxis.disableGrid !== true) {
+ context.setStrokeStyle(opts.xAxis.gridColor || "#cccccc");
+ context.setLineCap('butt');
+ context.setLineWidth(1 * opts.pixelRatio);
+ if (opts.xAxis.gridType == 'dash') {
+ context.setLineDash([opts.xAxis.dashLength, opts.xAxis.dashLength]);
+ }
+ opts.xAxis.gridEval = opts.xAxis.gridEval || 1;
+ xAxisPoints.forEach(function(item, index) {
+ if (index % opts.xAxis.gridEval == 0) {
+ context.beginPath();
+ context.moveTo(item, startY);
+ context.lineTo(item, endY);
+ context.stroke();
+ }
+ });
+ context.setLineDash([]);
+ }
+
+
+ //绘制X轴文案
+ if (opts.xAxis.disabled !== true) {
+ // 对X轴列表做抽稀处理
+ //默认全部显示X轴标签
+ let maxXAxisListLength = categories.length;
+ //如果设置了X轴单屏数量
+ if (opts.xAxis.labelCount) {
+ //如果设置X轴密度
+ if (opts.xAxis.itemCount) {
+ maxXAxisListLength = Math.ceil(categories.length / opts.xAxis.itemCount * opts.xAxis.labelCount);
+ } else {
+ maxXAxisListLength = opts.xAxis.labelCount;
+ }
+ maxXAxisListLength -= 1;
+ }
+
+ let ratio = Math.ceil(categories.length / maxXAxisListLength);
+
+ let newCategories = [];
+ let cgLength = categories.length;
+ for (let i = 0; i < cgLength; i++) {
+ if (i % ratio !== 0) {
+ newCategories.push("");
+ } else {
+ newCategories.push(categories[i]);
+ }
+ }
+ newCategories[cgLength - 1] = categories[cgLength - 1];
+
+ var xAxisFontSize = opts.xAxis.fontSize || config.fontSize;
+ if (config._xAxisTextAngle_ === 0) {
+ newCategories.forEach(function(item, index) {
+ var offset = - measureText(String(item), xAxisFontSize) / 2;
+ if(boundaryGap == 'center'){
+ offset+=eachSpacing / 2;
+ }
+ var scrollHeight=0;
+ if(opts.xAxis.scrollShow){
+ scrollHeight=6*opts.pixelRatio;
+ }
+ context.beginPath();
+ context.setFontSize(xAxisFontSize);
+ context.setFillStyle(opts.xAxis.fontColor || '#666666');
+ context.fillText(String(item), xAxisPoints[index] + offset, startY + xAxisFontSize + (config.xAxisHeight - scrollHeight - xAxisFontSize) / 2);
+ context.closePath();
+ context.stroke();
+ });
+
+ } else {
+ newCategories.forEach(function(item, index) {
+ context.save();
+ context.beginPath();
+ context.setFontSize(xAxisFontSize);
+ context.setFillStyle(opts.xAxis.fontColor || '#666666');
+ var textWidth = measureText(String(item),xAxisFontSize);
+ var offset = - textWidth;
+ if(boundaryGap == 'center'){
+ offset+=eachSpacing / 2;
+ }
+ var _calRotateTranslate = calRotateTranslate(xAxisPoints[index] + eachSpacing / 2, startY + xAxisFontSize / 2 + 5, opts.height),
+ transX = _calRotateTranslate.transX,
+ transY = _calRotateTranslate.transY;
+
+ context.rotate(-1 * config._xAxisTextAngle_);
+ context.translate(transX, transY);
+ context.fillText(String(item), xAxisPoints[index] + offset, startY + xAxisFontSize + 5);
+ context.closePath();
+ context.stroke();
+ context.restore();
+ });
+ }
+ }
+ context.restore();
+
+ //绘制X轴轴线
+ if(opts.xAxis.axisLine){
+ context.beginPath();
+ context.setStrokeStyle(opts.xAxis.axisLineColor);
+ context.setLineWidth(1 * opts.pixelRatio);
+ context.moveTo(startX,opts.height-opts.area[2]);
+ context.lineTo(endX,opts.height-opts.area[2]);
+ context.stroke();
+ }
+}
+
+function drawYAxisGrid(categories, opts, config, context) {
+ if (opts.yAxis.disableGrid === true) {
+ return;
+ }
+ let spacingValid = opts.height - opts.area[0] - opts.area[2];
+ let eachSpacing = spacingValid / opts.yAxis.splitNumber;
+ let startX = opts.area[3];
+ let xAxisPoints = opts.chartData.xAxisData.xAxisPoints,
+ xAxiseachSpacing = opts.chartData.xAxisData.eachSpacing;
+ let TotalWidth = xAxiseachSpacing * (xAxisPoints.length - 1);
+ let endX = startX + TotalWidth;
+
+ let points = [];
+ for (let i = 0; i < opts.yAxis.splitNumber + 1; i++) {
+ points.push(opts.height - opts.area[2] - eachSpacing * i);
+ }
+
+ context.save();
+ if (opts._scrollDistance_ && opts._scrollDistance_ !== 0) {
+ context.translate(opts._scrollDistance_, 0);
+ }
+
+ if (opts.yAxis.gridType == 'dash') {
+ context.setLineDash([opts.yAxis.dashLength, opts.yAxis.dashLength]);
+ }
+ context.setStrokeStyle(opts.yAxis.gridColor);
+ context.setLineWidth(1 * opts.pixelRatio);
+ points.forEach(function(item, index) {
+ context.beginPath();
+ context.moveTo(startX, item);
+ context.lineTo(endX, item);
+ context.stroke();
+ });
+ context.setLineDash([]);
+
+ context.restore();
+}
+
+function drawYAxis(series, opts, config, context) {
+ if (opts.yAxis.disabled === true) {
+ return;
+ }
+ var spacingValid = opts.height - opts.area[0] - opts.area[2];
+ var eachSpacing = spacingValid / opts.yAxis.splitNumber;
+ var startX = opts.area[3];
+ var endX = opts.width - opts.area[1];
+ var endY = opts.height - opts.area[2];
+ var fillEndY = endY + config.xAxisHeight;
+ if (opts.xAxis.scrollShow) {
+ fillEndY -= 3 * opts.pixelRatio;
+ }
+ if (opts.xAxis.rotateLabel){
+ fillEndY = opts.height - opts.area[2]+3;
+ }
+ // set YAxis background
+ context.beginPath();
+ context.setFillStyle(opts.background || '#ffffff');
+ if (opts._scrollDistance_ < 0) {
+ context.fillRect(0, 0, startX, fillEndY);
+ }
+ if(opts.enableScroll == true){
+ context.fillRect(endX, 0, opts.width, fillEndY);
+ }
+ context.closePath();
+ context.stroke();
+
+ var points = [];
+ for (let i = 0; i <= opts.yAxis.splitNumber; i++) {
+ points.push(opts.area[0] + eachSpacing * i);
+ }
+
+ let tStartLeft=opts.area[3];
+ let tStartRight=opts.width-opts.area[1];
+
+ for (let i = 0; i < opts.yAxis.data.length; i++) {
+ let yData = opts.yAxis.data[i];
+ if(yData.disabled !== true){
+ let rangesFormat = opts.chartData.yAxisData.rangesFormat[i];
+ let yAxisFontSize = yData.fontSize || config.fontSize;
+ let yAxisWidth = opts.chartData.yAxisData.yAxisWidth[i];
+ //画Y轴刻度及文案
+ rangesFormat.forEach(function(item, index) {
+ var pos = points[index] ? points[index] : endY;
+ context.beginPath();
+ context.setFontSize(yAxisFontSize);
+ context.setLineWidth(1*opts.pixelRatio);
+ context.setStrokeStyle(yData.axisLineColor||'#cccccc');
+ context.setFillStyle(yData.fontColor|| '#666666');
+ if(yAxisWidth.position=='left'){
+ context.fillText(String(item), tStartLeft - yAxisWidth.width , pos + yAxisFontSize / 2);
+ //画刻度线
+ if(yData.calibration==true){
+ context.moveTo(tStartLeft,pos);
+ context.lineTo(tStartLeft - 3*opts.pixelRatio,pos);
+ }
+ }else{
+ context.fillText(String(item), tStartRight + 4*opts.pixelRatio, pos + yAxisFontSize / 2);
+ //画刻度线
+ if(yData.calibration==true){
+ context.moveTo(tStartRight,pos);
+ context.lineTo(tStartRight + 3*opts.pixelRatio,pos);
+ }
+ }
+ context.closePath();
+ context.stroke();
+ });
+ //画Y轴轴线
+ if (yData.axisLine!==false) {
+ context.beginPath();
+ context.setStrokeStyle(yData.axisLineColor||'#cccccc');
+ context.setLineWidth(1 * opts.pixelRatio);
+ if(yAxisWidth.position=='left'){
+ context.moveTo(tStartLeft,opts.height-opts.area[2]);
+ context.lineTo(tStartLeft,opts.area[0]);
+ }else{
+ context.moveTo(tStartRight,opts.height-opts.area[2]);
+ context.lineTo(tStartRight,opts.area[0]);
+ }
+ context.stroke();
+ }
+
+ //画Y轴标题
+ if (opts.yAxis.showTitle) {
+
+ let titleFontSize = yData.titleFontSize || config.fontSize;
+ let title = yData.title;
+ context.beginPath();
+ context.setFontSize(titleFontSize);
+ context.setFillStyle(yData.titleFontColor || '#666666');
+ if(yAxisWidth.position=='left'){
+ context.fillText(title, tStartLeft - measureText(title,titleFontSize)/2, opts.area[0]-10*opts.pixelRatio);
+ }else{
+ context.fillText(title,tStartRight - measureText(title,titleFontSize)/2, opts.area[0]-10*opts.pixelRatio);
+ }
+ context.closePath();
+ context.stroke();
+ }
+ if(yAxisWidth.position=='left'){
+ tStartLeft -=(yAxisWidth.width + opts.yAxis.padding);
+ }else{
+ tStartRight +=yAxisWidth.width+ opts.yAxis.padding;
+ }
+ }
+ }
+}
+
+function drawLegend(series, opts, config, context, chartData) {
+ if (opts.legend.show === false) {
+ return;
+ }
+ let legendData = chartData.legendData;
+ let legendList = legendData.points;
+ let legendArea = legendData.area;
+ let padding = opts.legend.padding;
+ let fontSize = opts.legend.fontSize;
+ let shapeWidth = 15 * opts.pixelRatio;
+ let shapeRight = 5 * opts.pixelRatio;
+ let itemGap = opts.legend.itemGap;
+ let lineHeight = Math.max(opts.legend.lineHeight * opts.pixelRatio, fontSize);
+
+ //画背景及边框
+ context.beginPath();
+ context.setLineWidth(opts.legend.borderWidth);
+ context.setStrokeStyle(opts.legend.borderColor);
+ context.setFillStyle(opts.legend.backgroundColor);
+ context.moveTo(legendArea.start.x, legendArea.start.y);
+ context.rect(legendArea.start.x, legendArea.start.y, legendArea.width, legendArea.height);
+ context.closePath();
+ context.fill();
+ context.stroke();
+
+ legendList.forEach(function(itemList, listIndex) {
+ let width = 0;
+ let height = 0;
+ width = legendData.widthArr[listIndex];
+ height = legendData.heightArr[listIndex];
+ let startX = 0;
+ let startY = 0;
+ if (opts.legend.position == 'top' || opts.legend.position == 'bottom') {
+ startX = legendArea.start.x + (legendArea.width - width) / 2;
+ startY = legendArea.start.y + padding + listIndex * lineHeight;
+ } else {
+ if (listIndex == 0) {
+ width = 0;
+ } else {
+ width = legendData.widthArr[listIndex - 1];
+ }
+ startX = legendArea.start.x + padding + width;
+ startY = legendArea.start.y + padding + (legendArea.height - height) / 2;
+ }
+
+ context.setFontSize(config.fontSize);
+ for (let i = 0; i < itemList.length; i++) {
+ let item = itemList[i];
+ item.area = [0, 0, 0, 0];
+ item.area[0] = startX;
+ item.area[1] = startY;
+ item.area[3] = startY + lineHeight;
+ context.beginPath();
+ context.setLineWidth(1 * opts.pixelRatio);
+ context.setStrokeStyle(item.show ? item.color : opts.legend.hiddenColor);
+ context.setFillStyle(item.show ? item.color : opts.legend.hiddenColor);
+ switch (item.legendShape) {
+ case 'line':
+ context.moveTo(startX, startY + 0.5 * lineHeight - 2 * opts.pixelRatio);
+ context.fillRect(startX, startY + 0.5 * lineHeight - 2 * opts.pixelRatio, 15 * opts.pixelRatio, 4 * opts.pixelRatio);
+ break;
+ case 'triangle':
+ context.moveTo(startX + 7.5 * opts.pixelRatio, startY + 0.5 * lineHeight - 5 * opts.pixelRatio);
+ context.lineTo(startX + 2.5 * opts.pixelRatio, startY + 0.5 * lineHeight + 5 * opts.pixelRatio);
+ context.lineTo(startX + 12.5 * opts.pixelRatio, startY + 0.5 * lineHeight + 5 * opts.pixelRatio);
+ context.lineTo(startX + 7.5 * opts.pixelRatio, startY + 0.5 * lineHeight - 5 * opts.pixelRatio);
+ break;
+ case 'diamond':
+ context.moveTo(startX + 7.5 * opts.pixelRatio, startY + 0.5 * lineHeight - 5 * opts.pixelRatio);
+ context.lineTo(startX + 2.5 * opts.pixelRatio, startY + 0.5 * lineHeight);
+ context.lineTo(startX + 7.5 * opts.pixelRatio, startY + 0.5 * lineHeight + 5 * opts.pixelRatio);
+ context.lineTo(startX + 12.5 * opts.pixelRatio, startY + 0.5 * lineHeight);
+ context.lineTo(startX + 7.5 * opts.pixelRatio, startY + 0.5 * lineHeight - 5 * opts.pixelRatio);
+ break;
+ case 'circle':
+ context.moveTo(startX + 7.5 * opts.pixelRatio, startY + 0.5 * lineHeight);
+ context.arc(startX + 7.5 * opts.pixelRatio, startY + 0.5 * lineHeight, 5 * opts.pixelRatio, 0, 2 * Math.PI);
+ break;
+ case 'rect':
+ context.moveTo(startX, startY + 0.5 * lineHeight - 5 * opts.pixelRatio);
+ context.fillRect(startX, startY + 0.5 * lineHeight - 5 * opts.pixelRatio, 15 * opts.pixelRatio, 10 * opts.pixelRatio);
+ break;
+ default:
+ context.moveTo(startX, startY + 0.5 * lineHeight - 5 * opts.pixelRatio);
+ context.fillRect(startX, startY + 0.5 * lineHeight - 5 * opts.pixelRatio, 15 * opts.pixelRatio, 10 * opts.pixelRatio);
+ }
+ context.closePath();
+ context.fill();
+ context.stroke();
+
+ startX += shapeWidth + shapeRight;
+ let fontTrans = 0.5 * lineHeight + 0.5 * fontSize - 2;
+ context.beginPath();
+ context.setFontSize(fontSize);
+ context.setFillStyle(item.show ? opts.legend.fontColor : opts.legend.hiddenColor);
+ context.fillText(item.name, startX, startY + fontTrans);
+ context.closePath();
+ context.stroke();
+ if (opts.legend.position == 'top' || opts.legend.position == 'bottom') {
+ startX += measureText(item.name, fontSize) + itemGap;
+ item.area[2] = startX;
+ } else {
+ item.area[2] = startX + measureText(item.name, fontSize) + itemGap;;
+ startX -= shapeWidth + shapeRight;
+ startY += lineHeight;
+ }
+ }
+ });
+}
+
+function drawPieDataPoints(series, opts, config, context) {
+ var process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1;
+ var pieOption = assign({}, {
+ activeOpacity: 0.5,
+ activeRadius: 10 * opts.pixelRatio,
+ offsetAngle: 0,
+ labelWidth: 15 * opts.pixelRatio,
+ ringWidth: 0,
+ border:false,
+ borderWidth:2,
+ borderColor:'#FFFFFF'
+ }, opts.extra.pie);
+ var centerPosition = {
+ x: opts.area[3] + (opts.width - opts.area[1] - opts.area[3]) / 2,
+ y: opts.area[0] + (opts.height - opts.area[0] - opts.area[2]) / 2
+ };
+ if (config.pieChartLinePadding == 0) {
+ config.pieChartLinePadding = pieOption.activeRadius;
+ }
+
+ var radius = Math.min((opts.width - opts.area[1] - opts.area[3]) / 2 - config.pieChartLinePadding - config.pieChartTextPadding - config._pieTextMaxLength_, (opts.height - opts.area[0] - opts.area[2]) / 2 - config.pieChartLinePadding - config.pieChartTextPadding);
+
+ series = getPieDataPoints(series, radius, process);
+
+ var activeRadius = pieOption.activeRadius;
+
+ series = series.map(function(eachSeries) {
+ eachSeries._start_ += (pieOption.offsetAngle) * Math.PI / 180;
+ return eachSeries;
+ });
+ series.forEach(function(eachSeries, seriesIndex) {
+ if (opts.tooltip) {
+ if (opts.tooltip.index == seriesIndex) {
+ context.beginPath();
+ context.setFillStyle(hexToRgb(eachSeries.color, opts.extra.pie.activeOpacity || 0.5));
+ context.moveTo(centerPosition.x, centerPosition.y);
+ context.arc(centerPosition.x, centerPosition.y, eachSeries._radius_ + activeRadius, eachSeries._start_,
+ eachSeries._start_ + 2 *
+ eachSeries._proportion_ * Math.PI);
+ context.closePath();
+ context.fill();
+ }
+ }
+ context.beginPath();
+ context.setLineWidth(pieOption.borderWidth * opts.pixelRatio);
+ context.lineJoin = "round";
+ context.setStrokeStyle(pieOption.borderColor);
+ context.setFillStyle(eachSeries.color);
+ context.moveTo(centerPosition.x, centerPosition.y);
+ context.arc(centerPosition.x, centerPosition.y, eachSeries._radius_, eachSeries._start_, eachSeries._start_ + 2 * eachSeries._proportion_ * Math.PI);
+ context.closePath();
+ context.fill();
+ if (pieOption.border == true) {
+ context.stroke();
+ }
+ });
+
+ if (opts.type === 'ring') {
+ var innerPieWidth = radius * 0.6;
+ if (typeof opts.extra.pie.ringWidth === 'number' && opts.extra.pie.ringWidth > 0) {
+ innerPieWidth = Math.max(0, radius - opts.extra.pie.ringWidth);
+ }
+ context.beginPath();
+ context.setFillStyle(opts.background || '#ffffff');
+ context.moveTo(centerPosition.x, centerPosition.y);
+ context.arc(centerPosition.x, centerPosition.y, innerPieWidth, 0, 2 * Math.PI);
+ context.closePath();
+ context.fill();
+ }
+
+ if (opts.dataLabel !== false && process === 1) {
+ var valid = false;
+ for (var i = 0, len = series.length; i < len; i++) {
+ if (series[i].data > 0) {
+ valid = true;
+ break;
+ }
+ }
+
+ if (valid) {
+ drawPieText(series, opts, config, context, radius, centerPosition);
+ }
+ }
+
+ if (process === 1 && opts.type === 'ring') {
+ drawRingTitle(opts, config, context, centerPosition);
+ }
+
+ return {
+ center: centerPosition,
+ radius: radius,
+ series: series
+ };
+}
+
+function drawRoseDataPoints(series, opts, config, context) {
+ var process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1;
+ var roseOption = assign({}, {
+ type: 'area',
+ activeOpacity: 0.5,
+ activeRadius: 10 * opts.pixelRatio,
+ offsetAngle: 0,
+ labelWidth: 15 * opts.pixelRatio,
+ border:false,
+ borderWidth:2,
+ borderColor:'#FFFFFF'
+ }, opts.extra.rose);
+ if (config.pieChartLinePadding == 0) {
+ config.pieChartLinePadding = roseOption.activeRadius;
+ }
+ var centerPosition = {
+ x: opts.area[3] + (opts.width - opts.area[1] - opts.area[3]) / 2,
+ y: opts.area[0] + (opts.height - opts.area[0] - opts.area[2]) / 2
+ };
+ var radius = Math.min((opts.width - opts.area[1] - opts.area[3]) / 2 - config.pieChartLinePadding - config.pieChartTextPadding - config._pieTextMaxLength_, (opts.height - opts.area[0] - opts.area[2]) / 2 - config.pieChartLinePadding - config.pieChartTextPadding);
+ var minRadius = roseOption.minRadius || radius * 0.5;
+
+ series = getRoseDataPoints(series, roseOption.type, minRadius, radius, process);
+
+ var activeRadius = roseOption.activeRadius;
+
+ series = series.map(function(eachSeries) {
+ eachSeries._start_ += (roseOption.offsetAngle || 0) * Math.PI / 180;
+ return eachSeries;
+ });
+
+ series.forEach(function(eachSeries, seriesIndex) {
+ if (opts.tooltip) {
+ if (opts.tooltip.index == seriesIndex) {
+ context.beginPath();
+ context.setFillStyle(hexToRgb(eachSeries.color, roseOption.activeOpacity || 0.5));
+ context.moveTo(centerPosition.x, centerPosition.y);
+ context.arc(centerPosition.x, centerPosition.y, activeRadius + eachSeries._radius_, eachSeries._start_,
+ eachSeries._start_ + 2 * eachSeries._rose_proportion_ * Math.PI);
+ context.closePath();
+ context.fill();
+ }
+ }
+ context.beginPath();
+ context.setLineWidth(roseOption.borderWidth * opts.pixelRatio);
+ context.lineJoin = "round";
+ context.setStrokeStyle(roseOption.borderColor);
+ context.setFillStyle(eachSeries.color);
+ context.moveTo(centerPosition.x, centerPosition.y);
+ context.arc(centerPosition.x, centerPosition.y, eachSeries._radius_, eachSeries._start_, eachSeries._start_ + 2 *
+ eachSeries._rose_proportion_ * Math.PI);
+ context.closePath();
+ context.fill();
+ if (roseOption.border == true) {
+ context.stroke();
+ }
+ });
+
+ if (opts.dataLabel !== false && process === 1) {
+ var valid = false;
+ for (var i = 0, len = series.length; i < len; i++) {
+ if (series[i].data > 0) {
+ valid = true;
+ break;
+ }
+ }
+
+ if (valid) {
+ drawPieText(series, opts, config, context, radius, centerPosition);
+ }
+ }
+
+ return {
+ center: centerPosition,
+ radius: radius,
+ series: series
+ };
+}
+
+function drawArcbarDataPoints(series, opts, config, context) {
+ var process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1;
+ var arcbarOption = assign({}, {
+ startAngle: 0.75,
+ endAngle: 0.25,
+ type: 'default',
+ width: 12 * opts.pixelRatio,
+ gap:2 * opts.pixelRatio
+ }, opts.extra.arcbar);
+
+ series = getArcbarDataPoints(series, arcbarOption, process);
+
+ var centerPosition;
+ if(arcbarOption.center){
+ centerPosition=arcbarOption.center;
+ }else{
+ centerPosition= {
+ x: opts.width / 2,
+ y: opts.height / 2
+ };
+ }
+
+ var radius;
+ if(arcbarOption.radius){
+ radius=arcbarOption.radius;
+ }else{
+ radius = Math.min(centerPosition.x, centerPosition.y);
+ radius -= 5 * opts.pixelRatio;
+ radius -= arcbarOption.width / 2;
+ }
+
+ for (let i = 0; i < series.length; i++) {
+ let eachSeries = series[i];
+ //背景颜色
+ context.setLineWidth(arcbarOption.width);
+ context.setStrokeStyle(arcbarOption.backgroundColor || '#E9E9E9');
+ context.setLineCap('round');
+ context.beginPath();
+ if (arcbarOption.type == 'default') {
+ context.arc(centerPosition.x, centerPosition.y, radius-(arcbarOption.width+arcbarOption.gap)*i, arcbarOption.startAngle * Math.PI, arcbarOption.endAngle * Math.PI, false);
+ } else {
+ context.arc(centerPosition.x, centerPosition.y, radius-(arcbarOption.width+arcbarOption.gap)*i, 0, 2 * Math.PI, false);
+ }
+ context.stroke();
+ //进度条
+ context.setLineWidth(arcbarOption.width);
+ context.setStrokeStyle(eachSeries.color);
+ context.setLineCap('round');
+ context.beginPath();
+ context.arc(centerPosition.x, centerPosition.y, radius-(arcbarOption.width+arcbarOption.gap)*i, arcbarOption.startAngle * Math.PI, eachSeries._proportion_ * Math.PI, false);
+ context.stroke();
+ }
+
+ drawRingTitle(opts, config, context, centerPosition);
+
+ return {
+ center: centerPosition,
+ radius: radius,
+ series: series
+ };
+}
+
+function drawGaugeDataPoints(categories, series, opts, config, context) {
+ var process = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 1;
+ var gaugeOption = assign({}, {
+ type:'default',
+ startAngle: 0.75,
+ endAngle: 0.25,
+ width: 15,
+ splitLine: {
+ fixRadius: 0,
+ splitNumber: 10,
+ width: 15,
+ color: '#FFFFFF',
+ childNumber: 5,
+ childWidth: 5
+ },
+ pointer: {
+ width: 15,
+ color: 'auto'
+ }
+ }, opts.extra.gauge);
+
+ if (gaugeOption.oldAngle == undefined) {
+ gaugeOption.oldAngle = gaugeOption.startAngle;
+ }
+ if (gaugeOption.oldData == undefined) {
+ gaugeOption.oldData = 0;
+ }
+ categories = getGaugeAxisPoints(categories, gaugeOption.startAngle, gaugeOption.endAngle);
+
+ var centerPosition = {
+ x: opts.width / 2,
+ y: opts.height / 2
+ };
+ var radius = Math.min(centerPosition.x, centerPosition.y);
+ radius -= 5 * opts.pixelRatio;
+ radius -= gaugeOption.width / 2;
+ var innerRadius = radius - gaugeOption.width;
+ var totalAngle=0;
+
+ //判断仪表盘的样式:default百度样式,progress新样式
+ if(gaugeOption.type == 'progress'){
+
+ //## 第一步画中心圆形背景和进度条背景
+ //中心圆形背景
+ var pieRadius = radius - gaugeOption.width*3;
+ context.beginPath();
+ let gradient = context.createLinearGradient(centerPosition.x, centerPosition.y-pieRadius, centerPosition.x , centerPosition.y+pieRadius);
+ //配置渐变填充(起点:中心点向上减半径;结束点中心点向下加半径)
+ gradient.addColorStop('0', hexToRgb(series[0].color, 0.3));
+ gradient.addColorStop('1.0',hexToRgb("#FFFFFF", 0.1));
+ context.setFillStyle(gradient);
+ context.arc(centerPosition.x, centerPosition.y, pieRadius, 0, 2*Math.PI, false);
+ context.fill();
+ //画进度条背景
+ context.setLineWidth(gaugeOption.width);
+ context.setStrokeStyle(hexToRgb(series[0].color, 0.3));
+ context.setLineCap('round');
+ context.beginPath();
+ context.arc(centerPosition.x, centerPosition.y, innerRadius , gaugeOption.startAngle * Math.PI, gaugeOption.endAngle *Math.PI, false);
+ context.stroke();
+
+ //## 第二步画刻度线
+ totalAngle = gaugeOption.startAngle - gaugeOption.endAngle + 1;
+ let splitAngle = totalAngle / gaugeOption.splitLine.splitNumber;
+ let childAngle = totalAngle / gaugeOption.splitLine.splitNumber / gaugeOption.splitLine.childNumber;
+ let startX = -radius - gaugeOption.width * 0.5 - gaugeOption.splitLine.fixRadius;
+ let endX = -radius - gaugeOption.width - gaugeOption.splitLine.fixRadius + gaugeOption.splitLine.width;
+ context.save();
+ context.translate(centerPosition.x, centerPosition.y);
+ context.rotate((gaugeOption.startAngle - 1) * Math.PI);
+ let len = gaugeOption.splitLine.splitNumber * gaugeOption.splitLine.childNumber + 1;
+ let proc = series[0].data * process;
+ for (let i = 0; i < len; i++) {
+ context.beginPath();
+ //刻度线随进度变色
+ if(proc>(i/len)){
+ context.setStrokeStyle(hexToRgb(series[0].color, 1));
+ }else{
+ context.setStrokeStyle(hexToRgb(series[0].color, 0.3));
+ }
+ context.setLineWidth(3 * opts.pixelRatio);
+ context.moveTo(startX, 0);
+ context.lineTo(endX, 0);
+ context.stroke();
+ context.rotate(childAngle * Math.PI);
+ }
+ context.restore();
+
+ //## 第三步画进度条
+ series = getArcbarDataPoints(series, gaugeOption, process);
+ context.setLineWidth(gaugeOption.width);
+ context.setStrokeStyle(series[0].color);
+ context.setLineCap('round');
+ context.beginPath();
+ context.arc(centerPosition.x, centerPosition.y, innerRadius , gaugeOption.startAngle * Math.PI, series[0]._proportion_ *Math.PI, false);
+ context.stroke();
+
+ //## 第四步画指针
+ let pointerRadius = radius - gaugeOption.width*2.5;
+ context.save();
+ context.translate(centerPosition.x, centerPosition.y);
+ context.rotate((series[0]._proportion_ - 1) * Math.PI);
+ context.beginPath();
+ context.setLineWidth(gaugeOption.width/3);
+ let gradient3 = context.createLinearGradient(0, -pointerRadius*0.6, 0 , pointerRadius*0.6);
+ gradient3.addColorStop('0', hexToRgb('#FFFFFF', 0));
+ gradient3.addColorStop('0.5', hexToRgb(series[0].color, 1));
+ gradient3.addColorStop('1.0', hexToRgb('#FFFFFF', 0));
+ context.setStrokeStyle(gradient3);
+ context.arc(0, 0, pointerRadius , 0.85* Math.PI, 1.15 * Math.PI, false);
+ context.stroke();
+ context.beginPath();
+ context.setLineWidth(1);
+ context.setStrokeStyle(series[0].color);
+ context.setFillStyle(series[0].color);
+ context.moveTo(-pointerRadius-gaugeOption.width/3/2,-4);
+ context.lineTo(-pointerRadius-gaugeOption.width/3/2-4,0);
+ context.lineTo(-pointerRadius-gaugeOption.width/3/2,4);
+ context.lineTo(-pointerRadius-gaugeOption.width/3/2,-4);
+ context.stroke();
+ context.fill();
+ context.restore();
+
+ //default百度样式
+ }else{
+ //画背景
+ context.setLineWidth(gaugeOption.width);
+ context.setLineCap('butt');
+ for (let i = 0; i < categories.length; i++) {
+ let eachCategories = categories[i];
+ context.beginPath();
+ context.setStrokeStyle(eachCategories.color);
+ context.arc(centerPosition.x, centerPosition.y, radius, eachCategories._startAngle_ * Math.PI, eachCategories._endAngle_ *Math.PI, false);
+ context.stroke();
+ }
+ context.save();
+
+ //画刻度线
+ totalAngle = gaugeOption.startAngle - gaugeOption.endAngle + 1;
+ let splitAngle = totalAngle / gaugeOption.splitLine.splitNumber;
+ let childAngle = totalAngle / gaugeOption.splitLine.splitNumber / gaugeOption.splitLine.childNumber;
+ let startX = -radius - gaugeOption.width * 0.5 - gaugeOption.splitLine.fixRadius;
+ let endX = -radius - gaugeOption.width * 0.5 - gaugeOption.splitLine.fixRadius + gaugeOption.splitLine.width;
+ let childendX = -radius - gaugeOption.width * 0.5 - gaugeOption.splitLine.fixRadius + gaugeOption.splitLine.childWidth;
+
+ context.translate(centerPosition.x, centerPosition.y);
+ context.rotate((gaugeOption.startAngle - 1) * Math.PI);
+
+ for (let i = 0; i < gaugeOption.splitLine.splitNumber + 1; i++) {
+ context.beginPath();
+ context.setStrokeStyle(gaugeOption.splitLine.color);
+ context.setLineWidth(2 * opts.pixelRatio);
+ context.moveTo(startX, 0);
+ context.lineTo(endX, 0);
+ context.stroke();
+ context.rotate(splitAngle * Math.PI);
+ }
+ context.restore();
+
+ context.save();
+ context.translate(centerPosition.x, centerPosition.y);
+ context.rotate((gaugeOption.startAngle - 1) * Math.PI);
+
+ for (let i = 0; i < gaugeOption.splitLine.splitNumber * gaugeOption.splitLine.childNumber + 1; i++) {
+ context.beginPath();
+ context.setStrokeStyle(gaugeOption.splitLine.color);
+ context.setLineWidth(1 * opts.pixelRatio);
+ context.moveTo(startX, 0);
+ context.lineTo(childendX, 0);
+ context.stroke();
+ context.rotate(childAngle * Math.PI);
+ }
+ context.restore();
+
+ //画指针
+ series = getGaugeDataPoints(series, categories, gaugeOption, process);
+
+ for (let i = 0; i < series.length; i++) {
+ let eachSeries = series[i];
+ context.save();
+ context.translate(centerPosition.x, centerPosition.y);
+ context.rotate((eachSeries._proportion_ - 1) * Math.PI);
+ context.beginPath();
+ context.setFillStyle(eachSeries.color);
+ context.moveTo(gaugeOption.pointer.width, 0);
+ context.lineTo(0, -gaugeOption.pointer.width / 2);
+ context.lineTo(-innerRadius, 0);
+ context.lineTo(0, gaugeOption.pointer.width / 2);
+ context.lineTo(gaugeOption.pointer.width, 0);
+ context.closePath();
+ context.fill();
+ context.beginPath();
+ context.setFillStyle('#FFFFFF');
+ context.arc(0, 0, gaugeOption.pointer.width / 6, 0, 2 * Math.PI, false);
+ context.fill();
+ context.restore();
+ }
+
+ if (opts.dataLabel !== false) {
+ drawGaugeLabel(gaugeOption, radius, centerPosition, opts, config, context);
+ }
+ }
+
+ //画仪表盘标题,副标题
+ drawRingTitle(opts, config, context, centerPosition);
+
+ if (process === 1 && opts.type === 'gauge') {
+ opts.extra.gauge.oldAngle = series[0]._proportion_;
+ opts.extra.gauge.oldData = series[0].data;
+ }
+ return {
+ center: centerPosition,
+ radius: radius,
+ innerRadius: innerRadius,
+ categories: categories,
+ totalAngle: totalAngle
+ };
+}
+
+function drawRadarDataPoints(series, opts, config, context) {
+ var process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1;
+ var radarOption = assign({},{
+ gridColor: '#cccccc',
+ labelColor: '#666666',
+ opacity: 0.2,
+ gridCount:3
+ },opts.extra.radar);
+
+ var coordinateAngle = getRadarCoordinateSeries(opts.categories.length);
+
+ var centerPosition = {
+ x: opts.area[3] + (opts.width - opts.area[1] - opts.area[3]) / 2,
+ y: opts.area[0] + (opts.height - opts.area[0] - opts.area[2]) / 2
+ };
+
+ var radius = Math.min(centerPosition.x - (getMaxTextListLength(opts.categories) + config.radarLabelTextMargin),
+ centerPosition.y - config.radarLabelTextMargin);
+ //TODO逻辑不对
+ radius -= opts.padding[1];
+
+ // draw grid
+ context.beginPath();
+ context.setLineWidth(1 * opts.pixelRatio);
+ context.setStrokeStyle(radarOption.gridColor);
+ coordinateAngle.forEach(function(angle) {
+ var pos = convertCoordinateOrigin(radius * Math.cos(angle), radius * Math.sin(angle), centerPosition);
+ context.moveTo(centerPosition.x, centerPosition.y);
+ context.lineTo(pos.x, pos.y);
+ });
+ context.stroke();
+ context.closePath();
+ // draw split line grid
+
+ var _loop = function _loop(i) {
+ var startPos = {};
+ context.beginPath();
+ context.setLineWidth(1 * opts.pixelRatio);
+ context.setStrokeStyle(radarOption.gridColor);
+ coordinateAngle.forEach(function(angle, index) {
+ var pos = convertCoordinateOrigin(radius / radarOption.gridCount * i * Math.cos(angle), radius / radarOption.gridCount * i * Math.sin(angle), centerPosition);
+ if (index === 0) {
+ startPos = pos;
+ context.moveTo(pos.x, pos.y);
+ } else {
+ context.lineTo(pos.x, pos.y);
+ }
+ });
+ context.lineTo(startPos.x, startPos.y);
+ context.stroke();
+ context.closePath();
+ };
+
+ for (var i = 1; i <= radarOption.gridCount; i++) {
+ _loop(i);
+ }
+
+ var radarDataPoints = getRadarDataPoints(coordinateAngle, centerPosition, radius, series, opts, process);
+
+ radarDataPoints.forEach(function(eachSeries, seriesIndex) {
+ // 绘制区域数据
+ context.beginPath();
+ context.setFillStyle(hexToRgb(eachSeries.color, radarOption.opacity));
+ eachSeries.data.forEach(function(item, index) {
+ if (index === 0) {
+ context.moveTo(item.position.x, item.position.y);
+ } else {
+ context.lineTo(item.position.x, item.position.y);
+ }
+ });
+ context.closePath();
+ context.fill();
+
+ if (opts.dataPointShape !== false) {
+ var points = eachSeries.data.map(function(item) {
+ return item.position;
+ });
+ drawPointShape(points, eachSeries.color, eachSeries.pointShape, context, opts);
+ }
+ });
+ // draw label text
+ drawRadarLabel(coordinateAngle, radius, centerPosition, opts, config, context);
+
+ return {
+ center: centerPosition,
+ radius: radius,
+ angleList: coordinateAngle
+ };
+}
+
+function normalInt(min, max, iter) {
+ iter = iter==0?1:iter;
+ var arr = [];
+ for (var i = 0; i < iter; i++) {
+ arr[i] = Math.random();
+ };
+ return Math.floor(arr.reduce(function(i,j){return i+j})/iter*(max-min))+min;
+};
+
+function collisionNew(area,points,width,height){
+ var isIn=false;
+ for(let i=0;ipoints[i].area[2]||area[1]>points[i].area[3]||area[2]width || area[3]>height){
+ isIn=true;
+ break;
+ }else{
+ isIn=false;
+ }
+ }else{
+ isIn=true;
+ break;
+ }
+ }
+ }
+ return isIn;
+};
+
+function getBoundingBox(data) {
+ var bounds = {}, coords;
+ bounds.xMin = 180;
+ bounds.xMax = 0;
+ bounds.yMin = 90;
+ bounds.yMax = 0
+ for (var i = 0; i < data.length; i++) {
+ var coorda = data[i].geometry.coordinates
+ for (var k = 0; k < coorda.length; k++) {
+ coords = coorda[k];
+ if (coords.length == 1) {
+ coords = coords[0]
+ }
+ for (var j = 0; j < coords.length; j++) {
+ var longitude = coords[j][0];
+ var latitude = coords[j][1];
+ var point = {
+ x: longitude,
+ y: latitude
+ }
+ bounds.xMin = bounds.xMin < point.x ? bounds.xMin : point.x;
+ bounds.xMax = bounds.xMax > point.x ? bounds.xMax : point.x;
+ bounds.yMin = bounds.yMin < point.y ? bounds.yMin : point.y;
+ bounds.yMax = bounds.yMax > point.y ? bounds.yMax : point.y;
+ }
+ }
+ }
+ return bounds;
+}
+
+function coordinateToPoint(latitude, longitude,bounds,scale,xoffset,yoffset) {
+ return {
+ x: (longitude - bounds.xMin) * scale+xoffset,
+ y: (bounds.yMax - latitude) * scale+yoffset
+ };
+}
+
+function pointToCoordinate(pointY, pointX,bounds,scale,xoffset,yoffset) {
+ return {
+ x: (pointX-xoffset)/scale+bounds.xMin,
+ y: bounds.yMax - (pointY-yoffset)/scale
+ };
+}
+
+function isRayIntersectsSegment(poi,s_poi,e_poi){
+ if (s_poi[1]==e_poi[1]){return false;}
+ if (s_poi[1]>poi[1] && e_poi[1]>poi[1]){return false;}
+ if (s_poi[1]poi[1]){return false;}
+ if (e_poi[1]==poi[1] && s_poi[1]>poi[1]){return false;}
+ if (s_poi[0]0.7) {
+ return true;
+ }else {return false};
+ };
+ for (let i = 0; i < points.length; i++) {
+ let text = points[i].name;
+ let tHeight = points[i].textSize;
+ let tWidth = measureText(text,tHeight);
+ let isSpin = Spin();
+ let x,y,area,areav;
+ let breaknum=0;
+ while(true) {
+ breaknum++;
+ let isCollision;
+ if (isSpin) {
+ x = normalInt(-opts.width/2, opts.width/2,5) - tWidth/2;
+ y = normalInt(-opts.height/2, opts.height/2,5)+tHeight/2;
+ area=[y-5-tWidth+opts.width/2,(-x-5+opts.height/2),y+5+opts.width/2,(-x+tHeight+5+opts.height/2)];
+ areav=[opts.width-(opts.width/2-opts.height/2)-(-x+tHeight+5+opts.height/2)-5,(opts.height/2-opts.width/2)+(y-5-tWidth+opts.width/2)-5,opts.width-(opts.width/2-opts.height/2)-(-x+tHeight+5+opts.height/2)+tHeight,(opts.height/2-opts.width/2)+(y-5-tWidth+opts.width/2)+tWidth+5];
+ isCollision = collisionNew(areav,points,opts.height,opts.width);
+ }else{
+ x = normalInt(-opts.width/2, opts.width/2,5) - tWidth/2;
+ y = normalInt(-opts.height/2, opts.height/2,5)+tHeight/2;
+ area=[x-5+opts.width/2,y-5-tHeight+opts.height/2,x+tWidth+5+opts.width/2,y+5+opts.height/2];
+ isCollision = collisionNew(area,points,opts.width,opts.height);
+ }
+ if (!isCollision) break;
+ if (breaknum==1000){
+ area=[-1000,-1000,-1000,-1000];
+ break;
+ }
+ };
+ if (isSpin) {
+ points[i].area=areav;
+ points[i].areav=area;
+ }else{
+ points[i].area=area;
+ }
+ points[i].rotate=isSpin;
+ };
+ break;
+ }
+ return points;
+}
+
+
+function drawWordCloudDataPoints(series, opts, config, context) {
+ let process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1;
+ let wordOption = assign({},{
+ type: 'normal',
+ autoColors: true
+ },opts.extra.word);
+
+ context.beginPath();
+ context.setFillStyle(opts.background||'#FFFFFF');
+ context.rect(0,0,opts.width,opts.height);
+ context.fill();
+ context.save();
+ let points = opts.chartData.wordCloudData;
+ context.translate(opts.width/2,opts.height/2);
+
+ for(let i=0;i0){
+ if (opts.tooltip) {
+ if (opts.tooltip.index == i) {
+ context.strokeText(text,(points[i].areav[0]+5-opts.width/2)*process-tWidth*(1-process)/2,(points[i].areav[1]+5+tHeight-opts.height/2)*process);
+ }else{
+ context.fillText(text,(points[i].areav[0]+5-opts.width/2)*process-tWidth*(1-process)/2,(points[i].areav[1]+5+tHeight-opts.height/2)*process);
+ }
+ }else{
+ context.fillText(text,(points[i].areav[0]+5-opts.width/2)*process-tWidth*(1-process)/2,(points[i].areav[1]+5+tHeight-opts.height/2)*process);
+ }
+ }
+ }else{
+ if(points[i].area[0]>0){
+ if (opts.tooltip) {
+ if (opts.tooltip.index == i) {
+ context.strokeText(text,(points[i].area[0]+5-opts.width/2)*process-tWidth*(1-process)/2,(points[i].area[1]+5+tHeight-opts.height/2)*process);
+ }else{
+ context.fillText(text,(points[i].area[0]+5-opts.width/2)*process-tWidth*(1-process)/2,(points[i].area[1]+5+tHeight-opts.height/2)*process);
+ }
+ }else{
+ context.fillText(text,(points[i].area[0]+5-opts.width/2)*process-tWidth*(1-process)/2,(points[i].area[1]+5+tHeight-opts.height/2)*process);
+ }
+
+ }
+ }
+
+ context.stroke();
+ context.restore();
+ }
+ context.restore();
+}
+
+function drawFunnelDataPoints(series, opts, config, context) {
+ let process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1;
+ let funnelOption = assign({},{
+ activeWidth:10,
+ activeOpacity:0.3,
+ border:false,
+ borderWidth:2,
+ borderColor:'#FFFFFF',
+ fillOpacity:1,
+ labelAlign:'right'
+ },opts.extra.funnel);
+ let eachSpacing = (opts.height - opts.area[0] - opts.area[2])/series.length;
+ let centerPosition = {
+ x: opts.area[3] + (opts.width - opts.area[1] - opts.area[3]) / 2,
+ y: opts.height-opts.area[2]
+ };
+ let activeWidth = funnelOption.activeWidth;
+ let radius = Math.min((opts.width - opts.area[1] - opts.area[3]) / 2 - activeWidth, (opts.height - opts.area[0] - opts.area[2]) / 2 - activeWidth);
+ series = getFunnelDataPoints(series, radius, process);
+ context.save();
+ context.translate(centerPosition.x,centerPosition.y);
+ for(let i=0;i0){
+ opts.area[3] += yAxisWidth[i].width + opts.yAxis.padding;
+ }else{
+ opts.area[3] += yAxisWidth[i].width;
+ }
+ leftIndex +=1;
+ }else{
+ if(rightIndex>0){
+ opts.area[1] += yAxisWidth[i].width + opts.yAxis.padding;
+ }else{
+ opts.area[1] += yAxisWidth[i].width;
+ }
+ rightIndex +=1;
+ }
+ }
+ }else{
+ config.yAxisWidth = yAxisWidth;
+ }
+ opts.chartData.yAxisData = _calYAxisData;
+
+ if (opts.categories && opts.categories.length) {
+ opts.chartData.xAxisData = getXAxisPoints(opts.categories, opts, config);
+ let _calCategoriesData = calCategoriesData(opts.categories, opts, config, opts.chartData.xAxisData.eachSpacing),
+ xAxisHeight = _calCategoriesData.xAxisHeight,
+ angle = _calCategoriesData.angle;
+ config.xAxisHeight = xAxisHeight;
+ config._xAxisTextAngle_ = angle;
+ opts.area[2] += xAxisHeight;
+ opts.chartData.categoriesData = _calCategoriesData;
+ }else{
+ if (opts.type === 'line' || opts.type === 'area' || opts.type === 'points') {
+ opts.chartData.xAxisData = calXAxisData(series, opts, config);
+ categories=opts.chartData.xAxisData.rangesFormat;
+ let _calCategoriesData = calCategoriesData(categories, opts, config, opts.chartData.xAxisData.eachSpacing),
+ xAxisHeight = _calCategoriesData.xAxisHeight,
+ angle = _calCategoriesData.angle;
+ config.xAxisHeight = xAxisHeight;
+ config._xAxisTextAngle_ = angle;
+ opts.area[2] += xAxisHeight;
+ opts.chartData.categoriesData = _calCategoriesData;
+ }else{
+ opts.chartData.xAxisData={
+ xAxisPoints: []
+ };
+ }
+ }
+ //计算右对齐偏移距离
+ if (opts.enableScroll && opts.xAxis.scrollAlign == 'right' && opts._scrollDistance_ === undefined) {
+ let offsetLeft = 0,
+ xAxisPoints = opts.chartData.xAxisData.xAxisPoints,
+ startX = opts.chartData.xAxisData.startX,
+ endX = opts.chartData.xAxisData.endX,
+ eachSpacing = opts.chartData.xAxisData.eachSpacing;
+ let totalWidth = eachSpacing * (xAxisPoints.length - 1);
+ let screenWidth = endX - startX;
+ offsetLeft = screenWidth - totalWidth;
+ _this.scrollOption = {
+ currentOffset: offsetLeft,
+ startTouchX: offsetLeft,
+ distance: 0,
+ lastMoveTime: 0
+ };
+ opts._scrollDistance_ = offsetLeft;
+ }
+
+ if (type === 'pie' || type === 'ring' || type === 'rose') {
+ config._pieTextMaxLength_ = opts.dataLabel === false ? 0 : getPieTextMaxLength(seriesMA);
+ }
+
+ switch (type) {
+ case 'word':
+ let wordOption = assign({},{
+ type: 'normal',
+ autoColors: true
+ },opts.extra.word);
+ if(opts.updateData==true || opts.updateData==undefined){
+ opts.chartData.wordCloudData=getWordCloudPoint(opts,wordOption.type);
+ }
+ this.animationInstance = new Animation({
+ timing: 'easeInOut',
+ duration: duration,
+ onProcess: function(process) {
+ context.clearRect(0, 0, opts.width, opts.height);
+ if (opts.rotate) {
+ contextRotate(context, opts);
+ }
+ drawWordCloudDataPoints(series, opts, config, context,process);
+ drawCanvas(opts, context);
+ },
+ onAnimationFinish: function onAnimationFinish() {
+ _this.event.trigger('renderComplete');
+ }
+ });
+ break;
+ case 'map':
+ context.clearRect(0, 0, opts.width, opts.height);
+ drawMapDataPoints(series, opts, config, context);
+ break;
+ case 'funnel':
+ this.animationInstance = new Animation({
+ timing: 'easeInOut',
+ duration: duration,
+ onProcess: function(process) {
+ context.clearRect(0, 0, opts.width, opts.height);
+ if (opts.rotate) {
+ contextRotate(context, opts);
+ }
+ opts.chartData.funnelData = drawFunnelDataPoints(series, opts, config, context, process);
+ drawLegend(opts.series, opts, config, context, opts.chartData);
+ drawToolTipBridge(opts, config, context, process);
+ drawCanvas(opts, context);
+ },
+ onAnimationFinish: function onAnimationFinish() {
+ _this.event.trigger('renderComplete');
+ }
+ });
+ break;
+ case 'line':
+ this.animationInstance = new Animation({
+ timing: 'easeIn',
+ duration: duration,
+ onProcess: function onProcess(process) {
+ context.clearRect(0, 0, opts.width, opts.height);
+ if (opts.rotate) {
+ contextRotate(context, opts);
+ }
+ drawYAxisGrid(categories, opts, config, context);
+ drawXAxis(categories, opts, config, context);
+ var _drawLineDataPoints = drawLineDataPoints(series, opts, config, context, process),
+ xAxisPoints = _drawLineDataPoints.xAxisPoints,
+ calPoints = _drawLineDataPoints.calPoints,
+ eachSpacing = _drawLineDataPoints.eachSpacing;
+ opts.chartData.xAxisPoints = xAxisPoints;
+ opts.chartData.calPoints = calPoints;
+ opts.chartData.eachSpacing = eachSpacing;
+ drawYAxis(series, opts, config, context);
+ if (opts.enableMarkLine !== false && process === 1) {
+ drawMarkLine(opts, config, context);
+ }
+ drawLegend(opts.series, opts, config, context, opts.chartData);
+ drawToolTipBridge(opts, config, context, process, eachSpacing, xAxisPoints);
+ drawCanvas(opts, context);
+
+ },
+ onAnimationFinish: function onAnimationFinish() {
+ _this.event.trigger('renderComplete');
+ }
+ });
+ break;
+ case 'mix':
+ this.animationInstance = new Animation({
+ timing: 'easeIn',
+ duration: duration,
+ onProcess: function onProcess(process) {
+ context.clearRect(0, 0, opts.width, opts.height);
+ if (opts.rotate) {
+ contextRotate(context, opts);
+ }
+ drawYAxisGrid(categories, opts, config, context);
+ drawXAxis(categories, opts, config, context);
+ var _drawMixDataPoints = drawMixDataPoints(series, opts, config, context, process),
+ xAxisPoints = _drawMixDataPoints.xAxisPoints,
+ calPoints = _drawMixDataPoints.calPoints,
+ eachSpacing = _drawMixDataPoints.eachSpacing;
+ opts.chartData.xAxisPoints = xAxisPoints;
+ opts.chartData.calPoints = calPoints;
+ opts.chartData.eachSpacing = eachSpacing;
+ drawYAxis(series, opts, config, context);
+ if (opts.enableMarkLine !== false && process === 1) {
+ drawMarkLine(opts, config, context);
+ }
+ drawLegend(opts.series, opts, config, context, opts.chartData);
+ drawToolTipBridge(opts, config, context, process, eachSpacing, xAxisPoints);
+ drawCanvas(opts, context);
+ },
+ onAnimationFinish: function onAnimationFinish() {
+ _this.event.trigger('renderComplete');
+ }
+ });
+ break;
+ case 'column':
+ this.animationInstance = new Animation({
+ timing: 'easeIn',
+ duration: duration,
+ onProcess: function onProcess(process) {
+ context.clearRect(0, 0, opts.width, opts.height);
+ if (opts.rotate) {
+ contextRotate(context, opts);
+ }
+ drawYAxisGrid(categories, opts, config, context);
+ drawXAxis(categories, opts, config, context);
+ var _drawColumnDataPoints = drawColumnDataPoints(series, opts, config, context, process),
+ xAxisPoints = _drawColumnDataPoints.xAxisPoints,
+ calPoints = _drawColumnDataPoints.calPoints,
+ eachSpacing = _drawColumnDataPoints.eachSpacing;
+ opts.chartData.xAxisPoints = xAxisPoints;
+ opts.chartData.calPoints = calPoints;
+ opts.chartData.eachSpacing = eachSpacing;
+ drawYAxis(series, opts, config, context);
+ if (opts.enableMarkLine !== false && process === 1) {
+ drawMarkLine(opts, config, context);
+ }
+ drawLegend(opts.series, opts, config, context, opts.chartData);
+ drawToolTipBridge(opts, config, context, process, eachSpacing, xAxisPoints);
+ drawCanvas(opts, context);
+ },
+ onAnimationFinish: function onAnimationFinish() {
+ _this.event.trigger('renderComplete');
+ }
+ });
+ break;
+ case 'area':
+ this.animationInstance = new Animation({
+ timing: 'easeIn',
+ duration: duration,
+ onProcess: function onProcess(process) {
+ context.clearRect(0, 0, opts.width, opts.height);
+ if (opts.rotate) {
+ contextRotate(context, opts);
+ }
+ drawYAxisGrid(categories, opts, config, context);
+ drawXAxis(categories, opts, config, context);
+ var _drawAreaDataPoints = drawAreaDataPoints(series, opts, config, context, process),
+ xAxisPoints = _drawAreaDataPoints.xAxisPoints,
+ calPoints = _drawAreaDataPoints.calPoints,
+ eachSpacing = _drawAreaDataPoints.eachSpacing;
+ opts.chartData.xAxisPoints = xAxisPoints;
+ opts.chartData.calPoints = calPoints;
+ opts.chartData.eachSpacing = eachSpacing;
+ drawYAxis(series, opts, config, context);
+ if (opts.enableMarkLine !== false && process === 1) {
+ drawMarkLine(opts, config, context);
+ }
+ drawLegend(opts.series, opts, config, context, opts.chartData);
+ drawToolTipBridge(opts, config, context, process, eachSpacing, xAxisPoints);
+ drawCanvas(opts, context);
+ },
+ onAnimationFinish: function onAnimationFinish() {
+ _this.event.trigger('renderComplete');
+ }
+ });
+ break;
+ case 'ring':
+ case 'pie':
+ this.animationInstance = new Animation({
+ timing: 'easeInOut',
+ duration: duration,
+ onProcess: function onProcess(process) {
+ context.clearRect(0, 0, opts.width, opts.height);
+ if (opts.rotate) {
+ contextRotate(context, opts);
+ }
+ opts.chartData.pieData = drawPieDataPoints(series, opts, config, context, process);
+ drawLegend(opts.series, opts, config, context, opts.chartData);
+ drawToolTipBridge(opts, config, context, process);
+ drawCanvas(opts, context);
+ },
+ onAnimationFinish: function onAnimationFinish() {
+ _this.event.trigger('renderComplete');
+ }
+ });
+ break;
+ case 'rose':
+ this.animationInstance = new Animation({
+ timing: 'easeInOut',
+ duration: duration,
+ onProcess: function onProcess(process) {
+ context.clearRect(0, 0, opts.width, opts.height);
+ if (opts.rotate) {
+ contextRotate(context, opts);
+ }
+ opts.chartData.pieData = drawRoseDataPoints(series, opts, config, context, process);
+ drawLegend(opts.series, opts, config, context, opts.chartData);
+ drawToolTipBridge(opts, config, context, process);
+ drawCanvas(opts, context);
+ },
+ onAnimationFinish: function onAnimationFinish() {
+ _this.event.trigger('renderComplete');
+ }
+ });
+ break;
+ case 'radar':
+ this.animationInstance = new Animation({
+ timing: 'easeInOut',
+ duration: duration,
+ onProcess: function onProcess(process) {
+ context.clearRect(0, 0, opts.width, opts.height);
+ if (opts.rotate) {
+ contextRotate(context, opts);
+ }
+ opts.chartData.radarData = drawRadarDataPoints(series, opts, config, context, process);
+ drawLegend(opts.series, opts, config, context, opts.chartData);
+ drawToolTipBridge(opts, config, context, process);
+ drawCanvas(opts, context);
+ },
+ onAnimationFinish: function onAnimationFinish() {
+ _this.event.trigger('renderComplete');
+ }
+ });
+ break;
+ case 'arcbar':
+ this.animationInstance = new Animation({
+ timing: 'easeInOut',
+ duration: duration,
+ onProcess: function onProcess(process) {
+ context.clearRect(0, 0, opts.width, opts.height);
+ if (opts.rotate) {
+ contextRotate(context, opts);
+ }
+ opts.chartData.arcbarData = drawArcbarDataPoints(series, opts, config, context, process);
+ drawCanvas(opts, context);
+ },
+ onAnimationFinish: function onAnimationFinish() {
+ _this.event.trigger('renderComplete');
+ }
+ });
+ break;
+ case 'gauge':
+ this.animationInstance = new Animation({
+ timing: 'easeInOut',
+ duration: duration,
+ onProcess: function onProcess(process) {
+ context.clearRect(0, 0, opts.width, opts.height);
+ if (opts.rotate) {
+ contextRotate(context, opts);
+ }
+ opts.chartData.gaugeData = drawGaugeDataPoints(categories, series, opts, config, context, process);
+ drawCanvas(opts, context);
+ },
+ onAnimationFinish: function onAnimationFinish() {
+ _this.event.trigger('renderComplete');
+ }
+ });
+ break;
+ case 'candle':
+ this.animationInstance = new Animation({
+ timing: 'easeIn',
+ duration: duration,
+ onProcess: function onProcess(process) {
+ context.clearRect(0, 0, opts.width, opts.height);
+ if (opts.rotate) {
+ contextRotate(context, opts);
+ }
+ drawYAxisGrid(categories, opts, config, context);
+ drawXAxis(categories, opts, config, context);
+ var _drawCandleDataPoints = drawCandleDataPoints(series, seriesMA, opts, config, context, process),
+ xAxisPoints = _drawCandleDataPoints.xAxisPoints,
+ calPoints = _drawCandleDataPoints.calPoints,
+ eachSpacing = _drawCandleDataPoints.eachSpacing;
+ opts.chartData.xAxisPoints = xAxisPoints;
+ opts.chartData.calPoints = calPoints;
+ opts.chartData.eachSpacing = eachSpacing;
+ drawYAxis(series, opts, config, context);
+ if (opts.enableMarkLine !== false && process === 1) {
+ drawMarkLine(opts, config, context);
+ }
+ if (seriesMA) {
+ drawLegend(seriesMA, opts, config, context, opts.chartData);
+ } else {
+ drawLegend(opts.series, opts, config, context, opts.chartData);
+ }
+ drawToolTipBridge(opts, config, context, process, eachSpacing, xAxisPoints);
+ drawCanvas(opts, context);
+ },
+ onAnimationFinish: function onAnimationFinish() {
+ _this.event.trigger('renderComplete');
+ }
+ });
+ break;
+ }
+}
+
+// simple event implement
+
+function Event() {
+ this.events = {};
+}
+
+Event.prototype.addEventListener = function(type, listener) {
+ this.events[type] = this.events[type] || [];
+ this.events[type].push(listener);
+};
+
+Event.prototype.trigger = function() {
+ for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
+ args[_key] = arguments[_key];
+ }
+
+ var type = args[0];
+ var params = args.slice(1);
+ if (!!this.events[type]) {
+ this.events[type].forEach(function(listener) {
+ try {
+ listener.apply(null, params);
+ } catch (e) {
+ console.error(e);
+ }
+ });
+ }
+};
+
+var Charts = function Charts(opts) {
+ opts.pixelRatio = opts.pixelRatio ? opts.pixelRatio : 1;
+ opts.fontSize = opts.fontSize ? opts.fontSize * opts.pixelRatio : 13 * opts.pixelRatio;
+ opts.title = assign({}, opts.title);
+ opts.subtitle = assign({}, opts.subtitle);
+ opts.duration = opts.duration ? opts.duration : 1000;
+ opts.yAxis = assign({}, {
+ data:[],
+ showTitle:false,
+ disabled:false,
+ disableGrid:false,
+ splitNumber:5,
+ gridType: 'solid',
+ dashLength: 4 * opts.pixelRatio,
+ gridColor:'#cccccc',
+ padding:10,
+ fontColor:'#666666'
+ }, opts.yAxis);
+ opts.yAxis.dashLength *= opts.pixelRatio;
+ opts.yAxis.padding *= opts.pixelRatio;
+ opts.xAxis = assign({}, {
+ rotateLabel: false,
+ type: 'calibration',
+ gridType: 'solid',
+ dashLength: 4,
+ scrollAlign: 'left',
+ boundaryGap:'center',
+ axisLine:true,
+ axisLineColor:'#cccccc'
+ }, opts.xAxis);
+ opts.xAxis.dashLength *= opts.pixelRatio;
+ opts.legend = assign({}, {
+ show: true,
+ position: 'bottom',
+ float: 'center',
+ backgroundColor: 'rgba(0,0,0,0)',
+ borderColor: 'rgba(0,0,0,0)',
+ borderWidth: 0,
+ padding: 5,
+ margin: 5,
+ itemGap: 10,
+ fontSize: opts.fontSize,
+ lineHeight: opts.fontSize,
+ fontColor: '#333333',
+ format: {},
+ hiddenColor: '#CECECE'
+ }, opts.legend);
+ opts.legend.borderWidth = opts.legend.borderWidth * opts.pixelRatio;
+ opts.legend.itemGap = opts.legend.itemGap * opts.pixelRatio;
+ opts.legend.padding = opts.legend.padding * opts.pixelRatio;
+ opts.legend.margin = opts.legend.margin * opts.pixelRatio;
+ opts.extra = assign({}, opts.extra);
+ opts.rotate = opts.rotate ? true : false;
+ opts.animation = opts.animation ? true : false;
+ opts.rotate = opts.rotate ? true : false;
+
+ let config$$1 = JSON.parse(JSON.stringify(config));
+ config$$1.colors = opts.colors ? opts.colors : config$$1.colors;
+ config$$1.yAxisTitleWidth = opts.yAxis.disabled !== true && opts.yAxis.title ? config$$1.yAxisTitleWidth : 0;
+ if (opts.type == 'pie' || opts.type == 'ring') {
+ config$$1.pieChartLinePadding = opts.dataLabel === false ? 0 : opts.extra.pie.labelWidth * opts.pixelRatio || config$$1.pieChartLinePadding * opts.pixelRatio;
+ }
+ if (opts.type == 'rose') {
+ config$$1.pieChartLinePadding = opts.dataLabel === false ? 0 : opts.extra.rose.labelWidth * opts.pixelRatio || config$$1.pieChartLinePadding * opts.pixelRatio;
+ }
+ config$$1.pieChartTextPadding = opts.dataLabel === false ? 0 : config$$1.pieChartTextPadding * opts.pixelRatio;
+ config$$1.yAxisSplit = opts.yAxis.splitNumber ? opts.yAxis.splitNumber : config.yAxisSplit;
+
+ //屏幕旋转
+ config$$1.rotate = opts.rotate;
+ if (opts.rotate) {
+ let tempWidth = opts.width;
+ let tempHeight = opts.height;
+ opts.width = tempHeight;
+ opts.height = tempWidth;
+ }
+
+ //适配高分屏
+ opts.padding = opts.padding ? opts.padding : config$$1.padding;
+ for (let i = 0; i < 4; i++) {
+ opts.padding[i] *= opts.pixelRatio;
+ }
+ config$$1.yAxisWidth = config.yAxisWidth * opts.pixelRatio;
+ config$$1.xAxisHeight = config.xAxisHeight * opts.pixelRatio;
+ if (opts.enableScroll && opts.xAxis.scrollShow) {
+ config$$1.xAxisHeight += 6 * opts.pixelRatio;
+ }
+ config$$1.xAxisLineHeight = config.xAxisLineHeight * opts.pixelRatio;
+ config$$1.fontSize = opts.fontSize;
+ config$$1.titleFontSize = config.titleFontSize * opts.pixelRatio;
+ config$$1.subtitleFontSize = config.subtitleFontSize * opts.pixelRatio;
+ config$$1.toolTipPadding = config.toolTipPadding * opts.pixelRatio;
+ config$$1.toolTipLineHeight = config.toolTipLineHeight * opts.pixelRatio;
+ config$$1.columePadding = config.columePadding * opts.pixelRatio;
+ opts.$this = opts.$this ? opts.$this : this;
+
+ this.context = uni.createCanvasContext(opts.canvasId, opts.$this);
+ /* 兼容原生H5
+ this.context = document.getElementById(opts.canvasId).getContext("2d");
+ this.context.setStrokeStyle = function(e){ return this.strokeStyle=e; }
+ this.context.setLineWidth = function(e){ return this.lineWidth=e; }
+ this.context.setLineCap = function(e){ return this.lineCap=e; }
+ this.context.setFontSize = function(e){ return this.font=e+"px sans-serif"; }
+ this.context.setFillStyle = function(e){ return this.fillStyle=e; }
+ this.context.draw = function(){ }
+ */
+
+ opts.chartData = {};
+ this.event = new Event();
+ this.scrollOption = {
+ currentOffset: 0,
+ startTouchX: 0,
+ distance: 0,
+ lastMoveTime: 0
+ };
+
+ this.opts = opts;
+ this.config = config$$1;
+
+ drawCharts.call(this, opts.type, opts, config$$1, this.context);
+};
+
+Charts.prototype.updateData = function() {
+ let data = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
+ this.opts = assign({}, this.opts, data);
+ this.opts.updateData = true;
+ let scrollPosition = data.scrollPosition || 'current';
+ switch (scrollPosition) {
+ case 'current':
+ this.opts._scrollDistance_ = this.scrollOption.currentOffset;
+ break;
+ case 'left':
+ this.opts._scrollDistance_ = 0;
+ this.scrollOption = {
+ currentOffset: 0,
+ startTouchX: 0,
+ distance: 0,
+ lastMoveTime: 0
+ };
+ break;
+ case 'right':
+ let _calYAxisData = calYAxisData(this.opts.series, this.opts, this.config),
+ yAxisWidth = _calYAxisData.yAxisWidth;
+ this.config.yAxisWidth = yAxisWidth;
+ let offsetLeft = 0;
+ let _getXAxisPoints0 = getXAxisPoints(this.opts.categories, this.opts, this.config),
+ xAxisPoints = _getXAxisPoints0.xAxisPoints,
+ startX = _getXAxisPoints0.startX,
+ endX = _getXAxisPoints0.endX,
+ eachSpacing = _getXAxisPoints0.eachSpacing;
+ let totalWidth = eachSpacing * (xAxisPoints.length - 1);
+ let screenWidth = endX - startX;
+ offsetLeft = screenWidth - totalWidth;
+ this.scrollOption = {
+ currentOffset: offsetLeft,
+ startTouchX: offsetLeft,
+ distance: 0,
+ lastMoveTime: 0
+ };
+ this.opts._scrollDistance_ = offsetLeft;
+ break;
+ }
+ drawCharts.call(this, this.opts.type, this.opts, this.config, this.context);
+};
+
+Charts.prototype.zoom = function() {
+ var val = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.opts.xAxis.itemCount;
+ if (this.opts.enableScroll !== true) {
+ console.log('请启用滚动条后使用!')
+ return;
+ }
+ //当前屏幕中间点
+ let centerPoint = Math.round(Math.abs(this.scrollOption.currentOffset) / this.opts.chartData.eachSpacing) + Math.round(
+ this.opts.xAxis.itemCount / 2);
+ this.opts.animation = false;
+ this.opts.xAxis.itemCount = val.itemCount;
+ //重新计算x轴偏移距离
+ let _calYAxisData = calYAxisData(this.opts.series, this.opts, this.config),
+ yAxisWidth = _calYAxisData.yAxisWidth;
+ this.config.yAxisWidth = yAxisWidth;
+ let offsetLeft = 0;
+ let _getXAxisPoints0 = getXAxisPoints(this.opts.categories, this.opts, this.config),
+ xAxisPoints = _getXAxisPoints0.xAxisPoints,
+ startX = _getXAxisPoints0.startX,
+ endX = _getXAxisPoints0.endX,
+ eachSpacing = _getXAxisPoints0.eachSpacing;
+ let centerLeft = eachSpacing * centerPoint;
+ let screenWidth = endX - startX;
+ let MaxLeft = screenWidth - eachSpacing * (xAxisPoints.length - 1);
+ offsetLeft = screenWidth / 2 - centerLeft;
+ if (offsetLeft > 0) {
+ offsetLeft = 0;
+ }
+ if (offsetLeft < MaxLeft) {
+ offsetLeft = MaxLeft;
+ }
+ this.scrollOption = {
+ currentOffset: offsetLeft,
+ startTouchX: offsetLeft,
+ distance: 0,
+ lastMoveTime: 0
+ };
+ this.opts._scrollDistance_ = offsetLeft;
+ drawCharts.call(this, this.opts.type, this.opts, this.config, this.context);
+};
+
+Charts.prototype.stopAnimation = function() {
+ this.animationInstance && this.animationInstance.stop();
+};
+
+Charts.prototype.addEventListener = function(type, listener) {
+ this.event.addEventListener(type, listener);
+};
+
+Charts.prototype.getCurrentDataIndex = function(e) {
+ var touches = null;
+ if (e.changedTouches) {
+ touches = e.changedTouches[0];
+ } else {
+ touches = e.mp.changedTouches[0];
+ }
+ if (touches) {
+ let _touches$ = getTouches(touches, this.opts, e);
+ if (this.opts.type === 'pie' || this.opts.type === 'ring' || this.opts.type === 'rose') {
+ return findPieChartCurrentIndex({
+ x: _touches$.x,
+ y: _touches$.y
+ }, this.opts.chartData.pieData);
+ } else if (this.opts.type === 'radar') {
+ return findRadarChartCurrentIndex({
+ x: _touches$.x,
+ y: _touches$.y
+ }, this.opts.chartData.radarData, this.opts.categories.length);
+ } else if (this.opts.type === 'funnel') {
+ return findFunnelChartCurrentIndex({
+ x: _touches$.x,
+ y: _touches$.y
+ }, this.opts.chartData.funnelData);
+ } else if (this.opts.type === 'map') {
+ return findMapChartCurrentIndex({
+ x: _touches$.x,
+ y: _touches$.y
+ }, this.opts);
+ }else if (this.opts.type === 'word') {
+ return findWordChartCurrentIndex({
+ x: _touches$.x,
+ y: _touches$.y
+ }, this.opts.chartData.wordCloudData);
+ } else {
+ return findCurrentIndex({
+ x: _touches$.x,
+ y: _touches$.y
+ }, this.opts.chartData.calPoints, this.opts, this.config, Math.abs(this.scrollOption.currentOffset));
+ }
+ }
+ return -1;
+};
+
+Charts.prototype.getLegendDataIndex = function(e) {
+ var touches = null;
+ if (e.changedTouches) {
+ touches = e.changedTouches[0];
+ } else {
+ touches = e.mp.changedTouches[0];
+ }
+ if (touches) {
+ let _touches$ = getTouches(touches, this.opts, e);
+ return findLegendIndex({
+ x: _touches$.x,
+ y: _touches$.y
+ }, this.opts.chartData.legendData);
+ }
+ return -1;
+};
+
+Charts.prototype.touchLegend = function(e) {
+ var option = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
+ var touches = null;
+ if (e.changedTouches) {
+ touches = e.changedTouches[0];
+ } else {
+ touches = e.mp.changedTouches[0];
+ }
+ if (touches) {
+ var _touches$ = getTouches(touches, this.opts, e);
+ var index = this.getLegendDataIndex(e);
+ if (index >= 0) {
+ this.opts.series[index].show = !this.opts.series[index].show;
+ this.opts.animation = option.animation ? true : false;
+ this.opts._scrollDistance_= this.scrollOption.currentOffset;
+ drawCharts.call(this, this.opts.type, this.opts, this.config, this.context);
+ }
+ }
+
+};
+
+Charts.prototype.showToolTip = function(e) {
+ var option = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
+ var touches = null;
+ if (e.changedTouches) {
+ touches = e.changedTouches[0];
+ } else {
+ touches = e.mp.changedTouches[0];
+ }
+ if (!touches) {
+ console.log("touchError");
+ }
+ var _touches$ = getTouches(touches, this.opts, e);
+ var currentOffset = this.scrollOption.currentOffset;
+ var opts = assign({}, this.opts, {
+ _scrollDistance_: currentOffset,
+ animation: false
+ });
+ if (this.opts.type === 'line' || this.opts.type === 'area' || this.opts.type === 'column') {
+ var index = option.index==undefined? this.getCurrentDataIndex(e):option.index ;
+ if (index > -1) {
+ var seriesData = getSeriesDataItem(this.opts.series, index);
+ if (seriesData.length !== 0) {
+ var _getToolTipData = getToolTipData(seriesData, this.opts.chartData.calPoints, index, this.opts.categories,option),
+ textList = _getToolTipData.textList,
+ offset = _getToolTipData.offset;
+ offset.y = _touches$.y;
+ opts.tooltip = {
+ textList: option.textList?option.textList:textList,
+ offset: offset,
+ option: option,
+ index: index
+ };
+ }
+ }
+ drawCharts.call(this, opts.type, opts, this.config, this.context);
+ }
+ if (this.opts.type === 'mix') {
+ var index = option.index==undefined? this.getCurrentDataIndex(e):option.index ;
+ if (index > -1) {
+ var currentOffset = this.scrollOption.currentOffset;
+ var opts = assign({}, this.opts, {
+ _scrollDistance_: currentOffset,
+ animation: false
+ });
+ var seriesData = getSeriesDataItem(this.opts.series, index);
+ if (seriesData.length !== 0) {
+ var _getMixToolTipData = getMixToolTipData(seriesData, this.opts.chartData.calPoints, index, this.opts.categories,option),
+ textList = _getMixToolTipData.textList,
+ offset = _getMixToolTipData.offset;
+ offset.y = _touches$.y;
+ opts.tooltip = {
+ textList: option.textList?option.textList:textList,
+ offset: offset,
+ option: option,
+ index: index
+ };
+ }
+ }
+ drawCharts.call(this, opts.type, opts, this.config, this.context);
+ }
+ if (this.opts.type === 'candle') {
+ var index = option.index==undefined? this.getCurrentDataIndex(e):option.index ;
+ if (index > -1) {
+ var currentOffset = this.scrollOption.currentOffset;
+ var opts = assign({}, this.opts, {
+ _scrollDistance_: currentOffset,
+ animation: false
+ });
+ var seriesData = getSeriesDataItem(this.opts.series, index);
+ if (seriesData.length !== 0) {
+ var _getToolTipData = getCandleToolTipData(this.opts.series[0].data, seriesData, this.opts.chartData.calPoints,
+ index, this.opts.categories, this.opts.extra.candle, option),
+ textList = _getToolTipData.textList,
+ offset = _getToolTipData.offset;
+ offset.y = _touches$.y;
+ opts.tooltip = {
+ textList: option.textList?option.textList:textList,
+ offset: offset,
+ option: option,
+ index: index
+ };
+ }
+ }
+ drawCharts.call(this, opts.type, opts, this.config, this.context);
+ }
+ if (this.opts.type === 'pie' || this.opts.type === 'ring' || this.opts.type === 'rose'||this.opts.type === 'funnel' ) {
+ var index = option.index==undefined? this.getCurrentDataIndex(e):option.index ;
+ if (index > -1) {
+ var currentOffset = this.scrollOption.currentOffset;
+ var opts = assign({}, this.opts, {
+ _scrollDistance_: currentOffset,
+ animation: false
+ });
+ var seriesData = this.opts._series_[index];
+ var textList = [{
+ text: option.format ? option.format(seriesData) : seriesData.name + ': ' + seriesData.data,
+ color: seriesData.color
+ }];
+ var offset = {
+ x: _touches$.x,
+ y: _touches$.y
+ };
+ opts.tooltip = {
+ textList: option.textList?option.textList:textList,
+ offset: offset,
+ option: option,
+ index: index
+ };
+ }
+ drawCharts.call(this, opts.type, opts, this.config, this.context);
+ }
+ if (this.opts.type === 'map'||this.opts.type === 'word') {
+ var index = option.index==undefined? this.getCurrentDataIndex(e):option.index ;
+ if (index > -1) {
+ var currentOffset = this.scrollOption.currentOffset;
+ var opts = assign({}, this.opts, {
+ _scrollDistance_: currentOffset,
+ animation: false
+ });
+ var seriesData = this.opts._series_[index];
+ var textList = [{
+ text: option.format ? option.format(seriesData) : seriesData.properties.name ,
+ color: seriesData.color
+ }];
+ var offset = {
+ x: _touches$.x,
+ y: _touches$.y
+ };
+ opts.tooltip = {
+ textList: option.textList?option.textList:textList,
+ offset: offset,
+ option: option,
+ index: index
+ };
+ }
+ opts.updateData = false;
+ drawCharts.call(this, opts.type, opts, this.config, this.context);
+ }
+ if (this.opts.type === 'radar') {
+ var index = option.index==undefined? this.getCurrentDataIndex(e):option.index ;
+ if (index > -1) {
+ var currentOffset = this.scrollOption.currentOffset;
+ var opts = assign({}, this.opts, {
+ _scrollDistance_: currentOffset,
+ animation: false
+ });
+ var seriesData = getSeriesDataItem(this.opts.series, index);
+ if (seriesData.length !== 0) {
+ var textList = seriesData.map(function(item) {
+ return {
+ text: option.format ? option.format(item) : item.name + ': ' + item.data,
+ color: item.color
+ };
+ });
+ var offset = {
+ x: _touches$.x,
+ y: _touches$.y
+ };
+ opts.tooltip = {
+ textList: option.textList?option.textList:textList,
+ offset: offset,
+ option: option,
+ index: index
+ };
+ }
+ }
+ drawCharts.call(this, opts.type, opts, this.config, this.context);
+ }
+};
+
+Charts.prototype.translate = function(distance) {
+ this.scrollOption = {
+ currentOffset: distance,
+ startTouchX: distance,
+ distance: 0,
+ lastMoveTime: 0
+ };
+ let opts = assign({}, this.opts, {
+ _scrollDistance_: distance,
+ animation: false
+ });
+ drawCharts.call(this, this.opts.type, opts, this.config, this.context);
+};
+
+Charts.prototype.scrollStart = function(e) {
+ var touches = null;
+ if (e.changedTouches) {
+ touches = e.changedTouches[0];
+ } else {
+ touches = e.mp.changedTouches[0];
+ }
+ var _touches$ = getTouches(touches, this.opts, e);
+ if (touches && this.opts.enableScroll === true) {
+ this.scrollOption.startTouchX = _touches$.x;
+ }
+};
+
+Charts.prototype.scroll = function(e) {
+ if (this.scrollOption.lastMoveTime === 0) {
+ this.scrollOption.lastMoveTime = Date.now();
+ }
+ let Limit = this.opts.extra.touchMoveLimit || 20;
+ let currMoveTime = Date.now();
+ let duration = currMoveTime - this.scrollOption.lastMoveTime;
+ if (duration < Math.floor(1000 / Limit)) return;
+ this.scrollOption.lastMoveTime = currMoveTime;
+ var touches = null;
+ if (e.changedTouches) {
+ touches = e.changedTouches[0];
+ } else {
+ touches = e.mp.changedTouches[0];
+ }
+ if (touches && this.opts.enableScroll === true) {
+ var _touches$ = getTouches(touches, this.opts, e);
+ var _distance;
+ _distance = _touches$.x - this.scrollOption.startTouchX;
+ var currentOffset = this.scrollOption.currentOffset;
+ var validDistance = calValidDistance(this,currentOffset + _distance, this.opts.chartData, this.config, this.opts);
+ this.scrollOption.distance = _distance = validDistance - currentOffset;
+ var opts = assign({}, this.opts, {
+ _scrollDistance_: currentOffset + _distance,
+ animation: false
+ });
+ drawCharts.call(this, opts.type, opts, this.config, this.context);
+ return currentOffset + _distance;
+ }
+};
+
+Charts.prototype.scrollEnd = function(e) {
+ if (this.opts.enableScroll === true) {
+ var _scrollOption = this.scrollOption,
+ currentOffset = _scrollOption.currentOffset,
+ distance = _scrollOption.distance;
+ this.scrollOption.currentOffset = currentOffset + distance;
+ this.scrollOption.distance = 0;
+ }
+};
+if (typeof module === "object" && typeof module.exports === "object") {
+ module.exports = Charts;
+ //export default Charts;//建议使用nodejs的module导出方式,如报错请使用export方式导出
+}
diff --git a/components/utils/util.js b/components/utils/util.js
new file mode 100644
index 0000000..d4cf5d0
--- /dev/null
+++ b/components/utils/util.js
@@ -0,0 +1,315 @@
+function formatTime2(date) {
+ var year = date.getFullYear()
+ var month = date.getMonth() + 1
+ var day = date.getDate()
+
+ var hour = date.getHours()
+ var minute = date.getMinutes()
+ var second = date.getSeconds()
+
+
+ return [year, month, day].map(formatNumber).join('-')
+}
+
+function dateAddDays(date) {
+ date = date.replace(/\-/g, '\/'); //日期参数 格式new Date("2017/09/12")所有浏览器都兼容,new Date("2017-09-12") 部分IE不兼容
+ var dd = new Date(date);
+ dd.setDate(dd.getDate() + 1);
+ var year = dd.getFullYear();
+ var m = dd.getMonth() + 1; //获取当前月份的日期
+ var d = dd.getDate();
+ var mon = (m < 10) ? ('0' + m) : ('' + m);
+ var day = (d < 10) ? ('0' + d) : ('' + d);
+ return year + "-" + mon + "-" + day;
+}
+
+function dateAddDayz(date) {
+ date = date.replace(/\-/g, '\/'); //日期参数 格式new Date("2017/09/12")所有浏览器都兼容,new Date("2017-09-12") 部分IE不兼容
+ var dd = new Date(date);
+ dd.setDate(dd.getDate() - 1);
+ var year = dd.getFullYear();
+ var m = dd.getMonth() + 1; //获取当前月份的日期
+ var d = dd.getDate();
+ var mon = (m < 10) ? ('0' + m) : ('' + m);
+ var day = (d < 10) ? ('0' + d) : ('' + d);
+ return year + "-" + mon + "-" + day;
+
+ return pdate;
+}
+
+function dateDiffIncludeToday(startDateString, endDateString) {
+ var oDate1 = new Date(startDateString);
+ var oDate2 = new Date(endDateString);
+ if (oDate1.getTime() > oDate2.getTime()) {
+ return 1;
+ } else {
+ return 2;
+ }
+}
+
+function jianDate(date, days) {
+ var d = new Date(date);
+ d.setDate(d.getDate() - days);
+ var m = d.getMonth() + 1;
+ return d.getFullYear() + '-' + m + '-' + d.getDate();
+}
+
+function formatTime(time) {
+ if (typeof time !== 'number' || time < 0) {
+ return time
+ }
+
+ var hour = parseInt(time / 3600)
+ time = time % 3600
+ var minute = parseInt(time / 60)
+ time = time % 60
+ var second = time
+
+ return ([hour, minute, second]).map(function(n) {
+ n = n.toString()
+ return n[1] ? n : '0' + n
+ }).join(':')
+}
+
+function formatLocation(longitude, latitude) {
+ if (typeof longitude === 'string' && typeof latitude === 'string') {
+ longitude = parseFloat(longitude)
+ latitude = parseFloat(latitude)
+ }
+
+ longitude = longitude.toFixed(2)
+ latitude = latitude.toFixed(2)
+
+ return {
+ longitude: longitude.toString().split('.'),
+ latitude: latitude.toString().split('.')
+ }
+}
+
+function formatDate(date) {
+ var year = date.getFullYear()
+ var month = date.getMonth() + 1
+ var day = date.getDate()
+
+ // if (date.getHours() >= 24) {
+ // day = date.getDate()+24
+ // }
+
+ return [year, month, day].map(formatNumber).join('-')
+}
+
+function adddate(date, num) {
+ var dd = new Date(date);
+ dd.setDate(dd.getDate() + num); //获取AddDayCount天后的日期
+ var y = dd.getFullYear();
+ var m = dd.getMonth() + 1; //获取当前月份的日期
+ var d = dd.getDate();
+ return y + '-' + (m < 10 ? '0' + m : m) + '-' + d
+}
+
+function formatNumber(n) {
+ n = n.toString()
+ return n[1] ? n : '0' + n
+}
+
+
+//判断两个日期间隔
+function comparedate(sDate, eDate){
+ var sdate = new Date(sDate);
+ var edate = new Date(eDate);
+ var comp = Math.abs(sdate.getTime() - edate.getTime());
+ return Math.floor(comp/86400000);
+}
+// 农历日期
+var lunar = {
+ tg: '甲乙丙丁戊己庚辛壬癸',
+ dz: '子丑寅卯辰巳午未申酉戌亥',
+ number: '一二三四五六七八九十',
+ year: '鼠牛虎兔龙蛇马羊猴鸡狗猪',
+ month: '正二三四五六七八九十冬腊',
+ monthadd: [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334],
+ calendar: [
+ 0xa4b,
+ 0x5164b,
+ 0x6a5,
+ 0x6d4,
+ 0x415b5,
+ 0x2b6,
+ 0x957,
+ 0x2092f,
+ 0x497,
+ 0x60c96,
+ 0xd4a,
+ 0xea5,
+ 0x50da9,
+ 0x5ad,
+ 0x2b6,
+ 0x3126e,
+ 0x92e,
+ 0x7192d,
+ 0xc95,
+ 0xd4a,
+ 0x61b4a,
+ 0xb55,
+ 0x56a,
+ 0x4155b,
+ 0x25d,
+ 0x92d,
+ 0x2192b,
+ 0xa95,
+ 0x71695,
+ 0x6ca,
+ 0xb55,
+ 0x50ab5,
+ 0x4da,
+ 0xa5b,
+ 0x30a57,
+ 0x52b,
+ 0x8152a,
+ 0xe95,
+ 0x6aa,
+ 0x615aa,
+ 0xab5,
+ 0x4b6,
+ 0x414ae,
+ 0xa57,
+ 0x526,
+ 0x31d26,
+ 0xd95,
+ 0x70b55,
+ 0x56a,
+ 0x96d,
+ 0x5095d,
+ 0x4ad,
+ 0xa4d,
+ 0x41a4d,
+ 0xd25,
+ 0x81aa5,
+ 0xb54,
+ 0xb6a,
+ 0x612da,
+ 0x95b,
+ 0x49b,
+ 0x41497,
+ 0xa4b,
+ 0xa164b,
+ 0x6a5,
+ 0x6d4,
+ 0x615b4,
+ 0xab6,
+ 0x957,
+ 0x5092f,
+ 0x497,
+ 0x64b,
+ 0x30d4a,
+ 0xea5,
+ 0x80d65,
+ 0x5ac,
+ 0xab6,
+ 0x5126d,
+ 0x92e,
+ 0xc96,
+ 0x41a95,
+ 0xd4a,
+ 0xda5,
+ 0x20b55,
+ 0x56a,
+ 0x7155b,
+ 0x25d,
+ 0x92d,
+ 0x5192b,
+ 0xa95,
+ 0xb4a,
+ 0x416aa,
+ 0xad5,
+ 0x90ab5,
+ 0x4ba,
+ 0xa5b,
+ 0x60a57,
+ 0x52b,
+ 0xa93,
+ 0x40e95
+ ]
+};
+// 农历日期
+function getLunarDate(date) {
+ var year, month, day;
+ if (!date) {
+ (date = new Date()), (year = date.getFullYear()), (month = date.getMonth()), (day = date.getDate());
+ } else {
+ (date = date.split('-')), (year = parseInt(date[0])), (month = date[1] - 1), (day = parseInt(date[2]));
+ }
+ if (year < 1921 ) {
+ return {};
+ }
+ var total, m, n, k, bit, lunarYear, lunarMonth, lunarDay;
+ var isEnd = false;
+ var tmp = year;
+ if (tmp < 1900) {
+ tmp += 1900;
+ }
+ total = (tmp - 1921) * 365 + Math.floor((tmp - 1921) / 4) + lunar.monthadd[month] + day - 38;
+ if (year % 4 == 0 && month > 1) {
+ total++;
+ }
+ for (m = 0; ; m++) {
+ k = lunar.calendar[m] < 0xfff ? 11 : 12;
+ for (n = k; n >= 0; n--) {
+ bit = (lunar.calendar[m] >> n) & 1;
+ if (total <= 29 + bit) {
+ isEnd = true;
+ break;
+ }
+ total = total - 29 - bit;
+ }
+ if (isEnd) break;
+ }
+ lunarYear = 1921 + m;
+ lunarMonth = k - n + 1;
+ lunarDay = total;
+ if (k == 12) {
+ if (lunarMonth == Math.floor(lunar.calendar[m] / 0x10000) + 1) {
+ lunarMonth = 1 - lunarMonth;
+ }
+ if (lunarMonth > Math.floor(lunar.calendar[m] / 0x10000) + 1) {
+ lunarMonth--;
+ }
+ }
+ return {
+ lunarYear: lunarYear,
+ lunarMonth: lunarMonth,
+ lunarDay: lunarDay
+ };
+}
+// 农历日期
+function getLunarDateString(lunarDate) {
+ if (!lunarDate.lunarDay) return;
+ var data = {},
+ lunarYear = lunarDate.lunarYear,
+ lunarMonth = lunarDate.lunarMonth,
+ lunarDay = lunarDate.lunarDay;
+ data.tg = lunar.tg.charAt((lunarYear - 4) % 10);
+ data.dz = lunar.dz.charAt((lunarYear - 4) % 12);
+ data.year = lunar.year.charAt((lunarYear - 4) % 12);
+ data.month = lunarMonth < 1 ? '(闰)' + lunar.month.charAt(-lunarMonth - 1) : lunar.month.charAt(lunarMonth - 1);
+
+ data.day = lunarDay < 11 ? '初' : lunarDay < 20 ? '十' : lunarDay < 30 ? '廿' : '三十';
+ if (lunarDay % 10 != 0 || lunarDay == 10) {
+ data.day += lunar.number.charAt((lunarDay - 1) % 10);
+ }
+ return data;
+}
+
+
+module.exports = {
+ comparedate:comparedate,
+ formatTime: formatTime,
+ formatDate: formatDate,
+ formatTime2: formatTime2,
+ dateAddDays: dateAddDays,
+ dateAddDayz: dateAddDayz,
+ dateDiffIncludeToday: dateDiffIncludeToday,
+ adddate: adddate,
+ getLunarDate:getLunarDate,
+ getLunarDateString:getLunarDateString
+}
diff --git a/components/utils/zixunpj.vue b/components/utils/zixunpj.vue
new file mode 100644
index 0000000..c681d3d
--- /dev/null
+++ b/components/utils/zixunpj.vue
@@ -0,0 +1,363 @@
+
+
+
+
+ 游客评论
+
+
+ 空空如也,这暂时什么都没有哦~
+
+
+
+
+
+ {{el.userName}}
+
+
+
+
+
+
+
+
+
+
+ {{el.content}}
+
+
+ {{el.createTime}}
+
+
+
+
+ {{item}}
+
+
+
+
+
+ 去评论
+
+
+
+
+
+
+
+
diff --git a/components/w-picker/areadata/areadata.js b/components/w-picker/areadata/areadata.js
new file mode 100644
index 0000000..b07228c
--- /dev/null
+++ b/components/w-picker/areadata/areadata.js
@@ -0,0 +1 @@
+const cityData=[{value:'110000',label:'北京市',children:[{value:"110100",label:"北京市",children:[{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:'120000',label:'天津市',children:[{value:"120100",label:"天津市",children:[{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:'130000',label:'河北省',children:[{value:"130100",label:"石家庄市",children:[{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:"130181",label:"辛集市"},{value:"130183",label:"晋州市"},{value:"130184",label:"新乐市"},{value:"130172",label:"石家庄循环化工园区"},{value:"130171",label:"石家庄高新技术产业开发区"}]},{value:"130200",label:"唐山市",children:[{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:"130281",label:"遵化市"},{value:"130283",label:"迁安市"},{value:"130271",label:"唐山市芦台经济技术开发区"},{value:"130272",label:"唐山市汉沽管理区"},{value:"130273",label:"唐山高新技术产业开发区"},{value:"130274",label:"河北唐山海港经济开发区"}]},{value:"130300",label:"秦皇岛市",children:[{value:"130302",label:"海港区"},{value:"130303",label:"山海关区"},{value:"130304",label:"北戴河区"},{value:"130321",label:"青龙满族自治县"},{value:"130322",label:"昌黎县"},{value:"130306",label:"抚宁区"},{value:"130324",label:"卢龙县"},{value:"130371",label:"秦皇岛市经济技术开发区"},{value:"130372",label:"北戴河新区"}]},{value:"130400",label:"邯郸市",children:[{value:"130402",label:"邯山区"},{value:"130403",label:"丛台区"},{value:"130404",label:"复兴区"},{value:"130406",label:"峰峰矿区"},{value:"130421",label:"邯郸县"},{value:"130423",label:"临漳县"},{value:"130424",label:"成安县"},{value:"130425",label:"大名县"},{value:"130426",label:"涉县"},{value:"130427",label:"磁县"},{value:"130407",label:"肥乡区"},{value:"130408",label:"永年区"},{value:"130430",label:"邱县"},{value:"130431",label:"鸡泽县"},{value:"130432",label:"广平县"},{value:"130433",label:"馆陶县"},{value:"130434",label:"魏县"},{value:"130435",label:"曲周县"},{value:"130481",label:"武安市"},{value:"130471",label:"邯郸经济技术开发区"},{value:"130473",label:"邯郸冀南新区"}]},{value:"130500",label:"邢台市",children:[{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:"130581",label:"南宫市"},{value:"130582",label:"沙河市"},{value:"130571",label:"河北邢台经济开发区"}]},{value:"130600",label:"保定市",children:[{value:"130602",label:"竞秀区"},{value:"130606",label:"莲池区"},{value:"130607",label:"满城区"},{value:"130608",label:"清苑区"},{value:"130623",label:"涞水县"},{value:"130624",label:"阜平县"},{value:"130609",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:"130681",label:"涿州市"},{value:"130682",label:"定州市"},{value:"130683",label:"安国市"},{value:"130684",label:"高碑店市"},{value:"130671",label:"保定高新技术产业开发区"},{value:"130672",label:"保定白沟新城"}]},{value:"130700",label:"张家口市",children:[{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:"130733",label:"崇礼县"},{value:"130771",label:"张家口市高新技术产业开发区"},{value:"130772",label:"张家口市察北管理区"},{value:"130773",label:"张家口市塞北管理区"}]},{value:"130800",label:"承德市",children:[{value:"130802",label:"双桥区"},{value:"130803",label:"双滦区"},{value:"130804",label:"鹰手营子矿区"},{value:"130821",label:"承德县"},{value:"130822",label:"兴隆县"},{value:"130881",label:"平泉市"},{value:"130824",label:"滦平县"},{value:"130825",label:"隆化县"},{value:"130826",label:"丰宁满族自治县"},{value:"130827",label:"宽城满族自治县"},{value:"130828",label:"围场满族蒙古族自治县"},{value:"130871",label:"承德高新技术产业开发区"}]},{value:"130900",label:"沧州市",children:[{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:"130981",label:"泊头市"},{value:"130982",label:"任丘市"},{value:"130983",label:"黄骅市"},{value:"130984",label:"河间市"},{value:"130971",label:"河北沧州经济开发区"},{value:"130972",label:"沧州高新技术产业开发区"},{value:"130973",label:"沧州渤海新区"}]},{value:"131000",label:"廊坊市",children:[{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:"131100",label:"衡水市",children:[{value:"131102",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:"131103",label:"冀州区"},{value:"131182",label:"深州市"},{value:"131172",label:"衡水滨湖新区"},{value:"131171",label:"河北衡水经济开发区"}]}]},{value:'140000',label:'山西省',children:[{value:"140100",label:"太原市",children:[{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:"140181",label:"古交市"},{value:"140171",label:"山西转型综合改革示范区"}]},{value:"140200",label:"大同市",children:[{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:"140300",label:"阳泉市",children:[{value:"140302",label:"城区"},{value:"140303",label:"矿区"},{value:"140311",label:"郊区"},{value:"140321",label:"平定县"},{value:"140322",label:"盂县"},{value:"140371",label:"山西阳泉经济开发区"}]},{value:"140400",label:"长治市",children:[{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:"140481",label:"潞城市"},{value:"140402",label:"城区"},{value:"140411",label:"郊区"},{value:"140471",label:"山西长治高新技术产业园区"}]},{value:"140500",label:"晋城市",children:[{value:"140502",label:"城区"},{value:"140521",label:"沁水县"},{value:"140522",label:"阳城县"},{value:"140524",label:"陵川县"},{value:"140525",label:"泽州县"},{value:"140581",label:"高平市"}]},{value:"140600",label:"朔州市",children:[{value:"140602",label:"朔城区"},{value:"140603",label:"平鲁区"},{value:"140621",label:"山阴县"},{value:"140622",label:"应县"},{value:"140623",label:"右玉县"},{value:"140624",label:"怀仁县"},{value:"140671",label:"山西朔州经济开发区"}]},{value:"140700",label:"晋中市",children:[{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:"140800",label:"运城市",children:[{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:"140900",label:"忻州市",children:[{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:"140981",label:"原平市"},{value:"140971",label:"五台山风景名胜区"}]},{value:"141000",label:"临汾市",children:[{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:"141100",label:"吕梁市",children:[{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:'150000',label:'内蒙古',children:[{value:"150100",label:"呼和浩特市",children:[{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:"150200",label:"包头市",children:[{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:"150300",label:"乌海市",children:[{value:"150302",label:"海勃湾区"},{value:"150303",label:"海南区"},{value:"150304",label:"乌达区"}]},{value:"150400",label:"赤峰市",children:[{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:"150500",label:"通辽市",children:[{value:"150502",label:"科尔沁区"},{value:"150521",label:"科尔沁左翼中旗"},{value:"150522",label:"科尔沁左翼后旗"},{value:"150523",label:"开鲁县"},{value:"150524",label:"库伦旗"},{value:"150525",label:"奈曼旗"},{value:"150526",label:"扎鲁特旗"},{value:"150581",label:"霍林郭勒市"},{value:"150571",label:"通辽经济技术开发区"}]},{value:"150600",label:"鄂尔多斯市",children:[{value:"150602",label:"东胜区"},{value:"150621",label:"达拉特旗"},{value:"150622",label:"准格尔旗"},{value:"150623",label:"鄂托克前旗"},{value:"150624",label:"鄂托克旗"},{value:"150625",label:"杭锦旗"},{value:"150626",label:"乌审旗"},{value:"150627",label:"伊金霍洛旗"},{value:"150603",label:"康巴什区"}]},{value:"150700",label:"呼伦贝尔市",children:[{value:"150702",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:"150703",label:"扎赉诺尔区"}]},{value:"150800",label:"巴彦淖尔市",children:[{value:"150802",label:"临河区"},{value:"150821",label:"五原县"},{value:"150822",label:"磴口县"},{value:"150823",label:"乌拉特前旗"},{value:"150824",label:"乌拉特中旗"},{value:"150825",label:"乌拉特后旗"},{value:"150826",label:"杭锦后旗"}]},{value:"150900",label:"乌兰察布市",children:[{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:"152200",label:"兴安盟",children:[{value:"152201",label:"乌兰浩特市"},{value:"152202",label:"阿尔山市"},{value:"152221",label:"科尔沁右翼前旗"},{value:"152222",label:"科尔沁右翼中旗"},{value:"152223",label:"扎赉特旗"},{value:"152224",label:"突泉县"}]},{value:"152500",label:"锡林郭勒盟",children:[{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:"152900",label:"阿拉善盟",children:[{value:"152921",label:"阿拉善左旗"},{value:"152922",label:"阿拉善右旗"},{value:"152923",label:"额济纳旗"},{value:"152971",label:"内蒙古阿拉善经济开发区"}]}]},{value:'210000',label:'辽宁省',children:[{value:"210100",label:"沈阳市",children:[{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:"210112",label:"浑南区"},{value:"210113",label:"沈北新区"}]},{value:"210200",label:"大连市",children:[{value:"210202",label:"中山区"},{value:"210203",label:"西岗区"},{value:"210204",label:"沙河口区"},{value:"210211",label:"甘井子区"},{value:"210212",label:"旅顺口区"},{value:"210213",label:"金州区"},{value:"210224",label:"长海县"},{value:"210251",label:"开发区"},{value:"210281",label:"瓦房店市"},{value:"210214",label:"普兰店区"},{value:"210283",label:"庄河市"}]},{value:"210300",label:"鞍山市",children:[{value:"210302",label:"铁东区"},{value:"210303",label:"铁西区"},{value:"210304",label:"立山区"},{value:"210311",label:"千山区"},{value:"210321",label:"台安县"},{value:"210323",label:"岫岩满族自治县"},{value:"210381",label:"海城市"}]},{value:"210400",label:"抚顺市",children:[{value:"210402",label:"新抚区"},{value:"210403",label:"东洲区"},{value:"210404",label:"望花区"},{value:"210411",label:"顺城区"},{value:"210421",label:"抚顺县"},{value:"210422",label:"新宾满族自治县"},{value:"210423",label:"清原满族自治县"}]},{value:"210500",label:"本溪市",children:[{value:"210502",label:"平山区"},{value:"210503",label:"溪湖区"},{value:"210504",label:"明山区"},{value:"210505",label:"南芬区"},{value:"210521",label:"本溪满族自治县"},{value:"210522",label:"桓仁满族自治县"}]},{value:"210600",label:"丹东市",children:[{value:"210602",label:"元宝区"},{value:"210603",label:"振兴区"},{value:"210604",label:"振安区"},{value:"210624",label:"宽甸满族自治县"},{value:"210681",label:"东港市"},{value:"210682",label:"凤城市"}]},{value:"210700",label:"锦州市",children:[{value:"210702",label:"古塔区"},{value:"210703",label:"凌河区"},{value:"210711",label:"太和区"},{value:"210726",label:"黑山县"},{value:"210727",label:"义县"},{value:"210781",label:"凌海市"},{value:"210782",label:"北镇市"}]},{value:"210800",label:"营口市",children:[{value:"210802",label:"站前区"},{value:"210803",label:"西市区"},{value:"210804",label:"鲅鱼圈区"},{value:"210811",label:"老边区"},{value:"210881",label:"盖州市"},{value:"210882",label:"大石桥市"}]},{value:"210900",label:"阜新市",children:[{value:"210902",label:"海州区"},{value:"210903",label:"新邱区"},{value:"210904",label:"太平区"},{value:"210905",label:"清河门区"},{value:"210911",label:"细河区"},{value:"210921",label:"阜新蒙古族自治县"},{value:"210922",label:"彰武县"}]},{value:"211000",label:"辽阳市",children:[{value:"211002",label:"白塔区"},{value:"211003",label:"文圣区"},{value:"211004",label:"宏伟区"},{value:"211005",label:"弓长岭区"},{value:"211011",label:"太子河区"},{value:"211021",label:"辽阳县"},{value:"211081",label:"灯塔市"}]},{value:"211100",label:"盘锦市",children:[{value:"211102",label:"双台子区"},{value:"211103",label:"兴隆台区"},{value:"211121",label:"大洼县"},{value:"211122",label:"盘山县"}]},{value:"211200",label:"铁岭市",children:[{value:"211202",label:"银州区"},{value:"211204",label:"清河区"},{value:"211221",label:"铁岭县"},{value:"211223",label:"西丰县"},{value:"211224",label:"昌图县"},{value:"211281",label:"调兵山市"},{value:"211282",label:"开原市"}]},{value:"211300",label:"朝阳市",children:[{value:"211302",label:"双塔区"},{value:"211303",label:"龙城区"},{value:"211321",label:"朝阳县"},{value:"211322",label:"建平县"},{value:"211324",label:"喀喇沁左翼蒙古族自治县"},{value:"211381",label:"北票市"},{value:"211382",label:"凌源市"}]},{value:"211400",label:"葫芦岛市",children:[{value:"211402",label:"连山区"},{value:"211403",label:"龙港区"},{value:"211404",label:"南票区"},{value:"211421",label:"绥中县"},{value:"211422",label:"建昌县"},{value:"211481",label:"兴城市"}]}]},{value:'220000',label:'吉林省',children:[{value:"220100",label:"长春市",children:[{value:"220102",label:"南关区"},{value:"220103",label:"宽城区"},{value:"220104",label:"朝阳区"},{value:"220105",label:"二道区"},{value:"220106",label:"绿园区"},{value:"220112",label:"双阳区"},{value:"220122",label:"农安县"},{value:"220181",label:"九台市"},{value:"220182",label:"榆树市"},{value:"220183",label:"德惠市"},{value:"220171",label:"长春经济技术开发区"},{value:"220172",label:"长春净月高新技术产业开发区"},{value:"220173",label:"长春高新技术产业开发区"},{value:"220174",label:"长春汽车经济技术开发区"}]},{value:"220200",label:"吉林市",children:[{value:"220202",label:"昌邑区"},{value:"220203",label:"龙潭区"},{value:"220204",label:"船营区"},{value:"220211",label:"丰满区"},{value:"220221",label:"永吉县"},{value:"220281",label:"蛟河市"},{value:"220282",label:"桦甸市"},{value:"220283",label:"舒兰市"},{value:"220284",label:"磐石市"},{value:"220271",label:"吉林经济开发区"},{value:"220272",label:"吉林高新技术产业开发区"},{value:"220273",label:"吉林中国新加坡食品区"}]},{value:"220300",label:"四平市",children:[{value:"220302",label:"铁西区"},{value:"220303",label:"铁东区"},{value:"220322",label:"梨树县"},{value:"220323",label:"伊通满族自治县"},{value:"220381",label:"公主岭市"},{value:"220382",label:"双辽市"}]},{value:"220400",label:"辽源市",children:[{value:"220402",label:"龙山区"},{value:"220403",label:"西安区"},{value:"220421",label:"东丰县"},{value:"220422",label:"东辽县"}]},{value:"220500",label:"通化市",children:[{value:"220502",label:"东昌区"},{value:"220503",label:"二道江区"},{value:"220521",label:"通化县"},{value:"220523",label:"辉南县"},{value:"220524",label:"柳河县"},{value:"220581",label:"梅河口市"},{value:"220582",label:"集安市"}]},{value:"220600",label:"白山市",children:[{value:"220602",label:"八道江区"},{value:"220621",label:"抚松县"},{value:"220622",label:"靖宇县"},{value:"220623",label:"长白朝鲜族自治县"},{value:"220605",label:"江源区"},{value:"220681",label:"临江市"},{value:"220602",label:"浑江区"}]},{value:"220700",label:"松原市",children:[{value:"220702",label:"宁江区"},{value:"220721",label:"前郭尔罗斯蒙古族自治县"},{value:"220722",label:"长岭县"},{value:"220723",label:"乾安县"},{value:"220781",label:"扶余市"},{value:"220771",label:"吉林松原经济开发区"}]},{value:"220800",label:"白城市",children:[{value:"220802",label:"洮北区"},{value:"220821",label:"镇赉县"},{value:"220822",label:"通榆县"},{value:"220881",label:"洮南市"},{value:"220882",label:"大安市"},{value:"220871",label:"吉林白城经济开发区"}]},{value:"222400",label:"延边朝鲜族自治州",children:[{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:'230000',label:'黑龙江省',children:[{value:"230100",label:"哈尔滨市",children:[{value:"230102",label:"道里区"},{value:"230103",label:"南岗区"},{value:"230104",label:"道外区"},{value:"230110",label:"香坊区"},{value:"230107",label:"动力区"},{value:"230108",label:"平房区"},{value:"230109",label:"松北区"},{value:"230111",label:"呼兰区"},{value:"230123",label:"依兰县"},{value:"230124",label:"方正县"},{value:"230125",label:"宾县"},{value:"230126",label:"巴彦县"},{value:"230127",label:"木兰县"},{value:"230128",label:"通河县"},{value:"230129",label:"延寿县"},{value:"230112",label:"阿城区"},{value:"230113",label:"双城区"},{value:"230183",label:"尚志市"},{value:"230184",label:"五常市"}]},{value:"230200",label:"齐齐哈尔市",children:[{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:"230300",label:"鸡西市",children:[{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:"230400",label:"鹤岗市",children:[{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:"230500",label:"双鸭山市",children:[{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:"230600",label:"大庆市",children:[{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:"230700",label:"伊春市",children:[{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:"230800",label:"佳木斯市",children:[{value:"230803",label:"向阳区"},{value:"230804",label:"前进区"},{value:"230805",label:"东风区"},{value:"230811",label:"郊区"},{value:"230822",label:"桦南县"},{value:"230826",label:"桦川县"},{value:"230828",label:"汤原县"},{value:"230833",label:"抚远市"},{value:"230881",label:"同江市"},{value:"230882",label:"富锦市"}]},{value:"230900",label:"七台河市",children:[{value:"230902",label:"新兴区"},{value:"230903",label:"桃山区"},{value:"230904",label:"茄子河区"},{value:"230921",label:"勃利县"}]},{value:"231000",label:"牡丹江市",children:[{value:"231002",label:"东安区"},{value:"231003",label:"阳明区"},{value:"231004",label:"爱民区"},{value:"231005",label:"西安区"},{value:"231086",label:"东宁市"},{value:"231025",label:"林口县"},{value:"231081",label:"绥芬河市"},{value:"231083",label:"海林市"},{value:"231084",label:"宁安市"},{value:"231085",label:"穆棱市"},{value:"231071",label:"牡丹江经济技术开发区"}]},{value:"231100",label:"黑河市",children:[{value:"231102",label:"爱辉区"},{value:"231121",label:"嫩江县"},{value:"231123",label:"逊克县"},{value:"231124",label:"孙吴县"},{value:"231181",label:"北安市"},{value:"231182",label:"五大连池市"}]},{value:"231200",label:"绥化市",children:[{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:"232700",label:"大兴安岭地区",children:[{value:"232721",label:"呼玛县"},{value:"232722",label:"塔河县"},{value:"232723",label:"漠河县"},{value:"232701",label:"加格达奇区"},{value:"232704",label:"呼中区"},{value:"232703",label:"新林区"}]}]},{value:'310000',label:'上海市',children:[{value:'310100',label:'上海市',children:[{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:'320000',label:'江苏省',children:[{value:"320100",label:"南京市",children:[{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:"320200",label:"无锡市",children:[{value:"320205",label:"锡山区"},{value:"320206",label:"惠山区"},{value:"320211",label:"滨湖区"},{value:"320281",label:"江阴市"},{value:"320282",label:"宜兴市"},{value:"320213",label:"梁溪区"},{value:"320214",label:"新吴区"}]},{value:"320300",label:"徐州市",children:[{value:"320302",label:"鼓楼区"},{value:"320303",label:"云龙区"},{value:"320305",label:"贾汪区"},{value:"320311",label:"泉山区"},{value:"320321",label:"丰县"},{value:"320322",label:"沛县"},{value:"320324",label:"睢宁县"},{value:"320381",label:"新沂市"},{value:"320382",label:"邳州市"},{value:"320371",label:"徐州经济技术开发区"}]},{value:"320400",label:"常州市",children:[{value:"320402",label:"天宁区"},{value:"320404",label:"钟楼区"},{value:"320411",label:"新北区"},{value:"320412",label:"武进区"},{value:"320481",label:"溧阳市"},{value:"320413",label:"金坛区"}]},{value:"320500",label:"苏州市",children:[{value:"320505",label:"虎丘区"},{value:"320506",label:"吴中区"},{value:"320507",label:"相城区"},{value:"320581",label:"常熟市"},{value:"320582",label:"张家港市"},{value:"320583",label:"昆山市"},{value:"320509",label:"吴江区"},{value:"320585",label:"太仓市"},{value:"320508",label:"姑苏区"},{value:"320571",label:"苏州工业园区"}]},{value:"320600",label:"南通市",children:[{value:"320602",label:"崇川区"},{value:"320611",label:"港闸区"},{value:"320612",label:"通州区"},{value:"320621",label:"海安县"},{value:"320623",label:"如东县"},{value:"320681",label:"启东市"},{value:"320682",label:"如皋市"},{value:"320684",label:"海门市"},{value:"320671",label:"南通经济技术开发区"}]},{value:"320700",label:"连云港市",children:[{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:"320800",label:"淮安市",children:[{value:"320804",label:"淮阴区"},{value:"320812",label:"清江浦区"},{value:"320826",label:"涟水县"},{value:"320813",label:"洪泽区"},{value:"320830",label:"盱眙县"},{value:"320831",label:"金湖县"},{value:"320803",label:"淮安区"},{value:"320871",label:"淮安经济技术开发区"}]},{value:"320900",label:"盐城市",children:[{value:"320902",label:"亭湖区"},{value:"320903",label:"盐都区"},{value:"320921",label:"响水县"},{value:"320922",label:"滨海县"},{value:"320904",label:"大丰区"},{value:"320923",label:"阜宁县"},{value:"320924",label:"射阳县"},{value:"320925",label:"建湖县"},{value:"320981",label:"东台市"},{value:"320971",label:"盐城经济技术开发区"}]},{value:"321000",label:"扬州市",children:[{value:"321002",label:"广陵区"},{value:"321003",label:"邗江区"},{value:"321011",label:"维扬区"},{value:"321023",label:"宝应县"},{value:"321081",label:"仪征市"},{value:"321084",label:"高邮市"},{value:"321012",label:"江都区"},{value:"321071",label:"扬州经济技术开发区"}]},{value:"321100",label:"镇江市",children:[{value:"321102",label:"京口区"},{value:"321111",label:"润州区"},{value:"321112",label:"丹徒区"},{value:"321181",label:"丹阳市"},{value:"321182",label:"扬中市"},{value:"321183",label:"句容市"},{value:"321171",label:"镇江新区"}]},{value:"321200",label:"泰州市",children:[{value:"321202",label:"海陵区"},{value:"321203",label:"高港区"},{value:"321281",label:"兴化市"},{value:"321282",label:"靖江市"},{value:"321283",label:"泰兴市"},{value:"321204",label:"姜堰区"},{value:"321271",label:"泰州医药高新技术产业开发区"}]},{value:"321300",label:"宿迁市",children:[{value:"321302",label:"宿城区"},{value:"321311",label:"宿豫区"},{value:"321322",label:"沭阳县"},{value:"321323",label:"泗阳县"},{value:"321324",label:"泗洪县"}]}]},{value:'330000',label:'浙江省',children:[{value:"330100",label:"杭州市",children:[{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:"330122",label:"桐庐县"},{value:"330127",label:"淳安县"},{value:"330182",label:"建德市"},{value:"330111",label:"富阳区"},{value:"330112",label:"临安区"},{value:"330186",label:"其它区"}]},{value:"330200",label:"宁波市",children:[{value:"330203",label:"海曙区"},{value:"330205",label:"江北区"},{value:"330206",label:"北仑区"},{value:"330211",label:"镇海区"},{value:"330212",label:"鄞州区"},{value:"330225",label:"象山县"},{value:"330226",label:"宁海县"},{value:"330281",label:"余姚市"},{value:"330282",label:"慈溪市"},{value:"330213",label:"奉化区"}]},{value:"330300",label:"温州市",children:[{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:"330381",label:"瑞安市"},{value:"330382",label:"乐清市"},{value:"330371",label:"温州经济技术开发区"}]},{value:"330400",label:"嘉兴市",children:[{value:"330402",label:"南湖区"},{value:"330411",label:"秀洲区"},{value:"330421",label:"嘉善县"},{value:"330424",label:"海盐县"},{value:"330481",label:"海宁市"},{value:"330482",label:"平湖市"},{value:"330483",label:"桐乡市"}]},{value:"330500",label:"湖州市",children:[{value:"330502",label:"吴兴区"},{value:"330503",label:"南浔区"},{value:"330521",label:"德清县"},{value:"330522",label:"长兴县"},{value:"330523",label:"安吉县"}]},{value:"330600",label:"绍兴市",children:[{value:"330602",label:"越城区"},{value:"330621",label:"柯桥区"},{value:"330681",label:"诸暨市"},{value:"330604",label:"上虞区"},{value:"330683",label:"嵊州市"},{value:"330624",label:"新昌县"}]},{value:"330700",label:"金华市",children:[{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:"330800",label:"衢州市",children:[{value:"330802",label:"柯城区"},{value:"330803",label:"衢江区"},{value:"330822",label:"常山县"},{value:"330824",label:"开化县"},{value:"330825",label:"龙游县"},{value:"330881",label:"江山市"}]},{value:"330900",label:"舟山市",children:[{value:"330902",label:"定海区"},{value:"330903",label:"普陀区"},{value:"330921",label:"岱山县"},{value:"330922",label:"嵊泗县"}]},{value:"331000",label:"台州市",children:[{value:"331002",label:"椒江区"},{value:"331003",label:"黄岩区"},{value:"331004",label:"路桥区"},{value:"331083",label:"玉环市"},{value:"331022",label:"三门县"},{value:"331023",label:"天台县"},{value:"331024",label:"仙居县"},{value:"331081",label:"温岭市"},{value:"331082",label:"临海市"}]},{value:"331100",label:"丽水市",children:[{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:'340000',label:'安徽省',children:[{value:"340100",label:"合肥市",children:[{value:"340111",label:"包河区"},{value:"340104",label:"蜀山区"},{value:"340103",label:"庐阳区"},{value:"340102",label:"瑶海区"},{value:"340171",label:"合肥高新技术产业开发区"},{value:"340172",label:"合肥经济技术开发区"},{value:"340173",label:"合肥新站高新技术产业开发区"},{value:"340121",label:"长丰县"},{value:"340122",label:"肥东县"},{value:"340123",label:"肥西县"},{value:"340124",label:"庐江县"},{value:"340181",label:"巢湖市"}]},{value:"340200",label:"芜湖市",children:[{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:"340272",label:"安徽芜湖长江大桥经济开发区"},{value:"340271",label:"芜湖经济技术开发区"}]},{value:"340300",label:"蚌埠市",children:[{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:"340400",label:"淮南市",children:[{value:"340402",label:"大通区"},{value:"340403",label:"田家庵区"},{value:"340404",label:"谢家集区"},{value:"340405",label:"八公山区"},{value:"340406",label:"潘集区"},{value:"340421",label:"凤台县"},{value:"340422",label:"寿县"}]},{value:"340500",label:"马鞍山市",children:[{value:"340503",label:"花山区"},{value:"340504",label:"雨山区"},{value:"340521",label:"当涂县"},{value:"340506",label:"博望区"},{value:"340522",label:"含山县"},{value:"340523",label:"和县"}]},{value:"340600",label:"淮北市",children:[{value:"340602",label:"杜集区"},{value:"340603",label:"相山区"},{value:"340604",label:"烈山区"},{value:"340621",label:"濉溪县"}]},{value:"340700",label:"铜陵市",children:[{value:"340705",label:"铜官区"},{value:"340706",label:"义安区"},{value:"340711",label:"郊区"},{value:"340722",label:"枞阳县"}]},{value:"340800",label:"安庆市",children:[{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:"340881",label:"桐城市"},{value:"340871",label:"安徽安庆经济开发区"}]},{value:"341000",label:"黄山市",children:[{value:"341002",label:"屯溪区"},{value:"341003",label:"黄山区"},{value:"341004",label:"徽州区"},{value:"341021",label:"歙县"},{value:"341022",label:"休宁县"},{value:"341023",label:"黟县"},{value:"341024",label:"祁门县"}]},{value:"341100",label:"滁州市",children:[{value:"341102",label:"琅琊区"},{value:"341103",label:"南谯区"},{value:"341122",label:"来安县"},{value:"341124",label:"全椒县"},{value:"341125",label:"定远县"},{value:"341126",label:"凤阳县"},{value:"341181",label:"天长市"},{value:"341182",label:"明光市"},{value:"341171",label:"苏滁现代产业园"},{value:"341172",label:"滁州经济技术开发区"}]},{value:"341200",label:"阜阳市",children:[{value:"341202",label:"颍州区"},{value:"341203",label:"颍东区"},{value:"341204",label:"颍泉区"},{value:"341221",label:"临泉县"},{value:"341222",label:"太和县"},{value:"341225",label:"阜南县"},{value:"341226",label:"颍上县"},{value:"341282",label:"界首市"},{value:"341272",label:"阜阳经济技术开发区"},{value:"341271",label:"阜阳合肥现代产业园区"}]},{value:"341300",label:"宿州市",children:[{value:"341302",label:"埇桥区"},{value:"341321",label:"砀山县"},{value:"341322",label:"萧县"},{value:"341323",label:"灵璧县"},{value:"341324",label:"泗县"},{value:"341371",label:"宿州马鞍山现代产业园区"},{value:"341372",label:"宿州经济技术开发区"}]},{value:"341500",label:"六安市",children:[{value:"341502",label:"金安区"},{value:"341503",label:"裕安区"},{value:"341504",label:"叶集区"},{value:"341522",label:"霍邱县"},{value:"341523",label:"舒城县"},{value:"341524",label:"金寨县"},{value:"341525",label:"霍山县"}]},{value:"341600",label:"亳州市",children:[{value:"341602",label:"谯城区"},{value:"341621",label:"涡阳县"},{value:"341622",label:"蒙城县"},{value:"341623",label:"利辛县"}]},{value:"341700",label:"池州市",children:[{value:"341702",label:"贵池区"},{value:"341721",label:"东至县"},{value:"341722",label:"石台县"},{value:"341723",label:"青阳县"}]},{value:"341800",label:"宣城市",children:[{value:"341802",label:"宣州区"},{value:"341821",label:"郎溪县"},{value:"341822",label:"广德县"},{value:"341823",label:"泾县"},{value:"341824",label:"绩溪县"},{value:"341825",label:"旌德县"},{value:"341881",label:"宁国市"},{value:"341871",label:"宣城市经济开发区"}]}]},{value:'350000',label:'福建省',children:[{value:"350100",label:"福州市",children:[{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:"350200",label:"厦门市",children:[{value:"350203",label:"思明区"},{value:"350205",label:"海沧区"},{value:"350206",label:"湖里区"},{value:"350211",label:"集美区"},{value:"350212",label:"同安区"},{value:"350213",label:"翔安区"}]},{value:"350300",label:"莆田市",children:[{value:"350302",label:"城厢区"},{value:"350303",label:"涵江区"},{value:"350304",label:"荔城区"},{value:"350305",label:"秀屿区"},{value:"350322",label:"仙游县"}]},{value:"350400",label:"三明市",children:[{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:"350500",label:"泉州市",children:[{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:"350600",label:"漳州市",children:[{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:"350700",label:"南平市",children:[{value:"350702",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:"350703",label:"建阳区"}]},{value:"350800",label:"龙岩市",children:[{value:"350802",label:"新罗区"},{value:"350821",label:"长汀县"},{value:"350803",label:"永定区"},{value:"350823",label:"上杭县"},{value:"350824",label:"武平县"},{value:"350825",label:"连城县"},{value:"350881",label:"漳平市"}]},{value:"350900",label:"宁德市",children:[{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:'360000',label:'江西省',children:[{value:"360100",label:"南昌市",children:[{value:"360102",label:"东湖区"},{value:"360103",label:"西湖区"},{value:"360104",label:"青云谱区"},{value:"360105",label:"湾里区"},{value:"360111",label:"青山湖区"},{value:"360121",label:"南昌县"},{value:"360112",label:"新建区"},{value:"360123",label:"安义县"},{value:"360124",label:"进贤县"}]},{value:"360200",label:"景德镇市",children:[{value:"360202",label:"昌江区"},{value:"360203",label:"珠山区"},{value:"360222",label:"浮梁县"},{value:"360281",label:"乐平市"}]},{value:"360300",label:"萍乡市",children:[{value:"360302",label:"安源区"},{value:"360313",label:"湘东区"},{value:"360321",label:"莲花县"},{value:"360322",label:"上栗县"},{value:"360323",label:"芦溪县"}]},{value:"360400",label:"九江市",children:[{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:"360500",label:"新余市",children:[{value:"360502",label:"渝水区"},{value:"360521",label:"分宜县"}]},{value:"360600",label:"鹰潭市",children:[{value:"360602",label:"月湖区"},{value:"360622",label:"余江县"},{value:"360681",label:"贵溪市"}]},{value:"360700",label:"赣州市",children:[{value:"360702",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:"360703",label:"南康区"}]},{value:"360800",label:"吉安市",children:[{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:"360900",label:"宜春市",children:[{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:"361000",label:"抚州市",children:[{value:"361002",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:"361003",label:"东乡区"},{value:"361030",label:"广昌县"}]},{value:"361100",label:"上饶市",children:[{value:"361102",label:"信州区"},{value:"361121",label:"上饶县"},{value:"361103",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:'370000',label:'山东省',children:[{value:"370100",label:"济南市",children:[{value:"370102",label:"历下区"},{value:"370103",label:"市中区"},{value:"370104",label:"槐荫区"},{value:"370105",label:"天桥区"},{value:"370112",label:"历城区"},{value:"370113",label:"长清区"},{value:"370124",label:"平阴县"},{value:"370125",label:"济阳县"},{value:"370126",label:"商河县"},{value:"370114",label:"章丘区"},{value:"370171",label:"济南高新技术产业开发区"}]},{value:"370200",label:"青岛市",children:[{value:"370202",label:"市南区"},{value:"370203",label:"市北区"},{value:"370211",label:"黄岛区"},{value:"370212",label:"崂山区"},{value:"370213",label:"李沧区"},{value:"370214",label:"城阳区"},{value:"370281",label:"胶州市"},{value:"370215",label:"即墨区"},{value:"370283",label:"平度市"},{value:"370285",label:"莱西市"},{value:"370271",label:"青岛高新技术产业开发区"}]},{value:"370300",label:"淄博市",children:[{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:"370400",label:"枣庄市",children:[{value:"370402",label:"市中区"},{value:"370403",label:"薛城区"},{value:"370404",label:"峄城区"},{value:"370405",label:"台儿庄区"},{value:"370406",label:"山亭区"},{value:"370481",label:"滕州市"}]},{value:"370500",label:"东营市",children:[{value:"370502",label:"东营区"},{value:"370503",label:"河口区"},{value:"370521",label:"垦利县"},{value:"370522",label:"利津县"},{value:"370523",label:"广饶县"},{value:"370589",label:"西城区"},{value:"370571",label:"东营经济技术开发区"},{value:"370572",label:"东营港经济开发区"}]},{value:"370600",label:"烟台市",children:[{value:"370602",label:"芝罘区"},{value:"370611",label:"福山区"},{value:"370612",label:"牟平区"},{value:"370613",label:"莱山区"},{value:"370634",label:"长岛县"},{value:"370681",label:"龙口市"},{value:"370682",label:"莱阳市"},{value:"370683",label:"莱州市"},{value:"370684",label:"蓬莱市"},{value:"370685",label:"招远市"},{value:"370686",label:"栖霞市"},{value:"370687",label:"海阳市"},{value:"370671",label:"烟台高新技术产业开发区"},{value:"370672",label:"烟台经济技术开发区"}]},{value:"370700",label:"潍坊市",children:[{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:"370800",label:"济宁市",children:[{value:"370811",label:"任城区"},{value:"370826",label:"微山县"},{value:"370827",label:"鱼台县"},{value:"370828",label:"金乡县"},{value:"370829",label:"嘉祥县"},{value:"370830",label:"汶上县"},{value:"370831",label:"泗水县"},{value:"370832",label:"梁山县"},{value:"370881",label:"曲阜市"},{value:"370812",label:"兖州区"},{value:"370883",label:"邹城市"},{value:"370871",label:"济宁高新技术产业开发区"}]},{value:"370900",label:"泰安市",children:[{value:"370902",label:"泰山区"},{value:"370903",label:"岱岳区"},{value:"370921",label:"宁阳县"},{value:"370923",label:"东平县"},{value:"370982",label:"新泰市"},{value:"370983",label:"肥城市"}]},{value:"371000",label:"威海市",children:[{value:"371002",label:"环翠区"},{value:"371003",label:"文登区"},{value:"371082",label:"荣成市"},{value:"371083",label:"乳山市"},{value:"371071",label:"威海火炬高技术产业开发区"},{value:"371072",label:"威海经济技术开发区"},{value:"371073",label:"威海临港经济技术开发区"}]},{value:"371100",label:"日照市",children:[{value:"371102",label:"东港区"},{value:"371103",label:"岚山区"},{value:"371121",label:"五莲县"},{value:"371122",label:"莒县"},{value:"371171",label:"日照经济技术开发区"},{value:"371172",label:"日照国际海洋城"}]},{value:"371200",label:"莱芜市",children:[{value:"371202",label:"莱城区"},{value:"371203",label:"钢城区"}]},{value:"371300",label:"临沂市",children:[{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:"371373",label:"临沂临港经济开发区"},{value:"371372",label:"临沂经济技术开发区"}]},{value:"371400",label:"德州市",children:[{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:"371481",label:"乐陵市"},{value:"371482",label:"禹城市"},{value:"371471",label:"德州经济技术开发区"},{value:"371472",label:"德州运河经济开发区"}]},{value:"371500",label:"聊城市",children:[{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:"371600",label:"滨州市",children:[{value:"371602",label:"滨城区"},{value:"371621",label:"惠民县"},{value:"371622",label:"阳信县"},{value:"371623",label:"无棣县"},{value:"371603",label:"沾化区"},{value:"371625",label:"博兴县"},{value:"371626",label:"邹平县"}]},{value:"371700",label:"菏泽市",children:[{value:"371702",label:"牡丹区"},{value:"371721",label:"曹县"},{value:"371722",label:"单县"},{value:"371723",label:"成武县"},{value:"371724",label:"巨野县"},{value:"371725",label:"郓城县"},{value:"371726",label:"鄄城县"},{value:"371727",label:"定陶区"},{value:"371728",label:"东明县"},{value:"371771",label:"菏泽经济技术开发区"},{value:"371772",label:"菏泽高新技术开发区"}]}]},{value:'410000',label:'河南省',children:[{value:"410100",label:"郑州市",children:[{value:"410102",label:"中原区"},{value:"410103",label:"二七区"},{value:"410104",label:"管城回族区"},{value:"410105",label:"金水区"},{value:"410106",label:"上街区"},{value:"410108",label:"惠济区"},{value:"410122",label:"中牟县"},{value:"410181",label:"巩义市"},{value:"410182",label:"荥阳市"},{value:"410183",label:"新密市"},{value:"410184",label:"新郑市"},{value:"410185",label:"登封市"},{value:"410171",label:"郑州经济技术开发区"},{value:"410172",label:"郑州高新技术产业开发区"},{value:"410173",label:"郑州航空港经济综合实验区"}]},{value:"410200",label:"开封市",children:[{value:"410202",label:"龙亭区"},{value:"410203",label:"顺河回族区"},{value:"410204",label:"鼓楼区"},{value:"410205",label:"禹王台区"},{value:"410211",label:"金明区"},{value:"410221",label:"杞县"},{value:"410222",label:"通许县"},{value:"410223",label:"尉氏县"},{value:"410225",label:"兰考县"},{value:"410212",label:"祥符区"}]},{value:"410300",label:"洛阳市",children:[{value:"410302",label:"老城区"},{value:"410303",label:"西工区"},{value:"410304",label:"廛河回族区"},{value:"410305",label:"涧西区"},{value:"410306",label:"吉利区"},{value:"410307",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:"410381",label:"偃师市"},{value:"410371",label:"洛阳高新技术产业开发区"},{value:"471005",label:"其它区"}]},{value:"410400",label:"平顶山市",children:[{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:"410481",label:"舞钢市"},{value:"410482",label:"汝州市"},{value:"410471",label:"平顶山高新技术产业开发区"},{value:"410472",label:"平顶山市新城区"}]},{value:"410500",label:"安阳市",children:[{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:"410581",label:"林州市"},{value:"410571",label:"安阳高新技术产业开发区"}]},{value:"410600",label:"鹤壁市",children:[{value:"410602",label:"鹤山区"},{value:"410603",label:"山城区"},{value:"410611",label:"淇滨区"},{value:"410621",label:"浚县"},{value:"410622",label:"淇县"},{value:"410671",label:"鹤壁经济技术开发区"}]},{value:"410700",label:"新乡市",children:[{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:"410781",label:"卫辉市"},{value:"410782",label:"辉县市"},{value:"410771",label:"新乡高新技术产业开发区"},{value:"410773",label:"新乡市平原城乡一体化示范区"},{value:"410772",label:"新乡经济技术开发区"}]},{value:"410800",label:"焦作市",children:[{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:"410882",label:"沁阳市"},{value:"410883",label:"孟州市"},{value:"410871",label:"焦作城乡一体化示范区"}]},{value:"410900",label:"濮阳市",children:[{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:"411000",label:"许昌市",children:[{value:"411002",label:"魏都区"},{value:"411003",label:"建安区"},{value:"411024",label:"鄢陵县"},{value:"411025",label:"襄城县"},{value:"411081",label:"禹州市"},{value:"411082",label:"长葛市"},{value:"411071",label:"许昌经济技术开发区"}]},{value:"411100",label:"漯河市",children:[{value:"411102",label:"源汇区"},{value:"411103",label:"郾城区"},{value:"411104",label:"召陵区"},{value:"411121",label:"舞阳县"},{value:"411122",label:"临颍县"},{value:"411171",label:"漯河经济技术开发区"}]},{value:"411200",label:"三门峡市",children:[{value:"411202",label:"湖滨区"},{value:"411221",label:"渑池县"},{value:"411222",label:"陕县"},{value:"411224",label:"卢氏县"},{value:"411281",label:"义马市"},{value:"411282",label:"灵宝市"},{value:"411203",label:"陕州区"},{value:"411271",label:"河南三门峡经济开发区"}]},{value:"411300",label:"南阳市",children:[{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:"411381",label:"邓州市"},{value:"411371",label:"南阳高新技术产业开发区"},{value:"411372",label:"南阳市城乡一体化示范区"}]},{value:"411400",label:"商丘市",children:[{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:"411481",label:"永城市"},{value:"411471",label:"豫东综合物流产业聚集区"},{value:"411472",label:"河南商丘经济开发"}]},{value:"411500",label:"信阳市",children:[{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:"411600",label:"周口市",children:[{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:"411681",label:"项城市"},{value:"411671",label:"河南周口经济开发区"}]},{value:"411700",label:"驻马店市",children:[{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:"411628",label:"遂平县"},{value:"411729",label:"新蔡县"},{value:"411771",label:"河南驻马店经济开发区"}]}]},{value:'420000',label:'湖北省',children:[{value:"420100",label:"武汉市",children:[{value:"420101",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:"420200",label:"黄石市",children:[{value:"420201",label:"市辖区"},{value:"420202",label:"黄石港区"},{value:"420203",label:"西塞山区"},{value:"420204",label:"下陆区"},{value:"420205",label:"铁山区"},{value:"420222",label:"阳新县"},{value:"420281",label:"大冶市"}]},{value:"420300",label:"十堰市",children:[{value:"420301",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:"420500",label:"宜昌市",children:[{value:"420501",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:"420600",label:"襄阳市",children:[{value:"420601",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:"420700",label:"鄂州市",children:[{value:"420701",label:"市辖区"},{value:"420702",label:"梁子湖区"},{value:"420703",label:"华容区"},{value:"420704",label:"鄂城区"}]},{value:"420800",label:"荆门市",children:[{value:"420801",label:"市辖区"},{value:"420802",label:"东宝区"},{value:"420804",label:"掇刀区"},{value:"420821",label:"京山县"},{value:"420822",label:"沙洋县"},{value:"420881",label:"钟祥市"}]},{value:"420900",label:"孝感市",children:[{value:"420901",label:"市辖区"},{value:"420902",label:"孝南区"},{value:"420921",label:"孝昌县"},{value:"420922",label:"大悟县"},{value:"420923",label:"云梦县"},{value:"420981",label:"应城市"},{value:"420982",label:"安陆市"},{value:"420984",label:"汉川市"}]},{value:"421000",label:"荆州市",children:[{value:"421001",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:"421100",label:"黄冈市",children:[{value:"421101",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:"421200",label:"咸宁市",children:[{value:"421201",label:"市辖区"},{value:"421202",label:"咸安区"},{value:"421221",label:"嘉鱼县"},{value:"421222",label:"通城县"},{value:"421223",label:"崇阳县"},{value:"421224",label:"通山县"},{value:"421281",label:"赤壁市"}]},{value:"421300",label:"随州市",children:[{value:"421301",label:"市辖区"},{value:"421303",label:"曾都区"},{value:"421321",label:"随县"},{value:"421381",label:"广水市"}]},{value:"422800",label:"恩施土家族苗族自治州",children:[{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:"429000",label:"省直辖县级行政区划",children:[{value:"429004",label:"仙桃市"},{value:"429005",label:"潜江市"},{value:"429006",label:"天门市"},{value:"429021",label:"神农架林区"}]}]},{value:'430000',label:'湖南省',children:[{value:"430100",label:"长沙市",children:[{value:"430101",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:"430200",label:"株洲市",children:[{value:"430201",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:"430300",label:"湘潭市",children:[{value:"430301",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:"430400",label:"衡阳市",children:[{value:"430401",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:"430500",label:"邵阳市",children:[{value:"430501",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:"430600",label:"岳阳市",children:[{value:"430601",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:"430700",label:"常德市",children:[{value:"430701",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:"430800",label:"张家界市",children:[{value:"430801",label:"市辖区"},{value:"430802",label:"永定区"},{value:"430811",label:"武陵源区"},{value:"430821",label:"慈利县"},{value:"430822",label:"桑植县"}]},{value:"430900",label:"益阳市",children:[{value:"430901",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:"431000",label:"郴州市",children:[{value:"431001",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:"431100",label:"永州市",children:[{value:"431101",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:"431200",label:"怀化市",children:[{value:"431201",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:"431300",label:"娄底市",children:[{value:"431301",label:"市辖区"},{value:"431302",label:"娄星区"},{value:"431321",label:"双峰县"},{value:"431322",label:"新化县"},{value:"431381",label:"冷水江市"},{value:"431382",label:"涟源市"}]},{value:"433100",label:"湘西土家族苗族自治州",children:[{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:'440000',label:'广东省',children:[{value:"440100",label:"广州市",children:[{value:"440101",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:"440200",label:"韶关市",children:[{value:"440201",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:"440300",label:"深圳市",children:[{value:"440301",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:"440400",label:"珠海市",children:[{value:"440401",label:"市辖区"},{value:"440402",label:"香洲区"},{value:"440403",label:"斗门区"},{value:"440404",label:"金湾区"}]},{value:"440500",label:"汕头市",children:[{value:"440501",label:"市辖区"},{value:"440507",label:"龙湖区"},{value:"440511",label:"金平区"},{value:"440512",label:"濠江区"},{value:"440513",label:"潮阳区"},{value:"440514",label:"潮南区"},{value:"440515",label:"澄海区"},{value:"440523",label:"南澳县"}]},{value:"440600",label:"佛山市",children:[{value:"440601",label:"市辖区"},{value:"440604",label:"禅城区"},{value:"440605",label:"南海区"},{value:"440606",label:"顺德区"},{value:"440607",label:"三水区"},{value:"440608",label:"高明区"}]},{value:"440700",label:"江门市",children:[{value:"440701",label:"市辖区"},{value:"440703",label:"蓬江区"},{value:"440704",label:"江海区"},{value:"440705",label:"新会区"},{value:"440781",label:"台山市"},{value:"440783",label:"开平市"},{value:"440784",label:"鹤山市"},{value:"440785",label:"恩平市"}]},{value:"440800",label:"湛江市",children:[{value:"440801",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:"440900",label:"茂名市",children:[{value:"440901",label:"市辖区"},{value:"440902",label:"茂南区"},{value:"440904",label:"电白区"},{value:"440981",label:"高州市"},{value:"440982",label:"化州市"},{value:"440983",label:"信宜市"}]},{value:"441200",label:"肇庆市",children:[{value:"441201",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:"441300",label:"惠州市",children:[{value:"441301",label:"市辖区"},{value:"441302",label:"惠城区"},{value:"441303",label:"惠阳区"},{value:"441322",label:"博罗县"},{value:"441323",label:"惠东县"},{value:"441324",label:"龙门县"}]},{value:"441400",label:"梅州市",children:[{value:"441401",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:"441500",label:"汕尾市",children:[{value:"441501",label:"市辖区"},{value:"441502",label:"城区"},{value:"441521",label:"海丰县"},{value:"441523",label:"陆河县"},{value:"441581",label:"陆丰市"}]},{value:"441600",label:"河源市",children:[{value:"441601",label:"市辖区"},{value:"441602",label:"源城区"},{value:"441621",label:"紫金县"},{value:"441622",label:"龙川县"},{value:"441623",label:"连平县"},{value:"441624",label:"和平县"},{value:"441625",label:"东源县"}]},{value:"441700",label:"阳江市",children:[{value:"441701",label:"市辖区"},{value:"441702",label:"江城区"},{value:"441704",label:"阳东区"},{value:"441721",label:"阳西县"},{value:"441781",label:"阳春市"}]},{value:"441800",label:"清远市",children:[{value:"441801",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:"445100",label:"潮州市",children:[{value:"445101",label:"市辖区"},{value:"445102",label:"湘桥区"},{value:"445103",label:"潮安区"},{value:"445122",label:"饶平县"}]},{value:"445200",label:"揭阳市",children:[{value:"445201",label:"市辖区"},{value:"445202",label:"榕城区"},{value:"445203",label:"揭东区"},{value:"445222",label:"揭西县"},{value:"445224",label:"惠来县"},{value:"445281",label:"普宁市"}]},{value:"445300",label:"云浮市",children:[{value:"445301",label:"市辖区"},{value:"445302",label:"云城区"},{value:"445303",label:"云安区"},{value:"445321",label:"新兴县"},{value:"445322",label:"郁南县"},{value:"445381",label:"罗定市"}]}]},{value:'450000',label:'广西壮族',children:[{value:"450100",label:"南宁市",children:[{value:"450101",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:"450200",label:"柳州市",children:[{value:"450201",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:"450300",label:"桂林市",children:[{value:"450301",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:"450400",label:"梧州市",children:[{value:"450401",label:"市辖区"},{value:"450403",label:"万秀区"},{value:"450405",label:"长洲区"},{value:"450406",label:"龙圩区"},{value:"450421",label:"苍梧县"},{value:"450422",label:"藤县"},{value:"450423",label:"蒙山县"},{value:"450481",label:"岑溪市"}]},{value:"450500",label:"北海市",children:[{value:"450501",label:"市辖区"},{value:"450502",label:"海城区"},{value:"450503",label:"银海区"},{value:"450512",label:"铁山港区"},{value:"450521",label:"合浦县"}]},{value:"450600",label:"防城港市",children:[{value:"450601",label:"市辖区"},{value:"450602",label:"港口区"},{value:"450603",label:"防城区"},{value:"450621",label:"上思县"},{value:"450681",label:"东兴市"}]},{value:"450700",label:"钦州市",children:[{value:"450701",label:"市辖区"},{value:"450702",label:"钦南区"},{value:"450703",label:"钦北区"},{value:"450721",label:"灵山县"},{value:"450722",label:"浦北县"}]},{value:"450800",label:"贵港市",children:[{value:"450801",label:"市辖区"},{value:"450802",label:"港北区"},{value:"450803",label:"港南区"},{value:"450804",label:"覃塘区"},{value:"450821",label:"平南县"},{value:"450881",label:"桂平市"}]},{value:"450900",label:"玉林市",children:[{value:"450901",label:"市辖区"},{value:"450902",label:"玉州区"},{value:"450903",label:"福绵区"},{value:"450921",label:"容县"},{value:"450922",label:"陆川县"},{value:"450923",label:"博白县"},{value:"450924",label:"兴业县"},{value:"450981",label:"北流市"}]},{value:"451000",label:"百色市",children:[{value:"451001",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:"451100",label:"贺州市",children:[{value:"451101",label:"市辖区"},{value:"451102",label:"八步区"},{value:"451103",label:"平桂区"},{value:"451121",label:"昭平县"},{value:"451122",label:"钟山县"},{value:"451123",label:"富川瑶族自治县"}]},{value:"451200",label:"河池市",children:[{value:"451201",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:"451300",label:"来宾市",children:[{value:"451301",label:"市辖区"},{value:"451302",label:"兴宾区"},{value:"451321",label:"忻城县"},{value:"451322",label:"象州县"},{value:"451323",label:"武宣县"},{value:"451324",label:"金秀瑶族自治县"},{value:"451381",label:"合山市"}]},{value:"451400",label:"崇左市",children:[{value:"451401",label:"市辖区"},{value:"451402",label:"江州区"},{value:"451421",label:"扶绥县"},{value:"451422",label:"宁明县"},{value:"451423",label:"龙州县"},{value:"451424",label:"大新县"},{value:"451425",label:"天等县"},{value:"451481",label:"凭祥市"}]}]},{value:'460000',label:'海南省',children:[{value:"460100",label:"海口市",children:[{value:"460101",label:"市辖区"},{value:"460105",label:"秀英区"},{value:"460106",label:"龙华区"},{value:"460107",label:"琼山区"},{value:"460108",label:"美兰区"}]},{value:"460200",label:"三亚市",children:[{value:"460201",label:"市辖区"},{value:"460202",label:"海棠区"},{value:"460203",label:"吉阳区"},{value:"460204",label:"天涯区"},{value:"460205",label:"崖州区"}]},{value:"460300",label:"三沙市",children:[{value:"460321",label:"西沙群岛"},{value:"460322",label:"南沙群岛"},{value:"460323",label:"中沙群岛的岛礁及其海域"}]},{value:"460400",label:"儋州市"},{value:"469000",label:"省直辖县级行政区划",children:[{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:'500000',label:'重庆',children:[{value:"500100",label:"市辖区",children:[{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:"500200",label:"县",children:[{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:'510000',label:'四川省',children:[{value:"510100",label:"成都市",children:[{value:"510101",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:"510300",label:"自贡市",children:[{value:"510301",label:"市辖区"},{value:"510302",label:"自流井区"},{value:"510303",label:"贡井区"},{value:"510304",label:"大安区"},{value:"510311",label:"沿滩区"},{value:"510321",label:"荣县"},{value:"510322",label:"富顺县"}]},{value:"510400",label:"攀枝花市",children:[{value:"510401",label:"市辖区"},{value:"510402",label:"东区"},{value:"510403",label:"西区"},{value:"510411",label:"仁和区"},{value:"510421",label:"米易县"},{value:"510422",label:"盐边县"}]},{value:"510500",label:"泸州市",children:[{value:"510501",label:"市辖区"},{value:"510502",label:"江阳区"},{value:"510503",label:"纳溪区"},{value:"510504",label:"龙马潭区"},{value:"510521",label:"泸县"},{value:"510522",label:"合江县"},{value:"510524",label:"叙永县"},{value:"510525",label:"古蔺县"}]},{value:"510600",label:"德阳市",children:[{value:"510601",label:"市辖区"},{value:"510603",label:"旌阳区"},{value:"510604",label:"罗江区"},{value:"510623",label:"中江县"},{value:"510681",label:"广汉市"},{value:"510682",label:"什邡市"},{value:"510683",label:"绵竹市"}]},{value:"510700",label:"绵阳市",children:[{value:"510701",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:"510800",label:"广元市",children:[{value:"510801",label:"市辖区"},{value:"510802",label:"利州区"},{value:"510811",label:"昭化区"},{value:"510812",label:"朝天区"},{value:"510821",label:"旺苍县"},{value:"510822",label:"青川县"},{value:"510823",label:"剑阁县"},{value:"510824",label:"苍溪县"}]},{value:"510900",label:"遂宁市",children:[{value:"510901",label:"市辖区"},{value:"510903",label:"船山区"},{value:"510904",label:"安居区"},{value:"510921",label:"蓬溪县"},{value:"510922",label:"射洪县"},{value:"510923",label:"大英县"}]},{value:"511000",label:"内江市",children:[{value:"511001",label:"市辖区"},{value:"511002",label:"市中区"},{value:"511011",label:"东兴区"},{value:"511024",label:"威远县"},{value:"511025",label:"资中县"},{value:"511071",label:"内江经济开发区"},{value:"511083",label:"隆昌市"}]},{value:"511100",label:"乐山市",children:[{value:"511101",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:"511300",label:"南充市",children:[{value:"511301",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:"511400",label:"眉山市",children:[{value:"511401",label:"市辖区"},{value:"511402",label:"东坡区"},{value:"511403",label:"彭山区"},{value:"511421",label:"仁寿县"},{value:"511423",label:"洪雅县"},{value:"511424",label:"丹棱县"},{value:"511425",label:"青神县"}]},{value:"511500",label:"宜宾市",children:[{value:"511501",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:"511600",label:"广安市",children:[{value:"511601",label:"市辖区"},{value:"511602",label:"广安区"},{value:"511603",label:"前锋区"},{value:"511621",label:"岳池县"},{value:"511622",label:"武胜县"},{value:"511623",label:"邻水县"},{value:"511681",label:"华蓥市"}]},{value:"511700",label:"达州市",children:[{value:"511701",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:"511800",label:"雅安市",children:[{value:"511801",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:"511900",label:"巴中市",children:[{value:"511901",label:"市辖区"},{value:"511902",label:"巴州区"},{value:"511903",label:"恩阳区"},{value:"511921",label:"通江县"},{value:"511922",label:"南江县"},{value:"511923",label:"平昌县"},{value:"511971",label:"巴中经济开发区"}]},{value:"512000",label:"资阳市",children:[{value:"512001",label:"市辖区"},{value:"512002",label:"雁江区"},{value:"512021",label:"安岳县"},{value:"512022",label:"乐至县"}]},{value:"513200",label:"阿坝藏族羌族自治州",children:[{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:"513300",label:"甘孜藏族自治州",children:[{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:"513400",label:"凉山彝族自治州",children:[{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:'520000',label:'贵州省',children:[{value:"520100",label:"贵阳市",children:[{value:"520101",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:"520200",label:"六盘水市",children:[{value:"520201",label:"钟山区"},{value:"520203",label:"六枝特区"},{value:"520221",label:"水城县"},{value:"520281",label:"盘州市"}]},{value:"520300",label:"遵义市",children:[{value:"520301",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:"520400",label:"安顺市",children:[{value:"520401",label:"市辖区"},{value:"520402",label:"西秀区"},{value:"520403",label:"平坝区"},{value:"520422",label:"普定县"},{value:"520423",label:"镇宁布依族苗族自治县"},{value:"520424",label:"关岭布依族苗族自治县"},{value:"520425",label:"紫云苗族布依族自治县"}]},{value:"520500",label:"毕节市",children:[{value:"520501",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:"520600",label:"铜仁市",children:[{value:"520601",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:"522300",label:"黔西南布依族苗族自治州",children:[{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:"522600",label:"黔东南苗族侗族自治州",children:[{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:"522700",label:"黔南布依族苗族自治州",children:[{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:'530000',label:'云南省',children:[{value:"530100",label:"昆明市",children:[{value:"530101",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:"530300",label:"曲靖市",children:[{value:"530301",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:"530400",label:"玉溪市",children:[{value:"530401",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:"530500",label:"保山市",children:[{value:"530501",label:"市辖区"},{value:"530502",label:"隆阳区"},{value:"530521",label:"施甸县"},{value:"530523",label:"龙陵县"},{value:"530524",label:"昌宁县"},{value:"530581",label:"腾冲市"}]},{value:"530600",label:"昭通市",children:[{value:"530601",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:"530700",label:"丽江市",children:[{value:"530701",label:"市辖区"},{value:"530702",label:"古城区"},{value:"530721",label:"玉龙纳西族自治县"},{value:"530722",label:"永胜县"},{value:"530723",label:"华坪县"},{value:"530724",label:"宁蒗彝族自治县"}]},{value:"530800",label:"普洱市",children:[{value:"530801",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:"530900",label:"临沧市",children:[{value:"530901",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:"532300",label:"楚雄彝族自治州",children:[{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:"532500",label:"红河哈尼族彝族自治州",children:[{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:"532600",label:"文山壮族苗族自治州",children:[{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:"532800",label:"西双版纳傣族自治州",children:[{value:"532801",label:"景洪市"},{value:"532822",label:"勐海县"},{value:"532823",label:"勐腊县"}]},{value:"532900",label:"大理白族自治州",children:[{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:"533100",label:"德宏傣族景颇族自治州",children:[{value:"533102",label:"瑞丽市"},{value:"533103",label:"芒市"},{value:"533122",label:"梁河县"},{value:"533123",label:"盈江县"},{value:"533124",label:"陇川县"}]},{value:"533300",label:"怒江傈僳族自治州",children:[{value:"533301",label:"泸水市"},{value:"533323",label:"福贡县"},{value:"533324",label:"贡山独龙族怒族自治县"},{value:"533325",label:"兰坪白族普米族自治县"}]},{value:"533400",label:"迪庆藏族自治州",children:[{value:"533401",label:"香格里拉市"},{value:"533422",label:"德钦县"},{value:"533423",label:"维西傈僳族自治县"}]}]},{value:'540000',label:'西藏',children:[{value:"540100",label:"拉萨市",children:[{value:"540101",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:"540200",label:"日喀则市",children:[{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:"540300",label:"昌都市",children:[{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:"540400",label:"林芝市",children:[{value:"540402",label:"巴宜区"},{value:"540421",label:"工布江达县"},{value:"540422",label:"米林县"},{value:"540423",label:"墨脱县"},{value:"540424",label:"波密县"},{value:"540425",label:"察隅县"},{value:"540426",label:"朗县"}]},{value:"540500",label:"山南市",children:[{value:"540501",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:"542400",label:"那曲地区",children:[{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:"542500",label:"阿里地区",children:[{value:"542521",label:"普兰县"},{value:"542522",label:"札达县"},{value:"542523",label:"噶尔县"},{value:"542524",label:"日土县"},{value:"542525",label:"革吉县"},{value:"542526",label:"改则县"},{value:"542527",label:"措勤县"}]}]},{value:'610000',label:'陕西省',children:[{value:"610100",label:"西安市",children:[{value:"610101",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:"610200",label:"铜川市",children:[{value:"610201",label:"市辖区"},{value:"610202",label:"王益区"},{value:"610203",label:"印台区"},{value:"610204",label:"耀州区"},{value:"610222",label:"宜君县"}]},{value:"610300",label:"宝鸡市",children:[{value:"610301",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:"610400",label:"咸阳市",children:[{value:"610401",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:"610500",label:"渭南市",children:[{value:"610501",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:"610600",label:"延安市",children:[{value:"610601",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:"610700",label:"汉中市",children:[{value:"610701",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:"610800",label:"榆林市",children:[{value:"610801",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:"610900",label:"安康市",children:[{value:"610901",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:"611000",label:"商洛市",children:[{value:"611001",label:"市辖区"},{value:"611002",label:"商州区"},{value:"611021",label:"洛南县"},{value:"611022",label:"丹凤县"},{value:"611023",label:"商南县"},{value:"611024",label:"山阳县"},{value:"611025",label:"镇安县"},{value:"611026",label:"柞水县"}]}]},{value:'620000',label:'甘肃省',children:[{value:"620100",label:"兰州市",children:[{value:"620101",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:"620200",label:"嘉峪关市",children:[{value:"620201",label:"市辖区"}]},{value:"620300",label:"金昌市",children:[{value:"620301",label:"市辖区"},{value:"620302",label:"金川区"},{value:"620321",label:"永昌县"}]},{value:"620400",label:"白银市",children:[{value:"620401",label:"市辖区"},{value:"620402",label:"白银区"},{value:"620403",label:"平川区"},{value:"620421",label:"靖远县"},{value:"620422",label:"会宁县"},{value:"620423",label:"景泰县"}]},{value:"620500",label:"天水市",children:[{value:"620501",label:"市辖区"},{value:"620502",label:"秦州区"},{value:"620503",label:"麦积区"},{value:"620521",label:"清水县"},{value:"620522",label:"秦安县"},{value:"620523",label:"甘谷县"},{value:"620524",label:"武山县"},{value:"620525",label:"张家川回族自治县"}]},{value:"620600",label:"武威市",children:[{value:"620601",label:"市辖区"},{value:"620602",label:"凉州区"},{value:"620621",label:"民勤县"},{value:"620622",label:"古浪县"},{value:"620623",label:"天祝藏族自治县"}]},{value:"620700",label:"张掖市",children:[{value:"620701",label:"市辖区"},{value:"620702",label:"甘州区"},{value:"620721",label:"肃南裕固族自治县"},{value:"620722",label:"民乐县"},{value:"620723",label:"临泽县"},{value:"620724",label:"高台县"},{value:"620725",label:"山丹县"}]},{value:"620800",label:"平凉市",children:[{value:"620801",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:"620900",label:"酒泉市",children:[{value:"620901",label:"市辖区"},{value:"620902",label:"肃州区"},{value:"620921",label:"金塔县"},{value:"620922",label:"瓜州县"},{value:"620923",label:"肃北蒙古族自治县"},{value:"620924",label:"阿克塞哈萨克族自治县"},{value:"620981",label:"玉门市"},{value:"620982",label:"敦煌市"}]},{value:"621000",label:"庆阳市",children:[{value:"621001",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:"621100",label:"定西市",children:[{value:"621101",label:"市辖区"},{value:"621102",label:"安定区"},{value:"621121",label:"通渭县"},{value:"621122",label:"陇西县"},{value:"621123",label:"渭源县"},{value:"621124",label:"临洮县"},{value:"621125",label:"漳县"},{value:"621126",label:"岷县"}]},{value:"621200",label:"陇南市",children:[{value:"621201",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:"622900",label:"临夏回族自治州",children:[{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:"623000",label:"甘南藏族自治州",children:[{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:'630000',label:'青海省',children:[{value:"630100",label:"西宁市",children:[{value:"630101",label:"市辖区"},{value:"630102",label:"城东区"},{value:"630103",label:"城中区"},{value:"630104",label:"城西区"},{value:"630105",label:"城北区"},{value:"630121",label:"大通回族土族自治县"},{value:"630122",label:"湟中县"},{value:"630123",label:"湟源县"}]},{value:"630200",label:"海东市",children:[{value:"630202",label:"乐都区"},{value:"630203",label:"平安区"},{value:"630222",label:"民和回族土族自治县"},{value:"630223",label:"互助土族自治县"},{value:"630224",label:"化隆回族自治县"},{value:"630225",label:"循化撒拉族自治县"}]},{value:"632200",label:"海北藏族自治州",children:[{value:"632221",label:"门源回族自治县"},{value:"632222",label:"祁连县"},{value:"632223",label:"海晏县"},{value:"632224",label:"刚察县"}]},{value:"632300",label:"黄南藏族自治州",children:[{value:"632321",label:"同仁县"},{value:"632322",label:"尖扎县"},{value:"632323",label:"泽库县"},{value:"632324",label:"河南蒙古族自治县"}]},{value:"632500",label:"海南藏族自治州",children:[{value:"632521",label:"共和县"},{value:"632522",label:"同德县"},{value:"632523",label:"贵德县"},{value:"632524",label:"兴海县"},{value:"632525",label:"贵南县"}]},{value:"632600",label:"果洛藏族自治州",children:[{value:"632621",label:"玛沁县"},{value:"632622",label:"班玛县"},{value:"632623",label:"甘德县"},{value:"632624",label:"达日县"},{value:"632625",label:"久治县"},{value:"632626",label:"玛多县"}]},{value:"632700",label:"玉树藏族自治州",children:[{value:"632701",label:"玉树市"},{value:"632722",label:"杂多县"},{value:"632723",label:"称多县"},{value:"632724",label:"治多县"},{value:"632725",label:"囊谦县"},{value:"632726",label:"曲麻莱县"}]},{value:"632800",label:"海西蒙古族藏族自治州",children:[{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:'640000',label:'宁夏',children:[{value:"640100",label:"银川市",children:[{value:"640101",label:"市辖区"},{value:"640104",label:"兴庆区"},{value:"640105",label:"西夏区"},{value:"640106",label:"金凤区"},{value:"640121",label:"永宁县"},{value:"640122",label:"贺兰县"},{value:"640181",label:"灵武市"}]},{value:"640200",label:"石嘴山市",children:[{value:"640201",label:"市辖区"},{value:"640202",label:"大武口区"},{value:"640205",label:"惠农区"},{value:"640221",label:"平罗县"}]},{value:"640300",label:"吴忠市",children:[{value:"640301",label:"市辖区"},{value:"640302",label:"利通区"},{value:"640303",label:"红寺堡区"},{value:"640323",label:"盐池县"},{value:"640324",label:"同心县"},{value:"640381",label:"青铜峡市"}]},{value:"640400",label:"固原市",children:[{value:"640401",label:"市辖区"},{value:"640402",label:"原州区"},{value:"640422",label:"西吉县"},{value:"640423",label:"隆德县"},{value:"640424",label:"泾源县"},{value:"640425",label:"彭阳县"}]},{value:"640500",label:"中卫市",children:[{value:"640501",label:"市辖区"},{value:"640502",label:"沙坡头区"},{value:"640521",label:"中宁县"},{value:"640522",label:"海原县"}]}]},{value:'650000',label:'新疆',children:[{value:"650100",label:"乌鲁木齐市",children:[{value:"650101",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:"650200",label:"克拉玛依市",children:[{value:"650201",label:"市辖区"},{value:"650202",label:"独山子区"},{value:"650203",label:"克拉玛依区"},{value:"650204",label:"白碱滩区"},{value:"650205",label:"乌尔禾区"}]},{value:"650400",label:"吐鲁番市",children:[{value:"650402",label:"高昌区"},{value:"650421",label:"鄯善县"},{value:"650422",label:"托克逊县"}]},{value:"650500",label:"哈密市",children:[{value:"650502",label:"伊州区"},{value:"650521",label:"巴里坤哈萨克自治县"},{value:"650522",label:"伊吾县"}]},{value:"652300",label:"昌吉回族自治州",children:[{value:"652301",label:"昌吉市"},{value:"652302",label:"阜康市"},{value:"652323",label:"呼图壁县"},{value:"652324",label:"玛纳斯县"},{value:"652325",label:"奇台县"},{value:"652327",label:"吉木萨尔县"},{value:"652328",label:"木垒哈萨克自治县"}]},{value:"652700",label:"博尔塔拉蒙古自治州",children:[{value:"652701",label:"博乐市"},{value:"652702",label:"阿拉山口市"},{value:"652722",label:"精河县"},{value:"652723",label:"温泉县"}]},{value:"652800",label:"巴音郭楞蒙古自治州",children:[{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:"652900",label:"阿克苏地区",children:[{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:"653000",label:"克孜勒苏柯尔克孜自治州",children:[{value:"653001",label:"阿图什市"},{value:"653022",label:"阿克陶县"},{value:"653023",label:"阿合奇县"},{value:"653024",label:"乌恰县"}]},{value:"653100",label:"喀什地区",children:[{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:"653200",label:"和田地区",children:[{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:"654000",label:"伊犁哈萨克自治州",children:[{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:"654200",label:"塔城地区",children:[{value:"654201",label:"塔城市"},{value:"654202",label:"乌苏市"},{value:"654221",label:"额敏县"},{value:"654223",label:"沙湾县"},{value:"654224",label:"托里县"},{value:"654225",label:"裕民县"},{value:"654226",label:"和布克赛尔蒙古自治县"}]},{value:"654300",label:"阿勒泰地区",children:[{value:"654301",label:"阿勒泰市"},{value:"654321",label:"布尔津县"},{value:"654322",label:"富蕴县"},{value:"654323",label:"福海县"},{value:"654324",label:"哈巴河县"},{value:"654325",label:"青河县"},{value:"654326",label:"吉木乃县"}]},{value:"659000",label:"自治区直辖县级行政区划",children:[{value:"659001",label:"石河子市"},{value:"659002",label:"阿拉尔市"},{value:"659003",label:"图木舒克市"},{value:"659004",label:"五家渠市"},{value:"659006",label:"铁门关市"}]}]},{value:'660000',label:'台湾省',children:[{value:"660100",label:"台北市",children:[{value:"660101",label:"中正区"},{value:"660102",label:"大同区"},{value:"660103",label:"中山区"},{value:"660104",label:"松山区"},{value:"660105",label:"大安区"},{value:"660106",label:"万华区"},{value:"660107",label:"信义区"},{value:"660108",label:"士林区"},{value:"660109",label:"北投区"},{value:"660110",label:"内湖区"},{value:"660111",label:"南港区"},{value:"660112",label:"文山区"}]},{value:"660200",label:"高雄市",children:[{value:"660201",label:"新兴区"},{value:"660202",label:"前金区"},{value:"660203",label:"芩雅区"},{value:"660204",label:"盐埕区"},{value:"660205",label:"鼓山区"},{value:"660206",label:"旗津区"},{value:"660207",label:"前镇区"},{value:"660208",label:"三民区"},{value:"660209",label:"左营区"},{value:"660210",label:"楠梓区"},{value:"660211",label:"小港区"}]},{value:"660300",label:"台南市",children:[{value:"660301",label:"中西区"},{value:"660302",label:"东区"},{value:"660303",label:"南区"},{value:"660304",label:"北区"},{value:"660305",label:"安平区"},{value:"660306",label:"安南区"}]},{value:"660400",label:"台中市",children:[{value:"660401",label:"中区"},{value:"660402",label:"东区"},{value:"660403",label:"南区"},{value:"660404",label:"西区"},{value:"660405",label:"北区"},{value:"660406",label:"北屯区"},{value:"660407",label:"西屯区"},{value:"660408",label:"南屯区"}]},{value:"660500",label:"金门县",children:[{value:"660501",label:"金门县"}]},{value:"660600",label:"南投县",children:[{value:"660601",label:"南投县",}]},{value:"660700",label:"基隆市",children:[{value:"660701",label:"仁爱区"},{value:"660702",label:"信义区"},{value:"660703",label:"中正区"},{value:"660704",label:"中山区"},{value:"660705",label:"安乐区"},{value:"660706",label:"暖暖区"},{value:"660707",label:"七堵区"}]},{value:"660800",label:"新竹市",children:[{value:"660801",label:"东区"},{value:"660802",label:"北区"},{value:"660803",label:"香山区"}]},{value:"660900",label:"嘉义市",children:[{value:"660901",label:"东区"},{value:"660902",label:"西区"}]},{value:"661000",label:"新北市",children:[{value:"661001",label:"新北市"}]},{value:"661100",label:"宜兰县",children:[{value:"661100",label:"宜兰县"}]},{value:"661200",label:"新竹县",children:[{value:"661201",label:"新竹县"}]},{value:"661300",label:"桃园县",children:[{value:"661301",label:"桃园县"}]},{value:"661400",label:"苗栗县",children:[{value:"661401",label:"苗栗县"}]},{value:"661500",label:"彰化县",children:[{value:"661501",label:"彰化县"}]},{value:"661600",label:"嘉义县",children:[{value:"661601",label:"嘉义县"}]},{value:"661700",label:"云林县",children:[{value:"661701",label:"云林县"}]},{value:"661800",label:"屏东县",children:[{value:"661801",label:"屏东县"}]},{value:"661900",label:"台东县",children:[{value:"661901",label:"台东县"}]},{value:"662000",label:"花莲县",children:[{value:"662001",label:"花莲县"}]},{value:"662100",label:"澎湖县",children:[{value:"662101",label:"澎湖县"}]}]},{value:'670000',label:'香港',children:[{value:"670100",label:"香港岛",children:[{value:"670101",label:"中西区"},{value:"670102",label:"湾仔区"},{value:"670103",label:"东区"},{value:"670104",label:"南区"}]},{value:"670200",label:"九龙半岛",children:[{value:"670201",label:"九龙城区"},{value:"670202",label:"油尖旺区"},{value:"670203",label:"深水埗区"},{value:"670204",label:"黄大仙区"},{value:"670205",label:"观塘区"}]},{value:"670300",label:"新界",children:[{value:"670301",label:"北区"},{value:"670302",label:"大埔区"},{value:"670303",label:"沙田区"},{value:"670304",label:"西贡区"},{value:"670305",label:"元朗区"},{value:"670306",label:"屯门区"},{value:"670307",label:"荃湾区"},{value:"670308",label:"葵青区"},{value:"670309",label:"离岛区"}]}]},{value:'680000',label:'澳门',children:[{value:"680100",label:"澳门半岛",children:[{value:"680101",label:"花地玛堂区"},{value:"680102",label:"圣安多尼堂区"},{value:"680103",label:"大堂区"},{value:"680104",label:"望德堂区"},{value:"680105",label:"风顺堂区"}]},{value:"680200",label:"离岛",children:[{value:"680201",label:"嘉模堂区"},{value:"680202",label:"圣方济各堂区"}]}]}];export default cityData
\ No newline at end of file
diff --git a/components/w-picker/date-picker.vue b/components/w-picker/date-picker.vue
new file mode 100644
index 0000000..c0154d5
--- /dev/null
+++ b/components/w-picker/date-picker.vue
@@ -0,0 +1,742 @@
+
+
+
+
+ {{item}}年
+
+
+
+
+ {{item}}年
+
+
+ {{item}}月
+
+
+
+
+ {{item}}年
+
+
+ {{item}}月
+
+
+ {{item}}日
+
+
+
+
+ {{item}}年
+
+
+ {{item}}月
+
+
+ {{item}}日
+
+
+ {{item}}时
+
+
+
+
+ {{item}}年
+
+
+ {{item}}月
+
+
+ {{item}}日
+
+
+ {{item}}时
+
+
+ {{item}}分
+
+
+
+
+ {{item}}年
+
+
+ {{item}}月
+
+
+ {{item}}日
+
+
+ {{item}}时
+
+
+ {{item}}分
+
+
+ {{item}}秒
+
+
+
+
+
+
+
+
diff --git a/components/w-picker/half-picker.vue b/components/w-picker/half-picker.vue
new file mode 100644
index 0000000..0fdfb33
--- /dev/null
+++ b/components/w-picker/half-picker.vue
@@ -0,0 +1,345 @@
+
+
+
+
+ {{item}}年
+
+
+ {{item}}月
+
+
+ {{item}}日
+
+
+ {{item}}
+
+
+
+
+
+
+
+
diff --git a/components/w-picker/linkage-picker.vue b/components/w-picker/linkage-picker.vue
new file mode 100644
index 0000000..290422d
--- /dev/null
+++ b/components/w-picker/linkage-picker.vue
@@ -0,0 +1,274 @@
+
+
+
+
+ {{item[nodeKey]}}
+
+
+
+
+
+
+
+
+
diff --git a/components/w-picker/range-picker.vue b/components/w-picker/range-picker.vue
new file mode 100644
index 0000000..7dd8b5b
--- /dev/null
+++ b/components/w-picker/range-picker.vue
@@ -0,0 +1,344 @@
+
+
+
+
+ {{item}}年
+
+
+ {{item}}月
+
+
+ {{item}}日
+
+
+ -
+
+
+ {{item}}年
+
+
+ {{item}}月
+
+
+ {{item}}日
+
+
+
+
+
+
+
+
diff --git a/components/w-picker/region-picker.vue b/components/w-picker/region-picker.vue
new file mode 100644
index 0000000..34c1f40
--- /dev/null
+++ b/components/w-picker/region-picker.vue
@@ -0,0 +1,183 @@
+
+
+
+
+ {{item.label}}
+
+
+ {{item.label}}
+
+
+ {{item.label}}
+
+
+
+
+
+
+
+
+
diff --git a/components/w-picker/selector-picker.vue b/components/w-picker/selector-picker.vue
new file mode 100644
index 0000000..6ce2ced
--- /dev/null
+++ b/components/w-picker/selector-picker.vue
@@ -0,0 +1,129 @@
+
+
+
+
+ {{item[nodeKey]}}
+
+
+
+
+
+
+
+
diff --git a/components/w-picker/shortterm-picker.vue b/components/w-picker/shortterm-picker.vue
new file mode 100644
index 0000000..d133cf4
--- /dev/null
+++ b/components/w-picker/shortterm-picker.vue
@@ -0,0 +1,250 @@
+
+
+
+
+ {{item.label}}
+
+
+ {{item.label}}时
+
+
+ {{item.label}}分
+
+
+
+
+
+
+
+
diff --git a/components/w-picker/time-picker.vue b/components/w-picker/time-picker.vue
new file mode 100644
index 0000000..b00b0ab
--- /dev/null
+++ b/components/w-picker/time-picker.vue
@@ -0,0 +1,218 @@
+
+
+
+
+ {{item}}时
+
+
+ {{item}}分
+
+
+ {{item}}秒
+
+
+
+
+
+
+
+
+
diff --git a/components/w-picker/w-picker.css b/components/w-picker/w-picker.css
new file mode 100644
index 0000000..fb42e78
--- /dev/null
+++ b/components/w-picker/w-picker.css
@@ -0,0 +1,26 @@
+.w-picker-flex2{
+ flex:2;
+}
+.w-picker-flex1{
+ flex:1;
+}
+.w-picker-view {
+ width: 100%;
+ height: 476upx;
+ overflow: hidden;
+ background-color: rgba(255, 255, 255, 1);
+ z-index: 666;
+}
+.d-picker-view{
+ height: 100%;
+}
+
+.w-picker-item {
+ text-align: center;
+ width: 100%;
+ height: 88upx;
+ line-height: 88upx;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ font-size: 30upx;
+}
\ No newline at end of file
diff --git a/components/w-picker/w-picker.vue b/components/w-picker/w-picker.vue
new file mode 100644
index 0000000..d8f7d76
--- /dev/null
+++ b/components/w-picker/w-picker.vue
@@ -0,0 +1,340 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/zhouWei-navBar/index.vue b/components/zhouWei-navBar/index.vue
new file mode 100644
index 0000000..e6ff651
--- /dev/null
+++ b/components/zhouWei-navBar/index.vue
@@ -0,0 +1,669 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/zhouWei-navBar/zhouWei-navBar.md b/components/zhouWei-navBar/zhouWei-navBar.md
new file mode 100644
index 0000000..39779c4
--- /dev/null
+++ b/components/zhouWei-navBar/zhouWei-navBar.md
@@ -0,0 +1,152 @@
+# zhouWei-navBar 适用于 uni-app 项目的头部导航组件,支持V3编译、nvue编译
+
+导航栏组件,主要用于头部导航,组件名:zhouWei-navBar
+
+本组件目前兼容微信小程序、H5、5+APP。其他平台没试过
+
+本组件支持模式:
+1. 普通固定顶部导航
+2. 透明导航
+3. 透明固定顶部导航
+4. 不固定普通导航
+5. 颜色渐变导航
+
+本组件内置特殊功能:
+1. fontColor字体颜色为白色的时候手机状态栏会自动显示白色,否则显示灰色
+2. 页面为第一个页面时左上角自动显示返回主页的图标(具体看组件:zhouWei-navBar/index.vue =>页面script)
+3. nvue页面必须在当前页面引入本组件才可以使用
+
+### QQ交流群(学习干货多多) 607391225
+
+
+### 本组件全局配置(位置:zhouWei-navBar/index.vue =>页面script)
+1. 主页页面的页面路径
+2. 首页页面路径
+
+```
+// 主页页面的页面路径
+// 关联功能:打开的页面只有一个的时候右上角自动显示返回首页按钮,下面这个数组是排除显示返回首页的页面。
+// 主页使用场景:小程序分享出去的页面,用户点击开是分享页面,很多情况下是没有返回首页按钮的
+const mainPagePath = ["pages/navList"];
+//返回首页的地址
+const homePath = "/pages/navList";
+```
+
+### 在main.js引入组件,并注册全局组件
+```
+import zhouWeiNavBar from "@/components/zhouWei-navBar";
+Vue.component("nav-bar", zhouWeiNavBar);
+```
+
+### 或者在页面script中引入组件,并注册组件(nvue页面必须是这样引入)
+```
+import navBar from "@/components/zhouWei-navBar";
+export default {
+ components: {navBar}
+}
+```
+
+### 案例一
+默认特性:左上角有返回箭头,nav-bar导航固定在顶部、标题居中
+```
+我的
+```
+
+### 案例二
+特性:无返回箭头、字体色为白色、标题左对齐、nav-bar导航透明并不固定在顶部、右边插槽有按钮
+```
+
+ 设置
+
+```
+
+### 案例三:颜色渐变导航
+特性:颜色渐变导航
+```
+
+```
+
+### 案例四:颜色渐变导航
+特性:颜色渐变导航
+```
+
+
+bgColorList:[
+ {color:"#f37402",scale:"0%"},
+ {color:"#0f0",scale:"20%"},
+ {color:"#f00",scale:"80%"},
+ {color:"#00f",scale:"100%"}
+]
+```
+
+### 案例五:滑动透明导航
+特性:有返回箭头、nav-bar导航透明并固定在顶部、透明状态字体为白色、页面想下滑动nav-bar导航条逐渐变白色、右边插槽有按钮
+```
+
+ 预览 //透明状态下的按钮
+ 预览 //不状态下的按钮
+
+```
+```
+//设置滚动值方法一:
+data() {
+ return {
+ scrollTop:0
+ }
+},
+onPageScroll(e) {
+ this.scrollTop = e.scrollTop;
+}
+//设置滚动值方法二:
+onPageScroll (e) {
+ this.$refs.navBar.pageScroll(e);
+}
+```
+
+### 案例六:搜索框|地区选择
+特性:无返回箭头、nav-bar导航固定在顶部、地区选择、搜索框
+```
+
+ 深圳市
+
+
+ 搜索目的地/职位等
+
+
+```
+
+### 属性
+| 名称 | 类型 | 默认值 | 描述 |
+| ----------------------------|--------------- | ------------- | ---------------------------------------------------|
+| backState | String | 1000 | 返回上一页面按钮,`1000` 显示返回按钮,`2000` 不显示返回按钮,`3000`自定义返回按钮方法,点击返回箭头后会发送一个`backClick`事件|
+| home | Boolean | true | 返回首页按钮(首页地址在源文件里配置) |
+| bgColor | String,Array | #FFF | 导航背景颜色,值为数组的时候显示渐变颜色,`bgColor="themeBgColor"`的时候会调用全局`class="themeBgColor"`的样式|
+| bgColorAngle | String,Number | 90 | 导航背景颜色渐变角度(`bgColor`为数组生效) |
+| fontColor | String | #000 | 导航字体颜色,(当颜色为白色的时候导航状态栏和图片为白色的)|
+| titleCenter | Boolean | true | 标题`title`居中 |
+| title | String | -- | 标题`title`值 |
+| transparentFixedFontColor | String | #000 | 导航`type`类型为`transparentFixed`时透明状态下的字体颜色 |
+| type | String | fixed | 导航类型,可选:1.`fixed`固定导航 2.`ordinary`不固定导航 3.`transparent`透明不固定导航 4.`transparentFixed`透明固定导航|
+| scrollTop | Number | 0 | 导航`type`类型为`transparentFixed`时页面滚动值(`具体看上面的案例五`)|
+| shadow | Boolean | true | 背景色为纯白色的时候是否显示底边阴影 |
+
+### bgColor数组值为JSON的参数
+| 名称 | 类型 | 默认值 | 描述 |
+| ----------------------------|--------------- | ------------- | ---------------------------------------------------|
+| color | String | -- | 渐变颜色值 |
+| scale | String | -- | 渐变比例(百分比%) |
+
+### 插槽
+| 名称 | 描述 |
+| ----------------------|-------------------------------------------------------------------|
+| left | 左插槽 |
+| default | 中间标题插槽(`type`类型为`transparentFixed`时插槽只会穿透到实色背景下) |
+| right | 右插槽 |
+| transparentFixed | 导航`type`类型为`transparentFixed`时透明状态下中间插槽 |
+| transparentFixedRight | 导航`type`类型为`transparentFixed`时透明状态下右插槽 |
+| transparentFixedRight | 导航`type`类型为`transparentFixed`时透明状态下右插槽 |
+
+### 事件(type类型为transparentFixed时可用)
+| 名称 | 参数 | 描述 |
+| -----------------|------------------ | --------------------------|
+| backClick | 返回上一页按钮方法 | `backState=3000`时生效 |
diff --git a/js_sdk/u-charts/u-charts/component.vue b/js_sdk/u-charts/u-charts/component.vue
new file mode 100644
index 0000000..ec9eaa9
--- /dev/null
+++ b/js_sdk/u-charts/u-charts/component.vue
@@ -0,0 +1,166 @@
+
+
+
+
+
+
+
diff --git a/js_sdk/u-charts/u-charts/u-charts.js b/js_sdk/u-charts/u-charts/u-charts.js
new file mode 100644
index 0000000..06d190b
--- /dev/null
+++ b/js_sdk/u-charts/u-charts/u-charts.js
@@ -0,0 +1,5662 @@
+/*
+ * uCharts v1.9.4.20200331
+ * uni-app平台高性能跨全端图表,支持H5、APP、小程序(微信/支付宝/百度/头条/QQ/360)
+ * Copyright (c) 2019 QIUN秋云 https://www.ucharts.cn All rights reserved.
+ * Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
+ *
+ * uCharts官方网站
+ * https://www.uCharts.cn
+ *
+ * 开源地址:
+ * https://gitee.com/uCharts/uCharts
+ *
+ * uni-app插件市场地址:
+ * http://ext.dcloud.net.cn/plugin?id=271
+ *
+ */
+
+'use strict';
+
+var config = {
+ yAxisWidth: 15,
+ yAxisSplit: 5,
+ xAxisHeight: 15,
+ xAxisLineHeight: 15,
+ legendHeight: 15,
+ yAxisTitleWidth: 15,
+ padding: [10, 10, 10, 10],
+ pixelRatio: 1,
+ rotate: false,
+ columePadding: 3,
+ fontSize: 13,
+ //dataPointShape: ['diamond', 'circle', 'triangle', 'rect'],
+ dataPointShape: ['circle', 'circle', 'circle', 'circle'],
+ colors: ['#1890ff', '#2fc25b', '#facc14', '#f04864', '#8543e0', '#90ed7d'],
+ pieChartLinePadding: 15,
+ pieChartTextPadding: 5,
+ xAxisTextPadding: 3,
+ titleColor: '#333333',
+ titleFontSize: 20,
+ subtitleColor: '#999999',
+ subtitleFontSize: 15,
+ toolTipPadding: 3,
+ toolTipBackground: '#000000',
+ toolTipOpacity: 0.7,
+ toolTipLineHeight: 20,
+ radarLabelTextMargin: 15,
+ gaugeLabelTextMargin: 15
+};
+
+let assign = function (target, ...varArgs) {
+ if (target == null) {
+ throw new TypeError('Cannot convert undefined or null to object');
+ }
+ if (!varArgs || varArgs.length <= 0) {
+ return target;
+ }
+ // 深度合并对象
+ function deepAssign(obj1, obj2) {
+ for (let key in obj2) {
+ obj1[key] = obj1[key] && obj1[key].toString() === "[object Object]" ?
+ deepAssign(obj1[key], obj2[key]) : obj1[key] = obj2[key];
+ }
+ return obj1;
+ }
+
+ varArgs.forEach(val => {
+ target = deepAssign(target, val);
+ });
+ return target;
+};
+
+var util = {
+ toFixed: function toFixed(num, limit) {
+ limit = limit || 2;
+ if (this.isFloat(num)) {
+ num = num.toFixed(limit);
+ }
+ return num;
+ },
+ isFloat: function isFloat(num) {
+ return num % 1 !== 0;
+ },
+ approximatelyEqual: function approximatelyEqual(num1, num2) {
+ return Math.abs(num1 - num2) < 1e-10;
+ },
+ isSameSign: function isSameSign(num1, num2) {
+ return Math.abs(num1) === num1 && Math.abs(num2) === num2 || Math.abs(num1) !== num1 && Math.abs(num2) !== num2;
+ },
+ isSameXCoordinateArea: function isSameXCoordinateArea(p1, p2) {
+ return this.isSameSign(p1.x, p2.x);
+ },
+ isCollision: function isCollision(obj1, obj2) {
+ obj1.end = {};
+ obj1.end.x = obj1.start.x + obj1.width;
+ obj1.end.y = obj1.start.y - obj1.height;
+ obj2.end = {};
+ obj2.end.x = obj2.start.x + obj2.width;
+ obj2.end.y = obj2.start.y - obj2.height;
+ var flag = obj2.start.x > obj1.end.x || obj2.end.x < obj1.start.x || obj2.end.y > obj1.start.y || obj2.start.y < obj1.end.y;
+ return !flag;
+ }
+};
+
+//兼容H5点击事件
+function getH5Offset(e) {
+ e.mp = {
+ changedTouches: []
+ };
+ e.mp.changedTouches.push({
+ x: e.offsetX,
+ y: e.offsetY
+ });
+ return e;
+}
+
+// hex 转 rgba
+function hexToRgb(hexValue, opc) {
+ var rgx = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
+ var hex = hexValue.replace(rgx, function(m, r, g, b) {
+ return r + r + g + g + b + b;
+ });
+ var rgb = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
+ var r = parseInt(rgb[1], 16);
+ var g = parseInt(rgb[2], 16);
+ var b = parseInt(rgb[3], 16);
+ return 'rgba(' + r + ',' + g + ',' + b + ',' + opc + ')';
+}
+
+function findRange(num, type, limit) {
+ if (isNaN(num)) {
+ throw new Error('[uCharts] unvalid series data!');
+ }
+ limit = limit || 10;
+ type = type ? type : 'upper';
+ var multiple = 1;
+ while (limit < 1) {
+ limit *= 10;
+ multiple *= 10;
+ }
+ if (type === 'upper') {
+ num = Math.ceil(num * multiple);
+ } else {
+ num = Math.floor(num * multiple);
+ }
+ while (num % limit !== 0) {
+ if (type === 'upper') {
+ num++;
+ } else {
+ num--;
+ }
+ }
+ return num / multiple;
+}
+
+function calCandleMA(dayArr, nameArr, colorArr, kdata) {
+ let seriesTemp = [];
+ for (let k = 0; k < dayArr.length; k++) {
+ let seriesItem = {
+ data: [],
+ name: nameArr[k],
+ color: colorArr[k]
+ };
+ for (let i = 0, len = kdata.length; i < len; i++) {
+ if (i < dayArr[k]) {
+ seriesItem.data.push(null);
+ continue;
+ }
+ let sum = 0;
+ for (let j = 0; j < dayArr[k]; j++) {
+ sum += kdata[i - j][1];
+ }
+ seriesItem.data.push(+(sum / dayArr[k]).toFixed(3));
+ }
+ seriesTemp.push(seriesItem);
+ }
+ return seriesTemp;
+}
+
+function calValidDistance(self,distance, chartData, config, opts) {
+ var dataChartAreaWidth = opts.width - opts.area[1] - opts.area[3];
+ var dataChartWidth = chartData.eachSpacing * (opts.chartData.xAxisData.xAxisPoints.length-1);
+ var validDistance = distance;
+ if (distance >= 0) {
+ validDistance = 0;
+ self.event.trigger('scrollLeft');
+ } else if (Math.abs(distance) >= dataChartWidth - dataChartAreaWidth) {
+ validDistance = dataChartAreaWidth - dataChartWidth;
+ self.event.trigger('scrollRight');
+ }
+ return validDistance;
+}
+
+function isInAngleRange(angle, startAngle, endAngle) {
+ function adjust(angle) {
+ while (angle < 0) {
+ angle += 2 * Math.PI;
+ }
+ while (angle > 2 * Math.PI) {
+ angle -= 2 * Math.PI;
+ }
+ return angle;
+ }
+ angle = adjust(angle);
+ startAngle = adjust(startAngle);
+ endAngle = adjust(endAngle);
+ if (startAngle > endAngle) {
+ endAngle += 2 * Math.PI;
+ if (angle < startAngle) {
+ angle += 2 * Math.PI;
+ }
+ }
+ return angle >= startAngle && angle <= endAngle;
+}
+
+function calRotateTranslate(x, y, h) {
+ var xv = x;
+ var yv = h - y;
+ var transX = xv + (h - yv - xv) / Math.sqrt(2);
+ transX *= -1;
+ var transY = (h - yv) * (Math.sqrt(2) - 1) - (h - yv - xv) / Math.sqrt(2);
+ return {
+ transX: transX,
+ transY: transY
+ };
+}
+
+function createCurveControlPoints(points, i) {
+
+ function isNotMiddlePoint(points, i) {
+ if (points[i - 1] && points[i + 1]) {
+ return points[i].y >= Math.max(points[i - 1].y, points[i + 1].y) || points[i].y <= Math.min(points[i - 1].y,points[i + 1].y);
+ } else {
+ return false;
+ }
+ }
+ function isNotMiddlePointX(points, i) {
+ if (points[i - 1] && points[i + 1]) {
+ return points[i].x >= Math.max(points[i - 1].x, points[i + 1].x) || points[i].x <= Math.min(points[i - 1].x,points[i + 1].x);
+ } else {
+ return false;
+ }
+ }
+ var a = 0.2;
+ var b = 0.2;
+ var pAx = null;
+ var pAy = null;
+ var pBx = null;
+ var pBy = null;
+ if (i < 1) {
+ pAx = points[0].x + (points[1].x - points[0].x) * a;
+ pAy = points[0].y + (points[1].y - points[0].y) * a;
+ } else {
+ pAx = points[i].x + (points[i + 1].x - points[i - 1].x) * a;
+ pAy = points[i].y + (points[i + 1].y - points[i - 1].y) * a;
+ }
+
+ if (i > points.length - 3) {
+ var last = points.length - 1;
+ pBx = points[last].x - (points[last].x - points[last - 1].x) * b;
+ pBy = points[last].y - (points[last].y - points[last - 1].y) * b;
+ } else {
+ pBx = points[i + 1].x - (points[i + 2].x - points[i].x) * b;
+ pBy = points[i + 1].y - (points[i + 2].y - points[i].y) * b;
+ }
+ if (isNotMiddlePoint(points, i + 1)) {
+ pBy = points[i + 1].y;
+ }
+ if (isNotMiddlePoint(points, i)) {
+ pAy = points[i].y;
+ }
+ if (isNotMiddlePointX(points, i + 1)) {
+ pBx = points[i + 1].x;
+ }
+ if (isNotMiddlePointX(points, i)) {
+ pAx = points[i].x;
+ }
+ if (pAy >= Math.max(points[i].y, points[i + 1].y) || pAy <= Math.min(points[i].y, points[i + 1].y)) {
+ pAy = points[i].y;
+ }
+ if (pBy >= Math.max(points[i].y, points[i + 1].y) || pBy <= Math.min(points[i].y, points[i + 1].y)) {
+ pBy = points[i + 1].y;
+ }
+ if (pAx >= Math.max(points[i].x, points[i + 1].x) || pAx <= Math.min(points[i].x, points[i + 1].x)) {
+ pAx = points[i].x;
+ }
+ if (pBx >= Math.max(points[i].x, points[i + 1].x) || pBx <= Math.min(points[i].x, points[i + 1].x)) {
+ pBx = points[i + 1].x;
+ }
+ return {
+ ctrA: {
+ x: pAx,
+ y: pAy
+ },
+ ctrB: {
+ x: pBx,
+ y: pBy
+ }
+ };
+}
+
+function convertCoordinateOrigin(x, y, center) {
+ return {
+ x: center.x + x,
+ y: center.y - y
+ };
+}
+
+function avoidCollision(obj, target) {
+ if (target) {
+ // is collision test
+ while (util.isCollision(obj, target)) {
+ if (obj.start.x > 0) {
+ obj.start.y--;
+ } else if (obj.start.x < 0) {
+ obj.start.y++;
+ } else {
+ if (obj.start.y > 0) {
+ obj.start.y++;
+ } else {
+ obj.start.y--;
+ }
+ }
+ }
+ }
+ return obj;
+}
+
+function fillSeries(series, opts, config) {
+ var index = 0;
+ return series.map(function(item) {
+ if (!item.color) {
+ item.color = config.colors[index];
+ index = (index + 1) % config.colors.length;
+ }
+ if (!item.index) {
+ item.index = 0;
+ }
+ if (!item.type) {
+ item.type = opts.type;
+ }
+ if (typeof item.show == "undefined") {
+ item.show = true;
+ }
+ if (!item.type) {
+ item.type = opts.type;
+ }
+ if (!item.pointShape) {
+ item.pointShape = "circle";
+ }
+ if (!item.legendShape) {
+ switch (item.type) {
+ case 'line':
+ item.legendShape = "line";
+ break;
+ case 'column':
+ item.legendShape = "rect";
+ break;
+ case 'area':
+ item.legendShape = "triangle";
+ break;
+ default:
+ item.legendShape = "circle";
+ }
+ }
+ return item;
+ });
+}
+
+function getDataRange(minData, maxData) {
+ var limit = 0;
+ var range = maxData - minData;
+ if (range >= 10000) {
+ limit = 1000;
+ } else if (range >= 1000) {
+ limit = 100;
+ } else if (range >= 100) {
+ limit = 10;
+ } else if (range >= 10) {
+ limit = 5;
+ } else if (range >= 1) {
+ limit = 1;
+ } else if (range >= 0.1) {
+ limit = 0.1;
+ } else if (range >= 0.01) {
+ limit = 0.01;
+ } else if (range >= 0.001) {
+ limit = 0.001;
+ } else if (range >= 0.0001) {
+ limit = 0.0001;
+ } else if (range >= 0.00001) {
+ limit = 0.00001;
+ } else {
+ limit = 0.000001;
+ }
+ return {
+ minRange: findRange(minData, 'lower', limit),
+ maxRange: findRange(maxData, 'upper', limit)
+ };
+}
+
+function measureText(text) {
+ var fontSize = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : config.fontSize;
+ text = String(text);
+ var text = text.split('');
+ var width = 0;
+ for (let i = 0; i < text.length; i++) {
+ let item = text[i];
+ if (/[a-zA-Z]/.test(item)) {
+ width += 7;
+ } else if (/[0-9]/.test(item)) {
+ width += 5.5;
+ } else if (/\./.test(item)) {
+ width += 2.7;
+ } else if (/-/.test(item)) {
+ width += 3.25;
+ } else if (/[\u4e00-\u9fa5]/.test(item)) {
+ width += 10;
+ } else if (/\(|\)/.test(item)) {
+ width += 3.73;
+ } else if (/\s/.test(item)) {
+ width += 2.5;
+ } else if (/%/.test(item)) {
+ width += 8;
+ } else {
+ width += 10;
+ }
+ }
+ return width * fontSize / 10;
+}
+
+function dataCombine(series) {
+ return series.reduce(function(a, b) {
+ return (a.data ? a.data : a).concat(b.data);
+ }, []);
+}
+
+function dataCombineStack(series, len) {
+ var sum = new Array(len);
+ for (var j = 0; j < sum.length; j++) {
+ sum[j] = 0;
+ }
+ for (var i = 0; i < series.length; i++) {
+ for (var j = 0; j < sum.length; j++) {
+ sum[j] += series[i].data[j];
+ }
+ }
+ return series.reduce(function(a, b) {
+ return (a.data ? a.data : a).concat(b.data).concat(sum);
+ }, []);
+}
+
+function getTouches(touches, opts, e) {
+ let x, y;
+ if (touches.clientX) {
+ if (opts.rotate) {
+ y = opts.height - touches.clientX * opts.pixelRatio;
+ x = (touches.pageY - e.currentTarget.offsetTop - (opts.height / opts.pixelRatio / 2) * (opts.pixelRatio - 1)) *
+ opts.pixelRatio;
+ } else {
+ x = touches.clientX * opts.pixelRatio;
+ y = (touches.pageY - e.currentTarget.offsetTop - (opts.height / opts.pixelRatio / 2) * (opts.pixelRatio - 1)) *
+ opts.pixelRatio;
+ }
+ } else {
+ if (opts.rotate) {
+ y = opts.height - touches.x * opts.pixelRatio;
+ x = touches.y * opts.pixelRatio;
+ } else {
+ x = touches.x * opts.pixelRatio;
+ y = touches.y * opts.pixelRatio;
+ }
+ }
+ return {
+ x: x,
+ y: y
+ }
+}
+
+function getSeriesDataItem(series, index) {
+ var data = [];
+ for (let i = 0; i < series.length; i++) {
+ let item = series[i];
+ if (item.data[index] !== null && typeof item.data[index] !== 'undefined' && item.show) {
+ let seriesItem = {};
+ seriesItem.color = item.color;
+ seriesItem.type = item.type;
+ seriesItem.style = item.style;
+ seriesItem.pointShape = item.pointShape;
+ seriesItem.disableLegend = item.disableLegend;
+ seriesItem.name = item.name;
+ seriesItem.show = item.show;
+ seriesItem.data = item.format ? item.format(item.data[index]) : item.data[index];
+ data.push(seriesItem);
+ }
+ }
+ return data;
+}
+
+function getMaxTextListLength(list) {
+ var lengthList = list.map(function(item) {
+ return measureText(item);
+ });
+ return Math.max.apply(null, lengthList);
+}
+
+function getRadarCoordinateSeries(length) {
+ var eachAngle = 2 * Math.PI / length;
+ var CoordinateSeries = [];
+ for (var i = 0; i < length; i++) {
+ CoordinateSeries.push(eachAngle * i);
+ }
+
+ return CoordinateSeries.map(function(item) {
+ return -1 * item + Math.PI / 2;
+ });
+}
+
+function getToolTipData(seriesData, calPoints, index, categories) {
+ var option = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};
+
+ var textList = seriesData.map(function(item) {
+ let titleText=[];
+ if(categories){
+ titleText=categories;
+ }else{
+ titleText=item.data;
+ }
+ return {
+ text: option.format ? option.format(item, titleText[index]) : item.name + ': ' + item.data,
+ color: item.color
+ };
+ });
+ var validCalPoints = [];
+ var offset = {
+ x: 0,
+ y: 0
+ };
+ for (let i = 0; i < calPoints.length; i++) {
+ let points = calPoints[i];
+ if (typeof points[index] !== 'undefined' && points[index] !== null) {
+ validCalPoints.push(points[index]);
+ }
+ }
+ for (let i = 0; i < validCalPoints.length; i++) {
+ let item = validCalPoints[i];
+ offset.x = Math.round(item.x);
+ offset.y += item.y;
+ }
+ offset.y /= validCalPoints.length;
+ return {
+ textList: textList,
+ offset: offset
+ };
+}
+
+function getMixToolTipData(seriesData, calPoints, index, categories) {
+ var option = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};
+ var textList = seriesData.map(function(item) {
+ return {
+ text: option.format ? option.format(item, categories[index]) : item.name + ': ' + item.data,
+ color: item.color,
+ disableLegend: item.disableLegend ? true : false
+ };
+ });
+ textList = textList.filter(function(item) {
+ if (item.disableLegend !== true) {
+ return item;
+ }
+ });
+ var validCalPoints = [];
+ var offset = {
+ x: 0,
+ y: 0
+ };
+ for (let i = 0; i < calPoints.length; i++) {
+ let points = calPoints[i];
+ if (typeof points[index] !== 'undefined' && points[index] !== null) {
+ validCalPoints.push(points[index]);
+ }
+ }
+ for (let i = 0; i < validCalPoints.length; i++) {
+ let item = validCalPoints[i];
+ offset.x = Math.round(item.x);
+ offset.y += item.y;
+ }
+ offset.y /= validCalPoints.length;
+ return {
+ textList: textList,
+ offset: offset
+ };
+}
+
+function getCandleToolTipData(series, seriesData, calPoints, index, categories, extra) {
+ var option = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : {};
+ let upColor = extra.color.upFill;
+ let downColor = extra.color.downFill;
+ //颜色顺序为开盘,收盘,最低,最高
+ let color = [upColor, upColor, downColor, upColor];
+ var textList = [];
+ let text0 = {
+ text: categories[index],
+ color: null
+ };
+ textList.push(text0);
+ seriesData.map(function(item) {
+ if (index == 0) {
+ if(item.data[1] - item.data[0] < 0){
+ color[1] = downColor;
+ }else{
+ color[1] = upColor;
+ }
+ } else {
+ if (item.data[0] < series[index - 1][1]) {
+ color[0] = downColor;
+ }
+ if (item.data[1] < item.data[0]) {
+ color[1] = downColor;
+ }
+ if (item.data[2] > series[index - 1][1]) {
+ color[2] = upColor;
+ }
+ if (item.data[3] < series[index - 1][1]) {
+ color[3] = downColor;
+ }
+ }
+ let text1 = {
+ text: '开盘:' + item.data[0],
+ color: color[0]
+ };
+ let text2 = {
+ text: '收盘:' + item.data[1],
+ color: color[1]
+ };
+ let text3 = {
+ text: '最低:' + item.data[2],
+ color: color[2]
+ };
+ let text4 = {
+ text: '最高:' + item.data[3],
+ color: color[3]
+ };
+ textList.push(text1, text2, text3, text4);
+ });
+ var validCalPoints = [];
+ var offset = {
+ x: 0,
+ y: 0
+ };
+ for (let i = 0; i < calPoints.length; i++) {
+ let points = calPoints[i];
+ if (typeof points[index] !== 'undefined' && points[index] !== null) {
+ validCalPoints.push(points[index]);
+ }
+ }
+ offset.x = Math.round(validCalPoints[0][0].x);
+ return {
+ textList: textList,
+ offset: offset
+ };
+}
+
+function filterSeries(series) {
+ let tempSeries = [];
+ for (let i = 0; i < series.length; i++) {
+ if (series[i].show == true) {
+ tempSeries.push(series[i])
+ }
+ }
+ return tempSeries;
+}
+
+function findCurrentIndex(currentPoints, calPoints, opts, config) {
+ var offset = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 0;
+ var currentIndex = -1;
+ var spacing = opts.chartData.eachSpacing/2;
+ let xAxisPoints=[];
+ if(calPoints.length>0){
+ if(opts.type=='candle'){
+ for(let i=0;i item) {
+ currentIndex = index;
+ }
+ });
+ }
+ }
+ return currentIndex;
+}
+
+function findLegendIndex(currentPoints, legendData, opts) {
+ let currentIndex = -1;
+ if (isInExactLegendArea(currentPoints, legendData.area)) {
+ let points = legendData.points;
+ let index = -1;
+ for (let i = 0, len = points.length; i < len; i++) {
+ let item = points[i];
+ for (let j = 0; j < item.length; j++) {
+ index += 1;
+ let area = item[j]['area'];
+ if (currentPoints.x > area[0] && currentPoints.x < area[2] && currentPoints.y > area[1] && currentPoints.y < area[3]) {
+ currentIndex = index;
+ break;
+ }
+ }
+ }
+ return currentIndex;
+ }
+ return currentIndex;
+}
+
+function isInExactLegendArea(currentPoints, area) {
+ return currentPoints.x > area.start.x && currentPoints.x < area.end.x && currentPoints.y > area.start.y &&
+ currentPoints.y < area.end.y;
+}
+
+function isInExactChartArea(currentPoints, opts, config) {
+ return currentPoints.x <= opts.width - opts.area[1] + 10 && currentPoints.x >= opts.area[3] -10 && currentPoints.y >= opts.area[0] && currentPoints.y <= opts.height - opts.area[2];
+}
+
+function findRadarChartCurrentIndex(currentPoints, radarData, count) {
+ var eachAngleArea = 2 * Math.PI / count;
+ var currentIndex = -1;
+ if (isInExactPieChartArea(currentPoints, radarData.center, radarData.radius)) {
+ var fixAngle = function fixAngle(angle) {
+ if (angle < 0) {
+ angle += 2 * Math.PI;
+ }
+ if (angle > 2 * Math.PI) {
+ angle -= 2 * Math.PI;
+ }
+ return angle;
+ };
+
+ var angle = Math.atan2(radarData.center.y - currentPoints.y, currentPoints.x - radarData.center.x);
+ angle = -1 * angle;
+ if (angle < 0) {
+ angle += 2 * Math.PI;
+ }
+
+ var angleList = radarData.angleList.map(function(item) {
+ item = fixAngle(-1 * item);
+
+ return item;
+ });
+
+ angleList.forEach(function(item, index) {
+ var rangeStart = fixAngle(item - eachAngleArea / 2);
+ var rangeEnd = fixAngle(item + eachAngleArea / 2);
+ if (rangeEnd < rangeStart) {
+ rangeEnd += 2 * Math.PI;
+ }
+ if (angle >= rangeStart && angle <= rangeEnd || angle + 2 * Math.PI >= rangeStart && angle + 2 * Math.PI <=
+ rangeEnd) {
+ currentIndex = index;
+ }
+ });
+ }
+
+ return currentIndex;
+}
+
+function findFunnelChartCurrentIndex(currentPoints, funnelData) {
+ var currentIndex = -1;
+ for (var i = 0, len = funnelData.series.length; i < len; i++) {
+ var item = funnelData.series[i];
+ if (currentPoints.x > item.funnelArea[0] && currentPoints.x < item.funnelArea[2] && currentPoints.y > item.funnelArea[1] && currentPoints.y < item.funnelArea[3]) {
+ currentIndex = i;
+ break;
+ }
+ }
+ return currentIndex;
+}
+
+function findWordChartCurrentIndex(currentPoints, wordData) {
+ var currentIndex = -1;
+ for (var i = 0, len = wordData.length; i < len; i++) {
+ var item = wordData[i];
+ if (currentPoints.x > item.area[0] && currentPoints.x < item.area[2] && currentPoints.y > item.area[1] && currentPoints.y < item.area[3]) {
+ currentIndex = i;
+ break;
+ }
+ }
+ return currentIndex;
+}
+
+function findMapChartCurrentIndex(currentPoints, opts) {
+ var currentIndex = -1;
+ var cData=opts.chartData.mapData;
+ var data=opts.series;
+ var tmp=pointToCoordinate(currentPoints.y, currentPoints.x,cData.bounds,cData.scale,cData.xoffset,cData.yoffset);
+ var poi=[tmp.x, tmp.y];
+ for (var i = 0, len = data.length; i < len; i++) {
+ var item = data[i].geometry.coordinates;
+ if(isPoiWithinPoly(poi,item)){
+ currentIndex = i;
+ break;
+ }
+ }
+ return currentIndex;
+}
+
+function findPieChartCurrentIndex(currentPoints, pieData) {
+ var currentIndex = -1;
+ if (isInExactPieChartArea(currentPoints, pieData.center, pieData.radius)) {
+ var angle = Math.atan2(pieData.center.y - currentPoints.y, currentPoints.x - pieData.center.x);
+ angle = -angle;
+ for (var i = 0, len = pieData.series.length; i < len; i++) {
+ var item = pieData.series[i];
+ if (isInAngleRange(angle, item._start_, item._start_ + item._proportion_ * 2 * Math.PI)) {
+ currentIndex = i;
+ break;
+ }
+ }
+ }
+
+ return currentIndex;
+}
+
+function isInExactPieChartArea(currentPoints, center, radius) {
+ return Math.pow(currentPoints.x - center.x, 2) + Math.pow(currentPoints.y - center.y, 2) <= Math.pow(radius, 2);
+}
+
+function splitPoints(points) {
+ var newPoints = [];
+ var items = [];
+ points.forEach(function(item, index) {
+ if (item !== null) {
+ items.push(item);
+ } else {
+ if (items.length) {
+ newPoints.push(items);
+ }
+ items = [];
+ }
+ });
+ if (items.length) {
+ newPoints.push(items);
+ }
+
+ return newPoints;
+}
+
+function calLegendData(series, opts, config, chartData) {
+ let legendData = {
+ area: {
+ start: {
+ x: 0,
+ y: 0
+ },
+ end: {
+ x: 0,
+ y: 0
+ },
+ width: 0,
+ height: 0,
+ wholeWidth: 0,
+ wholeHeight: 0
+ },
+ points: [],
+ widthArr: [],
+ heightArr: []
+ };
+ if (opts.legend.show === false) {
+ chartData.legendData = legendData;
+ return legendData;
+ }
+
+ let padding = opts.legend.padding;
+ let margin = opts.legend.margin;
+ let fontSize = opts.legend.fontSize;
+ let shapeWidth = 15 * opts.pixelRatio;
+ let shapeRight = 5 * opts.pixelRatio;
+ let lineHeight = Math.max(opts.legend.lineHeight * opts.pixelRatio, fontSize);
+ if (opts.legend.position == 'top' || opts.legend.position == 'bottom') {
+ let legendList = [];
+ let widthCount = 0;
+ let widthCountArr = [];
+ let currentRow = [];
+ for (let i = 0; i < series.length; i++) {
+ let item = series[i];
+ let itemWidth = shapeWidth + shapeRight + measureText(item.name || 'undefined', fontSize) + opts.legend.itemGap;
+ if (widthCount + itemWidth > opts.width - opts.padding[1] - opts.padding[3]) {
+ legendList.push(currentRow);
+ widthCountArr.push(widthCount - opts.legend.itemGap);
+ widthCount = itemWidth;
+ currentRow = [item];
+ } else {
+ widthCount += itemWidth;
+ currentRow.push(item);
+ }
+ }
+ if (currentRow.length) {
+ legendList.push(currentRow);
+ widthCountArr.push(widthCount - opts.legend.itemGap);
+ legendData.widthArr = widthCountArr;
+ let legendWidth = Math.max.apply(null, widthCountArr);
+ switch (opts.legend.float) {
+ case 'left':
+ legendData.area.start.x = opts.padding[3];
+ legendData.area.end.x = opts.padding[3] + 2 * padding;
+ break;
+ case 'right':
+ legendData.area.start.x = opts.width - opts.padding[1] - legendWidth - 2 * padding;
+ legendData.area.end.x = opts.width - opts.padding[1];
+ break;
+ default:
+ legendData.area.start.x = (opts.width - legendWidth) / 2 - padding;
+ legendData.area.end.x = (opts.width + legendWidth) / 2 + padding;
+ }
+ legendData.area.width = legendWidth + 2 * padding;
+ legendData.area.wholeWidth = legendWidth + 2 * padding;
+ legendData.area.height = legendList.length * lineHeight + 2 * padding;
+ legendData.area.wholeHeight = legendList.length * lineHeight + 2 * padding + 2 * margin;
+ legendData.points = legendList;
+ }
+ } else {
+ let len = series.length;
+ let maxHeight = opts.height - opts.padding[0] - opts.padding[2] - 2 * margin - 2 * padding;
+ let maxLength = Math.min(Math.floor(maxHeight / lineHeight), len);
+ legendData.area.height = maxLength * lineHeight + padding * 2;
+ legendData.area.wholeHeight = maxLength * lineHeight + padding * 2;
+ switch (opts.legend.float) {
+ case 'top':
+ legendData.area.start.y = opts.padding[0] + margin;
+ legendData.area.end.y = opts.padding[0] + margin + legendData.area.height;
+ break;
+ case 'bottom':
+ legendData.area.start.y = opts.height - opts.padding[2] - margin - legendData.area.height;
+ legendData.area.end.y = opts.height - opts.padding[2] - margin;
+ break;
+ default:
+ legendData.area.start.y = (opts.height - legendData.area.height) / 2;
+ legendData.area.end.y = (opts.height + legendData.area.height) / 2;
+ }
+ let lineNum = len % maxLength === 0 ? len / maxLength : Math.floor((len / maxLength) + 1);
+ let currentRow = [];
+ for (let i = 0; i < lineNum; i++) {
+ let temp = series.slice(i * maxLength, i * maxLength + maxLength);
+ currentRow.push(temp);
+ }
+
+ legendData.points = currentRow;
+
+ if (currentRow.length) {
+ for (let i = 0; i < currentRow.length; i++) {
+ let item = currentRow[i];
+ let maxWidth = 0;
+ for (let j = 0; j < item.length; j++) {
+ let itemWidth = shapeWidth + shapeRight + measureText(item[j].name || 'undefined', fontSize) + opts.legend.itemGap;
+ if (itemWidth > maxWidth) {
+ maxWidth = itemWidth;
+ }
+ }
+ legendData.widthArr.push(maxWidth);
+ legendData.heightArr.push(item.length * lineHeight + padding * 2);
+ }
+ let legendWidth = 0
+ for (let i = 0; i < legendData.widthArr.length; i++) {
+ legendWidth += legendData.widthArr[i];
+ }
+ legendData.area.width = legendWidth - opts.legend.itemGap + 2 * padding;
+ legendData.area.wholeWidth = legendData.area.width + padding;
+ }
+ }
+
+ switch (opts.legend.position) {
+ case 'top':
+ legendData.area.start.y = opts.padding[0] + margin;
+ legendData.area.end.y = opts.padding[0] + margin + legendData.area.height;
+ break;
+ case 'bottom':
+ legendData.area.start.y = opts.height - opts.padding[2] - legendData.area.height - margin;
+ legendData.area.end.y = opts.height - opts.padding[2] - margin;
+ break;
+ case 'left':
+ legendData.area.start.x = opts.padding[3];
+ legendData.area.end.x = opts.padding[3] + legendData.area.width;
+ break;
+ case 'right':
+ legendData.area.start.x = opts.width - opts.padding[1] - legendData.area.width;
+ legendData.area.end.x = opts.width - opts.padding[1];
+ break;
+ }
+ chartData.legendData = legendData;
+ return legendData;
+}
+
+function calCategoriesData(categories, opts, config, eachSpacing) {
+ var result = {
+ angle: 0,
+ xAxisHeight: config.xAxisHeight
+ };
+ var categoriesTextLenth = categories.map(function(item) {
+ return measureText(item,opts.xAxis.fontSize||config.fontSize);
+ });
+ var maxTextLength = Math.max.apply(this, categoriesTextLenth);
+
+ if (opts.xAxis.rotateLabel == true && maxTextLength + 2 * config.xAxisTextPadding > eachSpacing) {
+ result.angle = 45 * Math.PI / 180;
+ result.xAxisHeight = 2 * config.xAxisTextPadding + maxTextLength * Math.sin(result.angle);
+ }
+ return result;
+}
+
+function getXAxisTextList(series, opts, config) {
+ var index = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : -1;
+ var data = dataCombine(series);
+ var sorted = [];
+ // remove null from data
+ data = data.filter(function(item) {
+ //return item !== null;
+ if (typeof item === 'object' && item !== null) {
+ if (item.constructor.toString().indexOf('Array')>-1) {
+ return item !== null;
+ } else {
+ return item.value !== null;
+ }
+ } else {
+ return item !== null;
+ }
+ });
+ data.map(function(item) {
+ if (typeof item === 'object') {
+ if (item.constructor.toString().indexOf('Array')>-1) {
+ if(opts.type=='candle'){
+ item.map(function(subitem) {
+ sorted.push(subitem);
+ })
+ }else{
+ sorted.push(item[0]);
+ }
+ } else {
+ sorted.push(item.value);
+ }
+ } else {
+ sorted.push(item);
+ }
+ })
+
+ var minData = 0;
+ var maxData = 0;
+ if (sorted.length > 0) {
+ minData = Math.min.apply(this, sorted);
+ maxData = Math.max.apply(this, sorted);
+ }
+ //为了兼容v1.9.0之前的项目
+ if(index>-1){
+ if (typeof opts.xAxis.data[index].min === 'number') {
+ minData = Math.min(opts.xAxis.data[index].min, minData);
+ }
+ if (typeof opts.xAxis.data[index].max === 'number') {
+ maxData = Math.max(opts.xAxis.data[index].max, maxData);
+ }
+ }else{
+ if (typeof opts.xAxis.min === 'number') {
+ minData = Math.min(opts.xAxis.min, minData);
+ }
+ if (typeof opts.xAxis.max === 'number') {
+ maxData = Math.max(opts.xAxis.max, maxData);
+ }
+ }
+
+
+ if (minData === maxData) {
+ var rangeSpan = maxData || 10;
+ maxData += rangeSpan;
+ }
+
+ //var dataRange = getDataRange(minData, maxData);
+ var minRange = minData;
+ var maxRange = maxData;
+
+ var range = [];
+ var eachRange = (maxRange - minRange) / opts.xAxis.splitNumber;
+
+ for (var i = 0; i <= opts.xAxis.splitNumber; i++) {
+ range.push(minRange + eachRange * i);
+ }
+ return range;
+}
+
+function calXAxisData(series, opts, config){
+ var result = {
+ angle: 0,
+ xAxisHeight: config.xAxisHeight
+ };
+
+ result.ranges = getXAxisTextList(series, opts, config);
+ result.rangesFormat = result.ranges.map(function(item){
+ item = opts.xAxis.format? opts.xAxis.format(item):util.toFixed(item, 2);
+ return item;
+ });
+
+ var xAxisScaleValues = result.ranges.map(function (item) {
+ // 如果刻度值是浮点数,则保留两位小数
+ item = util.toFixed(item, 2);
+ // 若有自定义格式则调用自定义的格式化函数
+ item = opts.xAxis.format ? opts.xAxis.format(Number(item)) : item;
+ return item;
+ });
+
+ result = Object.assign(result,getXAxisPoints(xAxisScaleValues, opts, config));
+ // 计算X轴刻度的属性譬如每个刻度的间隔,刻度的起始点\结束点以及总长
+ var eachSpacing = result.eachSpacing;
+
+ var textLength = xAxisScaleValues.map(function (item) {
+ return measureText(item);
+ });
+
+ // get max length of categories text
+ var maxTextLength = Math.max.apply(this, textLength);
+
+ // 如果刻度值文本内容过长,则将其逆时针旋转45°
+ if (maxTextLength + 2 * config.xAxisTextPadding > eachSpacing) {
+ result.angle = 45 * Math.PI / 180;
+ result.xAxisHeight = 2 * config.xAxisTextPadding + maxTextLength * Math.sin(result.angle);
+ }
+
+ if (opts.xAxis.disabled === true) {
+ result.xAxisHeight = 0;
+ }
+
+ return result;
+}
+
+function getRadarDataPoints(angleList, center, radius, series, opts) {
+ var process = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 1;
+
+ var radarOption = opts.extra.radar || {};
+ radarOption.max = radarOption.max || 0;
+ var maxData = Math.max(radarOption.max, Math.max.apply(null, dataCombine(series)));
+
+ var data = [];
+ for (let i = 0; i < series.length; i++) {
+ let each = series[i];
+ let listItem = {};
+ listItem.color = each.color;
+ listItem.legendShape = each.legendShape;
+ listItem.pointShape = each.pointShape;
+ listItem.data = [];
+ each.data.forEach(function(item, index) {
+ let tmp = {};
+ tmp.angle = angleList[index];
+
+ tmp.proportion = item / maxData;
+ tmp.position = convertCoordinateOrigin(radius * tmp.proportion * process * Math.cos(tmp.angle), radius * tmp.proportion *
+ process * Math.sin(tmp.angle), center);
+ listItem.data.push(tmp);
+ });
+
+ data.push(listItem);
+ }
+
+ return data;
+}
+
+function getPieDataPoints(series, radius) {
+ var process = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1;
+
+ var count = 0;
+ var _start_ = 0;
+ for (let i = 0; i < series.length; i++) {
+ let item = series[i];
+ item.data = item.data === null ? 0 : item.data;
+ count += item.data;
+ }
+ for (let i = 0; i < series.length; i++) {
+ let item = series[i];
+ item.data = item.data === null ? 0 : item.data;
+ if (count === 0) {
+ item._proportion_ = 1 / series.length * process;
+ } else {
+ item._proportion_ = item.data / count * process;
+ }
+ item._radius_ = radius;
+ }
+ for (let i = 0; i < series.length; i++) {
+ let item = series[i];
+ item._start_ = _start_;
+ _start_ += 2 * item._proportion_ * Math.PI;
+ }
+
+ return series;
+}
+
+function getFunnelDataPoints(series, radius) {
+ var process = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1;
+ series = series.sort(function(a,b){return parseInt(b.data)-parseInt(a.data);});
+ for (let i = 0; i < series.length; i++) {
+ series[i].radius = series[i].data/series[0].data*radius*process;
+ series[i]._proportion_ = series[i].data/series[0].data;
+ }
+ return series.reverse();
+}
+
+function getRoseDataPoints(series, type, minRadius, radius) {
+ var process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1;
+ var count = 0;
+ var _start_ = 0;
+
+ var dataArr = [];
+ for (let i = 0; i < series.length; i++) {
+ let item = series[i];
+ item.data = item.data === null ? 0 : item.data;
+ count += item.data;
+ dataArr.push(item.data);
+ }
+
+ var minData = Math.min.apply(null, dataArr);
+ var maxData = Math.max.apply(null, dataArr);
+ var radiusLength = radius - minRadius;
+
+ for (let i = 0; i < series.length; i++) {
+ let item = series[i];
+ item.data = item.data === null ? 0 : item.data;
+ if (count === 0 || type == 'area') {
+ item._proportion_ = item.data / count * process;
+ item._rose_proportion_ = 1 / series.length * process;
+ } else {
+ item._proportion_ = item.data / count * process;
+ item._rose_proportion_ = item.data / count * process;
+ }
+ item._radius_ = minRadius + radiusLength * ((item.data - minData) / (maxData - minData));
+ }
+ for (let i = 0; i < series.length; i++) {
+ let item = series[i];
+ item._start_ = _start_;
+ _start_ += 2 * item._rose_proportion_ * Math.PI;
+ }
+
+ return series;
+}
+
+function getArcbarDataPoints(series, arcbarOption) {
+ var process = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1;
+ if (process == 1) {
+ process = 0.999999;
+ }
+ for (let i = 0; i < series.length; i++) {
+ let item = series[i];
+ item.data = item.data === null ? 0 : item.data;
+ let totalAngle;
+ if (arcbarOption.type == 'circle') {
+ totalAngle = 2;
+ } else {
+ if (arcbarOption.endAngle < arcbarOption.startAngle) {
+ totalAngle = 2 + arcbarOption.endAngle - arcbarOption.startAngle;
+ } else{
+ totalAngle = arcbarOption.startAngle - arcbarOption.endAngle;
+ }
+ }
+ item._proportion_ = totalAngle * item.data * process + arcbarOption.startAngle;
+ if (item._proportion_ >= 2) {
+ item._proportion_ = item._proportion_ % 2;
+ }
+ }
+ return series;
+}
+
+function getGaugeAxisPoints(categories, startAngle, endAngle) {
+ let totalAngle = startAngle - endAngle + 1;
+ let tempStartAngle = startAngle;
+ for (let i = 0; i < categories.length; i++) {
+ categories[i].value = categories[i].value === null ? 0 : categories[i].value;
+ categories[i]._startAngle_ = tempStartAngle;
+ categories[i]._endAngle_ = totalAngle * categories[i].value + startAngle;
+ if (categories[i]._endAngle_ >= 2) {
+ categories[i]._endAngle_ = categories[i]._endAngle_ % 2;
+ }
+ tempStartAngle = categories[i]._endAngle_;
+ }
+ return categories;
+}
+
+function getGaugeDataPoints(series, categories, gaugeOption) {
+ let process = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 1;
+ for (let i = 0; i < series.length; i++) {
+ let item = series[i];
+ item.data = item.data === null ? 0 : item.data;
+ if (gaugeOption.pointer.color == 'auto') {
+ for (let i = 0; i < categories.length; i++) {
+ if (item.data <= categories[i].value) {
+ item.color = categories[i].color;
+ break;
+ }
+ }
+ } else {
+ item.color = gaugeOption.pointer.color;
+ }
+ let totalAngle = gaugeOption.startAngle - gaugeOption.endAngle + 1;
+ item._endAngle_ = totalAngle * item.data + gaugeOption.startAngle;
+ item._oldAngle_ = gaugeOption.oldAngle;
+ if (gaugeOption.oldAngle < gaugeOption.endAngle) {
+ item._oldAngle_ += 2;
+ }
+ if (item.data >= gaugeOption.oldData) {
+ item._proportion_ = (item._endAngle_ - item._oldAngle_) * process + gaugeOption.oldAngle;
+ } else {
+ item._proportion_ = item._oldAngle_ - (item._oldAngle_ - item._endAngle_) * process;
+ }
+ if (item._proportion_ >= 2) {
+ item._proportion_ = item._proportion_ % 2;
+ }
+ }
+ return series;
+}
+
+function getPieTextMaxLength(series) {
+ series = getPieDataPoints(series);
+ let maxLength = 0;
+ for (let i = 0; i < series.length; i++) {
+ let item = series[i];
+ let text = item.format ? item.format(+item._proportion_.toFixed(2)) : util.toFixed(item._proportion_ * 100) + '%';
+ maxLength = Math.max(maxLength, measureText(text));
+ }
+
+ return maxLength;
+}
+
+function fixColumeData(points, eachSpacing, columnLen, index, config, opts) {
+ return points.map(function(item) {
+ if (item === null) {
+ return null;
+ }
+ item.width = Math.ceil((eachSpacing - 2 * config.columePadding) / columnLen);
+
+ if (opts.extra.column && opts.extra.column.width && +opts.extra.column.width > 0) {
+ item.width = Math.min(item.width, +opts.extra.column.width);
+ }
+ if (item.width <= 0) {
+ item.width = 1;
+ }
+ item.x += (index + 0.5 - columnLen / 2) * item.width;
+ return item;
+ });
+}
+
+function fixColumeMeterData(points, eachSpacing, columnLen, index, config, opts, border) {
+ return points.map(function(item) {
+ if (item === null) {
+ return null;
+ }
+ item.width = Math.ceil((eachSpacing - 2 * config.columePadding) / 2);
+
+ if (opts.extra.column && opts.extra.column.width && +opts.extra.column.width > 0) {
+ item.width = Math.min(item.width, +opts.extra.column.width);
+ }
+
+ if (index > 0) {
+ item.width -= 2 * border;
+ }
+ return item;
+ });
+}
+
+function fixColumeStackData(points, eachSpacing, columnLen, index, config, opts, series) {
+
+ return points.map(function(item, indexn) {
+
+ if (item === null) {
+ return null;
+ }
+ item.width = Math.ceil((eachSpacing - 2 * config.columePadding) / 2);
+
+ if (opts.extra.column && opts.extra.column.width && +opts.extra.column.width > 0) {
+ item.width = Math.min(item.width, +opts.extra.column.width);
+ }
+ return item;
+ });
+}
+
+function getXAxisPoints(categories, opts, config) {
+ var spacingValid = opts.width - opts.area[1] - opts.area[3];
+ var dataCount = opts.enableScroll ? Math.min(opts.xAxis.itemCount, categories.length) : categories.length;
+ if((opts.type=='line' || opts.type=='area') && dataCount>1 && opts.xAxis.boundaryGap=='justify'){
+ dataCount -=1;
+ }
+ var eachSpacing = spacingValid / dataCount;
+
+ var xAxisPoints = [];
+ var startX = opts.area[3];
+ var endX = opts.width - opts.area[1];
+ categories.forEach(function(item, index) {
+ xAxisPoints.push(startX + index * eachSpacing);
+ });
+ if(opts.xAxis.boundaryGap !=='justify'){
+ if (opts.enableScroll === true) {
+ xAxisPoints.push(startX + categories.length * eachSpacing);
+ } else {
+ xAxisPoints.push(endX);
+ }
+ }
+ return {
+ xAxisPoints: xAxisPoints,
+ startX: startX,
+ endX: endX,
+ eachSpacing: eachSpacing
+ };
+}
+
+function getCandleDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config) {
+ var process = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : 1;
+ var points = [];
+ var validHeight = opts.height - opts.area[0] - opts.area[2];
+ data.forEach(function(item, index) {
+ if (item === null) {
+ points.push(null);
+ } else {
+ var cPoints = [];
+ item.forEach(function(items, indexs) {
+ var point = {};
+ point.x = xAxisPoints[index] + Math.round(eachSpacing / 2);
+ var value = items.value || items;
+ var height = validHeight * (value - minRange) / (maxRange - minRange);
+ height *= process;
+ point.y = opts.height - Math.round(height) - opts.area[2];
+ cPoints.push(point);
+ });
+ points.push(cPoints);
+ }
+ });
+
+ return points;
+}
+
+function getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config) {
+ var process = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : 1;
+ var boundaryGap='center';
+ if (opts.type == 'line'||opts.type == 'area'){
+ boundaryGap=opts.xAxis.boundaryGap;
+ }
+ var points = [];
+ var validHeight = opts.height - opts.area[0] - opts.area[2];
+ var validWidth = opts.width - opts.area[1] - opts.area[3];
+ data.forEach(function(item, index) {
+ if (item === null) {
+ points.push(null);
+ } else {
+ var point = {};
+ point.color = item.color;
+ point.x = xAxisPoints[index];
+ var value = item;
+ if (typeof item === 'object' && item !== null) {
+ if (item.constructor.toString().indexOf('Array')>-1) {
+ let xranges,xminRange,xmaxRange;
+ xranges = [].concat(opts.chartData.xAxisData.ranges);
+ xminRange = xranges.shift();
+ xmaxRange = xranges.pop();
+ value = item[1];
+ point.x = opts.area[3]+ validWidth * (item[0] - xminRange) / (xmaxRange - xminRange);
+ } else {
+ value = item.value;
+ }
+ }
+ if(boundaryGap=='center'){
+ point.x += Math.round(eachSpacing / 2);
+ }
+ var height = validHeight * (value - minRange) / (maxRange - minRange);
+ height *= process;
+ point.y = opts.height - Math.round(height) - opts.area[2];
+ points.push(point);
+ }
+ });
+
+ return points;
+}
+
+function getStackDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, seriesIndex, stackSeries) {
+ var process = arguments.length > 9 && arguments[9] !== undefined ? arguments[9] : 1;
+ var points = [];
+ var validHeight = opts.height - opts.area[0] - opts.area[2];
+
+ data.forEach(function(item, index) {
+ if (item === null) {
+ points.push(null);
+ } else {
+ var point = {};
+ point.color = item.color;
+ point.x = xAxisPoints[index] + Math.round(eachSpacing / 2);
+
+ if (seriesIndex > 0) {
+ var value = 0;
+ for (let i = 0; i <= seriesIndex; i++) {
+ value += stackSeries[i].data[index];
+ }
+ var value0 = value - item;
+ var height = validHeight * (value - minRange) / (maxRange - minRange);
+ var height0 = validHeight * (value0 - minRange) / (maxRange - minRange);
+ } else {
+ var value = item;
+ var height = validHeight * (value - minRange) / (maxRange - minRange);
+ var height0 = 0;
+ }
+ var heightc = height0;
+ height *= process;
+ heightc *= process;
+ point.y = opts.height - Math.round(height) - opts.area[2];
+ point.y0 = opts.height - Math.round(heightc) - opts.area[2];
+ points.push(point);
+ }
+ });
+
+ return points;
+}
+
+function getYAxisTextList(series, opts, config, stack) {
+ var index = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : -1;
+ var data;
+ if (stack == 'stack') {
+ data = dataCombineStack(series, opts.categories.length);
+ } else {
+ data = dataCombine(series);
+ }
+ var sorted = [];
+ // remove null from data
+ data = data.filter(function(item) {
+ //return item !== null;
+ if (typeof item === 'object' && item !== null) {
+ if (item.constructor.toString().indexOf('Array')>-1) {
+ return item !== null;
+ } else {
+ return item.value !== null;
+ }
+ } else {
+ return item !== null;
+ }
+ });
+ data.map(function(item) {
+ if (typeof item === 'object') {
+ if (item.constructor.toString().indexOf('Array')>-1) {
+ if(opts.type=='candle'){
+ item.map(function(subitem) {
+ sorted.push(subitem);
+ })
+ }else{
+ sorted.push(item[1]);
+ }
+ } else {
+ sorted.push(item.value);
+ }
+ } else {
+ sorted.push(item);
+ }
+ })
+
+ var minData = 0;
+ var maxData = 0;
+ if (sorted.length > 0) {
+ minData = Math.min.apply(this, sorted);
+ maxData = Math.max.apply(this, sorted);
+ }
+ //为了兼容v1.9.0之前的项目
+ if(index>-1){
+ if (typeof opts.yAxis.data[index].min === 'number') {
+ minData = Math.min(opts.yAxis.data[index].min, minData);
+ }
+ if (typeof opts.yAxis.data[index].max === 'number') {
+ maxData = Math.max(opts.yAxis.data[index].max, maxData);
+ }
+ }else{
+ if (typeof opts.yAxis.min === 'number') {
+ minData = Math.min(opts.yAxis.min, minData);
+ }
+ if (typeof opts.yAxis.max === 'number') {
+ maxData = Math.max(opts.yAxis.max, maxData);
+ }
+ }
+
+
+ if (minData === maxData) {
+ var rangeSpan = maxData || 10;
+ maxData += rangeSpan;
+ }
+
+ var dataRange = getDataRange(minData, maxData);
+ var minRange = dataRange.minRange;
+ var maxRange = dataRange.maxRange;
+
+ var range = [];
+ var eachRange = (maxRange - minRange) / opts.yAxis.splitNumber;
+
+ for (var i = 0; i <= opts.yAxis.splitNumber; i++) {
+ range.push(minRange + eachRange * i);
+ }
+ return range.reverse();
+}
+
+function calYAxisData(series, opts, config) {
+ //堆叠图重算Y轴
+ var columnstyle = assign({}, {
+ type: ""
+ }, opts.extra.column);
+ //如果是多Y轴,重新计算
+ var YLength = opts.yAxis.data.length;
+ var newSeries=new Array(YLength);
+ if(YLength>0){
+ for(let i=0;i= 2) {
+ nowAngle = nowAngle % 2;
+ }
+ nowNumber += splitNumber;
+ }
+
+}
+
+function drawRadarLabel(angleList, radius, centerPosition, opts, config, context) {
+ var radarOption = opts.extra.radar || {};
+ radius += config.radarLabelTextMargin;
+
+ angleList.forEach(function(angle, index) {
+ var pos = {
+ x: radius * Math.cos(angle),
+ y: radius * Math.sin(angle)
+ };
+ var posRelativeCanvas = convertCoordinateOrigin(pos.x, pos.y, centerPosition);
+ var startX = posRelativeCanvas.x;
+ var startY = posRelativeCanvas.y;
+ if (util.approximatelyEqual(pos.x, 0)) {
+ startX -= measureText(opts.categories[index] || '') / 2;
+ } else if (pos.x < 0) {
+ startX -= measureText(opts.categories[index] || '');
+ }
+ context.beginPath();
+ context.setFontSize(config.fontSize);
+ context.setFillStyle(radarOption.labelColor || '#666666');
+ context.fillText(opts.categories[index] || '', startX, startY + config.fontSize / 2);
+ context.closePath();
+ context.stroke();
+ });
+
+}
+
+function drawPieText(series, opts, config, context, radius, center) {
+ var lineRadius = config.pieChartLinePadding;
+ var textObjectCollection = [];
+ var lastTextObject = null;
+
+ var seriesConvert = series.map(function(item) {
+ var text = item.format ? item.format(+item._proportion_.toFixed(2)) : util.toFixed(item._proportion_.toFixed(4) * 100) +'%';
+ if(item._rose_proportion_) item._proportion_=item._rose_proportion_;
+ var arc = 2 * Math.PI - (item._start_ + 2 * Math.PI * item._proportion_ / 2);
+ var color = item.color;
+ var radius = item._radius_;
+ return {
+ arc: arc,
+ text: text,
+ color: color,
+ radius: radius,
+ textColor: item.textColor,
+ textSize: item.textSize,
+ };
+ });
+ for (let i = 0; i < seriesConvert.length; i++) {
+ let item = seriesConvert[i];
+ // line end
+ let orginX1 = Math.cos(item.arc) * (item.radius + lineRadius);
+ let orginY1 = Math.sin(item.arc) * (item.radius + lineRadius);
+
+ // line start
+ let orginX2 = Math.cos(item.arc) * item.radius;
+ let orginY2 = Math.sin(item.arc) * item.radius;
+
+ // text start
+ let orginX3 = orginX1 >= 0 ? orginX1 + config.pieChartTextPadding : orginX1 - config.pieChartTextPadding;
+ let orginY3 = orginY1;
+ let textWidth = measureText(item.text,item.textSize||config.fontSize);
+ let startY = orginY3;
+
+ if (lastTextObject && util.isSameXCoordinateArea(lastTextObject.start, {
+ x: orginX3
+ })) {
+ if (orginX3 > 0) {
+ startY = Math.min(orginY3, lastTextObject.start.y);
+ } else if (orginX1 < 0) {
+ startY = Math.max(orginY3, lastTextObject.start.y);
+ } else {
+ if (orginY3 > 0) {
+ startY = Math.max(orginY3, lastTextObject.start.y);
+ } else {
+ startY = Math.min(orginY3, lastTextObject.start.y);
+ }
+ }
+ }
+ if (orginX3 < 0) {
+ orginX3 -= textWidth;
+ }
+
+ let textObject = {
+ lineStart: {
+ x: orginX2,
+ y: orginY2
+ },
+ lineEnd: {
+ x: orginX1,
+ y: orginY1
+ },
+ start: {
+ x: orginX3,
+ y: startY
+ },
+ width: textWidth,
+ height: config.fontSize,
+ text: item.text,
+ color: item.color,
+ textColor: item.textColor,
+ textSize: item.textSize
+ };
+ lastTextObject = avoidCollision(textObject, lastTextObject);
+ textObjectCollection.push(lastTextObject);
+ }
+
+ for (let i = 0; i < textObjectCollection.length; i++) {
+ let item = textObjectCollection[i];
+ let lineStartPoistion = convertCoordinateOrigin(item.lineStart.x, item.lineStart.y, center);
+ let lineEndPoistion = convertCoordinateOrigin(item.lineEnd.x, item.lineEnd.y, center);
+ let textPosition = convertCoordinateOrigin(item.start.x, item.start.y, center);
+ context.setLineWidth(1 * opts.pixelRatio);
+ context.setFontSize(config.fontSize);
+ context.beginPath();
+ context.setStrokeStyle(item.color);
+ context.setFillStyle(item.color);
+ context.moveTo(lineStartPoistion.x, lineStartPoistion.y);
+ let curveStartX = item.start.x < 0 ? textPosition.x + item.width : textPosition.x;
+ let textStartX = item.start.x < 0 ? textPosition.x - 5 : textPosition.x + 5;
+ context.quadraticCurveTo(lineEndPoistion.x, lineEndPoistion.y, curveStartX, textPosition.y);
+ context.moveTo(lineStartPoistion.x, lineStartPoistion.y);
+ context.stroke();
+ context.closePath();
+ context.beginPath();
+ context.moveTo(textPosition.x + item.width, textPosition.y);
+ context.arc(curveStartX, textPosition.y, 2, 0, 2 * Math.PI);
+ context.closePath();
+ context.fill();
+ context.beginPath();
+ context.setFontSize(item.textSize || config.fontSize);
+ context.setFillStyle(item.textColor || '#666666');
+ context.fillText(item.text, textStartX, textPosition.y + 3);
+ context.closePath();
+ context.stroke();
+ context.closePath();
+ }
+}
+
+function drawToolTipSplitLine(offsetX, opts, config, context) {
+ var toolTipOption = opts.extra.tooltip || {};
+ toolTipOption.gridType = toolTipOption.gridType == undefined ? 'solid' : toolTipOption.gridType;
+ toolTipOption.dashLength = toolTipOption.dashLength == undefined ? 4 : toolTipOption.dashLength;
+ var startY = opts.area[0];
+ var endY = opts.height - opts.area[2];
+
+ if (toolTipOption.gridType == 'dash') {
+ context.setLineDash([toolTipOption.dashLength, toolTipOption.dashLength]);
+ }
+ context.setStrokeStyle(toolTipOption.gridColor || '#cccccc');
+ context.setLineWidth(1 * opts.pixelRatio);
+ context.beginPath();
+ context.moveTo(offsetX, startY);
+ context.lineTo(offsetX, endY);
+ context.stroke();
+ context.setLineDash([]);
+
+ if (toolTipOption.xAxisLabel) {
+ let labelText = opts.categories[opts.tooltip.index];
+ context.setFontSize(config.fontSize);
+ let textWidth = measureText(labelText, config.fontSize);
+
+ let textX = offsetX - 0.5 * textWidth;
+ let textY = endY;
+ context.beginPath();
+ context.setFillStyle(hexToRgb(toolTipOption.labelBgColor || config.toolTipBackground, toolTipOption.labelBgOpacity || config.toolTipOpacity));
+ context.setStrokeStyle(toolTipOption.labelBgColor || config.toolTipBackground);
+ context.setLineWidth(1 * opts.pixelRatio);
+ context.rect(textX - config.toolTipPadding, textY, textWidth + 2 * config.toolTipPadding, config.fontSize + 2 * config.toolTipPadding);
+ context.closePath();
+ context.stroke();
+ context.fill();
+
+ context.beginPath();
+ context.setFontSize(config.fontSize);
+ context.setFillStyle(toolTipOption.labelFontColor || config.fontColor);
+ context.fillText(String(labelText), textX, textY + config.toolTipPadding + config.fontSize);
+ context.closePath();
+ context.stroke();
+ }
+}
+
+function drawMarkLine(opts, config, context) {
+ let markLineOption = assign({}, {
+ type: 'solid',
+ dashLength: 4,
+ data: []
+ }, opts.extra.markLine);
+ let startX = opts.area[3];
+ let endX = opts.width - opts.area[1];
+ let points = calMarkLineData(markLineOption.data, opts);
+
+ for (let i = 0; i < points.length; i++) {
+ let item = assign({}, {
+ lineColor: '#DE4A42',
+ showLabel: false,
+ labelFontColor: '#666666',
+ labelBgColor: '#DFE8FF',
+ labelBgOpacity: 0.8,
+ yAxisIndex: 0
+ }, points[i]);
+
+ if (markLineOption.type == 'dash') {
+ context.setLineDash([markLineOption.dashLength, markLineOption.dashLength]);
+ }
+ context.setStrokeStyle(item.lineColor);
+ context.setLineWidth(1 * opts.pixelRatio);
+ context.beginPath();
+ context.moveTo(startX, item.y);
+ context.lineTo(endX, item.y);
+ context.stroke();
+ context.setLineDash([]);
+ if (item.showLabel) {
+ let labelText = opts.yAxis.format ? opts.yAxis.format(Number(item.value)) : item.value;
+ context.setFontSize(config.fontSize);
+ let textWidth = measureText(labelText, config.fontSize);
+ let bgStartX = opts.padding[3] + config.yAxisTitleWidth - config.toolTipPadding;
+ let bgEndX = Math.max(opts.area[3], textWidth + config.toolTipPadding * 2);
+ let bgWidth = bgEndX - bgStartX;
+
+ let textX = bgStartX + (bgWidth - textWidth) / 2;
+ let textY = item.y;
+ context.setFillStyle(hexToRgb(item.labelBgColor, item.labelBgOpacity));
+ context.setStrokeStyle(item.labelBgColor);
+ context.setLineWidth(1 * opts.pixelRatio);
+ context.beginPath();
+ context.rect(bgStartX, textY - 0.5 * config.fontSize - config.toolTipPadding, bgWidth, config.fontSize + 2 * config.toolTipPadding);
+ context.closePath();
+ context.stroke();
+ context.fill();
+
+ context.beginPath();
+ context.setFontSize(config.fontSize);
+ context.setFillStyle(item.labelFontColor);
+ context.fillText(String(labelText), textX, textY + 0.5 * config.fontSize);
+ context.stroke();
+ }
+ }
+}
+
+function drawToolTipHorizentalLine(opts, config, context, eachSpacing, xAxisPoints) {
+ var toolTipOption = assign({}, {
+ gridType: 'solid',
+ dashLength: 4
+ }, opts.extra.tooltip);
+
+ var startX = opts.area[3];
+ var endX = opts.width - opts.area[1];
+
+ if (toolTipOption.gridType == 'dash') {
+ context.setLineDash([toolTipOption.dashLength, toolTipOption.dashLength]);
+ }
+ context.setStrokeStyle(toolTipOption.gridColor || '#cccccc');
+ context.setLineWidth(1 * opts.pixelRatio);
+ context.beginPath();
+ context.moveTo(startX, opts.tooltip.offset.y);
+ context.lineTo(endX, opts.tooltip.offset.y);
+ context.stroke();
+ context.setLineDash([]);
+
+ if (toolTipOption.yAxisLabel) {
+ let labelText = calTooltipYAxisData(opts.tooltip.offset.y, opts.series, opts, config, eachSpacing);
+ let widthArr = opts.chartData.yAxisData.yAxisWidth;
+ let tStartLeft=opts.area[3];
+ let tStartRight=opts.width-opts.area[1];
+ for(let i=0;i opts.width) {
+ isOverRightBorder = true;
+ }
+ if (toolTipHeight + offset.y > opts.height) {
+ offset.y = opts.height - toolTipHeight;
+ }
+ // draw background rect
+ context.beginPath();
+ context.setFillStyle(hexToRgb(toolTipOption.bgColor || config.toolTipBackground, toolTipOption.bgOpacity || config.toolTipOpacity));
+ if (isOverRightBorder) {
+ context.moveTo(offset.x, offset.y + 10 * opts.pixelRatio);
+ context.lineTo(offset.x - arrowWidth, offset.y + 10 * opts.pixelRatio - 5 * opts.pixelRatio);
+ context.lineTo(offset.x - arrowWidth, offset.y);
+ context.lineTo(offset.x - arrowWidth - Math.round(toolTipWidth), offset.y);
+ context.lineTo(offset.x - arrowWidth - Math.round(toolTipWidth), offset.y + toolTipHeight);
+ context.lineTo(offset.x - arrowWidth, offset.y + toolTipHeight);
+ context.lineTo(offset.x - arrowWidth, offset.y + 10 * opts.pixelRatio + 5 * opts.pixelRatio);
+ context.lineTo(offset.x, offset.y + 10 * opts.pixelRatio);
+ } else {
+ context.moveTo(offset.x, offset.y + 10 * opts.pixelRatio);
+ context.lineTo(offset.x + arrowWidth, offset.y + 10 * opts.pixelRatio - 5 * opts.pixelRatio);
+ context.lineTo(offset.x + arrowWidth, offset.y);
+ context.lineTo(offset.x + arrowWidth + Math.round(toolTipWidth), offset.y);
+ context.lineTo(offset.x + arrowWidth + Math.round(toolTipWidth), offset.y + toolTipHeight);
+ context.lineTo(offset.x + arrowWidth, offset.y + toolTipHeight);
+ context.lineTo(offset.x + arrowWidth, offset.y + 10 * opts.pixelRatio + 5 * opts.pixelRatio);
+ context.lineTo(offset.x, offset.y + 10 * opts.pixelRatio);
+ }
+
+ context.closePath();
+ context.fill();
+
+ // draw legend
+ textList.forEach(function(item, index) {
+ if (item.color !== null) {
+ context.beginPath();
+ context.setFillStyle(item.color);
+ var startX = offset.x + arrowWidth + 2 * config.toolTipPadding;
+ var startY = offset.y + (config.toolTipLineHeight - config.fontSize) / 2 + config.toolTipLineHeight * index +
+ config.toolTipPadding + 1;
+ if (isOverRightBorder) {
+ startX = offset.x - toolTipWidth - arrowWidth + 2 * config.toolTipPadding;
+ }
+ context.fillRect(startX, startY, legendWidth, config.fontSize);
+ context.closePath();
+ }
+ });
+
+ // draw text list
+
+ textList.forEach(function(item, index) {
+ var startX = offset.x + arrowWidth + 2 * config.toolTipPadding + legendWidth + legendMarginRight;
+ if (isOverRightBorder) {
+ startX = offset.x - toolTipWidth - arrowWidth + 2 * config.toolTipPadding + +legendWidth + legendMarginRight;
+ }
+ var startY = offset.y + (config.toolTipLineHeight - config.fontSize) / 2 + config.toolTipLineHeight * index +
+ config.toolTipPadding;
+ context.beginPath();
+ context.setFontSize(config.fontSize);
+ context.setFillStyle(toolTipOption.fontColor);
+ context.fillText(item.text, startX, startY + config.fontSize);
+ context.closePath();
+ context.stroke();
+ });
+}
+
+function drawYAxisTitle(title, opts, config, context) {
+ var startX = config.xAxisHeight + (opts.height - config.xAxisHeight - measureText(title)) / 2;
+ context.save();
+ context.beginPath();
+ context.setFontSize(config.fontSize);
+ context.setFillStyle(opts.yAxis.titleFontColor || '#333333');
+ context.translate(0, opts.height);
+ context.rotate(-90 * Math.PI / 180);
+ context.fillText(title, startX, opts.padding[3] + 0.5 * config.fontSize);
+ context.closePath();
+ context.stroke();
+ context.restore();
+}
+
+function drawColumnDataPoints(series, opts, config, context) {
+ let process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1;
+ let xAxisData = opts.chartData.xAxisData,
+ xAxisPoints = xAxisData.xAxisPoints,
+ eachSpacing = xAxisData.eachSpacing;
+ let columnOption = assign({}, {
+ type: 'group',
+ width: eachSpacing / 2,
+ meter: {
+ border: 4,
+ fillColor: '#FFFFFF'
+ }
+ }, opts.extra.column);
+
+ let calPoints = [];
+ context.save();
+
+ let leftNum=-2;
+ let rightNum=xAxisPoints.length+2;
+
+ if (opts._scrollDistance_ && opts._scrollDistance_ !== 0 && opts.enableScroll === true) {
+ context.translate(opts._scrollDistance_, 0);
+ leftNum=Math.floor(-opts._scrollDistance_/eachSpacing)-2;
+ rightNum=leftNum+opts.xAxis.itemCount+4;
+ }
+ if (opts.tooltip && opts.tooltip.textList && opts.tooltip.textList.length && process === 1) {
+ drawToolTipSplitArea(opts.tooltip.offset.x, opts, config, context, eachSpacing);
+ }
+
+ series.forEach(function(eachSeries, seriesIndex) {
+ let ranges,minRange,maxRange;
+ ranges = [].concat(opts.chartData.yAxisData.ranges[eachSeries.index]);
+ minRange = ranges.pop();
+ maxRange = ranges.shift();
+
+ var data = eachSeries.data;
+ switch (columnOption.type) {
+ case 'group':
+ var points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process);
+ var tooltipPoints = getStackDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, seriesIndex, series, process);
+ calPoints.push(tooltipPoints);
+ points = fixColumeData(points, eachSpacing, series.length, seriesIndex, config, opts);
+ for(let i=0;ileftNum && ileftNum && i 0) {
+ height -= height0;
+ }
+ context.moveTo(startX, item.y);
+ context.fillRect(startX, item.y, item.width - 2, height);
+ context.closePath();
+ context.fill();
+ }
+ };
+ break;
+ case 'meter':
+ // 绘制温度计数据图
+ var points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process);
+ calPoints.push(points);
+ points = fixColumeMeterData(points, eachSpacing, series.length, seriesIndex, config, opts, columnOption.meter.border);
+ if (seriesIndex == 0) {
+ for(let i=0;ileftNum && i 0) {
+ context.beginPath();
+ context.setStrokeStyle(eachSeries.color);
+ context.setLineWidth(columnOption.meter.border * opts.pixelRatio);
+ context.moveTo(startX + columnOption.meter.border * 0.5, item.y + height);
+ context.lineTo(startX + columnOption.meter.border * 0.5, item.y + columnOption.meter.border * 0.5);
+ context.lineTo(startX + item.width - columnOption.meter.border * 0.5, item.y + columnOption.meter.border * 0.5);
+ context.lineTo(startX + item.width - columnOption.meter.border * 0.5, item.y + height);
+ context.stroke();
+ }
+ }
+ };
+ } else {
+ for(let i=0;ileftNum && i 5 && arguments[5] !== undefined ? arguments[5] : 1;
+ var candleOption = assign({}, {
+ color: {},
+ average: {}
+ }, opts.extra.candle);
+ candleOption.color = assign({}, {
+ upLine: '#f04864',
+ upFill: '#f04864',
+ downLine: '#2fc25b',
+ downFill: '#2fc25b'
+ }, candleOption.color);
+ candleOption.average = assign({}, {
+ show: false,
+ name: [],
+ day: [],
+ color: config.colors
+ }, candleOption.average);
+ opts.extra.candle = candleOption;
+
+ let xAxisData = opts.chartData.xAxisData,
+ xAxisPoints = xAxisData.xAxisPoints,
+ eachSpacing = xAxisData.eachSpacing;
+
+ let calPoints = [];
+
+ context.save();
+
+ let leftNum=-2;
+ let rightNum=xAxisPoints.length+2;
+ let leftSpace=0;
+ let rightSpace=opts.width+eachSpacing;
+
+ if (opts._scrollDistance_ && opts._scrollDistance_ !== 0 && opts.enableScroll === true) {
+ context.translate(opts._scrollDistance_, 0);
+ leftNum=Math.floor(-opts._scrollDistance_/eachSpacing)-2;
+ rightNum=leftNum+opts.xAxis.itemCount+4;
+ leftSpace=-opts._scrollDistance_-eachSpacing+opts.area[3];
+ rightSpace=leftSpace+(opts.xAxis.itemCount+4)*eachSpacing;
+ }
+
+ //画均线
+ if (candleOption.average.show) {
+ seriesMA.forEach(function(eachSeries, seriesIndex) {
+ let ranges,minRange,maxRange;
+ ranges = [].concat(opts.chartData.yAxisData.ranges[eachSeries.index]);
+ minRange = ranges.pop();
+ maxRange = ranges.shift();
+
+ var data = eachSeries.data;
+ var points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process);
+ var splitPointList = splitPoints(points);
+
+ for(let i=0;i leftSpace){
+ context.moveTo(item.x, item.y);
+ startPoint=1;
+ }
+ if (j > 0 && item.x > leftSpace && item.x < rightSpace) {
+ var ctrlPoint = createCurveControlPoints(points, j - 1);
+ context.bezierCurveTo(ctrlPoint.ctrA.x, ctrlPoint.ctrA.y, ctrlPoint.ctrB.x, ctrlPoint.ctrB.y,item.x, item.y);
+ }
+ }
+ context.moveTo(points[0].x, points[0].y);
+ }
+ context.closePath();
+ context.stroke();
+ }
+ });
+ }
+ //画K线
+ series.forEach(function(eachSeries, seriesIndex) {
+ let ranges,minRange,maxRange;
+ ranges = [].concat(opts.chartData.yAxisData.ranges[eachSeries.index]);
+ minRange = ranges.pop();
+ maxRange = ranges.shift();
+ var data = eachSeries.data;
+ var points = getCandleDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process);
+ calPoints.push(points);
+ var splitPointList = splitPoints(points);
+
+ for(let i=0;ileftNum && i 0) {
+ context.setStrokeStyle(candleOption.color.upLine);
+ context.setFillStyle(candleOption.color.upFill);
+ context.setLineWidth(1 * opts.pixelRatio);
+ context.moveTo(item[3].x, item[3].y); //顶点
+ context.lineTo(item[1].x, item[1].y); //收盘中间点
+ context.lineTo(item[1].x - eachSpacing / 4, item[1].y); //收盘左侧点
+ context.lineTo(item[0].x - eachSpacing / 4, item[0].y); //开盘左侧点
+ context.lineTo(item[0].x, item[0].y); //开盘中间点
+ context.lineTo(item[2].x, item[2].y); //底点
+ context.lineTo(item[0].x, item[0].y); //开盘中间点
+ context.lineTo(item[0].x + eachSpacing / 4, item[0].y); //开盘右侧点
+ context.lineTo(item[1].x + eachSpacing / 4, item[1].y); //收盘右侧点
+ context.lineTo(item[1].x, item[1].y); //收盘中间点
+ context.moveTo(item[3].x, item[3].y); //顶点
+ } else {
+ context.setStrokeStyle(candleOption.color.downLine);
+ context.setFillStyle(candleOption.color.downFill);
+ context.setLineWidth(1 * opts.pixelRatio);
+ context.moveTo(item[3].x, item[3].y); //顶点
+ context.lineTo(item[0].x, item[0].y); //开盘中间点
+ context.lineTo(item[0].x - eachSpacing / 4, item[0].y); //开盘左侧点
+ context.lineTo(item[1].x - eachSpacing / 4, item[1].y); //收盘左侧点
+ context.lineTo(item[1].x, item[1].y); //收盘中间点
+ context.lineTo(item[2].x, item[2].y); //底点
+ context.lineTo(item[1].x, item[1].y); //收盘中间点
+ context.lineTo(item[1].x + eachSpacing / 4, item[1].y); //收盘右侧点
+ context.lineTo(item[0].x + eachSpacing / 4, item[0].y); //开盘右侧点
+ context.lineTo(item[0].x, item[0].y); //开盘中间点
+ context.moveTo(item[3].x, item[3].y); //顶点
+ }
+ context.closePath();
+ context.fill();
+ context.stroke();
+ }
+ }
+ });
+
+ context.restore();
+
+ return {
+ xAxisPoints: xAxisPoints,
+ calPoints: calPoints,
+ eachSpacing: eachSpacing
+ };
+}
+
+function drawAreaDataPoints(series, opts, config, context) {
+ var process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1;
+ var areaOption = assign({},{
+ type: 'straight',
+ opacity: 0.2,
+ addLine: false,
+ width: 2,
+ gradient:false
+ },opts.extra.area);
+
+ let xAxisData = opts.chartData.xAxisData,
+ xAxisPoints = xAxisData.xAxisPoints,
+ eachSpacing = xAxisData.eachSpacing;
+
+ let endY = opts.height - opts.area[2];
+ let calPoints = [];
+
+ context.save();
+ let leftSpace=0;
+ let rightSpace=opts.width+eachSpacing;
+ if (opts._scrollDistance_ && opts._scrollDistance_ !== 0 && opts.enableScroll === true) {
+ context.translate(opts._scrollDistance_, 0);
+ leftSpace=-opts._scrollDistance_-eachSpacing+opts.area[3];
+ rightSpace=leftSpace+(opts.xAxis.itemCount+4)*eachSpacing;
+ }
+
+ series.forEach(function(eachSeries, seriesIndex) {
+ let ranges,minRange,maxRange;
+ ranges = [].concat(opts.chartData.yAxisData.ranges[eachSeries.index]);
+ minRange = ranges.pop();
+ maxRange = ranges.shift();
+ let data = eachSeries.data;
+ let points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process);
+ calPoints.push(points);
+
+ let splitPointList = splitPoints(points);
+ for (let i = 0; i < splitPointList.length; i++) {
+ let points = splitPointList[i];
+ // 绘制区域数
+ context.beginPath();
+ context.setStrokeStyle(hexToRgb(eachSeries.color, areaOption.opacity));
+ if(areaOption.gradient){
+ let gradient = context.createLinearGradient(0, opts.area[0], 0, opts.height-opts.area[2]);
+ gradient.addColorStop('0', hexToRgb(eachSeries.color, areaOption.opacity));
+ gradient.addColorStop('1.0',hexToRgb("#FFFFFF", 0.1));
+ context.setFillStyle(gradient);
+ }else{
+ context.setFillStyle(hexToRgb(eachSeries.color, areaOption.opacity));
+ }
+ context.setLineWidth(areaOption.width * opts.pixelRatio);
+ if (points.length > 1) {
+ let firstPoint = points[0];
+ let lastPoint = points[points.length - 1];
+ context.moveTo(firstPoint.x, firstPoint.y);
+ let startPoint=0;
+ if (areaOption.type === 'curve') {
+ for(let j=0;j leftSpace){
+ context.moveTo(item.x, item.y);
+ startPoint=1;
+ }
+ if (j > 0 && item.x > leftSpace && item.x < rightSpace) {
+ let ctrlPoint = createCurveControlPoints(points, j - 1);
+ context.bezierCurveTo(ctrlPoint.ctrA.x, ctrlPoint.ctrA.y, ctrlPoint.ctrB.x, ctrlPoint.ctrB.y,item.x, item.y);
+ }
+ };
+ } else {
+ for(let j=0;j leftSpace){
+ context.moveTo(item.x, item.y);
+ startPoint=1;
+ }
+ if (j > 0 && item.x > leftSpace && item.x < rightSpace) {
+ context.lineTo(item.x, item.y);
+ }
+ };
+ }
+
+ context.lineTo(lastPoint.x, endY);
+ context.lineTo(firstPoint.x, endY);
+ context.lineTo(firstPoint.x, firstPoint.y);
+ } else {
+ let item = points[0];
+ context.moveTo(item.x - eachSpacing / 2, item.y);
+ context.lineTo(item.x + eachSpacing / 2, item.y);
+ context.lineTo(item.x + eachSpacing / 2, endY);
+ context.lineTo(item.x - eachSpacing / 2, endY);
+ context.moveTo(item.x - eachSpacing / 2, item.y);
+ }
+ context.closePath();
+ context.fill();
+
+ //画连线
+ if (areaOption.addLine) {
+ if (eachSeries.lineType == 'dash') {
+ let dashLength = eachSeries.dashLength?eachSeries.dashLength:8;
+ dashLength *= opts.pixelRatio;
+ context.setLineDash([dashLength, dashLength]);
+ }
+ context.beginPath();
+ context.setStrokeStyle(eachSeries.color);
+ context.setLineWidth(areaOption.width * opts.pixelRatio);
+ if (points.length === 1) {
+ context.moveTo(points[0].x, points[0].y);
+ context.arc(points[0].x, points[0].y, 1, 0, 2 * Math.PI);
+ } else {
+ context.moveTo(points[0].x, points[0].y);
+ let startPoint=0;
+ if (areaOption.type === 'curve') {
+ for(let j=0;j leftSpace){
+ context.moveTo(item.x, item.y);
+ startPoint=1;
+ }
+ if (j > 0 && item.x > leftSpace && item.x < rightSpace) {
+ let ctrlPoint = createCurveControlPoints(points, j - 1);
+ context.bezierCurveTo(ctrlPoint.ctrA.x, ctrlPoint.ctrA.y, ctrlPoint.ctrB.x, ctrlPoint.ctrB.y,item.x,item.y);
+ }
+ };
+ } else {
+ for(let j=0;j leftSpace){
+ context.moveTo(item.x, item.y);
+ startPoint=1;
+ }
+ if (j > 0 && item.x > leftSpace && item.x < rightSpace) {
+ context.lineTo(item.x, item.y);
+ }
+ };
+ }
+ context.moveTo(points[0].x, points[0].y);
+ }
+ context.stroke();
+ context.setLineDash([]);
+ }
+ }
+
+ //画点
+ if (opts.dataPointShape !== false) {
+ drawPointShape(points, eachSeries.color, eachSeries.pointShape, context, opts);
+ }
+
+ });
+
+ if (opts.dataLabel !== false && process === 1) {
+ series.forEach(function(eachSeries, seriesIndex) {
+ let ranges,minRange,maxRange;
+ ranges = [].concat(opts.chartData.yAxisData.ranges[eachSeries.index]);
+ minRange = ranges.pop();
+ maxRange = ranges.shift();
+ var data = eachSeries.data;
+ var points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process);
+ drawPointText(points, eachSeries, config, context);
+ });
+ }
+
+ context.restore();
+
+ return {
+ xAxisPoints: xAxisPoints,
+ calPoints: calPoints,
+ eachSpacing: eachSpacing
+ };
+}
+
+function drawLineDataPoints(series, opts, config, context) {
+ var process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1;
+ var lineOption = assign({},{
+ type: 'straight',
+ width: 2
+ },opts.extra.line);
+ lineOption.width *=opts.pixelRatio;
+
+ let xAxisData = opts.chartData.xAxisData,
+ xAxisPoints = xAxisData.xAxisPoints,
+ eachSpacing = xAxisData.eachSpacing;
+ var calPoints = [];
+
+ context.save();
+ let leftSpace=0;
+ let rightSpace=opts.width+eachSpacing;
+ if (opts._scrollDistance_ && opts._scrollDistance_ !== 0 && opts.enableScroll === true) {
+ context.translate(opts._scrollDistance_, 0);
+ leftSpace=-opts._scrollDistance_-eachSpacing+opts.area[3];
+ rightSpace=leftSpace+(opts.xAxis.itemCount+4)*eachSpacing;
+ }
+
+ series.forEach(function(eachSeries, seriesIndex) {
+ let ranges,minRange,maxRange;
+ ranges = [].concat(opts.chartData.yAxisData.ranges[eachSeries.index]);
+ minRange = ranges.pop();
+ maxRange = ranges.shift();
+ var data = eachSeries.data;
+ var points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process);
+ calPoints.push(points);
+ var splitPointList = splitPoints(points);
+
+ if (eachSeries.lineType == 'dash') {
+ let dashLength = eachSeries.dashLength?eachSeries.dashLength:8;
+ dashLength *= opts.pixelRatio;
+ context.setLineDash([dashLength, dashLength]);
+ }
+ context.beginPath();
+ context.setStrokeStyle(eachSeries.color);
+ context.setLineWidth(lineOption.width);
+
+ splitPointList.forEach(function(points, index) {
+
+ if (points.length === 1) {
+ context.moveTo(points[0].x, points[0].y);
+ context.arc(points[0].x, points[0].y, 1, 0, 2 * Math.PI);
+ } else {
+ context.moveTo(points[0].x, points[0].y);
+ let startPoint=0;
+ if (lineOption.type === 'curve') {
+ for(let j=0;j leftSpace){
+ context.moveTo(item.x, item.y);
+ startPoint=1;
+ }
+ if (j > 0 && item.x > leftSpace && item.x < rightSpace) {
+ var ctrlPoint = createCurveControlPoints(points, j - 1);
+ context.bezierCurveTo(ctrlPoint.ctrA.x, ctrlPoint.ctrA.y, ctrlPoint.ctrB.x, ctrlPoint.ctrB.y,item.x, item.y);
+ }
+ };
+ } else {
+ for(let j=0;j leftSpace){
+ context.moveTo(item.x, item.y);
+ startPoint=1;
+ }
+ if (j > 0 && item.x > leftSpace && item.x < rightSpace) {
+ context.lineTo(item.x, item.y);
+ }
+ };
+ }
+ context.moveTo(points[0].x, points[0].y);
+ }
+
+ });
+
+ context.stroke();
+ context.setLineDash([]);
+
+ if (opts.dataPointShape !== false) {
+ drawPointShape(points, eachSeries.color, eachSeries.pointShape, context, opts);
+ }
+ });
+
+ if (opts.dataLabel !== false && process === 1) {
+ series.forEach(function(eachSeries, seriesIndex) {
+ let ranges,minRange,maxRange;
+ ranges = [].concat(opts.chartData.yAxisData.ranges[eachSeries.index]);
+ minRange = ranges.pop();
+ maxRange = ranges.shift();
+ var data = eachSeries.data;
+ var points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process);
+ drawPointText(points, eachSeries, config, context);
+ });
+ }
+
+ context.restore();
+
+ return {
+ xAxisPoints: xAxisPoints,
+ calPoints: calPoints,
+ eachSpacing: eachSpacing
+ };
+}
+
+function drawMixDataPoints(series, opts, config, context) {
+ let process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1;
+
+ let xAxisData = opts.chartData.xAxisData,
+ xAxisPoints = xAxisData.xAxisPoints,
+ eachSpacing = xAxisData.eachSpacing;
+
+ let endY = opts.height - opts.area[2];
+ let calPoints = [];
+
+ var columnIndex = 0;
+ var columnLength = 0;
+ series.forEach(function(eachSeries, seriesIndex) {
+ if (eachSeries.type == 'column') {
+ columnLength += 1;
+ }
+ });
+ context.save();
+ let leftNum=-2;
+ let rightNum=xAxisPoints.length+2;
+ let leftSpace=0;
+ let rightSpace=opts.width+eachSpacing;
+ if (opts._scrollDistance_ && opts._scrollDistance_ !== 0 && opts.enableScroll === true) {
+ context.translate(opts._scrollDistance_, 0);
+ leftNum=Math.floor(-opts._scrollDistance_/eachSpacing)-2;
+ rightNum=leftNum+opts.xAxis.itemCount+4;
+ leftSpace=-opts._scrollDistance_-eachSpacing+opts.area[3];
+ rightSpace=leftSpace+(opts.xAxis.itemCount+4)*eachSpacing;
+ }
+
+ series.forEach(function(eachSeries, seriesIndex) {
+ let ranges,minRange,maxRange;
+
+ ranges = [].concat(opts.chartData.yAxisData.ranges[eachSeries.index]);
+ minRange = ranges.pop();
+ maxRange = ranges.shift();
+
+ var data = eachSeries.data;
+ var points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process);
+ calPoints.push(points);
+
+ // 绘制柱状数据图
+ if (eachSeries.type == 'column') {
+ points = fixColumeData(points, eachSpacing, columnLength, columnIndex, config, opts);
+ for(let i=0;ileftNum && i 1) {
+ var firstPoint = points[0];
+ let lastPoint = points[points.length - 1];
+ context.moveTo(firstPoint.x, firstPoint.y);
+ let startPoint=0;
+ if (eachSeries.style === 'curve') {
+ for(let j=0;j leftSpace){
+ context.moveTo(item.x, item.y);
+ startPoint=1;
+ }
+ if (j > 0 && item.x > leftSpace && item.x < rightSpace) {
+ var ctrlPoint = createCurveControlPoints(points, j - 1);
+ context.bezierCurveTo(ctrlPoint.ctrA.x, ctrlPoint.ctrA.y, ctrlPoint.ctrB.x, ctrlPoint.ctrB.y, item.x, item.y);
+ }
+ };
+ } else {
+ for(let j=0;j leftSpace){
+ context.moveTo(item.x, item.y);
+ startPoint=1;
+ }
+ if (j > 0 && item.x > leftSpace && item.x < rightSpace) {
+ context.lineTo(item.x, item.y);
+ }
+ };
+ }
+ context.lineTo(lastPoint.x, endY);
+ context.lineTo(firstPoint.x, endY);
+ context.lineTo(firstPoint.x, firstPoint.y);
+ } else {
+ let item = points[0];
+ context.moveTo(item.x - eachSpacing / 2, item.y);
+ context.lineTo(item.x + eachSpacing / 2, item.y);
+ context.lineTo(item.x + eachSpacing / 2, endY);
+ context.lineTo(item.x - eachSpacing / 2, endY);
+ context.moveTo(item.x - eachSpacing / 2, item.y);
+ }
+ context.closePath();
+ context.fill();
+ }
+ }
+
+ // 绘制折线数据图
+ if (eachSeries.type == 'line') {
+ var splitPointList = splitPoints(points);
+ splitPointList.forEach(function(points, index) {
+ if (eachSeries.lineType == 'dash') {
+ let dashLength = eachSeries.dashLength?eachSeries.dashLength:8;
+ dashLength *= opts.pixelRatio;
+ context.setLineDash([dashLength, dashLength]);
+ }
+ context.beginPath();
+ context.setStrokeStyle(eachSeries.color);
+ context.setLineWidth(2 * opts.pixelRatio);
+ if (points.length === 1) {
+ context.moveTo(points[0].x, points[0].y);
+ context.arc(points[0].x, points[0].y, 1, 0, 2 * Math.PI);
+ } else {
+ context.moveTo(points[0].x, points[0].y);
+ let startPoint=0;
+ if (eachSeries.style == 'curve') {
+ for(let j=0;j leftSpace){
+ context.moveTo(item.x, item.y);
+ startPoint=1;
+ }
+ if (j > 0 && item.x > leftSpace && item.x < rightSpace) {
+ var ctrlPoint = createCurveControlPoints(points, j - 1);
+ context.bezierCurveTo(ctrlPoint.ctrA.x, ctrlPoint.ctrA.y, ctrlPoint.ctrB.x, ctrlPoint.ctrB.y,item.x,item.y);
+ }
+ }
+ } else {
+ for(let j=0;j leftSpace){
+ context.moveTo(item.x, item.y);
+ startPoint=1;
+ }
+ if (j > 0 && item.x > leftSpace && item.x < rightSpace) {
+ context.lineTo(item.x, item.y);
+ }
+ }
+ }
+ context.moveTo(points[0].x, points[0].y);
+ }
+ context.stroke();
+ context.setLineDash([]);
+ });
+ }
+
+ // 绘制点数据图
+ if (eachSeries.type == 'point') {
+ eachSeries.addPoint = true;
+ }
+
+ if (eachSeries.addPoint == true && eachSeries.type !== 'column' ) {
+ drawPointShape(points, eachSeries.color, eachSeries.pointShape, context, opts);
+ }
+ });
+ if (opts.dataLabel !== false && process === 1) {
+ var columnIndex = 0;
+ series.forEach(function(eachSeries, seriesIndex) {
+ let ranges,minRange,maxRange;
+
+ ranges = [].concat(opts.chartData.yAxisData.ranges[eachSeries.index]);
+ minRange = ranges.pop();
+ maxRange = ranges.shift();
+
+ var data = eachSeries.data;
+ var points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process);
+ if (eachSeries.type !== 'column') {
+ drawPointText(points, eachSeries, config, context);
+ } else {
+ points = fixColumeData(points, eachSpacing, columnLength, columnIndex, config, opts);
+ drawPointText(points, eachSeries, config, context);
+ columnIndex += 1;
+ }
+
+ });
+ }
+
+ context.restore();
+
+ return {
+ xAxisPoints: xAxisPoints,
+ calPoints: calPoints,
+ eachSpacing: eachSpacing,
+ }
+}
+
+function drawToolTipBridge(opts, config, context, process, eachSpacing, xAxisPoints) {
+ var toolTipOption = opts.extra.tooltip || {};
+ if (toolTipOption.horizentalLine && opts.tooltip && process === 1 && (opts.type == 'line' || opts.type == 'area' || opts.type == 'column' || opts.type == 'candle' || opts.type == 'mix')) {
+ drawToolTipHorizentalLine(opts, config, context, eachSpacing, xAxisPoints)
+ }
+ context.save();
+ if (opts._scrollDistance_ && opts._scrollDistance_ !== 0 && opts.enableScroll === true) {
+ context.translate(opts._scrollDistance_, 0);
+ }
+ if (opts.tooltip && opts.tooltip.textList && opts.tooltip.textList.length && process === 1) {
+ drawToolTip(opts.tooltip.textList, opts.tooltip.offset, opts, config, context, eachSpacing, xAxisPoints);
+ }
+ context.restore();
+
+}
+
+function drawXAxis(categories, opts, config, context) {
+
+ let xAxisData = opts.chartData.xAxisData,
+ xAxisPoints = xAxisData.xAxisPoints,
+ startX = xAxisData.startX,
+ endX = xAxisData.endX,
+ eachSpacing = xAxisData.eachSpacing;
+ var boundaryGap='center';
+ if (opts.type == 'line'||opts.type == 'area'){
+ boundaryGap=opts.xAxis.boundaryGap;
+ }
+ var startY = opts.height - opts.area[2];
+ var endY = opts.area[0];
+
+ //绘制滚动条
+ if (opts.enableScroll && opts.xAxis.scrollShow) {
+ var scrollY = opts.height - opts.area[2] + config.xAxisHeight;
+ var scrollScreenWidth = endX - startX;
+ var scrollTotalWidth = eachSpacing * (xAxisPoints.length - 1);
+ var scrollWidth = scrollScreenWidth * scrollScreenWidth / scrollTotalWidth;
+ var scrollLeft = 0;
+ if (opts._scrollDistance_) {
+ scrollLeft = -opts._scrollDistance_ * (scrollScreenWidth) / scrollTotalWidth;
+ }
+ context.beginPath();
+ context.setLineCap('round');
+ context.setLineWidth(6 * opts.pixelRatio);
+ context.setStrokeStyle(opts.xAxis.scrollBackgroundColor || "#EFEBEF");
+ context.moveTo(startX, scrollY);
+ context.lineTo(endX, scrollY);
+ context.stroke();
+ context.closePath();
+ context.beginPath();
+ context.setLineCap('round');
+ context.setLineWidth(6 * opts.pixelRatio);
+ context.setStrokeStyle(opts.xAxis.scrollColor || "#A6A6A6");
+ context.moveTo(startX + scrollLeft, scrollY);
+ context.lineTo(startX + scrollLeft + scrollWidth, scrollY);
+ context.stroke();
+ context.closePath();
+ context.setLineCap('butt');
+ }
+
+ context.save();
+
+ if (opts._scrollDistance_ && opts._scrollDistance_ !== 0) {
+ context.translate(opts._scrollDistance_, 0);
+ }
+
+ //绘制X轴刻度线
+ if (opts.xAxis.calibration === true) {
+ context.setStrokeStyle(opts.xAxis.gridColor || "#cccccc");
+ context.setLineCap('butt');
+ context.setLineWidth(1 * opts.pixelRatio);
+ xAxisPoints.forEach(function(item, index) {
+ if (index > 0) {
+ context.beginPath();
+ context.moveTo(item - eachSpacing / 2, startY);
+ context.lineTo(item - eachSpacing / 2, startY + 3 * opts.pixelRatio);
+ context.closePath();
+ context.stroke();
+ }
+ });
+ }
+ //绘制X轴网格
+ if (opts.xAxis.disableGrid !== true) {
+ context.setStrokeStyle(opts.xAxis.gridColor || "#cccccc");
+ context.setLineCap('butt');
+ context.setLineWidth(1 * opts.pixelRatio);
+ if (opts.xAxis.gridType == 'dash') {
+ context.setLineDash([opts.xAxis.dashLength, opts.xAxis.dashLength]);
+ }
+ opts.xAxis.gridEval = opts.xAxis.gridEval || 1;
+ xAxisPoints.forEach(function(item, index) {
+ if (index % opts.xAxis.gridEval == 0) {
+ context.beginPath();
+ context.moveTo(item, startY);
+ context.lineTo(item, endY);
+ context.stroke();
+ }
+ });
+ context.setLineDash([]);
+ }
+
+
+ //绘制X轴文案
+ if (opts.xAxis.disabled !== true) {
+ // 对X轴列表做抽稀处理
+ //默认全部显示X轴标签
+ let maxXAxisListLength = categories.length;
+ //如果设置了X轴单屏数量
+ if (opts.xAxis.labelCount) {
+ //如果设置X轴密度
+ if (opts.xAxis.itemCount) {
+ maxXAxisListLength = Math.ceil(categories.length / opts.xAxis.itemCount * opts.xAxis.labelCount);
+ } else {
+ maxXAxisListLength = opts.xAxis.labelCount;
+ }
+ maxXAxisListLength -= 1;
+ }
+
+ let ratio = Math.ceil(categories.length / maxXAxisListLength);
+
+ let newCategories = [];
+ let cgLength = categories.length;
+ for (let i = 0; i < cgLength; i++) {
+ if (i % ratio !== 0) {
+ newCategories.push("");
+ } else {
+ newCategories.push(categories[i]);
+ }
+ }
+ newCategories[cgLength - 1] = categories[cgLength - 1];
+
+ var xAxisFontSize = opts.xAxis.fontSize || config.fontSize;
+ if (config._xAxisTextAngle_ === 0) {
+ newCategories.forEach(function(item, index) {
+ var offset = - measureText(String(item), xAxisFontSize) / 2;
+ if(boundaryGap == 'center'){
+ offset+=eachSpacing / 2;
+ }
+ var scrollHeight=0;
+ if(opts.xAxis.scrollShow){
+ scrollHeight=6*opts.pixelRatio;
+ }
+ context.beginPath();
+ context.setFontSize(xAxisFontSize);
+ context.setFillStyle(opts.xAxis.fontColor || '#666666');
+ context.fillText(String(item), xAxisPoints[index] + offset, startY + xAxisFontSize + (config.xAxisHeight - scrollHeight - xAxisFontSize) / 2);
+ context.closePath();
+ context.stroke();
+ });
+
+ } else {
+ newCategories.forEach(function(item, index) {
+ context.save();
+ context.beginPath();
+ context.setFontSize(xAxisFontSize);
+ context.setFillStyle(opts.xAxis.fontColor || '#666666');
+ var textWidth = measureText(String(item),xAxisFontSize);
+ var offset = - textWidth;
+ if(boundaryGap == 'center'){
+ offset+=eachSpacing / 2;
+ }
+ var _calRotateTranslate = calRotateTranslate(xAxisPoints[index] + eachSpacing / 2, startY + xAxisFontSize / 2 + 5, opts.height),
+ transX = _calRotateTranslate.transX,
+ transY = _calRotateTranslate.transY;
+
+ context.rotate(-1 * config._xAxisTextAngle_);
+ context.translate(transX, transY);
+ context.fillText(String(item), xAxisPoints[index] + offset, startY + xAxisFontSize + 5);
+ context.closePath();
+ context.stroke();
+ context.restore();
+ });
+ }
+ }
+ context.restore();
+
+ //绘制X轴轴线
+ if(opts.xAxis.axisLine){
+ context.beginPath();
+ context.setStrokeStyle(opts.xAxis.axisLineColor);
+ context.setLineWidth(1 * opts.pixelRatio);
+ context.moveTo(startX,opts.height-opts.area[2]);
+ context.lineTo(endX,opts.height-opts.area[2]);
+ context.stroke();
+ }
+}
+
+function drawYAxisGrid(categories, opts, config, context) {
+ if (opts.yAxis.disableGrid === true) {
+ return;
+ }
+ let spacingValid = opts.height - opts.area[0] - opts.area[2];
+ let eachSpacing = spacingValid / opts.yAxis.splitNumber;
+ let startX = opts.area[3];
+ let xAxisPoints = opts.chartData.xAxisData.xAxisPoints,
+ xAxiseachSpacing = opts.chartData.xAxisData.eachSpacing;
+ let TotalWidth = xAxiseachSpacing * (xAxisPoints.length - 1);
+ let endX = startX + TotalWidth;
+
+ let points = [];
+ for (let i = 0; i < opts.yAxis.splitNumber + 1; i++) {
+ points.push(opts.height - opts.area[2] - eachSpacing * i);
+ }
+
+ context.save();
+ if (opts._scrollDistance_ && opts._scrollDistance_ !== 0) {
+ context.translate(opts._scrollDistance_, 0);
+ }
+
+ if (opts.yAxis.gridType == 'dash') {
+ context.setLineDash([opts.yAxis.dashLength, opts.yAxis.dashLength]);
+ }
+ context.setStrokeStyle(opts.yAxis.gridColor);
+ context.setLineWidth(1 * opts.pixelRatio);
+ points.forEach(function(item, index) {
+ context.beginPath();
+ context.moveTo(startX, item);
+ context.lineTo(endX, item);
+ context.stroke();
+ });
+ context.setLineDash([]);
+
+ context.restore();
+}
+
+function drawYAxis(series, opts, config, context) {
+ if (opts.yAxis.disabled === true) {
+ return;
+ }
+ var spacingValid = opts.height - opts.area[0] - opts.area[2];
+ var eachSpacing = spacingValid / opts.yAxis.splitNumber;
+ var startX = opts.area[3];
+ var endX = opts.width - opts.area[1];
+ var endY = opts.height - opts.area[2];
+ var fillEndY = endY + config.xAxisHeight;
+ if (opts.xAxis.scrollShow) {
+ fillEndY -= 3 * opts.pixelRatio;
+ }
+ if (opts.xAxis.rotateLabel){
+ fillEndY = opts.height - opts.area[2]+3;
+ }
+ // set YAxis background
+ context.beginPath();
+ context.setFillStyle(opts.background || '#ffffff');
+ if (opts._scrollDistance_ < 0) {
+ context.fillRect(0, 0, startX, fillEndY);
+ }
+ if(opts.enableScroll == true){
+ context.fillRect(endX, 0, opts.width, fillEndY);
+ }
+ context.closePath();
+ context.stroke();
+
+ var points = [];
+ for (let i = 0; i <= opts.yAxis.splitNumber; i++) {
+ points.push(opts.area[0] + eachSpacing * i);
+ }
+
+ let tStartLeft=opts.area[3];
+ let tStartRight=opts.width-opts.area[1];
+
+ for (let i = 0; i < opts.yAxis.data.length; i++) {
+ let yData = opts.yAxis.data[i];
+ if(yData.disabled !== true){
+ let rangesFormat = opts.chartData.yAxisData.rangesFormat[i];
+ let yAxisFontSize = yData.fontSize || config.fontSize;
+ let yAxisWidth = opts.chartData.yAxisData.yAxisWidth[i];
+ //画Y轴刻度及文案
+ rangesFormat.forEach(function(item, index) {
+ var pos = points[index] ? points[index] : endY;
+ context.beginPath();
+ context.setFontSize(yAxisFontSize);
+ context.setLineWidth(1*opts.pixelRatio);
+ context.setStrokeStyle(yData.axisLineColor||'#cccccc');
+ context.setFillStyle(yData.fontColor|| '#666666');
+ if(yAxisWidth.position=='left'){
+ context.fillText(String(item), tStartLeft - yAxisWidth.width , pos + yAxisFontSize / 2);
+ //画刻度线
+ if(yData.calibration==true){
+ context.moveTo(tStartLeft,pos);
+ context.lineTo(tStartLeft - 3*opts.pixelRatio,pos);
+ }
+ }else{
+ context.fillText(String(item), tStartRight + 4*opts.pixelRatio, pos + yAxisFontSize / 2);
+ //画刻度线
+ if(yData.calibration==true){
+ context.moveTo(tStartRight,pos);
+ context.lineTo(tStartRight + 3*opts.pixelRatio,pos);
+ }
+ }
+ context.closePath();
+ context.stroke();
+ });
+ //画Y轴轴线
+ if (yData.axisLine!==false) {
+ context.beginPath();
+ context.setStrokeStyle(yData.axisLineColor||'#cccccc');
+ context.setLineWidth(1 * opts.pixelRatio);
+ if(yAxisWidth.position=='left'){
+ context.moveTo(tStartLeft,opts.height-opts.area[2]);
+ context.lineTo(tStartLeft,opts.area[0]);
+ }else{
+ context.moveTo(tStartRight,opts.height-opts.area[2]);
+ context.lineTo(tStartRight,opts.area[0]);
+ }
+ context.stroke();
+ }
+
+ //画Y轴标题
+ if (opts.yAxis.showTitle) {
+
+ let titleFontSize = yData.titleFontSize || config.fontSize;
+ let title = yData.title;
+ context.beginPath();
+ context.setFontSize(titleFontSize);
+ context.setFillStyle(yData.titleFontColor || '#666666');
+ if(yAxisWidth.position=='left'){
+ context.fillText(title, tStartLeft - measureText(title,titleFontSize)/2, opts.area[0]-10*opts.pixelRatio);
+ }else{
+ context.fillText(title,tStartRight - measureText(title,titleFontSize)/2, opts.area[0]-10*opts.pixelRatio);
+ }
+ context.closePath();
+ context.stroke();
+ }
+ if(yAxisWidth.position=='left'){
+ tStartLeft -=(yAxisWidth.width + opts.yAxis.padding);
+ }else{
+ tStartRight +=yAxisWidth.width+ opts.yAxis.padding;
+ }
+ }
+ }
+}
+
+function drawLegend(series, opts, config, context, chartData) {
+ if (opts.legend.show === false) {
+ return;
+ }
+ let legendData = chartData.legendData;
+ let legendList = legendData.points;
+ let legendArea = legendData.area;
+ let padding = opts.legend.padding;
+ let fontSize = opts.legend.fontSize;
+ let shapeWidth = 15 * opts.pixelRatio;
+ let shapeRight = 5 * opts.pixelRatio;
+ let itemGap = opts.legend.itemGap;
+ let lineHeight = Math.max(opts.legend.lineHeight * opts.pixelRatio, fontSize);
+
+ //画背景及边框
+ context.beginPath();
+ context.setLineWidth(opts.legend.borderWidth);
+ context.setStrokeStyle(opts.legend.borderColor);
+ context.setFillStyle(opts.legend.backgroundColor);
+ context.moveTo(legendArea.start.x, legendArea.start.y);
+ context.rect(legendArea.start.x, legendArea.start.y, legendArea.width, legendArea.height);
+ context.closePath();
+ context.fill();
+ context.stroke();
+
+ legendList.forEach(function(itemList, listIndex) {
+ let width = 0;
+ let height = 0;
+ width = legendData.widthArr[listIndex];
+ height = legendData.heightArr[listIndex];
+ let startX = 0;
+ let startY = 0;
+ if (opts.legend.position == 'top' || opts.legend.position == 'bottom') {
+ startX = legendArea.start.x + (legendArea.width - width) / 2;
+ startY = legendArea.start.y + padding + listIndex * lineHeight;
+ } else {
+ if (listIndex == 0) {
+ width = 0;
+ } else {
+ width = legendData.widthArr[listIndex - 1];
+ }
+ startX = legendArea.start.x + padding + width;
+ startY = legendArea.start.y + padding + (legendArea.height - height) / 2;
+ }
+
+ context.setFontSize(config.fontSize);
+ for (let i = 0; i < itemList.length; i++) {
+ let item = itemList[i];
+ item.area = [0, 0, 0, 0];
+ item.area[0] = startX;
+ item.area[1] = startY;
+ item.area[3] = startY + lineHeight;
+ context.beginPath();
+ context.setLineWidth(1 * opts.pixelRatio);
+ context.setStrokeStyle(item.show ? item.color : opts.legend.hiddenColor);
+ context.setFillStyle(item.show ? item.color : opts.legend.hiddenColor);
+ switch (item.legendShape) {
+ case 'line':
+ context.moveTo(startX, startY + 0.5 * lineHeight - 2 * opts.pixelRatio);
+ context.fillRect(startX, startY + 0.5 * lineHeight - 2 * opts.pixelRatio, 15 * opts.pixelRatio, 4 * opts.pixelRatio);
+ break;
+ case 'triangle':
+ context.moveTo(startX + 7.5 * opts.pixelRatio, startY + 0.5 * lineHeight - 5 * opts.pixelRatio);
+ context.lineTo(startX + 2.5 * opts.pixelRatio, startY + 0.5 * lineHeight + 5 * opts.pixelRatio);
+ context.lineTo(startX + 12.5 * opts.pixelRatio, startY + 0.5 * lineHeight + 5 * opts.pixelRatio);
+ context.lineTo(startX + 7.5 * opts.pixelRatio, startY + 0.5 * lineHeight - 5 * opts.pixelRatio);
+ break;
+ case 'diamond':
+ context.moveTo(startX + 7.5 * opts.pixelRatio, startY + 0.5 * lineHeight - 5 * opts.pixelRatio);
+ context.lineTo(startX + 2.5 * opts.pixelRatio, startY + 0.5 * lineHeight);
+ context.lineTo(startX + 7.5 * opts.pixelRatio, startY + 0.5 * lineHeight + 5 * opts.pixelRatio);
+ context.lineTo(startX + 12.5 * opts.pixelRatio, startY + 0.5 * lineHeight);
+ context.lineTo(startX + 7.5 * opts.pixelRatio, startY + 0.5 * lineHeight - 5 * opts.pixelRatio);
+ break;
+ case 'circle':
+ context.moveTo(startX + 7.5 * opts.pixelRatio, startY + 0.5 * lineHeight);
+ context.arc(startX + 7.5 * opts.pixelRatio, startY + 0.5 * lineHeight, 5 * opts.pixelRatio, 0, 2 * Math.PI);
+ break;
+ case 'rect':
+ context.moveTo(startX, startY + 0.5 * lineHeight - 5 * opts.pixelRatio);
+ context.fillRect(startX, startY + 0.5 * lineHeight - 5 * opts.pixelRatio, 15 * opts.pixelRatio, 10 * opts.pixelRatio);
+ break;
+ default:
+ context.moveTo(startX, startY + 0.5 * lineHeight - 5 * opts.pixelRatio);
+ context.fillRect(startX, startY + 0.5 * lineHeight - 5 * opts.pixelRatio, 15 * opts.pixelRatio, 10 * opts.pixelRatio);
+ }
+ context.closePath();
+ context.fill();
+ context.stroke();
+
+ startX += shapeWidth + shapeRight;
+ let fontTrans = 0.5 * lineHeight + 0.5 * fontSize - 2;
+ context.beginPath();
+ context.setFontSize(fontSize);
+ context.setFillStyle(item.show ? opts.legend.fontColor : opts.legend.hiddenColor);
+ context.fillText(item.name, startX, startY + fontTrans);
+ context.closePath();
+ context.stroke();
+ if (opts.legend.position == 'top' || opts.legend.position == 'bottom') {
+ startX += measureText(item.name, fontSize) + itemGap;
+ item.area[2] = startX;
+ } else {
+ item.area[2] = startX + measureText(item.name, fontSize) + itemGap;;
+ startX -= shapeWidth + shapeRight;
+ startY += lineHeight;
+ }
+ }
+ });
+}
+
+function drawPieDataPoints(series, opts, config, context) {
+ var process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1;
+ var pieOption = assign({}, {
+ activeOpacity: 0.5,
+ activeRadius: 10 * opts.pixelRatio,
+ offsetAngle: 0,
+ labelWidth: 15 * opts.pixelRatio,
+ ringWidth: 0,
+ border:false,
+ borderWidth:2,
+ borderColor:'#FFFFFF'
+ }, opts.extra.pie);
+ var centerPosition = {
+ x: opts.area[3] + (opts.width - opts.area[1] - opts.area[3]) / 2,
+ y: opts.area[0] + (opts.height - opts.area[0] - opts.area[2]) / 2
+ };
+ if (config.pieChartLinePadding == 0) {
+ config.pieChartLinePadding = pieOption.activeRadius;
+ }
+
+ var radius = Math.min((opts.width - opts.area[1] - opts.area[3]) / 2 - config.pieChartLinePadding - config.pieChartTextPadding - config._pieTextMaxLength_, (opts.height - opts.area[0] - opts.area[2]) / 2 - config.pieChartLinePadding - config.pieChartTextPadding);
+
+ series = getPieDataPoints(series, radius, process);
+
+ var activeRadius = pieOption.activeRadius;
+
+ series = series.map(function(eachSeries) {
+ eachSeries._start_ += (pieOption.offsetAngle) * Math.PI / 180;
+ return eachSeries;
+ });
+ series.forEach(function(eachSeries, seriesIndex) {
+ if (opts.tooltip) {
+ if (opts.tooltip.index == seriesIndex) {
+ context.beginPath();
+ context.setFillStyle(hexToRgb(eachSeries.color, opts.extra.pie.activeOpacity || 0.5));
+ context.moveTo(centerPosition.x, centerPosition.y);
+ context.arc(centerPosition.x, centerPosition.y, eachSeries._radius_ + activeRadius, eachSeries._start_,
+ eachSeries._start_ + 2 *
+ eachSeries._proportion_ * Math.PI);
+ context.closePath();
+ context.fill();
+ }
+ }
+ context.beginPath();
+ context.setLineWidth(pieOption.borderWidth * opts.pixelRatio);
+ context.lineJoin = "round";
+ context.setStrokeStyle(pieOption.borderColor);
+ context.setFillStyle(eachSeries.color);
+ context.moveTo(centerPosition.x, centerPosition.y);
+ context.arc(centerPosition.x, centerPosition.y, eachSeries._radius_, eachSeries._start_, eachSeries._start_ + 2 * eachSeries._proportion_ * Math.PI);
+ context.closePath();
+ context.fill();
+ if (pieOption.border == true) {
+ context.stroke();
+ }
+ });
+
+ if (opts.type === 'ring') {
+ var innerPieWidth = radius * 0.6;
+ if (typeof opts.extra.pie.ringWidth === 'number' && opts.extra.pie.ringWidth > 0) {
+ innerPieWidth = Math.max(0, radius - opts.extra.pie.ringWidth);
+ }
+ context.beginPath();
+ context.setFillStyle(opts.background || '#ffffff');
+ context.moveTo(centerPosition.x, centerPosition.y);
+ context.arc(centerPosition.x, centerPosition.y, innerPieWidth, 0, 2 * Math.PI);
+ context.closePath();
+ context.fill();
+ }
+
+ if (opts.dataLabel !== false && process === 1) {
+ var valid = false;
+ for (var i = 0, len = series.length; i < len; i++) {
+ if (series[i].data > 0) {
+ valid = true;
+ break;
+ }
+ }
+
+ if (valid) {
+ drawPieText(series, opts, config, context, radius, centerPosition);
+ }
+ }
+
+ if (process === 1 && opts.type === 'ring') {
+ drawRingTitle(opts, config, context, centerPosition);
+ }
+
+ return {
+ center: centerPosition,
+ radius: radius,
+ series: series
+ };
+}
+
+function drawRoseDataPoints(series, opts, config, context) {
+ var process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1;
+ var roseOption = assign({}, {
+ type: 'area',
+ activeOpacity: 0.5,
+ activeRadius: 10 * opts.pixelRatio,
+ offsetAngle: 0,
+ labelWidth: 15 * opts.pixelRatio,
+ border:false,
+ borderWidth:2,
+ borderColor:'#FFFFFF'
+ }, opts.extra.rose);
+ if (config.pieChartLinePadding == 0) {
+ config.pieChartLinePadding = roseOption.activeRadius;
+ }
+ var centerPosition = {
+ x: opts.area[3] + (opts.width - opts.area[1] - opts.area[3]) / 2,
+ y: opts.area[0] + (opts.height - opts.area[0] - opts.area[2]) / 2
+ };
+ var radius = Math.min((opts.width - opts.area[1] - opts.area[3]) / 2 - config.pieChartLinePadding - config.pieChartTextPadding - config._pieTextMaxLength_, (opts.height - opts.area[0] - opts.area[2]) / 2 - config.pieChartLinePadding - config.pieChartTextPadding);
+ var minRadius = roseOption.minRadius || radius * 0.5;
+
+ series = getRoseDataPoints(series, roseOption.type, minRadius, radius, process);
+
+ var activeRadius = roseOption.activeRadius;
+
+ series = series.map(function(eachSeries) {
+ eachSeries._start_ += (roseOption.offsetAngle || 0) * Math.PI / 180;
+ return eachSeries;
+ });
+
+ series.forEach(function(eachSeries, seriesIndex) {
+ if (opts.tooltip) {
+ if (opts.tooltip.index == seriesIndex) {
+ context.beginPath();
+ context.setFillStyle(hexToRgb(eachSeries.color, roseOption.activeOpacity || 0.5));
+ context.moveTo(centerPosition.x, centerPosition.y);
+ context.arc(centerPosition.x, centerPosition.y, activeRadius + eachSeries._radius_, eachSeries._start_,
+ eachSeries._start_ + 2 * eachSeries._rose_proportion_ * Math.PI);
+ context.closePath();
+ context.fill();
+ }
+ }
+ context.beginPath();
+ context.setLineWidth(roseOption.borderWidth * opts.pixelRatio);
+ context.lineJoin = "round";
+ context.setStrokeStyle(roseOption.borderColor);
+ context.setFillStyle(eachSeries.color);
+ context.moveTo(centerPosition.x, centerPosition.y);
+ context.arc(centerPosition.x, centerPosition.y, eachSeries._radius_, eachSeries._start_, eachSeries._start_ + 2 *
+ eachSeries._rose_proportion_ * Math.PI);
+ context.closePath();
+ context.fill();
+ if (roseOption.border == true) {
+ context.stroke();
+ }
+ });
+
+ if (opts.dataLabel !== false && process === 1) {
+ var valid = false;
+ for (var i = 0, len = series.length; i < len; i++) {
+ if (series[i].data > 0) {
+ valid = true;
+ break;
+ }
+ }
+
+ if (valid) {
+ drawPieText(series, opts, config, context, radius, centerPosition);
+ }
+ }
+
+ return {
+ center: centerPosition,
+ radius: radius,
+ series: series
+ };
+}
+
+function drawArcbarDataPoints(series, opts, config, context) {
+ var process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1;
+ var arcbarOption = assign({}, {
+ startAngle: 0.75,
+ endAngle: 0.25,
+ type: 'default',
+ width: 12 * opts.pixelRatio,
+ gap:2 * opts.pixelRatio
+ }, opts.extra.arcbar);
+
+ series = getArcbarDataPoints(series, arcbarOption, process);
+
+ var centerPosition;
+ if(arcbarOption.center){
+ centerPosition=arcbarOption.center;
+ }else{
+ centerPosition= {
+ x: opts.width / 2,
+ y: opts.height / 2
+ };
+ }
+
+ var radius;
+ if(arcbarOption.radius){
+ radius=arcbarOption.radius;
+ }else{
+ radius = Math.min(centerPosition.x, centerPosition.y);
+ radius -= 5 * opts.pixelRatio;
+ radius -= arcbarOption.width / 2;
+ }
+
+ for (let i = 0; i < series.length; i++) {
+ let eachSeries = series[i];
+ //背景颜色
+ context.setLineWidth(arcbarOption.width);
+ context.setStrokeStyle(arcbarOption.backgroundColor || '#E9E9E9');
+ context.setLineCap('round');
+ context.beginPath();
+ if (arcbarOption.type == 'default') {
+ context.arc(centerPosition.x, centerPosition.y, radius-(arcbarOption.width+arcbarOption.gap)*i, arcbarOption.startAngle * Math.PI, arcbarOption.endAngle * Math.PI, false);
+ } else {
+ context.arc(centerPosition.x, centerPosition.y, radius-(arcbarOption.width+arcbarOption.gap)*i, 0, 2 * Math.PI, false);
+ }
+ context.stroke();
+ //进度条
+ context.setLineWidth(arcbarOption.width);
+ context.setStrokeStyle(eachSeries.color);
+ context.setLineCap('round');
+ context.beginPath();
+ context.arc(centerPosition.x, centerPosition.y, radius-(arcbarOption.width+arcbarOption.gap)*i, arcbarOption.startAngle * Math.PI, eachSeries._proportion_ * Math.PI, false);
+ context.stroke();
+ }
+
+ drawRingTitle(opts, config, context, centerPosition);
+
+ return {
+ center: centerPosition,
+ radius: radius,
+ series: series
+ };
+}
+
+function drawGaugeDataPoints(categories, series, opts, config, context) {
+ var process = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 1;
+ var gaugeOption = assign({}, {
+ type:'default',
+ startAngle: 0.75,
+ endAngle: 0.25,
+ width: 15,
+ splitLine: {
+ fixRadius: 0,
+ splitNumber: 10,
+ width: 15,
+ color: '#FFFFFF',
+ childNumber: 5,
+ childWidth: 5
+ },
+ pointer: {
+ width: 15,
+ color: 'auto'
+ }
+ }, opts.extra.gauge);
+
+ if (gaugeOption.oldAngle == undefined) {
+ gaugeOption.oldAngle = gaugeOption.startAngle;
+ }
+ if (gaugeOption.oldData == undefined) {
+ gaugeOption.oldData = 0;
+ }
+ categories = getGaugeAxisPoints(categories, gaugeOption.startAngle, gaugeOption.endAngle);
+
+ var centerPosition = {
+ x: opts.width / 2,
+ y: opts.height / 2
+ };
+ var radius = Math.min(centerPosition.x, centerPosition.y);
+ radius -= 5 * opts.pixelRatio;
+ radius -= gaugeOption.width / 2;
+ var innerRadius = radius - gaugeOption.width;
+ var totalAngle=0;
+
+ //判断仪表盘的样式:default百度样式,progress新样式
+ if(gaugeOption.type == 'progress'){
+
+ //## 第一步画中心圆形背景和进度条背景
+ //中心圆形背景
+ var pieRadius = radius - gaugeOption.width*3;
+ context.beginPath();
+ let gradient = context.createLinearGradient(centerPosition.x, centerPosition.y-pieRadius, centerPosition.x , centerPosition.y+pieRadius);
+ //配置渐变填充(起点:中心点向上减半径;结束点中心点向下加半径)
+ gradient.addColorStop('0', hexToRgb(series[0].color, 0.3));
+ gradient.addColorStop('1.0',hexToRgb("#FFFFFF", 0.1));
+ context.setFillStyle(gradient);
+ context.arc(centerPosition.x, centerPosition.y, pieRadius, 0, 2*Math.PI, false);
+ context.fill();
+ //画进度条背景
+ context.setLineWidth(gaugeOption.width);
+ context.setStrokeStyle(hexToRgb(series[0].color, 0.3));
+ context.setLineCap('round');
+ context.beginPath();
+ context.arc(centerPosition.x, centerPosition.y, innerRadius , gaugeOption.startAngle * Math.PI, gaugeOption.endAngle *Math.PI, false);
+ context.stroke();
+
+ //## 第二步画刻度线
+ totalAngle = gaugeOption.startAngle - gaugeOption.endAngle + 1;
+ let splitAngle = totalAngle / gaugeOption.splitLine.splitNumber;
+ let childAngle = totalAngle / gaugeOption.splitLine.splitNumber / gaugeOption.splitLine.childNumber;
+ let startX = -radius - gaugeOption.width * 0.5 - gaugeOption.splitLine.fixRadius;
+ let endX = -radius - gaugeOption.width - gaugeOption.splitLine.fixRadius + gaugeOption.splitLine.width;
+ context.save();
+ context.translate(centerPosition.x, centerPosition.y);
+ context.rotate((gaugeOption.startAngle - 1) * Math.PI);
+ let len = gaugeOption.splitLine.splitNumber * gaugeOption.splitLine.childNumber + 1;
+ let proc = series[0].data * process;
+ for (let i = 0; i < len; i++) {
+ context.beginPath();
+ //刻度线随进度变色
+ if(proc>(i/len)){
+ context.setStrokeStyle(hexToRgb(series[0].color, 1));
+ }else{
+ context.setStrokeStyle(hexToRgb(series[0].color, 0.3));
+ }
+ context.setLineWidth(3 * opts.pixelRatio);
+ context.moveTo(startX, 0);
+ context.lineTo(endX, 0);
+ context.stroke();
+ context.rotate(childAngle * Math.PI);
+ }
+ context.restore();
+
+ //## 第三步画进度条
+ series = getArcbarDataPoints(series, gaugeOption, process);
+ context.setLineWidth(gaugeOption.width);
+ context.setStrokeStyle(series[0].color);
+ context.setLineCap('round');
+ context.beginPath();
+ context.arc(centerPosition.x, centerPosition.y, innerRadius , gaugeOption.startAngle * Math.PI, series[0]._proportion_ *Math.PI, false);
+ context.stroke();
+
+ //## 第四步画指针
+ let pointerRadius = radius - gaugeOption.width*2.5;
+ context.save();
+ context.translate(centerPosition.x, centerPosition.y);
+ context.rotate((series[0]._proportion_ - 1) * Math.PI);
+ context.beginPath();
+ context.setLineWidth(gaugeOption.width/3);
+ let gradient3 = context.createLinearGradient(0, -pointerRadius*0.6, 0 , pointerRadius*0.6);
+ gradient3.addColorStop('0', hexToRgb('#FFFFFF', 0));
+ gradient3.addColorStop('0.5', hexToRgb(series[0].color, 1));
+ gradient3.addColorStop('1.0', hexToRgb('#FFFFFF', 0));
+ context.setStrokeStyle(gradient3);
+ context.arc(0, 0, pointerRadius , 0.85* Math.PI, 1.15 * Math.PI, false);
+ context.stroke();
+ context.beginPath();
+ context.setLineWidth(1);
+ context.setStrokeStyle(series[0].color);
+ context.setFillStyle(series[0].color);
+ context.moveTo(-pointerRadius-gaugeOption.width/3/2,-4);
+ context.lineTo(-pointerRadius-gaugeOption.width/3/2-4,0);
+ context.lineTo(-pointerRadius-gaugeOption.width/3/2,4);
+ context.lineTo(-pointerRadius-gaugeOption.width/3/2,-4);
+ context.stroke();
+ context.fill();
+ context.restore();
+
+ //default百度样式
+ }else{
+ //画背景
+ context.setLineWidth(gaugeOption.width);
+ context.setLineCap('butt');
+ for (let i = 0; i < categories.length; i++) {
+ let eachCategories = categories[i];
+ context.beginPath();
+ context.setStrokeStyle(eachCategories.color);
+ context.arc(centerPosition.x, centerPosition.y, radius, eachCategories._startAngle_ * Math.PI, eachCategories._endAngle_ *Math.PI, false);
+ context.stroke();
+ }
+ context.save();
+
+ //画刻度线
+ totalAngle = gaugeOption.startAngle - gaugeOption.endAngle + 1;
+ let splitAngle = totalAngle / gaugeOption.splitLine.splitNumber;
+ let childAngle = totalAngle / gaugeOption.splitLine.splitNumber / gaugeOption.splitLine.childNumber;
+ let startX = -radius - gaugeOption.width * 0.5 - gaugeOption.splitLine.fixRadius;
+ let endX = -radius - gaugeOption.width * 0.5 - gaugeOption.splitLine.fixRadius + gaugeOption.splitLine.width;
+ let childendX = -radius - gaugeOption.width * 0.5 - gaugeOption.splitLine.fixRadius + gaugeOption.splitLine.childWidth;
+
+ context.translate(centerPosition.x, centerPosition.y);
+ context.rotate((gaugeOption.startAngle - 1) * Math.PI);
+
+ for (let i = 0; i < gaugeOption.splitLine.splitNumber + 1; i++) {
+ context.beginPath();
+ context.setStrokeStyle(gaugeOption.splitLine.color);
+ context.setLineWidth(2 * opts.pixelRatio);
+ context.moveTo(startX, 0);
+ context.lineTo(endX, 0);
+ context.stroke();
+ context.rotate(splitAngle * Math.PI);
+ }
+ context.restore();
+
+ context.save();
+ context.translate(centerPosition.x, centerPosition.y);
+ context.rotate((gaugeOption.startAngle - 1) * Math.PI);
+
+ for (let i = 0; i < gaugeOption.splitLine.splitNumber * gaugeOption.splitLine.childNumber + 1; i++) {
+ context.beginPath();
+ context.setStrokeStyle(gaugeOption.splitLine.color);
+ context.setLineWidth(1 * opts.pixelRatio);
+ context.moveTo(startX, 0);
+ context.lineTo(childendX, 0);
+ context.stroke();
+ context.rotate(childAngle * Math.PI);
+ }
+ context.restore();
+
+ //画指针
+ series = getGaugeDataPoints(series, categories, gaugeOption, process);
+
+ for (let i = 0; i < series.length; i++) {
+ let eachSeries = series[i];
+ context.save();
+ context.translate(centerPosition.x, centerPosition.y);
+ context.rotate((eachSeries._proportion_ - 1) * Math.PI);
+ context.beginPath();
+ context.setFillStyle(eachSeries.color);
+ context.moveTo(gaugeOption.pointer.width, 0);
+ context.lineTo(0, -gaugeOption.pointer.width / 2);
+ context.lineTo(-innerRadius, 0);
+ context.lineTo(0, gaugeOption.pointer.width / 2);
+ context.lineTo(gaugeOption.pointer.width, 0);
+ context.closePath();
+ context.fill();
+ context.beginPath();
+ context.setFillStyle('#FFFFFF');
+ context.arc(0, 0, gaugeOption.pointer.width / 6, 0, 2 * Math.PI, false);
+ context.fill();
+ context.restore();
+ }
+
+ if (opts.dataLabel !== false) {
+ drawGaugeLabel(gaugeOption, radius, centerPosition, opts, config, context);
+ }
+ }
+
+ //画仪表盘标题,副标题
+ drawRingTitle(opts, config, context, centerPosition);
+
+ if (process === 1 && opts.type === 'gauge') {
+ opts.extra.gauge.oldAngle = series[0]._proportion_;
+ opts.extra.gauge.oldData = series[0].data;
+ }
+ return {
+ center: centerPosition,
+ radius: radius,
+ innerRadius: innerRadius,
+ categories: categories,
+ totalAngle: totalAngle
+ };
+}
+
+function drawRadarDataPoints(series, opts, config, context) {
+ var process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1;
+ var radarOption = assign({},{
+ gridColor: '#cccccc',
+ labelColor: '#666666',
+ opacity: 0.2,
+ gridCount:3
+ },opts.extra.radar);
+
+ var coordinateAngle = getRadarCoordinateSeries(opts.categories.length);
+
+ var centerPosition = {
+ x: opts.area[3] + (opts.width - opts.area[1] - opts.area[3]) / 2,
+ y: opts.area[0] + (opts.height - opts.area[0] - opts.area[2]) / 2
+ };
+
+ var radius = Math.min(centerPosition.x - (getMaxTextListLength(opts.categories) + config.radarLabelTextMargin),
+ centerPosition.y - config.radarLabelTextMargin);
+ //TODO逻辑不对
+ radius -= opts.padding[1];
+
+ // draw grid
+ context.beginPath();
+ context.setLineWidth(1 * opts.pixelRatio);
+ context.setStrokeStyle(radarOption.gridColor);
+ coordinateAngle.forEach(function(angle) {
+ var pos = convertCoordinateOrigin(radius * Math.cos(angle), radius * Math.sin(angle), centerPosition);
+ context.moveTo(centerPosition.x, centerPosition.y);
+ context.lineTo(pos.x, pos.y);
+ });
+ context.stroke();
+ context.closePath();
+ // draw split line grid
+
+ var _loop = function _loop(i) {
+ var startPos = {};
+ context.beginPath();
+ context.setLineWidth(1 * opts.pixelRatio);
+ context.setStrokeStyle(radarOption.gridColor);
+ coordinateAngle.forEach(function(angle, index) {
+ var pos = convertCoordinateOrigin(radius / radarOption.gridCount * i * Math.cos(angle), radius / radarOption.gridCount * i * Math.sin(angle), centerPosition);
+ if (index === 0) {
+ startPos = pos;
+ context.moveTo(pos.x, pos.y);
+ } else {
+ context.lineTo(pos.x, pos.y);
+ }
+ });
+ context.lineTo(startPos.x, startPos.y);
+ context.stroke();
+ context.closePath();
+ };
+
+ for (var i = 1; i <= radarOption.gridCount; i++) {
+ _loop(i);
+ }
+
+ var radarDataPoints = getRadarDataPoints(coordinateAngle, centerPosition, radius, series, opts, process);
+
+ radarDataPoints.forEach(function(eachSeries, seriesIndex) {
+ // 绘制区域数据
+ context.beginPath();
+ context.setFillStyle(hexToRgb(eachSeries.color, radarOption.opacity));
+ eachSeries.data.forEach(function(item, index) {
+ if (index === 0) {
+ context.moveTo(item.position.x, item.position.y);
+ } else {
+ context.lineTo(item.position.x, item.position.y);
+ }
+ });
+ context.closePath();
+ context.fill();
+
+ if (opts.dataPointShape !== false) {
+ var points = eachSeries.data.map(function(item) {
+ return item.position;
+ });
+ drawPointShape(points, eachSeries.color, eachSeries.pointShape, context, opts);
+ }
+ });
+ // draw label text
+ drawRadarLabel(coordinateAngle, radius, centerPosition, opts, config, context);
+
+ return {
+ center: centerPosition,
+ radius: radius,
+ angleList: coordinateAngle
+ };
+}
+
+function normalInt(min, max, iter) {
+ iter = iter==0?1:iter;
+ var arr = [];
+ for (var i = 0; i < iter; i++) {
+ arr[i] = Math.random();
+ };
+ return Math.floor(arr.reduce(function(i,j){return i+j})/iter*(max-min))+min;
+};
+
+function collisionNew(area,points,width,height){
+ var isIn=false;
+ for(let i=0;ipoints[i].area[2]||area[1]>points[i].area[3]||area[2]width || area[3]>height){
+ isIn=true;
+ break;
+ }else{
+ isIn=false;
+ }
+ }else{
+ isIn=true;
+ break;
+ }
+ }
+ }
+ return isIn;
+};
+
+function getBoundingBox(data) {
+ var bounds = {}, coords;
+ bounds.xMin = 180;
+ bounds.xMax = 0;
+ bounds.yMin = 90;
+ bounds.yMax = 0
+ for (var i = 0; i < data.length; i++) {
+ var coorda = data[i].geometry.coordinates
+ for (var k = 0; k < coorda.length; k++) {
+ coords = coorda[k];
+ if (coords.length == 1) {
+ coords = coords[0]
+ }
+ for (var j = 0; j < coords.length; j++) {
+ var longitude = coords[j][0];
+ var latitude = coords[j][1];
+ var point = {
+ x: longitude,
+ y: latitude
+ }
+ bounds.xMin = bounds.xMin < point.x ? bounds.xMin : point.x;
+ bounds.xMax = bounds.xMax > point.x ? bounds.xMax : point.x;
+ bounds.yMin = bounds.yMin < point.y ? bounds.yMin : point.y;
+ bounds.yMax = bounds.yMax > point.y ? bounds.yMax : point.y;
+ }
+ }
+ }
+ return bounds;
+}
+
+function coordinateToPoint(latitude, longitude,bounds,scale,xoffset,yoffset) {
+ return {
+ x: (longitude - bounds.xMin) * scale+xoffset,
+ y: (bounds.yMax - latitude) * scale+yoffset
+ };
+}
+
+function pointToCoordinate(pointY, pointX,bounds,scale,xoffset,yoffset) {
+ return {
+ x: (pointX-xoffset)/scale+bounds.xMin,
+ y: bounds.yMax - (pointY-yoffset)/scale
+ };
+}
+
+function isRayIntersectsSegment(poi,s_poi,e_poi){
+ if (s_poi[1]==e_poi[1]){return false;}
+ if (s_poi[1]>poi[1] && e_poi[1]>poi[1]){return false;}
+ if (s_poi[1]poi[1]){return false;}
+ if (e_poi[1]==poi[1] && s_poi[1]>poi[1]){return false;}
+ if (s_poi[0]0.7) {
+ return true;
+ }else {return false};
+ };
+ for (let i = 0; i < points.length; i++) {
+ let text = points[i].name;
+ let tHeight = points[i].textSize;
+ let tWidth = measureText(text,tHeight);
+ let isSpin = Spin();
+ let x,y,area,areav;
+ let breaknum=0;
+ while(true) {
+ breaknum++;
+ let isCollision;
+ if (isSpin) {
+ x = normalInt(-opts.width/2, opts.width/2,5) - tWidth/2;
+ y = normalInt(-opts.height/2, opts.height/2,5)+tHeight/2;
+ area=[y-5-tWidth+opts.width/2,(-x-5+opts.height/2),y+5+opts.width/2,(-x+tHeight+5+opts.height/2)];
+ areav=[opts.width-(opts.width/2-opts.height/2)-(-x+tHeight+5+opts.height/2)-5,(opts.height/2-opts.width/2)+(y-5-tWidth+opts.width/2)-5,opts.width-(opts.width/2-opts.height/2)-(-x+tHeight+5+opts.height/2)+tHeight,(opts.height/2-opts.width/2)+(y-5-tWidth+opts.width/2)+tWidth+5];
+ isCollision = collisionNew(areav,points,opts.height,opts.width);
+ }else{
+ x = normalInt(-opts.width/2, opts.width/2,5) - tWidth/2;
+ y = normalInt(-opts.height/2, opts.height/2,5)+tHeight/2;
+ area=[x-5+opts.width/2,y-5-tHeight+opts.height/2,x+tWidth+5+opts.width/2,y+5+opts.height/2];
+ isCollision = collisionNew(area,points,opts.width,opts.height);
+ }
+ if (!isCollision) break;
+ if (breaknum==1000){
+ area=[-1000,-1000,-1000,-1000];
+ break;
+ }
+ };
+ if (isSpin) {
+ points[i].area=areav;
+ points[i].areav=area;
+ }else{
+ points[i].area=area;
+ }
+ points[i].rotate=isSpin;
+ };
+ break;
+ }
+ return points;
+}
+
+
+function drawWordCloudDataPoints(series, opts, config, context) {
+ let process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1;
+ let wordOption = assign({},{
+ type: 'normal',
+ autoColors: true
+ },opts.extra.word);
+
+ context.beginPath();
+ context.setFillStyle(opts.background||'#FFFFFF');
+ context.rect(0,0,opts.width,opts.height);
+ context.fill();
+ context.save();
+ let points = opts.chartData.wordCloudData;
+ context.translate(opts.width/2,opts.height/2);
+
+ for(let i=0;i0){
+ if (opts.tooltip) {
+ if (opts.tooltip.index == i) {
+ context.strokeText(text,(points[i].areav[0]+5-opts.width/2)*process-tWidth*(1-process)/2,(points[i].areav[1]+5+tHeight-opts.height/2)*process);
+ }else{
+ context.fillText(text,(points[i].areav[0]+5-opts.width/2)*process-tWidth*(1-process)/2,(points[i].areav[1]+5+tHeight-opts.height/2)*process);
+ }
+ }else{
+ context.fillText(text,(points[i].areav[0]+5-opts.width/2)*process-tWidth*(1-process)/2,(points[i].areav[1]+5+tHeight-opts.height/2)*process);
+ }
+ }
+ }else{
+ if(points[i].area[0]>0){
+ if (opts.tooltip) {
+ if (opts.tooltip.index == i) {
+ context.strokeText(text,(points[i].area[0]+5-opts.width/2)*process-tWidth*(1-process)/2,(points[i].area[1]+5+tHeight-opts.height/2)*process);
+ }else{
+ context.fillText(text,(points[i].area[0]+5-opts.width/2)*process-tWidth*(1-process)/2,(points[i].area[1]+5+tHeight-opts.height/2)*process);
+ }
+ }else{
+ context.fillText(text,(points[i].area[0]+5-opts.width/2)*process-tWidth*(1-process)/2,(points[i].area[1]+5+tHeight-opts.height/2)*process);
+ }
+
+ }
+ }
+
+ context.stroke();
+ context.restore();
+ }
+ context.restore();
+}
+
+function drawFunnelDataPoints(series, opts, config, context) {
+ let process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1;
+ let funnelOption = assign({},{
+ activeWidth:10,
+ activeOpacity:0.3,
+ border:false,
+ borderWidth:2,
+ borderColor:'#FFFFFF',
+ fillOpacity:1,
+ labelAlign:'right'
+ },opts.extra.funnel);
+ let eachSpacing = (opts.height - opts.area[0] - opts.area[2])/series.length;
+ let centerPosition = {
+ x: opts.area[3] + (opts.width - opts.area[1] - opts.area[3]) / 2,
+ y: opts.height-opts.area[2]
+ };
+ let activeWidth = funnelOption.activeWidth;
+ let radius = Math.min((opts.width - opts.area[1] - opts.area[3]) / 2 - activeWidth, (opts.height - opts.area[0] - opts.area[2]) / 2 - activeWidth);
+ series = getFunnelDataPoints(series, radius, process);
+ context.save();
+ context.translate(centerPosition.x,centerPosition.y);
+ for(let i=0;i0){
+ opts.area[3] += yAxisWidth[i].width + opts.yAxis.padding;
+ }else{
+ opts.area[3] += yAxisWidth[i].width;
+ }
+ leftIndex +=1;
+ }else{
+ if(rightIndex>0){
+ opts.area[1] += yAxisWidth[i].width + opts.yAxis.padding;
+ }else{
+ opts.area[1] += yAxisWidth[i].width;
+ }
+ rightIndex +=1;
+ }
+ }
+ }else{
+ config.yAxisWidth = yAxisWidth;
+ }
+ opts.chartData.yAxisData = _calYAxisData;
+
+ if (opts.categories && opts.categories.length) {
+ opts.chartData.xAxisData = getXAxisPoints(opts.categories, opts, config);
+ let _calCategoriesData = calCategoriesData(opts.categories, opts, config, opts.chartData.xAxisData.eachSpacing),
+ xAxisHeight = _calCategoriesData.xAxisHeight,
+ angle = _calCategoriesData.angle;
+ config.xAxisHeight = xAxisHeight;
+ config._xAxisTextAngle_ = angle;
+ opts.area[2] += xAxisHeight;
+ opts.chartData.categoriesData = _calCategoriesData;
+ }else{
+ if (opts.type === 'line' || opts.type === 'area' || opts.type === 'points') {
+ opts.chartData.xAxisData = calXAxisData(series, opts, config);
+ categories=opts.chartData.xAxisData.rangesFormat;
+ let _calCategoriesData = calCategoriesData(categories, opts, config, opts.chartData.xAxisData.eachSpacing),
+ xAxisHeight = _calCategoriesData.xAxisHeight,
+ angle = _calCategoriesData.angle;
+ config.xAxisHeight = xAxisHeight;
+ config._xAxisTextAngle_ = angle;
+ opts.area[2] += xAxisHeight;
+ opts.chartData.categoriesData = _calCategoriesData;
+ }else{
+ opts.chartData.xAxisData={
+ xAxisPoints: []
+ };
+ }
+ }
+ //计算右对齐偏移距离
+ if (opts.enableScroll && opts.xAxis.scrollAlign == 'right' && opts._scrollDistance_ === undefined) {
+ let offsetLeft = 0,
+ xAxisPoints = opts.chartData.xAxisData.xAxisPoints,
+ startX = opts.chartData.xAxisData.startX,
+ endX = opts.chartData.xAxisData.endX,
+ eachSpacing = opts.chartData.xAxisData.eachSpacing;
+ let totalWidth = eachSpacing * (xAxisPoints.length - 1);
+ let screenWidth = endX - startX;
+ offsetLeft = screenWidth - totalWidth;
+ _this.scrollOption = {
+ currentOffset: offsetLeft,
+ startTouchX: offsetLeft,
+ distance: 0,
+ lastMoveTime: 0
+ };
+ opts._scrollDistance_ = offsetLeft;
+ }
+
+ if (type === 'pie' || type === 'ring' || type === 'rose') {
+ config._pieTextMaxLength_ = opts.dataLabel === false ? 0 : getPieTextMaxLength(seriesMA);
+ }
+
+ switch (type) {
+ case 'word':
+ let wordOption = assign({},{
+ type: 'normal',
+ autoColors: true
+ },opts.extra.word);
+ if(opts.updateData==true || opts.updateData==undefined){
+ opts.chartData.wordCloudData=getWordCloudPoint(opts,wordOption.type);
+ }
+ this.animationInstance = new Animation({
+ timing: 'easeInOut',
+ duration: duration,
+ onProcess: function(process) {
+ context.clearRect(0, 0, opts.width, opts.height);
+ if (opts.rotate) {
+ contextRotate(context, opts);
+ }
+ drawWordCloudDataPoints(series, opts, config, context,process);
+ drawCanvas(opts, context);
+ },
+ onAnimationFinish: function onAnimationFinish() {
+ _this.event.trigger('renderComplete');
+ }
+ });
+ break;
+ case 'map':
+ context.clearRect(0, 0, opts.width, opts.height);
+ drawMapDataPoints(series, opts, config, context);
+ break;
+ case 'funnel':
+ this.animationInstance = new Animation({
+ timing: 'easeInOut',
+ duration: duration,
+ onProcess: function(process) {
+ context.clearRect(0, 0, opts.width, opts.height);
+ if (opts.rotate) {
+ contextRotate(context, opts);
+ }
+ opts.chartData.funnelData = drawFunnelDataPoints(series, opts, config, context, process);
+ drawLegend(opts.series, opts, config, context, opts.chartData);
+ drawToolTipBridge(opts, config, context, process);
+ drawCanvas(opts, context);
+ },
+ onAnimationFinish: function onAnimationFinish() {
+ _this.event.trigger('renderComplete');
+ }
+ });
+ break;
+ case 'line':
+ this.animationInstance = new Animation({
+ timing: 'easeIn',
+ duration: duration,
+ onProcess: function onProcess(process) {
+ context.clearRect(0, 0, opts.width, opts.height);
+ if (opts.rotate) {
+ contextRotate(context, opts);
+ }
+ drawYAxisGrid(categories, opts, config, context);
+ drawXAxis(categories, opts, config, context);
+ var _drawLineDataPoints = drawLineDataPoints(series, opts, config, context, process),
+ xAxisPoints = _drawLineDataPoints.xAxisPoints,
+ calPoints = _drawLineDataPoints.calPoints,
+ eachSpacing = _drawLineDataPoints.eachSpacing;
+ opts.chartData.xAxisPoints = xAxisPoints;
+ opts.chartData.calPoints = calPoints;
+ opts.chartData.eachSpacing = eachSpacing;
+ drawYAxis(series, opts, config, context);
+ if (opts.enableMarkLine !== false && process === 1) {
+ drawMarkLine(opts, config, context);
+ }
+ drawLegend(opts.series, opts, config, context, opts.chartData);
+ drawToolTipBridge(opts, config, context, process, eachSpacing, xAxisPoints);
+ drawCanvas(opts, context);
+
+ },
+ onAnimationFinish: function onAnimationFinish() {
+ _this.event.trigger('renderComplete');
+ }
+ });
+ break;
+ case 'mix':
+ this.animationInstance = new Animation({
+ timing: 'easeIn',
+ duration: duration,
+ onProcess: function onProcess(process) {
+ context.clearRect(0, 0, opts.width, opts.height);
+ if (opts.rotate) {
+ contextRotate(context, opts);
+ }
+ drawYAxisGrid(categories, opts, config, context);
+ drawXAxis(categories, opts, config, context);
+ var _drawMixDataPoints = drawMixDataPoints(series, opts, config, context, process),
+ xAxisPoints = _drawMixDataPoints.xAxisPoints,
+ calPoints = _drawMixDataPoints.calPoints,
+ eachSpacing = _drawMixDataPoints.eachSpacing;
+ opts.chartData.xAxisPoints = xAxisPoints;
+ opts.chartData.calPoints = calPoints;
+ opts.chartData.eachSpacing = eachSpacing;
+ drawYAxis(series, opts, config, context);
+ if (opts.enableMarkLine !== false && process === 1) {
+ drawMarkLine(opts, config, context);
+ }
+ drawLegend(opts.series, opts, config, context, opts.chartData);
+ drawToolTipBridge(opts, config, context, process, eachSpacing, xAxisPoints);
+ drawCanvas(opts, context);
+ },
+ onAnimationFinish: function onAnimationFinish() {
+ _this.event.trigger('renderComplete');
+ }
+ });
+ break;
+ case 'column':
+ this.animationInstance = new Animation({
+ timing: 'easeIn',
+ duration: duration,
+ onProcess: function onProcess(process) {
+ context.clearRect(0, 0, opts.width, opts.height);
+ if (opts.rotate) {
+ contextRotate(context, opts);
+ }
+ drawYAxisGrid(categories, opts, config, context);
+ drawXAxis(categories, opts, config, context);
+ var _drawColumnDataPoints = drawColumnDataPoints(series, opts, config, context, process),
+ xAxisPoints = _drawColumnDataPoints.xAxisPoints,
+ calPoints = _drawColumnDataPoints.calPoints,
+ eachSpacing = _drawColumnDataPoints.eachSpacing;
+ opts.chartData.xAxisPoints = xAxisPoints;
+ opts.chartData.calPoints = calPoints;
+ opts.chartData.eachSpacing = eachSpacing;
+ drawYAxis(series, opts, config, context);
+ if (opts.enableMarkLine !== false && process === 1) {
+ drawMarkLine(opts, config, context);
+ }
+ drawLegend(opts.series, opts, config, context, opts.chartData);
+ drawToolTipBridge(opts, config, context, process, eachSpacing, xAxisPoints);
+ drawCanvas(opts, context);
+ },
+ onAnimationFinish: function onAnimationFinish() {
+ _this.event.trigger('renderComplete');
+ }
+ });
+ break;
+ case 'area':
+ this.animationInstance = new Animation({
+ timing: 'easeIn',
+ duration: duration,
+ onProcess: function onProcess(process) {
+ context.clearRect(0, 0, opts.width, opts.height);
+ if (opts.rotate) {
+ contextRotate(context, opts);
+ }
+ drawYAxisGrid(categories, opts, config, context);
+ drawXAxis(categories, opts, config, context);
+ var _drawAreaDataPoints = drawAreaDataPoints(series, opts, config, context, process),
+ xAxisPoints = _drawAreaDataPoints.xAxisPoints,
+ calPoints = _drawAreaDataPoints.calPoints,
+ eachSpacing = _drawAreaDataPoints.eachSpacing;
+ opts.chartData.xAxisPoints = xAxisPoints;
+ opts.chartData.calPoints = calPoints;
+ opts.chartData.eachSpacing = eachSpacing;
+ drawYAxis(series, opts, config, context);
+ if (opts.enableMarkLine !== false && process === 1) {
+ drawMarkLine(opts, config, context);
+ }
+ drawLegend(opts.series, opts, config, context, opts.chartData);
+ drawToolTipBridge(opts, config, context, process, eachSpacing, xAxisPoints);
+ drawCanvas(opts, context);
+ },
+ onAnimationFinish: function onAnimationFinish() {
+ _this.event.trigger('renderComplete');
+ }
+ });
+ break;
+ case 'ring':
+ case 'pie':
+ this.animationInstance = new Animation({
+ timing: 'easeInOut',
+ duration: duration,
+ onProcess: function onProcess(process) {
+ context.clearRect(0, 0, opts.width, opts.height);
+ if (opts.rotate) {
+ contextRotate(context, opts);
+ }
+ opts.chartData.pieData = drawPieDataPoints(series, opts, config, context, process);
+ drawLegend(opts.series, opts, config, context, opts.chartData);
+ drawToolTipBridge(opts, config, context, process);
+ drawCanvas(opts, context);
+ },
+ onAnimationFinish: function onAnimationFinish() {
+ _this.event.trigger('renderComplete');
+ }
+ });
+ break;
+ case 'rose':
+ this.animationInstance = new Animation({
+ timing: 'easeInOut',
+ duration: duration,
+ onProcess: function onProcess(process) {
+ context.clearRect(0, 0, opts.width, opts.height);
+ if (opts.rotate) {
+ contextRotate(context, opts);
+ }
+ opts.chartData.pieData = drawRoseDataPoints(series, opts, config, context, process);
+ drawLegend(opts.series, opts, config, context, opts.chartData);
+ drawToolTipBridge(opts, config, context, process);
+ drawCanvas(opts, context);
+ },
+ onAnimationFinish: function onAnimationFinish() {
+ _this.event.trigger('renderComplete');
+ }
+ });
+ break;
+ case 'radar':
+ this.animationInstance = new Animation({
+ timing: 'easeInOut',
+ duration: duration,
+ onProcess: function onProcess(process) {
+ context.clearRect(0, 0, opts.width, opts.height);
+ if (opts.rotate) {
+ contextRotate(context, opts);
+ }
+ opts.chartData.radarData = drawRadarDataPoints(series, opts, config, context, process);
+ drawLegend(opts.series, opts, config, context, opts.chartData);
+ drawToolTipBridge(opts, config, context, process);
+ drawCanvas(opts, context);
+ },
+ onAnimationFinish: function onAnimationFinish() {
+ _this.event.trigger('renderComplete');
+ }
+ });
+ break;
+ case 'arcbar':
+ this.animationInstance = new Animation({
+ timing: 'easeInOut',
+ duration: duration,
+ onProcess: function onProcess(process) {
+ context.clearRect(0, 0, opts.width, opts.height);
+ if (opts.rotate) {
+ contextRotate(context, opts);
+ }
+ opts.chartData.arcbarData = drawArcbarDataPoints(series, opts, config, context, process);
+ drawCanvas(opts, context);
+ },
+ onAnimationFinish: function onAnimationFinish() {
+ _this.event.trigger('renderComplete');
+ }
+ });
+ break;
+ case 'gauge':
+ this.animationInstance = new Animation({
+ timing: 'easeInOut',
+ duration: duration,
+ onProcess: function onProcess(process) {
+ context.clearRect(0, 0, opts.width, opts.height);
+ if (opts.rotate) {
+ contextRotate(context, opts);
+ }
+ opts.chartData.gaugeData = drawGaugeDataPoints(categories, series, opts, config, context, process);
+ drawCanvas(opts, context);
+ },
+ onAnimationFinish: function onAnimationFinish() {
+ _this.event.trigger('renderComplete');
+ }
+ });
+ break;
+ case 'candle':
+ this.animationInstance = new Animation({
+ timing: 'easeIn',
+ duration: duration,
+ onProcess: function onProcess(process) {
+ context.clearRect(0, 0, opts.width, opts.height);
+ if (opts.rotate) {
+ contextRotate(context, opts);
+ }
+ drawYAxisGrid(categories, opts, config, context);
+ drawXAxis(categories, opts, config, context);
+ var _drawCandleDataPoints = drawCandleDataPoints(series, seriesMA, opts, config, context, process),
+ xAxisPoints = _drawCandleDataPoints.xAxisPoints,
+ calPoints = _drawCandleDataPoints.calPoints,
+ eachSpacing = _drawCandleDataPoints.eachSpacing;
+ opts.chartData.xAxisPoints = xAxisPoints;
+ opts.chartData.calPoints = calPoints;
+ opts.chartData.eachSpacing = eachSpacing;
+ drawYAxis(series, opts, config, context);
+ if (opts.enableMarkLine !== false && process === 1) {
+ drawMarkLine(opts, config, context);
+ }
+ if (seriesMA) {
+ drawLegend(seriesMA, opts, config, context, opts.chartData);
+ } else {
+ drawLegend(opts.series, opts, config, context, opts.chartData);
+ }
+ drawToolTipBridge(opts, config, context, process, eachSpacing, xAxisPoints);
+ drawCanvas(opts, context);
+ },
+ onAnimationFinish: function onAnimationFinish() {
+ _this.event.trigger('renderComplete');
+ }
+ });
+ break;
+ }
+}
+
+// simple event implement
+
+function Event() {
+ this.events = {};
+}
+
+Event.prototype.addEventListener = function(type, listener) {
+ this.events[type] = this.events[type] || [];
+ this.events[type].push(listener);
+};
+
+Event.prototype.trigger = function() {
+ for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
+ args[_key] = arguments[_key];
+ }
+
+ var type = args[0];
+ var params = args.slice(1);
+ if (!!this.events[type]) {
+ this.events[type].forEach(function(listener) {
+ try {
+ listener.apply(null, params);
+ } catch (e) {
+ console.error(e);
+ }
+ });
+ }
+};
+
+var Charts = function Charts(opts) {
+ opts.pixelRatio = opts.pixelRatio ? opts.pixelRatio : 1;
+ opts.fontSize = opts.fontSize ? opts.fontSize * opts.pixelRatio : 13 * opts.pixelRatio;
+ opts.title = assign({}, opts.title);
+ opts.subtitle = assign({}, opts.subtitle);
+ opts.duration = opts.duration ? opts.duration : 1000;
+ opts.yAxis = assign({}, {
+ data:[],
+ showTitle:false,
+ disabled:false,
+ disableGrid:false,
+ splitNumber:5,
+ gridType: 'solid',
+ dashLength: 4 * opts.pixelRatio,
+ gridColor:'#cccccc',
+ padding:10,
+ fontColor:'#666666'
+ }, opts.yAxis);
+ opts.yAxis.dashLength *= opts.pixelRatio;
+ opts.yAxis.padding *= opts.pixelRatio;
+ opts.xAxis = assign({}, {
+ rotateLabel: false,
+ type: 'calibration',
+ gridType: 'solid',
+ dashLength: 4,
+ scrollAlign: 'left',
+ boundaryGap:'center',
+ axisLine:true,
+ axisLineColor:'#cccccc'
+ }, opts.xAxis);
+ opts.xAxis.dashLength *= opts.pixelRatio;
+ opts.legend = assign({}, {
+ show: true,
+ position: 'bottom',
+ float: 'center',
+ backgroundColor: 'rgba(0,0,0,0)',
+ borderColor: 'rgba(0,0,0,0)',
+ borderWidth: 0,
+ padding: 5,
+ margin: 5,
+ itemGap: 10,
+ fontSize: opts.fontSize,
+ lineHeight: opts.fontSize,
+ fontColor: '#333333',
+ format: {},
+ hiddenColor: '#CECECE'
+ }, opts.legend);
+ opts.legend.borderWidth = opts.legend.borderWidth * opts.pixelRatio;
+ opts.legend.itemGap = opts.legend.itemGap * opts.pixelRatio;
+ opts.legend.padding = opts.legend.padding * opts.pixelRatio;
+ opts.legend.margin = opts.legend.margin * opts.pixelRatio;
+ opts.extra = assign({}, opts.extra);
+ opts.rotate = opts.rotate ? true : false;
+ opts.animation = opts.animation ? true : false;
+ opts.rotate = opts.rotate ? true : false;
+
+ let config$$1 = JSON.parse(JSON.stringify(config));
+ config$$1.colors = opts.colors ? opts.colors : config$$1.colors;
+ config$$1.yAxisTitleWidth = opts.yAxis.disabled !== true && opts.yAxis.title ? config$$1.yAxisTitleWidth : 0;
+ if (opts.type == 'pie' || opts.type == 'ring') {
+ config$$1.pieChartLinePadding = opts.dataLabel === false ? 0 : opts.extra.pie.labelWidth * opts.pixelRatio || config$$1.pieChartLinePadding * opts.pixelRatio;
+ }
+ if (opts.type == 'rose') {
+ config$$1.pieChartLinePadding = opts.dataLabel === false ? 0 : opts.extra.rose.labelWidth * opts.pixelRatio || config$$1.pieChartLinePadding * opts.pixelRatio;
+ }
+ config$$1.pieChartTextPadding = opts.dataLabel === false ? 0 : config$$1.pieChartTextPadding * opts.pixelRatio;
+ config$$1.yAxisSplit = opts.yAxis.splitNumber ? opts.yAxis.splitNumber : config.yAxisSplit;
+
+ //屏幕旋转
+ config$$1.rotate = opts.rotate;
+ if (opts.rotate) {
+ let tempWidth = opts.width;
+ let tempHeight = opts.height;
+ opts.width = tempHeight;
+ opts.height = tempWidth;
+ }
+
+ //适配高分屏
+ opts.padding = opts.padding ? opts.padding : config$$1.padding;
+ for (let i = 0; i < 4; i++) {
+ opts.padding[i] *= opts.pixelRatio;
+ }
+ config$$1.yAxisWidth = config.yAxisWidth * opts.pixelRatio;
+ config$$1.xAxisHeight = config.xAxisHeight * opts.pixelRatio;
+ if (opts.enableScroll && opts.xAxis.scrollShow) {
+ config$$1.xAxisHeight += 6 * opts.pixelRatio;
+ }
+ config$$1.xAxisLineHeight = config.xAxisLineHeight * opts.pixelRatio;
+ config$$1.fontSize = opts.fontSize;
+ config$$1.titleFontSize = config.titleFontSize * opts.pixelRatio;
+ config$$1.subtitleFontSize = config.subtitleFontSize * opts.pixelRatio;
+ config$$1.toolTipPadding = config.toolTipPadding * opts.pixelRatio;
+ config$$1.toolTipLineHeight = config.toolTipLineHeight * opts.pixelRatio;
+ config$$1.columePadding = config.columePadding * opts.pixelRatio;
+ opts.$this = opts.$this ? opts.$this : this;
+
+ this.context = uni.createCanvasContext(opts.canvasId, opts.$this);
+ /* 兼容原生H5
+ this.context = document.getElementById(opts.canvasId).getContext("2d");
+ this.context.setStrokeStyle = function(e){ return this.strokeStyle=e; }
+ this.context.setLineWidth = function(e){ return this.lineWidth=e; }
+ this.context.setLineCap = function(e){ return this.lineCap=e; }
+ this.context.setFontSize = function(e){ return this.font=e+"px sans-serif"; }
+ this.context.setFillStyle = function(e){ return this.fillStyle=e; }
+ this.context.draw = function(){ }
+ */
+
+ opts.chartData = {};
+ this.event = new Event();
+ this.scrollOption = {
+ currentOffset: 0,
+ startTouchX: 0,
+ distance: 0,
+ lastMoveTime: 0
+ };
+
+ this.opts = opts;
+ this.config = config$$1;
+
+ drawCharts.call(this, opts.type, opts, config$$1, this.context);
+};
+
+Charts.prototype.updateData = function() {
+ let data = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
+ this.opts = assign({}, this.opts, data);
+ this.opts.updateData = true;
+ let scrollPosition = data.scrollPosition || 'current';
+ switch (scrollPosition) {
+ case 'current':
+ this.opts._scrollDistance_ = this.scrollOption.currentOffset;
+ break;
+ case 'left':
+ this.opts._scrollDistance_ = 0;
+ this.scrollOption = {
+ currentOffset: 0,
+ startTouchX: 0,
+ distance: 0,
+ lastMoveTime: 0
+ };
+ break;
+ case 'right':
+ let _calYAxisData = calYAxisData(this.opts.series, this.opts, this.config),
+ yAxisWidth = _calYAxisData.yAxisWidth;
+ this.config.yAxisWidth = yAxisWidth;
+ let offsetLeft = 0;
+ let _getXAxisPoints0 = getXAxisPoints(this.opts.categories, this.opts, this.config),
+ xAxisPoints = _getXAxisPoints0.xAxisPoints,
+ startX = _getXAxisPoints0.startX,
+ endX = _getXAxisPoints0.endX,
+ eachSpacing = _getXAxisPoints0.eachSpacing;
+ let totalWidth = eachSpacing * (xAxisPoints.length - 1);
+ let screenWidth = endX - startX;
+ offsetLeft = screenWidth - totalWidth;
+ this.scrollOption = {
+ currentOffset: offsetLeft,
+ startTouchX: offsetLeft,
+ distance: 0,
+ lastMoveTime: 0
+ };
+ this.opts._scrollDistance_ = offsetLeft;
+ break;
+ }
+ drawCharts.call(this, this.opts.type, this.opts, this.config, this.context);
+};
+
+Charts.prototype.zoom = function() {
+ var val = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.opts.xAxis.itemCount;
+ if (this.opts.enableScroll !== true) {
+ console.log('请启用滚动条后使用!')
+ return;
+ }
+ //当前屏幕中间点
+ let centerPoint = Math.round(Math.abs(this.scrollOption.currentOffset) / this.opts.chartData.eachSpacing) + Math.round(
+ this.opts.xAxis.itemCount / 2);
+ this.opts.animation = false;
+ this.opts.xAxis.itemCount = val.itemCount;
+ //重新计算x轴偏移距离
+ let _calYAxisData = calYAxisData(this.opts.series, this.opts, this.config),
+ yAxisWidth = _calYAxisData.yAxisWidth;
+ this.config.yAxisWidth = yAxisWidth;
+ let offsetLeft = 0;
+ let _getXAxisPoints0 = getXAxisPoints(this.opts.categories, this.opts, this.config),
+ xAxisPoints = _getXAxisPoints0.xAxisPoints,
+ startX = _getXAxisPoints0.startX,
+ endX = _getXAxisPoints0.endX,
+ eachSpacing = _getXAxisPoints0.eachSpacing;
+ let centerLeft = eachSpacing * centerPoint;
+ let screenWidth = endX - startX;
+ let MaxLeft = screenWidth - eachSpacing * (xAxisPoints.length - 1);
+ offsetLeft = screenWidth / 2 - centerLeft;
+ if (offsetLeft > 0) {
+ offsetLeft = 0;
+ }
+ if (offsetLeft < MaxLeft) {
+ offsetLeft = MaxLeft;
+ }
+ this.scrollOption = {
+ currentOffset: offsetLeft,
+ startTouchX: offsetLeft,
+ distance: 0,
+ lastMoveTime: 0
+ };
+ this.opts._scrollDistance_ = offsetLeft;
+ drawCharts.call(this, this.opts.type, this.opts, this.config, this.context);
+};
+
+Charts.prototype.stopAnimation = function() {
+ this.animationInstance && this.animationInstance.stop();
+};
+
+Charts.prototype.addEventListener = function(type, listener) {
+ this.event.addEventListener(type, listener);
+};
+
+Charts.prototype.getCurrentDataIndex = function(e) {
+ var touches = null;
+ if (e.changedTouches) {
+ touches = e.changedTouches[0];
+ } else {
+ touches = e.mp.changedTouches[0];
+ }
+ if (touches) {
+ let _touches$ = getTouches(touches, this.opts, e);
+ if (this.opts.type === 'pie' || this.opts.type === 'ring' || this.opts.type === 'rose') {
+ return findPieChartCurrentIndex({
+ x: _touches$.x,
+ y: _touches$.y
+ }, this.opts.chartData.pieData);
+ } else if (this.opts.type === 'radar') {
+ return findRadarChartCurrentIndex({
+ x: _touches$.x,
+ y: _touches$.y
+ }, this.opts.chartData.radarData, this.opts.categories.length);
+ } else if (this.opts.type === 'funnel') {
+ return findFunnelChartCurrentIndex({
+ x: _touches$.x,
+ y: _touches$.y
+ }, this.opts.chartData.funnelData);
+ } else if (this.opts.type === 'map') {
+ return findMapChartCurrentIndex({
+ x: _touches$.x,
+ y: _touches$.y
+ }, this.opts);
+ }else if (this.opts.type === 'word') {
+ return findWordChartCurrentIndex({
+ x: _touches$.x,
+ y: _touches$.y
+ }, this.opts.chartData.wordCloudData);
+ } else {
+ return findCurrentIndex({
+ x: _touches$.x,
+ y: _touches$.y
+ }, this.opts.chartData.calPoints, this.opts, this.config, Math.abs(this.scrollOption.currentOffset));
+ }
+ }
+ return -1;
+};
+
+Charts.prototype.getLegendDataIndex = function(e) {
+ var touches = null;
+ if (e.changedTouches) {
+ touches = e.changedTouches[0];
+ } else {
+ touches = e.mp.changedTouches[0];
+ }
+ if (touches) {
+ let _touches$ = getTouches(touches, this.opts, e);
+ return findLegendIndex({
+ x: _touches$.x,
+ y: _touches$.y
+ }, this.opts.chartData.legendData);
+ }
+ return -1;
+};
+
+Charts.prototype.touchLegend = function(e) {
+ var option = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
+ var touches = null;
+ if (e.changedTouches) {
+ touches = e.changedTouches[0];
+ } else {
+ touches = e.mp.changedTouches[0];
+ }
+ if (touches) {
+ var _touches$ = getTouches(touches, this.opts, e);
+ var index = this.getLegendDataIndex(e);
+ if (index >= 0) {
+ this.opts.series[index].show = !this.opts.series[index].show;
+ this.opts.animation = option.animation ? true : false;
+ this.opts._scrollDistance_= this.scrollOption.currentOffset;
+ drawCharts.call(this, this.opts.type, this.opts, this.config, this.context);
+ }
+ }
+
+};
+
+Charts.prototype.showToolTip = function(e) {
+ var option = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
+ var touches = null;
+ if (e.changedTouches) {
+ touches = e.changedTouches[0];
+ } else {
+ touches = e.mp.changedTouches[0];
+ }
+ if (!touches) {
+ console.log("touchError");
+ }
+ var _touches$ = getTouches(touches, this.opts, e);
+ var currentOffset = this.scrollOption.currentOffset;
+ var opts = assign({}, this.opts, {
+ _scrollDistance_: currentOffset,
+ animation: false
+ });
+ if (this.opts.type === 'line' || this.opts.type === 'area' || this.opts.type === 'column') {
+ var index = option.index==undefined? this.getCurrentDataIndex(e):option.index ;
+ if (index > -1) {
+ var seriesData = getSeriesDataItem(this.opts.series, index);
+ if (seriesData.length !== 0) {
+ var _getToolTipData = getToolTipData(seriesData, this.opts.chartData.calPoints, index, this.opts.categories,option),
+ textList = _getToolTipData.textList,
+ offset = _getToolTipData.offset;
+ offset.y = _touches$.y;
+ opts.tooltip = {
+ textList: option.textList?option.textList:textList,
+ offset: offset,
+ option: option,
+ index: index
+ };
+ }
+ }
+ drawCharts.call(this, opts.type, opts, this.config, this.context);
+ }
+ if (this.opts.type === 'mix') {
+ var index = option.index==undefined? this.getCurrentDataIndex(e):option.index ;
+ if (index > -1) {
+ var currentOffset = this.scrollOption.currentOffset;
+ var opts = assign({}, this.opts, {
+ _scrollDistance_: currentOffset,
+ animation: false
+ });
+ var seriesData = getSeriesDataItem(this.opts.series, index);
+ if (seriesData.length !== 0) {
+ var _getMixToolTipData = getMixToolTipData(seriesData, this.opts.chartData.calPoints, index, this.opts.categories,option),
+ textList = _getMixToolTipData.textList,
+ offset = _getMixToolTipData.offset;
+ offset.y = _touches$.y;
+ opts.tooltip = {
+ textList: option.textList?option.textList:textList,
+ offset: offset,
+ option: option,
+ index: index
+ };
+ }
+ }
+ drawCharts.call(this, opts.type, opts, this.config, this.context);
+ }
+ if (this.opts.type === 'candle') {
+ var index = option.index==undefined? this.getCurrentDataIndex(e):option.index ;
+ if (index > -1) {
+ var currentOffset = this.scrollOption.currentOffset;
+ var opts = assign({}, this.opts, {
+ _scrollDistance_: currentOffset,
+ animation: false
+ });
+ var seriesData = getSeriesDataItem(this.opts.series, index);
+ if (seriesData.length !== 0) {
+ var _getToolTipData = getCandleToolTipData(this.opts.series[0].data, seriesData, this.opts.chartData.calPoints,
+ index, this.opts.categories, this.opts.extra.candle, option),
+ textList = _getToolTipData.textList,
+ offset = _getToolTipData.offset;
+ offset.y = _touches$.y;
+ opts.tooltip = {
+ textList: option.textList?option.textList:textList,
+ offset: offset,
+ option: option,
+ index: index
+ };
+ }
+ }
+ drawCharts.call(this, opts.type, opts, this.config, this.context);
+ }
+ if (this.opts.type === 'pie' || this.opts.type === 'ring' || this.opts.type === 'rose'||this.opts.type === 'funnel' ) {
+ var index = option.index==undefined? this.getCurrentDataIndex(e):option.index ;
+ if (index > -1) {
+ var currentOffset = this.scrollOption.currentOffset;
+ var opts = assign({}, this.opts, {
+ _scrollDistance_: currentOffset,
+ animation: false
+ });
+ var seriesData = this.opts._series_[index];
+ var textList = [{
+ text: option.format ? option.format(seriesData) : seriesData.name + ': ' + seriesData.data,
+ color: seriesData.color
+ }];
+ var offset = {
+ x: _touches$.x,
+ y: _touches$.y
+ };
+ opts.tooltip = {
+ textList: option.textList?option.textList:textList,
+ offset: offset,
+ option: option,
+ index: index
+ };
+ }
+ drawCharts.call(this, opts.type, opts, this.config, this.context);
+ }
+ if (this.opts.type === 'map'||this.opts.type === 'word') {
+ var index = option.index==undefined? this.getCurrentDataIndex(e):option.index ;
+ if (index > -1) {
+ var currentOffset = this.scrollOption.currentOffset;
+ var opts = assign({}, this.opts, {
+ _scrollDistance_: currentOffset,
+ animation: false
+ });
+ var seriesData = this.opts._series_[index];
+ var textList = [{
+ text: option.format ? option.format(seriesData) : seriesData.properties.name ,
+ color: seriesData.color
+ }];
+ var offset = {
+ x: _touches$.x,
+ y: _touches$.y
+ };
+ opts.tooltip = {
+ textList: option.textList?option.textList:textList,
+ offset: offset,
+ option: option,
+ index: index
+ };
+ }
+ opts.updateData = false;
+ drawCharts.call(this, opts.type, opts, this.config, this.context);
+ }
+ if (this.opts.type === 'radar') {
+ var index = option.index==undefined? this.getCurrentDataIndex(e):option.index ;
+ if (index > -1) {
+ var currentOffset = this.scrollOption.currentOffset;
+ var opts = assign({}, this.opts, {
+ _scrollDistance_: currentOffset,
+ animation: false
+ });
+ var seriesData = getSeriesDataItem(this.opts.series, index);
+ if (seriesData.length !== 0) {
+ var textList = seriesData.map(function(item) {
+ return {
+ text: option.format ? option.format(item) : item.name + ': ' + item.data,
+ color: item.color
+ };
+ });
+ var offset = {
+ x: _touches$.x,
+ y: _touches$.y
+ };
+ opts.tooltip = {
+ textList: option.textList?option.textList:textList,
+ offset: offset,
+ option: option,
+ index: index
+ };
+ }
+ }
+ drawCharts.call(this, opts.type, opts, this.config, this.context);
+ }
+};
+
+Charts.prototype.translate = function(distance) {
+ this.scrollOption = {
+ currentOffset: distance,
+ startTouchX: distance,
+ distance: 0,
+ lastMoveTime: 0
+ };
+ let opts = assign({}, this.opts, {
+ _scrollDistance_: distance,
+ animation: false
+ });
+ drawCharts.call(this, this.opts.type, opts, this.config, this.context);
+};
+
+Charts.prototype.scrollStart = function(e) {
+ var touches = null;
+ if (e.changedTouches) {
+ touches = e.changedTouches[0];
+ } else {
+ touches = e.mp.changedTouches[0];
+ }
+ var _touches$ = getTouches(touches, this.opts, e);
+ if (touches && this.opts.enableScroll === true) {
+ this.scrollOption.startTouchX = _touches$.x;
+ }
+};
+
+Charts.prototype.scroll = function(e) {
+ if (this.scrollOption.lastMoveTime === 0) {
+ this.scrollOption.lastMoveTime = Date.now();
+ }
+ let Limit = this.opts.extra.touchMoveLimit || 20;
+ let currMoveTime = Date.now();
+ let duration = currMoveTime - this.scrollOption.lastMoveTime;
+ if (duration < Math.floor(1000 / Limit)) return;
+ this.scrollOption.lastMoveTime = currMoveTime;
+ var touches = null;
+ if (e.changedTouches) {
+ touches = e.changedTouches[0];
+ } else {
+ touches = e.mp.changedTouches[0];
+ }
+ if (touches && this.opts.enableScroll === true) {
+ var _touches$ = getTouches(touches, this.opts, e);
+ var _distance;
+ _distance = _touches$.x - this.scrollOption.startTouchX;
+ var currentOffset = this.scrollOption.currentOffset;
+ var validDistance = calValidDistance(this,currentOffset + _distance, this.opts.chartData, this.config, this.opts);
+ this.scrollOption.distance = _distance = validDistance - currentOffset;
+ var opts = assign({}, this.opts, {
+ _scrollDistance_: currentOffset + _distance,
+ animation: false
+ });
+ drawCharts.call(this, opts.type, opts, this.config, this.context);
+ return currentOffset + _distance;
+ }
+};
+
+Charts.prototype.scrollEnd = function(e) {
+ if (this.opts.enableScroll === true) {
+ var _scrollOption = this.scrollOption,
+ currentOffset = _scrollOption.currentOffset,
+ distance = _scrollOption.distance;
+ this.scrollOption.currentOffset = currentOffset + distance;
+ this.scrollOption.distance = 0;
+ }
+};
+if (typeof module === "object" && typeof module.exports === "object") {
+ module.exports = Charts;
+ //export default Charts;//建议使用nodejs的module导出方式,如报错请使用export方式导出
+}
diff --git a/main.js b/main.js
new file mode 100644
index 0000000..64ccb1a
--- /dev/null
+++ b/main.js
@@ -0,0 +1,67 @@
+import Vue from 'vue'
+import App from './App'
+import store from './store'
+import uView from "uview-ui"
+Vue.use(uView)
+
+import util from "./utils/util"; //加载js公共函数
+import constant from "./utils/constant"; //常量
+import config from "./utils/config"; //地址
+import reQuest from "./common/http/" //请求函数
+import MescrollUni from "@/components/mescroll-uni/mescroll-uni.vue";
+
+
+Vue.prototype.$gettqimg = function(url) {
+ return 'https://cs.tour-ma.com/r/cms/www/m/tianqi/' + url + '.png'
+}
+Vue.prototype.$getimg = function(url) {
+ return 'https://cs.tour-ma.com/r/cms/www/m/changshu/' + url
+}
+// Vue.prototype.$getimg = function(url) {
+// return 'https://cs.tour-ma.comww/xcx/img/' + url
+// }
+Vue.prototype.$geturl = function(url) {
+ return 'https://cs.tour-ma.com' + url
+}
+Vue.prototype.$geturl6 = function(url) {
+ return 'https://cs.tour-ma.com/w640' + url
+}
+Vue.prototype.$geturl480 = function(url) {
+ return 'https://cs.tour-ma.com/w480' + url
+}
+Vue.prototype.$geturl4 = function(url) {
+ return 'https://cs.tour-ma.com/wc400' + url
+}
+Vue.prototype.$getpage = function(url) {
+ console.log(url);
+ uni.navigateTo({
+ url: url
+ });
+}
+Vue.prototype.$getTag = function(tags) {
+ if(!tags){return}
+ let arry=tags.split(',').filter(function(e){return e});
+ return arry;
+}
+
+
+Vue.config.productionTip = false
+
+App.mpType = 'app'
+
+Vue.prototype.$constant = constant;
+Vue.prototype.$doGet = reQuest.doGet;
+Vue.prototype.$doPost = reQuest.doPost;
+Vue.prototype.$util = util;
+Vue.prototype.isPlatform = "";//平台判断
+Vue.prototype.isLogin = true;//登录判断
+Vue.prototype.baseImgUrl = config.baseImgUrl;
+Vue.prototype.serverUrl = config.serverUrl;
+
+Vue.component('mescroll-uni', MescrollUni);
+
+const app = new Vue({
+ store,
+ ...App
+})
+app.$mount()
diff --git a/manifest.json b/manifest.json
new file mode 100644
index 0000000..dda1e3f
--- /dev/null
+++ b/manifest.json
@@ -0,0 +1,77 @@
+{
+ "name" : "changshou_xcx",
+ "appid" : "__UNI__60B00B9",
+ "description" : "",
+ "versionName" : "1.0.0",
+ "versionCode" : "100",
+ "transformPx" : false,
+ /* 5+App特有相关 */
+ "app-plus" : {
+ "usingComponents" : true,
+ "nvueStyleCompiler" : "uni-app",
+ "compilerVersion" : 3,
+ "splashscreen" : {
+ "alwaysShowBeforeRender" : true,
+ "waiting" : true,
+ "autoclose" : true,
+ "delay" : 0
+ },
+ /* 模块配置 */
+ "modules" : {},
+ /* 应用发布信息 */
+ "distribute" : {
+ /* android打包配置 */
+ "android" : {
+ "permissions" : [
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ ""
+ ]
+ },
+ /* ios打包配置 */
+ "ios" : {},
+ /* SDK配置 */
+ "sdkConfigs" : {}
+ }
+ },
+ /* 快应用特有相关 */
+ "quickapp" : {},
+ /* 小程序特有相关 */
+ "mp-weixin" : {
+ "appid" : "wx4df5fd9a6a5ea123",
+ "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/other/720sny.vue b/other/720sny.vue
new file mode 100644
index 0000000..67675dc
--- /dev/null
+++ b/other/720sny.vue
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/other/allSearch.vue b/other/allSearch.vue
new file mode 100644
index 0000000..8e22c1d
--- /dev/null
+++ b/other/allSearch.vue
@@ -0,0 +1,351 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ¥
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/other/components/mx-datepicker/mx-datepicker.vue b/other/components/mx-datepicker/mx-datepicker.vue
new file mode 100644
index 0000000..5bb2910
--- /dev/null
+++ b/other/components/mx-datepicker/mx-datepicker.vue
@@ -0,0 +1,937 @@
+
+
+
+
+
+
+
+
+ {{week}}
+
+
+
+
+
+
+ {{date.title}}
+
+ ¥
+ {{date.price}}
+
+
+
+
+
+ {{date.tips}}
+
+
+
+
+
+
+
+
+
+
+
+ {{i<10?'0'+i:i}}时
+
+
+ {{i<10?'0'+i:i}}分
+
+
+ {{i<10?'0'+i:i}}秒
+
+
+
+
+
+
+
+
+
+
+
diff --git a/other/components/tags-list.vue b/other/components/tags-list.vue
new file mode 100644
index 0000000..f53e6a9
--- /dev/null
+++ b/other/components/tags-list.vue
@@ -0,0 +1,54 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/other/consulting.vue b/other/consulting.vue
new file mode 100644
index 0000000..b75c442
--- /dev/null
+++ b/other/consulting.vue
@@ -0,0 +1,340 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{el.name}}
+ {{el.tel}}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/other/detailList.vue b/other/detailList.vue
new file mode 100644
index 0000000..9db53f5
--- /dev/null
+++ b/other/detailList.vue
@@ -0,0 +1,248 @@
+
+
+
+
+
+
+
+
+
+ {{el.title}}
+
+
+
+
+ {{(el.releaseDate).substr(0,19)}}
+
+
+
+
+
+ {{el.ups}}
+
+ {{el.views}}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/other/feiyi.vue b/other/feiyi.vue
new file mode 100644
index 0000000..63ac041
--- /dev/null
+++ b/other/feiyi.vue
@@ -0,0 +1,373 @@
+
+
+
+ 非遗推荐
+ 非遗精选
+
+
+
+
+ {{item.name}}
+
+
+
+
+
+
+ {{ el.title}}
+
+
+
+
+
+
+
+ {{el.cateType}}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/other/festival.vue b/other/festival.vue
new file mode 100644
index 0000000..7162246
--- /dev/null
+++ b/other/festival.vue
@@ -0,0 +1,235 @@
+
+
+
+
+
+
+
+
+
+
+
+ {{ el.title}}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/other/foodCard.vue b/other/foodCard.vue
new file mode 100644
index 0000000..f215528
--- /dev/null
+++ b/other/foodCard.vue
@@ -0,0 +1,305 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{xllist.title }}
+
+
+
+ {{xllist.upsNum}}
+
+
+
+
+
+
+
+
+ {{ xllist.upsNum}}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/other/foodList.vue b/other/foodList.vue
new file mode 100644
index 0000000..9609228
--- /dev/null
+++ b/other/foodList.vue
@@ -0,0 +1,275 @@
+
+
+
+
+
+
+ {{nowdata.name}}
+ {{nowdata.description}}
+
+
+ 特色美食
+
+
+ {{alldata[0].title}}
+
+
+
+
+
+
+
+
+
+
+
+
+ {{el.title}}
+
+
+
+
+
+
+
+
diff --git a/other/gftjedit.vue b/other/gftjedit.vue
new file mode 100644
index 0000000..b60d158
--- /dev/null
+++ b/other/gftjedit.vue
@@ -0,0 +1,376 @@
+
+
+
+
+
+
+
+
+ {{defaultValue}}
+
+
+
+
+ {{browse}}人已浏览
+
+
+
+
+ 登高、漫步、骑行,这个秋日假期给疲惫的身心来一次洗礼,感受山水带来的那份怡然自得吧!
+
+
+ {{feature}}
+
+
+
+
+ D{{el.days}}
+ 出发啦~
+
+
+
+
+
+ 虞山>{{el1.name}}
+ {{el.data.scenic[ind1 - 1].name}}距离{{el.data.scenic[ind1].name}}{{el.data.scenic[ind1].distanceToPreviousScenic}}
+
+
+
+
+
+
+
+ {{el1.name}}
+ 人均预算{{el1.consume}}元
+ 地址:{{el1.address}}
+
+
+
+
+
+
+
+
+
+
+ {{el1.name}}
+ 地址:{{el1.address}}
+
+
+
+
+
+
+
+
+
+
+ {{el1.name}}
+ 地址:{{el1.address}}
+
+
+
+
+
+
+
+
+
+
+ {{el1.name}}
+
+
+
+
+
+
+
+
+
+
+ {{el1.name}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{el.scenicName}}
+ 位于虞山市飞云江北岸的红…
+ 建议游玩1.5小时
+
+
+
+
+
+
+ 已选择{{jdnum}}个景点
+ 确定
+
+
+
+
+
+
+
+
diff --git a/other/gonggjt.vue b/other/gonggjt.vue
new file mode 100644
index 0000000..daef0b5
--- /dev/null
+++ b/other/gonggjt.vue
@@ -0,0 +1,170 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/other/hotel-detail/components/jbxx-page.vue b/other/hotel-detail/components/jbxx-page.vue
new file mode 100644
index 0000000..5d41151
--- /dev/null
+++ b/other/hotel-detail/components/jbxx-page.vue
@@ -0,0 +1,142 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/other/hotel-detail/components/list-page.vue b/other/hotel-detail/components/list-page.vue
new file mode 100644
index 0000000..813bec2
--- /dev/null
+++ b/other/hotel-detail/components/list-page.vue
@@ -0,0 +1,259 @@
+
+
+
+
+ {{ item.name }}
+
+
+
+
+
+ 查看更多
+
+
+
+
+
+
+
diff --git a/other/hotel-detail/components/swiper-page.vue b/other/hotel-detail/components/swiper-page.vue
new file mode 100644
index 0000000..96fa03d
--- /dev/null
+++ b/other/hotel-detail/components/swiper-page.vue
@@ -0,0 +1,118 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/other/hotel-detail/components/tags-list.vue b/other/hotel-detail/components/tags-list.vue
new file mode 100644
index 0000000..bd55476
--- /dev/null
+++ b/other/hotel-detail/components/tags-list.vue
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/other/hotel-detail/components/ydmp-page.vue b/other/hotel-detail/components/ydmp-page.vue
new file mode 100644
index 0000000..6574a70
--- /dev/null
+++ b/other/hotel-detail/components/ydmp-page.vue
@@ -0,0 +1,233 @@
+
+
+
+
+ {{getWeek(1)}} 入住
+ {{range[0]}}
+
+ {{numwan}}晚
+
+ {{getWeek(2)}} 离店
+ {{range[1]}}
+
+
+
+
+
+
+
+ {{item.name}}
+ {{item.roomFacility}}
+
+
+ ¥{{item.price}}
+
+ 政府错峰价
+
+ ¥{{item.sellPrice}}
+
+
+ 预定
+
+
+
+
+
+
+
+
+
diff --git a/other/hotel-detail/hotel-detail.vue b/other/hotel-detail/hotel-detail.vue
new file mode 100644
index 0000000..185da70
--- /dev/null
+++ b/other/hotel-detail/hotel-detail.vue
@@ -0,0 +1,581 @@
+
+
+
+
+
+
+
+
+
+
+ {{ detailInfo.name }}
+
+ {{ detailInfo.level }}星
+
+
+
+
+
+
+
+
+ {{ detailInfo.address || '' }}
+ 距离您的位置{{detailInfo.distance}}
+
+
+
+
+ 地图
+
+
+
+
+
+
+ 基本信息
+
+
+
+
+ 搜周边
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/other/hotel.vue b/other/hotel.vue
new file mode 100644
index 0000000..65a134a
--- /dev/null
+++ b/other/hotel.vue
@@ -0,0 +1,508 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/other/pingjia/pingjia.vue b/other/pingjia/pingjia.vue
new file mode 100644
index 0000000..dd6bfd8
--- /dev/null
+++ b/other/pingjia/pingjia.vue
@@ -0,0 +1,316 @@
+
+
+
+
+
+
+
+ {{datas.name}}
+
+
+
+
+
+
+
+ {{el.name}}
+
+
+
+
+ 提交评价
+
+
+
+
+
+
diff --git a/other/pingjia/pingjiazx.vue b/other/pingjia/pingjiazx.vue
new file mode 100644
index 0000000..a670458
--- /dev/null
+++ b/other/pingjia/pingjiazx.vue
@@ -0,0 +1,308 @@
+
+
+
+
+
+
+
+ {{datas.title}}
+
+
+
+
+
+
+
+ {{el.name}}
+
+
+
+
+ 提交评价
+
+
+
+
+
+
diff --git a/other/public.vue b/other/public.vue
new file mode 100644
index 0000000..07cfdb8
--- /dev/null
+++ b/other/public.vue
@@ -0,0 +1,304 @@
+
+
+
+
+
+
+
+
+
+
+
+ {{ xllist.title }}
+
+
+
+
+ {{ xllist.pubDate }}
+
+
+ {{ xllist.upsNum }}
+
+
+
+
+
+
+
+
+ {{ xllist.upsNum }}
+
+
+
+ {{ xllist.upsNum }}
+
+
+
+
+
+
+
+
diff --git a/other/scenic.vue b/other/scenic.vue
new file mode 100644
index 0000000..f56b974
--- /dev/null
+++ b/other/scenic.vue
@@ -0,0 +1,522 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/other/shusd.vue b/other/shusd.vue
new file mode 100644
index 0000000..9b90fb3
--- /dev/null
+++ b/other/shusd.vue
@@ -0,0 +1,548 @@
+
+
+
+
+ 客流实时数据
+
+
+ {{el.name}}
+
+
+ 票务实时在园
+ {{el.value}}
+
+
+ 最大承载量
+ {{el.max}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/other/theme.vue b/other/theme.vue
new file mode 100644
index 0000000..eca4d5c
--- /dev/null
+++ b/other/theme.vue
@@ -0,0 +1,328 @@
+
+
+
+
+
+
+
+
+
+
+
+ {{ztrj[allind].name}}
+
+
+
+
+ {{el.browse}}人已浏览
+
+
+
+ {{el.journeyName}}
+ {{el.feature}}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/other/tianqi.vue b/other/tianqi.vue
new file mode 100644
index 0000000..9363049
--- /dev/null
+++ b/other/tianqi.vue
@@ -0,0 +1,853 @@
+
+
+
+
+
+
+
+ {{ date1 }}
+
+ {{ date3 }}
+
+
+
+ {{ alldata.now.tmp }}
+ ℃
+
+
+
+
+
+
+ {{ alldata.now.cond_txt }}
+
+
+ 空气质量:
+ {{ alldata.aqi.city.aqi }}
+ 空气{{ alldata.aqi.city.qlty }}
+
+
+
+ 气象预警
+
+
+ {{el.content}}
+
+
+
+
+
+ 24小时天气
+
+
+
+
+
+
+
+ -
+
+ {{el.date}}
+ {{el.title}}
+
+
+
+ {{el.wind_dir}}
+ {{el.wind_sc}}
+
+
+
+
+
+
+
+
+
+
+ -
+
+
+
+
+
+ {{ el.name }}
+ {{ el.data }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/other/travelogue.vue b/other/travelogue.vue
new file mode 100644
index 0000000..cb1779e
--- /dev/null
+++ b/other/travelogue.vue
@@ -0,0 +1,269 @@
+
+
+
+
+
+ 游记攻略
+
+
+
+
+ {{zslist[0].title}}
+ {{zslist[0].description}}
+
+
+
+
+
+
+
+
+
+
+
+ {{el.title}}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/other/virtual.vue b/other/virtual.vue
new file mode 100644
index 0000000..932852f
--- /dev/null
+++ b/other/virtual.vue
@@ -0,0 +1,338 @@
+
+
+
+ {{city}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{el.title}}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages.json b/pages.json
new file mode 100644
index 0000000..1740cda
--- /dev/null
+++ b/pages.json
@@ -0,0 +1,297 @@
+{
+ "pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
+ {
+ "path": "pages/index",
+ "style": {
+ "navigationBarTitleText": "",
+ "navigationStyle": "custom"
+ }
+ },{
+ "path": "pages/fjtcc",
+ "style": {
+ "navigationBarTitleText": "公共服务"
+ // "navigationStyle": "custom"
+ }
+ },{
+ "path": "pages/tab/index/index",
+ "style": {
+ "navigationBarTitleText": "场馆预约"
+ }
+ },{
+ "path": "pages/tab/my/index",
+ "style": {
+ "navigationBarTitleText": "我的",
+ "disableScroll": true,
+ "enablePullDownRefresh": false,
+ "navigationStyle": "custom",
+ "navigationBarTextStyle": "white"
+ }
+ },
+
+ {
+ "path": "pages/login/index",
+ "style": {
+ "navigationBarTitleText": "登录"
+ }
+ },
+ {
+ "path": "pages/search/index",
+ "style": {
+ "navigationBarTitleText": "搜索页面"
+ }
+ },
+ {
+ "path": "pages/map",
+ "style": {
+ "navigationBarTitleText": "夜游虞城"
+ }
+ }, {
+ "path": "pages/daohang",
+ "style": {
+ "navigationBarTitleText": "地图模式"
+ }
+ },
+ {
+ "path": "pages/dydl",
+ "style": {
+ "navigationBarTitleText": "导游导览"
+ }
+ },
+ {
+ "path": "pages/jqDet",
+ "style": {
+ "navigationBarTitleText": "畅游常熟"
+ }
+ }
+ ],
+ "subPackages": [{
+ "root": "other",
+ "pages": [{
+ "path": "tianqi",
+ "style": {
+ "navigationBarTitleText": "天气"
+ }
+ },
+ {
+ "path": "allSearch",
+ "style": {
+ "navigationBarTitleText": "搜索"
+ }
+ },
+ {
+ "path": "foodList",
+ "style": {
+ "navigationBarTitleText": "",
+ "navigationStyle": "custom" //美食列表
+ }
+ },
+ {
+ "path": "foodCard",
+ "style": {
+ "navigationBarTitleText": "详情"
+ }
+ },
+ {
+ "path": "pingjia/pingjiazx",
+ "style": {
+ "navigationBarTitleText": "评价" //内容评价
+ }
+ },
+ {
+ "path": "pingjia/pingjia",
+ "style": {
+ "navigationBarTitleText": "评价"
+ }
+ },
+ {
+ "path": "feiyi",
+ "style": {
+ "navigationBarTitleText": "非遗民俗"
+ }
+ },
+ {
+ "path": "virtual",
+ "style": {
+ "navigationBarTitleText": "",
+ "navigationStyle": "custom" //虚拟游
+ }
+ },
+ {
+ "path": "travelogue",
+ "style": {
+ "navigationBarTitleText": "游记攻略"
+ }
+ },
+ {
+ "path": "scenic",
+ "style": {
+ "navigationBarTitleText": "景区"
+ }
+ },
+ {
+ "path": "hotel",
+ "style": {
+ "navigationBarTitleText": "酒店"
+ }
+ },
+ {
+ "path": "festival",
+ "style": {
+ "navigationBarTitleText": "节庆活动"
+ }
+ },
+ {
+ "path": "theme",
+ "style": {
+ "navigationBarTitleText": "主题线路"
+ }
+ },
+ {
+ "path": "detailList",
+ "style": {
+ "navigationBarTitleText": "新闻"
+ }
+ },
+ {
+ "path": "720sny",
+ "style": {
+ "navigationBarTitleText": "虚拟游"
+ }
+ },
+ {
+ "path": "shusd",
+ "style": {
+ "navigationBarTitleText": "景区舒适度"
+ }
+ },
+ {
+ "path": "gonggjt",
+ "style": {
+ "navigationBarTitleText": "公共交通"
+ }
+ },
+ {
+ "path": "public",
+ "style": {
+ "navigationBarTitleText": "",
+ "navigationStyle": "custom" //新闻详情
+ }
+ },
+ {
+ "path": "hotel-detail/hotel-detail",
+ "style": {
+ "navigationBarTitleText": "",
+ "navigationStyle": "custom"
+ }
+ },
+ {
+ "path": "consulting",
+ "style": {
+ "navigationBarTitleText": "",
+ "navigationStyle": "custom"
+ }
+ },
+ {
+ "path": "gftjedit",
+ "style": {
+ "navigationBarTitleText": "线路详情"
+ }
+ }
+ ]
+ },{
+ "root": "pagescs",
+ "pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
+ {
+ "path": "list/jdmp",
+ "style": {
+ "navigationBarTitleText": "景点门票"
+ }
+ }
+ ]
+ }, {
+ "root": "pages/changguan/",
+ "pages": [{
+ "path": "detail/index",
+ "style": {
+ "navigationBarTitleText": "场馆详情"
+ }
+ }, {
+ "path": "reservation/index",
+ "style": {
+ "navigationBarTitleText": "预约"
+ }
+ }, {
+ "path": "comment/index",
+ "style": {
+ "navigationBarTitleText": "我要评论"
+ }
+ }]
+ }, {
+ "root": "pages/my/",
+ "pages": [{
+ "path": "myActivity/index",
+ "style": {
+ "navigationBarTitleText": "活动报名"
+ }
+ }, {
+ "path": "myReservation/index",
+ "style": {
+ "navigationBarTitleText": "场馆预约"
+ }
+ }, {
+ "path": "myCollect/index",
+ "style": {
+ "navigationBarTitleText": "我的收藏"
+ }
+ }, {
+ "path": "myComment/index",
+ "style": {
+ "navigationBarTitleText": "我的评论"
+ }
+ }]
+ }, {
+ "root": "pages/home/",
+ "pages": []
+ }, {
+ "root": "pages/activity/",
+ "pages": [{
+ "path": "course/index",
+ "style": {
+ "navigationBarTitleText": "活动历程"
+ }
+ }, {
+ "path": "detail/index",
+ "style": {
+ "navigationBarTitleText": "活动详情"
+ }
+ }, {
+ "path": "activity/index",
+ "style": {
+ "navigationBarTitleText": "活动"
+ }
+ }]
+ }],
+ "preloadRule": {
+ "other/tianqi": {
+ "network": "all",
+ "packages": ["other"]
+ }
+ },
+ "permission": {
+ "scope.userLocation": {
+ "desc": "你的位置信息将用于位置接口的效果展示"
+ }
+ },
+ "globalStyle": {
+ "navigationBarTextStyle": "black",
+ "navigationBarTitleText": "uni-app",
+ "navigationBarBackgroundColor": "#F8F8F8",
+ "backgroundColor": "#F8F8F8"
+ },
+ "easycom": {
+ "autoscan": true,
+ "custom": {
+ "^u-(.*)": "@/uview-ui/components/u-$1/u-$1.vue"
+ }
+ }
+}
diff --git a/pages/activity/activity/index.vue b/pages/activity/activity/index.vue
new file mode 100644
index 0000000..d9ae374
--- /dev/null
+++ b/pages/activity/activity/index.vue
@@ -0,0 +1,281 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/activity/course/index.vue b/pages/activity/course/index.vue
new file mode 100644
index 0000000..fed37a3
--- /dev/null
+++ b/pages/activity/course/index.vue
@@ -0,0 +1,295 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ 活动名称:{{ item.Title }}
+
+
+
+
+
+
+
+ 负责人:{{ item.LinkUrl }}
+
+
+
+ 活动地址:{{ item.MContent }}
+
+
+
+ 活动介绍:{{ item.Content }}
+
+
+
+
+
+ 已签到,签到时间:{{ item.qdtime }}
+
+
+
+
+
+ 暂未签到,快去签到吧
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/activity/detail/index.vue b/pages/activity/detail/index.vue
new file mode 100644
index 0000000..94167d2
--- /dev/null
+++ b/pages/activity/detail/index.vue
@@ -0,0 +1,733 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ /
+
+
+
+
+
+
+
+
+ 活动时间:
+
+
+
+
+
+ 收藏
+
+
+
+
+
+
+ 负责人
+ 陈立将
+
+
+
+ 主办方
+ 盛世嘉园
+
+
+ 活动地址:
+
+
+
+ 查看活动历程
+
+
+
+
+ 入选名单
+ /人
+
+
+
+
+
+
+
+
+
+
+
+
+ 活动介绍
+
+
+
+ 为贯彻落实《公共文化服务保障法》、省委省政府《全面实施乡村振兴战略高水平推进农业农村现代化行动计划(2018-2022年)》以及省委办公厅、省政府办公厅《关于推进农村文化礼堂建设的意见》,发挥公共图书馆的服务职能,推动全省农村文化礼堂建设与发展,助力美丽乡村建设,将举办“全民饮茶日活动”
+
+
+
+
+
+
+
+ 报名
+
+
+ 已报名
+
+
+ 报名结束
+
+
+
+ 当前用户进行报名
+
+
+ 姓名
+
+
+
+
+
+ 手机号
+
+
+
+
+
+ 身份证
+
+
+
+
+
+
+ 取消
+ 确定
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/changguan/changguan/index.vue b/pages/changguan/changguan/index.vue
new file mode 100644
index 0000000..8a5671c
--- /dev/null
+++ b/pages/changguan/changguan/index.vue
@@ -0,0 +1,189 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/changguan/comment/index.vue b/pages/changguan/comment/index.vue
new file mode 100644
index 0000000..a995fb9
--- /dev/null
+++ b/pages/changguan/comment/index.vue
@@ -0,0 +1,121 @@
+
+
+
+
+
+
+ 0/300
+
+
+
+ 发布评论
+
+
+
+
+
+
+
+
+
diff --git a/pages/changguan/detail/index.vue b/pages/changguan/detail/index.vue
new file mode 100644
index 0000000..bb4a897
--- /dev/null
+++ b/pages/changguan/detail/index.vue
@@ -0,0 +1,554 @@
+
+
+
+
+
+
+
+
+
+
+ /
+
+
+
+
+
+
+
+ 百人体育馆
+ 常熟市社区活动
+
+
+
+
+
+ 收藏
+
+
+
+
+
+
+ 负责人电话
+
+
+
+
+
+
+ 场馆介绍
+
+
+
+
+ 百人体育馆( Sports
+ Centre)位于浙江省杭州市余杭区,可进行足球、篮球等多种比赛,是现中甲球队浙江绿城队的主场,也是FIFA2007年中国女足世界杯的比赛场地之一。
+
+
+ 干净卫生,基础设施完善
+ 地理位置优越,四周环境独特,景色宜人,交通便利,生活方便,是福州迄今为止保留最完整的一座古典园林...
+
+
+
+
+ 网友评论
+
+ 发表评论
+
+
+
+
+
+
+
+
+
+ 去预约
+
+
+ 无预约时间
+
+
+
+
+
+
+
diff --git a/pages/changguan/reservation/index.vue b/pages/changguan/reservation/index.vue
new file mode 100644
index 0000000..5f8d861
--- /dev/null
+++ b/pages/changguan/reservation/index.vue
@@ -0,0 +1,616 @@
+
+
+
+
+
+
+
+
+ 姓名
+
+
+
+ 联系方式
+
+
+
+ 身份证
+
+
+
+ 团队人数
+
+
+
+ 是否需要讲解
+
+
+
+ 其他需求
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 预约时段:{{item.title}}
+ 预约进度:{{item.currentNum}}/{{item.maxnum}}
+ 点击预约
+
+ ~ 暂无预约时间 ~
+
+
+
+ 开始时间
+
+
+ 请选择
+
+
+
+ 结束时间
+
+
+ 请选择
+
+
+
+ 点击预约
+
+
+
+
+
+
+
+
+
diff --git a/pages/daohang.vue b/pages/daohang.vue
new file mode 100644
index 0000000..b2ca163
--- /dev/null
+++ b/pages/daohang.vue
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
+
diff --git a/pages/dydl.vue b/pages/dydl.vue
new file mode 100644
index 0000000..1da7364
--- /dev/null
+++ b/pages/dydl.vue
@@ -0,0 +1,515 @@
+
+
+
+
+
+
+ 景区
+
+
+
+
+
+ 酒店
+
+
+
+
+
+ 餐饮
+
+
+
+
+
+ 农家乐
+
+
+
+
+
+
+ 娱乐
+
+
+
+
+
+ 民宿
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{nowPoi.name}}
+
+
+
+
+
+
+
+ {{nowPoi.address}}
+ {{nowPoi.content}}
+
+
+
+
+ 导航
+
+
+ 查看详情
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/fjtcc.vue b/pages/fjtcc.vue
new file mode 100644
index 0000000..c3ceac2
--- /dev/null
+++ b/pages/fjtcc.vue
@@ -0,0 +1,236 @@
+
+
+
+ 停车场
+ 厕所
+
+
+
+
+
+
+ {{nowData.name}}
+ {{nowData.address}}
+
+ 导航
+
+
+
+
+
+
+
diff --git a/pages/index.vue b/pages/index.vue
new file mode 100644
index 0000000..8f463ce
--- /dev/null
+++ b/pages/index.vue
@@ -0,0 +1,1431 @@
+
+
+
+
+
+
+
+ {{weather.data.now}} {{weather.data.weather}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{bannerel.title}}
+ {{bannerel.description}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{el.title}}
+
+
+ 查看更多
+
+
+
+
+
+
+
+
+
+
+
+
+ {{el.name}}
+
+
+
+ {{el.name}}
+
+
+
+
+
+
+
+ {{el.name}}
+
+
+
+ {{el.name}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 街巷美食
+ 畅享常熟美味
+
+
+
+
+
+ 导游导览
+ 立即出发
+
+
+
+
+
+
+
+ {{el.name}}
+ {{el.ename}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ztrj[allind].name}}
+
+
+
+
+
+ {{el.browse}}人已浏览
+
+
+
+ {{el.journeyName}}
+
+ {{el.feature}}
+
+
+
+
+ 查看更多
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{el.name}}
+ {{el.des}}
+
+
+
+
+
+ {{el.name}}
+ {{el.des}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{el.name}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/jqDet.vue b/pages/jqDet.vue
new file mode 100644
index 0000000..956b895
--- /dev/null
+++ b/pages/jqDet.vue
@@ -0,0 +1,953 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ showdesname }}
+
+
+
+
+
+
+ 开放时间
+
+
+
+
+ 咨询电话
+
+
+
+
+ 游览时间
+ {{xllist.playPrompt}}
+
+
+
+ 门票价格
+
+
+
+
+ 地址
+
+
+
+
+
+
+ 自驾线路
+
+
+
+
+
+
+
+
+ 优惠政策
+
+
+
+
+
+
+
+
+ 图片集
+
+
+
+
+
+
+
+ 周边推荐
+
+
+
+ -
+
+
+
+
+ {{ztitlewz}}
+
+
+
+ {{el.name}}
+
+ A
+ AA
+ AAA
+ AAAA
+ AAAAA
+
+
+
+
+
+
+
+
+
+ 距:{{el.distanceStr}}
+
+
+
+
+
+
+
+ 评价列表
+
+
+ 暂无评价
+
+
+
+
+
+
+
+
+ {{ el.userName }}
+
+
+ 超赞
+ 不错
+ 好
+ 一般
+ 差
+
+
+
+ {{ el.createTime }}
+
+ {{ el.content }}
+
+
+
+
+
+
+
+ 留下您的评价
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/login/index.vue b/pages/login/index.vue
new file mode 100644
index 0000000..7baacb0
--- /dev/null
+++ b/pages/login/index.vue
@@ -0,0 +1,181 @@
+
+
+
+ 欢迎使用 场馆预约小程序
+ 立即登录,享受优质服务
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/map.vue b/pages/map.vue
new file mode 100644
index 0000000..b9c5f3b
--- /dev/null
+++ b/pages/map.vue
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
diff --git a/pages/my/myActivity/index.vue b/pages/my/myActivity/index.vue
new file mode 100644
index 0000000..78b2a69
--- /dev/null
+++ b/pages/my/myActivity/index.vue
@@ -0,0 +1,260 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/my/myCollect/index.vue b/pages/my/myCollect/index.vue
new file mode 100644
index 0000000..726a493
--- /dev/null
+++ b/pages/my/myCollect/index.vue
@@ -0,0 +1,418 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/my/myComment/index.vue b/pages/my/myComment/index.vue
new file mode 100644
index 0000000..d26ff53
--- /dev/null
+++ b/pages/my/myComment/index.vue
@@ -0,0 +1,314 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/my/myReservation/index.vue b/pages/my/myReservation/index.vue
new file mode 100644
index 0000000..c392bd5
--- /dev/null
+++ b/pages/my/myReservation/index.vue
@@ -0,0 +1,325 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 预约时间:
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/search/index.vue b/pages/search/index.vue
new file mode 100644
index 0000000..c1b8175
--- /dev/null
+++ b/pages/search/index.vue
@@ -0,0 +1,400 @@
+
+
+
+
+
+
+
+ {{ arrays[genderIndex].title }}
+
+
+
+
+
+
+ 搜索
+
+
+
+ 搜索 “”
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/tab/index/index.vue b/pages/tab/index/index.vue
new file mode 100644
index 0000000..6bff921
--- /dev/null
+++ b/pages/tab/index/index.vue
@@ -0,0 +1,186 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/tab/my/index.vue b/pages/tab/my/index.vue
new file mode 100644
index 0000000..39e2cb1
--- /dev/null
+++ b/pages/tab/my/index.vue
@@ -0,0 +1,810 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 签到
+
+
+
+
+ 登录
+ 登录获取更多信息
+
+ 签到
+
+
+
+
+
+ 我的预约
+
+
+
+ 我的收藏
+
+
+
+ 我的评论
+
+
+
+
+ 场馆预约
+
+ 查看更多
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 预约时间:
+
+
+
+
+ ~ 暂无相关数据 ~
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pagescs/list/jdmp.vue b/pagescs/list/jdmp.vue
new file mode 100644
index 0000000..48d48ea
--- /dev/null
+++ b/pagescs/list/jdmp.vue
@@ -0,0 +1,8 @@
+
+
+
+
+
+
diff --git a/static/activity_icon1.png b/static/activity_icon1.png
new file mode 100644
index 0000000..39e9a3c
Binary files /dev/null and b/static/activity_icon1.png differ
diff --git a/static/activity_icon2.png b/static/activity_icon2.png
new file mode 100644
index 0000000..9b5a29d
Binary files /dev/null and b/static/activity_icon2.png differ
diff --git a/static/checked2.png b/static/checked2.png
new file mode 100644
index 0000000..ece40db
Binary files /dev/null and b/static/checked2.png differ
diff --git a/static/close_icon.png b/static/close_icon.png
new file mode 100644
index 0000000..c8d90dd
Binary files /dev/null and b/static/close_icon.png differ
diff --git a/static/collect1.png b/static/collect1.png
new file mode 100644
index 0000000..63fdd36
Binary files /dev/null and b/static/collect1.png differ
diff --git a/static/collect2.png b/static/collect2.png
new file mode 100644
index 0000000..8adf59a
Binary files /dev/null and b/static/collect2.png differ
diff --git a/static/collect_icon.png b/static/collect_icon.png
new file mode 100644
index 0000000..8e8e692
Binary files /dev/null and b/static/collect_icon.png differ
diff --git a/static/comment_icon.png b/static/comment_icon.png
new file mode 100644
index 0000000..0c8f2b8
Binary files /dev/null and b/static/comment_icon.png differ
diff --git a/static/header.png b/static/header.png
new file mode 100644
index 0000000..729b924
Binary files /dev/null and b/static/header.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/static/map_icon.png b/static/map_icon.png
new file mode 100644
index 0000000..a78cc9d
Binary files /dev/null and b/static/map_icon.png differ
diff --git a/static/menus_icon1.png b/static/menus_icon1.png
new file mode 100644
index 0000000..4f88b12
Binary files /dev/null and b/static/menus_icon1.png differ
diff --git a/static/menus_icon2.png b/static/menus_icon2.png
new file mode 100644
index 0000000..91d779a
Binary files /dev/null and b/static/menus_icon2.png differ
diff --git a/static/menus_icon3.png b/static/menus_icon3.png
new file mode 100644
index 0000000..057c6b3
Binary files /dev/null and b/static/menus_icon3.png differ
diff --git a/static/more_arrow.png b/static/more_arrow.png
new file mode 100644
index 0000000..a08bb2e
Binary files /dev/null and b/static/more_arrow.png differ
diff --git a/static/more_arrow2.png b/static/more_arrow2.png
new file mode 100644
index 0000000..96d003a
Binary files /dev/null and b/static/more_arrow2.png differ
diff --git a/static/my_bg.png b/static/my_bg.png
new file mode 100644
index 0000000..d751e67
Binary files /dev/null and b/static/my_bg.png differ
diff --git a/static/news_icon1.png b/static/news_icon1.png
new file mode 100644
index 0000000..c8df175
Binary files /dev/null and b/static/news_icon1.png differ
diff --git a/static/news_icon2.png b/static/news_icon2.png
new file mode 100644
index 0000000..e8845a7
Binary files /dev/null and b/static/news_icon2.png differ
diff --git a/static/news_icon3.png b/static/news_icon3.png
new file mode 100644
index 0000000..7f762e3
Binary files /dev/null and b/static/news_icon3.png differ
diff --git a/static/news_icon4.png b/static/news_icon4.png
new file mode 100644
index 0000000..976dd1b
Binary files /dev/null and b/static/news_icon4.png differ
diff --git a/static/news_icon5.png b/static/news_icon5.png
new file mode 100644
index 0000000..3a19ebb
Binary files /dev/null and b/static/news_icon5.png differ
diff --git a/static/news_icon6.png b/static/news_icon6.png
new file mode 100644
index 0000000..4be066d
Binary files /dev/null and b/static/news_icon6.png differ
diff --git a/static/news_icon7.png b/static/news_icon7.png
new file mode 100644
index 0000000..18149ec
Binary files /dev/null and b/static/news_icon7.png differ
diff --git a/static/people_icon1.png b/static/people_icon1.png
new file mode 100644
index 0000000..de8a8ee
Binary files /dev/null and b/static/people_icon1.png differ
diff --git a/static/people_icon2.png b/static/people_icon2.png
new file mode 100644
index 0000000..b62db06
Binary files /dev/null and b/static/people_icon2.png differ
diff --git a/static/phone.png b/static/phone.png
new file mode 100644
index 0000000..fb1ac28
Binary files /dev/null and b/static/phone.png differ
diff --git a/static/phone_icon.png b/static/phone_icon.png
new file mode 100644
index 0000000..48e7b3a
Binary files /dev/null and b/static/phone_icon.png differ
diff --git a/static/reservation_icon.png b/static/reservation_icon.png
new file mode 100644
index 0000000..8e17ad1
Binary files /dev/null and b/static/reservation_icon.png differ
diff --git a/static/search_icon.png b/static/search_icon.png
new file mode 100644
index 0000000..ba8b42a
Binary files /dev/null and b/static/search_icon.png differ
diff --git a/static/search_icon2.png b/static/search_icon2.png
new file mode 100644
index 0000000..2e05f18
Binary files /dev/null and b/static/search_icon2.png differ
diff --git a/static/share_icon.png b/static/share_icon.png
new file mode 100644
index 0000000..3f7ea76
Binary files /dev/null and b/static/share_icon.png differ
diff --git a/static/time_icon.png b/static/time_icon.png
new file mode 100644
index 0000000..4eb15a3
Binary files /dev/null and b/static/time_icon.png differ
diff --git a/static/wx_icon2.png b/static/wx_icon2.png
new file mode 100644
index 0000000..471e53c
Binary files /dev/null and b/static/wx_icon2.png differ
diff --git a/static/zhouWei-navBar/icon_back_black.png b/static/zhouWei-navBar/icon_back_black.png
new file mode 100644
index 0000000..02895ca
Binary files /dev/null and b/static/zhouWei-navBar/icon_back_black.png differ
diff --git a/static/zhouWei-navBar/icon_back_white.png b/static/zhouWei-navBar/icon_back_white.png
new file mode 100644
index 0000000..6081a2a
Binary files /dev/null and b/static/zhouWei-navBar/icon_back_white.png differ
diff --git a/static/zhouWei-navBar/icon_home_black.png b/static/zhouWei-navBar/icon_home_black.png
new file mode 100644
index 0000000..02895ca
Binary files /dev/null and b/static/zhouWei-navBar/icon_home_black.png differ
diff --git a/static/zhouWei-navBar/wfqy-icon-shouye-hei.png b/static/zhouWei-navBar/wfqy-icon-shouye-hei.png
new file mode 100644
index 0000000..90af4ea
Binary files /dev/null and b/static/zhouWei-navBar/wfqy-icon-shouye-hei.png differ
diff --git a/static/zhouWei-navBar/wfqy-icon-shouye.png b/static/zhouWei-navBar/wfqy-icon-shouye.png
new file mode 100644
index 0000000..749d3c7
Binary files /dev/null and b/static/zhouWei-navBar/wfqy-icon-shouye.png differ
diff --git a/store/getters.js b/store/getters.js
new file mode 100644
index 0000000..7eb110f
--- /dev/null
+++ b/store/getters.js
@@ -0,0 +1,14 @@
+const getters = {
+ navHeight: state => state.navBar.navHeight,
+ capsule: state => state.navBar.capsule,
+ isBottomLine: state => state.navBar.isBottomLine,
+ sessionkey:state => state.navBar.sessionkey,
+ openId:state => state.navBar.openId,
+ isAccount:state => state.navBar.isAccount,
+ isLogin:state => state.navBar.isLogin,
+ lon:state => state.navBar.lon,
+ lat:state => state.navBar.lat,
+ carNo:state => state.navBar.carNo,
+ phone:state => state.navBar.phone
+}
+export default getters
diff --git a/store/index.js b/store/index.js
new file mode 100644
index 0000000..9e195c0
--- /dev/null
+++ b/store/index.js
@@ -0,0 +1,11 @@
+import Vue from "vue"
+import Vuex from 'vuex'
+Vue.use(Vuex)
+import navBar from './modules/navBar'
+import getters from './getters'
+export default new Vuex.Store({
+ modules: {
+ navBar
+ },
+ getters
+})
diff --git a/store/modules/navBar.js b/store/modules/navBar.js
new file mode 100644
index 0000000..0aaa756
--- /dev/null
+++ b/store/modules/navBar.js
@@ -0,0 +1,71 @@
+import web from '@/components/utils/request.js';
+const navBar = {
+ state: {
+ navHeight: 0,
+ capsule: {},
+ isBottomLine: false,
+ sessionkey:'',//用户sessionkey
+ openId:'',//用户openId
+ isAccount:false,//是否注册
+ isLogin:false,//是否登录
+ lon:120.21201,
+ lat:30.2084,
+ carNo:'',
+ phone:''
+ },
+ mutations: {
+ SET_NAVHEIGHT: (state, navHeight) => {
+ state.navHeight = navHeight
+ },
+ SET_CAPSULE: (state, capsule) => {
+ state.capsule = capsule
+ },
+ SET_ISBOTTOMLINE: (state, isBottomLine) => {
+ state.isBottomLine = isBottomLine
+ },
+ SET_SESSIONKEY: (state, sessionkey) => {
+ state.sessionkey = sessionkey
+ },
+ SET_OPENID: (state, openId) => {
+ state.openId = openId
+ },
+ SET_ISACCOUNT: (state, isAccount) => {
+ state.isAccount = isAccount
+ },
+ SET_ISLOGIN: (state, isLogin) => {
+ state.isLogin = isLogin
+ },
+ SET_LON: (state, lon) => {
+ state.lon = lon
+ },
+ SET_LAT: (state, lat) => {
+ state.lat = lat
+ },
+ SET_CARNO: (state, carNo) => {
+ state.carNo = carNo
+ },
+ SET_PHONE: (state, phone) => {
+ state.phone = phone
+ }
+ },
+ actions: {
+ getNavHeight({commit}) {
+ return new Promise(() => {
+ uni.getSystemInfo({
+ success(res) {
+ commit('SET_NAVHEIGHT', res.statusBarHeight + 46)
+ let capsule = uni.getMenuButtonBoundingClientRect()
+ commit('SET_CAPSULE', capsule)
+ }
+ })
+ })
+ },
+ judgingAbnormity({commit}) {
+ return new Promise(() => {
+ const modelsInfo = uni.getSystemInfoSync(); //x及以上的异形屏top为44,非异形屏为20
+ modelsInfo.safeArea.top > 20 ? commit('SET_ISBOTTOMLINE', true) : commit('SET_ISBOTTOMLINE',false)
+ })
+ },
+ }
+}
+export default navBar
diff --git a/uni.scss b/uni.scss
new file mode 100644
index 0000000..2a69aa1
--- /dev/null
+++ b/uni.scss
@@ -0,0 +1,94 @@
+/**
+ * 这里是uni-app内置的常用样式变量
+ *
+ * uni-app 官方扩展插件及插件市场(https://ext.dcloud.net.cn)上很多三方插件均使用了这些样式变量
+ * 如果你是插件开发者,建议你使用scss预处理,并在插件代码中直接使用这些变量(无需 import 这个文件),方便用户通过搭积木的方式开发整体风格一致的App
+ *
+ */
+
+/**
+ * 如果你是App开发者(插件使用者),你可以通过修改这些变量来定制自己的插件主题,实现自定义主题功能
+ *
+ * 如果你的项目同样使用了scss预处理,你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
+ */
+
+/* 颜色变量 */
+@import 'uview-ui/theme.scss';
+$color_main:#3eab2c;
+$color_e5e5e5:#e5e5e5;
+$color_999:#999;
+$color_666:#666;
+$color_fff:#fff;
+$color_black:#010101;
+$color_bg:#f1f3f5;
+$color_green:#0aaf1b;
+$color_light_green:#96de77;
+$color_red:#fa0303;
+$color_blue:#368fee;
+$color_orange:#f99b13;
+$color_111:#111111;
+$color_808080:#808080;
+$color_ccc:#ccc;
+$color_333:#333;
+$color_pink:#f56452;
+
+/* 行为相关颜色 */
+$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/utils/common.js b/utils/common.js
new file mode 100644
index 0000000..5909006
--- /dev/null
+++ b/utils/common.js
@@ -0,0 +1,36 @@
+let that = null;
+module.exports = {
+ currentPage: null,
+ currentPageOptions: {},
+ onLoad: function(e, t) {
+ that = this;
+ that.currentPage = e;
+ that.currentPageOptions = t;
+ that.isPlatformFun();
+ },
+ onShow: function(e) {
+ that.currentPage = e;
+ that.setLogin();
+ },
+ setLogin(){
+ if(!that.currentPage.$util.isLoginCallBack()){
+ that.currentPage.isLogin = false;
+ }else{
+ that.currentPage.isLogin = true;
+ }
+ },
+ isPlatformFun(){
+ // #ifdef H5
+ that.currentPage.isPlatform = "h5";
+ console.log(that.currentPage.isPlatform + "======platform");
+ // #endif
+ // #ifdef APP-PLUS
+ that.currentPage.isPlatform = "app";
+ console.log(that.currentPage.isPlatform + "======platform");
+ // #endif
+ // #ifdef MP-WEIXIN
+ that.currentPage.isPlatform = "wx";
+ console.log(that.currentPage.isPlatform + "======platform");
+ // #endif
+ }
+};
diff --git a/utils/config.js b/utils/config.js
new file mode 100644
index 0000000..3aad0d0
--- /dev/null
+++ b/utils/config.js
@@ -0,0 +1,21 @@
+let baseUrl = "",
+ baseImgUrl = "",
+ serverUrl = "";
+if (process.env.NODE_ENV == "development") {
+ // 开发环境 47.111.93.24:9012,192.168.0.109:6547, 开发地址:http://47.114.46.83:30001/API/ https://cstest.51gugua.com/
+ //http://yltest.51gugua.com https://cstest.51gugua.com/
+
+ baseUrl = "https://cstest.51gugua.com/API/";
+ baseImgUrl = "https://cstest.51gugua.com/";
+ serverUrl = "https://cstest.51gugua.com/";
+} else {
+ // 生产环境
+ baseUrl = "https://cstest.51gugua.com/API/";
+ baseImgUrl = "https://cstest.51gugua.com";
+ serverUrl = "https://cstest.51gugua.com/";
+}
+export default {
+ baseUrl: baseUrl,
+ baseImgUrl: baseImgUrl,
+ serverUrl: serverUrl
+}
diff --git a/utils/constant.js b/utils/constant.js
new file mode 100644
index 0000000..d1731d1
--- /dev/null
+++ b/utils/constant.js
@@ -0,0 +1,3 @@
+module.exports ={
+ LOGIN_INFO:"LOGIN_INFO",//登录信息
+};
\ No newline at end of file
diff --git a/utils/md5.js b/utils/md5.js
new file mode 100644
index 0000000..f5ebdac
--- /dev/null
+++ b/utils/md5.js
@@ -0,0 +1,206 @@
+
+ function safe_add(x, y) {
+ var lsw = (x & 0xFFFF) + (y & 0xFFFF),
+ msw = (x >> 16) + (y >> 16) + (lsw >> 16);
+ return (msw << 16) | (lsw & 0xFFFF);
+ }
+
+ function bit_rol(num, cnt) {
+ return (num << cnt) | (num >>> (32 - cnt));
+ }
+ 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);
+ }
+ function binl_md5(x, len) {
+
+ x[len >> 5] |= 0x80 << (len % 32);
+ x[(((len + 64) >>> 9) << 4) + 14] = len;
+
+ var i, olda, oldb, oldc, oldd,
+ a = 1732584193,
+ b = -271733879,
+ c = -1732584194,
+ d = 271733878;
+
+ for (i = 0; i < x.length; i += 16) {
+ olda = a;
+ oldb = b;
+ oldc = c;
+ oldd = d;
+
+ a = md5_ff(a, b, c, d, x[i], 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], 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], 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], 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 [a, b, c, d];
+ }
+
+ function binl2rstr(input) {
+ var i,
+ output = '';
+ for (i = 0; i < input.length * 32; i += 8) {
+ output += String.fromCharCode((input[i >> 5] >>> (i % 32)) & 0xFF);
+ }
+ return output;
+ }
+ function rstr2binl(input) {
+ var i,
+ output = [];
+ output[(input.length >> 2) - 1] = undefined;
+ for (i = 0; i < output.length; i += 1) {
+ output[i] = 0;
+ }
+ for (i = 0; i < input.length * 8; i += 8) {
+ output[i >> 5] |= (input.charCodeAt(i / 8) & 0xFF) << (i % 32);
+ }
+ return output;
+ }
+
+ function rstr_md5(s) {
+ return binl2rstr(binl_md5(rstr2binl(s), s.length * 8));
+ }
+ function rstr_hmac_md5(key, data) {
+ var i,
+ bkey = rstr2binl(key),
+ ipad = [],
+ opad = [],
+ hash;
+ ipad[15] = opad[15] = undefined;
+ if (bkey.length > 16) {
+ bkey = binl_md5(bkey, key.length * 8);
+ }
+ for (i = 0; i < 16; i += 1) {
+ ipad[i] = bkey[i] ^ 0x36363636;
+ opad[i] = bkey[i] ^ 0x5C5C5C5C;
+ }
+ hash = binl_md5(ipad.concat(rstr2binl(data)), 512 + data.length * 8);
+ return binl2rstr(binl_md5(opad.concat(hash), 512 + 128));
+ }
+
+ function rstr2hex(input) {
+ var hex_tab = '0123456789abcdef',
+ output = '',
+ x,
+ i;
+ for (i = 0; i < input.length; i += 1) {
+ x = input.charCodeAt(i);
+ output += hex_tab.charAt((x >>> 4) & 0x0F) +
+ hex_tab.charAt(x & 0x0F);
+ }
+ return output;
+ }
+ function str2rstr_utf8(input) {
+ return unescape(encodeURIComponent(input));
+ }
+
+ function raw_md5(s) {
+ return rstr_md5(str2rstr_utf8(s));
+ }
+ function hex_md5(s) {
+ return rstr2hex(raw_md5(s));
+ }
+ function raw_hmac_md5(k, d) {
+ return rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d));
+ }
+ function hex_hmac_md5(k, d) {
+ return rstr2hex(raw_hmac_md5(k, d));
+ }
+
+ function md5(string, key, raw) {
+ if (!key) {
+ if (!raw) {
+ return hex_md5(string);
+ }
+ return raw_md5(string);
+ }
+ if (!raw) {
+ return hex_hmac_md5(key, string);
+ }
+ return raw_hmac_md5(key, string);
+ }
+
+
+module.exports={
+ md5:md5
+}
\ No newline at end of file
diff --git a/utils/qqmap-wx-jssdk.min.js b/utils/qqmap-wx-jssdk.min.js
new file mode 100644
index 0000000..8fa1477
--- /dev/null
+++ b/utils/qqmap-wx-jssdk.min.js
@@ -0,0 +1 @@
+var ERROR_CONF = { KEY_ERR: 311, KEY_ERR_MSG: 'key格式错误', PARAM_ERR: 310, PARAM_ERR_MSG: '请求参数信息有误', SYSTEM_ERR: 600, SYSTEM_ERR_MSG: '系统错误', WX_ERR_CODE: 1000, WX_OK_CODE: 200 }; var BASE_URL = 'https://apis.map.qq.com/ws/'; var URL_SEARCH = BASE_URL + 'place/v1/search'; var URL_SUGGESTION = BASE_URL + 'place/v1/suggestion'; var URL_GET_GEOCODER = BASE_URL + 'geocoder/v1/'; var URL_CITY_LIST = BASE_URL + 'district/v1/list'; var URL_AREA_LIST = BASE_URL + 'district/v1/getchildren'; var URL_DISTANCE = BASE_URL + 'distance/v1/'; var URL_DIRECTION = BASE_URL + 'direction/v1/'; var MODE = { driving: 'driving', transit: 'transit' }; var EARTH_RADIUS = 6378136.49; var Utils = { safeAdd(x, y) { var lsw = (x & 0xffff) + (y & 0xffff); var msw = (x >> 16) + (y >> 16) + (lsw >> 16); return (msw << 16) | (lsw & 0xffff) }, bitRotateLeft(num, cnt) { return (num << cnt) | (num >>> (32 - cnt)) }, md5cmn(q, a, b, x, s, t) { return this.safeAdd(this.bitRotateLeft(this.safeAdd(this.safeAdd(a, q), this.safeAdd(x, t)), s), b) }, md5ff(a, b, c, d, x, s, t) { return this.md5cmn((b & c) | (~b & d), a, b, x, s, t) }, md5gg(a, b, c, d, x, s, t) { return this.md5cmn((b & d) | (c & ~d), a, b, x, s, t) }, md5hh(a, b, c, d, x, s, t) { return this.md5cmn(b ^ c ^ d, a, b, x, s, t) }, md5ii(a, b, c, d, x, s, t) { return this.md5cmn(c ^ (b | ~d), a, b, x, s, t) }, binlMD5(x, len) { x[len >> 5] |= 0x80 << (len % 32); x[((len + 64) >>> 9 << 4) + 14] = len; var i; var olda; var oldb; var oldc; var oldd; var a = 1732584193; var b = -271733879; var c = -1732584194; var d = 271733878; for (i = 0; i < x.length; i += 16) { olda = a; oldb = b; oldc = c; oldd = d; a = this.md5ff(a, b, c, d, x[i], 7, -680876936); d = this.md5ff(d, a, b, c, x[i + 1], 12, -389564586); c = this.md5ff(c, d, a, b, x[i + 2], 17, 606105819); b = this.md5ff(b, c, d, a, x[i + 3], 22, -1044525330); a = this.md5ff(a, b, c, d, x[i + 4], 7, -176418897); d = this.md5ff(d, a, b, c, x[i + 5], 12, 1200080426); c = this.md5ff(c, d, a, b, x[i + 6], 17, -1473231341); b = this.md5ff(b, c, d, a, x[i + 7], 22, -45705983); a = this.md5ff(a, b, c, d, x[i + 8], 7, 1770035416); d = this.md5ff(d, a, b, c, x[i + 9], 12, -1958414417); c = this.md5ff(c, d, a, b, x[i + 10], 17, -42063); b = this.md5ff(b, c, d, a, x[i + 11], 22, -1990404162); a = this.md5ff(a, b, c, d, x[i + 12], 7, 1804603682); d = this.md5ff(d, a, b, c, x[i + 13], 12, -40341101); c = this.md5ff(c, d, a, b, x[i + 14], 17, -1502002290); b = this.md5ff(b, c, d, a, x[i + 15], 22, 1236535329); a = this.md5gg(a, b, c, d, x[i + 1], 5, -165796510); d = this.md5gg(d, a, b, c, x[i + 6], 9, -1069501632); c = this.md5gg(c, d, a, b, x[i + 11], 14, 643717713); b = this.md5gg(b, c, d, a, x[i], 20, -373897302); a = this.md5gg(a, b, c, d, x[i + 5], 5, -701558691); d = this.md5gg(d, a, b, c, x[i + 10], 9, 38016083); c = this.md5gg(c, d, a, b, x[i + 15], 14, -660478335); b = this.md5gg(b, c, d, a, x[i + 4], 20, -405537848); a = this.md5gg(a, b, c, d, x[i + 9], 5, 568446438); d = this.md5gg(d, a, b, c, x[i + 14], 9, -1019803690); c = this.md5gg(c, d, a, b, x[i + 3], 14, -187363961); b = this.md5gg(b, c, d, a, x[i + 8], 20, 1163531501); a = this.md5gg(a, b, c, d, x[i + 13], 5, -1444681467); d = this.md5gg(d, a, b, c, x[i + 2], 9, -51403784); c = this.md5gg(c, d, a, b, x[i + 7], 14, 1735328473); b = this.md5gg(b, c, d, a, x[i + 12], 20, -1926607734); a = this.md5hh(a, b, c, d, x[i + 5], 4, -378558); d = this.md5hh(d, a, b, c, x[i + 8], 11, -2022574463); c = this.md5hh(c, d, a, b, x[i + 11], 16, 1839030562); b = this.md5hh(b, c, d, a, x[i + 14], 23, -35309556); a = this.md5hh(a, b, c, d, x[i + 1], 4, -1530992060); d = this.md5hh(d, a, b, c, x[i + 4], 11, 1272893353); c = this.md5hh(c, d, a, b, x[i + 7], 16, -155497632); b = this.md5hh(b, c, d, a, x[i + 10], 23, -1094730640); a = this.md5hh(a, b, c, d, x[i + 13], 4, 681279174); d = this.md5hh(d, a, b, c, x[i], 11, -358537222); c = this.md5hh(c, d, a, b, x[i + 3], 16, -722521979); b = this.md5hh(b, c, d, a, x[i + 6], 23, 76029189); a = this.md5hh(a, b, c, d, x[i + 9], 4, -640364487); d = this.md5hh(d, a, b, c, x[i + 12], 11, -421815835); c = this.md5hh(c, d, a, b, x[i + 15], 16, 530742520); b = this.md5hh(b, c, d, a, x[i + 2], 23, -995338651); a = this.md5ii(a, b, c, d, x[i], 6, -198630844); d = this.md5ii(d, a, b, c, x[i + 7], 10, 1126891415); c = this.md5ii(c, d, a, b, x[i + 14], 15, -1416354905); b = this.md5ii(b, c, d, a, x[i + 5], 21, -57434055); a = this.md5ii(a, b, c, d, x[i + 12], 6, 1700485571); d = this.md5ii(d, a, b, c, x[i + 3], 10, -1894986606); c = this.md5ii(c, d, a, b, x[i + 10], 15, -1051523); b = this.md5ii(b, c, d, a, x[i + 1], 21, -2054922799); a = this.md5ii(a, b, c, d, x[i + 8], 6, 1873313359); d = this.md5ii(d, a, b, c, x[i + 15], 10, -30611744); c = this.md5ii(c, d, a, b, x[i + 6], 15, -1560198380); b = this.md5ii(b, c, d, a, x[i + 13], 21, 1309151649); a = this.md5ii(a, b, c, d, x[i + 4], 6, -145523070); d = this.md5ii(d, a, b, c, x[i + 11], 10, -1120210379); c = this.md5ii(c, d, a, b, x[i + 2], 15, 718787259); b = this.md5ii(b, c, d, a, x[i + 9], 21, -343485551); a = this.safeAdd(a, olda); b = this.safeAdd(b, oldb); c = this.safeAdd(c, oldc); d = this.safeAdd(d, oldd) } return [a, b, c, d] }, binl2rstr(input) { var i; var output = ''; var length32 = input.length * 32; for (i = 0; i < length32; i += 8) { output += String.fromCharCode((input[i >> 5] >>> (i % 32)) & 0xff) } return output }, rstr2binl(input) { var i; var output = []; output[(input.length >> 2) - 1] = undefined; for (i = 0; i < output.length; i += 1) { output[i] = 0 } var length8 = input.length * 8; for (i = 0; i < length8; i += 8) { output[i >> 5] |= (input.charCodeAt(i / 8) & 0xff) << (i % 32) } return output }, rstrMD5(s) { return this.binl2rstr(this.binlMD5(this.rstr2binl(s), s.length * 8)) }, rstrHMACMD5(key, data) { var i; var bkey = this.rstr2binl(key); var ipad = []; var opad = []; var hash; ipad[15] = opad[15] = undefined; if (bkey.length > 16) { bkey = this.binlMD5(bkey, key.length * 8) } for (i = 0; i < 16; i += 1) { ipad[i] = bkey[i] ^ 0x36363636; opad[i] = bkey[i] ^ 0x5c5c5c5c } hash = this.binlMD5(ipad.concat(this.rstr2binl(data)), 512 + data.length * 8); return this.binl2rstr(this.binlMD5(opad.concat(hash), 512 + 128)) }, rstr2hex(input) { var hexTab = '0123456789abcdef'; var output = ''; var x; var i; for (i = 0; i < input.length; i += 1) { x = input.charCodeAt(i); output += hexTab.charAt((x >>> 4) & 0x0f) + hexTab.charAt(x & 0x0f) } return output }, str2rstrUTF8(input) { return unescape(encodeURIComponent(input)) }, rawMD5(s) { return this.rstrMD5(this.str2rstrUTF8(s)) }, hexMD5(s) { return this.rstr2hex(this.rawMD5(s)) }, rawHMACMD5(k, d) { return this.rstrHMACMD5(this.str2rstrUTF8(k), str2rstrUTF8(d)) }, hexHMACMD5(k, d) { return this.rstr2hex(this.rawHMACMD5(k, d)) }, md5(string, key, raw) { if (!key) { if (!raw) { return this.hexMD5(string) } return this.rawMD5(string) } if (!raw) { return this.hexHMACMD5(key, string) } return this.rawHMACMD5(key, string) }, getSig(requestParam, sk, feature, mode) { var sig = null; var requestArr = []; Object.keys(requestParam).sort().forEach(function (key) { requestArr.push(key + '=' + requestParam[key]) }); if (feature == 'search') { sig = '/ws/place/v1/search?' + requestArr.join('&') + sk } if (feature == 'suggest') { sig = '/ws/place/v1/suggestion?' + requestArr.join('&') + sk } if (feature == 'reverseGeocoder') { sig = '/ws/geocoder/v1/?' + requestArr.join('&') + sk } if (feature == 'geocoder') { sig = '/ws/geocoder/v1/?' + requestArr.join('&') + sk } if (feature == 'getCityList') { sig = '/ws/district/v1/list?' + requestArr.join('&') + sk } if (feature == 'getDistrictByCityId') { sig = '/ws/district/v1/getchildren?' + requestArr.join('&') + sk } if (feature == 'calculateDistance') { sig = '/ws/distance/v1/?' + requestArr.join('&') + sk } if (feature == 'direction') { sig = '/ws/direction/v1/' + mode + '?' + requestArr.join('&') + sk } sig = this.md5(sig); return sig }, location2query(data) { if (typeof data == 'string') { return data } var query = ''; for (var i = 0; i < data.length; i++) { var d = data[i]; if (!!query) { query += ';' } if (d.location) { query = query + d.location.lat + ',' + d.location.lng } if (d.latitude && d.longitude) { query = query + d.latitude + ',' + d.longitude } } return query }, rad(d) { return d * Math.PI / 180.0 }, getEndLocation(location) { var to = location.split(';'); var endLocation = []; for (var i = 0; i < to.length; i++) { endLocation.push({ lat: parseFloat(to[i].split(',')[0]), lng: parseFloat(to[i].split(',')[1]) }) } return endLocation }, getDistance(latFrom, lngFrom, latTo, lngTo) { var radLatFrom = this.rad(latFrom); var radLatTo = this.rad(latTo); var a = radLatFrom - radLatTo; var b = this.rad(lngFrom) - this.rad(lngTo); var distance = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) + Math.cos(radLatFrom) * Math.cos(radLatTo) * Math.pow(Math.sin(b / 2), 2))); distance = distance * EARTH_RADIUS; distance = Math.round(distance * 10000) / 10000; return parseFloat(distance.toFixed(0)) }, getWXLocation(success, fail, complete) { wx.getLocation({ type: 'gcj02', success: success, fail: fail, complete: complete }) }, getLocationParam(location) { if (typeof location == 'string') { var locationArr = location.split(','); if (locationArr.length === 2) { location = { latitude: location.split(',')[0], longitude: location.split(',')[1] } } else { location = {} } } return location }, polyfillParam(param) { param.success = param.success || function () { }; param.fail = param.fail || function () { }; param.complete = param.complete || function () { } }, checkParamKeyEmpty(param, key) { if (!param[key]) { var errconf = this.buildErrorConfig(ERROR_CONF.PARAM_ERR, ERROR_CONF.PARAM_ERR_MSG + key + '参数格式有误'); param.fail(errconf); param.complete(errconf); return true } return false }, checkKeyword(param) { return !this.checkParamKeyEmpty(param, 'keyword') }, checkLocation(param) { var location = this.getLocationParam(param.location); if (!location || !location.latitude || !location.longitude) { var errconf = this.buildErrorConfig(ERROR_CONF.PARAM_ERR, ERROR_CONF.PARAM_ERR_MSG + ' location参数格式有误'); param.fail(errconf); param.complete(errconf); return false } return true }, buildErrorConfig(errCode, errMsg) { return { status: errCode, message: errMsg } }, handleData(param, data, feature) { if (feature == 'search') { var searchResult = data.data; var searchSimplify = []; for (var i = 0; i < searchResult.length; i++) { searchSimplify.push({ id: searchResult[i].id || null, title: searchResult[i].title || null, latitude: searchResult[i].location && searchResult[i].location.lat || null, longitude: searchResult[i].location && searchResult[i].location.lng || null, address: searchResult[i].address || null, category: searchResult[i].category || null, tel: searchResult[i].tel || null, adcode: searchResult[i].ad_info && searchResult[i].ad_info.adcode || null, city: searchResult[i].ad_info && searchResult[i].ad_info.city || null, district: searchResult[i].ad_info && searchResult[i].ad_info.district || null, province: searchResult[i].ad_info && searchResult[i].ad_info.province || null }) } param.success(data, { searchResult: searchResult, searchSimplify: searchSimplify }) } else if (feature == 'suggest') { var suggestResult = data.data; var suggestSimplify = []; for (var i = 0; i < suggestResult.length; i++) { suggestSimplify.push({ adcode: suggestResult[i].adcode || null, address: suggestResult[i].address || null, category: suggestResult[i].category || null, city: suggestResult[i].city || null, district: suggestResult[i].district || null, id: suggestResult[i].id || null, latitude: suggestResult[i].location && suggestResult[i].location.lat || null, longitude: suggestResult[i].location && suggestResult[i].location.lng || null, province: suggestResult[i].province || null, title: suggestResult[i].title || null, type: suggestResult[i].type || null }) } param.success(data, { suggestResult: suggestResult, suggestSimplify: suggestSimplify }) } else if (feature == 'reverseGeocoder') { var reverseGeocoderResult = data.result; var reverseGeocoderSimplify = { address: reverseGeocoderResult.address || null, latitude: reverseGeocoderResult.location && reverseGeocoderResult.location.lat || null, longitude: reverseGeocoderResult.location && reverseGeocoderResult.location.lng || null, adcode: reverseGeocoderResult.ad_info && reverseGeocoderResult.ad_info.adcode || null, city: reverseGeocoderResult.address_component && reverseGeocoderResult.address_component.city || null, district: reverseGeocoderResult.address_component && reverseGeocoderResult.address_component.district || null, nation: reverseGeocoderResult.address_component && reverseGeocoderResult.address_component.nation || null, province: reverseGeocoderResult.address_component && reverseGeocoderResult.address_component.province || null, street: reverseGeocoderResult.address_component && reverseGeocoderResult.address_component.street || null, street_number: reverseGeocoderResult.address_component && reverseGeocoderResult.address_component.street_number || null, recommend: reverseGeocoderResult.formatted_addresses && reverseGeocoderResult.formatted_addresses.recommend || null, rough: reverseGeocoderResult.formatted_addresses && reverseGeocoderResult.formatted_addresses.rough || null }; if (reverseGeocoderResult.pois) { var pois = reverseGeocoderResult.pois; var poisSimplify = []; for (var i = 0; i < pois.length; i++) { poisSimplify.push({ id: pois[i].id || null, title: pois[i].title || null, latitude: pois[i].location && pois[i].location.lat || null, longitude: pois[i].location && pois[i].location.lng || null, address: pois[i].address || null, category: pois[i].category || null, adcode: pois[i].ad_info && pois[i].ad_info.adcode || null, city: pois[i].ad_info && pois[i].ad_info.city || null, district: pois[i].ad_info && pois[i].ad_info.district || null, province: pois[i].ad_info && pois[i].ad_info.province || null }) } param.success(data, { reverseGeocoderResult: reverseGeocoderResult, reverseGeocoderSimplify: reverseGeocoderSimplify, pois: pois, poisSimplify: poisSimplify }) } else { param.success(data, { reverseGeocoderResult: reverseGeocoderResult, reverseGeocoderSimplify: reverseGeocoderSimplify }) } } else if (feature == 'geocoder') { var geocoderResult = data.result; var geocoderSimplify = { title: geocoderResult.title || null, latitude: geocoderResult.location && geocoderResult.location.lat || null, longitude: geocoderResult.location && geocoderResult.location.lng || null, adcode: geocoderResult.ad_info && geocoderResult.ad_info.adcode || null, province: geocoderResult.address_components && geocoderResult.address_components.province || null, city: geocoderResult.address_components && geocoderResult.address_components.city || null, district: geocoderResult.address_components && geocoderResult.address_components.district || null, street: geocoderResult.address_components && geocoderResult.address_components.street || null, street_number: geocoderResult.address_components && geocoderResult.address_components.street_number || null, level: geocoderResult.level || null }; param.success(data, { geocoderResult: geocoderResult, geocoderSimplify: geocoderSimplify }) } else if (feature == 'getCityList') { var provinceResult = data.result[0]; var cityResult = data.result[1]; var districtResult = data.result[2]; param.success(data, { provinceResult: provinceResult, cityResult: cityResult, districtResult: districtResult }) } else if (feature == 'getDistrictByCityId') { var districtByCity = data.result[0]; param.success(data, districtByCity) } else if (feature == 'calculateDistance') { var calculateDistanceResult = data.result.elements; var distance = []; for (var i = 0; i < calculateDistanceResult.length; i++) { distance.push(calculateDistanceResult[i].distance) } param.success(data, { calculateDistanceResult: calculateDistanceResult, distance: distance }) } else if (feature == 'direction') { var direction = data.result.routes; param.success(data, direction) } else { param.success(data) } }, buildWxRequestConfig(param, options, feature) { var that = this; options.header = { "content-type": "application/json" }; options.method = 'GET'; options.success = function (res) { var data = res.data; if (data.status === 0) { that.handleData(param, data, feature) } else { param.fail(data) } }; options.fail = function (res) { res.statusCode = ERROR_CONF.WX_ERR_CODE; param.fail(that.buildErrorConfig(ERROR_CONF.WX_ERR_CODE, res.errMsg)) }; options.complete = function (res) { var statusCode = +res.statusCode; switch (statusCode) { case ERROR_CONF.WX_ERR_CODE: { param.complete(that.buildErrorConfig(ERROR_CONF.WX_ERR_CODE, res.errMsg)); break } case ERROR_CONF.WX_OK_CODE: { var data = res.data; if (data.status === 0) { param.complete(data) } else { param.complete(that.buildErrorConfig(data.status, data.message)) } break } default: { param.complete(that.buildErrorConfig(ERROR_CONF.SYSTEM_ERR, ERROR_CONF.SYSTEM_ERR_MSG)) } } }; return options }, locationProcess(param, locationsuccess, locationfail, locationcomplete) { var that = this; locationfail = locationfail || function (res) { res.statusCode = ERROR_CONF.WX_ERR_CODE; param.fail(that.buildErrorConfig(ERROR_CONF.WX_ERR_CODE, res.errMsg)) }; locationcomplete = locationcomplete || function (res) { if (res.statusCode == ERROR_CONF.WX_ERR_CODE) { param.complete(that.buildErrorConfig(ERROR_CONF.WX_ERR_CODE, res.errMsg)) } }; if (!param.location) { that.getWXLocation(locationsuccess, locationfail, locationcomplete) } else if (that.checkLocation(param)) { var location = Utils.getLocationParam(param.location); locationsuccess(location) } } }; class QQMapWX { constructor(options) { if (!options.key) { throw Error('key值不能为空') } this.key = options.key }; search(options) { var that = this; options = options || {}; Utils.polyfillParam(options); if (!Utils.checkKeyword(options)) { return } var requestParam = { keyword: options.keyword, orderby: options.orderby || '_distance', page_size: options.page_size || 10, page_index: options.page_index || 1, output: 'json', key: that.key }; if (options.address_format) { requestParam.address_format = options.address_format } if (options.filter) { requestParam.filter = options.filter } var distance = options.distance || "1000"; var auto_extend = options.auto_extend || 1; var region = null; var rectangle = null; if (options.region) { region = options.region } if (options.rectangle) { rectangle = options.rectangle } var locationsuccess = function (result) { if (region && !rectangle) { requestParam.boundary = "region(" + region + "," + auto_extend + "," + result.latitude + "," + result.longitude + ")"; if (options.sig) { requestParam.sig = Utils.getSig(requestParam, options.sig, 'search') } } else if (rectangle && !region) { requestParam.boundary = "rectangle(" + rectangle + ")"; if (options.sig) { requestParam.sig = Utils.getSig(requestParam, options.sig, 'search') } } else { requestParam.boundary = "nearby(" + result.latitude + "," + result.longitude + "," + distance + "," + auto_extend + ")"; if (options.sig) { requestParam.sig = Utils.getSig(requestParam, options.sig, 'search') } } wx.request(Utils.buildWxRequestConfig(options, { url: URL_SEARCH, data: requestParam }, 'search')) }; Utils.locationProcess(options, locationsuccess) }; getSuggestion(options) { var that = this; options = options || {}; Utils.polyfillParam(options); if (!Utils.checkKeyword(options)) { return } var requestParam = { keyword: options.keyword, region: options.region || '全国', region_fix: options.region_fix || 0, policy: options.policy || 0, page_size: options.page_size || 10, page_index: options.page_index || 1, get_subpois: options.get_subpois || 0, output: 'json', key: that.key }; if (options.address_format) { requestParam.address_format = options.address_format } if (options.filter) { requestParam.filter = options.filter } if (options.location) { var locationsuccess = function (result) { requestParam.location = result.latitude + ',' + result.longitude; if (options.sig) { requestParam.sig = Utils.getSig(requestParam, options.sig, 'suggest') } wx.request(Utils.buildWxRequestConfig(options, { url: URL_SUGGESTION, data: requestParam }, "suggest")) }; Utils.locationProcess(options, locationsuccess) } else { if (options.sig) { requestParam.sig = Utils.getSig(requestParam, options.sig, 'suggest') } wx.request(Utils.buildWxRequestConfig(options, { url: URL_SUGGESTION, data: requestParam }, "suggest")) } }; reverseGeocoder(options) { var that = this; options = options || {}; Utils.polyfillParam(options); var requestParam = { coord_type: options.coord_type || 5, get_poi: options.get_poi || 0, output: 'json', key: that.key }; if (options.poi_options) { requestParam.poi_options = options.poi_options } var locationsuccess = function (result) { requestParam.location = result.latitude + ',' + result.longitude; if (options.sig) { requestParam.sig = Utils.getSig(requestParam, options.sig, 'reverseGeocoder') } wx.request(Utils.buildWxRequestConfig(options, { url: URL_GET_GEOCODER, data: requestParam }, 'reverseGeocoder')) }; Utils.locationProcess(options, locationsuccess) }; geocoder(options) { var that = this; options = options || {}; Utils.polyfillParam(options); if (Utils.checkParamKeyEmpty(options, 'address')) { return } var requestParam = { address: options.address, output: 'json', key: that.key }; if (options.region) { requestParam.region = options.region } if (options.sig) { requestParam.sig = Utils.getSig(requestParam, options.sig, 'geocoder') } wx.request(Utils.buildWxRequestConfig(options, { url: URL_GET_GEOCODER, data: requestParam }, 'geocoder')) }; getCityList(options) { var that = this; options = options || {}; Utils.polyfillParam(options); var requestParam = { output: 'json', key: that.key }; if (options.sig) { requestParam.sig = Utils.getSig(requestParam, options.sig, 'getCityList') } wx.request(Utils.buildWxRequestConfig(options, { url: URL_CITY_LIST, data: requestParam }, 'getCityList')) }; getDistrictByCityId(options) { var that = this; options = options || {}; Utils.polyfillParam(options); if (Utils.checkParamKeyEmpty(options, 'id')) { return } var requestParam = { id: options.id || '', output: 'json', key: that.key }; if (options.sig) { requestParam.sig = Utils.getSig(requestParam, options.sig, 'getDistrictByCityId') } wx.request(Utils.buildWxRequestConfig(options, { url: URL_AREA_LIST, data: requestParam }, 'getDistrictByCityId')) }; calculateDistance(options) { var that = this; options = options || {}; Utils.polyfillParam(options); if (Utils.checkParamKeyEmpty(options, 'to')) { return } var requestParam = { mode: options.mode || 'walking', to: Utils.location2query(options.to), output: 'json', key: that.key }; if (options.from) { options.location = options.from } if (requestParam.mode == 'straight') { var locationsuccess = function (result) { var locationTo = Utils.getEndLocation(requestParam.to); var data = { message: "query ok", result: { elements: [] }, status: 0 }; for (var i = 0; i < locationTo.length; i++) { data.result.elements.push({ distance: Utils.getDistance(result.latitude, result.longitude, locationTo[i].lat, locationTo[i].lng), duration: 0, from: { lat: result.latitude, lng: result.longitude }, to: { lat: locationTo[i].lat, lng: locationTo[i].lng } }) } var calculateResult = data.result.elements; var distanceResult = []; for (var i = 0; i < calculateResult.length; i++) { distanceResult.push(calculateResult[i].distance) } return options.success(data, { calculateResult: calculateResult, distanceResult: distanceResult }) }; Utils.locationProcess(options, locationsuccess) } else { var locationsuccess = function (result) { requestParam.from = result.latitude + ',' + result.longitude; if (options.sig) { requestParam.sig = Utils.getSig(requestParam, options.sig, 'calculateDistance') } wx.request(Utils.buildWxRequestConfig(options, { url: URL_DISTANCE, data: requestParam }, 'calculateDistance')) }; Utils.locationProcess(options, locationsuccess) } }; direction(options) { var that = this; options = options || {}; Utils.polyfillParam(options); if (Utils.checkParamKeyEmpty(options, 'to')) { return } var requestParam = { output: 'json', key: that.key }; if (typeof options.to == 'string') { requestParam.to = options.to } else { requestParam.to = options.to.latitude + ',' + options.to.longitude } var SET_URL_DIRECTION = null; options.mode = options.mode || MODE.driving; SET_URL_DIRECTION = URL_DIRECTION + options.mode; if (options.from) { options.location = options.from } if (options.mode == MODE.driving) { if (options.from_poi) { requestParam.from_poi = options.from_poi } if (options.heading) { requestParam.heading = options.heading } if (options.speed) { requestParam.speed = options.speed } if (options.accuracy) { requestParam.accuracy = options.accuracy } if (options.road_type) { requestParam.road_type = options.road_type } if (options.to_poi) { requestParam.to_poi = options.to_poi } if (options.from_track) { requestParam.from_track = options.from_track } if (options.waypoints) { requestParam.waypoints = options.waypoints } if (options.policy) { requestParam.policy = options.policy } if (options.plate_number) { requestParam.plate_number = options.plate_number } } if (options.mode == MODE.transit) { if (options.departure_time) { requestParam.departure_time = options.departure_time } if (options.policy) { requestParam.policy = options.policy } } var locationsuccess = function (result) { requestParam.from = result.latitude + ',' + result.longitude; if (options.sig) { requestParam.sig = Utils.getSig(requestParam, options.sig, 'direction', options.mode) } wx.request(Utils.buildWxRequestConfig(options, { url: SET_URL_DIRECTION, data: requestParam }, 'direction')) }; Utils.locationProcess(options, locationsuccess) } }; module.exports = QQMapWX;
\ No newline at end of file
diff --git a/utils/util.js b/utils/util.js
new file mode 100644
index 0000000..f23e4ce
--- /dev/null
+++ b/utils/util.js
@@ -0,0 +1,337 @@
+import $reQuest from '@/common/http/' //请求函数
+import $constant from '@/utils/constant' //常量
+/* 计算星期几*/
+function format(format, date) {
+ var Week = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'];
+ var o = {
+ "M+": date.getMonth() + 1,
+ //month
+ "d+": date.getDate(),
+ //day
+ "h+": date.getHours(),
+ //hour
+ "m+": date.getMinutes(),
+ //minute
+ "s+": date.getSeconds(),
+ //second
+ "q+": Math.floor((date.getMonth() + 3) / 3),
+ //week
+ 'w': Week[date.getDay()],
+ //quarter
+ "S": date.getMilliseconds() //millisecond
+ };
+
+ if (/(y+)/.test(format)) {
+ format = format.replace(RegExp.$1, (date.getFullYear() + "").substr(4 - RegExp.$1.length));
+ }
+
+ for (var k in o) {
+ if (new RegExp("(" + k + ")").test(format)) {
+ format = format.replace(RegExp.$1, RegExp.$1.length == 1 ? o[k] : ("00" + o[k]).substr(("" + o[k]).length));
+ }
+ }
+ return format;
+}
+
+/* 计算两日期相差的日期年月日等 */
+function dateDiff(interval, objDate2, date) {
+ var d = date,
+ i = {},
+ t = d.getTime(),
+ t2 = objDate2.getTime();
+ i['y'] = objDate2.getFullYear() - d.getFullYear();
+ i['q'] = i['y'] * 4 + Math.floor(objDate2.getMonth() / 4) - Math.floor(d.getMonth() / 4);
+ i['m'] = i['y'] * 12 + objDate2.getMonth() - d.getMonth();
+ i['ms'] = objDate2.getTime() - d.getTime();
+ i['w'] = Math.floor((t2 + 345600000) / (604800000)) - Math.floor((t + 345600000) / (604800000));
+ i['d'] = Math.floor(t2 / 86400000) - Math.floor(t / 86400000);
+ i['h'] = Math.floor(t2 / 3600000) - Math.floor(t / 3600000);
+ i['n'] = Math.floor(t2 / 60000) - Math.floor(t / 60000);
+ i['s'] = Math.floor(t2 / 1000) - Math.floor(t / 1000);
+ return i[interval];
+}
+
+/* 得到日期年月日等加数字后的日期 */
+function dateAdd(interval, number, date) {
+ number = parseInt(number);
+ var dtTmp = date;
+ switch (interval) {
+ case 's':
+ return new Date(Date.parse(dtTmp) + (1000 * number));
+
+ case 'n':
+ return new Date(Date.parse(dtTmp) + (60000 * number));
+
+ case 'h':
+ return new Date(Date.parse(dtTmp) + (3600000 * number));
+
+ case 'd':
+ return new Date(Date.parse(dtTmp) + (86400000 * number));
+
+ case 'w':
+ return new Date(Date.parse(dtTmp) + ((86400000 * 7) * number));
+
+ case 'q':
+ return new Date(dtTmp.getFullYear(), (dtTmp.getMonth()) + number * 3, dtTmp.getDate(), dtTmp.getHours(),
+ dtTmp.getMinutes(),
+ dtTmp.getSeconds());
+
+ case 'm':
+ return new Date(dtTmp.getFullYear(), (dtTmp.getMonth()) + number, dtTmp.getDate(), dtTmp.getHours(), dtTmp.getMinutes(),
+ dtTmp.getSeconds());
+
+ case 'y':
+ return new Date((dtTmp.getFullYear() + number), dtTmp.getMonth(), dtTmp.getDate(), dtTmp.getHours(), dtTmp.getMinutes(),
+ dtTmp.getSeconds());
+
+ }
+}
+
+//字符串转换成日期
+function strToDate(str, formatStr) {
+ if (!str) {
+ return false;
+ }
+ var date = new Date(str.replace(/-/g, "/").replace(".0", ""));
+ if (formatStr) {
+ return format(formatStr, date);
+ }
+ return date;
+}
+/*特殊string时间格式化*/
+function strDateFormat(str, formatStr) {
+ if (!str) return "";
+ var date = new Date(parseInt(str.substring(6, str.toString().length - 2)));
+ if (formatStr) {
+ return format(formatStr, date);
+ }
+ return date;
+}
+
+function showToast(text, time) {
+ let duration = 2500;
+ let title = "请填写提法语";
+ if (time) {
+ duration = time;
+ }
+ if (text) {
+ title = text;
+ }
+ uni.showToast({
+ title: title,
+ icon: 'none',
+ duration: duration,
+ mask: true
+ })
+}
+/** 手机号码验证*/
+function isPhone(mobile) {
+ if (/^[0-9]{11}$/.test(mobile) || /^[0-9]{10}$/.test(mobile)) {
+ return true;
+ }
+ return false;
+}
+/** 退出登录*/
+function loginOut() {
+ uni.clearStorageSync();
+ uni.switchTab({
+ url: "/pages/tab/index/index",
+ success() {
+ showToast("退登成功");
+ }
+ })
+}
+/** 保留两位数*/
+function toFixedFun(num) {
+ if (!num) {
+ return "";
+ }
+ return num.toFixed(2);
+}
+
+function isJson(obj) {
+ let isjson = typeof(obj) == "object" && Object.prototype.toString.call(obj).toLowerCase() == "[object object]" && !
+ obj.length;
+ return isjson;
+}
+
+function contains(str, arr) {
+ for (var i = 0; i < arr; i++) {
+ if (str.indexOf(arr[i]) > -1) {
+ return true;
+ }
+ }
+ return false;
+}
+
+function isEmail(email) {
+ var reg = /^([a-zA-Z]|[0-9])(\w|\-)+@[a-zA-Z0-9]+\.([a-zA-Z]{2,4})$/;
+ if (reg.test(email)) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+function callPhone(num) {
+ if(!num){
+ return;
+ }
+ uni.makePhoneCall({
+ phoneNumber: num
+ });
+}
+
+function isLogin() {
+ let loginInfo = uni.getStorageSync($constant.LOGIN_INFO);
+ if (loginInfo && loginInfo.hasPhone) {
+ return true;
+ }
+ return false;
+}
+
+function getLoginInfo() {
+ let loginInfo = uni.getStorageSync($constant.LOGIN_INFO);
+ return loginInfo;
+}
+
+
+function setUserInfo(data, callback) {
+ let loginInfo = uni.getStorageSync($constant.LOGIN_INFO);
+ if (loginInfo && loginInfo.openid) {
+ callback && callback(loginInfo);
+ return;
+ }
+ if (data.detail.errMsg == "getUserInfo:ok") {
+ let userInfo = data.detail.userInfo;
+ uni.login({
+ success(res) {
+ if (res.code) {
+ var obj = {
+ js_code: res.code,
+ mod: "getLogin",
+ nickName: userInfo.nickName,
+ imgurl: userInfo.avatarUrl,
+ gender: userInfo.gender,
+ province: userInfo.province,
+ city: userInfo.city,
+ country: userInfo.country
+ }
+ $reQuest.doPost("Wx.aspx", obj).then(res => {
+ if (res.data.success) {
+ let body = res.data.data;
+ body.userinfo.hasPhone = body.hasphone == 1 ? true : false;
+ uni.setStorageSync($constant.LOGIN_INFO, body.userinfo);
+ callback && callback(body.userinfo);
+ } else {
+ showToast(res.data.message);
+ }
+ })
+ .catch(err => {
+ console.log('request fail', err);
+ });
+ } else {
+ console.log('登录失败!' + res.errMsg)
+ }
+ }
+ })
+ }
+}
+
+function filterGroup(arrays, subGroupLength) {
+ let index = 0;
+ let newArrays = [];
+ while (index < arrays.length) {
+ newArrays.push(arrays.slice(index, index += subGroupLength));
+ }
+ return newArrays;
+}
+function isCardNo(num) {
+ num = num.toUpperCase();
+ //身份证号码为15位或者18位,15位时全为数字,18位前17位为数字,最后一位是校验位,可能为数字或字符X。
+ if (!(/(^\d{15}$)|(^\d{17}([0-9]|X)$)/.test(num))) {
+ return false;
+ }
+ //校验位按照ISO 7064:1983.MOD 11-2的规定生成,X可以认为是数字10。
+ //下面分别分析出生日期和校验位
+ var len, re;
+ len = num.length;
+ if (len == 15) {
+ re = new RegExp(/^(\d{6})(\d{2})(\d{2})(\d{2})(\d{3})$/);
+ var arrSplit = num.match(re);
+
+ //检查生日日期是否正确
+ var dtmBirth = new Date('19' + arrSplit[2] + '/' + arrSplit[3] + '/' + arrSplit[4]);
+ var bCorrectDay;
+ bCorrectDay = (dtmBirth.getYear() == Number(arrSplit[2])) && ((dtmBirth.getMonth() + 1) == Number(arrSplit[3])) &&
+ (
+ dtmBirth.getDate() == Number(arrSplit[4]));
+ if (!bCorrectDay) {
+ return false;
+ } else {
+ //将15位身份证转成18位
+ //校验位按照ISO 7064:1983.MOD 11-2的规定生成,X可以认为是数字10。
+ var arrInt = new Array(7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2);
+ var arrCh = new Array('1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2');
+ var nTemp = 0,
+ i;
+ num = num.substr(0, 6) + '19' + num.substr(6, num.length - 6);
+ for (i = 0; i < 17; i++) {
+ nTemp += num.substr(i, 1) * arrInt[i];
+ }
+ num += arrCh[nTemp % 11];
+ return true;
+ }
+ }
+ if (len == 18) {
+ re = new RegExp(/^(\d{6})(\d{4})(\d{2})(\d{2})(\d{3})([0-9]|X)$/);
+ var arrSplit = num.match(re);
+
+ //检查生日日期是否正确
+ var dtmBirth = new Date(arrSplit[2] + "/" + arrSplit[3] + "/" + arrSplit[4]);
+ var bCorrectDay;
+ bCorrectDay = (dtmBirth.getFullYear() == Number(arrSplit[2])) && ((dtmBirth.getMonth() + 1) == Number(arrSplit[3])) &&
+ (dtmBirth.getDate() == Number(arrSplit[4]));
+ if (!bCorrectDay) {
+ return false;
+ } else {
+ //检验18位身份证的校验码是否正确。
+ //校验位按照ISO 7064:1983.MOD 11-2的规定生成,X可以认为是数字10。
+ var valnum;
+ var arrInt = new Array(7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2);
+ var arrCh = new Array('1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2');
+ var nTemp = 0,
+ i;
+ for (i = 0; i < 17; i++) {
+ nTemp += num.substr(i, 1) * arrInt[i];
+ }
+ valnum = arrCh[nTemp % 11];
+ if (valnum != num.substr(17, 1)) {
+ return false;
+ }
+ return true;
+ }
+ }
+ return false;
+}
+
+module.exports = {
+ showToast,
+ format,
+ dateDiff,
+ dateAdd,
+ strToDate,
+ strDateFormat,
+ isPhone,
+ loginOut,
+ toFixedFun,
+ isJson,
+ contains,
+ isEmail,
+ callPhone,
+ isLogin,
+ getLoginInfo,
+ setUserInfo,
+ filterGroup,
+ isCardNo
+}
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 @@
+
+
+
+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 @@
+
+
+
+ {{tips.text}}
+
+
+
+ {{item.text}}
+ {{item.subText}}
+
+
+
+
+ {{cancelText}}
+
+
+
+
+
+
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 @@
+
+
+
+
+
+
+
+ {{title}}
+
+
+ {{description}}
+
+
+
+
+
+ {{closeText}}
+
+
+
+
+
+
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 @@
+
+
+
+ {{uText}}
+
+
+
+
+
+
+
+
+
+
+
+
+
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 @@
+
+
+
+
+
+ {{tips}}
+
+
+
+
+
+
+
+
+
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 @@
+
+
+ {{showText}}
+
+
+
+
+
+
\ 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..2b30184
--- /dev/null
+++ b/uview-ui/components/u-calendar/u-calendar.vue
@@ -0,0 +1,639 @@
+
+
+
+
+
+
+
+
+
+
+
+ {{ showTitle }}
+
+
+
+
+
+
+
+
+ {{item}}
+
+
+
+
+
+
+
+
+ {{ index + 1 }}
+
+ {{startText}}
+ {{endText}}
+
+ {{month}}
+
+
+
+ {{mode == 'date' ? activeDate : startDate}}
+ 至{{endDate}}
+
+
+ 确定
+
+
+
+
+
+
+
+
\ No newline at end of file
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 @@
+
+ {}">
+
+
+
+
+ {{ item }}
+
+
+
+
+
+
+ 中
+ /
+ 英
+
+
+
+
+
+
+
+
+
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 @@
+
+
+
+
+
+
+
+ {{ title }}
+
+
+
+
+ {{ subTitle }}
+
+
+
+
+
+
+
+
+
+
+
+
+
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 @@
+
+
+
+ {{title}}
+
+
+
+
+
+
+
+
+
+
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 @@
+
+
+
+
+
+
+
+ {{ title }}
+
+
+
+ {{ label }}
+
+
+
+
+
+ {{ value }}
+
+
+
+
+
+
+
+
+
+
+
+
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 @@
+
+
+
+
+
+ {{percent + '%'}}
+
+
+
+
+
+
+
+
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..3b66bfa
--- /dev/null
+++ b/uview-ui/components/u-collapse-item/u-collapse-item.vue
@@ -0,0 +1,204 @@
+
+
+
+
+
+ {{ title }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
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 @@
+
+
+
+
+
+
+
+
+ {{ item }}
+
+
+
+
+
+
+
+
+
+
+
+
+
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 @@
+
+
+
+
+ {{ d }}
+
+
+
+ {{ separator == 'colon' ? ':' : '天' }}
+
+
+
+ {{ h }}
+
+
+
+ {{ separator == 'colon' ? ':' : '时' }}
+
+
+
+ {{ i }}
+
+
+
+ {{ separator == 'colon' ? ':' : '分' }}
+
+
+
+ {{ s }}
+
+
+
+ 秒
+
+
+
+
+
+
+
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 @@
+
+
+ {{ displayValue }}
+
+
+
+
+
+
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..0cd52e7
--- /dev/null
+++ b/uview-ui/components/u-dropdown-item/u-dropdown-item.vue
@@ -0,0 +1,133 @@
+
+ {}" @tap.stop.prevent="() => {}">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
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..54b6fba
--- /dev/null
+++ b/uview-ui/components/u-dropdown/u-dropdown.vue
@@ -0,0 +1,304 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
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 @@
+
+
+
+
+
+
+
+
+ {{ label }}
+
+
+
+
+
+
+
+
+
+
+
+ {{ errorMessage }}
+
+
+
+
+
+
diff --git a/uview-ui/components/u-form-item/u-form-item.vue b/uview-ui/components/u-form-item/u-form-item.vue
new file mode 100644
index 0000000..d6b8c8b
--- /dev/null
+++ b/uview-ui/components/u-form-item/u-form-item.vue
@@ -0,0 +1,431 @@
+
+
+
+
+
+
+
+
+ *
+
+
+
+
+ {{label}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{validateMessage}}
+
+
+
+
+
+
diff --git a/uview-ui/components/u-form/u-form.vue b/uview-ui/components/u-form/u-form.vue
new file mode 100644
index 0000000..bdbafaf
--- /dev/null
+++ b/uview-ui/components/u-form/u-form.vue
@@ -0,0 +1,134 @@
+
+
+
+
+
+
+
diff --git a/uview-ui/components/u-full-screen/u-full-screen.vue b/uview-ui/components/u-full-screen/u-full-screen.vue
new file mode 100644
index 0000000..4f7e7d9
--- /dev/null
+++ b/uview-ui/components/u-full-screen/u-full-screen.vue
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/uview-ui/components/u-gap/u-gap.vue b/uview-ui/components/u-gap/u-gap.vue
new file mode 100644
index 0000000..6c01f94
--- /dev/null
+++ b/uview-ui/components/u-gap/u-gap.vue
@@ -0,0 +1,54 @@
+
+
+
+
+
+
+
diff --git a/uview-ui/components/u-grid-item/u-grid-item.vue b/uview-ui/components/u-grid-item/u-grid-item.vue
new file mode 100644
index 0000000..0773307
--- /dev/null
+++ b/uview-ui/components/u-grid-item/u-grid-item.vue
@@ -0,0 +1,126 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/uview-ui/components/u-grid/u-grid.vue b/uview-ui/components/u-grid/u-grid.vue
new file mode 100644
index 0000000..6588c06
--- /dev/null
+++ b/uview-ui/components/u-grid/u-grid.vue
@@ -0,0 +1,108 @@
+
+
+
+
+
+
+
diff --git a/uview-ui/components/u-icon/u-icon.vue b/uview-ui/components/u-icon/u-icon.vue
new file mode 100644
index 0000000..db1b019
--- /dev/null
+++ b/uview-ui/components/u-icon/u-icon.vue
@@ -0,0 +1,336 @@
+
+
+
+
+
+
+
+
+ {{ label }}
+
+
+
+
+
+
+
diff --git a/uview-ui/components/u-image/u-image.vue b/uview-ui/components/u-image/u-image.vue
new file mode 100644
index 0000000..c729c3c
--- /dev/null
+++ b/uview-ui/components/u-image/u-image.vue
@@ -0,0 +1,267 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/uview-ui/components/u-index-anchor/u-index-anchor.vue b/uview-ui/components/u-index-anchor/u-index-anchor.vue
new file mode 100644
index 0000000..5038827
--- /dev/null
+++ b/uview-ui/components/u-index-anchor/u-index-anchor.vue
@@ -0,0 +1,89 @@
+
+
+
+
+
+
+
+ {{ index }}
+
+
+
+
+
+
+
+
+
diff --git a/uview-ui/components/u-index-list/u-index-list.vue b/uview-ui/components/u-index-list/u-index-list.vue
new file mode 100644
index 0000000..30fcda0
--- /dev/null
+++ b/uview-ui/components/u-index-list/u-index-list.vue
@@ -0,0 +1,315 @@
+
+
+
+
+
+
+
+ {{indexList[touchmoveIndex]}}
+
+
+
+
+
+
+
+
diff --git a/uview-ui/components/u-input/u-input.vue b/uview-ui/components/u-input/u-input.vue
new file mode 100644
index 0000000..f2aea72
--- /dev/null
+++ b/uview-ui/components/u-input/u-input.vue
@@ -0,0 +1,387 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/uview-ui/components/u-keyboard/u-keyboard.vue b/uview-ui/components/u-keyboard/u-keyboard.vue
new file mode 100644
index 0000000..1904a2b
--- /dev/null
+++ b/uview-ui/components/u-keyboard/u-keyboard.vue
@@ -0,0 +1,217 @@
+
+
+
+
+
+ {{cancelBtn ? cancelText : ''}}
+
+
+ {{tips ? tips : mode == 'number' ? '数字键盘' : mode == 'card' ? '身份证键盘' : '车牌号键盘'}}
+
+
+ {{confirmBtn ? confirmText : ''}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/uview-ui/components/u-lazy-load/u-lazy-load.vue b/uview-ui/components/u-lazy-load/u-lazy-load.vue
new file mode 100644
index 0000000..429a680
--- /dev/null
+++ b/uview-ui/components/u-lazy-load/u-lazy-load.vue
@@ -0,0 +1,244 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/uview-ui/components/u-line-progress/u-line-progress.vue b/uview-ui/components/u-line-progress/u-line-progress.vue
new file mode 100644
index 0000000..77e2da2
--- /dev/null
+++ b/uview-ui/components/u-line-progress/u-line-progress.vue
@@ -0,0 +1,147 @@
+
+
+
+
+
+ {{percent + '%'}}
+
+
+
+
+
+
+
+
diff --git a/uview-ui/components/u-line/u-line.vue b/uview-ui/components/u-line/u-line.vue
new file mode 100644
index 0000000..c56fbc3
--- /dev/null
+++ b/uview-ui/components/u-line/u-line.vue
@@ -0,0 +1,84 @@
+
+
+
+
+
+
+
+
+
diff --git a/uview-ui/components/u-link/u-link.vue b/uview-ui/components/u-link/u-link.vue
new file mode 100644
index 0000000..2dd2a73
--- /dev/null
+++ b/uview-ui/components/u-link/u-link.vue
@@ -0,0 +1,89 @@
+
+
+
+
+
+
+
+
+
diff --git a/uview-ui/components/u-loading-page/u-loading-page.vue b/uview-ui/components/u-loading-page/u-loading-page.vue
new file mode 100644
index 0000000..7e04401
--- /dev/null
+++ b/uview-ui/components/u-loading-page/u-loading-page.vue
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
diff --git a/uview-ui/components/u-loading/u-loading.vue b/uview-ui/components/u-loading/u-loading.vue
new file mode 100644
index 0000000..c747f64
--- /dev/null
+++ b/uview-ui/components/u-loading/u-loading.vue
@@ -0,0 +1,103 @@
+
+
+
+
+
+
+
+
diff --git a/uview-ui/components/u-loadmore/u-loadmore.vue b/uview-ui/components/u-loadmore/u-loadmore.vue
new file mode 100644
index 0000000..6b852a8
--- /dev/null
+++ b/uview-ui/components/u-loadmore/u-loadmore.vue
@@ -0,0 +1,203 @@
+
+
+
+
+
+
+
+
+
+
+ {{ showText }}
+
+
+
+
+
+
+
+
+
diff --git a/uview-ui/components/u-mask/u-mask.vue b/uview-ui/components/u-mask/u-mask.vue
new file mode 100644
index 0000000..0b55d9d
--- /dev/null
+++ b/uview-ui/components/u-mask/u-mask.vue
@@ -0,0 +1,123 @@
+
+ {}" :class="{
+ 'u-mask-zoom': zoom,
+ 'u-mask-show': show
+ }">
+
+
+
+
+
+
+
diff --git a/uview-ui/components/u-message-input/u-message-input.vue b/uview-ui/components/u-message-input/u-message-input.vue
new file mode 100644
index 0000000..41e0719
--- /dev/null
+++ b/uview-ui/components/u-message-input/u-message-input.vue
@@ -0,0 +1,311 @@
+
+
+
+
+
+
+
+
+
+ {{ charArr[index] ? charArr[index] : ''}}
+
+ {{ charArr[index] ? '●' : ''}}
+
+
+
+
+
+
+
+
+
+
diff --git a/uview-ui/components/u-modal/u-modal.vue b/uview-ui/components/u-modal/u-modal.vue
new file mode 100644
index 0000000..ce58113
--- /dev/null
+++ b/uview-ui/components/u-modal/u-modal.vue
@@ -0,0 +1,283 @@
+
+
+
+
+ {{ title }}
+
+
+
+
+ {{ content }}
+
+
+
+
+
+
+
+
+
+
diff --git a/uview-ui/components/u-navbar/u-navbar.vue b/uview-ui/components/u-navbar/u-navbar.vue
new file mode 100644
index 0000000..450242e
--- /dev/null
+++ b/uview-ui/components/u-navbar/u-navbar.vue
@@ -0,0 +1,315 @@
+
+
+
+
+
+
+
+
+
+ {{ backText }}
+
+
+
+ {{ title }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/uview-ui/components/u-no-network/u-no-network.vue b/uview-ui/components/u-no-network/u-no-network.vue
new file mode 100644
index 0000000..51d9f4f
--- /dev/null
+++ b/uview-ui/components/u-no-network/u-no-network.vue
@@ -0,0 +1,233 @@
+
+ {}">
+
+
+
+ {{tips}}
+
+
+
+
+ 请检查网络,或前往设置
+
+
+
+ 重试
+
+
+
+
+
+
+
+
diff --git a/uview-ui/components/u-notice-bar/u-notice-bar.vue b/uview-ui/components/u-notice-bar/u-notice-bar.vue
new file mode 100644
index 0000000..41a6cc4
--- /dev/null
+++ b/uview-ui/components/u-notice-bar/u-notice-bar.vue
@@ -0,0 +1,272 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/uview-ui/components/u-number-box/u-number-box.vue b/uview-ui/components/u-number-box/u-number-box.vue
new file mode 100644
index 0000000..54a679e
--- /dev/null
+++ b/uview-ui/components/u-number-box/u-number-box.vue
@@ -0,0 +1,363 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/uview-ui/components/u-number-keyboard/u-number-keyboard.vue b/uview-ui/components/u-number-keyboard/u-number-keyboard.vue
new file mode 100644
index 0000000..6425a1f
--- /dev/null
+++ b/uview-ui/components/u-number-keyboard/u-number-keyboard.vue
@@ -0,0 +1,158 @@
+
+ {}">
+
+
+ {{ item }}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/uview-ui/components/u-parse/libs/CssHandler.js b/uview-ui/components/u-parse/libs/CssHandler.js
new file mode 100644
index 0000000..75c6015
--- /dev/null
+++ b/uview-ui/components/u-parse/libs/CssHandler.js
@@ -0,0 +1,100 @@
+const cfg = require('./config.js'),
+ isLetter = c => (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
+
+function CssHandler(tagStyle) {
+ var styles = Object.assign(Object.create(null), cfg.userAgentStyles);
+ for (var item in tagStyle)
+ styles[item] = (styles[item] ? styles[item] + ';' : '') + tagStyle[item];
+ this.styles = styles;
+}
+CssHandler.prototype.getStyle = function(data) {
+ this.styles = new parser(data, this.styles).parse();
+}
+CssHandler.prototype.match = function(name, attrs) {
+ var tmp, matched = (tmp = this.styles[name]) ? tmp + ';' : '';
+ if (attrs.class) {
+ var items = attrs.class.split(' ');
+ for (var i = 0, item; item = items[i]; i++)
+ if (tmp = this.styles['.' + item])
+ matched += tmp + ';';
+ }
+ if (tmp = this.styles['#' + attrs.id])
+ matched += tmp + ';';
+ return matched;
+}
+module.exports = CssHandler;
+
+function parser(data, init) {
+ this.data = data;
+ this.floor = 0;
+ this.i = 0;
+ this.list = [];
+ this.res = init;
+ this.state = this.Space;
+}
+parser.prototype.parse = function() {
+ for (var c; c = this.data[this.i]; this.i++)
+ this.state(c);
+ return this.res;
+}
+parser.prototype.section = function() {
+ return this.data.substring(this.start, this.i);
+}
+// 状态机
+parser.prototype.Space = function(c) {
+ if (c == '.' || c == '#' || isLetter(c)) {
+ this.start = this.i;
+ this.state = this.Name;
+ } else if (c == '/' && this.data[this.i + 1] == '*')
+ this.Comment();
+ else if (!cfg.blankChar[c] && c != ';')
+ this.state = this.Ignore;
+}
+parser.prototype.Comment = function() {
+ this.i = this.data.indexOf('*/', this.i) + 1;
+ if (!this.i) this.i = this.data.length;
+ this.state = this.Space;
+}
+parser.prototype.Ignore = function(c) {
+ if (c == '{') this.floor++;
+ else if (c == '}' && !--this.floor) {
+ this.list = [];
+ this.state = this.Space;
+ }
+}
+parser.prototype.Name = function(c) {
+ if (cfg.blankChar[c]) {
+ this.list.push(this.section());
+ this.state = this.NameSpace;
+ } else if (c == '{') {
+ this.list.push(this.section());
+ this.Content();
+ } else if (c == ',') {
+ this.list.push(this.section());
+ this.Comma();
+ } else if (!isLetter(c) && (c < '0' || c > '9') && c != '-' && c != '_')
+ this.state = this.Ignore;
+}
+parser.prototype.NameSpace = function(c) {
+ if (c == '{') this.Content();
+ else if (c == ',') this.Comma();
+ else if (!cfg.blankChar[c]) this.state = this.Ignore;
+}
+parser.prototype.Comma = function() {
+ while (cfg.blankChar[this.data[++this.i]]);
+ if (this.data[this.i] == '{') this.Content();
+ else {
+ this.start = this.i--;
+ this.state = this.Name;
+ }
+}
+parser.prototype.Content = function() {
+ this.start = ++this.i;
+ if ((this.i = this.data.indexOf('}', this.i)) == -1) this.i = this.data.length;
+ var content = this.section();
+ for (var i = 0, item; item = this.list[i++];)
+ if (this.res[item]) this.res[item] += ';' + content;
+ else this.res[item] = content;
+ this.list = [];
+ this.state = this.Space;
+}
diff --git a/uview-ui/components/u-parse/libs/MpHtmlParser.js b/uview-ui/components/u-parse/libs/MpHtmlParser.js
new file mode 100644
index 0000000..aeb0fc3
--- /dev/null
+++ b/uview-ui/components/u-parse/libs/MpHtmlParser.js
@@ -0,0 +1,580 @@
+/**
+ * html 解析器
+ * @tutorial https://github.com/jin-yufeng/Parser
+ * @version 20201029
+ * @author JinYufeng
+ * @listens MIT
+ */
+const cfg = require('./config.js'),
+ blankChar = cfg.blankChar,
+ CssHandler = require('./CssHandler.js'),
+ windowWidth = uni.getSystemInfoSync().windowWidth;
+var emoji;
+
+function MpHtmlParser(data, options = {}) {
+ this.attrs = {};
+ this.CssHandler = new CssHandler(options.tagStyle, windowWidth);
+ this.data = data;
+ this.domain = options.domain;
+ this.DOM = [];
+ this.i = this.start = this.audioNum = this.imgNum = this.videoNum = 0;
+ options.prot = (this.domain || '').includes('://') ? this.domain.split('://')[0] : 'http';
+ this.options = options;
+ this.state = this.Text;
+ this.STACK = [];
+ // 工具函数
+ this.bubble = () => {
+ for (var i = this.STACK.length, item; item = this.STACK[--i];) {
+ if (cfg.richOnlyTags[item.name]) return false;
+ item.c = 1;
+ }
+ return true;
+ }
+ this.decode = (val, amp) => {
+ var i = -1,
+ j, en;
+ while (1) {
+ if ((i = val.indexOf('&', i + 1)) == -1) break;
+ if ((j = val.indexOf(';', i + 2)) == -1) break;
+ if (val[i + 1] == '#') {
+ en = parseInt((val[i + 2] == 'x' ? '0' : '') + val.substring(i + 2, j));
+ if (!isNaN(en)) val = val.substr(0, i) + String.fromCharCode(en) + val.substr(j + 1);
+ } else {
+ en = val.substring(i + 1, j);
+ if (cfg.entities[en] || en == amp)
+ val = val.substr(0, i) + (cfg.entities[en] || '&') + val.substr(j + 1);
+ }
+ }
+ return val;
+ }
+ this.getUrl = url => {
+ if (url[0] == '/') {
+ if (url[1] == '/') url = this.options.prot + ':' + url;
+ else if (this.domain) url = this.domain + url;
+ } else if (this.domain && url.indexOf('data:') != 0 && !url.includes('://'))
+ url = this.domain + '/' + url;
+ return url;
+ }
+ this.isClose = () => this.data[this.i] == '>' || (this.data[this.i] == '/' && this.data[this.i + 1] == '>');
+ this.section = () => this.data.substring(this.start, this.i);
+ this.parent = () => this.STACK[this.STACK.length - 1];
+ this.siblings = () => this.STACK.length ? this.parent().children : this.DOM;
+}
+MpHtmlParser.prototype.parse = function() {
+ if (emoji) this.data = emoji.parseEmoji(this.data);
+ for (var c; c = this.data[this.i]; this.i++)
+ this.state(c);
+ if (this.state == this.Text) this.setText();
+ while (this.STACK.length) this.popNode(this.STACK.pop());
+ return this.DOM;
+}
+// 设置属性
+MpHtmlParser.prototype.setAttr = function() {
+ var name = this.attrName.toLowerCase(),
+ val = this.attrVal;
+ if (cfg.boolAttrs[name]) this.attrs[name] = 'T';
+ else if (val) {
+ if (name == 'src' || (name == 'data-src' && !this.attrs.src)) this.attrs.src = this.getUrl(this.decode(val, 'amp'));
+ else if (name == 'href' || name == 'style') this.attrs[name] = this.decode(val, 'amp');
+ else if (name.substr(0, 5) != 'data-') this.attrs[name] = val;
+ }
+ this.attrVal = '';
+ while (blankChar[this.data[this.i]]) this.i++;
+ if (this.isClose()) this.setNode();
+ else {
+ this.start = this.i;
+ this.state = this.AttrName;
+ }
+}
+// 设置文本节点
+MpHtmlParser.prototype.setText = function() {
+ var back, text = this.section();
+ if (!text) return;
+ text = (cfg.onText && cfg.onText(text, () => back = true)) || text;
+ if (back) {
+ this.data = this.data.substr(0, this.start) + text + this.data.substr(this.i);
+ let j = this.start + text.length;
+ for (this.i = this.start; this.i < j; this.i++) this.state(this.data[this.i]);
+ return;
+ }
+ if (!this.pre) {
+ // 合并空白符
+ var flag, tmp = [];
+ for (let i = text.length, c; c = text[--i];)
+ if (!blankChar[c]) {
+ tmp.unshift(c);
+ if (!flag) flag = 1;
+ } else {
+ if (tmp[0] != ' ') tmp.unshift(' ');
+ if (c == '\n' && flag == void 0) flag = 0;
+ }
+ if (flag == 0) return;
+ text = tmp.join('');
+ }
+ this.siblings().push({
+ type: 'text',
+ text: this.decode(text)
+ });
+}
+// 设置元素节点
+MpHtmlParser.prototype.setNode = function() {
+ var node = {
+ name: this.tagName.toLowerCase(),
+ attrs: this.attrs
+ },
+ close = cfg.selfClosingTags[node.name];
+ if (this.options.nodes.length) node.type = 'node';
+ this.attrs = {};
+ if (!cfg.ignoreTags[node.name]) {
+ // 处理属性
+ var attrs = node.attrs,
+ style = this.CssHandler.match(node.name, attrs, node) + (attrs.style || ''),
+ styleObj = {};
+ if (attrs.id) {
+ if (this.options.compress & 1) attrs.id = void 0;
+ else if (this.options.useAnchor) this.bubble();
+ }
+ if ((this.options.compress & 2) && attrs.class) attrs.class = void 0;
+ switch (node.name) {
+ case 'a':
+ case 'ad': // #ifdef APP-PLUS
+ case 'iframe':
+ // #endif
+ this.bubble();
+ break;
+ case 'font':
+ if (attrs.color) {
+ styleObj['color'] = attrs.color;
+ attrs.color = void 0;
+ }
+ if (attrs.face) {
+ styleObj['font-family'] = attrs.face;
+ attrs.face = void 0;
+ }
+ if (attrs.size) {
+ var size = parseInt(attrs.size);
+ if (size < 1) size = 1;
+ else if (size > 7) size = 7;
+ var map = ['xx-small', 'x-small', 'small', 'medium', 'large', 'x-large', 'xx-large'];
+ styleObj['font-size'] = map[size - 1];
+ attrs.size = void 0;
+ }
+ break;
+ case 'embed':
+ // #ifndef APP-PLUS
+ var src = node.attrs.src || '',
+ type = node.attrs.type || '';
+ if (type.includes('video') || src.includes('.mp4') || src.includes('.3gp') || src.includes('.m3u8'))
+ node.name = 'video';
+ else if (type.includes('audio') || src.includes('.m4a') || src.includes('.wav') || src.includes('.mp3') || src.includes(
+ '.aac'))
+ node.name = 'audio';
+ else break;
+ if (node.attrs.autostart)
+ node.attrs.autoplay = 'T';
+ node.attrs.controls = 'T';
+ // #endif
+ // #ifdef APP-PLUS
+ this.bubble();
+ break;
+ // #endif
+ case 'video':
+ case 'audio':
+ if (!attrs.id) attrs.id = node.name + (++this[`${node.name}Num`]);
+ else this[`${node.name}Num`]++;
+ if (node.name == 'video') {
+ if (this.videoNum > 3)
+ node.lazyLoad = 1;
+ if (attrs.width) {
+ styleObj.width = parseFloat(attrs.width) + (attrs.width.includes('%') ? '%' : 'px');
+ attrs.width = void 0;
+ }
+ if (attrs.height) {
+ styleObj.height = parseFloat(attrs.height) + (attrs.height.includes('%') ? '%' : 'px');
+ attrs.height = void 0;
+ }
+ }
+ if (!attrs.controls && !attrs.autoplay) attrs.controls = 'T';
+ attrs.source = [];
+ if (attrs.src) {
+ attrs.source.push(attrs.src);
+ attrs.src = void 0;
+ }
+ this.bubble();
+ break;
+ case 'td':
+ case 'th':
+ if (attrs.colspan || attrs.rowspan)
+ for (var k = this.STACK.length, item; item = this.STACK[--k];)
+ if (item.name == 'table') {
+ item.flag = 1;
+ break;
+ }
+ }
+ if (attrs.align) {
+ if (node.name == 'table') {
+ if (attrs.align == 'center') styleObj['margin-inline-start'] = styleObj['margin-inline-end'] = 'auto';
+ else styleObj['float'] = attrs.align;
+ } else styleObj['text-align'] = attrs.align;
+ attrs.align = void 0;
+ }
+ // 压缩 style
+ var styles = style.split(';');
+ style = '';
+ for (var i = 0, len = styles.length; i < len; i++) {
+ var info = styles[i].split(':');
+ if (info.length < 2) continue;
+ let key = info[0].trim().toLowerCase(),
+ value = info.slice(1).join(':').trim();
+ if (value[0] == '-' || value.includes('safe'))
+ style += `;${key}:${value}`;
+ else if (!styleObj[key] || value.includes('import') || !styleObj[key].includes('import'))
+ styleObj[key] = value;
+ }
+ if (node.name == 'img') {
+ if (attrs.src && !attrs.ignore) {
+ if (this.bubble())
+ attrs.i = (this.imgNum++).toString();
+ else attrs.ignore = 'T';
+ }
+ if (attrs.ignore) {
+ style += ';-webkit-touch-callout:none';
+ styleObj['max-width'] = '100%';
+ }
+ var width;
+ if (styleObj.width) width = styleObj.width;
+ else if (attrs.width) width = attrs.width.includes('%') ? attrs.width : parseFloat(attrs.width) + 'px';
+ if (width) {
+ styleObj.width = width;
+ attrs.width = '100%';
+ if (parseInt(width) > windowWidth) {
+ styleObj.height = '';
+ if (attrs.height) attrs.height = void 0;
+ }
+ }
+ if (styleObj.height) {
+ attrs.height = styleObj.height;
+ styleObj.height = '';
+ } else if (attrs.height && !attrs.height.includes('%'))
+ attrs.height = parseFloat(attrs.height) + 'px';
+ }
+ for (var key in styleObj) {
+ var value = styleObj[key];
+ if (!value) continue;
+ if (key.includes('flex') || key == 'order' || key == 'self-align') node.c = 1;
+ // 填充链接
+ if (value.includes('url')) {
+ var j = value.indexOf('(');
+ if (j++ != -1) {
+ while (value[j] == '"' || value[j] == "'" || blankChar[value[j]]) j++;
+ value = value.substr(0, j) + this.getUrl(value.substr(j));
+ }
+ }
+ // 转换 rpx
+ else if (value.includes('rpx'))
+ value = value.replace(/[0-9.]+\s*rpx/g, $ => parseFloat($) * windowWidth / 750 + 'px');
+ else if (key == 'white-space' && value.includes('pre') && !close)
+ this.pre = node.pre = true;
+ style += `;${key}:${value}`;
+ }
+ style = style.substr(1);
+ if (style) attrs.style = style;
+ if (!close) {
+ node.children = [];
+ if (node.name == 'pre' && cfg.highlight) {
+ this.remove(node);
+ this.pre = node.pre = true;
+ }
+ this.siblings().push(node);
+ this.STACK.push(node);
+ } else if (!cfg.filter || cfg.filter(node, this) != false)
+ this.siblings().push(node);
+ } else {
+ if (!close) this.remove(node);
+ else if (node.name == 'source') {
+ var parent = this.parent();
+ if (parent && (parent.name == 'video' || parent.name == 'audio') && node.attrs.src)
+ parent.attrs.source.push(node.attrs.src);
+ } else if (node.name == 'base' && !this.domain) this.domain = node.attrs.href;
+ }
+ if (this.data[this.i] == '/') this.i++;
+ this.start = this.i + 1;
+ this.state = this.Text;
+}
+// 移除标签
+MpHtmlParser.prototype.remove = function(node) {
+ var name = node.name,
+ j = this.i;
+ // 处理 svg
+ var handleSvg = () => {
+ var src = this.data.substring(j, this.i + 1);
+ node.attrs.xmlns = 'http://www.w3.org/2000/svg';
+ for (var key in node.attrs) {
+ if (key == 'viewbox') src = ` viewBox="${node.attrs.viewbox}"` + src;
+ else if (key != 'style') src = ` ${key}="${node.attrs[key]}"` + src;
+ }
+ src = '