基于springboot+vue的后台用户管理系统(二)

本文详细展示了使用HTML、CSS、JS以及Vue和ElementUI框架构建前端页面的过程,包括用户管理、权限角色管理和功能许可管理。每个模块都有相应的搜索、增删改查功能,并实现了分页。此外,还涵盖了登录和注册界面的设计,以及个人信息的查看和编辑。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、前端处理

1.概述

        在之前已经将系统后端逻辑业务代码编写了部分,在此,需要实现前端页面的展示,使用到html、css、js的技术,借助vue等进阶技术展示更优化的界面。

2.前端分析

        前端业务代码应当分为两部分,一部分为用户与界面的交互,另一部分为前台与后端的业务处理 。

3.运用技术

        采用vue、jquery和element等技术,需要调用各自的js文件库。创建目录路径如下,部分css、js文件需要网上下载导入。

二、前端实现

1.各功能的界面

(1)用户管理user.html

        需求分析

        顶部:分级关系;

        主体:搜索栏、数据列表、分页

        源码
<!DOCTYPE html>
<html lang="en">
<head>

    <meta charset="UTF-8">
    <meta HTTP-EQUIV="pragma" CONTENT="no-cache">
    <meta HTTP-EQUIV="Cache-Control" CONTENT="no-cache, must-revalidate">
    <meta HTTP-EQUIV="expires" CONTENT="0">
    <title>用户管理</title>

    <link rel="stylesheet" href="../../css/element.css">
    <link rel="stylesheet" href="../../css/base.css">

</head>
<body>

<!--整个界面-->
<div id="wrapper" v-cloak>

    <!--  顶部  -->
    <div style="padding-bottom: 10px">
        <!-- separator-class指定每两个item之前用图标相隔 -->
        <el-breadcrumb separator-class="el-icon-arrow-right">
            <!-- “首页”绑定点击事件,触发返回首页 -->
            <el-breadcrumb-item @click.native="parent.changeIndex('index')">首页</el-breadcrumb-item>
            <el-breadcrumb-item>用户管理</el-breadcrumb-item>
        </el-breadcrumb>
    </div>

    <!-- 分割线 -->
    <div style="height: 1px; margin: 10px 0; background-color: white"></div>

    <!-- 搜索框 -->
    <div style="margin: 10px 0">
        <!-- suffix-icon在输入框尾部插入,查询图标 -->
        <el-input v-model="search" style="width: 20%;" suffix-icon="el-icon-search"
                  placeholder="请输入关键字搜索"></el-input>
        <el-button @click="loadTable" type="primary" style="margin: 10px 0">查询</el-button>
        <el-button @click="add" type="primary" style="margin: 10px 0">新增</el-button>
    </div>

    <!-- 展示列表的表头,通过data注入数据,prop取数据并填充,label定义列名 -->
    <el-table :data="tableData" border style="width: 100%">
        <!-- sortable指定列具备排序功能,主键 -->
        <el-table-column prop="id" label="ID" width="70" sortable></el-table-column>

        <!-- 基础属性 -->
        <el-table-column prop="username" label="用户名"></el-table-column>
        <el-table-column prop="nickName" label="昵称"></el-table-column>
        <el-table-column prop="email" label="邮箱"></el-table-column>
        <el-table-column prop="phone" label="电话"></el-table-column>
        <el-table-column prop="age" label="年龄"></el-table-column>
        <el-table-column prop="address" label="地址"></el-table-column>

        <!-- 设置用户的权限角色,使得在此单元格内可以随意更改权限角色的权限 -->
        <el-table-column label="角色">
            <!-- 定义模板将权限角色读取,设置复选框供选择 -->
            <template slot-scope="scope">
                <el-select v-model="scope.row.role" value-key="id" multiple placeholder="请选择"
                           @change="changeRole(scope.row)">
                    <el-option v-for="item in options" :key="item.id"
                               :label="item.name" :value="item.id"></el-option>
                </el-select>
            </template>
        </el-table-column>

        <!-- 操作:对每条数据进行编辑及删除 -->
        <el-table-column fixed="right" label="操作" width="150">
            <!-- 定义模板进行操作 -->
            <template slot-scope="scope">

                <!-- 第一按钮,编辑 -->
                <el-button type="primary" @click="edit(scope.row)" icon="el-icon-edit" circle></el-button>

                <!-- 第二个按钮,删除,设置type为danger,设置二次删除确认 -->
                <el-popconfirm @onConfirm="del(scope.row.id)" title="确定删除?">
                    <el-button type="danger" icon="el-icon-delete" circle slot="reference"></el-button>
                </el-popconfirm>

            </template>
        </el-table-column>

    </el-table>

    <!-- 分页 -->
    <div style="background-color: white; padding: 10px 0">
        <!-- layout:组件布局,子组件名用逗号隔开;prev(上一页按钮)、page(页码)、nex(下一页按钮)、jumper(跳转)、->(空格)、total(总条目数)-->
        <!-- 当前页数current-page,每页展示条目数page-size,可选每页展示条目数page-sizes-->
        <el-pagination
                @size-change="handleSizeChange"
                @current-change="handleCurrentChange"
                :current-page="pageNum"
                :page-sizes="[5, 10, 20, 40]"
                :page-size="pageSize"
                layout="total, sizes, prev, pager, next, jumper"
                :total="total">
        </el-pagination>
    </div>

    <!-- 新增用户提示框,有关闭按钮 -->
    <!-- 父子组件双向绑定,实现子组件向父组件通信 -->
    <el-dialog title="用户信息" :visible.sync="dialogFormVisible" width="40%"
               :close-on-click-modal="false">

        <el-form :model="entity">

            <!-- 用户各项信息填写 -->
            <el-form-item label="用户名" label-width="100px">
                <el-input v-model="entity.username" autocomplete="off" style="width: 80%"></el-input>
            </el-form-item>
            <el-form-item label="昵称" label-width="100px">
                <el-input v-model="entity.nickName" autocomplete="off" style="width: 80%"></el-input>
            </el-form-item>
            <el-form-item label="邮箱" label-width="100px">
                <el-input v-model="entity.email" autocomplete="off" style="width: 80%"></el-input>
            </el-form-item>
            <el-form-item label="电话" label-width="100px">
                <el-input v-model="entity.phone" autocomplete="off" style="width: 80%"></el-input>
            </el-form-item>
            <el-form-item label="年龄" label-width="100px">
                <el-input v-model="entity.age" autocomplete="off" style="width: 80%"></el-input>
            </el-form-item>
            <el-form-item label="地址" label-width="100px">
                <el-input v-model="entity.address" autocomplete="off" style="width: 80%"></el-input>
            </el-form-item>

            <!-- 用户密码可不在此设置,后台判断未设定密码,将自动赋值为“123456” -->

        </el-form>

        <!-- 自定义按钮,1.取消;2.确定 -->
        <div slot="footer" class="dialog-footer">
            <el-button @click="dialogFormVisible=false">取 消</el-button>
            <el-button type="primary" @click="save">确 定</el-button>
        </div>
    </el-dialog>

