Forráskód Böngészése

权益页面+头像裁剪功能

@dongkboy 1 hete
szülő
commit
73ff341e00

+ 21 - 2
pages.json

@@ -1101,9 +1101,28 @@
 				}
 			}
 
+		},
+		{
+			"path": "pages/institutional/applicationResult",
+			"style": {
+				"navigationBarTitleText": "申请结果",
+				"app-plus": {
+					"scrollIndicator": "none",
+					"bounce": "none"
+				}
+			}
+		},
+		{
+			"path": "pages/my/avatarCropper",
+			"style": {
+				"navigationBarTitleText": "裁剪",
+				"app-plus": {
+					"titleNView": false,
+					"scrollIndicator": "none",
+					"bounce": "none"
+				}
+			}
 		}
-
-
 	],
 	"globalStyle": {
 		"navigationBarTextStyle": "black",

+ 58 - 0
pages/institutional/applicationResult.vue

@@ -0,0 +1,58 @@
+<template>
+	<view class="page">
+		<view class="dis f-c a-c ">
+			<image src="/static/applicationSuccess.png" mode=""></image>
+			<text class="title">添加成功</text>
+			<text class="msg ">已提交成为%升级等级%的申请, 请等待耐心等待系统审核</text>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+
+			}
+		},
+		onShow() {
+
+		},
+		onLoad() {
+
+		},
+		methods: {
+
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	page {
+
+		background-color: #fff;
+
+	}
+
+	image {
+		margin-top: 100rpx;
+		width: 100rpx;
+		height: 100rpx;
+	}
+
+	.title {
+		font-size: 40rpx;
+		color: #333;
+		font-weight: bold;
+		margin-top: 30rpx;
+		margin-bottom: 12rpx;
+	}
+
+	.msg {
+		font-size: 28rpx;
+		color: #666;
+		padding: 0 160rpx;
+		box-sizing: border-box;
+		text-align: center;
+	}
+</style>

+ 8 - 2
pages/institutional/invitationCode.vue

@@ -22,7 +22,7 @@
 						<image :src="recommendImg" mode="widthFix" lazy-load></image>
 					</view>
 					<view class="operation mt-4 dis a-c ">
-						<view class="dis f-c a-c" style="margin-right: 136rpx;">
+						<view class="dis f-c a-c" style="margin-right: 136rpx;" @click="">
 							<image src="/static/share.png" mode=""></image>
 							<text class="mt-1">保存图片</text>
 						</view>
@@ -37,7 +37,7 @@
 			<view class="tag mt-2 dis f-c ">
 				<view class="dis a-c j-s">
 					<text>我的身份:合伙人</text>
-					<view class="entryPoint">去升级</view>
+					<view class="entryPoint" @click="upgrade">去升级</view>
 				</view>
 				<text class="mt-1">再邀请6个工作室,即可升级成为管理人,赚取更多收益</text>
 			</view>
@@ -72,6 +72,12 @@
 			this.recommendCode();
 		},
 		methods: {
+			//去升级
+			upgrade() {
+				uni.navigateTo({
+					url: '/pages/institutional/applicationResult'
+				})
+			},
 			//二维码生成
 			recommendCode() {
 				this.recommendImg = QR.createQrCodeImg("/#/pages/register/register?id=", {

+ 1 - 6
pages/login/login.vue

@@ -89,7 +89,7 @@
 				<button class="my-3 mt-4 d-flex a-center j-center font-weight bg-color" :loading="loading"
 					:class="{'bg-hover-color':disabled}" type="primary" @tap="submit" :disabled="disabled"
 					style="letter-spacing: 20rpx;">登录</button>
-				<view class=" left-0 right-0 dis a-c j-start  text-light-muted" style="bottom:30rpx">
+				<view class=" left-0 right-0 dis a-c j-start  text-light-muted">
 					<u-checkbox v-model="checked" active-color="#FF852D "></u-checkbox>
 					我已确认并同意<view> <text @tap="nav('/pages/login/xieyi')" class="text-color">平台协议</text>及<text
 							class="text-color" @tap="nav('/pages/login/mimi')">隐私协议</text>政策</view>
@@ -861,9 +861,4 @@
 	.text-color {
 		color: #FF9E2D;
 	}
-
-	// .u-checkbox>.u-checkbox__icon-wrap--checked{
-	// 	background-color: #FF9E2D !important;
-	// border-color: #FF9E2D !important;
-	// }
 </style>

+ 283 - 0
pages/my/avatarCropper.vue

@@ -0,0 +1,283 @@
+<template>
+	<view class="content">
+		<view class="cropper-wrapper" :style="{ height: cropperOpt.height + 'px' }">
+			<canvas class="cropper" :disable-scroll="true" @touchstart="touchStart" @touchmove="touchMove"
+				@touchend="touchEnd"
+				:style="{ width: cropperOpt.width, height: cropperOpt.height, backgroundColor: '#999' }"
+				canvas-id="cropper" id="cropper"></canvas>
+			<canvas class="cropper" :disable-scroll="true" :style="{
+					border:'2px solid #000',
+					position: 'fixed',
+					top: `-${cropperOpt.width * cropperOpt.pixelRatio}px`,
+					left: `-${cropperOpt.height * cropperOpt.pixelRatio}px`,
+					width: `${cropperOpt.width * cropperOpt.pixelRatio}px`,
+					height: `${cropperOpt.height * cropperOpt.pixelRatio}`
+				}" canvas-id="targetId" id="targetId"></canvas>
+		</view>
+		<view class="cropper-buttons safe-area-padding" :style="{ height: bottomNavHeight + 'px' }">
+			<!-- #ifdef H5 -->
+			<view class="upload" @tap="uploadTap">选择图片</view>
+			<!-- #endif -->
+			<!-- #ifndef H5 -->
+			<view class="upload" @tap="uploadTap">重新选择</view>
+			<!-- #endif -->
+			<view class="getCropperImage" @tap="getCropperImage(false)">确定</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	import WeCropper from './weCropper.js';
+	export default {
+		props: {
+			// 裁剪矩形框的样式,其中可包含的属性为lineWidth-边框宽度(单位rpx),color: 边框颜色,
+			// mask-遮罩颜色,一般设置为一个rgba的透明度,如"rgba(0, 0, 0, 0.35)"
+			boundStyle: {
+				type: Object,
+				default () {
+					return {
+						lineWidth: 4,
+						borderColor: 'rgb(245, 245, 245)',
+						mask: 'rgba(0, 0, 0, 0.35)'
+					};
+				}
+			}
+			// // 裁剪框宽度,单位rpx
+			// rectWidth: {
+			// 	type: [String, Number],
+			// 	default: 400
+			// },
+			// // 裁剪框高度,单位rpx
+			// rectHeight: {
+			// 	type: [String, Number],
+			// 	default: 400
+			// },
+			// // 输出图片宽度,单位rpx
+			// destWidth: {
+			// 	type: [String, Number],
+			// 	default: 400
+			// },
+			// // 输出图片高度,单位rpx
+			// destHeight: {
+			// 	type: [String, Number],
+			// 	default: 400
+			// },
+			// // 输出的图片类型,如果发现裁剪的图片很大,可能是因为设置为了"png",改成"jpg"即可
+			// fileType: {
+			// 	type: String,
+			// 	default: 'jpg',
+			// },
+			// // 生成的图片质量
+			// // H5上无效,目前不考虑使用此参数
+			// quality: {
+			// 	type: [Number, String],
+			// 	default: 1
+			// }
+		},
+		data() {
+			return {
+				// 底部导航的高度
+				bottomNavHeight: 50,
+				originWidth: 200,
+				width: 0,
+				height: 200,
+				cropperOpt: {
+					id: 'cropper',
+					targetId: 'targetCropper',
+					pixelRatio: 1,
+					width: 0,
+					height: 0,
+					scale: 2.5,
+					zoom: 8,
+					cut: {
+						x: (this.width - this.originWidth) / 2,
+						y: (this.height - this.originWidth) / 2,
+						width: this.originWidth,
+						height: this.originWidth
+					},
+					boundStyle: {
+						lineWidth: uni.upx2px(this.boundStyle.lineWidth),
+						mask: this.boundStyle.mask,
+						color: this.boundStyle.borderColor
+					}
+				},
+				// 裁剪框和输出图片的尺寸,高度默认等于宽度
+				// 输出图片宽度,单位px
+				destWidth: 300,
+				// 裁剪框宽度,单位px
+				rectWidth: 300,
+				// 输出的图片类型,如果'png'类型发现裁剪的图片太大,改成"jpg"即可
+				fileType: 'jpg',
+				src: '', // 选择的图片路径,用于在点击确定时,判断是否选择了图片
+			};
+		},
+		onLoad(option) {
+			let rectInfo = uni.getSystemInfoSync();
+			this.width = rectInfo.windowWidth;
+			this.height = rectInfo.windowHeight - this.bottomNavHeight;
+			this.cropperOpt.width = this.width;
+			this.cropperOpt.height = rectInfo.screenHeight;
+			this.cropperOpt.pixelRatio = rectInfo.pixelRatio;
+
+			let rectWidth = Number(280);
+			this.cropperOpt.cut = {
+				x: (this.width - rectWidth) / 2,
+				y: (this.height - rectWidth) / 2,
+				width: rectWidth,
+				height: rectWidth
+			};
+			// 初始化
+			this.cropper = new WeCropper(this.cropperOpt)
+				.on('ready', ctx => {
+					// wecropper is ready for work!
+				})
+				.on('beforeImageLoad', ctx => {
+					// before picture loaded, i can do something
+				})
+				.on('imageLoad', ctx => {
+					// picture loaded
+				})
+				.on('beforeDraw', (ctx, instance) => {
+					// before canvas draw,i can do something
+				});
+			// 设置导航栏样式,以免用户在page.json中没有设置为黑色背景
+			uni.setNavigationBarColor({
+				frontColor: '#ffffff',
+				backgroundColor: '#000000'
+			});
+			this.src = option.src; //已选图片
+			this.cropper.pushOrign(this.src); //图片赋值给裁剪框
+
+		},
+		methods: {
+			touchStart(e) {
+				this.cropper.touchStart(e);
+			},
+			touchMove(e) {
+				this.cropper.touchMove(e);
+			},
+			touchEnd(e) {
+				this.cropper.touchEnd(e);
+			},
+			getCropperImage(isPre = false) {
+				if (!this.src) return this.$u.toast('请先选择图片再裁剪');
+
+				let cropper_opt = {
+					destHeight: Number(this.destWidth), // uni.canvasToTempFilePath要求这些参数为数值
+					destWidth: Number(this.destWidth),
+					fileType: this.fileType
+				};
+				this.cropper.getCropperImage(cropper_opt, (path, err) => {
+					if (err) {
+						uni.showModal({
+							title: '温馨提示',
+							content: err.message
+						});
+					} else {
+						if (isPre) {
+							uni.previewImage({
+								current: '', // 当前显示图片的 http 链接
+								urls: [path] // 需要预览的图片 http 链接列表
+							});
+						} else {
+							console.log(path);
+							uni.$emit('uAvatarCropper', path);
+							this.$u.route({
+								type: 'back'
+							});
+						}
+					}
+				});
+			},
+			uploadTap() {
+				const self = this;
+				uni.chooseImage({
+					count: 1, // 默认9
+					sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有
+					sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有
+					success: (res) => {
+						self.src = res.tempFilePaths[0];
+						//  获取裁剪图片资源后,给data添加src属性及其值
+
+						self.cropper.pushOrign(this.src);
+					}
+				});
+			}
+		}
+	};
+</script>
+
+<style scoped lang="scss">
+	@mixin vue-flex($direction: row) {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		flex-direction: $direction;
+		/* #endif */
+	}
+
+	.content {
+		background: rgba(255, 255, 255, 1);
+		height: 100vh;
+	}
+
+	.cropper {
+		position: absolute;
+		top: 0;
+		left: 0;
+		width: 100%;
+		height: 100vh;
+		z-index: 11;
+	}
+
+	#targetId {
+		border: 2px solid #fff !important;
+	}
+
+	.cropper-wrapper {
+		position: relative;
+		@include vue-flex;
+		flex-direction: row;
+		justify-content: space-between;
+		align-items: center;
+		width: 100%;
+		height: 100vh;
+		background-color: #000;
+	}
+
+	.cropper-buttons {
+		padding: 0 46rpx;
+		box-sizing: border-box;
+		color: #eee;
+		width: 100vw;
+		height: auto;
+		@include vue-flex;
+		flex-direction: row;
+		justify-content: space-between;
+		align-items: center;
+		position: fixed;
+		bottom: 200rpx;
+		left: 0;
+		font-size: 28rpx;
+		z-index: 999;
+
+		view {
+			width: 48%;
+			text-align: center;
+			padding: 18rpx 65rpx;
+			box-sizing: border-box;
+			background-color: #fff;
+			border-radius: 4rpx;
+			font-size: 30rpx;
+
+		}
+
+		view:first-child {
+			color: #333;
+		}
+
+		view:last-child {
+			background: linear-gradient(132deg, #2DD9FF 0%, #2D6DFF 100%);
+			border-radius: 4rpx 4rpx 4rpx 4rpx;
+		}
+	}
+</style>

+ 36 - 1
pages/my/benefits.vue

@@ -8,7 +8,7 @@
 					<text>我的佣金比例</text>
 				</view>
 			</view>
-			<view class="ratio dis a-end ">
+			<view class="ratio dis a-end " @click="ratiodetail">
 				<text class="mr-1">0.8%</text>
 				<u-icon name="arrow-right" color="#999" size="28"></u-icon>
 			</view>
@@ -66,6 +66,29 @@
 				</view>
 			</view>
 		</view>
+		<u-popup v-model="ratiodetailshow" mode="bottom" border-radius="20" :closeable="true">
+			<view class=" dis a-c j-c " style="border-bottom: 1rpx solid #eee;padding: 24rpx;box-sizing: border-box;">
+				<text class="font-weight" style="font-size: 36rpx;color: #333;">我的佣金比例</text>
+			</view>
+			<view class="p-3">
+				<view class="ratioitem dis a-c j-s">
+					<text>创始人</text>
+					<text>0.1%</text>
+				</view>
+				<view class="ratioitem dis a-c j-s">
+					<text>管理人</text>
+					<text>0.1%</text>
+				</view>
+				<view class="ratioitem dis a-c j-s">
+					<text>合伙人</text>
+					<text>0.1%</text>
+				</view>
+				<view class="ratioitem dis a-c j-s">
+					<text>工作室</text>
+					<text>0.1%</text>
+				</view>
+			</view>
+		</u-popup>
 	</view>
 </template>
 
@@ -77,6 +100,7 @@
 	export default {
 		data() {
 			return {
+				ratiodetailshow: false, //佣金比例弹窗
 				ratioindex: 0,
 				content: "创始人身份可享受邀请的所有管理人发展的团队成员车险订单的0.1% \n例如:创始人邀请了管理人A,管理人A邀请了合伙人B,合伙人B邀请了工作室C,工作室C邀请了团队D,团队D内的成员出单保费1000元(除车船税),管理人即可获得1000*0.1% = 1元",
 				activeTab: 1,
@@ -124,12 +148,17 @@
 
 		},
 		methods: {
+			//切换事件
 			itemclick(item, index) {
 				this.ratioindex = index;
 				this.content = item.Text;
 			},
 			handleTab(index) {
 				this.activeTab = index
+			},
+			//比例弹窗
+			ratiodetail() {
+				this.ratiodetailshow = true;
 			}
 		}
 	}
@@ -361,4 +390,10 @@
 			height: 20rpx;
 		}
 	}
+
+	.ratioitem {
+		font-size: 30rpx;
+		color: #333;
+		margin-bottom: 52rpx;
+	}
 </style>

+ 53 - 6
pages/my/my.vue

@@ -28,9 +28,9 @@
 				推广码
 			</view>
 			<view class="dis a-c  Personnel-info">
-				<view class="Personnel-img">
+				<view class="Personnel-img" @click="updateAvatar">
 					<image :src="avatar" class="avatar" mode=""></image>
-					<image :src="backLogo" mode=""></image>
+					<image src="/static/image/my/updateAvatar.png" mode=""></image>
 				</view>
 				<view class="full-name">
 					<text>{{ userInfo.sysUser.userName }}</text>
@@ -157,6 +157,7 @@
 				</view>
 			</view>
 		</u-popup>
+		<u-action-sheet :list="Avatarlist" v-model="updateAvatarShow" border-radius="20"></u-action-sheet>
 	</view>
 </template>
 
@@ -164,6 +165,7 @@
 	import myDatePicker from '../components/date-picker.vue';
 	import QR from "@/common/wxqrcode.js"
 	import html2canvas from 'html2canvas'
+	import store from '@/store';
 	import {
 		mapState,
 		mapMutations
@@ -174,6 +176,15 @@
 		},
 		data() {
 			return {
+				updateAvatarShow: false, //头像工具
+				Avatarlist: [{
+					text: '点赞',
+					color: 'blue',
+					fontSize: 28,
+					subText: '感谢您的点赞'
+				}, {
+					text: '分享'
+				}, ],
 				supportStaffUrl: '',
 				ShowModalCode: false,
 				info: ["", ""],
@@ -250,6 +261,42 @@
 					url: "/pages/my/benefits"
 				})
 			},
+			//修改头像
+			async updateAvatar() {
+				let [chooseImageErr, chooseImageRes] = await uni.chooseImage({
+					count: 1,
+					sizeType: ['compressed']
+				});
+				if (chooseImageRes) {
+					console.log(chooseImageRes);
+					this.chooseAvatar(chooseImageRes.tempFilePaths[0]);
+					// uni.uploadFile({
+					// 	url: this.$base.baseUrl + '/ins/taskImage/uploadFile',
+					// 	filePath: chooseImageRes.tempFilePaths[0],
+					// 	name: "multipartFile",
+					// 	formData: {
+					// 		'type': 'image',
+					// 	},
+					// 	header: {
+					// 		Authorization: store.state.token,
+					// 	},
+					// 	success: (imgRes) => {
+					// 		let data = JSON.parse(imgRes.data);
+					// 		if (data.code == '200') {
+
+
+					// 		}
+
+					// 	}
+					// });
+				} else {}
+			},
+			chooseAvatar(src) {
+				uni.navigateTo({
+					url: '/pages/my/avatarCropper?src=' + src,
+
+				})
+			},
 			searchPopup() {
 				this.$refs.datePicker.open()
 			},
@@ -632,11 +679,11 @@
 
 		image:last-child {
 			display: inline-block;
-			width: 30px;
-			height: 30px;
+			width: 40rpx;
+			height: 40rpx;
 			position: absolute;
-			bottom: -5px;
-			right: -8px;
+			bottom: 0;
+			right: 0;
 		}
 	}
 

