一、用户中心
import React, { Component } from 'react'import bg from '../../images/login_bg.png'import profile from '../../images/profile.png'import './index.less'import { Link } from 'react-router-dom'import { connect } from 'react-redux'import actions from '../../store/actions/session'class Profile extends Component { componentDidMount () { this.props.toValidate() } render () { return ( <div className='profile'> <div className="profile-bg"> <img src={bg} alt=""/> <div className="avatar"> <img src={profile} alt=""/> </div> { this.props.user ? <a className='btn'>{this.props.user.username}</a> : <Link className='btn' to='/login'>登录</Link> } </div> </div>) }}export default connect(state => ({...state.session}), actions)(Profile)
.profile { width: 100%; .profile-bg { position: relative; width: 100%; img { width: 100%; } } .avatar { position: absolute; top: 35%; width: 60px; height: 60px; left: 50%; margin-left: -30px; img { width: 100%; height: 100%; } } .btn { position: absolute; bottom: 20%; left: 50%; margin-left: -60px; background: #fff; color: #239aea; width: 120px; height: 25px; line-height: 25px; border-radius: 5px; text-align: center; }}
import React, { Component } from 'react'import './index.less'import Header from "../../component/Header/Header";import { Link } from 'react-router-dom'import { connect } from 'react-redux'import actions from "../../store/actions/session";import Alert from '../../component/Aleart/Alert'class Login extends Component { login = () => { this.props.toLogin({ username: this.username.value, password: this.password.value }, this.props.history.push) } render () { return (<div className='login'> <Header title='登录' /> <ul className='container'> <li><input type="text" ref={(el) => this.username = el}/></li> <li><input type="text" ref={(el) => this.password = el}/></li> <li><Link to='/reg'>前往注册</Link></li> <li><button onClick={this.login}>登录</button></li> <li> <Alert /> </li> </ul> </div>) }}export default connect(state => ({...state.session}), actions)(Login)
.login { position: absolute; top: 0; left: 0; right: 0; bottom: 0; background: #fff; z-index: 100; ul { li { input { margin-top: 20px; width: 100%; height: 35px; border-radius: 5px; box-shadow: none; outline: none; border: 1px solid #eee; -webkit-appearance: none; } a { display: block; margin-top: 20px; color: #239aea; } button { margin-top: 20px; -webkit-appearance: none; background: #239aea; color: #fff; width: 100%; height: 35px; text-align: center; line-height: 35px; border: none; outline: none; border-radius: 5px; } } }}
import React, { Component } from 'react'import './index.less'import Header from "../../component/Header/Header";import { connect } from 'react-redux'import actions from "../../store/actions/session";import Alert from '../../component/Aleart/Alert'class Reg extends Component { reg = () => { this.props.toReg({ username: this.username.value, password: this.password.value }, this.props.history.push) } render () { return (<div className='login'> <Header title='注册' /> <ul className='container'> <li><input type="text" ref={(el) => {this.username = el}}/></li> <li><input type="text" ref={(el) => {this.password = el}}/></li> <li><button onClick={this.reg}>注册</button></li> <li><Alert /></li> </ul> </div>) }}export default connect(state => ({...state.session}), actions)(Reg)
.login { position: absolute; top: 0; left: 0; right: 0; bottom: 0; background: #fff; z-index: 100; ul { li { input { margin-top: 20px; width: 100%; height: 35px; border-radius: 5px; box-shadow: none; outline: none; border: 1px solid #eee; -webkit-appearance: none; } a { display: block; margin-top: 20px; color: #239aea; } button { margin-top: 20px; -webkit-appearance: none; background: #239aea; color: #fff; width: 100%; height: 35px; text-align: center; line-height: 35px; border: none; outline: none; border-radius: 5px; } } }}
二、STORE
import * as Types from '../action-types'let initState = { msg: '', err: 0, user: null}function reducer(state = initState, action) { switch (action.type) { case Types.SET_USER_INFO: return {...action.payload} } return state}export default reducer
三、server/package.json
{ "name": "ketang-server", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], "author": "", "license": "ISC", "dependencies": { "body-parser": "^1.19.0", "express": "^4.17.1", "express-session": "^1.16.2" }}
四、server/server.js
let express = require('express')let bodyParser = require('body-parser')let session = require('express-session')let fs = require('fs')let app = express()app.use(express.static(__dirname))app.use(bodyParser.json())app.use(session({ resave: true, // 保存 cookie saveUninitialized: true, // 保存未初始化的 session secret: 'zfpx' // 秘钥}))// CORS 跨域资源共享app.use(function (req, res, next) { // res.header('Access-Control-Allow-Origin', '*') res.header('Access-Control-Allow-Origin', 'http://localhost:8080') res.header('Access-Control-Allow-Credentials', true) res.header('Access-Control-Allow-Headers', 'Content-Type, Content-Length, Authorization, Accept, X-Request-With'); res.header('Access-Control-Allow-Methods', 'PUT,POST,GET,DELETE,OPTIONS') res.header('X-Powered-By', '3.2.1') if (req.method.toUpperCase() === 'OPTIONS') { // 让 options 快速返回 res.send(200) } else { next() }})let sliders = require('./database/sliders')let lessonsDir = __dirname + '/database/lessons.json'let jdb = (path) => JSON.parse(fs.readFileSync(path, 'utf8'))app.get('/api/sliders', (req, res) => { res.send(sliders)})app.get('/api/lessons', (req, res) => { // limit // offset // 1 let {limit, offset, type} = req.query limit = +limit offset = +offset let start = offset let end = offset + limit let data = jdb(lessonsDir) let list = data.filter((item, index) => item.type === type) list = list.slice(start, end) // 判断是否有更多 let hasMore = true hasMore = limit * offset < data.length setTimeout(() => { res.send({ hasMore, list }) }, 2000)})let users = [] // 保存所有的用户let obj = { msg: '', code: 0, user: {}}app.post('/api/login', (req, res) => { let {username, password} = req.body let isExist = users.find(i => i.username === username) if (isExist) { req.session.user = req.body console.log(users) res.send({ code: 0, user: isExist, msg: 'ok' }) } else { res.send({ code: -1, user: null, msg: '用户名或者密码错误' }) }})app.post('/api/reg', (req, res) => { let {username, password} = req.body console.log(users) let isExist = users.find(i => i.username === username) if (isExist) { res.send({ code: 1, msg: '该用户名已经被注册', user: null }) } else { users.push({ username, password }) res.send({ code: 0, msg: 'ok', user: { username, password } }) }})// 使用 session 持久化登录状态app.get('/api/validate', (req, res) => { if (req.session.user) { res.send({ msg: 'ok', code: 0, user: req.session.user }) } else { res.send({ msg: '用户未登录', code: -1, user: null }) }})app.listen(3000, () => console.log('port 3000 is on'))