</div>

<script src="../../js/jquery.min.js"></script>
<script src="../../js/vue.min.js"></script>
<script src="../../js/element.js"></script>
<script src="../../js/tinymce/tinymce.min.js"></script>

<script>

    // 设置路径
    let urlBase = "/api/user/";

    // vue接管
    new Vue({
        el: "#wrapper",
        // 部分数据初始化
        data: {
            user: {},
            tableData: [],
            pageNum: 1,
            pageSize: 10,
            total: 0,
            dialogFormVisible: false,
            entity: {},
            isCollapse: false,
            search: '',
            options: [],
            props: [
                {"label": "用户名", "prop": "username"},
                {"label": "邮箱", "prop": "email"},
                {"label": "电话", "prop": "phone"}
            ]
        },

        // 生命周期钩子函数
        created() {
            this.user = sessionStorage.getItem("user") ? JSON.parse(sessionStorage.getItem("user")) : {};
            this.loadTable();
        },

        // 函数定义
        methods: {

            // 用户的权限角色改变
            changeRole(row) {
                this.entity = JSON.parse(JSON.stringify(row));
                this.save();
            },

            // 请求退出接口
            logout() {
                $.get("/api/user/logout");
                localStorage.removeItem("user");
                location.href = "/page/end/login.html";
            },

            // 加载列表数据
            loadTable() {
                $.get(urlBase + "page?pageNum=" + this.pageNum + "&pageSize=" + this.pageSize + "&name=" + this.search).then(res => {
                    this.tableData = res.data.records;
                    this.total = res.data.total;
                })
                $.get("/api/role").then(res => {
                    this.options = res.data;
                })
            },

            // 改变每页展示条目数
            handleSizeChange(pageSize) {
                this.pageSize = pageSize;
                this.loadTable();
            },

            // 改变当前战术页
            handleCurrentChange(pageNum) {
                this.pageNum = pageNum;
                this.loadTable();
            },

            // 添加用户
            add() {
                this.entity = {};
                this.dialogFormVisible = true;
            },

            // 新增用户
            save() {

                // 需要用户名
                if (!this.entity.username) {
                    this.$message({
                        message: "请填写用户名",
                        type: "warning"
                    })
                    return
                }

                // ajax来处理保存
                let type = this.entity.id ? "PUT" : "POST";
                $.ajax({
                    url: urlBase,
                    type: type,
                    contentType: "application/json",
                    data: JSON.stringify(this.entity)
                }).then(res => {
                    if (res.code === '0') {
                        this.$message({
                            message: "保存成功",
                            type: "success"
                        });
                        this.loadTable();
                    } else {
                        this.$message({
                            message: res.msg,
                            type: "error"
                        })
                    }
                    // 保存后退出子组件
                    this.dialogFormVisible = false;
                })
            },

            // 编辑,进入子组件,展示用户信息,提供编辑
            edit(obj) {
                this.entity = JSON.parse(JSON.stringify(obj));
                this.dialogFormVisible = true;
            },

            // 删除用户
            del(id) {
                $.ajax({
                    url: urlBase + id,
                    type: "delete"
                }).then(res => {
                    if (res.code === '0') {
                        this.$message({
                            message: "删除成功",
                            type: "success"
                        })
                        this.loadTable();
                    } else {
                        this.$message({
                            message: res.msg,
                            type: "error"
                        })
                    }
                })
            }
        }
    })
</script>
</body>
</html>

(2)权限角色管理Role.html

        在前端需求上,用户管理、权限角色管理、功能许可管理,三者是相似的,因此直接前端代码也是近似。

        源码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta HTTP-EQUIV="pragma" CONTENT="no-cache">
    <meta HTTP-EQUIV="Cache-Control" CONTENT="no-cache, must-revalidate">
    <meta HTTP-EQUIV="expires" CONTENT="0">
    <title>权限角色管理</title>

    <link rel="stylesheet" href="../../css/element.css">
    <link rel="stylesheet" href="../../css/base.css">

</head>
<body>

<!-- 整体区域 -->
<div id="wrapper" v-cloak>

    <!-- 顶部 -->
    <div style="padding-bottom: 10px">
        <el-breadcrumb separator-class="el-icon-arrow-right">
            <el-breadcrumb-item @click.native="parent.changeIndex('index')">首页</el-breadcrumb-item>
            <el-breadcrumb-item>角色管理</el-breadcrumb-item>
        </el-breadcrumb>
    </div>

    <!-- 分割线 -->
    <div style="height: 1px; margin: 10px 0; background-color: white"></div>

    <!-- 搜索栏 -->
    <div style="margin: 10px 0">
        <el-input v-model="search" style="width: 20%;" suffix-icon="el-icon-search" placeholder="请输入名称搜索"></el-input>
        <el-button @click="loadTable" type="primary"  style="margin: 10px 0">查询</el-button>
        <el-button @click="add" type="primary"  style="margin: 10px 0">新增</el-button>
    </div>

    <!-- 数据列表 -->
    <el-table :data="tableData" border style="width: 100%">

        <!-- 基础属性 -->
        <el-table-column prop="id" label="ID" width="50"></el-table-column>
        <el-table-column prop="name" label="名称"></el-table-column>
        <el-table-column prop="description" label="描述"></el-table-column>

        <!-- 权限角色具备的许可的更改 -->
        <el-table-column label="权限" width="600">
            <template slot-scope="scope">
                <el-button type="text" @click="setPer(scope.row)">权限设置</el-button>
            </template>
        </el-table-column>

        <!-- 每行数据的操作,编辑、删除 -->
        <el-table-column fixed="right" label="操作" width="150">
            <template slot-scope="scope">
                <el-button type="primary" @click="edit(scope.row)"  icon="el-icon-edit" circle ></el-button>
                <el-popconfirm @onConfirm="del(scope.row.id)" title="确定删除?">
                    <el-button type="danger" icon="el-icon-delete" circle slot="reference" ></el-button>
                </el-popconfirm>
            </template>
        </el-table-column>
    </el-table>

    <!-- 分页 -->
    <div style="background-color: white">
        <el-pagination
                @size-change="handleSizeChange"
                @current-change="handleCurrentChange"
                :current-page="pageNum"
                :page-sizes="[5, 10, 20, 40]"
                :page-size="pageSize"
                layout="total, sizes, prev, pager, next, jumper"
                :total="total">
        </el-pagination>
    </div>

    <!-- 新增权限角色 -->
    <el-dialog title="角色信息" :visible.sync="dialogFormVisible" width="40%" :close-on-click-modal="false" >

        <el-form :model="entity">
            <el-form-item label="名称" label-width="120px">
                <el-input v-model="entity.name" autocomplete="off" style="width: 80%"></el-input>
            </el-form-item>
            <el-form-item label="描述" label-width="120px">
                <el-input v-model="entity.description" autocomplete="off" style="width: 80%"></el-input>
            </el-form-item>
        </el-form>

        <div slot="footer" class="dialog-footer">
            <el-button @click="dialogFormVisible = false">取 消</el-button>
            <el-button type="primary" @click="save">确 定</el-button>
        </div>

    </el-dialog>

    <!-- 编辑权限角色的功能许可 -->
    <el-dialog title="权限菜单" :visible.sync="vis" width="40%" :close-on-click-modal="false" >

        <el-form :model="entity" style="width: 80%; margin: 0 auto; line-height: 40px">
            <el-checkbox-group v-model="entity.permission" >
                <el-checkbox :label="item.id" v-for="item in options" :key="item.id">{{ item.name }}</el-checkbox>
            </el-checkbox-group>
        </el-form>

        <div slot="footer" class="dialog-footer">
            <el-button @click="vis = false">取 消</el-button>
            <el-button type="primary" @click="save">确 定</el-button>
        </div>

    </el-dialog>

