菜单路由以及新项目开发

我们在原来的基础上又新加了一个页面,就是用户的个人信息页面person:
菜单路由以及新项目开发_第1张图片
源码为:

<template>
    <div>
        <el-card style="width: 40%; margin: 10px">
        <el-form ref="form" :model="form" label-width="80px">
            <el-form-item label="用户名">
                <el-input v-model="form.username" disabled></el-input>
            </el-form-item>
            <el-form-item label="密码">
                <el-input v-model="form.password" show-password></el-input>
            </el-form-item>
            <el-form-item label="昵称">
                <el-input v-model="form.nickName"></el-input>
            </el-form-item>
            <el-form-item label="年龄">
                <el-input v-model="form.age"></el-input>
            </el-form-item>
            <el-form-item label="性别">
                <el-input v-model="form.sex"></el-input>
            </el-form-item>
            <el-form-item label="地址">
                <el-input v-model="form.address"></el-input>
            </el-form-item>
        </el-form>
            <div>
                <el-button type="primary" @click="update">保存</el-button>
            </div>
        </el-card>
    </div>
</template>

<script>
    import request from "../utils/request";

    export default {
     
        name: "Person",
        data(){
     
          return {
     
              form:{
     },

          }
        },
        methods:{
     
            update(){
     
                request.put("/api/user",this.form).then(res => {
     
                    console.log(res)
                    if(this.code === '0'){
     
                        this.$messageBox({
     
                            type: "success",
                            message: "更新成功"
                        })
                        sessionStorage.setItem("user",JSON.stringify(this.form))
                    }else{
     
                        this.$message({
     
                            type:"error",
                            message: res.msg
                        })
                    }
                })
            }
        }
    }
</script>

<style scoped>

</style>

然后我们要去写我们的路由:
菜单路由以及新项目开发_第2张图片
菜单路由以及新项目开发_第3张图片
现在点击个人信息,就可以弹出信息页面了。然后我们现在发现我们的项目的路由每次都要在前面加个/api,感觉很繁琐,解决办法是我们在request.js的文件下,加上一句话,如下图:
菜单路由以及新项目开发_第4张图片
现在我们写的路由都不需要加/api了,baseURL会帮我们自动拼接上去,但是我们之前写的都是加了的,改的话很麻烦,但是Idea提供了一个全局修改的功能,就是在我们要选中修改的地方,按control+shift+r,就可以进行全局修改了。
菜单路由以及新项目开发_第5张图片
那么接下来我们去实现菜单的路由跳转,这怎么实现其实很简单,比如在我们的Aside侧边栏组件里面,我们有这样的一个设置:
菜单路由以及新项目开发_第6张图片
default-active和index是一一对应的,正是这种一一对应的关系所以在进来Home时“用户管理”会有高亮状态:
菜单路由以及新项目开发_第7张图片
所以这里我们默认用户界面是高亮的就行,但这里的Home.vue组件的设置其实是不太合理的,因为这只是一个用户管理,并不是我们的项目主页,所以我们可以把这个Home组件的名字给改一下,shift+f6更改为User.vue:
菜单路由以及新项目开发_第8张图片

然后去记得改一下路由:
菜单路由以及新项目开发_第9张图片

访问:
菜单路由以及新项目开发_第10张图片
那么我们现在怎么去实现点击菜单实现路由跳转呢?
很简单,有一个值叫router我们用就行了,如下图:
菜单路由以及新项目开发_第11张图片
当然因为目前我们只有一个页面,所以看不出什么效果,所以我们现在再写一个页面,叫Book.vue:
菜单路由以及新项目开发_第12张图片
然后配置路由,记得页面内路由切换应该在子路由当中实现:
菜单路由以及新项目开发_第13张图片

然后我们记得在侧边栏中加上新增的菜单,index所指的位置就是页面的路由:
菜单路由以及新项目开发_第14张图片
现在我们访问页面就可以发现,点击哪个菜单,页面就往哪里跳转:
菜单路由以及新项目开发_第15张图片

然后现在的问题是,我们每回登录都是直接就进来了用户管理的界面,连登录都不需要,因为没有登录的原因所以右上角也并不会有用户信息显示,哪怕我们的用户信息已经存在了sessionStorage。
除了Person.vue里面需要保存sessionStorage,Login.vue里面也需要对应的改变,新写的Login页面源代码如下:

