都2022年了还没用过CMS数据可视化吗?02

182 阅读5分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第26天,点击查看活动详情

接CMS数据可视化01

配置Axios项目根路径

  • 目前echarts图表中的数据都是假数据

  • 如果获取真数据就需要调用接口

  • 这就需要至少要完成注册、登录、初始化数据等接口的调用才行

  • 项目中接口根路径是相同的,见前文 重要的三个地址

  • 所以,在 assets/utils 文件夹,创建axios的配置文件,取名 common.js 。代码如下:

    axios.defaults.baseURL = 'http://www.itcbc.com:8000';
    

    这里之所以放到 assets/utils 文件夹中,是因为 utils 在编程中常用来放工具函数。而request是请求的意思。

注册账号

切换登录和注册的盒子

登录和注册同在 login.html 中,因为定位的原因重叠在一起了。我们可以通过JS实现切换两个盒子

// 切换两个盒子
document.querySelector('.login a').addEventLister('click', function () {
    document.querySelector('.login').style.display = 'none';
    document.querySelector('.register').style.display = 'block';
})
document.querySelector('.register a').addEventLister('click', function () {
    document.querySelector('.login').style.display = 'block';
    document.querySelector('.register').style.display = 'none';
})

表单验证

完成注册

当表单验证通过后,根据接口文档,获取输入框的账号和密码,Ajax提交账号和密码

document.querySelector('.register form').addEventListener('submit', function (e) {
  e.preventDefault();
  // 通过验证,这里的代码将会执行。我们将Ajax请求的代码放到这里即可
  let data = $(this).serialize();
  // console.log(data);
  axios.post('/api/register', data).then(({ data: res }) => {
    // console.log(res);
    if (res.code === 0) { // 我们只考虑成功的情况即可,失败的情况后续统一使用拦截器处理
      toastr.success(res.message); // 使用插件提示消息
      document.querySelector('.register input').value = ''; // 清空输入框
      document.querySelector('.register a').click(); // 切换至登录的盒子
    }
  })
});

登录功能

  • 因为前文已经完成了注册,所以这里的登录功能极为简单

  • 问题是,登录如果成功,该做什么?

    • 将服务器响应的token存储到本地存储(关于token的说明见下文的 JWT身份认证
    • 跳转到 index.html 页面 (页面跳转,只考虑两个html之间的相对关系,不考虑js在哪里)

登录的代码如下:

document.querySelector('.login form').addEventListener('submit', function (e) {
    e.preventDefault();
    //提交逻辑
    let data = $(this).serialize();
    // console.log(data);
    axios.post('/api/login', data).then(({ data: res }) => {
        // console.log(res);
        if (res.code === 0) {
            localStorage.setItem('token', res.token);
            location.href = './index.html'
        }
    })
});

JWT身份认证

什么是jwt身份认证

在前后端分离模式的开发中,服务器如何知道来访者的身份呢?

  • 在登录后,服务器会响应给用户一个 令牌 (token)
  • 令牌中会包括该用户的id等唯一标识
  • 浏览器收到令牌后,自己保存
  • 下次请求其他接口时,(在请求头中)携带这个令牌去请求
  • 这样服务器就知道来访者的身份了,服务器就会为该用户开发接口的访问权限,并处理该用户的数据

这样,就明白为什么登录后,要将token保存到本地存储中了。

全局配置请求头

由于除了登录和注册接口外,其他所有接口都需要身份认证(都需要我们提供令牌),所以我们可以在 request.js 中,全局配置请求头。

axios.defaults.headers.common['Authorization'] = localStorage.getItem('token');

利用令牌控制页面的访问权限

浏览器端,可以通过合理使用令牌,控制页面的访问权限。

比如,用户默认只能访问登录页,如果不登录就不能访问首页,怎么做?

第一个判断:判断本地存储是否有token

<!-- index.html -->
<!-- 本地存储有token,则说明用户登录了;没有token,则说明用户没有登录,不允许访问首页 -->
<script>
  if (localStorage.getItem('token') === null) location.href = './login.html'
</script>

上述判断只能判断token有没有,但不能判断token的真假,所以需要发送Ajax请求,根据服务器响应结果再次判断

第二个判断:根据服务器响应结果,判断token是否是假token或者过期的token

  • 如果token值是正确的,是没有过期的,则服务器响应 code===0
  • 如果token是错误的获取过期的,则服务器响应 code===1 && message==='身份认证失败'
// request.js 中,使用响应拦截器,拦截响应结果进行判断
// 如果响应结果中 code === 1 && message === '身份认证失败' 则表示浏览器使用了无效的token
// 添加响应拦截器
axios.interceptors.response.use(function (response) {
    // 对响应数据做点什么
    return response;
}, function (error) {
    // 对响应错误做点什么
    if (error.response) {
        if (error.response.data.message === '身份认证失败') {
            localStorage.removeItem('token');
            location.href = './login.html'
        }
    }
    return Promise.reject(error);
});

统一处理错误提示

在上述响应拦截器的基础之上,顺便添加响应错误提示。

所有接口响应的结果有两种:

  • 响应状态码 小于 400,并且 code===1,比如登录账号密码错误。这样的响应进入响应拦截器中的第一个函数。
  • 响应状态码 大于等于 400,并且 code === 1 ,比如身份认证失败。这样的响应进入响应拦截器中的第二个函数。

所以分别提示

// request.js 中,使用响应拦截器,拦截响应结果进行判断
// 如果响应结果中 code === 1 && message === '身份认证失败' 则表示浏览器使用了无效的token
// 添加响应拦截器
axios.interceptors.response.use(function (response) {
    // 对响应数据做点什么
    if (response.data.code === 1) {
        toastr.warning(response.data.message)
    }
    return response;
}, function (error) {
    // 对响应错误做点什么
    if (error.response) {
        if (error.response.data.message === '身份认证失败') {
            localStorage.removeItem('token');
            location.href = './login.html'
        } else {
            toastr.error(error.response.data.message);
        }
    }
    return Promise.reject(error);
});

退出登录

一般来说,退出需要做的事和登录后做的事刚好相反。

  • 登录后,在本地存储了token;退出时,移除这个token
  • 登录后,跳转到了 index.html 页面;退出时,跳转到 login.html
// ------------------------ 退出登录 -------------------
document.querySelector('.logout a').addEventLister('click', function () {
  if (!confirm('确定要退出登录吗?')) return;
  localStorage.removeItem('token');
  location.href = './login.html';
})

初始化数据

为了减少手动录入数据的时间,特别设计了此接口。调用此接口将为你随机添加56名同学,并分为8个组。并为每位同学随机添加了三次成绩。

// ------------------------ 初始化数据 -------------------
document.querySelector('.init').addEventLister('click', function () {
  axios.get('/init/data').then(({ data: res }) => {
    if (res.code === 0) {
      toastr.success(res.message);
    }
  })
})

班级概况

  • 查阅接口文档,发现服务器已经将数据计算整理完毕,提供了现成的接口。
  • 所以我们前端开发者,只需要调用接口,并将数据展示到页面中即可。
// 获取班级概况数据
axios.get('/student/overview').then(({ data: res }) => {
  // console.log(res);
  let { code, data } = res;
  if (code === 0) {
    document.querySelector('.overview .total').innerHTML = data.total;
    document.querySelector('.overview .avgAge').innerHTML = data.avgAge;
    document.querySelector('.overview .avgSalary').innerHTML = data.avgSalary;
    document.querySelector('.overview .proportion').innerHTML = data.proportion;
  }
})

最后是原图

wallhaven-dpq193.jpg