> For the complete documentation index, see [llms.txt](https://close.gitbook.io/yun-wei-bi-ji/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://close.gitbook.io/yun-wei-bi-ji/centos/vue/xiang-mu/1-10.-feng-zhuang-qing-qiu-lan-jie-qi-he-xiang-ying-lan-jie-qi-ji-gong-ju-ku.md).

# 1 10.封装请求拦截器和响应拦截器及工具库

> 参考: [axios中文文档|axios中文网 | axios](http://axios-js.com/zh-cn/docs/index.html#%E6%8B%A6%E6%88%AA%E5%99%A8)
>
> 前面已经完成了登录，代码啰嗦重复部分有点多，接下来完成
>
> * 请求和响应拦截器
> * 常用工具库封装
> * 测试自动携带token

* #### 创建常用工具库文件夹；

> src/composables

* #### Cookie 工具库封装

```js
// src/composables/auth.js


import { useCookies } from '@vueuse/integrations/useCookies'

const TokenKey = 'admin-token'
const cookie = useCookies()


// 获取 token
export function getToken(){
    cookie.get(TokenKey)
}


// 设置 token
export function setToken(token){
    cookie.set(TokenKey, token)
}

// 清楚 token
export function removeToken(){
    cookie.get(TokenKey)
}

```

* #### 消息提示工具库封装

```js
// src/composables/util.js
import { ElNotification } from 'element-plus'



// 消息提示
export function toast(message, type = 'success', dangerouslyUseHTMLString = false) {
    ElNotification({
        message,
        type,
        dangerouslyUseHTMLString,
        duration: 3000
    })

}
```

* #### 请求和响应拦截器

```js
// src/axios.js
import axios from 'axios'
import { getToken } from '~/composables/auth'
import { toast } from '~/composables/util'


const service = axios.create({
  baseURL: '/api',
  // baseURL: 'http://ceshi13.dishait.cn',
  // timeout: 1000,
  // headers: {'X-Custom-Header': 'foobar'}
});


// 添加请求拦截器
service.interceptors.request.use(function (config) {
  
  // 请求时自动添加 token
  const token = getToken()
  if (token) {
    config.headers['token'] = token
  } 
  return config;
}, function (error) {
  // 对请求错误做些什么
  return Promise.reject(error);
});




// 添加响应拦截器
service.interceptors.response.use(function (response) {
  
  // 对响应数据做点什么, 直接获取响应数据当中的 data 数据
  return response.data.data;
}, function (error) {

  // 对响应错误做点什么, 如果错误直接消息提示
  toast(error.response.data.msg|| '请求失败', 'error')
  return Promise.reject(error);
});


export default service
```

* #### API 接口

```js
// src/api/manager.js
import axios  from "~/axios";

export function login(username, password) {
    return axios.post("/admin/login", {
        username,
        password
    })
}


export function getinfo() {
    return axios.post("/admin/getinfo")
}
```

* #### login.vue

```js
...略
<el-button round color="#626aef" class="w-[250px] " type="primary" :loading="loading" @click="onSubmit">登录</el-button>
...略

<script setup>
import { ref, reactive } from 'vue'
import { login,getinfo } from '~/api/manager'
import { useRouter } from 'vue-router'
import { setToken } from '~/composables/auth'
import { toast } from '~/composables/util'




const router = useRouter()

// do not use same name with ref
const form = reactive({
  username: '',
  password: '',
  
})

// 定义验证规则
const rules = {
    username: [
        {
            required: true,
            message: '用户名不能为空',
            trigger: 'blur',
        },
    ],
    password: [
        {
            required: true,
            message: '密码不能为空',
            trigger: 'blur',
        },
    ]
}

// 点击登录验证
const formRef = ref(null)
const loading = ref(false)

const onSubmit = () => {
    formRef.value.validate((valid) => {
        if (!valid) {
            console.log('error')
        }
        // 加载按钮动画
        loading.value = true

        login(form.username, form.password).then(res=> {

            // 存储 token 
            setToken(res.token)

            // 消息提示
            toast('登录成功')


            // 测试携带 Token 访问自己个人信息
            getinfo().then(res2=>{
                console.log(res2)
            })
            // 跳转到后台
            router.push('/')
        })
        .finally(()=> {
            loading.value = false
        })

    })
}
</script>
```
