Browse Source

增加个人信息的加载

YunaiV 3 years ago
parent
commit
2da6a746e4

+ 5 - 1
yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/util/SecurityFrameworkUtils.java

@@ -1,5 +1,6 @@
 package cn.iocoder.yudao.framework.security.core.util;
 
+import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
 import cn.iocoder.yudao.framework.security.core.LoginUser;
 import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
 import org.springframework.lang.Nullable;
@@ -11,6 +12,7 @@ import org.springframework.security.web.authentication.WebAuthenticationDetailsS
 import org.springframework.util.StringUtils;
 
 import javax.servlet.http.HttpServletRequest;
+import java.util.Objects;
 import java.util.Set;
 
 /**
@@ -100,7 +102,9 @@ public class SecurityFrameworkUtils {
         WebFrameworkUtils.setLoginUserId(request, loginUser.getId());
         WebFrameworkUtils.setLoginUserType(request, loginUser.getUserType());
         // TODO @jason:使用 userId 会不会更合适哈?
-        org.activiti.engine.impl.identity.Authentication.setAuthenticatedUserId(loginUser.getUsername());
+        if (Objects.equals(UserTypeEnum.ADMIN.getValue(), loginUser.getUserType())) {
+            org.activiti.engine.impl.identity.Authentication.setAuthenticatedUserId(loginUser.getUsername());
+        }
     }
 
 }

+ 7 - 7
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/member/controller/user/SysUserProfileController.http

@@ -1,11 +1,11 @@
-### 请求 /system/user/profile/get 接口 => 没有权限
-GET {{userServerUrl}}/system/user/profile/get
+### 请求 /member/user/profile/get 接口 => 没有权限
+GET {{userServerUrl}}/member/user/profile/get
 Authorization: Bearer test245
 
-### 请求 /system/user/profile/revise-nickname 接口 成功
-PUT {{userServerUrl}}/system/user/profile/update-nickname?nickName=yunai222
+### 请求 /member/user/profile/revise-nickname 接口 成功
+PUT {{userServerUrl}}/member/user/profile/update-nickname?nickName=yunai222
 Authorization: Bearer test245
 
-### 请求 /system/user/profile/get-user-info 接口 成功
-GET {{userServerUrl}}/system/user/profile/get-user-info?id=245
-Authorization: Bearer test245
+### 请求 /member/user/profile/get-user-info 接口 成功
+GET {{userServerUrl}}/member/user/profile/get-user-info?id=245
+Authorization: Bearer test245

+ 3 - 4
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/member/controller/user/SysUserProfileController.java

@@ -27,7 +27,7 @@ import static cn.iocoder.yudao.userserver.modules.member.enums.MbrErrorCodeConst
 
 @Api(tags = "用户个人中心")
 @RestController
-@RequestMapping("/system/user/profile")
+@RequestMapping("/member/user/profile")
 @Validated
 @Slf4j
 public class SysUserProfileController {
@@ -57,14 +57,13 @@ public class SysUserProfileController {
         return success(avatar);
     }
 
-    @GetMapping("/get-user-info")
-    @ApiOperation("获取用户头像与昵称")
+    @GetMapping("/get")
+    @ApiOperation("获得基本信息")
     @PreAuthenticated
     public CommonResult<MbrUserInfoRespVO> getUserInfo() {
         return success(userService.getUserInfo(getLoginUserId()));
     }
 
-
     @PostMapping("/update-mobile")
     @ApiOperation(value = "修改用户手机")
     @PreAuthenticated

+ 1 - 0
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/member/service/user/MbrUserService.java

@@ -65,6 +65,7 @@ public interface MbrUserService {
 
     /**
      * 根据用户id,获取用户头像与昵称
+     *
      * @param userId 用户id
      * @return 用户响应实体类
      */

+ 0 - 1
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/SysAuthController.java

