从零开始,搭建一个简单的购物平台(三)

从零开始,搭建一个简单的购物平台(二):https://blog.csdn.net/time_____/article/details/105408640
项目源码(持续更新):https://gitee.com/DieHunter/myCode/tree/master/shopping

这篇文章在上次的服务端登录基础上增加前端界面

在开始前我们可以简单用postman测试一下token和登录的功能,可以先在后端生成一段token从前端请求

验证token(成功和失败)

紧接着验证一下用户登录(前提事先在数据库添加用户信息,添加过程及加密不做详细说明)

测试成功后我们开始配置编写前端部分(只实现功能,对界面要求不高)

文件结构:

  • 配置config.js文件夹,新建config.js文件用于存放配置常量(和服务端config.js一样)
    export default class Config {
      static Agreement = "http://";
      static BaseUrl = "127.0.0.1";
      static ServerUrl = "";
      static ServerPort = ":1024";
      static Path = "/";
      static CryptoKey = "tokenkey";//加密信息关键字
      static FilePath = this.Agreement + this.BaseUrl + this.ServerPort + this.Path;
      static ServerApi = {//接口名
        token: "checkToken",
        user: {
          userLogin: "user/userLogin",
        }
      };
      static StorageName = {//本地缓存localstorage名称
        token: "token",
        userInfo: "userInfo"
      };
    }
  • 在utils文件中新建方法,将其放在react.component的原型中,使继承组件可以直接调用
    storage:
    import { Component } from "react";
    class Utils {
      static saveStorage(key, val) {//添加缓存
        localStorage.setItem(key, JSON.stringify(val));
      }
      static getStorage(key) {//获取缓存
        try {
          return JSON.parse(localStorage.getItem(key));
        } catch (error) {}
      }
      static clearStorage(key) {//清除缓存
        try {
          localStorage.removeItem(key);
        } catch (error) {}
      }
    }
    Component.prototype.$utils = Utils;
    

    axios:

    import Config from "../config/config";
    import Axios from "axios";
    import { Component } from "react";
    import { message } from "antd";
    Axios.defaults.baseURL =
      Config.Agreement + Config.BaseUrl + Config.ServerPort + Config.Path;
    // 添加请求拦截器
    Axios.interceptors.request.use(
      function (config) {
        // 在发送请求之前做些什么
        return config;
      },
      function (error) {
        // 对请求错误做些什么
        return Promise.reject(error);
      }
    );
    // 添加响应拦截器
    Axios.interceptors.response.use(
      function (response) {
        // 对响应数据做点什么
        if (response.data.result === -999) {
          //token验证失败
          return message.error(response.data.msg);
        }
        return response.data;
      },
      function (error) {
        console.log(error)
        // 对响应错误做点什么
        message.error("操作失败");
        return Promise.reject(error);
      }
    );
    
    Component.prototype.$axios = Axios;
    

    Crypto:

    import * as CryptoJS from "crypto-js";
    import { Component } from "react";
    import config from "../config/config";
    const { CryptoKey } = config;
    class CryptoTool {
      /* Crypto加密方法
       * @param {object} _data       对用户请求后端的参数进行加密
       */
      static setCrypto(_data) {
        let key = CryptoJS.enc.Utf8.parse(CryptoKey);
        let encrypted = CryptoJS.AES.encrypt(JSON.stringify(_data), key, {
          mode: CryptoJS.mode.ECB,
          padding: CryptoJS.pad.Pkcs7
        });
        return encrypted.toString();
      }
       /* Crypto解密方法
       * @param {string} _token       将秘文解密成对象形式
       */
      static getCrypto(_token) {
        let key = CryptoJS.enc.Utf8.parse(CryptoKey);
        let decrypt = CryptoJS.AES.decrypt(_token, key, {
          mode: CryptoJS.mode.ECB,
          padding: CryptoJS.pad.Pkcs7
        });
        return JSON.parse(CryptoJS.enc.Utf8.stringify(decrypt).toString());
      }
    }
    Component.prototype.$crypto = CryptoTool;
    
  • 在index.js中添加这些函数
    import React from "react";
    import ReactDOM from "react-dom";
    import App from "./App";
    import "./util/axios";
    import "./util/utils";
    import "./util/cryptoTool";
  •  随后在page/login中新增login.js,简单配置一下login页面后,在App.js中引入login页面
    import React from "react";
    import Login from "./page/login/login"
    
    function App() {
      return (
        <div className="App">
          <Login></Login>
        </div>
      );
    }
    
    export default App;
  • 在antd官网找到登录界面实例,直接把大部分复制到login界面,用less微调一下后实现以下界面
     
  • login.js
    import React from "react";
    import "./login.less";
    import { Card, Form, Input, Button, Checkbox, message } from "antd";
    import { UserOutlined, LockOutlined } from "@ant-design/icons";
    import config from "../../config/config";
    const { ServerApi, StorageName } = config;
    export default class Login extends React.Component {
      constructor(props) {
        super(props);
        this.checkToken(); //验证用户token是否过期
      }
      render() {
        return (
          <div className="cardBox">
            <Card title="登录">
              <Form
                name="normal_login"
                className="login-form"
                initialValues={
         
         { remember: true }}
                onFinish={this.sendData}
              >
                <Form.Item
                  name="username"
                  rules={[
                    {
                      required: true,
                      message: "请输入用户名/邮箱",
                    },
                  ]}
                >
                  <Input
                    className="infoInput"
                    prefix={<UserOutlined className="site-form-item-icon" />}
                    placeholder="用户名/邮箱"
                  />
                </Form.Item>
                <Form.Item
                  name="password"
                  rules={[
                    {
                      required: true,
                      message: "请输入密码",
                    },
                  ]}
                >
                  <Input
                    className="infoInput"
                    prefix={<LockOutlined className="site-form-item-icon" />}
                    type="password"
                    placeholder="密码"
                  />
                </Form.Item>
                <Form.Item>
                  <Form.Item name="remember" valuePropName="checked" noStyle>
                    <Checkbox>3天内免密</Checkbox>
                  </Form.Item>
                  <a className="login-form-forgot" href="#aaa">
                    忘记密码
                  </a>
                </Form.Item>
                <Form.Item>
                  <Button
                    type="primary"
                    htmlType="submit"
                    className="login-form-button"
                  >
                    登录
                  </Button>
                  或者<a href="#aaa">注册</a>
                </Form.Item>
              </Form>
            </Card>
          </div>
        );
      }
      checkToken() {
        let token = this.$utils.getStorage(StorageName.token);
        if (!token) return;
        this.$axios
          .get(ServerApi.token, {
            params: { token },
          })
          .then((res) => {
            switch (res.result) {
              case 1:
                message.success(res.msg).then(() => {
                  // this.props.history.push({
                  //   pathname: "/admin/findshop",
                  //   query: res,
                  // });
                });
                break;
              default:
                // message.warning(res.msg);
                break;
            }
          })
          .catch((err) => {
            console.log(err);
          });
      }
      sendData = (data) => {
        this.$axios
          .get(ServerApi.user.userLogin, {
            params: { crypto: this.$crypto.setCrypto(data) },
          })
          .then((res) => {
            switch (res.result) {
              case 1:
                this.$utils.saveStorage(StorageName.token, res.token);
                message.success(res.msg);
                // this.props.history.push({
                //   pathname: "/admin/findshop",
                //   query: res,
                // });
                break;
              default:
                message.warning(res.msg);
                break;
            }
          })
          .catch((err) => {
            console.log(err);
          });
      };
    }
    
  • 效果如下:

用户token验证,登录功能前端+后端基本实现

总结

前端与后端的项目搭建顺序可能有所不同,项目周期可能也不同,这时需要灵活使用前后端数据模拟和请求模拟工具,前端可以使用easymock和mockjs生成假数据,而后端最简单的直接放到浏览器url访问(仅限于get),或者使用postman,SoapUI等接口测试工具

猜你喜欢

转载自blog.csdn.net/time_____/article/details/105411636