React + Koa2打造『官方管理后台』3

七.编写Login页面组件以及button样式类

1.scss中编写common.css,样式初始化

html{
    font-size: 14px;
    background-color: #f3f5f7;
    color: #333;
}
body{
    margin:0;
}
ul{
    padding: 0;
    margin: 0;
    list-style: none;
}
a{
    text-decoration: none;
    color: #333;
}
input,
button{
    outline: none;
    border:none;
    box-sizing: border-box;
    border-radius: 3px;
}
h1,h2,h3,h4,h5,h6,p{
    margin:0;
    font-weight: normal;
}
div{
    box-sizing: border-box;
}
i{
    font-style: normal;
}
.clearfix::after{
    content: "";
    display: block;
    clear:both
}

2.iconfont文件引入

3.index.js引入

import React from 'react';
import ReactDOM from 'react-dom';

import App from './App';
import * as serviceWorker from './serviceWorker';

import './assets/scss/common.css';
import './assets/scss/iconfont.css';
ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
);

// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister();

4.compenents中新建login文件夹,在其建立Form和logo文件夹

,index.js&index.scss文件

login

js中

import React, { Component } from 'react'
import './index.scss'
export default class Login extends Component {
    render() {
        return (
            <div className="login-container">
                
            </div>
        )
    }
}
  }
}

scss中

login-container{
    position: fixed;
    top: 50%;
    left: 50%;
    width: 600px;
    height: 250px;
    margin: -125px 0 0 -300px;
    background-color: #fff;
    box-shadow: 1px 3px 5px #999;
    border-radius: 20px;
}

5.pages中login.js下引用组件

import React, { Component } from 'react'
import Login from "../components/Login"
export default class login extends Component {
    constructor(props){
        super(props)
        this.state={}
        
    }
    render() {
        return (
            <div className="container">
                <Login></Login>
            </div>
        )
    }
}

6.在components中的Login文件夹下的logo文件夹下建立index.js和index.scss

js中

import React, { Component } from 'react'
import './index.scss'
export default class Logo extends Component {
    render() {
        return (
            <div className="logo-wrapper">
                
            </div>
        )
    }
}

scss中

.logo-wrapper{
    width: 180px;
    height: 180px;
    margin: 35px 0 0 50px;
    background: url('../../../assets/img/logo.png') no-repeat;
    background-size: 180px 180px;
}

7.父组件index.js中引用

import React, { Component } from 'react'
import Logo from './Logo'
import './index.scss'
export default class Login extends Component {
    render() {
        return (
            <div className="login-container">
                <Logo/>
            </div>
        )
    }
}

8.from文件夹中新建LoginForm和title文件夹,与index.js和index.scss

js

import React, { Component } from 'react'
import './index.scss'
export default class Form extends Component {
    render() {
        return (
            <div className="form-wrapper">
                
            </div>
        )
    }
}

scss

.form-wrapper{
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    padding: 30px 15px 15px 250px;

}

9.外层的login.js引入

import React, { Component } from 'react'
import Logo from './Logo'
import Form from './Form'
import './index.scss'
export default class Login extends Component {
    render() {
        return (
            <div className="login-container">
                <Logo/>
                <Form/>
            </div>
        )
    }
}

10.title文件夹中新建index.js和index.scss

index.js中

import React, { Component } from 'react'
import './index.scss'
export default class Title extends Component {
    render() {
        return (
            <h1 className="login-title">海儿兄弟官方网站管理后台</h1>
        )
    }
}

index.scss

.login-title{
    font-size: 23px;
    text-align: center;
}

11.在loginform中新建index.js和index.scss

index.js

import React, { Component } from 'react'
import './index.scss'
export default class LoginForm extends Component {
    render() {
        return (
            <div className="login-form-wrapper">
                <div className="input-box">
                    <i className="iconfont icon-user"></i>
                    <input type="text" className="login-input" placeholder="用户名"></input>
                </div>
                <div className="input-box">
                    <i className="iconfont icon-lock"></i>
                    <input type="password" className="login-input" placeholder="密码"></input>
                </div>
                <div className="input-box">
                    <button className="btn btn-primary">登录后台</button>
                </div>
            </div>
        )
    }
}

assets中的scss中新建button.scss

.btn{
    width: 100%;
    height: 100%;
    border-radius: 3px;
    color:#fff;
    font-size: 14px;
    &.btn-primary{
        background-color: #337ab7;
        border-color: #2e6da4;
        &:hover{
            background-color: #286090;
            border-color: #204d74;
        }
    }

    &.btn-success{
        background-color: #5cb85c;
        border-color: #4cae4c;
        &:hover{
            background-color: #449d44;
            border-color: #398439;
        }
    }

    &.btn-info{
        background-color: #5bc0de;
        border-color: #46b8da;
        &:hover{
            background-color: #31b0d5;
            border-color: #269abc;
        }
    }

    &.btn-warning{
        background-color: #f0ad4e;
        border-color: #eea236;
        &:hover{
            background-color: #ec971f;
            border-color: #d58512;
        }
    }
    &.btn-danger{
        background-color: #d9534f;
        border-color: #de3f3a;
        &:hover{
            background-color: #c9302c;
            border-color: #ac2925;
        }
    }
}

index.js中全局导入

import './assets/scss/button.scss'

index.scss

