egg+vue 登录,注册分页器,详情,添加

这是一个小型还没有完善的特别完整的案例,里面包括了上面的功能,希望对小伙伴们有帮助哦!!!!!!!

技术栈

  • 前台 vue +element-ui
  • 后台 egg+mysql
注意以下几点
  • 首先需要配置 config.default.js和plugin,里面包括mysql的配置,以及安全检测的关闭。
* config.default.js
config.mysql = {
  // 单数据库信息配置
  client: {
    // host
    host: 'localhost',
    // 端口号
    port: '3306',
    // 用户名
    user: 'root',
    // 密码
    password: 'root',
    // 数据库名
    database: '1703d_bk',
  },
  // 是否加载到 app 上,默认开启
  app: true,
  // 是否加载到 agent 上,默认关闭
  agent: false,
};

 //安全检测关闭
config.security = {
    csrf: {
      enable: false,
    },
  };
  • 在plugins里面配置mysq
  • 注意需要下载 egg-mysql
//plugin
  exports.mysql = {
    enable: true,
    package: 'egg-mysql',
  };
  • 最后一点还需要配置前端代理
  • 前端 config/index.js
  proxyTable: {
      '/api':{
        target:"http://127.0.0.1:7001/",  
        changeOrigin:true,   
        pathRewrite:{
            '^/api':'' 
        }
      }
    },

接下来进入正题吧->

后台
  • 首先是登录
    • app/controller/login.js
'use strict';
const Controller = require('egg').Controller;
class LoginController extends Controller {
    async loginFn() {
        const { ctx, service } = this;
        let { user, pwd } = ctx.request.body;
        let result = await service.login.gologin(user, pwd);
        ctx.body = result;
    }
}
module.exports = LoginController;
  • app/service/login.js
'use strict';
const Service = require('egg').Service;
class LoginService extends Service {
    async gologin(user,pwd) {
        //some有一个条件成立就返回true
     let result= await this.app.mysql.select("user");
     let flag=result.some(
         item => item.userName === user && item.password === pwd
    )
    if(flag){
        //token签名 有效期为1小时
        // const token = await this.app.jwt.sign({user,pwd},"wangzhen",{expiresIn:'24h'})
        // console.log(token);
        return{
            code:1,
            message:'登陆成功',
            // token
        }
    }else{
        return{
            code:-1,
            message:'登陆失败'
        }
    }
  }
}
module.exports = LoginService;
  • 注册
    • app/controller/registry.js
'use strict';
const Controller = require('egg').Controller;
class RegistryController extends Controller {
    async registryFn() {
        const { ctx, service } = this;
        let { user, pwd, name, pwd1 } = ctx.request.body;
        let result = await service.registry.goregistry(user, pwd, name, pwd1);
        ctx.body = result;
    }
}
module.exports = RegistryController;
  • app/service/registry.js
'use strict';
const Service = require('egg').Service;
class RegistryService extends Service {
    async goregistry(user, pwd, name, pwd1) {
        let Sql = `SELECT * FROM user where userName="${user}" AND password="${pwd1}"`
        let flag = await this.app.mysql.query(Sql)
        if (flag.length > 0) {
            return {
                code: -1,
                message: '注册失败,用户已存在',
            }
        } else {
            let res = await this.app.mysql.insert('user', { userName: user, password: pwd1, name })
            return {
                code: 1,
                message: '注册成功',
                res
            }
        }
    }
}

module.exports = RegistryService;
  • 总数据,分页,详情,添加
    • app/constroller/list.js
'use strict';
const Controller = require('egg').Controller;
class ListController extends Controller {
    // 获取总数据
    async getInit() {
        const { ctx, service } = this;
        let result = await service.list.getInit();
        console.log(result)
        ctx.body={
            ...{result}
        };      
    }
   //分页
    async fenye(){
          const { ctx, service } = this;
          const obj=ctx.query;
          const result=await service.list.fenye(obj);
          ctx.body=result;
    }
    // 添加数据
    async addlist() {
        const { ctx, service } = this;
        let { title, tag, textarea } = ctx.request.body.obj;
        let result = await service.list.getaddlist(title, tag, textarea);
        ctx.body = result;
    }
    //详情
    async getDetail() {
    const { ctx ,service} = this;
     let listId=ctx.query.listId;
     console.log(listId)
     let result= await service.list.getDetail(listId);
      ctx.body={
        ...{result},
        code:1,
    }
  }
}
module.exports = ListController;
  • app/service/list.js
