gcz 4 年 前
コミット
85ae15af66

+ 21 - 1
App.vue

@@ -2,7 +2,27 @@
 	export default {
 		onLaunch: function() {
 			// console.log('App Launch')
-			this.$wxApi.config();
+			//判断客户端类别
+			if (/MicroMessenger/.test(window.navigator.userAgent)) {
+				uni.setStorage({
+					key:'userAgent',
+					data:'wxAgent'
+				});
+				// console.log('handleAliPay 微信客户端');
+			} else if (/AlipayClient/.test(window.navigator.userAgent)) {
+				uni.setStorage({
+					key:'userAgent',
+					data:'aliAgent'
+				});
+				// console.log('handleAliPay 支付宝客户端');
+			} else {
+				uni.setStorage({
+					key:'userAgent',
+					data:'otherAgent'
+				});
+				// console.log('handleAliPay 其他浏览器');
+			};
+			// this.$wxApi.config();
 		},
 		onShow: function() {
 			// console.log('App Show')

+ 8 - 0
common/apiurl.js

@@ -11,6 +11,14 @@ const apiurl = {
 	refundurl:'/app/order/refund',
 	// 绑定手机号
 	bindphoneurl:'/app/order/refund2',
+	// 手机登录验证码
+	phoneLoginCodeUrl:'/client/auth/sendSmsCode',
+	// 手机登录验证码验证
+	phoneLoginAuthUrl:'/client/auth/verifyCode',
+	// code换取微信信息
+	getWXInfoUrl:'http://wx.hw.hongweisoft.com/wxpaydemoapi/wechat/h5/code/',
+	// 微信支付
+	wxPayUrl:'http://wx.hw.hongweisoft.com/wxpaydemoapi/wechat/pay',
 }
 
 export {

+ 4 - 3
common/config.js

@@ -1,7 +1,8 @@
 const config = {
-	
-	//api baseUrl
-	baseUrl:'http://wx.hw.hongweisoft.com/wxpaydemoapi',
+	// wxAppid 
+	wxAppid:'wxbe90cc7c5233dd84',
+	//api baseUrl http://wx.hw.hongweisoft.com/wxpaydemoapi
+	baseUrl:'http://172.16.90.64:7000',
 	
 	//登录链接
 	loginUrl:'http://wx.hw.hongweisoft.com/wxpaydemoapi/wechat/h5/authorize?returnUrl=http://172.16.90.25:8080/',

+ 16 - 3
common/http.api.js

@@ -9,16 +9,29 @@ const install = (Vue, vm) => {
 	
 	let getuseinfo = (params = {}) => vm.$u.get(apiurl.getuseinfourl+'/'+params);
 	
-	let createOrder = (params = {}) => vm.$u.post(apiurl.createOrderurl, params);
+	let createOrder = (params = {}) => vm.$u.post(apiurl.createOrderurl, params);//
+	
+	let bindphone = (params = {}) => vm.$u.post(apiurl.bindphoneurl, params);//
+	
+	let getPhoneLoginCode = (params = {}) => vm.$u.post(apiurl.phoneLoginCodeUrl, params);
+	
+	let phoneLoginAuth = (params = {}) => vm.$u.post(apiurl.phoneLoginAuthUrl, {code:params.code},{Authorization:`Bearer ${params.accessToken}`,user_id:params.userId});
+	
+	let getWXInfo = (params = {}) => vm.$u.get(apiurl.getWXInfoUrl+params);
+	
+	let wxPay = (params = {}) => vm.$u.post(apiurl.wxPayUrl,params);
 	
-	let bindphone = (params = {}) => vm.$u.post(apiurl.bindphoneurl, params);
 	
 	// 将各个定义的接口名称,统一放进对象挂载到vm.$u.api(因为vm就是this,也即this.$u.api)下
 	vm.$u.api = {
 		feedbackAdd,
 		getuseinfo,
 		createOrder,
-		bindphone
+		bindphone,
+		getPhoneLoginCode,
+		phoneLoginAuth,
+		getWXInfo,
+		wxPay
 	};
 }
 

+ 3 - 2
common/http.interceptor.js

@@ -18,6 +18,7 @@ const install = (Vue, vm) => {
 		
 		// 方式一,存放在vuex的token,假设使用了uView封装的vuex方式,见:https://uviewui.com/components/globalVariable.html
 		config.header.token = vm.vuex_token;
+		config.header.Authorization = `Bearer ${vm.vuex_token}`;
 		
 		// 方式二,如果没有使用uView封装的vuex方法,那么需要使用$store.state获取
 		// config.header.token = vm.$store.state.token;
@@ -30,7 +31,7 @@ const install = (Vue, vm) => {
 		// config.header.token = token;
 		
 		// 此url参数为this.$u.get(url)中的url值
-		let noTokenList = ['/wechat/h5/user'];
+		let noTokenList = ['/wechat/h5/user','/client/auth/verifyCode'];
 		if(noTokenList.includes(config.url)) config.header.noToken = true;
 		// console.log('noTokenList.includes(config.url)',noTokenList.includes(config.url));
 		// console.log('config.url',config.url);
@@ -42,7 +43,7 @@ const install = (Vue, vm) => {
 		// 如果把originalData设置为了true,这里得到将会是服务器返回的所有的原始数据
 		// 判断可能变成了res.statueCode,或者res.data.code之类的,请打印查看结果
 		// console.log('interceptor res',res);
-		if(res.retHead.errCode == 0) {
+		if(res.code == 200) {
 			// 如果把originalData设置为了true,这里return回什么,this.$u.post的then回调中就会得到什么
 			return res;  
 		} else return false;

+ 1 - 1
manifest.json

@@ -80,7 +80,7 @@
     "h5" : {
         "template" : "template.h5.html",
         "router" : {
-            "mode" : "history"
+            "mode" : "hash"
         }
     }
 }

+ 7 - 0
pages.json

@@ -6,6 +6,7 @@
 		{
 			"path": "pages/index/index",
 			"style": {
+				"navigationStyle":"custom",// 隐藏系统导航栏
 				"navigationBarTitleText": "城市智慧停车"
 			}
 		},
@@ -14,6 +15,12 @@
 			"style": {
 				"navigationBarTitleText": "城市智慧停车"
 			}
+		},
+		{
+			"path": "pages/center/phoneLogin/phoneLogin",
+			"style": {
+				"navigationBarTitleText": "手机号登录"
+			}
 		}
 	],
 	"globalStyle": {

+ 133 - 15
pages/center/index.vue

@@ -1,37 +1,155 @@
 <template>
-	<view class="content">
-		<view class="link-demo">
-			<u-link :color="$u.color['primary']" :under-line="true" href="http://www.uviewui.com">Link超链接组件演示</u-link>
+	<view>
+		<u-navbar :is-back="false" title=" " :border-bottom="false">
+			<view class="u-flex u-row-right" style="width: 100%;">
+				<view class="camera u-flex u-row-center">
+					<u-icon name="camera-fill" color="#000000" size="48"></u-icon>
+				</view>
+			</view>
+		</u-navbar>
+		<view class="u-flex user-box u-p-l-30 u-p-r-20 u-p-b-30">
+			<view class="u-m-r-10" @click="login($store.state.vuex_hasLogin)">
+				<u-avatar :src="userInfo.headImgUrl || userInfo.avatar||pic" size="140"></u-avatar>
+			</view>
+			<view class="u-flex-1" @click="login($store.state.vuex_hasLogin)">
+				<view class="u-font-18 u-p-b-20">{{ userInfo.nickname || userInfo.userName || '请登录' }}</view>
+				<view class="u-font-14 u-tips-color">手机号:{{ userInfo.mobile || '暂无' }}</view>
+			</view>
+			<view class="u-m-l-10 u-p-10">
+				<u-icon name="arrow-right" color="#969799" size="28"></u-icon>
+			</view>
 		</view>
+		
+		<view class="u-m-t-20">
+			<u-cell-group>
+				<u-cell-item icon="star" title="收藏"></u-cell-item>
+				<u-cell-item icon="photo" title="相册"></u-cell-item>
+				<u-cell-item icon="coupon" title="卡券"></u-cell-item>
+				<u-cell-item icon="heart" title="关注"></u-cell-item>
+			</u-cell-group>
+		</view>
+		
+		<view class="u-m-t-20">
+			<u-cell-group>
+				<u-cell-item icon="star" title="手机号登录" @click="openPage('/pages/center/phoneLogin/phoneLogin')"></u-cell-item>
+				<u-cell-item icon="star" title="微信支付" @click="handlewxpay"></u-cell-item>
+			</u-cell-group>
+		</view>
+		
+		<u-toast ref="uToast" />
 	</view>
 </template>
 
 <script>
+	import getUrlParams from "../../utils/getUrlParams.js";
 	export default {
 		data() {
 			return {
-				title: 'Hello'
+				pic:'https://uviewui.com/common/logo.png',
+				userInfo:[],
+				code:null,
+				
 			}
 		},
 		onLoad() {
+			if(this.$store.state.vuex_hasLogin){
+				this.userInfo = this.$store.state.vuex_user;
+				if(this.$store.state.vuex_wxinfo){
+					this.userInfo = Object.assign(this.userInfo,this.$store.state.vuex_wxinfo);
+				}
+			}else{
+				this.userInfo = [];
+			};
+			let locationLocaturl = window.location.search;
+			this.code = getUrlParams(locationLocaturl,"code");
+			if(this.code&&!this.$store.state.vuex_wxinfo.openId){this.handleGetWXInfo(this.code)};
+			
 
 		},
 		methods: {
+			openPage(path) {
+				console.log('path',path);
+				this.$u.route({ 
+					url: path
+				})
+			},
+			//登录判断
+			login(status){
+				if(!status){
+					console.log('config',this.config);
+					window.location.replace(this.config.loginUrl)
+				}
+			},
+			getCode () {
+				var local = window.location.href // 获取页面url
+				let locationLocaturl = window.location.search;
+				this.code = getUrlParams(locationLocaturl,"code"); // 截取code
+				if (this.code == null || this.code === '') { // 如果没有code,则去请求
+					window.location.href = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${this.config.wxAppid}&redirect_uri=${encodeURIComponent(local)}&response_type=code&scope=snsapi_userinfo&#wechat_redirect`
+				} else {
+					// this.handleGetWXInfo(this.code) //把code传给后台获取用户信息
+				}
+			},
+			handleGetWXInfo (code) { // 通过code获取 openId等用户信息,/api/user/wechat/login 为后台接口
+				let _this = this
+				this.$u.api.getWXInfo(code).then((res) => {
+					if (res.code === 200 ) {
+						this.$u.vuex('vuex_wxinfo',res.data);
+						// 继续支付
+					}
+				}).catch((err) => {
+					this.$refs.uToast.show({
+						title: err.msg,
+						type: 'error',
+					});
+				})
+			},			
+			handlewxpay(){
+				if(!this.$store.state.vuex_wxinfo.openId){ // 如果微信openId,则需用code去后台获取
+					this.$refs.uToast.show({
+						title: '请登录后重试!',
+						type: 'info',
+						// url: '/pages/user/index'
+					});
+					this.getCode();
+				} else {
+					// 别的业务逻辑
+					this.getWXPay();
+				}
+			},
+			async getWXPay(id){
+				let params = {
+					orderId:id||new Date().getTime(),
+					openid:this.$store.state.vuex_wxinfo.openId,
+					tradeType:"test"
+				};
+				await this.$wxApi.config(); 
+				this.$pay.wxPay(params).then(res =>{
+					console.log('wxPay',res.code);
+					if(res.code == 0){
+						// 成功
+						// uni.reLaunch({
+						// 	url: '/pages/buySuccess/buySuccess?orderId=' + params.orderId
+						// })
+					}else if(res.code == 1){
+						// 取消
+						// uni.redirectTo({
+						// 	url: '/pages/userCenter/myOrder/myOrder'
+						// })
+					}else if(res.code == 2){
+						this.$refs.uToast.show({
+							title: '支付失败,请检查!',
+							type: 'error',
+							// url: '/pages/user/index'
+						});
+					}
+				});
+			},
 
 		}
 	}
 </script>
 
 <style lang="scss" scoped>
-	.content {
-		display: flex;
-		flex-direction: column;
-		align-items: center;
-		justify-content: center;
-		padding: 40rpx;
-	}
-	
-	.link-demo {
-		margin-top: 80rpx;
-	}
+
 </style>

+ 212 - 0
pages/center/phoneLogin/phoneLogin.vue

@@ -0,0 +1,212 @@
+<template>
+	<view class="wrap">
+		<view class="content">
+			<view class="title">手机号登录</view>
+			<input class="u-border-bottom" type="number" maxlength="11" v-model="tel" placeholder="请输入手机号" />
+			<button @tap="submit" :style="[inputStyle]" class="getCaptcha">获取短信验证码</button>
+			<u-message-input v-if="show" :focus="true" :value="messageCode" @change="change" @finish="finish" mode="bottomLine" :maxlength="codelength"></u-message-input>
+		</view>
+		<!-- <text v-if="messageError">验证码错误,请重新输入</text> -->
+		<view class="captcha">
+			<!-- <text v-if="show&&this.messageDisable==false" @tap="noCaptcha">收不到验证码点这里</text> -->
+			<text v-if="messageShow">{{ second }}秒后可重新获取验证码</text>
+		</view>
+		<view class="buttom">
+			<view class="hint">
+				登录代表同意
+				<text class="link">隐私政策,</text>
+				并授权使用您的账号信息(如昵称、头像、收获地址)以便您统一管理
+			</view>
+		</view>
+		<u-toast ref="uToast" />
+	</view>
+</template>
+
+<script>
+export default {
+	data() {
+		return {
+			tel: '',
+			messageCode:'',
+			messageShow: false,
+			messageDisable: false,
+			codelength: 4,
+			show: false,
+			second:10,
+			toastMsg:'',
+			toastUrl:'',
+			toastType:'',
+			accessToken:'',
+			userId:'',
+			// messageError:false
+		}
+	},
+	onLoad() {
+		
+	},
+	computed: {
+		inputStyle() {
+			let style = {};
+			if(this.tel.length==11&&this.messageDisable==false&&this.$u.test.mobile(this.tel)) {
+				style.color = "#fff";
+				style.backgroundColor = '#5295F5';
+				// style.backgroundColor = this.$u.color['warning'];
+			}
+			return style;
+		}
+	},
+	methods: {
+		showToast() {
+			this.$refs.uToast.show({
+				title: this.toastMsg,
+				type: this.toastType,
+				url: this.toastUrl
+			})
+		},
+		submit() {
+			if(this.$u.test.mobile(this.tel)&&this.messageDisable==false) {
+				let that = this;
+				this.$u.api.getPhoneLoginCode({mobile:this.tel})
+				.then(res =>{
+					this.messageDisable = true;
+					this.messageShow = true;
+					this.show = true;
+					let interval = setInterval(() => {
+						that.second--;
+						if (that.second <= 0) {						
+							that.messageDisable=false
+							that.messageShow = false;
+							if (that.messageCode.lenth != 4) {
+								// this.messageError = true;
+							}
+							clearInterval(interval);
+							that.second=10;
+						}
+					}, 1000);
+					console.log('getcode res',res);
+					this.accessToken = res.data.accessToken;
+					this.$u.vuex('vuex_token', res.data.accessToken);
+					this.userId = res.data.userId;
+				}).catch(err=>{
+					console.log('err',err)
+					this.toastMsg = err.code + ":" + err.msg;
+					this.showToast();
+					console.log('getcode err',err)
+				});
+			}
+		},
+		// 收不到验证码选择时的选择
+		// noCaptcha() {
+		// 	uni.showActionSheet({
+		// 		itemList: ['重新获取验证码', '接听语音验证码'],
+		// 		success: function(res) {
+					
+		// 		},
+		// 		fail: function(res) {
+					
+		// 		}
+		// 	});
+		// },
+		// change事件侦听
+		change(value) {
+			// console.log('change', value);
+		},
+		// 输入完验证码最后一位执行
+		finish(value) {
+			let params = {
+				accessToken:this.accessToken,
+				userId:this.userId,
+				code:value
+			};
+			console.log('params',params);
+			this.$u.api.phoneLoginAuth(params)
+			.then(res =>{
+				if(res.code=='200'){
+					// console.log('finish res',res);
+					this.$u.vuex('vuex_user', res.data);
+					this.$u.vuex('vuex_hasLogin', true);
+					this.$refs.uToast.show({
+						title: '操作成功',
+						url: '/pages/index/index',
+						isTab:true
+					});
+					
+					// this.$u.api.getuseinfo().then(res => {
+					// 	console.log('getuseinfo',res.retBody);
+					// 	this.$u.vuex('vuex_user', res.retBody);
+					// 	this.toastMsg = '操作成功';
+					// 	this.showToast();
+					// 	setTimeout(() => {
+					// 		this.$u.route({
+					// 			url: 'pages/template/wxCenter/index'
+					// 		})
+					// 	}, 2000);
+					// });
+					
+				}else{
+					this.toastMsg = res.msg;
+					this.showToast();
+				}
+				
+			}).catch(err=>{
+				console.log('finish err',err);
+				this.toastMsg = err.msg;
+				this.showToast();
+			});
+		}
+	}
+};
+</script>
+
+<style lang="scss" scoped>
+.hide{display: none!important;}
+.wrap {
+	font-size: 28rpx;
+	.content {
+		width: 600rpx;
+		margin: 80rpx auto 0;
+
+		.title {
+			text-align: left;
+			font-size: 60rpx;
+			font-weight: 500;
+			margin-bottom: 100rpx;
+		}
+		input {
+			text-align: left;
+			margin-bottom: 10rpx;
+			padding-bottom: 20rpx;
+			border-bottom: 1px solid #ddd;
+		}
+		.getCaptcha {
+			margin: 45rpx auto 130rpx;
+			background-color: #a8c6f1;
+			color: $u-tips-color;
+			border: none;
+			font-size: 30rpx;
+			padding: 12rpx 0;
+			
+			&::after {
+				border: none;
+			}
+		}
+	}
+	.buttom {
+		.hint {
+			padding: 20rpx 40rpx;
+			font-size: 20rpx;
+			color: $u-tips-color;
+			
+			.link {
+				color: $u-type-warning;
+			}
+		}
+	}
+	.captcha {
+		color: $u-type-warning;
+		font-size: 30rpx;
+		margin-top: 40rpx;
+		text-align: center;
+	}
+}
+</style>

+ 15 - 0
pages/index/index.scss

@@ -0,0 +1,15 @@
+page{background-color: $my-page-bg-color;}
+
+.header-bar{
+	background-color: $my-main-color;
+	height: 106rpx;
+	display: flex;
+	padding: 0 40rpx;
+	.city{
+		display: flex;
+		margin-right: 23rpx;
+		color: #fff;
+		align-items: center;
+	}
+	.scan{margin-left: 23rpx;}
+}

+ 15 - 8
pages/index/index.vue

@@ -1,8 +1,14 @@
 <template>
-	<view class="content">
-		<view class="link-demo">
-			<u-link :color="$u.color['primary']" :under-line="true" href="http://www.uviewui.com">跳转uView文档:www.uviewui.com</u-link>
+	<view class="wrap">
+		<u-navbar :is-back='false' :border-bottom="false" :background="{ background: '#008CFF' }" title=""></u-navbar>
+		<view class="header-bar">
+			<view class="city">
+				{{city}}<u-icon name="arrow-down" color="#fff" size="32"></u-icon>
+			</view>
+			<u-search placeholder="搜索发票、停车场" :show-action="false" v-model="keyword"></u-search>
+			<u-icon class="scan" name="scan" color="#fff" size="48"></u-icon>
 		</view>
+		<u-swiper :list="bannerList"></u-swiper>
 	</view>
 </template>
 
@@ -10,7 +16,11 @@
 	export default {
 		data() {
 			return {
-				title: 'Hello'
+				city: '贵阳市',
+				keyword:'',
+				bannerList:[
+					{image: 'https://cdn.uviewui.com/uview/swiper/1.jpg',title: '昨夜星辰昨夜风,画楼西畔桂堂东'}
+				]
 			}
 		},
 		onLoad() {
@@ -23,8 +33,5 @@
 </script>
 
 <style lang="scss" scoped>
-	.link-demo {
-		margin-top: 80rpx;
-		text-align: center;
-	}
+	@import "./index.scss";
 </style>

+ 2 - 2
pay.js

@@ -16,11 +16,11 @@ export default {
 			title: '支付中'
 		});
 		return new Promise(r => {
-			$http.post("/app/pay",obj)
+			$http.post("http://wx.hw.hongweisoft.com/wxpaydemoapi/wechat/pay",obj)
 			// this.$u.post("/wechat/h5/pay",obj)
 				.then(res=>{
 					//#ifdef H5
-					$wxApi.JSAPI(res.retBody).then(r);
+					$wxApi.JSAPI(res.data).then(r);
 					//#endif
 					this.payError(res);
 				}).catch(err =>{

+ 4 - 25
store/index.js

@@ -12,7 +12,7 @@ try{
 }
 
 // 需要永久存储,且下次APP启动需要取出的,在state中的变量名
-let saveStateKeys = ['vuex_user', 'vuex_token','vuex_hasLogin'];
+let saveStateKeys = ['vuex_user', 'vuex_token','vuex_wxinfo','vuex_hasLogin'];
 
 // 保存变量到本地存储中
 const saveLifeData = function(key, value){
@@ -31,33 +31,12 @@ const store = new Vuex.Store({
 	state: {
 		// 如果上面从本地获取的lifeData对象下有对应的属性,就赋值给state中对应的变量
 		// 加上vuex_前缀,是防止变量名冲突,也让人一目了然
-		vuex_user: lifeData.vuex_user ? lifeData.vuex_user : {name: '明月',type:'测试账号',wxId:'347567567',phone:'13682266954'},
+		vuex_user: lifeData.vuex_user ? lifeData.vuex_user : {},
+		vuex_wxinfo: lifeData.vuex_wxinfo ? lifeData.vuex_wxinfo : {},
 		vuex_hasLogin:lifeData.vuex_hasLogin?lifeData.vuex_hasLogin:false,
-		vuex_token: lifeData.vuex_token ? lifeData.vuex_token : '123123',
+		vuex_token: lifeData.vuex_token ? lifeData.vuex_token : '',
 		// 如果vuex_version无需保存到本地永久存储,无需lifeData.vuex_version方式
 		vuex_version: '1.0.1',
-		vuex_demo: '绛紫',
-		// 自定义tabbar数据
-		vuex_tabbar: [{
-				iconPath: "/static/uview/example/component.png",
-				selectedIconPath: "/static/uview/example/component_select.png",
-				text: '组件',
-				pagePath: '/pages/example/components'
-			},
-			{
-				iconPath: "/static/uview/example/js.png",
-				selectedIconPath: "/static/uview/example/js_select.png",
-				text: '工具',
-				midButton: true,
-				pagePath: '/pages/example/js'
-			},
-			{
-				iconPath: "/static/uview/example/template.png",
-				selectedIconPath: "/static/uview/example/template_select.png",
-				text: '模板',
-				pagePath: '/pages/example/template'
-			}
-		]
 	},
 	mutations: {
 		$uStore(state, payload) {

+ 3 - 0
uview-ui/theme.scss

@@ -2,6 +2,9 @@
 // uni.scss中引入的样式会同时混入到全局样式文件和单独每一个页面的样式中,造成微信程序包太大,
 // 故uni.scss只建议放scss变量名相关样式,其他的样式可以通过main.js或者App.vue引入
 
+$my-main-color: #008CFF;
+$my-page-bg-color: #F6F6FF;
+
 $u-main-color: #303133;
 $u-content-color: #606266;
 $u-tips-color: #909399;

+ 2 - 2
wxapi.js

@@ -2,7 +2,7 @@
 const wx = require('@/js_sdk/jweixin-1.4.0.js')
 
 //配置注册url
-const url = '/app/getJsapiTicket';
+const url = 'http://wx.hw.hongweisoft.com/wxpaydemoapi/wechat/pay/getJsapiTicket';
 
 //http方法
 // import $http from './utils/axios.js'
@@ -60,7 +60,7 @@ export default {
 				"chooseCard",
 				"openCard"
 			],
-			...(await $http.get(url,{url:href})).retBody,
+			...(await $http.get(url,{url:href})).data,
 			// ...(await uni.request(url,{url:href})).retBody,
 		});
 		wx.ready(e => {