Browse Source

人脸识别

qzyReal 1 year ago
parent
commit
089e3ab7e5

+ 68 - 0
common/common.js

@@ -0,0 +1,68 @@
+export default {
+
+	getuid() {
+		return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
+			var r = Math.random() * 16 | 0,
+				v = c == 'x' ? r : (r & 0x3 | 0x8);
+			return v.toString(16);
+		});
+	},
+
+	// 提示信息
+	toast(msg, icon = 'none', duration = 2000, mask) {
+		uni.showToast({
+			"icon": icon,
+			"title": msg,
+			"mask": mask || false,
+			"duration": duration
+		})
+	},
+	showLoading(msg) {
+		uni.showLoading({
+			'title': msg,
+			'mask': true
+		})
+	},
+	hidingLoading() {
+		uni.hideLoading();
+	},
+	// 提示信息 底部
+	toastBottom(msg, icon = 'none', duration = 2000, mask = false) {
+		uni.showToast({
+			"icon": icon,
+			"title": msg,
+			"mask": mask,
+			"duration": duration,
+			"position": 'bottom'
+		})
+	},
+	// 路由跳转
+	to(url) {
+		uni.navigateTo({
+			url: url,
+			animationType: 'slide-in-right',
+			animationDuration: 300
+		})
+	},
+	toBar(url) {
+		uni.switchTab({
+			url: url
+		})
+	},
+	// 返回上一页
+	back() {
+		uni.navigateBack({
+			delta: 1,
+			animationType: 'pop-out',
+			animationDuration: 200
+		})
+	},
+	// 验证邮箱
+	isEmail(email) {
+		let reg = /^([a-zA-Z]|[0-9])(\w|\-)+@[a-zA-Z0-9]+\.([a-zA-Z]{2,4})$/;
+		if (!reg.test(email)) {
+			this.$common.toast('请输入正确邮箱格式')
+		}
+		return reg.test(email)
+	}
+}

+ 2 - 2
common/http.js

@@ -1,6 +1,6 @@
 
-const ip = 'http://127.0.0.1:8080'; //线下
-// const ip = 'http://hs-server.aseanbusiness.cn'; //线上
+// const ip = 'http://192.168.2.8:8080'; //线下
+const ip = 'http://hs-server.aseanbusiness.cn'; //线上
 
 //const ip = 'http://192.168.88.36:8080'; //线下
 

+ 2 - 0
main.js

@@ -3,6 +3,7 @@ import uView from "uview-ui";
 import verify from './common/graceChecker.js' //数据校验证
 import http from './common/http.js'
 import util from './common/util.js' //工具类
+import common from './common/common.js' //工具类
 
 Vue.use(uView);
 // #ifndef VUE3
@@ -12,6 +13,7 @@ App.mpType = 'app'
 Vue.prototype.verify = verify;
 Vue.prototype.http = http;
 Vue.prototype.util = util;
+Vue.prototype.common = common;
 Vue.prototype.getUser = function() {
 	return uni.getStorageSync('info');
 }

+ 17 - 1
manifest.json

@@ -1,6 +1,6 @@
 {
     "name" : "边民互市贸易系统",
-    "appid" : "__UNI__8AC923A",
+    "appid" : "__UNI__4E5B775",
     "description" : "",
     "versionName" : "1.0.0",
     "versionCode" : "100",
@@ -90,6 +90,22 @@
                     }
                 }
             }
+        },
+        "nativePlugins" : {
+            "epii-camera" : {
+                "__plugin_info__" : {
+                    "name" : "摄像头组件 相机组件 内嵌的区域相机组件 自动聚焦 聚焦 缩放 变焦 闪光灯 - [试用版,仅用于自定义调试基座]",
+                    "description" : "摄像头组件,相机组件,内嵌的区域相机组件,可实现拍照,录制视频。支持自定义布局,点击聚焦,手势缩放 qq 543169072",
+                    "platforms" : "Android,iOS",
+                    "url" : "https://ext.dcloud.net.cn/plugin?id=3583",
+                    "android_package_name" : "",
+                    "ios_bundle_id" : "",
+                    "isCloud" : true,
+                    "bought" : 0,
+                    "pid" : "3583",
+                    "parameters" : {}
+                }
+            }
         }
     },
     /* 快应用特有相关 */

+ 12 - 0
pages.json