</div>

<script src="../../js/jquery.min.js"></script>
<script src="../../js/vue.min.js"></script>
<script src="../../js/element.js"></script>
<script src="../../js/tinymce/tinymce.min.js"></script>

<script>

    let urlBase = "/api/role/";
    new Vue({
        el: "#wrapper",
        data: {
            user: {},
            tableData: [],
            pageNum: 1,
            pageSize: 10,
            total: 0,
            dialogFormVisible: false,
            entity: {},
            isCollapse: false,
            search: '',
            options: [],
            vis: false
        },

        created() {
            this.user = sessionStorage.getItem("user") ? JSON.parse(sessionStorage.getItem("user")) : {};
            this.loadTable();
        },

        methods: {

            // 设置权限
            setPer(obj) {
                this.entity = JSON.parse(JSON.stringify(obj))
                this.vis = true;
            },

            // 退出
            logout() {
                $.get("/api/user/logout");
                sessionStorage.removeItem("user");
                location.href = "/page/end/login.html";
            },

            // 加载数据
            loadTable() {

                $.get(urlBase + "page?pageNum=" + this.pageNum + "&pageSize=" + this.pageSize + "&name=" + this.search).then(res => {
                    this.tableData = res.data.records;
                    this.total = res.data.total;
                });

                $.get("/api/permission").then(res => {
                    this.options = res.data;
                })

            },

            // 页面大小更改
            handleSizeChange(pageSize) {
                this.pageSize = pageSize;
                this.loadTable();
            },

            // 当前页更改
            handleCurrentChange(pageNum) {
                this.pageNum = pageNum;
                this.loadTable();
            },

            // 添加权限用户
            add() {
                this.entity = {};
                this.dialogFormVisible = true;
            },

            // 保存
            save() {
                let type = this.entity.id ? "PUT" : "POST";
                $.ajax({
                    url: urlBase,
                    type: type,
                    contentType: "application/json",
                    data: JSON.stringify(this.entity)
                }).then(res => {
                    if (res.code === '0') {
                        this.$message({
                            message: "保存成功",
                            type: "success"
                        });
                        this.loadTable();
                    } else {
                        this.$message({
                            message: res.msg,
                            type: "error"
                        })
                    }

                    // 退出子组件
                    this.dialogFormVisible = false;
                    this.vis = false;

                    // 重新请求用户基础数据
                    $.get("/api/user/detail/" + this.user.username).then(res => {
                        this.user = res.data;
                        sessionStorage.setItem("user", JSON.stringify(this.user));
                        parent.call()
                    })

                })
            },

            // 编辑
            edit(obj) {
                this.entity = JSON.parse(JSON.stringify(obj));
                this.dialogFormVisible = true;
            },

            // 删除
            del(id) {
                $.ajax({
                    url: urlBase + id,
                    type: "delete"
                }).then(res => {
                    if (res.code === '0') {
                        this.$message({
                            message: "删除成功",
                            type: "success"
                        })
                        this.loadTable();
                    } else {
                        this.$message({
                            message: res.msg,
                            type: "error"
                        })
                    }
                })
            },
        }
    })
</script>
</body>
</html>

(3)权限许可管理Permission.html

        源码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta HTTP-EQUIV="pragma" CONTENT="no-cache">
    <meta HTTP-EQUIV="Cache-Control" CONTENT="no-cache, must-revalidate">
    <meta HTTP-EQUIV="expires" CONTENT="0">
    <title>权限许可管理</title>

    <link rel="stylesheet" href="../../css/element.css">
    <link rel="stylesheet" href="../../css/base.css">

</head>
<body>

<!-- 整体区域 -->
<div id="wrapper" v-cloak>

    <!-- 顶部 -->
    <div style="padding-bottom: 10px">
        <el-breadcrumb separator-class="el-icon-arrow-right">
            <el-breadcrumb-item @click.native="parent.changeIndex('index')">首页</el-breadcrumb-item>
            <el-breadcrumb-item>权限管理</el-breadcrumb-item>
        </el-breadcrumb>
    </div>

    <!-- 分割线 -->
    <div style="height: 1px; margin: 10px 0; background-color: white"></div>

    <!-- 数据列表 -->
    <el-input v-model="search" style="width: 20%;" suffix-icon="el-icon-search" placeholder="请输入名称按回车搜索" @keyup.enter.native="loadTable"></el-input>
    <el-button @click="add" type="primary"  style="margin: 10px 0">新增</el-button>

    <el-table :data="tableData" border style="width: 100%">

        <!-- 表头 -->
        <el-table-column prop="id" label="ID" width="50"></el-table-column>
        <el-table-column prop="name" label="名称"></el-table-column>
        <el-table-column prop="description" label="描述"></el-table-column>
        <el-table-column prop="path" label="菜单路径"></el-table-column>
        <el-table-column prop="icon" label="图标"></el-table-column>

        <!--操作,编辑、删除-->
        <el-table-column fixed="right" label="操作" width="150">
            <template slot-scope="scope">
                <el-button type="primary" @click="edit(scope.row)"  icon="el-icon-edit" circle ></el-button>
                <el-popconfirm @onConfirm="del(scope.row.id)" title="确定删除?">
                    <el-button type="danger" icon="el-icon-delete" circle slot="reference" ></el-button>
                </el-popconfirm>
            </template>
        </el-table-column>

    </el-table>

    <!-- 分页 -->
    <div style="background-color: white">
        <el-pagination
                @size-change="handleSizeChange"
                @current-change="handleCurrentChange"
                :current-page="pageNum"
                :page-sizes="[5, 10, 20, 40]"
                :page-size="pageSize"
                layout="total, sizes, prev, pager, next, jumper"
                :total="total">
        </el-pagination>
    </div>

    <!-- 添加 -->
    <el-dialog title="权限信息" :visible.sync="dialogFormVisible" width="40%" :close-on-click-modal="false" >

        <!-- 基础属性 -->
        <el-form :model="entity">
            <el-form-item label="名称" label-width="120px">
                <el-input v-model="entity.name" autocomplete="off" style="width: 80%"></el-input>
            </el-form-item>
            <el-form-item label="描述" label-width="120px">
                <el-input v-model="entity.description" autocomplete="off" style="width: 80%"></el-input>
            </el-form-item>
            <el-form-item label="菜单路径" label-width="120px">
                <el-input v-model="entity.path" autocomplete="off" style="width: 80%"></el-input>
            </el-form-item>
            <el-form-item label="图标" label-width="120px">
                <el-input v-model="entity.icon" autocomplete="off" style="width: 80%"></el-input>
            </el-form-item>
        </el-form>

        <!-- 与否按钮 -->
        <div slot="footer" class="dialog-footer">
            <el-button @click="dialogFormVisible = false">取 消</el-button>
            <el-button type="primary" @click="save">确 定</el-button>
        </div>

    </el-dialog>