+ 1273 - 0
pages/my/weCropper.js

@@ -0,0 +1,1273 @@
+/**
+ * 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.strokeStyle = '#FFFFFF'; // 边框颜色为白色
+			self.ctx.lineWidth = 5; // 边框宽度为 5px
+			self.ctx.strokeRect(x, y, width, height); // 在裁剪框位置绘制边框
+			// ----------------------------------
+			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;
+
+})));

+ 436 - 458
pages/statistics/statistics.vue

@@ -17,46 +17,39 @@
 			<view class=" dis j-s a-c" style="padding: 10px 10px 0 0;">
 				<view class="statistics-title">新增人员汇总统计</view>
 				<year @queryData="queryData" @time="getTime"></year>
-			
+
 			</view>
-			<view class="statistics-number "> 
+			<view class="statistics-number ">
 				<view v-if="level <= 4">
 					<text>{{ echartsList.onePartnerNum || 0 }}</text>
-					<text>一级合伙人</text>
+					<text>管理人</text>
 				</view>
 				<view v-if="level <= 3">
 					<text>{{ echartsList.twoPartnerNum || 0 }}</text>
-					<text>二级合伙人</text>
+					<text>合伙人</text>
 				</view>
 				<view v-if="level <= 2">
 					<text>{{ echartsList.threePartnerNum || 0 }}</text>
-					<text>三级合伙人</text>
+					<text>工作室</text>
 				</view>
 				<view v-if="level == 1">
 					<text>{{ echartsList.fourPartnerNum || 0 }}</text>
-					<text>四级合伙人</text>
-				</view>
-				<view>
-					<text>{{ echartsList.workSum || 0 }}</text>
-					<text>工作室</text>
-				</view>
-				<view>
-					<text>{{ echartsList.deptSum || 0 }}</text>
 					<text>团队</text>
 				</view>
 				<view>
-					<text>{{ echartsList.deptManSum || 0 }}</text>
-					<text>代理人</text>
+					<text>{{ echartsList.workSum || 0 }}</text>
+					<text>业务员</text>
 				</view>
 			</view>
-			<view class="partner-type dis" >
+			<view class="partner-type dis">
 				<view style="width: 650px;overflow-x: auto;">
 					<text :class="typeStatistics == val.value ? 'selected' : ''" v-for="val in partnerTypeOption"
 						:key="val.value" @click="getPartnerType(val.value)">{{ val.lable }}</text>
 				</view>
 			</view>
-			<o-empty v-if="echartsList.countUserNumVoList && echartsList.countUserNumVoList.length == 0" height="20vh" />
-			<qiun-data-charts v-else type="area" :ontouch="true" :opts="opts1" :chartData="chartData1"   />
+			<o-empty v-if="echartsList.countUserNumVoList && echartsList.countUserNumVoList.length == 0"
+				height="20vh" />
+			<qiun-data-charts v-else type="area" :ontouch="true" :opts="opts1" :chartData="chartData1" />
 		</view>
 		<view class="body-box" v-if="type == 1 && level!==5">
 			<view class=" dis j-s a-c" style="padding: 10px 10px 0 0;">
@@ -126,7 +119,8 @@
 				<text :class="typeStatistics == 2 ? 'selected' : ''" @click="getStatistics(2)">团队</text>
 				<text :class="typeStatistics == 3 ? 'selected' : ''" @click="getStatistics(3)">代理人</text>
 			</view>
-			<o-empty v-if="echartsList.countUserNumVoList && echartsList.countUserNumVoList.length == 0" height="20vh" />
+			<o-empty v-if="echartsList.countUserNumVoList && echartsList.countUserNumVoList.length == 0"
+				height="20vh" />
 			<qiun-data-charts v-else type="area" :opts="opts1" :chartData="chartData1" />
 		</view>
 		<view class="body-box" style="margin-top: 100px;" v-if="type == 2">
@@ -153,65 +147,65 @@
 				<text :class="typeStatistics == 1 ? 'selected' : ''" @click="getStatistics(1)">团队</text>
 				<text :class="typeStatistics == 2 ? 'selected' : ''" @click="getStatistics(2)">代理人</text>
 			</view>
-			<o-empty v-if="echartsList.countUserNumVoList && echartsList.countUserNumVoList.length == 0" height="20vh" />
-			<qiun-data-charts v-else type="area" :opts="opts1" :chartData="chartData1" :ontouch="true"    />
+			<o-empty v-if="echartsList.countUserNumVoList && echartsList.countUserNumVoList.length == 0"
+				height="20vh" />
+			<qiun-data-charts v-else type="area" :opts="opts1" :chartData="chartData1" :ontouch="true" />
 		</view>
 
 	</view>
 </template>
 <script>
-import {
-	mapState,
-} from "vuex"
-import leverStaff from "../components/leverStaff.vue"
-import year from "../components/year.vue"
-export default {
-	components: {
-		leverStaff,
-		year
-	},
-	data() {
-		return {
-			beginTime: '',
-			endTime: '',
-			ringOpts: {
-				color: [ '#02CDFF ','#2D97FF'],
-				legend: {
-					show: false // 设置图例不显示
+	import {
+		mapState,
+	} from "vuex"
+	import leverStaff from "../components/leverStaff.vue"
+	import year from "../components/year.vue"
+	export default {
+		components: {
+			leverStaff,
+			year
+		},
+		data() {
+			return {
+				beginTime: '',
+				endTime: '',
+				ringOpts: {
+					color: ['#02CDFF ', '#2D97FF'],
+					legend: {
+						show: false // 设置图例不显示
+					},
+					dataLabel: true,
 				},
-				dataLabel: true,
-			},
-			chartsDataPie2: {},
-			echartsList2:{},
-			level: '',
-			type: null,
-			typeStatistics: 1,
-			typeStatistics2: 1,
-			typeStatistics3: 1,
-			option: {},
-			supportStaffUrl: '',
-			headerStyle: {
-				backgroundColor: 'transparent',
-				backgroundImage: 'url("/static/beijing (2).png")',
-				backgroundSize: 'cover',
-				backgroundPosition: '',
-				boxShadow: ''
-				// 其他样式属性...
-			},
-			year: [{
-				lable: '日',
-				startShow: false
-			}, {
-				lable: '周',
-				startShow: false
-			}, {
-				lable: '月',
-				startShow: false
-			}],
-			echartsList: {},
-			analysisEchartsList: {},
-			partnerTypeOption: [
-				{
+				chartsDataPie2: {},
+				echartsList2: {},
+				level: '',
+				type: null,
+				typeStatistics: 1,
+				typeStatistics2: 1,
+				typeStatistics3: 1,
+				option: {},
+				supportStaffUrl: '',
+				headerStyle: {
+					backgroundColor: 'transparent',
+					backgroundImage: 'url("/static/beijing (2).png")',
+					backgroundSize: 'cover',
+					backgroundPosition: '',
+					boxShadow: ''
+					// 其他样式属性...
+				},
+				year: [{
+					lable: '日',
+					startShow: false
+				}, {
+					lable: '周',
+					startShow: false
+				}, {
+					lable: '月',
+					startShow: false
+				}],
+				echartsList: {},
+				analysisEchartsList: {},
+				partnerTypeOption: [{
 					lable: '一级合伙人',
 					value: '1'
 				}, {
@@ -223,446 +217,430 @@ export default {
 				}, {
 					lable: '四级合伙人',
 					value: '4'
-				},
-			],
-			// optsMax:10,
-			opts1: {
-				 enableScroll: true,
-				padding: [15,10,15,0],
-				legend: {
-					show: false // 设置图例不显示
-				},
-				yAxis: {
-					gridType: "dash",
-					dashLength: 2,
-					data: [
-						{
-							min: 0,
-							max: 10
-						}
-					]
-				},
-				extra: {
-					area: {
-						type: "curve",
-						opacity: 0.2,
-						addLine: true,
-						width: 2,
-						gradient: true,
-						activeType: "hollow"
+				}, ],
+				// optsMax:10,
+
+				opts1: {
+					enableScroll: true,
+					padding: [15, 10, 15, 0],
+					legend: {
+						show: false // 设置图例不显示
+					},
+					xAxis: {
+						disableGrid: true,
+						type: 'grid',
+						gridType: 'dash',
+						itemCount: 4, //x轴单屏显示数据的数量,默认为5个
+						scrollShow: true, //新增是否显示滚动条,默认false
+						scrollAlign: 'left', //滚动条初始位置
+						scrollBackgroundColor: '#F7F7FF', //默认为 #EFEBEF
+						scrollColor: '#A6A6A6', //默认为 #A6A6A6,
+						fontSize: 11,
+					},
+					yAxis: {
+						gridType: "dash",
+						dashLength: 2,
+					},
+					extra: {
+						area: {
+							type: "curve",
+							opacity: 0.2,
+							addLine: true,
+							width: 2,
+							gradient: true,
+							activeType: "hollow"
+						},
 					},
-					// line: {
-					// 	type: "curve",
-					// 	width: 2,
-					// 	activeType: "hollow",
-					// 	linearType: "custom"
-					// }
 				},
-				xAxis: {
-					 disableGrid: true,
-					 type:'grid',
-					 gridType:'dash',
-					 itemCount:4,//x轴单屏显示数据的数量,默认为5个
-					 scrollShow:true,//新增是否显示滚动条,默认false
-					 scrollAlign:'left',//滚动条初始位置
-					 scrollBackgroundColor:'#F7F7FF',//默认为 #EFEBEF
-					 scrollColor:'#A6A6A6',//默认为 #A6A6A6,
-					 fontSize:11,
-				   },
-			},
-
-			chartData1: {},
-			directLsit: []
-		}
-	},
-	computed: {
-		...mapState(['userInfo']),
-	},
-	onLoad() {
-		this.level = this.userInfo.sysUser.level
-		if (this.level == 2) {
-			this.partnerTypeOption = this.partnerTypeOption.slice(0, -1);
-		}
-		if (this.level == 3) {
-			this.partnerTypeOption = this.partnerTypeOption.slice(0, -2);
-		}
-		if (this.level == 4) {
-			this.partnerTypeOption = this.partnerTypeOption.slice(0, 1);
-		}
-		this.$http.get('/sys/qy/wechat/find/picture').then(res => {
-			this.supportStaffUrl = res.data.supportStaffUrl
-		})
-	},
-	onShow() {
-		this.type = uni.getStorageSync('type')
-		// if(this.type ==2){
-		// 	this.queryData({type:1})
-		// }
-		// else{
-		// 	this.queryData({type:1})
-		// }
-		this.queryData()
-		if (this.type == 1 && this.level!==5) {
-			this.analysisQueryData()
-			this.rankingQueryData()
-		}
-
-	},
-
-	methods: {
-		canvasInit(canvas, width, height) {
-			// 初始化画布
-			this.canvas2d = canvas;
-		},
-		directDetail(val){
-			uni.navigateTo({
-					url: "/pages/statistics/statisticsDetail?key=" + encodeURIComponent(JSON.stringify(val.partnerIds))
-				})
-		},
-		getPartnerType2(type) {
-			this.typeStatistics2 = type
-			this.analysisQueryData()
-		},
-		getPartnerType3(type) {
-			this.typeStatistics3 = type
-			this.rankingQueryData()
-		},
-		getPartnerType(type) {
-			this.typeStatistics = type
-			this.queryData()
-		},
-		getStatistics(type) {
-			// 	uni.navigateTo({
-			// 	url: "/pages/tools/achievement/achievement"
-			// })
-			// this.studioType=type
-			this.typeStatistics = type
-			this.queryData()
+				chartData1: {},
+				directLsit: []
+			}
 		},
-		//点击跳转企业微信客服
-		weChatService() {
-			uni.share({
-				provider: "weixin",
-				openCustomerServiceChat: true,
-				customerUrl: this.supportStaffUrl, //企业微信地址
-				corpid: 'wwfe67d19509d43ec5', //企业id
-				success: (res) => { },
-				fail: (err) => { }
-			});
+		computed: {
+			...mapState(['userInfo']),
 		},
-		
-		async analysisQueryData() {
-			let params = {
-				beginTime: this.beginTime,
-				endTime: this.endTime,
-				type: this.typeStatistics2,	
+		onLoad() {
+			this.level = this.userInfo.sysUser.level
+			if (this.level == 2) {
+				this.partnerTypeOption = this.partnerTypeOption.slice(0, -1);
 			}
-			let res = await this.$http.post('/APPPartner/getPartnerProportion', params);
-			if (res.code == '200' ) {
-				this.echartsList2=res.data
-				this.chartsDataPie2 = {
-					series: [{
-						"data": [
-							{ name: `新增`, 
-							  value: res.data.newProportion, 
-							  labelText: `${res.data.newProportion?'新增:'+res.data.newProportion+'%':'新增:0%'}` 
-							},
-							{ name: "历史", 
-							  value: res.data.oldProportion, 
-							  labelText: `${res.data.oldProportion?'历史:'+res.data.oldProportion+'%':'历史:0%'}`
-							}
-						]
-						// "data": [
-						// 	{ name: `新增`, value: res.data.newProportion?res.data.newProportion:0},
-						// 	{ name: "历史", value: res.data.oldProportion?res.data.oldProportion:0}
-						// ]
-					}]
-				}
-			
+			if (this.level == 3) {
+				this.partnerTypeOption = this.partnerTypeOption.slice(0, -2);
 			}
+			if (this.level == 4) {
+				this.partnerTypeOption = this.partnerTypeOption.slice(0, 1);
+			}
+			this.$http.get('/sys/qy/wechat/find/picture').then(res => {
+				this.supportStaffUrl = res.data.supportStaffUrl
+			})
 		},
-		async rankingQueryData() {
-			let params = {
-				type: this.typeStatistics3,
+		onShow() {
+			this.type = uni.getStorageSync('type')
+			// if(this.type ==2){
+			// 	this.queryData({type:1})
+			// }
+			// else{
+			// 	this.queryData({type:1})
+			// }
+			this.queryData()
+			if (this.type == 1 && this.level !== 5) {
+				this.analysisQueryData()
+				this.rankingQueryData()
 			}
-			let res = await this.$http.get('/APPPartner/getLevelPartner', params);
 
-			if (res.code == '200') {
-				this.directLsit = res.data
-			}
-		},
-		getTime(beginTime,endTime){
-			this.beginTime=beginTime
-			this.endTime=endTime
 		},
-		async queryData() { 
-			let params = {
-				beginTime: this.beginTime,
-				endTime: this.endTime,
-				type: this.typeStatistics,
-			}
-			let res = {}
-			if (this.type == 1 &&this.level!==5) {
-				res = await this.$http.post('/APPPartner/getPartnerCount', params);
-			}else if (this.type == 1 &&this.level==5) {
-				params = {
+
+		methods: {
+			canvasInit(canvas, width, height) {
+				// 初始化画布
+				this.canvas2d = canvas;
+			},
+			directDetail(val) {
+				uni.navigateTo({
+					url: "/pages/statistics/statisticsDetail?key=" + encodeURIComponent(JSON.stringify(val
+						.partnerIds))
+				})
+			},
+			getPartnerType2(type) {
+				this.typeStatistics2 = type
+				this.analysisQueryData()
+			},
+			getPartnerType3(type) {
+				this.typeStatistics3 = type
+				this.rankingQueryData()
+			},
+			getPartnerType(type) {
+				this.typeStatistics = type
+				this.queryData()
+			},
+			getStatistics(type) {
+				// 	uni.navigateTo({
+				// 	url: "/pages/tools/achievement/achievement"
+				// })
+				// this.studioType=type
+				this.typeStatistics = type
+				this.queryData()
+			},
+			//点击跳转企业微信客服
+			weChatService() {
+				uni.share({
+					provider: "weixin",
+					openCustomerServiceChat: true,
+					customerUrl: this.supportStaffUrl, //企业微信地址
+					corpid: 'wwfe67d19509d43ec5', //企业id
+					success: (res) => {},
+					fail: (err) => {}
+				});
+			},
+
+			async analysisQueryData() {
+				let params = {
 					beginTime: this.beginTime,
 					endTime: this.endTime,
-					number: this.typeStatistics,
+					type: this.typeStatistics2,
 				}
-				res = await this.$http.post('/APPPartner/getFivePartnerCount', params);
-			}
-			else {
-				res = await this.$http.post('/APPPartner/getCountUser', params);
-			}
-			if (res.code == '200') {
-				this.echartsList = res.data
-				
-				
-				if (res.data.countUserNumVoList && res.data.countUserNumVoList.length > 0) {
-					let dateList = res.data.countUserNumVoList.map(function (item) {
-						// return item.time.split(" ")[1] ? item.time.split(" ")[1] + ':00' : item.time.split(" ")[0]
-						return item.time
-					});
-					let valueList = res.data.countUserNumVoList.map(function (item) {
-						return item.countNum;
-					});
-					let rualit = {
-						categories:dateList ,
-						series: [
-							{
+				let res = await this.$http.post('/APPPartner/getPartnerProportion', params);
+				if (res.code == '200') {
+					this.echartsList2 = res.data
+					this.chartsDataPie2 = {
+						series: [{
+							"data": [{
+									name: `新增`,
+									value: res.data.newProportion,
+									labelText: `${res.data.newProportion?'新增:'+res.data.newProportion+'%':'新增:0%'}`
+								},
+								{
+									name: "历史",
+									value: res.data.oldProportion,
+									labelText: `${res.data.oldProportion?'历史:'+res.data.oldProportion+'%':'历史:0%'}`
+								}
+							]
+							// "data": [
+							// 	{ name: `新增`, value: res.data.newProportion?res.data.newProportion:0},
+							// 	{ name: "历史", value: res.data.oldProportion?res.data.oldProportion:0}
+							// ]
+						}]
+					}
+
+				}
+			},
+			async rankingQueryData() {
+				let params = {
+					type: this.typeStatistics3,
+				}
+				let res = await this.$http.get('/APPPartner/getLevelPartner', params);
+
+				if (res.code == '200') {
+					this.directLsit = res.data
+				}
+			},
+			getTime(beginTime, endTime) {
+				this.beginTime = beginTime
+				this.endTime = endTime
+			},
+			async queryData() {
+				let params = {
+					beginTime: this.beginTime,
+					endTime: this.endTime,
+					type: this.typeStatistics,
+				}
+				let res = {}
+				if (this.type == 1 && this.level !== 5) {
+					res = await this.$http.post('/APPPartner/getPartnerCount', params);
+				} else if (this.type == 1 && this.level == 5) {
+					params = {
+						beginTime: this.beginTime,
+						endTime: this.endTime,
+						number: this.typeStatistics,
+					}
+					res = await this.$http.post('/APPPartner/getFivePartnerCount', params);
+				} else {
+					res = await this.$http.post('/APPPartner/getCountUser', params);
+				}
+				if (res.code == '200') {
+					this.echartsList = res.data
+
+
+					if (res.data.countUserNumVoList && res.data.countUserNumVoList.length > 0) {
+						let dateList = res.data.countUserNumVoList.map(function(item) {
+							// return item.time.split(" ")[1] ? item.time.split(" ")[1] + ':00' : item.time.split(" ")[0]
+							return item.time
+						});
+						let valueList = res.data.countUserNumVoList.map(function(item) {
+							return item.countNum;
+						});
+						let rualit = {
+							categories: dateList,
+							series: [{
 								name: "人数",
 								// type: "line",
 								data: valueList
-							},
-						]
-					};
-					
-					this.chartData1 = JSON.parse(JSON.stringify(rualit));
-					valueList.sort((a, b) => a - b)
-					this.opts1.yAxis.data[0].max = valueList[valueList.length - 1];
-				}
-				else {
-					this.echartsList.countUserNumVoList = []
+							}]
+						};
+
+						this.chartData1 = JSON.parse(JSON.stringify(rualit));
+					} else {
+						this.echartsList.countUserNumVoList = []
+					}
 				}
 			}
 		}
 	}
-}
 </script>
 <style lang="scss" scoped>
-.headers {
-	position: fixed;
-	top: 0;
-	left: 0;
-	height: auto;
-	width: 100%;
-	z-index: 999999;
-	padding: 16px;
-	padding-top: 40px;
-
-	text {
-		font-size: 18px;
-		font-weight: 700;
-		color: #333333;
+	.headers {
+		position: fixed;
+		top: 0;
+		left: 0;
+		height: auto;
+		width: 100%;
+		z-index: 999999;
+		padding: 16px;
+		padding-top: 40px;
+
+		text {
+			font-size: 18px;
+			font-weight: 700;
+			color: #333333;
+		}
 	}
-}
 
-.headers-right {
-	position: absolute;
-	right: 15px;
-	display: flex;
-	align-items: center;
+	.headers-right {
+		position: absolute;
+		right: 15px;
+		display: flex;
+		align-items: center;
 
-	text {
-		font-size: 13px;
-		color: #666666;
-	}
+		text {
+			font-size: 13px;
+			color: #666666;
+		}
 
-	image {
-		// right: 0;
-		width: 15px;
-		height: 15px;
-		margin-right: 5px;
+		image {
+			// right: 0;
+			width: 15px;
+			height: 15px;
+			margin-right: 5px;
+		}
 	}
-}
-
-.body-box {
-	background: #ffffff;
-
-	margin: 15px
-}
-
-.statistics-title {
-	font-size: 16px;
-	color: #333333;
-}
-
-.statistics-title::before {
-	content: " ";
-	display: inline-block;
-	width: 4px;
-	height: 12px;
-	background: linear-gradient(132deg, #2DD9FF 0%, #2D6DFF 100%);
-	border-radius: 5px 5px 5px 5px;
-	margin-right: 4px;
-	margin-top: 2px;
-}
-
-.search-data {
-	color: #666666;
-	border: 1px solid #EEEEEE;
-
-	.active {
-		color: #FFFFFF;
-		background: linear-gradient(132deg, #2DD9FF 0%, #2D6DFF 100%);
+
+	.body-box {
+		background: #ffffff;
+
+		margin: 15px
 	}
 
-	text {
-		padding: 5px 6px;
-		border-left: 1px solid #EEEEEE;
+	.statistics-title {
+		font-size: 16px;
+		color: #333333;
 	}
 
-	text:first-child {
-		border-left: none
+	.statistics-title::before {
+		content: " ";
+		display: inline-block;
+		width: 4px;
+		height: 12px;
+		background: linear-gradient(132deg, #2DD9FF 0%, #2D6DFF 100%);
+		border-radius: 5px 5px 5px 5px;
+		margin-right: 4px;
+		margin-top: 2px;
 	}
-}
 
-.statistics-number {
-	margin: 10px 10px 20px 10px;
-	background: #FBFBFB;
-	border-radius: 4px 4px 4px 4px;
-	text-align: center;
-	padding: 15px 0;
-	overflow: hidden;
+	.search-data {
+		color: #666666;
+		border: 1px solid #EEEEEE;
 
-	view {
-		width: 33.33%;
-		float: left;
+		.active {
+			color: #FFFFFF;
+			background: linear-gradient(132deg, #2DD9FF 0%, #2D6DFF 100%);
+		}
 
-	}
+		text {
+			padding: 5px 6px;
+			border-left: 1px solid #EEEEEE;
+		}
 
-	text {
-		display: block;
+		text:first-child {
+			border-left: none
+		}
 	}
 
-	text:first-child {
-		font-size: 25px;
-		color: #333333;
-	}
+	.statistics-number {
+		margin: 10px 10px 20px 10px;
+		background: #FBFBFB;
+		border-radius: 4px 4px 4px 4px;
+		text-align: center;
+		padding: 15px 0;
+		overflow: hidden;
+
+		view {
+			width: 33.33%;
+			float: left;
+
+		}
 
-	text:last-child {
-		font-size: 13px;
-		color: #999999;
+		text {
+			display: block;
+		}
+
+		text:first-child {
+			font-size: 25px;
+			color: #333333;
+		}
+
+		text:last-child {
+			font-size: 13px;
+			color: #999999;
+		}
 	}
-}
 
-.statistics-type {
-	text-align: center;
-margin-bottom: 20px;
-	text {
-		display: inline-block;
-		width: 80px;
-		height: 30px;
-		line-height: 30px;
+	.statistics-type {
 		text-align: center;
-		font-size: 16px;
-		color: #666666;
-		background: #F4F4F4;
-	}
+		margin-bottom: 20px;
+
+		text {
+			display: inline-block;
+			width: 80px;
+			height: 30px;
+			line-height: 30px;
+			text-align: center;
+			font-size: 16px;
+			color: #666666;
+			background: #F4F4F4;
+		}
 
-	.selected {
-		color: #FFFFFF;
-		background: linear-gradient(132deg, #2DD9FF 0%, #2D6DFF 100%);
-	}
+		.selected {
+			color: #FFFFFF;
+			background: linear-gradient(132deg, #2DD9FF 0%, #2D6DFF 100%);
+		}
 
-	// text:first-child{
-	// 	color: #FFFFFF;
-	// 	background: linear-gradient( 132deg, #2DD9FF 0%, #2D6DFF 100%);
+		// text:first-child{
+		// 	color: #FFFFFF;
+		// 	background: linear-gradient( 132deg, #2DD9FF 0%, #2D6DFF 100%);
 
-	// }
-}
+		// }
+	}
 
-.partner-type {
-	margin: 10px;
-	width: 97%;
-	overflow: hidden;
-	white-space: nowrap;
+	.partner-type {
+		margin: 10px;
+		width: 97%;
+		overflow: hidden;
+		white-space: nowrap;
+
+		text {
+			display: inline-block;
+			border-radius: 14px 14px 14px 14px;
+			font-size: 14px;
+			color: #666666;
+			padding: 1px 10px;
+			background: #F4F4F4;
+			margin-right: 8px;
+		}
 
-	text {
-		display: inline-block;
-		border-radius: 14px 14px 14px 14px;
-		font-size: 14px;
-		color: #666666;
-		padding: 1px 10px;
-		background: #F4F4F4;
-		margin-right: 8px;
+		.selected {
+			color: #FFFFFF;
+			background: linear-gradient(132deg, #2DD9FF 0%, #2D6DFF 100%);
+		}
 	}
 
-	.selected {
-		color: #FFFFFF;
-		background: linear-gradient(132deg, #2DD9FF 0%, #2D6DFF 100%);
+	.teamStatistics {
+		margin: 10px;
+		background: #FFFFFF;
+		// box-shadow: 0px 4px 10px 0px #DAE3F4;
+		border-radius: 2px 2px 2px 2px;
+		border: 1px solid #C8D8FF;
 	}
-}
-
-.teamStatistics {
-	margin: 10px;
-	background: #FFFFFF;
-	// box-shadow: 0px 4px 10px 0px #DAE3F4;
-	border-radius: 2px 2px 2px 2px;
-	border: 1px solid #C8D8FF;
-}
-
-.statisticsContent {
-	box-sizing: border-box;
-	height: 70upx;
-	text-align: center;
-	line-height: 70upx;
-	font-size: 26rpx;
-	color: #666666;
-	display: flex;
-	flex-wrap: nowrap;
-	justify-content: space-around;
-
-	view {
+
+	.statisticsContent {
+		box-sizing: border-box;
+		height: 70upx;
 		text-align: center;
 		line-height: 70upx;
-		width: 25%;
-		font-size: 12px;
-	}
+		font-size: 26rpx;
+		color: #666666;
+		display: flex;
+		flex-wrap: nowrap;
+		justify-content: space-around;
+
+		view {
+			text-align: center;
+			line-height: 70upx;
+			width: 25%;
+			font-size: 12px;
+		}
 
-	image {
-		display: inline-block;
-		width: 21px;
-		height: 21px;
-		vertical-align: middle;
-	}
-}
-
-.statisticsTitle {
-	display: flex;
-	flex-wrap: nowrap;
-	justify-content: space-around;
-	height: 70upx;
-	box-sizing: border-box;
-	line-height: 70upx;
-	font-size: 24rpx;
-	color: #232832;
-	background: linear-gradient(180deg, #DAE0EE 0%, #E9ECF4 100%);
-	// border-radius: 6px 6px 0 0;
-
-	view {
-		text-align: center;
-		line-height: 35px;
-		color: #2D6DFF;
-		width: 25%;
-		font-size: 12px;
+		image {
+			display: inline-block;
+			width: 21px;
+			height: 21px;
+			vertical-align: middle;
+		}
 	}
 
-}
+	.statisticsTitle {
+		display: flex;
+		flex-wrap: nowrap;
+		justify-content: space-around;
+		height: 70upx;
+		box-sizing: border-box;
+		line-height: 70upx;
+		font-size: 24rpx;
+		color: #232832;
+		background: linear-gradient(180deg, #DAE0EE 0%, #E9ECF4 100%);
+		// border-radius: 6px 6px 0 0;
+
+		view {
+			text-align: center;
+			line-height: 35px;
+			color: #2D6DFF;
+			width: 25%;
+			font-size: 12px;
+		}
+
+	}
 
-.charts-box {
-	width: 100%;
-	height: 300px;
-}
+	.charts-box {
+		width: 100%;
+		height: 300px;
+	}
 </style>

BIN
static/applicationSuccess.png


BIN
static/image/my/updateAvatar.png


BIN
static/shouye1.png