'use strict';
const Service = require('egg').Service;
class ListService extends Service {
    // 获取总数据
    async getInit(obj) {
        let result=await this.app.mysql.select("votelist")
        return result;
    }
    async fenye(obj){
        let result=await this.app.mysql.select("votelist",{
            orders:["createTime"],
            limit:+obj.size,
            offset:(+obj.page-1)*+obj.size
        })
        console.log(result,"1234567")
        return{
            code:1,
            msg:"成功",
            result
        }
    }
    // 添加数据
    async getaddlist(title, tag, textarea) {
        let time = new Date().toLocaleString();
        let result = await this.app.mysql.insert('votelist', {
            title,
            tagname: tag,
            context: textarea,
            author: "王者",
            createTime: time,
            count: 12
        });
        if (result.affectedRows === 1) {
            return {
                code: 1,
                message: "添加成功"
            }
        } else {
            return {
                code: -1,
                message: "添加失败"
            }
        }
    }
      //详情
     async getDetail(listId){
         return await this.app.mysql.get("votelist",{listId})
     }
}
module.exports = ListService;
  • 路由
    • app/router.js
'use strict';
/**
 * @param {Egg.Application} app - egg application
 */
module.exports = app => {
    const { router, controller } = app;
    router.get('/', controller.home.index);
    router.post('/goLogin', controller.login.loginFn);
    router.post('/goRegistry', controller.registry.registryFn);
    router.get('/getList', controller.list.getInit);
    router.post('/getAddList', controller.list.addlist);
    router.get("/getDetail",controller.list.getDetail)
    router.get("/fenye",controller.list.fenye)
};
前台
  • 首先app.vue里面需要写上样式宽高
  • 接下来进入正题

  • router.js
import Vue from 'vue'
import Router from 'vue-router'
const Login = () =>
    import ("@/views/login")
const Registry = () =>
    import ("@/views/registry")
const Home = () =>
    import ("@/views/home")
const Publish = () =>
    import ("@/views/publish")
const Detail = () =>
    import ("@/views/detail")

Vue.use(Router)

export default new Router({
    routes: [{
            path: '/',
            redirect: '/login'
        },
        {
            path: '/login',
            name: 'login',
            component: Login
        },
        {
            path: '/registry',
            name: 'registry',
            component: Registry
        },
        {
            path: '/home',
            name: 'home',
            component: Home,
        },
        {
            path: '/publish',
            name: 'publish',
            component: Publish
        },
        {
            path: '/detail/:listId',
            name: 'detail',
            component: Detail
        },
    ]
})
  • mian.js
import Vue from 'vue'
import App from './App'
import router from './router'
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
import store from "./store"
// import MyHeader from './components/header'
// Vue.prototype(MyHeader, MyHeader);
Vue.use(ElementUI);
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
    el: '#app',
    router,
    store,
    components: { App },
    template: ''
})
  • store.jsvuex部分
import Vue from 'vue'
import Vuex from 'vuex'
import axios from 'axios'
Vue.use(Vuex)
export default new Vuex.Store({
    state: {
        list: [],
        fenData:[]    
    },
    getters: {},
    mutations: {
        // 获取总数据
        getlist(state, list) {
            state.list = list   
        },
        // 添加数据
        getAdd(state, obj) {
            state.list.push(obj)
        },
        getFenye(state,obj){
            state.fenData=obj;
        }       
    },
    actions: {
        getData({ commit }) {
            axios.get('/api/getList').then(res => {
                commit("getlist", res.data.result)               
            })
        },
        getAddDATA({ commit }, obj) {
            axios.post('/api/getAddList', { obj }).then(res => {
                console.log(res.data.result)
            })
        },
        getlistFn({commit},payload){
            axios.get("/api/fenye?page="+payload.page+"&&size="+payload.size).then(res=>{
                commit("getFenye",res.data.result)       
            })
        }     
    },
})
  • login.vue
<template>
    <div class="wrap">
        <div class="mask-bg">
            <div class="mask">
                <div class="nav">
                    <h3>网站博客登录</h3>
                </div>
                <div class="mask-box">
                    <div class="group">
                       <p>
                             <label>用户名:</label>&nbsp;
                             <el-input placeholder="请输入用户" v-model="user"></el-input>
                       </p>
                        <h3></h3>
                       <p>
                            <label>&nbsp;&nbsp;&nbsp;:</label>&nbsp;
                             <el-input placeholder="请输入密码" v-model="pwd"></el-input>
                       </p>
                    </div>
                </div>
                 <button class="btn"
                 @click="goHome"
                 >登录</button>
            </div>
        </div>
    </div>