</div>

<script src="../../js/jquery.min.js"></script>
<script src="../../js/vue.min.js"></script>
<script src="../../js/element.js"></script>
<script src="../../js/tinymce/tinymce.min.js"></script>

<script>

    let urlBase = "/api/permission/";
    new Vue({
        el: "#wrapper",
        data: {
            user: {},
            tableData: [],
            pageNum: 1,
            pageSize: 10,
            total: 0,
            dialogFormVisible: false,
            entity: {},
            isCollapse: false,
            search: '',
        },

        created() {
            this.user = sessionStorage.getItem("user") ? JSON.parse(sessionStorage.getItem("user")) : {};
            this.loadTable();
        },

        methods: {

            // 退出
            logout() {
                $.get("/api/user/logout");
                sessionStorage.removeItem("user");
                location.href = "/page/end/login.html";
            },

            // 加载数据
            loadTable() {
                $.get(urlBase + "page?pageNum=" + this.pageNum + "&pageSize=" + this.pageSize + "&name=" + this.search).then(res => {
                    this.tableData = res.data.records;
                    this.total = res.data.total;
                })
            },

            handleSizeChange(pageSize) {
                this.pageSize = pageSize;
                this.loadTable();
            },

            handleCurrentChange(pageNum) {
                this.pageNum = pageNum;
                this.loadTable();
            },

            add() {
                this.entity = {};
                this.dialogFormVisible = true;
            },

            save() {
                let type = this.entity.id ? "PUT" : "POST";
                $.ajax({
                    url: urlBase,
                    type: type,
                    contentType: "application/json",
                    data: JSON.stringify(this.entity)
                }).then(res => {
                    if (res.code === '0') {
                        this.$message({
                            message: "保存成功",
                            type: "success"
                        });
                        this.loadTable();
                    } else {
                        this.$message({
                            message: res.msg,
                            type: "error"
                        })
                    }
                    this.dialogFormVisible = false;

                    // 重新请求用户基础数据
                    $.get("/api/user/detail/" + this.user.username).then(res => {
                        this.user = res.data;
                        sessionStorage.setItem("user", JSON.stringify(this.user));
                        parent.call()
                    })
                })

            },

            edit(obj) {
                this.entity = JSON.parse(JSON.stringify(obj));
                this.dialogFormVisible = true;
            },

            del(id) {
                $.ajax({
                    url: urlBase + id,
                    type: "delete"
                }).then(res => {
                    if (res.code === '0') {
                        this.$message({
                            message: "删除成功",
                            type: "success"
                        });
                        // 重新请求用户基础数据
                        $.get("/api/user/detail/" + this.user.username).then(res => {
                            this.user = res.data;
                            console.log(this.user)
                            sessionStorage.setItem("user", JSON.stringify(this.user));
                        })
                    } else {
                        this.$message({
                            message: res.msg,
                            type: "error"
                        })
                    }
                    this.loadTable();
                    // 重新请求用户基础数据
                    $.get("/api/user/detail/" + this.user.username).then(res => {
                        this.user = res.data;
                        sessionStorage.setItem("user", JSON.stringify(this.user));
                        parent.call()
                    })
                })
            }
        }
    })
</script>
</body>
</html>

2.登录及注册界面

(1)登录界面login.html

        需求分析

        一个系统登录界面,简单点就是验证用户输入的信息与库中数据的对比,在用户量较少的情况下,登录输入框就可以简单地设置为——用户名、密码。同时应该提供给用户注册账号的功能。

        源码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta HTTP-EQUIV="pragma" CONTENT="no-cache">
    <meta HTTP-EQUIV="Cache-Control" CONTENT="no-cache, must-revalidate">
    <meta HTTP-EQUIV="expires" CONTENT="0">
    <title>登录</title>

    <link rel="stylesheet" href="../../css/base.css">
    <link rel="stylesheet" href="../../css/element.css">

</head>
<body style="background:url('../../images/bg.jpg') no-repeat; background-size: cover;">

<!-- 整体区域 -->
<div id="wrapper">

    <!-- 登录框区域 -->
    <div style="width: 400px; margin: 120px auto; background-color:rgba(100,149,237,0.5); border-radius: 10px">

        <!-- 头 -->
        <div style="width: 100%; height: 100px; font-size: 30px;line-height: 100px; text-align: center; color: #eee">欢迎登录</div>

        <!-- 输入框 -->
        <div style="margin-top: 25px; width: 100%; height: 320px;">
            <div style="width: 60%; margin: 0 auto">

                <!-- 用户名 -->
                <input v-model="user.username" type="text"
                       style="border: 1px solid #ccc; height: 40px;
                           padding: 10px; width: 100%" placeholder="请输入账号" @keyup.enter="login">

                <!-- 密码 -->
                <input v-model="user.password" type="password"
                       style="border: 1px solid #ccc; height: 40px; padding: 10px; width: 100%; margin-top: 25px"
                       placeholder="请输入密码" @keyup.enter="login">

                <!-- 登录按钮 -->
                <button @click="login" style="height: 40px; padding: 10px; width: 100%; margin-top: 25px;
                background-color: mediumseagreen; color: white">登录</button>

                <!-- 注册按钮 -->
                <a style="width: 100%; text-align: right; display: inline-block; margin-top: 25px;
                color: #eee" href="register.html">还没账号?去注册</a>
            </div>
        </div>

    </div>

</div>

