mirror of
https://gitee.com/huangge1199_admin/vue-pro.git
synced 2025-02-17 09:40:34 +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 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 sendSmsCode = data => http.post('/member/auth/send-sms-code', data)
|
||||||
//使用手机 + 验证码登录
|
//使用手机 + 验证码登录
|
||||||
export const smsLogin = data => http.post('/member/auth/sms-login', 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 = {
|
module.exports = {
|
||||||
//后端接口地址
|
//后端接口地址
|
||||||
baseUrl: 'http://127.0.0.1:48080/app-api',
|
baseUrl: 'http://127.0.0.1:48080/app-api',
|
||||||
|
// 超时
|
||||||
|
timeout: 30000,
|
||||||
|
// 禁用 Cookie 等信息
|
||||||
|
withCredentials: false,
|
||||||
header: {
|
header: {
|
||||||
//租户ID
|
//租户ID
|
||||||
'tenant-id': 1
|
'tenant-id': 1
|
||||||
|
@ -21,6 +21,6 @@ const app = new Vue({
|
|||||||
})
|
})
|
||||||
|
|
||||||
// 引入请求封装
|
// 引入请求封装
|
||||||
require('./util/request/index')(app)
|
require('./utils/request/index')(app)
|
||||||
|
|
||||||
app.$mount()
|
app.$mount()
|
||||||
|
@ -139,15 +139,30 @@ export default {
|
|||||||
},
|
},
|
||||||
handleSubmit() {
|
handleSubmit() {
|
||||||
this.$refs.form.validate().then(res => {
|
this.$refs.form.validate().then(res => {
|
||||||
this.$store.dispatch('Login', { type: this.currentModeIndex, data: this.formData }).then(res => {
|
uni.login({
|
||||||
uni.$u.toast('登录成功')
|
provider: 'weixin',
|
||||||
setTimeout(() => {
|
success: res => {
|
||||||
uni.switchTab({
|
let data = this.formData
|
||||||
url: '/pages/user/user'
|
data.socialType = 34 //WECHAT_MINI_APP 先指定固定值
|
||||||
})
|
data.socialCode = res.code
|
||||||
}, 300)
|
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() {},
|
onReady() {},
|
||||||
methods: {
|
methods: {
|
||||||
getPhoneNumber(e) {
|
getPhoneNumber(e) {
|
||||||
let code = e.detail.code
|
let phoneCode = e.detail.code
|
||||||
if (!e.detail.code) {
|
if (!e.detail.code) {
|
||||||
uni.showModal({
|
uni.showModal({
|
||||||
title: '授权失败',
|
title: '授权失败',
|
||||||
@ -50,10 +50,10 @@ export default {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
uni.getUserInfo({
|
uni.login({
|
||||||
provider: 'weixin',
|
provider: 'weixin',
|
||||||
success: res => {
|
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('登录成功')
|
uni.$u.toast('登录成功')
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
uni.switchTab({
|
uni.switchTab({
|
||||||
|
@ -2,24 +2,25 @@ import Vue from 'vue'
|
|||||||
import Vuex from 'vuex'
|
import Vuex from 'vuex'
|
||||||
import { logout } from '@/api/auth'
|
import { logout } from '@/api/auth'
|
||||||
import { getUserInfo } from '@/api/user'
|
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的插件机制
|
Vue.use(Vuex) // vue的插件机制
|
||||||
|
|
||||||
// Vuex.Store 构造器选项
|
// Vuex.Store 构造器选项
|
||||||
const store = new Vuex.Store({
|
const store = new Vuex.Store({
|
||||||
state: {
|
state: {
|
||||||
openExamine: false, // 是否开启审核状态。用于小程序、App 等审核时,关闭部分功能。TODO 芋艿:暂时没找到刷新的地方
|
accessToken: uni.getStorageSync(AccessTokenKey), // 访问令牌
|
||||||
token: uni.getStorageSync(TokenKey), // 用户身份 Token
|
refreshToken: uni.getStorageSync(RefreshTokenKey), // 刷新令牌
|
||||||
userInfo: {}, // 用户基本信息
|
userInfo: {}
|
||||||
timerIdent: false // 全局 1s 定时器,只在全局开启一个,所有需要定时执行的任务监听该值即可,无需额外开启 TODO 芋艿:需要看看
|
|
||||||
},
|
},
|
||||||
getters: {
|
getters: {
|
||||||
token: state => state.token,
|
accessToken: state => state.accessToken,
|
||||||
|
refreshToken: state => state.refreshToken,
|
||||||
userInfo: state => state.userInfo,
|
userInfo: state => state.userInfo,
|
||||||
hasLogin: state => !!state.token
|
hasLogin: state => !!state.accessToken
|
||||||
},
|
},
|
||||||
mutations: {
|
mutations: {
|
||||||
// 更新 state 的通用方法
|
// 更新 state 的通用方法
|
||||||
@ -32,12 +33,14 @@ const store = new Vuex.Store({
|
|||||||
state[param.key] = param.val
|
state[param.key] = param.val
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// 更新token
|
// 更新令牌
|
||||||
SET_TOKEN(state, data) {
|
SET_TOKEN(state, data) {
|
||||||
// 设置 Token
|
// 设置令牌
|
||||||
const { token } = data
|
const { accessToken, refreshToken } = data
|
||||||
state.token = token
|
state.accessToken = accessToken
|
||||||
uni.setStorageSync(TokenKey, token)
|
state.refreshToken = refreshToken
|
||||||
|
uni.setStorageSync(AccessTokenKey, accessToken)
|
||||||
|
uni.setStorageSync(RefreshTokenKey, refreshToken)
|
||||||
|
|
||||||
// 加载用户信息
|
// 加载用户信息
|
||||||
this.dispatch('ObtainUserInfo')
|
this.dispatch('ObtainUserInfo')
|
||||||
@ -46,10 +49,12 @@ const store = new Vuex.Store({
|
|||||||
SET_USER_INFO(state, data) {
|
SET_USER_INFO(state, data) {
|
||||||
state.userInfo = data
|
state.userInfo = data
|
||||||
},
|
},
|
||||||
// 清空 Token 和 用户信息
|
// 清空令牌 和 用户信息
|
||||||
CLEAR_LOGIN_INFO(state) {
|
CLEAR_LOGIN_INFO(state) {
|
||||||
uni.removeStorageSync(TokenKey)
|
uni.removeStorageSync(AccessTokenKey)
|
||||||
state.token = ''
|
uni.removeStorageSync(RefreshTokenKey)
|
||||||
|
state.accessToken = ''
|
||||||
|
state.refreshToken = ''
|
||||||
state.userInfo = {}
|
state.userInfo = {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -65,7 +70,7 @@ const store = new Vuex.Store({
|
|||||||
commit('SET_TOKEN', res.data)
|
commit('SET_TOKEN', res.data)
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
return socialLogin(data).then(res => {
|
return weixinMiniAppLogin(data).then(res => {
|
||||||
commit('SET_TOKEN', res.data)
|
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,赋予默认{}
|
// 初始化请求拦截器时,会执行此方法,此时data为undefined,赋予默认{}
|
||||||
config.data = config.data || {}
|
config.data = config.data || {}
|
||||||
if (vm.$store.getters.hasLogin) {
|
if (vm.$store.getters.hasLogin) {
|
||||||
config.header.authorization = 'Bearer ' + vm.$store.getters.token
|
config.header.Authorization = 'Bearer ' + vm.$store.getters.accessToken
|
||||||
}
|
}
|
||||||
return config
|
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