<template>
    <!--将整个浏览器页面放在一个大div里
    width: 100%表示这个让div撑满全屏
    height: 100vh同上,一个撑满高度一个撑满宽度-->
    <div style="width: 100%; height: 100vh;background: darkslateblue; overflow: hidden">
        <!--margin: 参数1 参数2; 参数1表示上下距离,参数2表示左右距离,auto表示自动匹配
        如果页面产生了空白,就在外层最大的div上加一个overflow,设置为hidden即可-->
        <div style="width: 400px; margin: 150px auto">
            <!--font-size表示字体大小,text-align表示字体居中-->
            <div style="color: #cccccc; font-size: 30px; text-align: center; padding: 30px 0">
                欢迎登录
            </div>
            <!--然后去element上copy一个表单-->
            <el-form ref="form" :model="form" size="normal" :rules="rules">
                <el-form-item prop="username">
                    <el-input prefix-icon="el-icon-user-solid" v-model="form.username"></el-input>
                </el-form-item>
                <el-form-item prop="password">
                    <el-input prefix-icon="el-icon-lock" v-model="form.password" show-password></el-input>
                </el-form-item>
            </el-form>
            <el-form ref="form" :model="form" size="normal">
                <el-button style="width: 100%" type="primary" @click="login">登录</el-button>
            </el-form>
        </div>
    </div>
</template>

<script>
    import request from "../utils/request";

    export default {
     
        name: "Login",
        data(){
     
            return{
     
                form:{
     },
                rules:{
     
                    username:[
                        {
     required: true,message:"请输入用户名",trigger:'blur'},
                    ],
                    password:[
                        {
     required: true,message:"请输入密码",trigger:'blur'},
                    ]
                }
            }
        },
        created(){
     
            sessionStorage.removeItem("user")
        },
        methods: {
     
            login() {
     
                //发送请求之前先加这个判断,不为空且满足规则时才发送请求
                this.$refs['form'].validate((valid) => {
     
                    if (valid) {
     
                        request.post("/user/login",this.form).then(res => {
     
                            if(res.code === "0"){
     
                                this.$messageBox({
     
                                    type: "success",
                                    message: "登录成功"
                                })
                                //缓存用户信息
                                sessionStorage.setItem("user",JSON.stringify(res.data))
                                //    登录成功之后进行页面跳转,跳转到主页
                                this.$router.push("/")
                            }else{
     
                                this.$messageBox({
     
                                    type: "error",
                                    message: res.msg
                                })
                            }
                        })
                    }
                })
            }
        }
    }
</script>

<style scoped>

</style>

那么我们怎么去进行拦截使其只有登录了才能够访问我们的界面呢?其实也很简单,在我们的request.js里面其实已经定义好了拦截器,不管我们发送什么请求它都会进入到我们的拦截器里面:
菜单路由以及新项目开发_第16张图片
因为都会被拦截,所以我们现在在这里面进行一个判断,取出登录中提交的user数据:
菜单路由以及新项目开发_第17张图片

现在不管访问哪个页面都一定会经过登录页面了,但是我们页面的右上角的下拉框那里还没有解决,我们需要让他动态的与所登录的用户相绑定才行,这里就直接放源码了:

<template>
    <!--管理系统的第一部分,头部部分,用一个大的div来做导航栏,后台管理四个字在左边,下拉框放右边-->
    <div style="height: 50px; line-height: 50px; border-bottom: 1px solid #ccc; display: flex">

        <div style="width: 200px; padding-left: 30px; font-weight: bold; color: dodgerblue">后台管理</div>
        <div style="flex: 1"></div>
        <div style="width: 100px">

            <el-dropdown>
                <span class="el-dropdown-link">
                    {
     {
      user.nickName }}
                    <i class="el-icon-arrow-down el-icon--right"></i>
                </span>
                <template #dropdown>
                    <el-dropdown-menu>
                        <el-dropdown-item @click="$router.push('/person')">个人信息</el-dropdown-item>
                        <el-dropdown-item @click="$router.push('/login')">退出系统</el-dropdown-item>
                    </el-dropdown-menu>
                </template>
            </el-dropdown>

        </div>

    </div>
</template>

<script>
    export default {
     
        name: "Header",
        props:['user'],
        data(){
     
            return{
     
                user:{
     }
            }
        },
        created(){
     
            let userStr = sessionStorage.getItem("user") || "{}"
            this.user = JSON.parse(userStr)
        }
    }
</script>

<style scoped>

</style>

这样就连起来啦:
菜单路由以及新项目开发_第18张图片
现在我们来充实一下Book.vue里面的内容,我们可以直接把User.vue里面的东西复制过去,记得改变组件名以及路由位置还有表单的一些东西:

<template>
    <!--padding设置一点内边距-->
    <div style="padding: 10px">
        <!--功能区域-->
        <div style="margin: 10px 0">
            <el-button type="primary" @click="add">新增</el-button>
            <el-button type="primary">导入</el-button>
            <el-button type="primary">导出</el-button>
        </div>

        <!--搜索区域-->
        <div style="margin: 10px 0">
            <el-input v-model="search" placeholder="请输入关键字" style="width: 20%" clearable/>
            <el-button type="primary" style="margin-left: 5px" @click="load">搜索</el-button>
        </div>


        <!--后面的width可以不写,浏览器会自适应
        stripe是斑马纹效果-->
        <el-table :data="tableData" border stripe style="width: 100%">
            <!--sortable让日期排序-->
            <el-table-column prop="id" label="ID" sortable/>
            <el-table-column prop="name" label="书名"/>
            <el-table-column prop="price" label="单价" />
            <el-table-column prop="author" label="作者"/>
            <el-table-column prop="createTime" label="出版日期"/>

            <el-table-column fixed="right" label="操作">
                <template #default="scope">
                    <el-button size="mini" @click="handleEdit(scope.row)">编辑</el-button>

                    <!--弹出消息确认框-->
                    <el-popconfirm
                            confirm-button-text="是的,没错"
                            cancel-button-text="妈的,我再想想"
                            icon="el-icon-info"
                            icon-color="red"
                            title="确定删除吗?" @confirm="handleDelete(scope.row.id)">
                        <template #reference>
                            <el-button size="mini" type="danger">删除</el-button>
                        </template>
                    </el-popconfirm>
                </template>
            </el-table-column>
        </el-table>

        <!--分页功能区域-->
        <div style="margin: 10px 0">
            <el-pagination
                    v-model:currentPage="currentPage4"
                    :page-sizes="[5,10,20]"
                    :page-size="pageSize"
                    layout="total, sizes, prev, pager, next, jumper"
                    :total="total"
                    @size-change="handleSizeChange"
                    @current-change="handleCurrentChange">
            </el-pagination>
        </div>

        <!--弹窗输入用户信息-->
        <el-dialog v-model="dialogVisible" title="提示" width="30%">
            <!--定义表单在这个弹出框内以收集新增的用户信息-->
            <el-form :model="form" label="用户名">
                <el-form-item label="书名">
                    <el-input v-model="form.name" style="width: 80%"></el-input>
                </el-form-item>
                <el-form-item label="价格">
                    <el-input v-model="form.price" style="width: 80%"></el-input>
                </el-form-item>
                <el-form-item label="作者">
                    <el-input v-model="form.author" style="width: 80%"></el-input>
                </el-form-item>
                <el-form-item label="出版时间">
                    <el-data-picker v-model="form.createTime" value-format="YYYY-MM-DD" time="date" style="width: 80%" clearable></el-data-picker>
                </el-form-item>

            </el-form>
            <template #footer>
      <span class="dialog-footer">
        <el-button @click="dialogVisible = false">取 消</el-button>
        <el-button type="primary" @click="save">确 定</el-button>
      </span>
            </template>
        </el-dialog>
    </div>
</template>

<script>


    import request from "../utils/request";

    export default {
     
        name: 'Book',
        components: {
     

        },
        data() {
     
            return {
     
                form: {
     },
                dialogVisible: false,
                search: '',
                //当前页
                currentPage4: 1,
                pageSize: 10,
                total: 0,
                tableData: [

                ],
            }
        },
        //表示在页面被加载的时候,在这个方法里面的方法就全部调用
        created() {
     
            this.load()
        },
        methods: {
     
            //查询方法
            load(){
     
                request.get("/book",{
     
                    params: {
     
                        pageNum: this.currentPage4,
                        pageSize: this.pageSize,
                        search: this.search
                    }
                }).then(res => {
     
                    console.log(res)
                    this.tableData = res.data.records
                    this.total = res.data.total
                })
            },
            add(){
     
                this.dialogVisible = true;
                //清空表单域
                this.form = {
     };
            },
            save(){
     
                if(this.form.id){
       //更新操作
                    request.put("/book",this.form).then(res => {
     
                        console.log(res)
                        if(res.code == '0'){
     
                            //element给我们提供了一个可以供显示的结果的东西,如下
                            this.$messageBox({
     
                                type: "success",
                                message: "更新成功"
                            })
                        }else{
     
                            //element给我们提供了一个可以供显示的结果的东西,如下
                            this.$messageBox({
     
                                type: "error",
                                message: res.msg
                            })
                        }
                    })
                    this.load() //每一次更新后都自动刷新表格
                    this.dialogVisible = false //关闭弹窗
                }else{
      //新增操作
                    request.post("/book",this.form).then(res => {
     
                            console.log(res)
                            if (res.code == '0') {
     
                                //element给我们提供了一个可以供显示的结果的东西,如下
                                this.$messageBox({
     
                                    type: "success",
                                    message: "新增成功"
                                })
                            } else {
     
                                //element给我们提供了一个可以供显示的结果的东西,如下
                                this.$messageBox({
     
                                    type: "error",
                                    message: res.msg
                                })
                            }
                            this.load() //每次新增完都自动刷新表格
                            this.dialogVisible = false //关闭弹窗
                        }
                    )}
            },
            handleEdit(row){
     
                this.form = JSON.parse(JSON.stringify(row))
                this.dialogVisible = true
            },
            handleDelete(id){
     
                console.log(id)
                request.delete("/book/"+id).then(res =>{
     

                    if (res.code == '0') {
     
                        //element给我们提供了一个可以供显示的结果的东西,如下
                        this.$messageBox({
     
                            type: "success",
                            message: "删除成功"
                        })
                    } else {
     
                        //element给我们提供了一个可以供显示的结果的东西,如下
                        this.$messageBox({
     
                            type: "error",
                            message: res.msg
                        })
                    }
                    this.load() //删除之后重新加载表格的数据
                })
            },
            handleSizeChange(pageSize){
     
                //    改变当前每页的数据条数时触发
                this.pageSize = pageSize
                this.load()
            },
            handleCurrentChange(pageNum){
     
                //  改变当前页码时触发
                this.currentPage4 = pageNum
                this.load()
            }
        }
    }