</template>
<script>
import request from "../utils/axiosreq"
export default {
    props:{
    },
    components:{
    },
    data(){
        return {
            user:'',
            pwd:''
        }
    },
    computed:{
   },
    methods:{
         goHome(){
             request.post("/api/goLogin",{
                user:this.user,
                pwd:this.pwd
            }).then((res)=>{
                console.log(res);
                window.localStorage.setItem('token',res.token)
                if(res.code === 1){
                    this.$router.push('/home');
                    alert(res.message);
                }else{
                    this.$router.push('/registry');
                    alert(res.message);
                }
            })
        }        
    },
    created(){      
    },
    mounted(){     
    }
}
</script>
<style scoped lang="">
.mask-bg{
    width:100%;
    height:100%;
    position:absolute;
    top:0;
    left:0;
    background: #f5f5f5;
}
.mask{
    width:400px;
    height:300px;
    background: white;
    border-radius: 5px;
    position: absolute;
    top:50%;
    left:50%;
    transform: translate(-50%,-50%);
}
.nav{
    width:100%;
    height:50px;
    display: flex;
    justify-content:center;
    align-items: center;
    padding:0 10px;
    margin-top:1px;
}
.mask-box{
    width: 100%;
    height: 200px;
}
.group{
    padding:0px 20px;
}
.group .el-input {
    margin-top:28px;
    width:280px
}

.btn{
    width:150px;
    padding: 10px 10px;
    background: 0; 
    position: absolute;
    left: 32%;
    bottom:30px;
    background: deepskyblue;
    color:white;
    border-radius: 5px;
    border:0;
}

</style>
  • registry.vue
<template>
  <div class="wrap">
    <div class="mask-bg">
      <div class="mask">
        <div class="nav">
          <h3>网站博客注册</h3>
        </div>
        <div class="mask-box">
          <div class="group">
            <p>
                 <label>&nbsp;&nbsp;&nbsp;:</label>&nbsp;
                 <el-input placeholder="请输入用户" v-model="user"></el-input>
            </p>
           
            <p>
                 <label>真实姓名:</label>&nbsp;
                 <el-input placeholder="请输入密码" v-model="name"></el-input>
           </p>
           <p>
               <label>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:</label>&nbsp;
               <el-input placeholder="请输入密码" v-model="pwd"></el-input>
           </p>     
            <P>
               <label>确认密码:</label>&nbsp;
               <el-input placeholder="请输入密码" v-model="pwd1"></el-input>
            </P>
         </div>
        </div>
        <el-button type="primary" class="btn" @click="goLogin">注册</el-button>
      </div>
    </div>
  </div>
</template>
<script>
import request from "../utils/axiosreq";
export default {
  props: {},
  components: {},
  data() {
    return {
      user: "",
      pwd: "",
      name: "",
      pwd1: ""
    };
  },
  computed: {},
  methods: {
    goLogin() {
      request
        .post("/api/goRegistry", {
          user: this.user,
          pwd: this.pwd,
          name: this.name,
          pwd1: this.pwd1
        })
        .then(res => {
          if (res.code === 1) {
            this.$router.history.go(-1);
            alert(res.message);
          } else {
            alert(res.message);
          }
        });
    }
  },
  created() {},
  mounted() {}
};
</script>
<style scoped lang="">
.mask-bg {
  width: 100%;
  height: 100%;
  position: absolute;
  top: 0;
  left: 0;
  background: #f5f5f5;
}
.mask {
  width: 400px;
  height: 400px;
  background: white;
  border-radius: 5px;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}
.nav {
  width: 100%;
  height: 50px;
  display: flex;
  justify-content: center;
  align-items: center;
  padding: 0 10px;
}
.mask-box {
  width: 100%;
  height: 200px;
}
.group {
  width: 100%;
  height: 80px;
  padding:0px 20px;
}
 .group .el-input{
   width:270px;
   margin-top:28px;  
 }
.btn {
  width: 150px;
  padding: 10px 10px;
  background: 0;
  position: absolute;
  left: 32%;
  bottom: 10px;
  background: deepskyblue;
  color: white;
  border-radius: 5px;
  border: 0;

}
</style>
  • home.vue