<script src="../../js/jquery.min.js"></script>
<script src="../../js/vue.min.js"></script>
<script src="../../js/element.js"></script>
<script src="../../js/gVerify.js"></script>

<script>

    new Vue({
        el: "#wrapper",
        data: {
            user: {}
        },
        methods: {

            // 登录
            login() {

                // 名字不为空
                if (!this.user.username) {
                    this.$message({
                        message: "请输入用户名",
                        type: "error"
                    });
                    return;
                }

                // 密码不为空
                if (!this.user.password) {
                    this.$message({
                        message: "请输入密码",
                        type: "error"
                    });
                    return;
                }

                // ajax判断登录账号密码的正确
                $.ajax({
                    url: "/api/user/login",
                    type: "POST",
                    contentType: "application/json",
                    data: JSON.stringify(this.user)
                }).then(res => {
                    if (res.code === '0') {
                        this.$message({
                            message: "登录成功",
                            type: "success"
                        });
                        sessionStorage.setItem("user", JSON.stringify(res.data));
                        setTimeout(() => {
                            location.href = "/page/end/frame.html"
                        }, 1000)
                    } else {
                        this.$message({
                            message: res.msg,
                            type: "error"
                        })
                    }
                })
            }
        }
    })

</script>
</body>
</html>

(2)注册界面register.html

        需求分析

        注册界面面向用户就是让用户注册一个登录系统的账号,而对于系统来说就是创建一个新的user表的数据,因此,用户不仅需要输入想要的用户名、密码,还需要为系统提供应有的信息:邮箱email、电话phone。

        源码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta HTTP-EQUIV="pragma" CONTENT="no-cache">
    <meta HTTP-EQUIV="Cache-Control" CONTENT="no-cache, must-revalidate">
    <meta HTTP-EQUIV="expires" CONTENT="0">
    <title>注册</title>

    <link rel="stylesheet" href="../../css/base.css">
    <link rel="stylesheet" href="../../css/element.css">

</head>
<body style="background:url('../../images/bg.jpg') no-repeat; background-size: cover;">

<!-- 整体区域 -->
<div id="wrapper">
    <div style="width: 400px; margin: 120px auto;background-color:rgba(100,149,237,0.5); border-radius: 10px">

        <!-- 头部 -->
        <div style="width: 100%; height: 100px; color: #eee; font-size: 30px;line-height: 100px; text-align: center">
            欢迎注册
        </div>

        <div style="margin-top: 25px; width: 100%; height: 350px; text-align: center">

            <!-- 各信息输入框 -->
            <input v-model="user.username" type="text"
                   style="border: 1px solid #ccc; height: 40px; padding: 10px; width: 60%"
                   placeholder="请输入账号"
            >
            <input v-model="user.password" type="password"
                   style="border: 1px solid #ccc; height: 40px; padding: 10px; width: 60%; margin-top: 20px"
                   placeholder="请输入密码"
            >
            <input v-model="user.email" type="text"
                   style="border: 1px solid #ccc; height: 40px; padding: 10px; width: 60%;  margin-top: 20px"
                   placeholder="请输入邮箱"
            >
            <input v-model="user.phone" type="text"
                   style="border: 1px solid #ccc; height: 40px; padding: 10px; width: 60%;  margin-top: 20px"
                   placeholder="请输入电话"
                   @keyup.enter="register"
            >

            <!-- 注册按钮 -->
            <button @click="register"
                    style="height: 40px; padding: 10px; width: 60%; margin-top: 25px; background-color: steelblue; color: white"
            >注册
            </button>

            <!-- 跳转登录 -->
            <div style="margin-top: 25px">
                <a style="width: 60%; text-align: right; display: inline-block; color: #eee"
                   href="login.html">已有账号,去登录</a>
            </div>

        </div>

    </div>
</div>

<script src="../../js/jquery.min.js"></script>
<script src="../../js/vue.min.js"></script>
<script src="../../js/element.js"></script>

<script>

    new Vue({
        el: "#wrapper",
        data: {
            user: {}
        },
        methods: {

            // 注册
            register() {

                // 用户名和密码不能为空
                if (!this.user.username) {
                    this.$message({
                        message: "请输入用户名",
                        type: "error"
                    });
                    return;
                }
                if (!this.user.password) {
                    this.$message({
                        message: "请输入密码",
                        type: "error"
                    });
                    return;
                }
                $.ajax({
                    url: "/api/user/register",
                    type: "POST",
                    contentType: "application/json",
                    data: JSON.stringify(this.user)
                }).then(res => {
                    if (res.code === '0') {
                        this.$message({
                            message: "注册成功",
                            type: "success"
                        });
                        sessionStorage.setItem("user", JSON.stringify(res.data));
                        setTimeout(() => {
                            location.href = "/page/end/login.html"
                        }, 1000)
                    } else {
                        this.$message({
                            message: res.msg,
                            type: "error"
                        })
                    }
                })
            }
        }
    })
</script>
</body>
</html>

3.系统主界面及首页

(1)需求分析

        对于一个系统,应当将整个界面进行划分以便安排展示界面;在系统顶部,在左侧提供一个图标标识系统,同时能够方便用户快速返回首页,而在右侧,则是展示用户的个人部分信息,同时提供用户去往个人信息或是退出的功能。

(2)整体界面frame.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta HTTP-EQUIV="pragma" CONTENT="no-cache">
    <meta HTTP-EQUIV="Cache-Control" CONTENT="no-cache, must-revalidate">
    <meta HTTP-EQUIV="expires" CONTENT="0">
    <title>后台管理</title>

    <link rel="stylesheet" href="../../css/element.css">
    <link rel="stylesheet" href="../../css/base.css">

</head>
<body>