@@ -40,7 +40,6 @@ public class SysAuthController {
     @Resource
     private SysSocialService socialService;
 
-
     @PostMapping("/login")
     @ApiOperation("使用手机 + 密码登录")
     public CommonResult<SysAuthLoginRespVO> login(@RequestBody @Valid SysAuthLoginReqVO reqVO) {

File diff suppressed because it is too large
+ 78 - 8
yudao-vue-ui/App.vue


+ 9 - 0
yudao-vue-ui/api/member/userProfile.js

@@ -0,0 +1,9 @@
+import { request } from '@/common/js/request.js'
+
+// 获得用户的基本信息
+export function getUserInfo() {
+  return request({
+    url: 'member/user/profile/get',
+    method: 'get'
+  })
+}

+ 27 - 0
yudao-vue-ui/api/system/auth.js

@@ -0,0 +1,27 @@
+import { request } from '@/common/js/request.js'
+
+// 手机号 + 密码登陆
+export function login(mobile, password) {
+  const data = {
+    mobile,
+    password
+  }
+  return request({
+    url: 'login',
+    method: 'post',
+    data: data
+  })
+}
+
+// 手机号 + 验证码登陆
+export function smsLogin(mobile, code) {
+  const data = {
+    mobile,
+    code
+  }
+  return request({
+    url: 'sms-login',
+    method: 'post',
+    data: data
+  })
+}

+ 3 - 3
yudao-vue-ui/common/js/request.js

@@ -1,18 +1,18 @@
 const BASE_URL = 'http://127.0.0.1:28080/api/';
-import { msg } from './util'
+import { msg, getAuthToken } from './util'
 
 export const request = (options) => {
 	return new Promise((resolve, reject) => {
 		// 发起请求
+		const authToken = getAuthToken();
 		uni.request({
 			url: BASE_URL + options.url,
 			method: options.method || 'GET',
 			data: options.data || {},
 			header: {
-				'Authorization': '' // TODO 芋艿:带 token
+				'Authorization': authToken ? `Bearer ${authToken}` : ''
 			}
 		}).then(res => {
-			debugger
 			res = res[1];
 			const statusCode = res.statusCode;
 			if (statusCode !== 200) {

+ 92 - 3
yudao-vue-ui/common/js/util.js

@@ -34,14 +34,103 @@ export const throttle = (fn, delay=500) => {
 }
 
 /**
- * toast
+ * toast 提示
+ * 
+ * @param {String} title 标题
+ * @param {Object} param 拓展参数
+ * @param {Integer} param.duration 持续时间
+ * @param {Boolean} param.mask 是否遮罩
+ * @param {Boolean} param.icon 图标         
  */
 export const msg = (title = '', param={}) => {
-	if(!title) return;
+	if (!title) {
+		return;
+	}
 	uni.showToast({
 		title,
 		duration: param.duration || 1500,
 		mask: param.mask || false,
-		icon: param.icon || 'none'
+		icon: param.icon || 'none' // TODO 芋艿:是否要区分下 error 的提示,或者专门的封装
 	});
+}
+
+/**
+ * 检查登录
+ * 
+ * @param {Boolean} options.nav 如果未登陆,是否跳转到登陆页。默认为 true
+ * @return {Boolean} 是否登陆
+ */
+export const isLogin = (options = {}) => {
+	const token = this.getAuthToken();
+	if (token) {
+		return true;
+	}
+	// 若 nav 不为 false,则进行跳转登陆页
+	if (options.nav !== false) {
+		uni.navigateTo({
+			url: '/pages/auth/login'
+		})
+	}
+	return false;
+}
+
+/**
+ * 获得认证 Token
+ * 
+ * @return 认证 Token
+ */
+export const getAuthToken = () => {
+	return uni.getStorageSync('token');
+}
+
+/**
+ * 校验参数
+ *  
+ * @param {String} 字符串
+ * @param {String}  数据的类型。例如说 mobile 手机号、tel 座机 TODO 芋艿:是否组件里解决
+ */
+export const checkStr = (str, type) => {
+	switch (type) {
+		case 'mobile': //手机号码
+			return /^1[3|4|5|6|7|8|9][0-9]{9}$/.test(str);
+		case 'tel': //座机
+			return /^(0\d{2,3}-\d{7,8})(-\d{1,4})?$/.test(str);
+		case 'card': //身份证
+			return /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/.test(str);
+		case 'mobileCode': //6位数字验证码
+			return /^[0-9]{6}$/.test(str)
+		case 'pwd': //密码以字母开头,长度在6~18之间,只能包含字母、数字和下划线
+			return /^([a-zA-Z0-9_]){6,18}$/.test(str)
+		case 'payPwd': //支付密码 6位纯数字
+			return /^[0-9]{6}$/.test(str)
+		case 'postal': //邮政编码
+			return /[1-9]\d{5}(?!\d)/.test(str);
+		case 'QQ': //QQ号
+			return /^[1-9][0-9]{4,9}$/.test(str);
+		case 'email': //邮箱
+			return /^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$/.test(str);
+		case 'money': //金额(小数点2位)
+			return /^\d*(?:\.\d{0,2})?$/.test(str);
+		case 'URL': //网址
+			return /(http|ftp|https):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&:/~\+#]*[\w\-\@?^=%&/~\+#])?/.test(str)
+		case 'IP': //IP
+			return /((?:(?:25[0-5]|2[0-4]\\d|[01]?\\d?\\d)\\.){3}(?:25[0-5]|2[0-4]\\d|[01]?\\d?\\d))/.test(str);
+		case 'date': //日期时间
+			return /^(\d{4})\-(\d{2})\-(\d{2}) (\d{2})(?:\:\d{2}|:(\d{2}):(\d{2}))$/.test(str) || /^(\d{4})\-(\d{2})\-(\d{2})$/
+				.test(str)
+		case 'number': //数字
+			return /^[0-9]$/.test(str);
+		case 'english': //英文
+			return /^[a-zA-Z]+$/.test(str);
+		case 'chinese': //中文
+			return /^[\\u4E00-\\u9FA5]+$/.test(str);
+		case 'lower': //小写
+			return /^[a-z]+$/.test(str);
+		case 'upper': //大写
+			return /^[A-Z]+$/.test(str);
+		case 'HTML': //HTML标记
+			return /<("[^"]*"|'[^']*'|[^'">])*>/.test(str);
+		default:
+			return true;
+	}
 }

+ 31 - 22
yudao-vue-ui/pages/auth/login.vue

@@ -42,7 +42,7 @@
 							placeholder="请输入密码"	placeholder-style="color: #909399"/>
 					</view>
 				</view>
-				<mix-button ref="confirmBtn" text="立即登录" marginTop="60rpx" @onConfirm="login"></mix-button>
+				<mix-button ref="confirmBtn" text="立即登录" marginTop="60rpx" @onConfirm="mobileLogin"></mix-button>
 				<!-- 切换登陆 -->
 				<view class="login-type" v-if="loginType == 'code'" @click="setLoginType('password')">账号密码登录</view>
 				<view class="login-type" v-else @click="setLoginType('code')">免密登录</view>
@@ -78,9 +78,11 @@
 </template>
 
 <script>
-	import {checkStr} from '@/common/js/util'
+	import { checkStr } from '@/common/js/util'
+	import { login, smsLogin } from '@/api/system/auth.js'
 	import loginMpWx from './mixin/login-mp-wx.js'
 	import loginAppWx from './mixin/login-app-wx.js'
+
 	export default{
 		mixins: [loginMpWx, loginAppWx],
 		data(){
@@ -95,17 +97,10 @@
 		onLoad() {
 		},
 		methods: {
-			loginSuccessCallBack(data){
-				this.$util.msg('登录成功');
-				this.$store.commit('setToken', data);
-				setTimeout(()=>{
-					uni.navigateBack();
-				}, 1000)
-			},
 			// 手机号登录
-			async login(){
-				// 参数校验
-				if (!this.agreement){
+			async mobileLogin() {
+				// 参数校验 TODO 芋艿:表单校验的支持
+				if (!this.agreement) {
 					this.$util.msg('请阅读并同意用户服务及隐私协议');
 					this.$refs.confirmBtn.stop();
 					return;
@@ -116,23 +111,37 @@
 					this.$refs.confirmBtn.stop();
 					return;
 				}
-				if (!checkStr(code, 'mobileCode')) {
-					this.$util.msg('验证码错误');
+				if (this.loginType === 'code' && !checkStr(code, 'mobileCode')) {
+					this.$util.msg('验证码格式错误');
+					this.$refs.confirmBtn.stop();
+					return;
+				}
+				if (this.loginType === 'password' && !checkStr(password, 'pwd')) {
+					this.$util.msg('密码格式错误');
 					this.$refs.confirmBtn.stop();
 					return;
 				}
 				
 				// 执行登陆
-				const res = await this.$request('user', 'login', {mobile,code});
-				this.$refs.confirmBtn.stop();
-				
-				if (res.status === 1){
-					this.loginSuccessCallBack(res.data);
-				} else{
-					this.$util.msg(res.msg);
+				try {
+					const data = this.loginType === 'code' ? await smsLogin(mobile, code)
+						: await login(mobile, password);
+					// 登陆成功
+					this.loginSuccessCallBack(data);
+				} finally {
+					this.$refs.confirmBtn.stop();
 				}
 			},
-			navBack(){
+			// 登陆成功的处理逻辑
+			loginSuccessCallBack(data){
+				this.$util.msg('登录成功');
+				this.$store.commit('setToken', data);
+				// TODO 芋艿:如果当前页是第一页,则无法返回。期望是能够回到首页
+				setTimeout(()=>{
+					uni.navigateBack();
+				}, 1000)
+			},
+			navBack() {
 				uni.navigateBack();
 			},
 			setLoginType(loginType) {

+ 2 - 1
yudao-vue-ui/pages/tabbar/user.vue

@@ -82,7 +82,8 @@
 			};
 		},
 		onShow() {
-			// TODO 芋艿:加载用户信息
+			// 获得用户信息
+			this.$store.dispatch('obtainUserInfo');
 			// TODO 芋艿:获得订单数量
 		}
 	}

+ 21 - 49
yudao-vue-ui/store/index.js

@@ -1,6 +1,7 @@
 import Vue from 'vue'
 import Vuex from 'vuex'
 // import {request} from '@/common/js/request'
+import { getUserInfo } from '@/api/member/userProfile.js'
 
 Vue.use(Vuex)
 
@@ -10,7 +11,6 @@ const store = new Vuex.Store({
 		token: '', // 用户身份 Token
 		userInfo: {}, // 用户基本信息
 		timerIdent: false, // 全局 1s 定时器,只在全局开启一个,所有需要定时执行的任务监听该值即可,无需额外开启 TODO 芋艿:需要看看
-		orderCount: {}, // 订单数量
 	},
 	getters: {
 		hasLogin(state){
@@ -18,73 +18,45 @@ const store = new Vuex.Store({
 		}
 	},
 	mutations: {
-		//更新state数据
-		setStateAttr(state, param){
-			if(param instanceof Array){
+		// 更新 state 的通用方法
+		setStateAttr(state, param) {
+			if (param instanceof Array) {
 				for(let item of param){
 					state[item.key] = item.val;
 				}
-			}else{
+			} else {
 				state[param.key] = param.val;
 			}
 		},
-		//更新token
-		setToken(state, data){
-			const {token, tokenExpired} = data;
+		// 更新token
+		setToken(state, data) {
+			// 设置 Token
+			const { token } = data;
 			state.token = token;
-			uni.setStorageSync('uniIdToken', token);
-			uni.setStorageSync('tokenExpired', tokenExpired);
-			this.dispatch('getUserInfo'); //更新用户信息
-			this.dispatch('getCartCount');//更新购物车数量
-			uni.$emit('refreshCart');//刷新购物车
-			this.dispatch('getOrderCount'); //更新订单数量
+			uni.setStorageSync('token', token);
+			
+			// 加载用户信息
+			this.dispatch('obtainUserInfo');
 		},
 		// 退出登录
 		logout(state) {
+			// 清空 Token
 			state.token = '';
-			uni.removeStorageSync('uniIdToken');
-			this.dispatch('getCartCount');//更新购物车数量
-			uni.$emit('refreshCart');//刷新购物车
-			this.dispatch('getOrderCount'); //更新订单数量
+			uni.removeStorageSync('token');
+			// 清空用户信息 TODO 芋艿:这里 setTimeout 的原因是,上面可能还有一些 request 请求。后续得优化下
 			setTimeout(()=>{
 				state.userInfo = {};
 			}, 1100)
 		},
 	},
 	actions: {
-		//更新用户信息
-		async getUserInfo({state, commit}){
-			const res = await request('user', 'get', {}, {
-				checkAuthInvalid: false
-			});
-			if(res.status === 1){
-				const userInfo = res.data;
-				commit('setStateAttr', {
-					key: 'userInfo',
-					val: userInfo
-				})
-			}
-		},
-		//更新用户订单数量
-		async getOrderCount({state, commit}){
-			let data = {
-				c0: 0,
-				c1: 0,
-				c2: 0,
-				c3: 0
-			}
-			if(state.token){
-				try {
-					const res = await request('order', 'getOrderCount');
-					data = res;
-				}catch (err){
-					console.error('更新用户订单数量 => ', err);
-				}
-			}
+		// 获得用户基本信息
+		async obtainUserInfo({state, commit}) {
+			const data = await getUserInfo();
 			commit('setStateAttr', {
-				key: 'orderCount',
+				key: 'userInfo',
 				val: data
-			})
+			});
 		}
 	}
 }) 

Some files were not shown because too many files changed in this diff