mirror of
https://gitee.com/huangge1199_admin/vue-pro.git
synced 2024-11-23 07:41:53 +08:00
1.同步调整到OAuth2方式登录 2.微信小程序一键登录;
This commit is contained in:
parent
e1c08c4661
commit
13b5ad127a
@ -3,11 +3,13 @@ const { http } = uni.$u
|
||||
|
||||
//使用手机 + 密码登录
|
||||
export const passwordLogin = data => http.post('/member/auth/login', data)
|
||||
//退出登录
|
||||
export const logout = data => http.post('/member/auth/logout', data)
|
||||
//发送手机验证码
|
||||
export const sendSmsCode = data => http.post('/member/auth/send-sms-code', data)
|
||||
//使用手机 + 验证码登录
|
||||
export const smsLogin = data => http.post('/member/auth/sms-login', data)
|
||||
//社交登录,使用 (手机号授权)code + 用户信息
|
||||
export const socialLogin = data => http.post('/member/auth/social-login', data)
|
||||
//微信小程序的一键登录
|
||||
export const weixinMiniAppLogin = data => http.post('/member/auth/weixin-mini-app-login', data)
|
||||
//刷新令牌
|
||||
export const refreshToken = data => http.post('/member/auth/refresh-token', data)
|
||||
//退出登录
|
||||
export const logout = data => http.post('/member/auth/logout', data)
|
||||
|
@ -1,6 +1,10 @@
|
||||
module.exports = {
|
||||
//后端接口地址
|
||||
baseUrl: 'http://127.0.0.1:48080/app-api',
|
||||
// 超时
|
||||
timeout: 30000,
|
||||
// 禁用 Cookie 等信息
|
||||
withCredentials: false,
|
||||
header: {
|
||||
//租户ID
|
||||
'tenant-id': 1
|
||||
|
@ -21,6 +21,6 @@ const app = new Vue({
|
||||
})
|
||||
|
||||
// 引入请求封装
|
||||
require('./util/request/index')(app)
|
||||
require('./utils/request/index')(app)
|
||||
|
||||
app.$mount()
|
||||
|
@ -139,15 +139,30 @@ export default {
|
||||
},
|
||||
handleSubmit() {
|
||||
this.$refs.form.validate().then(res => {
|
||||
this.$store.dispatch('Login', { type: this.currentModeIndex, data: this.formData }).then(res => {
|
||||
uni.$u.toast('登录成功')
|
||||
setTimeout(() => {
|
||||
uni.switchTab({
|
||||
url: '/pages/user/user'
|
||||
})
|
||||
}, 300)
|
||||
uni.login({
|
||||
provider: 'weixin',
|
||||
success: res => {
|
||||
let data = this.formData
|
||||
data.socialType = 34 //WECHAT_MINI_APP 先指定固定值
|
||||
data.socialCode = res.code
|
||||
data.socialState = Math.random() // 该参数没有实际意义暂时传随机数
|
||||
this.mobileLogin(data)
|
||||
},
|
||||
fail: res => {
|
||||
this.mobileLogin(this.formData)
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
mobileLogin(data){
|
||||
this.$store.dispatch('Login', { type: this.currentModeIndex, data: data }).then(res => {
|
||||
uni.$u.toast('登录成功')
|
||||
setTimeout(() => {
|
||||
uni.switchTab({
|
||||
url: '/pages/user/user'
|
||||
})
|
||||
}, 300)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ export default {
|
||||
onReady() {},
|
||||
methods: {
|
||||
getPhoneNumber(e) {
|
||||
let code = e.detail.code
|
||||
let phoneCode = e.detail.code
|
||||
if (!e.detail.code) {
|
||||
uni.showModal({
|
||||
title: '授权失败',
|
||||
@ -50,10 +50,10 @@ export default {
|
||||
}
|
||||
})
|
||||
} else {
|
||||
uni.getUserInfo({
|
||||
uni.login({
|
||||
provider: 'weixin',
|
||||
success: res => {
|
||||
this.$store.dispatch('Login', { type: 2, data: { code: code, userData: res } }).then(res => {
|
||||
this.$store.dispatch('Login', { type: 2, data: { phoneCode: phoneCode, loginCode: res.code } }).then(res => {
|
||||
uni.$u.toast('登录成功')
|
||||
setTimeout(() => {
|
||||
uni.switchTab({
|
||||
|
@ -2,24 +2,25 @@ import Vue from 'vue'
|
||||
import Vuex from 'vuex'
|
||||
import { logout } from '@/api/auth'
|
||||
import { getUserInfo } from '@/api/user'
|
||||
import { passwordLogin, smsLogin, socialLogin } from '@/api/auth'
|
||||
import { passwordLogin, smsLogin, weixinMiniAppLogin } from '@/api/auth'
|
||||
|
||||
const TokenKey = 'App-Token'
|
||||
const AccessTokenKey = 'ACCESS_TOKEN'
|
||||
const RefreshTokenKey = 'REFRESH_TOKEN'
|
||||
|
||||
Vue.use(Vuex) // vue的插件机制
|
||||
|
||||
// Vuex.Store 构造器选项
|
||||
const store = new Vuex.Store({
|
||||
state: {
|
||||
openExamine: false, // 是否开启审核状态。用于小程序、App 等审核时,关闭部分功能。TODO 芋艿:暂时没找到刷新的地方
|
||||
token: uni.getStorageSync(TokenKey), // 用户身份 Token
|
||||
userInfo: {}, // 用户基本信息
|
||||
timerIdent: false // 全局 1s 定时器,只在全局开启一个,所有需要定时执行的任务监听该值即可,无需额外开启 TODO 芋艿:需要看看
|
||||
accessToken: uni.getStorageSync(AccessTokenKey), // 访问令牌
|
||||
refreshToken: uni.getStorageSync(RefreshTokenKey), // 刷新令牌
|
||||
userInfo: {}
|
||||
},
|
||||
getters: {
|
||||
token: state => state.token,
|
||||
accessToken: state => state.accessToken,
|
||||
refreshToken: state => state.refreshToken,
|
||||
userInfo: state => state.userInfo,
|
||||
hasLogin: state => !!state.token
|
||||
hasLogin: state => !!state.accessToken
|
||||
},
|
||||
mutations: {
|
||||
// 更新 state 的通用方法
|
||||
@ -32,12 +33,14 @@ const store = new Vuex.Store({
|
||||
state[param.key] = param.val
|
||||
}
|
||||
},
|
||||
// 更新token
|
||||
// 更新令牌
|
||||
SET_TOKEN(state, data) {
|
||||
// 设置 Token
|
||||
const { token } = data
|
||||
state.token = token
|
||||
uni.setStorageSync(TokenKey, token)
|
||||
// 设置令牌
|
||||
const { accessToken, refreshToken } = data
|
||||
state.accessToken = accessToken
|
||||
state.refreshToken = refreshToken
|
||||
uni.setStorageSync(AccessTokenKey, accessToken)
|
||||
uni.setStorageSync(RefreshTokenKey, refreshToken)
|
||||
|
||||
// 加载用户信息
|
||||
this.dispatch('ObtainUserInfo')
|
||||
@ -46,10 +49,12 @@ const store = new Vuex.Store({
|
||||
SET_USER_INFO(state, data) {
|
||||
state.userInfo = data
|
||||
},
|
||||
// 清空 Token 和 用户信息
|
||||
// 清空令牌 和 用户信息
|
||||
CLEAR_LOGIN_INFO(state) {
|
||||
uni.removeStorageSync(TokenKey)
|
||||
state.token = ''
|
||||
uni.removeStorageSync(AccessTokenKey)
|
||||
uni.removeStorageSync(RefreshTokenKey)
|
||||
state.accessToken = ''
|
||||
state.refreshToken = ''
|
||||
state.userInfo = {}
|
||||
}
|
||||
},
|
||||
@ -65,7 +70,7 @@ const store = new Vuex.Store({
|
||||
commit('SET_TOKEN', res.data)
|
||||
})
|
||||
} else {
|
||||
return socialLogin(data).then(res => {
|
||||
return weixinMiniAppLogin(data).then(res => {
|
||||
commit('SET_TOKEN', res.data)
|
||||
})
|
||||
}
|
||||
|
@ -1,29 +0,0 @@
|
||||
/**
|
||||
* 响应拦截
|
||||
* @param {Object} http
|
||||
*/
|
||||
module.exports = vm => {
|
||||
uni.$u.http.interceptors.response.use(
|
||||
res => {
|
||||
//对响应成功做点什么 可使用async await 做异步操作
|
||||
//可以根据业务情况做相应的处理
|
||||
if (res.data.code === 0) {
|
||||
return res.data
|
||||
} else if(res.data.code === 401) {
|
||||
//用户未登录或登录token已过期
|
||||
vm.$store.commit('CLEAR_LOGIN_INFO')
|
||||
} else {
|
||||
console.log(res)
|
||||
//其他错误信息统一处理
|
||||
uni.$u.toast(res.data.msg)
|
||||
return Promise.reject(res)
|
||||
}
|
||||
},
|
||||
err => {
|
||||
//对响应错误做点什么 (statusCode !== 200)
|
||||
console.log(err)
|
||||
uni.$u.toast('响应错误' + err.statusCode)
|
||||
return Promise.reject(err)
|
||||
}
|
||||
)
|
||||
}
|
6
yudao-ui-app/utils/request/errorCode.js
Normal file
6
yudao-ui-app/utils/request/errorCode.js
Normal file
@ -0,0 +1,6 @@
|
||||
export default {
|
||||
'401': '认证失败,无法访问系统资源',
|
||||
'403': '当前操作没有权限',
|
||||
'404': '访问资源不存在',
|
||||
'default': '系统未知错误,请反馈给管理员'
|
||||
}
|
14
yudao-ui-app/utils/request/index.js
Normal file
14
yudao-ui-app/utils/request/index.js
Normal file
@ -0,0 +1,14 @@
|
||||
// 引入配置
|
||||
import config from '@/common/config'
|
||||
// 初始化请求配置
|
||||
uni.$u.http.setConfig((defaultConfig) => {
|
||||
/* defaultConfig 为默认全局配置 */
|
||||
defaultConfig.baseURL = config.baseUrl /* 根域名 */
|
||||
defaultConfig.header = config.header
|
||||
return defaultConfig
|
||||
})
|
||||
|
||||
module.exports = (vm) => {
|
||||
require('./requestInterceptors')(vm)
|
||||
require('./responseInterceptors')(vm)
|
||||
}
|
@ -9,7 +9,7 @@ module.exports = vm => {
|
||||
// 初始化请求拦截器时,会执行此方法,此时data为undefined,赋予默认{}
|
||||
config.data = config.data || {}
|
||||
if (vm.$store.getters.hasLogin) {
|
||||
config.header.authorization = 'Bearer ' + vm.$store.getters.token
|
||||
config.header.Authorization = 'Bearer ' + vm.$store.getters.accessToken
|
||||
}
|
||||
return config
|
||||
},
|
98
yudao-ui-app/utils/request/responseInterceptors.js
Normal file
98
yudao-ui-app/utils/request/responseInterceptors.js
Normal file
@ -0,0 +1,98 @@
|
||||
import errorCode from '@/utils/request/errorCode'
|
||||
import { refreshToken } from '@/api/auth'
|
||||
|
||||
// 需要忽略的提示。忽略后,自动 Promise.reject('error')
|
||||
const ignoreMsgs = [
|
||||
'无效的刷新令牌', // 刷新令牌被删除时,不用提示
|
||||
'刷新令牌已过期' // 使用刷新令牌,刷新获取新的访问令牌时,结果因为过期失败,此时需要忽略。否则,会导致继续 401,无法跳转到登出界面
|
||||
]
|
||||
|
||||
// 请求队列
|
||||
let requestList = []
|
||||
// 是否正在刷新中
|
||||
let isRefreshToken = false
|
||||
|
||||
/**
|
||||
* 响应拦截
|
||||
* @param {Object} http
|
||||
*/
|
||||
module.exports = vm => {
|
||||
uni.$u.http.interceptors.response.use(
|
||||
async res => {
|
||||
const code = res.data.code || 0
|
||||
const msg = res.data.msg || errorCode[code] || errorCode['default']
|
||||
|
||||
if (ignoreMsgs.indexOf(msg) !== -1) {
|
||||
// 如果是忽略的错误码,直接返回 msg 异常
|
||||
return Promise.reject(msg)
|
||||
} else if (code === 401) {
|
||||
// 如果未认证,并且未进行刷新令牌,说明可能是访问令牌过期了
|
||||
if (!isRefreshToken) {
|
||||
isRefreshToken = true
|
||||
// 1. 如果获取不到刷新令牌,则只能执行登出操作
|
||||
if (!vm.$store.getters.refreshToken()) {
|
||||
vm.$store.commit('CLEAR_LOGIN_INFO')
|
||||
return Promise.reject(res)
|
||||
}
|
||||
// 2. 进行刷新访问令牌
|
||||
try {
|
||||
const refreshTokenRes = await refreshToken()
|
||||
// 2.1 刷新成功,则回放队列的请求 + 当前请求
|
||||
vm.$store.commit('SET_TOKEN', refreshTokenRes.data)
|
||||
requestList.forEach(cb => cb())
|
||||
return uni.$u.http.request(res.config)
|
||||
} catch (e) {
|
||||
// 为什么需要 catch 异常呢?刷新失败时,请求因为 Promise.reject 触发异常。
|
||||
// 2.2 刷新失败,只回放队列的请求
|
||||
requestList.forEach(cb => cb())
|
||||
// 登出。即不回放当前请求!不然会形成递归
|
||||
vm.$store.commit('CLEAR_LOGIN_INFO')
|
||||
return Promise.reject(res)
|
||||
} finally {
|
||||
requestList = []
|
||||
isRefreshToken = false
|
||||
}
|
||||
} else {
|
||||
// 添加到队列,等待刷新获取到新的令牌
|
||||
return new Promise(resolve => {
|
||||
requestList.push(() => {
|
||||
res.config.header.Authorization = 'Bearer ' + vm.$store.getters.accessToken // 让每个请求携带自定义token 请根据实际情况自行修改
|
||||
resolve(uni.$u.http.request(res.config))
|
||||
})
|
||||
})
|
||||
}
|
||||
} else if (code === 500) {
|
||||
uni.$u.toast(msg)
|
||||
return Promise.reject(res)
|
||||
} else if (code === 901) {
|
||||
uni.$u.toast('演示模式,无法进行写操作')
|
||||
return Promise.reject(res)
|
||||
} else if (code !== 0) {
|
||||
if (msg === '无效的刷新令牌') {
|
||||
// hard coding:忽略这个提示,直接登出
|
||||
console.log(msg)
|
||||
} else {
|
||||
uni.$u.toast(msg)
|
||||
}
|
||||
return Promise.reject(res)
|
||||
} else {
|
||||
return res.data
|
||||
}
|
||||
},
|
||||
err => {
|
||||
console.log(err)
|
||||
let { message } = err
|
||||
if (!message) {
|
||||
message = '系统发生未知错误'
|
||||
}else if (message === 'Network Error') {
|
||||
message = '后端接口连接异常'
|
||||
} else if (message.includes('timeout')) {
|
||||
message = '系统接口请求超时'
|
||||
} else if (message.includes('Request failed with status code')) {
|
||||
message = '系统接口' + message.substring(message.length - 3) + '异常'
|
||||
}
|
||||
uni.$u.toast(message)
|
||||
return Promise.reject(err)
|
||||
}
|
||||
)
|
||||
}
|
Loading…
Reference in New Issue
Block a user