<!-- 整体区域 -->
<div id="wrapper" v-cloak>

    <el-container>

        <el-aside :width="isCollapse ? '64px' : '200px'"
                  style="background-color: black; transition:width .5s; min-height: 100vh">

            <!-- 左上角标志,绑定点击事件为回到首页 -->
            <div style="background-color: black; height: 60px; line-height: 60px; text-align: center;color: white; font-size: 20px;">
                <transition name="el-fade-in-linear">
                    <span id="fade" v-show="!isCollapse"><a href="/page/end/frame.html">Megumi</a></span>
                </transition>
            </div>

            <!-- 侧边栏菜单 -->
            <el-menu style="border: none;" background-color="black" text-color="#fff" active-text-color="#ffd04b"
                     :default-active="src" @select="handleSelect" :collapse="isCollapse">

                <!-- 首页 -->
                <el-menu-item index="index">
                    <i class="el-icon-data-line"></i>
                    <span slot="title">首页</span>
                </el-menu-item>

                <!-- 根据用户的权限角色所持有的功能许可在侧边展示功能 -->
                <el-menu-item :index="item.path" v-for="item in user.permission">

                    <!-- 图标 -->
                    <i :class=`el-icon-${item.icon}`></i>

                    <!-- 名称 -->
                    <span slot="title">{{item.name}}</span>
                </el-menu-item>

            </el-menu>

        </el-aside>

        <el-container>

            <el-header style="background-color: black; line-height: 60px; color: white;">

                <el-row>

                    <!-- 侧边栏缩放,图标按钮 -->
                    <el-col :span="1">
                        <i style="font-size: 22px; cursor: pointer" :class="[isCollapse ? 'el-icon-s-unfold' : 'el-icon-s-fold']" @click="handleCollapse"></i>
                    </el-col>

                    <!-- 右上角当前登录系统的用户的个人信息 -->
                    <el-col :span="23" style="text-align: right">
                        <el-dropdown placement="bottom-end" @command="handleDropdownCommand">

                            <!-- 用户昵称及头像 -->
                            <div style="cursor:pointer;display:flex;flex-direction: row;margin-right: 20px;align-items: center;">

                                <span style="color: white; margin-right: 8px;font-size: 1.05rem;">{{user.nickName}}</span>
                                <img :src=`/files/${user.avatar}` style="width: 40px; height: 40px; border-radius: 50%">

                            </div>

                            <!-- 在鼠标聚焦用户昵称及头像时,出现下列选项,选择个人具体信息或用户退出系统 -->
                            <el-dropdown-menu slot="dropdown">

                                <el-dropdown-item @click="handleSelect('person')" command="person">个人信息</el-dropdown-item>
                                <el-dropdown-item @click="logout" command="logout">退出</el-dropdown-item>

                            </el-dropdown-menu>

                        </el-dropdown>
                    </el-col>

                </el-row>

            </el-header>

            <!-- 主体区域 -->
            <el-main>
                <iframe id="myIframe" :src="src + '.html?new=' + Math.random()" frameborder="0" scrolling="no" style="width: 100%"></iframe>
            </el-main>

        </el-container>

    </el-container>

</div>

<script src="../../js/jquery.min.js"></script>
<script src="../../js/vue.min.js"></script>
<script src="../../js/element.js"></script>

<script>

    // 请求用户信息
    function call() {
        vm.user = JSON.parse(sessionStorage.getItem("user"))
    }

    // 回到首页
    function changeIndex(index) {
        vm.src = index
        location.search = "target=" + index
        window.setInterval("reinitIframe()", 50);
    }

    // 实现 iframe  高度自适应
    function reinitIframe() {
        const iframe = document.getElementById("myIframe");
        try {
            const bHeight = iframe.contentWindow.document.body.scrollHeight;
            const dHeight = iframe.contentWindow.document.documentElement.scrollHeight;
            iframe.height = Math.max(bHeight, dHeight, (window.innerHeight - 105));
        } catch (ex) {
        }
    }

    window.setInterval("reinitIframe()", 50);

    let vm = new Vue({
        el: "#wrapper",
        data: {
            src: 'index',
            active: 0,
            user: {},
            isCollapse: false,
        },

        created() {
            this.user = sessionStorage.getItem("user") ? JSON.parse(sessionStorage.getItem("user")) : {};
            if (location.search) {
                this.src = getUrlParamValue('target')
            }
        },

        methods: {

            handleSelect(key) {
                this.src = key
                location.search = "target=" + this.src
                window.setInterval("reinitIframe()", 50);
            },

            handleDropdownCommand(command) {
                if (command === "person") {
                    this.handleSelect('person')
                }
                if (command === "logout") {
                    this.logout()
                }
            },

            handleCollapse() {
                this.isCollapse = !this.isCollapse;
            },

            logout() {
                $.get("/api/user/logout");
                sessionStorage.removeItem("user");
                location.href = "/page/end/login.html";
            }
        }
    })

    /**
     * 获取url参数
     * @param name
     * @returns {string|null}
     */
    function getUrlParamValue(name) {
        if (name == null || name === 'undefined') {
            return '';
        }
        let searchStr = decodeURI(location.search);
        let infoIndex = searchStr.indexOf(name + "=");
        if (infoIndex === -1) {
            return null;
        }
        let searchInfo = searchStr.substring(infoIndex + name.length + 1);
        let tagIndex = searchInfo.indexOf("&");
        if (tagIndex !== -1) {
            searchInfo = searchInfo.substring(0, tagIndex);
        }
        return searchInfo;
    }

</script>
</body>
</html>

(3)首页index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta HTTP-EQUIV="pragma" CONTENT="no-cache">
    <meta HTTP-EQUIV="Cache-Control" CONTENT="no-cache, must-revalidate">
    <meta HTTP-EQUIV="expires" CONTENT="0">
    <title>首页</title>

    <link rel="stylesheet" href="../../css/element.css">
    <link rel="stylesheet" href="../../css/base.css">

</head>
<body>

<!-- 整体区域 -->
<div id="wrapper" v-cloak>

    <!-- 左上角,系统公告 -->
    <el-row :gutter="10">
        <el-col :span="12">
            <el-card>

                <!-- 标题 -->
                <div slot="header" class="clearfix">
                    <h3>系统公告</h3>
                </div>

                <!--  -->
                <el-collapse accordion v-model="active">
                    <el-collapse-item :name="index" v-for="(item ,index) in notices">

                        <!-- 公告标题、发布时间、公告内容 -->
                        <template slot="title">
                            <b>{{ item.title }}</b>
                            <span style="margin-left: 50px; color: #888">{{ item.time }}</span>
                        </template>
                        <div style="padding: 0 20px">{{ item.content }}</div>

                    </el-collapse-item>
                </el-collapse>

            </el-card>
        </el-col>

        <!-- 设计饼状图统计用户地区比例 -->
        <el-col :span="12">
            <el-card>
                <!-- 为ECharts准备一个具备大小(宽高)的Dom -->
                <div id="main" style="width: 100%;height:400px; margin: 0 auto"></div>
            </el-card>
        </el-col>

    </el-row>

</div>

<script src="../../js/echarts.min.js"></script>
<script src="../../js/china.js"></script>
<script src="../../js/jquery.min.js"></script>
<script src="../../js/vue.min.js"></script>
<script src="../../js/element.js"></script>