</script>

然后我们去数据库中建book的表:
菜单路由以及新项目开发_第19张图片

然后我们去写我们book的实体类:
菜单路由以及新项目开发_第20张图片

再去写我们的BookMapper:
菜单路由以及新项目开发_第21张图片
再写controller层:

package com.why.demo.controller;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.why.demo.common.Result;
import com.why.demo.entity.Book;
import com.why.demo.entity.User;
import com.why.demo.mapper.BookMapper;
import com.why.demo.mapper.UserMapper;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;

@RestController //返回json格式字符串的注解
@RequestMapping("/book")
public class BookController {
     

    //理论上应该用三层架构,controller调用service,service调用dao的,这里图方便就直接在controller调了
    @Resource
    BookMapper bookMapper;


    //新增用户
    @PostMapping
    //@RequestBody就是把前台传过来的json数据转换成Java对象
    public Result save(@RequestBody Book book){
     
        bookMapper.insert(book);
        return Result.success();
    }

    //删除用户,根据id删除
    @DeleteMapping("/{id}")
    //@PathVariable就是把前台通过{id}占位符传过来的数据解析成Long类型的id值
    public Result delete(@PathVariable Long id){
     
        bookMapper.deleteById(id);
        return Result.success();
    }

    //更新用户,即访问/user即可
    @PutMapping
    //@RequestBody就是把前台传过来的json数据转换成Java对象
    public Result update(@RequestBody Book book){
     
        bookMapper.updateById(book);
        return Result.success();
    }

    //查询用户,用Get命令,且是分页查询
    /**
     * 分页查询,需要前台传过来三个参数,@RequestParm注解就是解析参数用的,如果不加后面的defaultValue设置
     * 默认的话,则请求时必须携带三个参数,不然就会报404错误
     * 第一个参数pageNum就是当前页的页码
     * 第二个参数pageSize就是每页多少条数据
     * 第三个参数search就是查询的关键字
     * @param pageNum
     * @param pageSize
     * @param search
     * @return
     */
    @GetMapping
    public Result<?> findPage(@RequestParam(defaultValue = "1") Integer pageNum,
                              @RequestParam(defaultValue = "10") Integer pageSize,
                              @RequestParam(defaultValue = "") String search){
     
        //下面这些操作都是Mp提供的,不懂的就需要自己去了解学习了
        //分页模糊查询,结果放在Result里面直接返回出去
        return Result.success(bookMapper.selectPage(new Page<>(pageNum, pageSize),Wrappers.<Book>lambdaQuery().like(Book::getName,search)));
    }

}

路由是我们之前就写好了的,这里可以直接访问测试了,登录进入主页,找到书籍管理,点击新增:
菜单路由以及新项目开发_第22张图片
可以看见新增成功:
菜单路由以及新项目开发_第23张图片
上面时间的显示好像有问题,日期的格式问题我们可以这样解决:
菜单路由以及新项目开发_第24张图片
就不会有时间格式问题了,或者也可以在yaml配置文件里面进行全局配置:
菜单路由以及新项目开发_第25张图片
然后解决一下默认的高亮问题:

<template>
    <div>
                <el-menu
                        style="width: 200px; min-height: calc(100vh - 50px)"
                        :default-active="path"
                        router
                        class="el-menu-vertical-demo">
                    <el-sub-menu index="1">
                        <template #title>系统管理</template>
                        <el-menu-item index="/user">用户管理</el-menu-item>
                    </el-sub-menu>


                    <el-menu-item index="/book">书籍管理</el-menu-item>

                </el-menu>

    </div>
</template>

<script>
    export default {
     
        name: "Aside",
        data(){
     
            return {
     
                path: this.$router.path //设置默认高亮的菜单
            }
        },
        created(){
     

        }
    }
</script>

<style scoped>

</style>

先到这,后续学习了再继续写。

你可能感兴趣的:(简易后台管理项目,javascript,vue.js)