<template>
    <div class="wrap">
        <Header></Header>
        <div class="main">
            <div class="main-fabu">
                <button @click="publishFn">发布</button>
            </div>
            <div class="box">
                <Item v-for="(item,index) in fenData"
                :key="index" :item="item" 
                ></Item>
            </div>
            <div class="main-fy">
              <el-pagination
                background
                layout="prev, pager, next"
                :total="list.length"
                @current-change="handChange"
                :page-size="size"
                >
                </el-pagination>
            </div>
        </div>
    </div>
</template>
<script>
import Header from '../components/header'
import Item from '../components/item'
import axios from "axios"
import {mapState,mapActions} from 'vuex'
export default {
    props:{
    },
    components:{
        Header,
        Item
    },
    data(){
        return {
          size:4,           
        }
    },
    computed:{
       ...mapState(['list',"fenData"])
    },
    methods:{
        ...mapActions(['getData']),
        publishFn(){
            this.$router.push('/publish')
        },
        handChange(page){
            this.$store.dispatch("getlistFn",{page,size:this.size})
        }
    },
       created(){
    },
    mounted(){
        this.$store.dispatch("getlistFn",{page:1,size:this.size})
        this.getData()       
    }
}
</script>
<style scoped lang="">
.main-fabu{ 
    width:1200px;
    height:40px;
    display: flex;
    justify-content: flex-end;
    align-items: center;
    padding:0 10px;
}
.box{
    width: 1200px;
}
.main-fabu button{
    padding:8px 40px;
    border-radius: 10px;
    background: 0;
    background: blue;
    color:white;
    border:0;
    cursor: pointer;
}
.main-fy{
    width: 1200px;
    height:50px;
    display: flex;
    justify-content: flex-end;
    align-items: center;
    padding:0 10px;
}
.list_ui{
    display: flex;
    width:300px;
    height:50px;
    display: flex;
    justify-content: space-between;
    padding:0px 10px;
    box-sizing: border-box;
    align-items: center;
  
}
.list_ul>li{
    border:1px solid deepskyblue;
}
.list_ul li.active{
    color:slateblue;
}

</style>
  • publish.vue
<template>
  <div class="wrap">
    <Header></Header>
    <div class="main">
      <div class="mask-box">
        <div class="group">         
           <div> 
             <h3>请输入你想要发布的标题:</h3>&nbsp;
             <el-input placeholder="请输入内容" v-model="title"></el-input>
           </div>
            
          <div> <h3>请输入你想要发布的标签:</h3>&nbsp;
               <el-input placeholder="请输入标签" v-model="tag"></el-input>
               
           </div>
            
         <div>
           <h3>请输入你想发布的内容</h3>
            <el-input type="textarea" :rows="4" placeholder="请输入内容" v-model="textarea"></el-input>
        </div>
        </div>
        <div class="group-box">
          <el-button type="primary" class="fabu" @click="publishFn">发布</el-button>
        </div>
      </div>
    </div>
  </div>
</template>
<script>
import Header from "../components/header";
import { mapState, mapActions } from "vuex";
export default {
  props: {},
  components: {
    Header,
     },
  data() {
    return {
      title: "",
      tag: "",
      textarea: ""
    };
  },
  computed: {
    ...mapState(["list"])
  },
  methods: {
    ...mapActions(["getAddDATA"]),
    publishFn() {
      let { title, tag, textarea } = this;
      this.getAddDATA({ title, tag, textarea })
      this.$router.push('/home')
    }
  },
  created() {},
  mounted() {
  }
};
</script>
<style scoped lang="">
.group div{
   line-height:3;
}
.group el-input{
   cursor: pointer;
}
.group h3{
  margin-left:10px;
  display: inline;
  color:slateblue;
  font-size:16px;
  font-family: "宋体";
}
.fabu{
  margin-top:20px;
  cursor: pointer;
}
</style>
  • components/item.vue
<template>
    <dl class="list_box" @click="goDetail(item.listId)">
        <dt @click="goDetail">
            <img src="https://ss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=3715405552,2612840062&fm=26&gp=0.jpg" alt="">
        </dt>
        <dd>
            <h3>{{item.title}}</h3>
            <p>{{item.context}}</p>
            <div class="item-box">
                <span class="img"></span>
                <span class="zuozhe">{{item.author}}</span>
                <span class="renqi">{{item.count}}</span>
                <span class="leibie">{{item.tagname}}</span>
                <span class="time">{{item.createTime}}</span>
            </div>
        </dd>
    </dl>