<script>

    // 设计饼状图的属性
    const pieOption = {
        title: {text: '用户地区比例统计'},
        tooltip: {trigger: 'item'},
        legend: {top: '0', left: 'right'},
        series: [
            {
                name: '访问来源',
                type: 'pie',
                radius: ['40%', '70%'],
                itemStyle: {
                    borderRadius: 10,
                    borderColor: '#fff',
                    borderWidth: 2
                },
                data: []
            }
        ]
    };

    new Vue({
        el: "#wrapper",
        data: {
            active: 0,
            users: [],
            roles: [],
            permissions: [],
            notices: [],
            user: {},
            tableData: [],
            pageNum: 1,
            pageSize: 10,
            total: 0,
            dialogFormVisible: false,
            entity: {},
            isCollapse: false
        },

        // 当前用户获取及加载
        mounted() {
            this.user = sessionStorage.getItem("user") ? JSON.parse(sessionStorage.getItem("user")) : {};
            this.load();
        },

        methods: {

            load() {

                // 加载系统公告
                $.get("/api/notice/").then((res) => {
                    this.notices = res.data;
                })

                // 基于准备好的dom,初始化echarts实例
                let myChart = echarts.init(document.getElementById('main'));
                $.ajax({
                    url: "/api/user",
                    success(res) {
                        let address = Array.from(new Set(res.data.map(v => v.address)))
                        address.forEach(item => {
                            let count = res.data.filter(v => v.address === item).length
                            pieOption.series[0].data.push({name: item, value: count})
                        })
                        // 使用刚指定的配置项和数据显示图表。
                        myChart.setOption(pieOption);
                    }
                })

            },

            handleCollapse() {
                this.isCollapse = !this.isCollapse;
            },

            // 退出
            logout() {
                $.get("/api/user/logout");
                sessionStorage.removeItem("user");
                location.href = "/page/end/login.html";
            }
        }
    })
</script>
</body>
</html>

3.其余界面

(1)个人信息person.html

        需求分析

        在首页顶部右侧提供了用户查看并编辑个人信息的功能。

        源码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta HTTP-EQUIV="pragma" CONTENT="no-cache">
    <meta HTTP-EQUIV="Cache-Control" CONTENT="no-cache, must-revalidate">
    <meta HTTP-EQUIV="expires" CONTENT="0">
    <title>个人信息</title>

    <link rel="stylesheet" href="../../css/element.css">
    <link rel="stylesheet" href="../../css/base.css">

    <!-- 设置部分标签样式 -->
    <style>

        .avatar-uploader {
            border: 1px dashed #d9d9d9;
            border-radius: 6px;
            cursor: pointer;
            position: relative;
            overflow: hidden;
        }

        .avatar-uploader-icon {
            font-size: 28px;
            color: #8c939d;
            width: 100px;
            height: 100px;
            line-height: 100px;
            text-align: center;
        }

        .avatar {
            width: 100px;
            height: 100px;
            display: block;
        }

    </style>

</head>

<body style="background-color: #ddd">

<!-- 整体区域 -->
<div id="wrapper" v-cloak>

    <el-card style="width: 40%;">

        <!-- 顶部 -->
        <div slot="header" class="clearfix" style="display: flex">

            <!-- 标题 -->
            <div style="font-size: 24px; flex: 1">个人信息</div>
            <div style="flex: 1; text-align: right">
                <el-button size="small" type="primary" @click="edit">编辑</el-button>
            </div>

        </div>

        <div>

            <!-- 用户头像及头像上传 -->
            <div style="padding: 10px 0; text-align: center">
                <el-upload
                        class="avatar-uploader"
                        action="/files/upload"
                        :show-file-list="false"
                        :on-success="handleAvatarSuccess">
                    <img v-if="user.avatar" :src="['/files/' + user.avatar]" class="avatar">
                    <i v-else class="el-icon-plus avatar-uploader-icon"></i>
                </el-upload>
            </div>

            <!-- 用户个人信息打印 -->
            <div style="width: 300px; margin: 0 auto">
                <el-form>
                    <el-form-item label="用户名:" label-width="120px" style="margin: 0">
                        <div>{{ user.username }}</div>
                    </el-form-item>
                    <el-form-item label="昵称:" label-width="120px" style="margin: 0">
                        <div>{{ user.nickName }}</div>
                    </el-form-item>
                    <el-form-item label="邮箱:" label-width="120px" style="margin: 0">
                        <div>{{ user.email }}</div>
                    </el-form-item>
                    <el-form-item label="电话:" label-width="120px" style="margin: 0">
                        <div>{{ user.phone }}</div>
                    </el-form-item>
                    <el-form-item label="年龄:" label-width="120px" style="margin: 0">
                        <div>{{ user.age }}</div>
                    </el-form-item>
                    <el-form-item label="地址:" label-width="120px" style="margin: 0">
                        <div>{{ user.address }}</div>
                    </el-form-item>
                </el-form>
            </div>

        </div>

    </el-card>

    <!-- 编辑子组件 -->
    <el-dialog title="用户信息" :visible.sync="dialogFormVisible" width="40%" close-on-click-modal="false" close-on-press-escape="false" show-close="false">

        <!-- 用户各信息展示并提供修改 -->
        <el-form :model="user">
            <el-form-item label="用户名" label-width="100px">
                <el-input v-model="entity.username" autocomplete="off" style="width: 80%"></el-input>
            </el-form-item>
            <el-form-item label="昵称" label-width="100px">
                <el-input v-model="entity.nickName" autocomplete="off" style="width: 80%"></el-input>
            </el-form-item>
            <el-form-item label="邮箱" label-width="100px">
                <el-input v-model="entity.email" autocomplete="off" style="width: 80%"></el-input>
            </el-form-item>
            <el-form-item label="电话" label-width="100px">
                <el-input v-model="entity.phone" autocomplete="off" style="width: 80%"></el-input>
            </el-form-item>
            <el-form-item label="年龄" label-width="100px">
                <el-input v-model="entity.age" autocomplete="off" style="width: 80%"></el-input>
            </el-form-item>
            <el-form-item label="地址" label-width="100px">
                <el-input v-model="entity.address" autocomplete="off" style="width: 80%"></el-input>
            </el-form-item>
            <el-form-item label="密码" label-width="100px">
                <el-input show-password v-model="user.password" autocomplete="off" style="width: 80%"></el-input>
            </el-form-item>
        </el-form>

        <!-- 与否按钮 -->
        <div slot="footer" class="dialog-footer">
            <el-button @click="dialogFormVisible = false">取 消</el-button>
            <el-button type="primary" @click="save">确 定</el-button>
        </div>

    </el-dialog>

</div>

<script src="../../js/jquery.min.js"></script>
<script src="../../js/vue.min.js"></script>
<script src="../../js/element.js"></script>