@@ -52,6 +52,18 @@
 
 		},
 		{
+			"path": "pages/face/faceRegister",
+			"style": {
+				"navigationBarTitleText": "人脸录入"
+			}
+		},
+		{
+			"path": "pages/login/faceLogin",
+			"style": {
+				"navigationBarTitleText": "人脸登录"
+			}
+		},
+		{
 			"path": "pages/authentication/index",
 			"style": {
 				"navigationBarTitleText": "实人认证",

+ 3 - 2
pages/authentication/face.vue

@@ -15,14 +15,15 @@ export default {
 		};
 	},
 	onLoad() {
+		uni.startFacialRecognitionVerify();
 		let increment = 100 / 3; // 每秒递增的进度值
 		let countdown = setInterval(() => {
 			this.progress += increment;
 			if (this.progress >= 100) {
 				this.progress = 100;
 				clearInterval(countdown); // 达到100后清除定时器
-				uni.$emit('face');
-				uni.navigateBack();
+				//uni.$emit('face');
+				//uni.navigateBack();
 			}
 		}, 1000);
 	}

+ 282 - 0
pages/face/faceRegister.nvue

@@ -0,0 +1,282 @@
+<template>
+	<view class="main" id="main">
+		<epii-camera ref="camera" class="epiiCamer" :style="{width:width,height:height}"></epii-camera>
+		<cover-view>
+			<image :style="{width:width,height:height}" src="../../static/sl.gif" mode="scaleToFill"></image>
+		</cover-view>
+	</view>
+</template>
+<script>
+	import http from '../../common/http.js'
+	export default {
+		data() {
+			return {
+				cameraId: 0,
+				height: "500rpx",
+				width: "750rpx",
+				userId: '',
+			}
+		},
+		onLoad(options) {
+			this.userId = options.id;
+			this.height = uni.getSystemInfoSync().screenHeight * 2 + 'rpx';
+			this.$nextTick(() => {
+				//这里可以做打开摄像头等功能
+				this.openCamera(1)
+			})
+		},
+		beforeDestroy() {
+			this.release();
+		},
+		mounted() {
+			console.log(this.$refs.camera)
+			//this.common.hidingLoading();
+		},
+		methods: {
+			takePicture(e) {
+				const that = this;
+				that.$refs.camera.takePicture({
+					base64: false,
+					quailty: 100,
+				}, function(data) {
+					let img = data.img;
+					that.registerFace(img);
+					return
+				});
+			},
+			registerFace(img) {
+				const that = this;
+				uni.uploadFile({
+					url: http.ip + '/sp-admin/app/AppUser/face',
+					filePath: 'file://' + img,
+					name: 'file',
+					formData: {
+						id: that.userId
+					},
+					header: {
+						satoken: uni.getStorageSync('token')
+					},
+					success(resp) {
+						let res = JSON.parse(resp.data);
+						if (res.code == 200) {
+							that.release();
+							uni.showToast({
+								title: '录入成功'
+							})
+							let user=uni.getStorageSync('info');
+							console.log(user);
+							user.face=1;
+							uni.setStorageSync('info',user)
+							setTimeout(()=>{
+								uni.navigateBack();
+								uni.hideLoading();
+							},500)
+						} else {
+							uni.showToast({
+								icon:'none',
+								title: res.msg
+							})
+							setTimeout(function() {
+								that.takePicture();
+							}, 600);
+						}
+
+					}
+				})
+			},
+			release() {
+				this.$refs.camera.release();
+			},
+			openCamera(id) {
+				if (uni.getSystemInfoSync().platform === "ios") {
+					let that = this;
+					this.$refs.camera.openCamera({
+						cameraId: id,
+					}, function(data) {
+						setTimeout(function() {
+							that.takePicture();
+						}, 1000);
+					});
+				} else {
+					//android 系统需要考虑 组件的宽高 和摄像头的宽高比例,如果不一致会导致拉伸
+					this.openCamera_1(id);
+				}
+			},
+			openCamera_1(id) {
+				//安卓解决拉伸问题,一般有两种思路。
+				//1. 组件宽高不变,找出最适合的分辨比率
+				//2. 根据摄像头的分辨率,来重新修改组件的宽和高。
+				this.cid = id;
+				let type = 2; //1  组件宽高不变,找出最适合的分辨比率  2根据摄像头的分辨率,来重新修改组件的宽和高。
+				this.$refs.camera.getSupportedPreviewSizesByCameraId({
+					cameraId: id
+				}, (data) => {
+					let bestHeight_index = 0;
+					//方法1 组件宽高不变,找出最适合的分辨比率,这样只能减少拉伸,不能解决
+					if (type == 1) {
+						let r0 = (this.height * 1.0) / this.width;
+						let diff = 1000;
+						for (var i = 0; i < data.sizes.length; i++) {
+							console.log(data.sizes[i]);
+							//找出最合适的分辨率,宽高比例尽量接近组件的(摄像头宽高是反着呢)
+							let tmp = Math.abs(r0 - (data.sizes[i].width * 1.0) / data.sizes[bestHeight_index]
+								.width);
+							if (tmp < diff) {
+								diff = tmp;
+								bestHeight_index = i;
+							}
+						}
+						//方法2 先获取摄像头 支持的分辨率,然后修改组件的大小(一般保持宽不变),这样肯定不拉伸	 
+					} else if (type == 2) {
+						for (var i = 0; i < data.sizes.length; i++) {
+							//找出最大高度对应的分辨比率(宽高是反着呢)
+							if (data.sizes[i].width > data.sizes[bestHeight_index].width) {
+								bestHeight_index = i;
+							}
+						}
+						//this.width = data.sizes[max_index].height;
+						//计算出当前宽度下最适合的高度,然后修改组件的高
+						this.height = ((data.sizes[bestHeight_index].width / (data.sizes[bestHeight_index].height *
+							1.0)) * 750) + "rpx";
+						// 3 用最大分辨比率,不考虑拉伸	
+					} else if (type == 3) {
+						bestHeight_index = 0; //最大的一般是第一个,你也可以遍历后找出最大分辨比率
+
+					}
+					//延迟打开摄像头,组件大小修改需要时间	
+					const that = this;
+					setTimeout(() => {
+						this.$refs.camera.openCamera({
+							cameraId: id,
+							previewWidth: data.sizes[bestHeight_index].width,
+							previewHeight: data.sizes[bestHeight_index].height
+						}, function(data) {
+							setTimeout(function() {
+								that.takePicture();
+							}, 1000);
+						});
+					}, 500);
+				});
+				return;
+			},
+			switchCamera() {
+				this.cameraId == 0 ? this.cameraId = 1 : this.cameraId = 0
+				this.$refs.camera.switchCamera({
+					cameraId: this.cameraId
+				}, function(data) {
+					uni.showModal({
+						content: JSON.stringify(data)
+					})
+				});
+			},
+			start() {
+				this.$refs.camera.startRecord({
+					videoEncodingBitRate: 3 * 1920 * 1080
+				});
+			},
+			stop() {
+				this.$refs.camera.stopRecord(function(data) {
+					//可以通过 uni.compressVideo 压缩视频 记得前缀 file://
+					uni.showModal({
+						content: JSON.stringify(data)
+					})
+				});
+			},
+			release() {
+				this.$refs.camera.release();
+			},
+			flashOpen() {
+				this.$refs.camera.flashOpen();
+			},
+			flashClose() {
+				this.$refs.camera.flashClose();
+			},
+			changeSize() {
+				this.height = "1100rpx";
+
+			},
+			getSupportedPreviewSizes() {
+				this.$refs.camera.getSupportedPreviewSizes((ret) => {
+					uni.showModal({
+						content: JSON.stringify(ret)
+					})
+				});
+			}
+		}
+	}
+</script>
+
+<style scoped>
+	.main {
+		position: relative;
+		width: 750rpx;
+		flex: 1;
+		overflow: hidden;
+	}
+
+	.operate-bg {
+		width: 750rpx;
+		background-color: #000000;
+		position: absolute;
+		left: 0;
+		bottom: 0;
+		justify-content: center;
+		align-items: center;
+		padding-top: 60rpx;
+		padding-bottom: 60rpx;
+	}
+
+	.operate {
+		width: 140rpx;
+		height: 140rpx;
+		background-color: #fff;
+		border-radius: 50%;
+		border-width: 10rpx;
+		border-style: solid;
+		border-color: #453f3f;
+	}
+
+	.change {
+		width: 96rpx;
+		height: 96rpx;
+		background-color: #453f3f;
+		position: absolute;
+		right: 60rpx;
+		bottom: 82rpx;
+		border-radius: 48rpx;
+		align-items: center;
+		justify-content: center;
+	}
+
+	.change-img {
+		width: 56rpx;
+		height: 56rpx;
+	}
+
+	.portrait-frame {
+		width: 750rpx;
+		flex: 1;
+		position: absolute;
+		top: 0;
+		left: 0;
+		right: 0;
+		bottom: 0;
+		align-items: center;
+		justify-content: center;
+		background-color: rgba(0, 0, 0, 0);
+	}
+
+	.pf-img {
+		width: 633.6rpx;
+		height: 582rpx;
+		margin-top: -280rpx;
+	}
+
+	.epiiCamer {
+		position: absolute;
+		top: 0;
+		right: 0;
+		bottom: 0;
+		left: 0;
+	}
+</style>

+ 270 - 187
pages/index/index.vue

@@ -4,16 +4,19 @@
 		<view class="cmain">
 			<view class="vsearch">
 				<view class="vse">
-					<u-search placeholder="搜索资讯" v-model="keyword" @search="search" :actionStyle="{ color: 'white' }" :animation="true" actionText="取消"></u-search>
+					<u-search placeholder="搜索资讯" v-model="keyword" @search="search" :actionStyle="{ color: 'white' }"
+						:animation="true" actionText="取消"></u-search>
 				</view>
 				<view class="icon" @click="message()">&#xe60d;</view>
 				<view class="bage" v-if="count > 0"></view>
 			</view>
 			<!--轮播图-->
-			<u-swiper circular :radius="5" :indicator="true" keyName="image" :list="bannerList" :height="110" class="uni-swiper" @click="click"></u-swiper>
+			<u-swiper circular :radius="5" :indicator="true" keyName="image" :list="bannerList" :height="110"
+				class="uni-swiper" @click="click"></u-swiper>
 			<!--通知公告-->
 			<view class="notice">
-				<u-notice-bar color="#848484" :text="noticeList" :step="true" direction="column" mode="link" bgColor="white" speed="300" url="/pages/notice/index"></u-notice-bar>
+				<u-notice-bar color="#848484" :text="noticeList" :step="true" direction="column" mode="link"
+					bgColor="white" speed="300" url="/pages/notice/index"></u-notice-bar>
 			</view>
 			<!--菜单-->
 			<view class="menu">
@@ -38,7 +41,8 @@
 					</text>
 				</view>
 				<view class="list animated fadeInDown">
-					<view class="news_item" v-for="(item, index) in newsList" :key="index" @click="go('/pages/news/detail?id=' + item.id)">
+					<view class="news_item" v-for="(item, index) in newsList" :key="index"
+						@click="go('/pages/news/detail?id=' + item.id)">
 						<image :src="item.cover" mode="aspectFill" class="img" v-if="item.cover"></image>
 						<image src="../../static/tp.jpg" mode="aspectFill" class="img" v-else></image>
 						<view class="con">
@@ -53,7 +57,8 @@
 				</view>
 			</view>
 		</view>
-		<u-popup :show="show" @close="close()" round="15" mode="center" :closeOnClickOverlay="false" :customStyle="{ width: '90%' }">
+		<u-popup :show="show" @close="close()" round="15" mode="center" :closeOnClickOverlay="false"
+			:customStyle="{ width: '90%' }">
 			<view class="ppopup">
 				<u-divider text="交易订单提醒" textSize="16"></u-divider>
 				<view class="contents">
@@ -73,211 +78,289 @@
 				<button class="btn" @click="confirm()">去处理</button>
 			</view>
 		</u-popup>
+		<u-popup :show="faceRegister" @close="close()" round="15" mode="center" :closeOnClickOverlay="false"
+			:customStyle="{ width: '90%' }">
+			<view class="reflush" @click="checkFace">刷新</view>
+			<view class="ppopup">
+				<u-divider text="人脸录入" textSize="16"></u-divider>
+				<view class="contents">
+					<view class="item omit">
+						<text class="label">边民信息:</text>
+						<text class="desc">{{ user.name }}({{ user.phone }})</text>
+					</view>
+
+					<view style="text-indent: 2rem;line-height: 60rpx;">
+						根据相关规定,边民进行互市贸易需要确保为本人实际操作,为了确保后续交易的合规合法话,需要您先录入人脸!</view>
+				</view>
+				<button class="btn" @click="go('/pages/face/faceRegister')">马上录入</button>
+			</view>
+		</u-popup>
 	</view>
 </template>
 
 <script>
-export default {
-	data() {
-		return {
-			keyword: '',
-			bannerList: [],
-			newsList: [],
-			noticeList: ['边民互市贸易APP上线了', '关于边民互市贸易开通注意事项'],
-			roleMenu: [],
-			menuList: [],
-			count: 0,
-			show: false,
-			order: {},
-			user:{}
-		};
-	},
-	onLoad() {
-		this.user=this.getUser();
-		this.getBannerList();
-		this.getNewsList();
-		this.getMenu();
-		uni.$on('getMenu', res => {
+	export default {
+		data() {
+			return {
+				keyword: '',
+				bannerList: [],
+				newsList: [],
+				noticeList: ['边民互市贸易APP上线了', '关于边民互市贸易开通注意事项'],
+				roleMenu: [],
+				menuList: [],
+				count: 0,
+				show: false,
+				order: {},
+				user: {},
+				faceRegister: false
+			};
+		},
+		onLoad() {
+			let user = this.getUser();
+			this.user = user;
+			this.getBannerList();
+			this.getNewsList();
 			this.getMenu();
-		});
-	},
-	onShow() {
-		this.keyword = '';
-		this.getRead();
-		this.getOrderConfirm();
-	},
-	methods: {
-		//获取待处理的订单弹出
-		getOrderConfirm() {
-			let user=this.getUser();
-			console.log(user);
-			if(user.userType>2){
-				return;
-			}
-			this.http.request({
-				url: '/level-one-server/app/TbOrder/getNoConfirmOrder',
-				loading: 'false',
-				success: res => {
-					if (res.data.data) {
-						this.order = res.data.data;
-						this.show = true;
-					}
-				}
+			uni.$on('getMenu', res => {
+				this.getMenu();
 			});
 		},
-		confirm() {
-			if(this.order.declareType == '1') {
-				uni.navigateTo({ url: '/pages/market/one/leader/handle?orderId=' + this.order.id });
-			} else {
-				uni.navigateTo({ url: '/pages/market/one/leader/handleThree?orderId=' + this.order.id + '&peopleConfirmStatus=' + this.order.peopleConfirmStatus + '&cooperEntrustStatus=' + this.order.cooperEntrustStatus+ '&applyConfirmStatus=' + this.order.applyConfirmStatus});
-			}
-			this.show = false;
+		onShow() {
+			this.checkFace()
+			this.keyword = '';
+			this.getRead();
+			this.getOrderConfirm();
 		},
-		getRead() {
-			this.http.request({
-				url: '/sp-admin/app/TbMessage/getRead',
-				loading: 'false',
-				success: res => {
-					if (res.data.data.count > 0) {
-						this.count = res.data.data.count;
-						uni.setTabBarBadge({ index: 1, text: res.data.data.count });
-					} else {
-						this.count = 0;
-					}
+		methods: {
+			checkFace() {
+				let user = this.getUser();
+				console.log(user);
+				if ((user.userType == 1 || user.userType == 2) && user.face == 0) {
+					this.faceRegister = true;
+					return;
 				}
-			});
-		},
-		getBannerList() {
-			this.http.request({
-				url: '/level-one-server/app/TbBanner/getList',
-				success: res => {
-					this.bannerList = res.data.data;
+				this.faceRegister=false;
+			},
+			go(url) {
+				uni.navigateTo({
+					url: url
+				});
+			},
+			//获取待处理的订单弹出
+			getOrderConfirm() {
+				let user = this.getUser();
+				if (user.userType > 2) {
+					return;
 				}
-			});
-		},
-		getMenu() {
-			this.menuList = [];
-			let menu = uni.getStorageSync('menu');
-			this.http.request({
-				url: '/sp-admin/app/AppMenu/getList',
-				success: res => {
-					let data = res.data.data;
-					menu.map((item2, index1) => {
-						data.map((item1, index) => {
-							if (parseInt(item1.id) == parseInt(item2)) {
-								this.menuList.push(item1);
-							}
-						});
+				this.http.request({
+					url: '/level-one-server/app/TbOrder/getNoConfirmOrder',
+					loading: 'false',
+					success: res => {
+						if (res.data.data) {
+							this.order = res.data.data;
+							this.show = true;
+						}
+					}
+				});
+			},
+			confirm() {
+				if (this.order.declareType == '1') {
+					uni.navigateTo({
+						url: '/pages/market/one/leader/handle?orderId=' + this.order.id
+					});
+				} else {
+					uni.navigateTo({
+						url: '/pages/market/one/leader/handleThree?orderId=' + this.order.id +
+							'&peopleConfirmStatus=' + this.order.peopleConfirmStatus + '&cooperEntrustStatus=' +
+							this.order.cooperEntrustStatus + '&applyConfirmStatus=' + this.order.applyConfirmStatus
 					});
-					this.menuList.sort((a, b) => a.sort - b.sort);
 				}
-			});
-		},
-		getNewsList() {
-			this.http.request({
-				url: '/level-one-server/app/TbPortNews/getNewestList',
-				data: { limit: 3 },
-				success: res => {
-					this.newsList = res.data.data;
+				this.show = false;
+			},
+			getRead() {
+				this.http.request({
+					url: '/sp-admin/app/TbMessage/getRead',
+					loading: 'false',
+					success: res => {
+						if (res.data.data.count > 0) {
+							this.count = res.data.data.count;
+							uni.setTabBarBadge({
+								index: 1,
+								text: res.data.data.count
+							});
+						} else {
+							this.count = 0;
+						}
+					}
+				});
+			},
+			getBannerList() {
+				this.http.request({
+					url: '/level-one-server/app/TbBanner/getList',
+					success: res => {
+						this.bannerList = res.data.data;
+					}
+				});
+			},
+			getMenu() {
+				this.menuList = [];
+				let menu = uni.getStorageSync('menu');
+				this.http.request({
+					url: '/sp-admin/app/AppMenu/getList',
+					success: res => {
+						let data = res.data.data;
+						menu.map((item2, index1) => {
+							data.map((item1, index) => {
+								if (parseInt(item1.id) == parseInt(item2)) {
+									this.menuList.push(item1);
+								}
+							});
+						});
+						this.menuList.sort((a, b) => a.sort - b.sort);
+					}
+				});
+			},
+			getNewsList() {
+				this.http.request({
+					url: '/level-one-server/app/TbPortNews/getNewestList',
+					data: {
+						limit: 3
+					},
+					success: res => {
+						this.newsList = res.data.data;
+					}
+				});
+			},
+			//点击轮播图
+			click(index) {
+				uni.navigateTo({
+					url: '/pages/news/detail?id=8'
+				});
+			},
+			message() {
+				uni.switchTab({
+					url: '/pages/message/message'
+				});
+			},
+			search() {
+				uni.navigateTo({
+					url: '/pages/news/list?keyword=' + this.keyword
+				});
+			},
+			navTo(url) {
+				//收购商需要认证才给访问
+				if (this.getUser().userType == 3 && !this.hasAuth()) {
+					uni.navigateTo({
+						url: '/pages/authentication/index'
+					});
+					return;
 				}
-			});
-		},
-		//点击轮播图
-		click(index) {
-			uni.navigateTo({ url: '/pages/news/detail?id=8' });
-		},
-		message() {
-			uni.switchTab({ url: '/pages/message/message' });
-		},
-		search() {
-			uni.navigateTo({ url: '/pages/news/list?keyword=' + this.keyword });
-		},
-		navTo(url) {
-			//收购商需要认证才给访问
-			if (this.getUser().userType == 3 && !this.hasAuth()) {
-				uni.navigateTo({ url: '/pages/authentication/index' });
-				return;
+				uni.navigateTo({
+					url: url,
+					fail: res => {
+						console.log('zx:' + JSON.stringify(res));
+						uni.showModal({
+							content: '功能还在开发中',
+							showCancel: false
+						});
+					}
+				});
+			},
+			go(url) {
+				uni.navigateTo({
+					url: url
+				});
 			}
-			uni.navigateTo({
-				url: url,
-				fail: res => {
-					console.log('zx:' + JSON.stringify(res));
-					uni.showModal({ content: '功能还在开发中', showCancel: false });
-				}
-			});
 		},
-		go(url) {
-			uni.navigateTo({ url: url });
+		//下拉刷新
+		onPullDownRefresh() {
+			setTimeout(() => {
+				uni.stopPullDownRefresh();
+				this.getMenu();
+			}, 1000);
 		}
-	},
-	//下拉刷新
-	onPullDownRefresh() {
-		setTimeout(() => {
-			uni.stopPullDownRefresh();
-			this.getMenu();
-		}, 1000);
-	}
-};
+	};
 </script>
 <style lang="scss">
-page {
-	background-color: $pg;
-}
-.top {
-	width: 100%;
-	position: relative;
-}
-.cmain {
-	padding: 10px 15px 10px 15px;
-	margin-top: -183px;
-	position: relative;
-	.vsearch {
-		margin-bottom: 13px;
+	page {
+		background-color: $pg;
+	}
+
+	.top {
+		width: 100%;
+		position: relative;
+	}
+
+	.cmain {
+		padding: 10px 15px 10px 15px;
+		margin-top: -183px;
 		position: relative;
-		.vse {
-			width: 82% !important;
+
+		.vsearch {
+			margin-bottom: 13px;
+			position: relative;
+
+			.vse {
+				width: 82% !important;
+			}
+
+			.icon {
+				position: absolute;
+				right: 0px;
+				top: 0px;
+				color: white;
+				font-size: 25px;
+				top: 5px;
+			}
+
+			.bage {
+				width: 8px;
+				height: 8px;
+				border-radius: 50%;
+				background-color: #f44336;
+				top: 0px;
+				right: 0px;
+				position: absolute;
+			}
 		}
-		.icon {
-			position: absolute;
-			right: 0px;
-			top: 0px;
-			color: white;
-			font-size: 25px;
-			top: 5px;
+
+		.uni-swiper {
+			box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
 		}
-		.bage {
-			width: 8px;
-			height: 8px;
-			border-radius: 50%;
-			background-color: #f44336;
-			top: 0px;
-			right: 0px;
-			position: absolute;
+
+		.notice {
+			margin-top: 10px;
+			border-radius: 5px !important;
+			overflow: hidden;
+		}
+
+		.news {
+			margin-top: 15px;
 		}
 	}
-	.uni-swiper {
-		box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
-	}
-	.notice {
-		margin-top: 10px;
-		border-radius: 5px !important;
-		overflow: hidden;
-	}
-	.news {
-		margin-top: 15px;
+
+	.reflush {
+		width: 60rpx;
+		height: 60rpx;
+		float: right;
+		position: absolute;
+		right: 20rpx;
+		padding: 20rpx;
+		font-size: 24rpx;
 	}
-}
-.ppopup {
-	.item {
-		padding: 5px 0px 5px 0px;
-		color: $font-c;
-		.label {
-			width: 70px;
-			float: left;
-			text-align: left;
-			padding-right: 10px;
-			font-weight: bold;
+
+	.ppopup {
+		.item {
+			padding: 5px 0px 5px 0px;
+			color: $font-c;
+
+			.label {
+				width: 70px;
+				float: left;
+				text-align: left;
+				padding-right: 10px;
+				font-weight: bold;
+			}
 		}
 	}
-}
-</style>
+</style>

+ 282 - 0
pages/login/faceLogin.nvue

@@ -0,0 +1,282 @@
+<template>
+	<view class="main" id="main">
+		<epii-camera ref="camera" class="epiiCamer" :style="{width:width,height:height}"></epii-camera>
+		<cover-view>
+			<image :style="{width:width,height:height}" src="../../static/sl.gif" mode="scaleToFill"></image>
+		</cover-view>
+	</view>
+</template>
+<script>
+	import http from '../../common/http.js'
+	export default {
+		data() {
+			return {
+				cameraId: 0,
+				height: "500rpx",
+				width: "750rpx",
+				userId: '',
+			}
+		},
+		onLoad(options) {
+			this.userId = options.id;
+			this.height = uni.getSystemInfoSync().screenHeight * 2 + 'rpx';
+			this.$nextTick(() => {
+				//这里可以做打开摄像头等功能
+				this.openCamera(1)
+			})
+		},
+		beforeDestroy() {
+			this.release();
+		},
+		mounted() {
+			console.log(this.$refs.camera)
+			//this.common.hidingLoading();
+		},
+		methods: {
+			takePicture(e) {
+				const that = this;
+				that.$refs.camera.takePicture({
+					base64: false,
+					quailty: 100,
+				}, function(data) {
+					let img = data.img;
+					that.registerFace(img);
+					return
+				});
+			},
+			registerFace(img) {
+				const that = this;
+				uni.uploadFile({
+					url: http.ip + '/sp-admin/app/AppUser/faceLogin',
+					filePath: 'file://' + img,
+					name: 'file',
+					formData: {
+						id: that.userId
+					},
+					header: {
+						satoken: uni.getStorageSync('token')
+					},
+					success(resp) {
+						let res = JSON.parse(resp.data);
+						if (res.code == 200) {
+							that.release();
+							setTimeout(()=>{
+								let data=res.data;
+								uni.setStorageSync('token', data.tokenInfo.tokenValue);
+								uni.setStorageSync('info', data.appUser);
+								uni.setStorageSync('menu', data.per_list);
+								uni.showToast({ title: '登录成功' });
+								setTimeout(() => {
+									uni.$emit('getMenu');
+									uni.switchTab({ url: '/pages/index/index' });
+								}, 1000);
+							},500)
+						} else {
+							uni.showToast({
+								icon:'none',
+								title: res.msg
+							})
+							setTimeout(function() {
+								that.takePicture();
+							}, 1000);
+						}
+
+					}
+				})
+			},
+			release() {
+				this.$refs.camera.release();
+			},
+			openCamera(id) {
+				if (uni.getSystemInfoSync().platform === "ios") {
+					let that = this;
+					this.$refs.camera.openCamera({
+						cameraId: id,
+					}, function(data) {
+						setTimeout(function() {
+							that.takePicture();
+						}, 200);
+					});
+				} else {
+					//android 系统需要考虑 组件的宽高 和摄像头的宽高比例,如果不一致会导致拉伸
+					this.openCamera_1(id);
+				}
+			},
+			openCamera_1(id) {
+				//安卓解决拉伸问题,一般有两种思路。
+				//1. 组件宽高不变,找出最适合的分辨比率
+				//2. 根据摄像头的分辨率,来重新修改组件的宽和高。
+				this.cid = id;
+				let type = 2; //1  组件宽高不变,找出最适合的分辨比率  2根据摄像头的分辨率,来重新修改组件的宽和高。
+				this.$refs.camera.getSupportedPreviewSizesByCameraId({
+					cameraId: id
+				}, (data) => {
+					let bestHeight_index = 0;
+					//方法1 组件宽高不变,找出最适合的分辨比率,这样只能减少拉伸,不能解决
+					if (type == 1) {
+						let r0 = (this.height * 1.0) / this.width;
+						let diff = 1000;
+						for (var i = 0; i < data.sizes.length; i++) {
+							console.log(data.sizes[i]);
+							//找出最合适的分辨率,宽高比例尽量接近组件的(摄像头宽高是反着呢)
+							let tmp = Math.abs(r0 - (data.sizes[i].width * 1.0) / data.sizes[bestHeight_index]
+								.width);
+							if (tmp < diff) {
+								diff = tmp;
+								bestHeight_index = i;
+							}
+						}
+						//方法2 先获取摄像头 支持的分辨率,然后修改组件的大小(一般保持宽不变),这样肯定不拉伸	 
+					} else if (type == 2) {
+						for (var i = 0; i < data.sizes.length; i++) {
+							//找出最大高度对应的分辨比率(宽高是反着呢)
+							if (data.sizes[i].width > data.sizes[bestHeight_index].width) {
+								bestHeight_index = i;
+							}
+						}
+						//this.width = data.sizes[max_index].height;
+						//计算出当前宽度下最适合的高度,然后修改组件的高
+						this.height = ((data.sizes[bestHeight_index].width / (data.sizes[bestHeight_index].height *
+							1.0)) * 750) + "rpx";
+						// 3 用最大分辨比率,不考虑拉伸	
+					} else if (type == 3) {
+						bestHeight_index = 0; //最大的一般是第一个,你也可以遍历后找出最大分辨比率
+
+					}
+					//延迟打开摄像头,组件大小修改需要时间	
+					const that = this;
+					setTimeout(() => {
+						this.$refs.camera.openCamera({
+							cameraId: id,
+							previewWidth: data.sizes[bestHeight_index].width,
+							previewHeight: data.sizes[bestHeight_index].height
+						}, function(data) {
+							setTimeout(function() {
+								that.takePicture();
+							}, 800);
+						});
+					}, 500);
+				});
+				return;
+			},
+			switchCamera() {
+				this.cameraId == 0 ? this.cameraId = 1 : this.cameraId = 0
+				this.$refs.camera.switchCamera({
+					cameraId: this.cameraId
+				}, function(data) {
+					uni.showModal({
+						content: JSON.stringify(data)
+					})
+				});
+			},
+			start() {
+				this.$refs.camera.startRecord({
+					videoEncodingBitRate: 3 * 1920 * 1080
+				});
+			},
+			stop() {
+				this.$refs.camera.stopRecord(function(data) {
+					//可以通过 uni.compressVideo 压缩视频 记得前缀 file://
+					uni.showModal({
+						content: JSON.stringify(data)
+					})
+				});
+			},
+			release() {
+				this.$refs.camera.release();
+			},
+			flashOpen() {
+				this.$refs.camera.flashOpen();
+			},
+			flashClose() {
+				this.$refs.camera.flashClose();
+			},
+			changeSize() {
+				this.height = "1100rpx";
+
+			},
+			getSupportedPreviewSizes() {
+				this.$refs.camera.getSupportedPreviewSizes((ret) => {
+					uni.showModal({
+						content: JSON.stringify(ret)
+					})
+				});
+			}
+		}
+	}
+</script>
+
+<style scoped>
+	.main {
+		position: relative;
+		width: 750rpx;
+		flex: 1;
+		overflow: hidden;
+	}
+
+	.operate-bg {
+		width: 750rpx;
+		background-color: #000000;
+		position: absolute;
+		left: 0;
+		bottom: 0;
+		justify-content: center;
+		align-items: center;
+		padding-top: 60rpx;
+		padding-bottom: 60rpx;
+	}
+
+	.operate {
+		width: 140rpx;
+		height: 140rpx;
+		background-color: #fff;
+		border-radius: 50%;
+		border-width: 10rpx;
+		border-style: solid;
+		border-color: #453f3f;
+	}
+
+	.change {
+		width: 96rpx;
+		height: 96rpx;
+		background-color: #453f3f;
+		position: absolute;
+		right: 60rpx;
+		bottom: 82rpx;
+		border-radius: 48rpx;
+		align-items: center;
+		justify-content: center;
+	}
+
+	.change-img {
+		width: 56rpx;
+		height: 56rpx;
+	}
+
+	.portrait-frame {
+		width: 750rpx;
+		flex: 1;
+		position: absolute;
+		top: 0;
+		left: 0;
+		right: 0;
+		bottom: 0;
+		align-items: center;
+		justify-content: center;
+		background-color: rgba(0, 0, 0, 0);
+	}
+
+	.pf-img {
+		width: 633.6rpx;
+		height: 582rpx;
+		margin-top: -280rpx;
+	}
+
+	.epiiCamer {
+		position: absolute;
+		top: 0;
+		right: 0;
+		bottom: 0;
+		left: 0;
+	}
+</style>

+ 8 - 1
pages/login/login.vue

@@ -36,7 +36,7 @@ export default {
 	data() {
 		return {
 			show: true,
-			item: {}
+			item: {checked:[]}
 		};
 	},
 	onLoad() {
@@ -61,6 +61,13 @@ export default {
 		});
 	},
 	methods: {
+		toFaceLogin(){
+			if(this.item.checked.length==0){
+				this.common.toast('请同意并勾选协议');
+				return;
+			}
+			this.common.to('/pages/login/faceLogin');
+		},
 		submit() {
 			let rule = [
 				{ name: 'phone', checkType: 'notnull', errorMsg: '手机号不能为空' },

+ 2 - 2
pages/market/one/leader/handle.vue

@@ -50,10 +50,10 @@
 						<text class="label">商户名称</text>
 						<text class="desc">{{ item.enterpriseName }}</text>
 					</view>
-					<view class="item">
+				<!-- 	<view class="item">
 						<text class="label">边民额度序号</text>
 						<text class="desc">{{ item.limitNo }}</text>
-					</view>
+					</view> -->
 					<view class="item">
 						<text class="label">商品额度</text>
 						<text class="desc">{{ item.glimit }}</text>

+ 1 - 1
pages/market/two/purchaser/address/add.vue

@@ -2,7 +2,7 @@
 	<view>
 		<view class="forms">
 			<view class="form_group pt0">
-				<view class="lable re">收件人</view>
+				<view class="lable re">联系人</view>
 				<input placeholder="请输入" v-model="item.name" />
 			</view>
 			<view class="form_group">

+ 1 - 1
pages/personal/personal.vue

@@ -17,7 +17,7 @@
 				<text>你还未认证,请先认证</text>
 				<text class="icon" style="float: right">&#xe8f2;</text>
 			</view>
-			<view class="message _info" @click="go('/pages/authentication/face')" v-if="(user.userType == 1 || user.userType == 2) && user.face == 0">
+			<view class="message _info" @click="go('/pages/face/faceRegister')" v-if="(user.userType == 1 || user.userType == 2) && user.face == 0">
 				<text class="icon">&#xe78d;</text>
 				<text>你还未人脸认证,请先人脸认证</text>
 				<text class="icon" style="float: right">&#xe8f2;</text>

BIN
static/sl.gif