.login-form-wrapper{
    widows: 100%;
    .input-box{
        position: relative;
        width: 250px;
        height: 35px;
        margin: 18px auto 0;
        .iconfont{
            position: absolute;
            top:7px;
            left: 10px;
            font-size: 18px;
            color:#999;
        }
        .login-input{
            width: 100%;
            height: 100%;
            border: 1px solid #ddd;
            text-indent: 35px;
            font-size: 14px;
        }
    }
}

12.form中引入这两个组件

import React, { Component } from 'react'
import './index.scss'
import Title from './Title'
import LoginForm from './LoginForm'
export default class Form extends Component {
    render() {
        return (
            <div className="form-wrapper">
                <Title/>
                <LoginForm/>
            </div>
        )
    }
}

八.axios请求数据以及Koa2跨域请求配置

1.安装axios

npm i axios -S

在组件的login文件夹下的index.js中

import React, { Component } from 'react'
import axios from 'axios'
import Logo from './Logo'
import Form from './Form'
import './index.scss'
export default class Login extends Component {
    getCourseData(){
        axios('http://localhost:3000/get_courses')
        .then((res)=>{
            console.log(res)
        })
    }
    componentDidMount()
    {
        this.getCourseData();
    }
    render() {
        return (
            <div className="login-container">
                <Logo/>
                <Form/>
            </div>
        )
    }
}

2.测试连接前后端

api文件夹中安装跨域

npm i koa2-cors -S

在服务端的app.js中引入

const cors = require('koa2-cors');
app.use(cors({
  origin:function(ctx){
    return 'http://localhost:3001'
  }
}))

在控制器中的index.js中

const {getCourses} = require('../service/course')
  async getCourseData(ctx,next){
        const data = await getCourses();
        ctx.body = data;
    }

在service中的course.js中写getcourseData

 async getCourses(){
        return await CourseModel.findAll()
        }

3.在route的index.js中配置路由

const router = require('koa-router')(),
      indexController = require('../controller/index')
      router.get('/',indexController.index )      
      router.get('/get_courses',indexController.getCourseData)
      module.exports = router  

 

4.config.js中配置

  

   {isPard} = require('./env_config');
       corsOrigin:isPard ? 'xxx':'http://localhost:3001'

5.app.js中配置

const {sessionInfo,cookieInfo,redisInfo,corsOrigin} = require('./config/config')
app.use(cors({
  origin:function(ctx){
    return corsOrigin
  }
}))

九.编写登录接口以及抽离返回信息集合

1.在config中新建error_config.js

module.exports={
    LOGIN:{
        INVALID_USERNAME_LENGTH:{
            error_code:10001,
            error_msg:'Invalid username length'
        },
        INVALID_PASSWORD_LENGTH:{
            error_code:10002,
            error_msg:'Invalid password length'
        },
        USERNAME_NOT_EXIST:{
            error_code:10003,
            error_msg:'Username is not exist in database'
        },
        PASSWORD_ERROR:{
            error_code:10004,
            error_msg:'Password doesn\'t matched with the username'
        },
        INVALID_OPERATION:{
            error_code:10005,
            error_msg:'Invalid operation'
        },
        SUCCESS:{
            error_code:0,
            error_msg:'Login is ok'
        }
    }
}

2.lib下的util.js

function trimSpace(str){
    return str.replace(/\s+/g,'')
}
function returnInfo(errorInfo,data){
    if(data){
        errorInfo.data = data
    }
    return errorInfo
}
module.exports = {
    startProcess, qiniuUpload,makeCrypto,trimSpace,returnInfo
}      

3.service中的admin.js

async login(userInfo){
        const {username,password} = userInfo;
        const usernameExist = await AdminModel.findOne({
            where:{username}
        })
        if(!usernameExist){
            return 10003
        }
        const dbPassword = usernameExist.get('password');
        if(password != dbPassword){
            return 10004
        }
        return 0;
    }

4.在控制器中的的Admin.js中编写登录接口

const {adminInfo} = require('../config/config'),
      {addAdmin, login} = require('../service/admin'),
      {makeCrypto,trimSpace,returnInfo} = require('../lib/util'),
      {LOGIN} = require('../config/err_config')
class Admin {
    async createAdmin(){
        adminInfo.password = makeCrypto(adminInfo.password)
        const result = await addAdmin(adminInfo);
        if(result){
            console.log(0);
        }else{
            console.log(1);
        }
    }
    async loginAction(ctx,next){
        const {username,password} = ctx.request.body;
        if(!username||!password){
            ctx.body = returnInfo(LOGIN.INVALID_OPERATION)
            return
        }
        if(trimSpace(username).length<=0){
            ctx.body = returnInfo(LOGIN.INVALID_USERNAME_LENGTH);
            return
        }
        if(trimSpace(password).length<=0){
            ctx.body = returnInfo(LOGIN.INVALID_PASSWORD_LENGTH)
        }
        const userInfo = {
            username:trimSpace(username),
            password:makeCrypto(trimSpace(password))
        }
        const result = await login(userInfo);
        if(result === 10003){
            ctx.body = returnInfo(LOGIN.USERNAME_NOT_EXIST)
            return
        }
        if(result === 10004){
            ctx.body = returnInfo(LOGIN.PASSWORD_ERROR)
            return
        }
        return ctx.body = returnInfo(LOGIN.SUCCESS)

    }
}
module.exports = new Admin();

5.admin.js中添加路由

const router = require('koa-router')(),
adminController = require('../controller/admin')
router.prefix('/admin')
router.get('/create_admin',adminController.createAdmin)
router.post('/login_action',adminController.loginAction)
module.exports = router;

6.测试接口

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值