<script>

    new Vue({
        el: "#wrapper",
        data: {
            user: {},
            isCollapse: false,
            entity: {},
            dialogFormVisible: false
        },

        // 获取当前用户及加载
        created() {
            this.user = sessionStorage.getItem("user") ? JSON.parse(sessionStorage.getItem("user")) : {};
            this.load();
        },

        methods: {

            // 退出
            logout() {
                $.get("/api/user/logout");
                sessionStorage.removeItem("user");
                location.href = "/page/end/login.html";
            },

            handleCollapse() {
                this.isCollapse = !this.isCollapse;
            },

            // 编辑
            edit() {
                this.entity = JSON.parse(JSON.stringify(this.user))
                this.dialogFormVisible = true;
            },

            // 根据用户名加载用户数据
            load() {
                $.get("/api/user/detail/" + this.user.username).then(res => {
                    this.user = res.data;
                })
            },

            // 保存用户信息
            save() {
                $.ajax({
                    url: "/api/user",
                    type: "PUT",
                    contentType: "application/json",
                    data: JSON.stringify(this.entity)
                }).then(res => {
                    if (res.code === '0') {
                        this.$message({
                            message: "保存成功",
                            type: "success"
                        });
                        this.load();
                    } else {
                        this.$message({
                            message: res.msg,
                            type: "error"
                        })
                    }
                    // 退出子组件
                    this.dialogFormVisible = false;
                })
            },
        }
    })
</script>
</body>
</html>

(2)权限设置authority.html

        需求分析

        在前面的需求分析中,了解到,用户访问系统功能需要具备功能许可,因此在前端界面展示也因有根据权限展示的功能

        源码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta HTTP-EQUIV="pragma" CONTENT="no-cache">
    <meta HTTP-EQUIV="Cache-Control" CONTENT="no-cache, must-revalidate">
    <meta HTTP-EQUIV="expires" CONTENT="0">
    <title>权限限制</title>

    <link rel="stylesheet" href="../../css/element.css">
    <link rel="stylesheet" href="../../css/base.css">

</head>
<body>

<!-- 整体区域 -->
<div id="wrapper" v-cloak>
    <el-container>

        <el-aside :width="isCollapse ? '64px' : '200px'" style="background-color: black; transition:width .5s; min-height: 100vh">

            <!-- 左上角系统标识,绑定事件回到首页 -->
            <div style="background-color: black; height: 60px; line-height: 60px; text-align: center;color: white; font-size: 20px;">
                <transition name="el-fade-in-linear">
                    <span id="fade" v-show="!isCollapse"><a href="/page/end/frame.html">Megumi</a></span>
                </transition>
            </div>

            <!-- 侧边栏菜单 -->
            <el-menu :default-openeds="['1']" style="border: none;" background-color="black" text-color="#fff"
                     active-text-color="#ffd04b"
                     default-active="home"
                     class="el-menu-vertical-demo" :collapse="isCollapse">

                <!-- 首页 -->
                <a href="/page/end/frame.html">
                    <el-menu-item index="home">
                        <i class="el-icon-data-line"></i>
                        <span slot="title">首页</span>
                    </el-menu-item>
                </a>

                <!-- 其余有许可功能 -->
                <a :href=`${item.path}` v-for="item in user.permission" :key="item.id">
                    <el-menu-item :index="item.flag">
                        <i class="el-icon-s-data"></i>
                        <span slot="title">{{item.name}}</span>
                    </el-menu-item>
                </a>

            </el-menu>
        </el-aside>

        <el-container>

            <el-header style="background-color: black; line-height: 60px; color: white;">
                <el-row>

                    <!-- 侧边栏缩放 -->
                    <el-col :span="1">
                        <i style="font-size: 22px; cursor: pointer"
                           :class="[isCollapse ? 'el-icon-s-unfold' : 'el-icon-s-fold']" @click="handleCollapse"></i>
                    </el-col>

                    <el-col :span="2" :offset="21" style="text-align: right">

                        <!-- 用户昵称、头像,绑定事件鼠标聚焦展示下拉选项,提供个人信息、退出功能 -->
                        <span style="color: white; margin-right: 10px">{{user.username}}</span>
                        <el-dropdown>
                            <img :src=`/files/${user.avatar}`
                                 style="width: 40px; height: 40px; margin-right: 10px; border-radius: 50%">
                            <el-dropdown-menu slot="dropdown">
                                <a href="/page/end/person.html"
                                   style="display:inline-block; padding: 5px 0; width: 100px; text-align: center; color: black">个人信息</a>
                                <a @click="logout" href="#"
                                   style="display:block; width: 100px;  text-align: center; color: black">退出</a>
                            </el-dropdown-menu>
                        </el-dropdown>

                    </el-col>
                </el-row>
            </el-header>

            <!-- 主体区域 -->
            <el-main>
                <div style="padding: 10px; font-size: 30px; color: red">
                    good!
                </div>
            </el-main>

        </el-container>

    </el-container>
</div>

<script src="../../js/echarts.min.js"></script>
<script src="../../js/china.js"></script>
<script src="../../js/jquery.min.js"></script>
<script src="../../js/vue.min.js"></script>
<script src="../../js/element.js"></script>

<script>

    new Vue({
        el: "#wrapper",
        data: {
            user: {},
            isCollapse: false
        },

        // 获取当前用户及加载
        created() {
            this.user = sessionStorage.getItem("user") ? JSON.parse(sessionStorage.getItem("user")) : {};
        },

        methods: {

            handleCollapse() {
                this.isCollapse = !this.isCollapse;
            },

            // 退出
            logout() {
                $.get("/api/user/logout");
                sessionStorage.removeItem("user");
                location.href = "/page/end/login.html";
            }
        }
    });

</script>
</body>
</html>

(3)base.css

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}
ul,li{
    list-style: none;
}
a {
    text-decoration: none;
    color: cornflowerblue;
}
body {
    font-size:14px;
    color:#333;
    background-color: #eeeeee;
}
img {
    border: none;
    vertical-align: middle;
}
input, textarea {
    outline: none;
    border: none;
}

textarea {
    resize: none;
    overflow: auto;
}
button {
    border: none;
    outline: none;
    cursor: pointer;
}
.frame-body {
    background-color: Ivory;
}
.tip {
    position: relative;
    margin: 10px auto;
    height: 50px;
    line-height: 50px;
    color: white;
    text-align: center;
    border-radius: 10px;
    font-family: sans-serif;
}
.tip:after {
    content: '';
    position: absolute;
    width: 0;
    height: 0;
    border: 8px solid;
}
.right {
    background-color: deepskyblue;
}
.left {
    background-color: forestgreen;
}
.left:after {
    border-right-color: forestgreen;
    top: 50%;
    right: 100%;
    margin-top: -9px;
}
.right:after {
    border-left-color: deepskyblue;
    left: 100%;
    top: 50%;
    margin-top: -7px;
}
/*elementUI样式调整*/
[v-cloak] {
    display: none;
}
.el-header {
    padding-left: 0;
}
.el-aside {
    min-height: 100vh;
}
.el-aside,.el-menu {
    overflow-x: hidden;
}
.horizontal-collapse-transition {
    transition: 0s;
}
.el-menu a {
    color: white;
}
.el-menu .is-active a {
    color: #ffd04b;
}
.el-breadcrumb__inner {
    cursor: pointer;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值