Vue3 中使用axios
1.安装axios、js-cookie、pinia
axios命令行:
npm install axios
js-cookie命令行:
npm install js-cookie
store命令行:
npm install pinia
2.配置文件
(1)缓存文件配置
src/plugins/auth.js
const sessionCache = {set (key, value) {if (!sessionStorage) {return}if (key != null && value != null) {sessionStorage.setItem(key, value)}},get (key) {if (!sessionStorage) {return null}if (key == null) {return null}return sessionStorage.getItem(key)},setJSON (key, jsonValue) {if (jsonValue != null) {this.set(key, JSON.stringify(jsonValue))}},getJSON (key) {const value = this.get(key)if (value != null) {return JSON.parse(value)}},remove (key) {sessionStorage.removeItem(key);}
}
const localCache = {set (key, value) {if (!localStorage) {return}if (key != null && value != null) {localStorage.setItem(key, value)}},get (key) {if (!localStorage) {return null}if (key == null) {return null}return localStorage.getItem(key)},setJSON (key, jsonValue) {if (jsonValue != null) {this.set(key, JSON.stringify(jsonValue))}},getJSON (key) {const value = this.get(key)if (value != null) {return JSON.parse(value)}},remove (key) {localStorage.removeItem(key);}
}export default {/*** 会话级缓存*/session: sessionCache,/*** 本地缓存*/local: localCache
}
(2)js-cookie文件配置
src/utils/auth.js
import Cookies from 'js-cookie'const TokenKey = 'Admin-gis-jcpt-Token'export function getToken() {return Cookies.get(TokenKey)
}export function setToken(token) {return Cookies.set(TokenKey, token)
}export function removeToken() {return Cookies.remove(TokenKey)
}
(3)axios文件配置
src/utils/axiosHttp.js
import axios from "axios";
import { getToken } from '@/utils/auth';
import cache from '@/plugins/cache';
import store from "@/store";axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8';// 传参方式json
//axios.defaults.headers['Content-Type'] = 'application/x-www-form-urlencoded';//传参方式表单
// 设置接口超时时间
const timeout = 60000;
// 设置请求地址
const baseURL = 'http://192.168.1.167:8080/gis_jcpt';// 创建axios实例
const service = axios.create({// axios中请求配置有baseURL选项,表示请求URL公共部分//baseURL: process.env.VUE_APP_BASE_API,baseURL:baseURL,// 超时timeout: timeout})// http request 请求拦截器
service.interceptors.request.use(config =>{// 是否需要设置 tokenconst isToken = (config.headers || {}).isToken === false// 是否需要防止数据重复提交const isRepeatSubmit = (config.headers || {}).repeatSubmit === false;if (getToken() && !isToken) {//console.log("getToken",getToken());config.headers['Authorization'] = 'Bearer ' + getToken() // 让每个请求携带自定义token 请根据实际情况自行修改}// get请求映射params参数if (config.method === 'get' && config.params) {let url = config.url + '?' + tansParams(config.params);url = url.slice(0, -1);config.params = {};config.url = url;}if (!isRepeatSubmit && (config.method === 'post' || config.method === 'put')) {const requestObj = {url: config.url,data: typeof config.data === 'object' ? JSON.stringify(config.data) : config.data,time: new Date().getTime()}const requestSize = Object.keys(JSON.stringify(requestObj)).length; // 请求数据大小const limitSize = 5 * 1024 * 1024; // 限制存放数据5Mif (requestSize >= limitSize) {console.warn(`[${config.url}]: ` + '请求数据大小超出允许的5M限制,无法进行防重复提交验证。')return config;}const sessionObj = cache.session.getJSON('sessionObj')if (sessionObj === undefined || sessionObj === null || sessionObj === '') {cache.session.setJSON('sessionObj', requestObj)} else {const s_url = sessionObj.url; // 请求地址const s_data = sessionObj.data; // 请求数据const s_time = sessionObj.time; // 请求时间const interval = 1000; // 间隔时间(ms),小于此时间视为重复提交if (s_data === requestObj.data && requestObj.time - s_time < interval && s_url === requestObj.url) {const message = '数据正在处理,请勿重复提交';console.warn(`[${s_url}]: ` + message)return Promise.reject(new Error(message))} else {cache.session.setJSON('sessionObj', requestObj)}}}return config;},error =>{console.log(error)return Promise.reject(error);}
)// http response 响应拦截器
service.interceptors.response.use(response =>{// 未设置状态码则默认成功状态const code = response.data.code || 200;const msg = response.data.msg || '请求错误';if(code === 401){// 登录状态过期-退出store.dispatch('Logout').then(()=>{location.href = '/';})}else if(code === 500){return Promise.reject(new Error(msg));}else if(code === 601){//return Promise.reject('error');}else if(code !== 200){return Promise.reject('error'); }else {return response.data;}},error =>{console.log('err' + error)let { message } = error;if (message == "Network Error") {message = "后端接口连接异常";} else if (message.includes("timeout")) {message = "系统接口请求超时";} else if (message.includes("Request failed with status code")) {message = "系统接口" + message.substr(message.length - 3) + "异常";}console.log("message",message);return Promise.reject(error)}
)export default service;
登录请求为例:
src/api/login.js
import request from "@/utils/axiosHttp";// 登录方法
export function login(username, password, code, uuid) {const data = {username,password,code,uuid}return request({url: '/login',headers: {isToken: false,repeatSubmit: false},method: 'post',data: data})}// 获取用户详细信息
export function getInfo() {return request({url: '/getInfo',method: 'get'})}// 退出方法export function logout() {return request({url: '/logout',method: 'post'})}// 获取验证码
export function getCodeImg() {return request({url: '/captchaImage',headers: {isToken: false,},method: 'get',timeout: 20000})}
(4)pinia文件配置:
src/store/index.js
// store/index.js
import { createStore } from 'vuex';
import {login, logout, getInfo} from '@/api/login';
import { getToken, setToken, removeToken } from '@/utils/auth';export default createStore({state: {isLoggedIn: false, // 初始状态为未登录user: null // 存储用户信息},getters: {isLoggedIn: state => state.isLoggedIn,user: state => state.user,},mutations: {SET_TOKEN: (state, token) => {state.token = token},SET_ID: (state, id) => {state.id = id},SET_NAME: (state, name) => {state.name = name},SET_AVATAR: (state, avatar) => {state.avatar = avatar},SET_ROLES: (state, roles) => {state.roles = roles},SET_PERMISSIONS: (state, permissions) => {state.permissions = permissions},setLoginStatus(state, status) { state.isLoggedIn = status;},setUser(state, user) {state.user = user;}},actions: {Login({ commit }, user) {const username = user.username.trim();const password = user.password;const code = user.code;const uuid = user.uuid;return new Promise((resolve,reject)=>{login(username,password,code,uuid).then(res =>{console.log("res",res);if(res.code === 200){setToken(res.token);commit('SET_TOKEN', res.token);resolve(true);}else{alert(res.data.msg);}}).catch(error =>{reject(error);})})// 执行登录逻辑...//commit('setLoginStatus', true);//commit('setUser', user);//localStorage.setItem('auth', JSON.stringify(user)); // 保存到localStorage},// 获取用户信息GetInfo({ commit, state }) {return new Promise((resolve, reject) => {getInfo().then(res => {const user = res.user// 获取头像//const avatar = (user.avatar == "" || user.avatar == null) ? "@/assets/images/figure-1.png" : process.env.VUE_APP_BASE_API + user.avatar;const avatar = "@/assets/images/figure-1.png"; if (res.roles && res.roles.length > 0) { // 验证返回的roles是否是一个非空数组commit('SET_ROLES', res.roles)commit('SET_PERMISSIONS', res.permissions)} else {commit('SET_ROLES', ['ROLE_DEFAULT'])}commit('SET_ID', user.userId)commit('SET_NAME', user.userName)commit('SET_AVATAR', avatar)resolve(res)}).catch(error => {reject(error)})})},// 退出系统Logout({ commit }) {const logoutToken = {token:getToken(),}return new Promise((resolve,reject)=>{logout(logoutToken).then(() => {commit('SET_TOKEN', '')commit('SET_ROLES', [])commit('SET_PERMISSIONS', [])removeToken()resolve()}).catch(error => {reject(error)})})// 执行登出逻辑...// commit('setLoginStatus', false);// commit('setUser', null);// localStorage.removeItem('auth'); // 从localStorage移除}}
});
3.使用示例
登录:
***
***
<script setup>
import {onMounted, ref } from 'vue'
import { useRouter } from 'vue-router'
import { useStore } from 'vuex';
import { _service } from '@/api';
import { useRequest } from 'alova/client';
import {getCodeImg} from '@/api/login';const router = useRouter()
const store = useStore();
const code = ref('');
const codeUrl = ref('');
const uuid = ref('');
const username = ref('admin');
const password = ref('xxzxadmin');
// 验证码开关
const captchaEnabled = ref('');onMounted(()=>{getCode();
});// 获取验证码
const getCode = async() =>{getCodeImg().then(res => {//console.log("res",res);captchaEnabled.value = res.captchaEnabled === undefined ? true : res.captchaEnabled;if (captchaEnabled.value) {codeUrl.value = "data:image/gif;base64," + res.img;uuid.value = res.uuid;}});
}// 登录方法
const loginHandle = () => {// router.push('/')const user = {username: username.value,password: password.value,code: code.value,uuid: uuid.value};store.dispatch('Login', user).then((isLogin) => {if(isLogin){// 登录成功后跳转到首页或其他页面router.push('/index');}}).catch((error) => { console.error('Login failed:', error);alert(error);// 调用获取验证码方法getCode();});}
</script>
***
***
获取用户信息:
onMounted(()=>{// 获取用户信息store.dispatch('GetInfo').then((res)=>{console.log("GetInfo",res);})
})
退出:
***
***
<script setup>
import { useRouter } from 'vue-router';
import store from "@/store";const router = useRouter()// 退出按钮
const logout = () =>{// 退出store.dispatch('Logout').then(()=>{// 退出成功后跳转到登录页面//router.push('/');// 跳转到退出页面(当前页面打开URL页面)location.href = '/';})
}</script>
***
***
后台为若依