</template>
<script>
export default {
    props:['item'],
    components:{
    },
    data(){
        return {
        }
    },
    computed:{
    },
    methods:{
        goDetail(listId){
            this.$router.push({name:"detail",params:{listId:listId}})
            console.log(this.$route)
        }
    },
    created(){
    },
    mounted(){
    }
}
</script>
<style scoped lang="">
dl{
    width:1000px;
    height:auto;
    display: flex;
    margin-bottom:10px;
    margin-left:70px;
}
dl dt{
    width:220px;
    height:140px;
    margin-bottom:10px;
}
dl dt img{
    width:100%;
    height:100%;
    border-radius: 5px;
}
dl dd{
    flex:8;
    line-height: 2;
    margin-left:50px;    
}
dd>h3{
    margin-left:10px;
    margin-top:-2px;
}
.item-box .img{
    width:15px;
    height:15px;
    display: inline-block;
    line-height: 15px;
    border-radius: 50%;
    background: #333;
}
.item-box span{
    margin-right:10px;
}
.zuozhe{
    color:rgba(227, 60, 100, 1);
    font-size:14px;
}
.renqi{
    color: rgba(255, 141, 26, 1);
     font-size:14px;
}
.leibie{
    color: rgba(67, 207, 124, 1);
     font-size:14px;
}
.time{
    color: rgba(121, 72, 234, 1);
     font-size:14px;
}
</style>
  • detail.vue
<template>
    <div class="wrap">
        <Header></Header>
        <div class="main">
            <img src="https://ss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=3715405552,2612840062&fm=26&gp=0.jpg" alt="">
            <h3>{{item.title}}</h3>
            <p>{{item.context}}</p>
            <p class="title"><span class="one">作者:{{item.author}}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="two">时间:{{item.createTime}}</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;提示:{{item.tagname}}</span></p>

        </div>
    </div>
</template>
<script>
import Header from '../components/header'
import axios from "axios"
export default {
    props:{
    },
    components:{
        Header
    },
    data(){
        return {
           item:{}
        }
    },
    computed:{
    },
    methods:{
    },
    created(){
        let listId=this.$route.params.listId;
        axios.get(`/api/getDetail?listId=${listId}`).then(res=>{
            // console.log(res.data.resi,"1111")
            this.item=res.data.result;
        })
    },
    mounted(){
    }
}
</script>
<style scoped lang="">
.main{
    height:330px;
    width:800px;
    margin:20px auto;
    display: flex;
    justify-content: center;
    flex-direction: column;
    margin-top:50px;

}
.main img{
    height: 200px;
    width:80%;
    margin-left:10%;
   
}
.main>h3{
    height: 50px;
    width:8000px;
    line-height: 50px;
    margin-left:330px;
}

.main p{
    line-height: 3;
}
.main .title{
    margin-left:150px;
}
.title .one{
    color:red;
}
.two{
    color:dodgerblue;
}

</style>
  • components/header.vue
<template>
    <div class="header">
        <div class="header-left">
            <span></span>
        </div>
        <div class="header-cen">
            <h3>网站博客</h3>
        </div>
        <div class="header-right">
            <div class="header-lef">
                <img src="http://p2.ssl.cdn.btime.com/t015c5ac0243c3dace2.jpg?size=640x427" alt="">
            </div>
            <div class="header-rit">
                <button @click="outLogin">退出</button>
                <span class="sixe">修改密码</span>
            </div>
        </div>
    </div>
</template>
<script>
export default {
    props:{
    },
    components:{
    },
    data(){
        return {
        }
    },
    computed:{

    },
    methods:{
        outLogin(){
            this.$router.push('/login')
        }
    },
    created(){

    },
    mounted(){

    }
}
</script>
<style scoped lang="">
.header{
    width:100%;
    height:50px;
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding:0 10px;
    background-color: rgba(42, 130, 228, 1);
    color:white;
}
.header-right{
    height:50px;
    display: flex;

}
.header-lef{
    width:30px;
    height:30px;
    border-radius: 50%;
    line-height: 50px;
    margin-top:10px;
    margin-right:10px;
}
.header-lef img{
    width:100%;
    height:100%;
    border-radius: 50%;
}
.header-rit{
    display: flex;
    flex-direction: column;
}
.header-rit button{
    padding:4px 5px;
    border:0;
    border-radius: 5px;
    background: 0;
    background:red;
    color:white;
}
.sixe{
    font-size:14px;
    margin-top:2px;
}
</style>
最后奉上mysql数据数据格式
  • 数据库名以及表名
    在这里插入图片描述
  • user(登录注册)
    在这里插入图片描述
  • votelist总数据分页详情,添加
    在这里插入图片描述

你可能感兴趣的:(vue案例,egg)