增加个人信息的加载

This commit is contained in:
YunaiV 2021-11-26 09:47:23 +08:00
parent 86ef156de4
commit 2da6a746e4
13 changed files with 295 additions and 99 deletions

View File

@ -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());
}
}
}

View File

@ -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

View File

@ -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

View File

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

View File

@ -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 one or more lines are too long

View File

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

View File

@ -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
})
}

View File

@ -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) {

View File

@ -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;
}
}

View File

@ -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) {

View File

@ -82,7 +82,8 @@
};
},
onShow() {
// TODO
//
this.$store.dispatch('obtainUserInfo');
// TODO
}
}

View File

@ -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
})
});
}
}
})