登录综合案例02,退出完善,菜单权限,以及遇到的一些问题,前端使用vue+elementui+axios 后端 springboot+mybatis-plus+swagger2,

登录综合案例02,退出完善,菜单权限,前端使用vue+elementui+axios 后端 springboot+mybatis-plus+swagger2,


登录综合案例01中使用的是shiroConfig类放行退出的路径,这样写是不太合适的,

在这里插入图片描述

解决方案:定义登录过滤器类

import com.alibaba.fastjson.JSON;

//如果未登录 直接访问某个地址时
public class AuthcFilter extends FormAuthenticationFilter {

    @Resource
    private RedisTemplate redisTemplate;

    @Override
    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
//        跨域都会执行两次请求
//        对options请求放行,其他请求方式都拦截
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse resp = (HttpServletResponse) response;
//        获得请求的方法
        String method = req.getMethod();
//判断请求的方法是否为options,如果是就放行
        if (RequestMethod.OPTIONS.name().equals(method)) {
            return true;
        }
        return false;
    }

    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse resp = (HttpServletResponse) response;
//        是否携带请求头token
        String token = req.getHeader("token");
        if (StringUtils.isBlank(token)) {
            resp.setCharacterEncoding("utf-8");
            CommonResult result = new CommonResult();
            result.setCode(5000);
            result.setMsg("请先登录");
            String json = JSON.toJSONString(result);
            resp.getWriter().print(json);
            return false;
        }
        return true;

    }

    @Test
    public void ss(){
        System.out.println(redisTemplate.opsForValue().get("51712edcfc9b46b6a237ee19422fa82c"));
    }
}

ShiroConfig 配置类中需要使用该过滤器

// 放行过滤器
HashMap<String, Filter> filter = new HashMap<>();
filter.put(“authc”,new AuthcFilter());
shiroFilterFactoryBean.setFilters(filter);

以下是完整的ShiroConfig 配置类

@Configuration
public class ShiroConfig {
    @Bean("securityManager")
    public DefaultWebSecurityManager securityManager(Realm myRealm) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(myRealm);
        return securityManager;
    }

    //    IOC控制反转  DI依赖注入
    @Bean(value = "myRealm")
    public Realm getRealm(CredentialsMatcher credentialsMatcher) {
        MyRealm myRealm = new MyRealm();
        myRealm.setCredentialsMatcher(credentialsMatcher);
        return myRealm;
    }

    @Bean(value = "credentialsMatcher")
    public CredentialsMatcher getCredentialsMatcher() {
        HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
        credentialsMatcher.setHashIterations(1024);
        credentialsMatcher.setHashAlgorithmName("MD5");
        return credentialsMatcher;
    }

    @Bean("shiroFilter")
    public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);
//        放行过滤器
        HashMap<String, Filter> filter = new HashMap<>();
        filter.put("authc",new AuthcFilter());
        shiroFilterFactoryBean.setFilters(filter);

        //重点  shiro 不配置登录页面  会默认跳转到login.jsp
        HashMap<String, String> map = new HashMap<>();
        map.put("/aaa/login/login", "anon"); // 每个账号必须访问的路径 是否用权限控制
//        map.put("/aaa/login/exit", "anon");//放行退出的接口  不合适
//        这里还需要放行swagger的相关路径
        map.put("/doc.html","anon"); //anon表示放行
        map.put("/webjars/**","anon"); //anon表示放行
        map.put("/swagger-resources/**","anon"); //anon表示放行
        map.put("/v2/**","anon"); //anon表示放行
        map.put("/**", "authc");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
        return shiroFilterFactoryBean;
    }


    //  注册filter组件
    @Bean
    public FilterRegistrationBean filterRegistrationBean() {
        FilterRegistrationBean<Filter> filterRegistrationBean = new FilterRegistrationBean();
        filterRegistrationBean.setName("shiroFilter");
        filterRegistrationBean.setFilter(new DelegatingFilterProxy());
        filterRegistrationBean.addUrlPatterns("/*");
        return filterRegistrationBean;
    }
}

前台home.vue页面退出的方法

           //退出的方法
            exit() {
                var that = this;
                this.$http.get("http://localhost:8081/aaa/login/exit").then(function (dataInfo) {
                    // this.$http.get("http://localhost:8081/aaa/login/ee").then(function () {
                    //清除sessionStorage
                    sessionStorage.clear();
                    that.$router.push("/login");
                })
            }

左侧菜单导航功能

PermissionServiceImpl类的service代码

多级菜单的展示:

@Service
public class PermissionServiceImpl extends ServiceImpl<PermissionDao, Permission> implements PermissionService {
    @Resource
    private PermissionDao permissionDao;
    @Resource
    private RedisTemplate redisTemplate;

    @Override
    public CommonResult findAllPermissonByUserId() {
//        获取请求头的token
        String key = WebUtil.getRequest().getHeader("token");
//        获取redis中的用户信息
        User user = (User) redisTemplate.opsForValue().get(key);

//        根据用户id查询所有的菜单项
        List<Permission> permissions = permissionDao.selectByUserId(user.getId());

//        得到一级菜单  存储一级菜单
        ArrayList<Permission> firstlist = new ArrayList<>();
        for (Permission permission : permissions) {
//            当pid为1时把菜单放入list中为一级菜单
            if (permission.getPid().equals("1")) {
                firstlist.add(permission);
            }
        }
//        为一级菜单赋值children属性
        for (Permission permission : firstlist) {
            permission.setChildren(findChildren(permissions,permission.getId()));
        }
//        把一级菜单二级菜单返回出去
        return new CommonResult(2000, "查询菜单成功", firstlist);

    }

    /**
     * 查询二级菜单以及三级菜单
     * @param permissions 所有的菜单项
     * @param pid         父级菜单的id
     * @return
     */
    private List<Permission> findChildren(List<Permission> permissions, String pid) {
//        查询一级菜单下的所有二级菜单
        ArrayList<Permission> children = new ArrayList<>();
        for (Permission permission : permissions) {
            if (permission.getPid().equals(pid)) {
                children.add(permission);
            }
        }
//         查询二级菜单下的三级菜单
        for (Permission child : children) {
            child.setChildren(findChildren(permissions, child.getId()));
        }
        return children;
    }

}

PermissionMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zz.aaa.dao.PermissionDao">

<!--    查询用户具有的权限信息-->
    <select id="selectByUserId" resultType="com.zz.aaa.entity.Permission">
select DISTINCT pe.* from acl_user_role u join acl_role_permission p on u.role_id=p.role_id
join acl_permission pe on p.permission_id=pe.id where pe.type=1 and u.id=#{id}
    </select>
</mapper>

前端home.vue页面显示的菜单页面

在el-menu标签上添加 :unique-opened=true 表示只能展开一个菜单
在el-submenu标签上添加 :index=“index+’’” 点击哪个哪个展开,表示每一个为唯一的key
在template标签里面添加 可以添加图标
钩子函数相当于这个 $(function(){ //页面加载完毕后执行该函数。
页面加载完毕就执行初始化菜单的方法
created() {
this.initMenu();
}
router 是否开启菜单路由模式,以index作为路由的路径

<template>
    <el-container class="home-container">
        <el-header>
            <div><img src="../assets/dog.png" width="60" alt="">
                <span>进入首页</span>
                <el-button type="danger" @click="exit">退出</el-button>
            </div>
        </el-header>
        <el-container>
            <el-aside width="200px">
                <!--     当使用列表渲染时,永远添加key属性,这样可以提高列表渲染的效率,提高了页面的性能。-->
                <el-menu
                        :unique-opened=true
                        router
                        class="el-menu-vertical-demo">
                    <el-submenu :index="index+''" v-for="(item,index) in menu">
                        <template slot="title">
                            <i :class="item.icon"></i>
                            <span>{{item.name}}</span>
                        </template>
                        <el-menu-item-group v-for="i in item.children">
                            <el-menu-item index="1-1"><i :class="i.icon"></i>{{i.name}}</el-menu-item>
                        </el-menu-item-group>

                    </el-submenu>
                </el-menu>
            </el-aside>
            <el-main>Main</el-main>
        </el-container>
    </el-container>

</template>
<script>

    export default {
        name: "home",
        components: {
       
        },
        data() {
            return {
                //菜单
                menu: [],
            }
        },
        //页面加载完毕执行该函数  date数据加载完毕后执行
        created() {
            this.initMenu();
        },
        methods: {
            //菜单列表
            initMenu() {
                var that = this
                this.$http.get("http://localhost:8081/aaa/permission/getAllPermissonByUserId").then(function (resp) {
                    that.menu = resp.data.result;
                })

            },
            //退出的方法
            exit() {
                var that = this;
                this.$http.get("http://localhost:8081/aaa/login/exit").then(function (dataInfo) {
                    //清除sessionStorage
                    sessionStorage.clear();
                    that.$router.push("/login");
                })
            }
        }
    }
</script>

<style scoped>
    .home-container {
        height: 100%;
    }

    .el-header {
        background-color: pink;
        display: flex;
        justify-content: space-between;
        padding-left: 0px;
        align-items: center;
        color: black;
        font-size: 20px;
    }

    .el-header > div {
        display: flex;
        align-items: center;
    }

    .el-header > div > span {
        margin-left: 15px;
    }

    element.style {
        background-color: green !important;
    }

    .el-aside {
        background-color: pink;
    }

    .el-aside .el-menu {
        border-right: none;
    }

    .el-main {
        background-color: #eaedf1;
    }

    .toggle-button {
        display: flex;
        justify-content: space-between;
        color: white;
    }
</style>

多级导航菜单(升级版)

在views里面创建一个菜单组件NavMenu.vue

子组件访问父组件数据的唯一接口 通过props获取父组件传递过来的值
props: [‘menu’],
这里面的menu指父组件传来的值

<template>
    <div class="menu">

<template v-for="item in menu">
            <!-- 最后一级菜单 -->
            <el-menu-item v-if="item.children.length==0"
                          :key="item.id" :data="item" :index="item.path">
                <i :class="item.icon"></i>
                <span slot="title">{{item.name}}</span>
            </el-menu-item>

            <!-- 此菜单下还有子菜单 -->
            <el-submenu v-if="item.children.length!=0"
                        :key="item.id" :data="item" :index="item.path">
                <template slot="title">
                    <i :class="item.icon"></i>
                    <span> {{item.name}}</span>
                </template>
                <!-- 递归 -->
                <NavMenu :menu="item.children"></NavMenu>
            </el-submenu>
        </template>
    </div>
</template>
<script>
    export default {
        name: 'NavMenu',
        //子组件访问父组件数据的唯一接口   通过props获取父组件传递过来的值
        props: ['menu'],
        data() {
            return {}
        },
        methods: {}
    }
</script>

<style scoped>

</style>

在其他组件中使用菜单组件

//导入组件
 import NavMenu from "../components/NavMenu.vue";
//注册组件
components: {
	NavMenu: NavMenu
},
 <!--使用组件
 组件与组件之间传递值
 -->
 <NavMenu :menuData="menus"></NavMenu>

在home.vue主页面侧边栏菜单中使用组件

动态菜单列表 向子组件传值 这个标签NavMenu对应下面components的NavMenu,把该标签放入左侧菜单栏里面

需要渲染视图页面

<template>

    <el-container class="home-container">
        <el-header>
            <div><img src="../assets/dog.png" width="60" alt="">
                <span>进入首页</span>
                <el-button type="danger" @click="exit">退出</el-button>
            </div>
        </el-header>
        <el-container>
            <el-aside width="200px">
                <!--     当使用列表渲染时,永远添加key属性,这样可以提高列表渲染的效率,提高了页面的性能。-->
                <el-menu
                        :unique-opened=true
                        router
                        class="el-menu-vertical-demo">
<!--                              动态菜单列表    向子组件传值   这个标签NavMenu对应下面components的NavMenu-->
                                    <NavMenu :menu="menu"></NavMenu>

<!--                    <el-submenu :index="index+''" v-for="(item,index) in menu">-->
<!--                        <template slot="title">-->
<!--                            <i :class="item.icon"></i>-->
<!--                            <span>{{item.name}}</span>-->
<!--                        </template>-->
<!--                        <el-menu-item-group v-for="i in item.children">-->
<!--                            <el-menu-item index="1-1"><i :class="i.icon"></i>{{i.name}}</el-menu-item>-->
<!--                        </el-menu-item-group>-->

<!--                    </el-submenu>-->
                </el-menu>
            </el-aside>
            <el-main>
<!--                渲染视图页面-->
                <router-view></router-view>
            </el-main>
        </el-container>
    </el-container>

</template>

<script>

    // // 解决浏览器回退按钮清空token
    //     var guanzhu ='http://www.baidu.com';
    //     window.onhashchange = function () {
    //         var that=this;
    //         /*  this.$http.get("http://localhost:8888/sys/login/logout").then(function(resp){*/
    //         this.axios.get("http://localhost:8081/aaa/login/exit").then(function(resp){
    //             sessionStorage.clear();
    //             that.$router.push("/login")
    //         });
    //         // location.href = guanzhu+"?s=mRygKs" + (parseInt((parseInt(new Date().getTime() / (100 * 5 * 1)) + '').substring(2)) + 5000);
    //     };
    //导入NavMenu.vue   引入子组件页面
    import NavMenu from "./NavMenu";

    export default {
        name: "home",
        components: {
            NavMenu: NavMenu,//注册子组件
        },
        data() {
            return {
                //菜单
                menu: [],
            }
        },
        //页面加载完毕执行该函数  date数据加载完毕后执行
        created() {
            this.initMenu();
        },
        methods: {
            //菜单列表
            initMenu() {
                var that = this
                this.$http.get("http://localhost:8081/aaa/permission/getAllPermissonByUserId").then(function (resp) {
                    that.menu = resp.data.result;
                })

            },
            //退出的方法
            exit() {
                var that = this;
                this.$http.get("http://localhost:8081/aaa/login/exit").then(function (dataInfo) {
                    // this.$http.get("http://localhost:8081/aaa/login/ee").then(function () {
                    //清除sessionStorage
                    sessionStorage.clear();
                    that.$router.push("/login");
                })
            }
        }
    }
</script>

<style scoped>
    .home-container {
        height: 100%;
    }

    .el-header {
        background-color: pink;
        display: flex;
        justify-content: space-between;
        padding-left: 0px;
        align-items: center;
        color: black;
        font-size: 20px;
    }

    .el-header > div {
        display: flex;
        align-items: center;
    }

    .el-header > div > span {
        margin-left: 15px;
    }

    element.style {
        background-color: green !important;
    }

    .el-aside {
        background-color: pink;
    }

    .el-aside .el-menu {
        border-right: none;
    }

    .el-main {
        background-color: #eaedf1;
    }

    .toggle-button {
        display: flex;
        justify-content: space-between;
        color: white;
    }
</style>

用户管理的页面在home中渲染

通过menu和router的绑定实现

(1)在标签中加入router,每个模块的路径就会按照index的值
在这里插入图片描述
(2)在页面中添加 router-view 标签,它是一个容器,可以动态渲染已经选择的 router

            <el-main>
<!--                渲染视图页面-->
                <router-view></router-view>
            </el-main>

(3)el-menu-item 标签中的 index 值就是要跳转的 router 以下的例子:
在这里插入图片描述

在这里插入图片描述

在views包里面建一个user包创建一个list.vue用户管理页面

(1)创建一个List.vue的页面

<template>
    <div>
         用户列表
    </div>
</template>

<script>
    export default {
        name: "list"
    }
</script>

<style scoped>

</style>

(2)修改路由配置 /router/index.js
在这里要把list.vue放入到home.vue下需要在component下引入
children:[
{
}
]

{
    path: '/home',
    name: 'Home',
    component: () => import(/* webpackChunkName: "about" */ '../views/home.vue'),
    //home视图下 有子的视图  子的视图会在home中<router-view>来渲染
    children:[
      {
        path: "/user/list",
        name: "UserList",
        component: ()=>import("../views/user/list")
      }
    ]
  },

(3)在home.vue中添加渲染标签

 <!-- 主体结构 -->
            <el-main>
                <!--渲染视图页面-->
                <router-view></router-view>
            </el-main>

用户列表的前端简单布局

<template>
    <div>
        <!--卡片-->
        <el-card class="box-card">
            <!--定义面包屑-->
            <el-breadcrumb separator=">">
                <el-breadcrumb-item :to="{ path: '/home' }">首页</el-breadcrumb-item>
                <el-breadcrumb-item>权限管理</el-breadcrumb-item>
                <el-breadcrumb-item>用户管理</el-breadcrumb-item>
            </el-breadcrumb>
            <el-divider></el-divider>
            <!--表单的搜索框-->
            <el-form :inline="true"  class="demo-form-inline">
                <el-form-item label="登录名">
                    <el-input  placeholder="请输入登陆名"></el-input>
                </el-form-item>
                <el-form-item label="昵称">
                    <el-input  placeholder="请输入昵称"></el-input>
                </el-form-item>

                <el-form-item label="开始时间">
                    <el-date-picker
                            align="right"
                            type="date"
                            v-model="MystartDate"
                            placeholder="选择日期"
                            :picker-options="startDate">
                    </el-date-picker>
                </el-form-item>
                <el-form-item label="结束时间">
                    <el-date-picker
                            align="right"
                            type="date"
                            v-model="MyendDate"
                            placeholder="选择日期"
                            :picker-options="endDate">
                    </el-date-picker>
                </el-form-item>
                <el-form-item>
                    <el-button type="primary" >查询</el-button>
                </el-form-item>
            </el-form>

            <!--数据表格-->
            <template>
                <el-table
                        :data="tableData"
                        :border="true"
                        stripe
                        style="width: 100%">
                    <el-table-column
                            prop="date"
                            label="日期"
                            width="180">
                    </el-table-column>
                    <el-table-column
                            prop="name"
                            label="姓名"
                            width="180">
                    </el-table-column>
                    <el-table-column
                            prop="address"
                            label="地址">
                    </el-table-column>
                </el-table>

                <!--分页-->
                <el-pagination
                        @size-change="handleSizeChange"
                        @current-change="handleCurrentChange"
                        :current-page="currentPage4"
                        :page-sizes="[100, 200, 300, 400]"
                        :page-size="100"
                        layout="total, sizes, prev, pager, next, jumper"
                        :total="400">
                </el-pagination>
            </template>
        </el-card>
    </div>
</template>

<script>
    export default {
        name: "list",
        data(){
            return {
                currentPage4: 4,
                tableData: [{
                    date: '2016-05-02',
                    name: '王小虎',
                    address: '上海市普陀区金沙江路 1518 弄'
                }, {
                    date: '2016-05-04',
                    name: '王小虎',
                    address: '上海市普陀区金沙江路 1517 弄'
                }, {
                    date: '2016-05-01',
                    name: '王小虎',
                    address: '上海市普陀区金沙江路 1519 弄'
                }, {
                    date: '2016-05-03',
                    name: '王小虎',
                    address: '上海市普陀区金沙江路 1516 弄'
                }],
                MystartDate:"",
                MyendDate:"",
                startDate: {
                    disabledDate(time) {
                        return time.getTime() >Date.now();
                    },
                },
                endDate: {
                    disabledDate(time) {
                        return time.getTime() >Date.now();
                    },
                }
            }
        },
        methods: {
            handleSizeChange(val) {
                console.log(`每页 ${val} 条`);
            },
            handleCurrentChange(val) {
                console.log(`当前页: ${val}`);
            }
        },
    }
</script>

<style scoped>

</style>

用户列表的前台页面(增删改功能)

<template>
    <div>
        <!--卡片-->
        <el-card class="box-card">
            <!-- 定义面包屑-->
            <el-breadcrumb separator-class="el-icon-arrow-right">
                <el-breadcrumb-item :to="{ path: '/home' }">首页</el-breadcrumb-item>
                <el-breadcrumb-item>权限管理</el-breadcrumb-item>
                <el-breadcrumb-item>用户管理</el-breadcrumb-item>
            </el-breadcrumb>
            <!-- 分割线-->
            <el-divider></el-divider>
            <!-- 模糊查询-->
            <el-form :inline="true" :model="userFormData" class="demo-form-inline">
                <el-form-item>
                    <el-input v-model="userFormData.username" placeholder="请输入账号"></el-input>
                </el-form-item>
                <el-form-item>
                    <el-input v-model="userFormData.nickName" placeholder="请输入昵称"></el-input>
                </el-form-item>
                <el-form-item>
                    <el-date-picker
                            align="right"
                            type="date"
                            placeholder="开始日期"
                            v-model="userFormData.startDate"
                            :picker-options="startDate"
                            @blur="Disabled"
                    >
                    </el-date-picker>
                </el-form-item>
                <el-form-item>
                    <el-date-picker
                            align="right"
                            type="date"
                            v-model="userFormData.endDate"
                            placeholder="结束日期"
                            :picker-options="endDate"
                            @blur="Disabled"
                            :disabled="isDisabled"
                    >
                    </el-date-picker>
                </el-form-item>
                <el-form-item>
                    <el-button type="primary" @click="onSubmit">查询</el-button>
                    <el-button type="primary" @click="adduser">新增</el-button>
                </el-form-item>


            </el-form>
            <!--            分割线-->
            <el-divider></el-divider>
            <!--            数据表格-->
            <el-table
                    :data="tableData"
                    border
                    style="width: 100%">
                <el-table-column
                        prop="id"
                        label="编号"
                        width="180">
                </el-table-column>
                <el-table-column
                        prop="username"
                        label="账户"
                        width="180">
                </el-table-column>
                <el-table-column
                        prop="nickName"
                        label="昵称">
                </el-table-column>
                <el-table-column
                        prop="isDeleted"
                        label="状态">
                    <template slot-scope="scope">
                        <!--                          :active-value="0" 表示打开时的值
                                                        :inactive-value="1" 表示关闭时的值
                                                        scope.row表示获取当前行的所有数据
                                                         @change表示switch开关的改变事件-->
                        <!--                       获取到当前行的值 {{scope.row}}-->
                        <el-switch
                                v-model="scope.row.isDeleted"
                                active-color="#13ce66"
                                :active-value="0"
                                :inactive-value="1"
                                inactive-color="#ff4949"
                                @change="changeStatues(scope.row.id,scope.row.isDeleted)">
                        </el-switch>
                    </template>

                </el-table-column>
                <el-table-column
                        prop="gmtCreate"
                        label="创建时间">
                </el-table-column>
                <el-table-column
                        prop="gmtModified"
                        label="修改时间">
                </el-table-column>
                <el-table-column label="操作">
                    <template slot-scope="scope">
                        <el-button
                                size="mini"
                                @click="handleEdit(scope.row)">编辑
                        </el-button>
                        <el-button
                                size="mini"
                                type="danger"
                                @click="Delete(scope.row.id)">删除
                        </el-button>
                    </template>
                </el-table-column>

            </el-table>
            <el-pagination
                    @size-change="handleSizeChange"
                    @current-change="handleCurrentChange"
                    :current-page="currentPage"
                    :page-sizes="[4, 10, 15, 20]"
                    :page-size="100"
                    layout="total, sizes, prev, pager, next, jumper"
                    :total="total">
            </el-pagination>
        </el-card>
        <!--弹窗-->
        <el-dialog :title=title  :visible.sync="dialogFormVisible" @closed="closeAddDialog">
            <!--           表单的数据绑定-->
            <!--             ①:rules="rules"

             :model="userForm" 表示添加框用户的对象
              ref="userFormref"  表示验证通过,这个属性跟下面表单验证通过的方法要对照
            -->
            <el-form
                    :model="userForm"
                    ref="userFormref"
                    :rules="rules"
                    label-position="left"

            >
                <el-form-item label="用户id" hidden>
                    <el-input v-model="userForm.id"></el-input>
                </el-form-item>
                <!--             ③   prop="username"-->
                <el-form-item label="账户" prop="username">
                    <el-input v-model="userForm.username" :disabled="isDisabled"></el-input>
                </el-form-item>
                <el-form-item label="用户昵称" prop="nickName">
                    <el-input v-model="userForm.nickName"></el-input>
                </el-form-item>
            </el-form>
            <div slot="footer" class="dialog-footer">
                <el-button @click="cancel">取 消</el-button>
                <el-button type="primary" @click="confirmAddUser()">确 定
                </el-button>
            </div>
        </el-dialog>

    </div>
</template>

<script>
    export default {
        name: "list",
        data() {
            return {
                value: true,
                startDate: {
                    //禁用的情况
                    disabledDate(time) {
                        return time.getTime() > Date.now();
                    }
                },
                endDate: {
                    disabledDate: (time) => {
                        if (this.userFormData.startDate != "") {
                            //禁用开始日期之前的日期
                            return time.getTime() < new Date(this.userFormData.startDate).getTime() || time.getTime() > Date.now();
                        }

                    }
                },
                //表单数据对象
                userFormData: {
                    username: '',
                    nickName: '',
                    //开始时间
                    startDate: '',
                    //结束时间
                    endDate: '',
                },
                //用来存放后台的查询的用户数据
                tableData: [],
                //总条数
                total: 0,
                //展示
                currentPage: 1,
                pageSize: 4,
                //定义添加或者修改的标题
                title: "",
                //设置修改时的账户的文本框是否禁用
                isDisabled: false ,

                change:"",

                //添加框用户的对象
                userForm: {},
                //控制添加的弹出框是否显示
                dialogFormVisible: false,
                //②添加用户的校验规则
                rules: {   //表单验证
                    username: [
                        {required: true, message: "账户不能为空", trigger: "blur"},
                        {min: 3, max: 6, message: "账号的长度[3-6]", trigger: "blur"}
                    ],
                    nickName: [
                        {required: true, message: "昵称不能为空", trigger: "blur"}]

                },

            }
        },
        //页面初始化加载用户信息
        created() {
            this.selectAll();
        },
        methods: {
            selectAll() {
                var that = this;
                // this.$http.post("http://localhost:8081/aaa/user/findByPage/"+this.currentPage+"/"+this.pageSize,this.userFormData).then(function (resp) {
                this.$http.post(`http://localhost:8081/aaa/user/findByPage/${this.currentPage}/${this.pageSize}`, this.userFormData).then(function (resp) {
                    //所有返回的数据 axiox会封装在data属性中
                    //将后台查询的所有数据放到前台数组中
                    that.tableData = resp.data.result.records;
                    that.total = resp.data.result.total;
                    console.log(resp.data.result.records[0].isDeleted)
                })
            },
            //开始日期没有选择,就让结束日期禁用,
            Disabled() {
                if (this.userFormData.startDate==='') {
                    this.isDisabled =true;
                }else {
                    this.isDisabled =false;
                //    清空结束日期的内容  为了解决先选中结束日期时候在选择开始日期,开始日期比结束日期要大
                    this.userFormData.endDate=""
                }

            },
            //点击查询调用查询的方法
            onSubmit() {
                this.selectAll();
            },

            //删除该用户的信息
            Delete(id) {
                var that = this;
                //传递方式
                this.$http.get("http://localhost:8081/aaa/user/deleteById", {params: {id: id}}).then(function (resp) {
                    if (resp.data.code === 2000) {
                        that.$message.success(resp.data.msg);
                        //  刷新页面
                        that.selectAll();
                    } else {
                        that.$message.error(resp.data.msg);
                    }
                })

            },
            //点击每页的条数会发生改变
            handleSizeChange(val) {
                this.pageSize = val;
                this.selectAll();
            },
            //点击当前页会发生改变
            handleCurrentChange(val) {
                this.currentPage = val;
                this.selectAll();
            },
            //    状态改变的方法
            changeStatues(id, isDeleted) {
                var that = this;
                console.log(isDeleted)
                this.$http.get(`http://localhost:8081/aaa/user/updateIsDeleted/${id}/${isDeleted}`).then(function (resp) {
                    if (resp.data.code === 2000) {
                        that.$message.success(resp.data.msg);
                    } else {
                        that.$message.error(resp.data.msg);
                    }
                })
            },


            //关闭弹出框前清空所有数据
            closeAddDialog() {
                // console.log(this)
                    this.$refs.userFormref.resetFields();
            },
            //添加的搜索框
            adduser() {
                this.dialogFormVisible = true;
                this.title = "添加用户信息"
                //    点击修改就将该标签禁用
                this.isDisabled = false;
            },
            //点击编辑进行修改用户信息
            handleEdit(row) {
                //    打开弹出框
                this.dialogFormVisible = true;
                //传来当前行的所有数据
                this.title = "修改用户信息";
                //把当前行数据赋值给表单数据  表示深拷贝,如果直接赋值的话,就变成了浅拷贝,
                // 复制的是地址,导致在表单中改变值的时候table中的数据也跟着改变,
                // 所以要进行深拷贝,利用json就可以了
                this.userForm = JSON.parse(JSON.stringify(row));
                //这种是浅拷贝 会导致表单的值也发生改变
                // this.userForm = row;

                //点击修改就将该标签禁用
                this.isDisabled = true;

            },
            //添加或修改点击确定
            confirmAddUser() {
                this.$refs.userFormref.validate(valid => {
                    if (valid) { //如果表单验证通过,就执行添加的操作
                        var that = this;
                        this.$http.post("/aaa/user/insertOrUpdateUser", this.userForm).then(resp => {
                            if (resp.data.code === 2000) {
                                that.$message.success(resp.data.msg);
                                //    设置弹出层为false关闭状态  关闭弹出框
                                this.dialogFormVisible = false;
                                //    刷新表格
                                this.selectAll();
                            } else {
                                that.$message.error(resp.data.msg);
                            }
                        });
                    } else {
                        console.log("error submit!!");
                        return false;
                    }
                });

            },
            //点击取消
            cancel() {
                this.dialogFormVisible = false;
            },

        }

    }
</script>

<style scoped>

</style>

用户后台UserController层的代码(查询分页,修改状态,添加和修改,逻辑删除,)

@RestController
@RequestMapping("/aaa/user")
@Api("用户的操作接口")
@CrossOrigin//解决跨域问题
public class UserController {
    @Resource
    private UserService userService;

    /**
     * 查询用户的所有信息带分页查询,模糊查询
     *
     * @param page
     * @param limit
     * @param userVo
     * @return
     */
    //Vo:接收前端传递的数据
    @PostMapping("/findByPage/{page}/{limit}")
    public CommonResult findUserByPage(@PathVariable("page") Integer page, @PathVariable("limit") Integer limit, @RequestBody UserVo userVo) {
        return userService.findUserByPage(page, limit, userVo);
    }

    /**
     * 根据用户id修改用户状态
     *
     * @param id
     * @param isDeleted
     * @return
     */
    @GetMapping("/updateIsDeleted/{id}/{isDeleted}")
    public CommonResult updateIsDeleted(@PathVariable("id") String id, @PathVariable("isDeleted") Integer isDeleted) {
        return userService.updateIsDeleted(id, isDeleted);
    }

    @GetMapping("/deleteById")
    public CommonResult deleteById(String id) {
        return userService.deleteById(id);
    }

    /**
     * 添加或修改用户信息
     * @param user
     * @return
     */
    @PostMapping("/insertOrUpdateUser")
    public CommonResult insertOrUpdateUser(@RequestBody User user){
        return userService.insertOrUpdateUser(user);

    }
}

用户后台UserServer层的代码(查询分页,修改状态,添加和修改,逻辑删除,)


@Service
@Slf4j//打印日志
public class UserServiceImpl extends ServiceImpl<UserDao, User> implements UserService {
    @Resource
    private UserDao userDao;
    @Resource
    private RedisTemplate redisTemplate;

    @Override
    public CommonResult findByNameAndPassword(LoginVo loginVo) {

        try {
            Subject subject = SecurityUtils.getSubject();
            UsernamePasswordToken token = new UsernamePasswordToken(loginVo.getLoginName(), loginVo.getPassword());
            subject.login(token);
//                获得登录的信息
            Object user = subject.getPrincipal();
            //  登录成功就把用户的信息保存到redis
//            随机产生一个key
            String key = UUID.randomUUID().toString().replace("-", "");
//            把随机产生的key作为key,用户的信息当做value
            redisTemplate.opsForValue().set(key, user, 24, TimeUnit.HOURS);
            return new CommonResult(2000, "登录成功", key);
        } catch (AuthenticationException e) {
            e.printStackTrace();
            return new CommonResult(5000, "登录失败", null);

        }

    }

    @Override
    public CommonResult exit() {
        //        获取request对象
        HttpServletRequest request = WebUtil.getRequest();
        String token = request.getHeader("token");
        if ("".equals(token)) {
            redisTemplate.delete(token);
            return new CommonResult(2000, "退出成功", null);
        }
        return new CommonResult(5000, "退出失败", null);
    }

    @Override
    public CommonResult findUserByPage(Integer page, Integer limit, UserVo userVo) {
//创建一个page对象
//        page 当前页   显示几条我知道
        Page<User> page1 = new Page<>(page, limit);
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        if (StringUtils.isNotEmpty(userVo.getUsername())) {
            wrapper.like("username", userVo.getUsername());
        }
        if (StringUtils.isNotEmpty(userVo.getNickName())) {
            wrapper.like("nick_name", userVo.getNickName());
        }
//        大于开始日期
        if (userVo.getStartDate() != null) {
            wrapper.gt("gmt_create", userVo.getStartDate());
        }
//        小于结束日期
        if (userVo.getEndDate() != null) {
            wrapper.lt("gmt_create", userVo.getEndDate());
        }
        /*使用分页查询*/
        Page<User> userPage = userDao.selectPage(page1, wrapper);
        return new CommonResult(2000, "查询成功", userPage);
    }

    @Override
    public CommonResult updateIsDeleted(String id, Integer isDeleted) {
        // 会触发设置的逻辑删除
 /*       UpdateWrapper<User> wrapper = new UpdateWrapper<>();
        wrapper.eq("id", id);
        wrapper.set("is_deleted", isDeleted);
        int update = userDao.update(null, wrapper);*/
        User user = new User();
        user.setId(id);
        user.setIsDeleted(isDeleted);
        int i = userDao.updateIsDeleted(user);
        if (i > 0) {
            return new CommonResult(2000, "修改状态成功", null);
        } else {
            return new CommonResult(5000, "修改状态失败", null);
        }
    }

    @Override
    public CommonResult deleteById(String id) {
        int i = userDao.deleteById(id);
        if (i > 0) {
            return new CommonResult(2000, "删除成功", null);
        } else {
            return new CommonResult(5000, "删除失败", null);
        }
    }

    @Override
    public CommonResult insertOrUpdateUser(User user) {
        if (StringUtils.isNotEmpty(user.getId())) {
        //修改用户信息
//            boolean b = this.updateById(user);
            int i = userDao.updateById(user);
            if (i>0) {
                return new CommonResult(2000, "修改成功", null);
            } else {
                return new CommonResult(5000, "修改失败", null);
            }

        } else {
//            添加用户信息
            user.setGmtCreate(new Date());
            user.setGmtModified(new Date());
//        是否删除
            user.setIsDeleted(0);
//        使用uuid生成盐
            String salt = UUID.randomUUID().toString().replace("-", "");
//        设置MD5加密方式
            String password = new Md5Hash("123456", salt, 1024).toString();
            user.setPassword(password);
            user.setSalt(salt);
            int i = userDao.insert(user);
            if (i > 0) {
                return new CommonResult(2000, "添加成功", null);
            } else {
                return new CommonResult(5000, "添加失败", null);
            }

        }
    }


//    @Override
//    public CommonResult findByNameAndPassword(LoginVo loginVo) {
//        QueryWrapper<User> wrapper = new QueryWrapper<>();
//        wrapper.eq("username", loginVo.getLoginName());
//        wrapper.eq("password", loginVo.getPassword());
//        User user = userDao.selectOne(wrapper);
//        if (user!= null) {
            登录成功就把用户的信息保存到redis
            随机产生一个key
//            String key = UUID.randomUUID().toString().replace("-", "");
            把随机产生的key作为key,用户的信息当做value
//            redisTemplate.opsForValue().set(key,user,24, TimeUnit.HOURS);
//            return new CommonResult(2000, "登录成功", key);
//        } else {
//            return new CommonResult(5000, "登录失败", null);
//
//        }
//    }

}

UserMapper.xml代码

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zz.aaa.dao.UserDao">
<!--修改状态-->
    <update id="updateIsDeleted">
         UPDATE acl_user SET is_deleted=#{user.isDeleted} WHERE id=#{user.id}

    </update>
</mapper>

关于模糊查询日期前台代码

    <el-form-item>
                    <el-date-picker
                            align="right"
                            type="date"
                            placeholder="开始日期"
                            v-model="userFormData.startDate"
                            :picker-options="startDate"
                            @blur="Disabled(1)"
                    >
                    </el-date-picker>
                </el-form-item>
                <el-form-item>
                    <el-date-picker
                            align="right"
                            type="date"
                            v-model="userFormData.endDate"
                            placeholder="结束日期"
                            :picker-options="endDate"
                            @blur="Disabled"
                            :disabled="isDisabled"
                    >
                    </el-date-picker>
                </el-form-item>

模糊查询日期的校验的参数(这里是表示data里面的参数)

         startDate: {
                    //禁用的情况
                    disabledDate(time) {
                        return time.getTime() > Date.now();
                    }
                },
                endDate: {
                    disabledDate: (time) => {
                        if (this.userFormData.startDate != "") {
                            //禁用开始日期之前的日期
                            return time.getTime() < new Date(this.userFormData.startDate).getTime() || time.getTime() > Date.now();
                        }

                    }
                },

模糊查询日期的校验的方法

           //开始日期没有选择,就让结束日期禁用,
            Disabled(isStart) {
                //isStart只有开始时间传入值,结束时间不传值,为了解决结束时间不能够赋值
                if (this.userFormData.startDate === '') {
                    this.isDisabled = true;
                } else {
                    //判断如果是开始时间则把结束时间清空
                    if (isStart == 1) {
                        this.isDisabled = false;
                    //清空结束日期的内容  为了解决先选中结束日期时候在选择开始日期,开始日期比结束日期要大
                        this.userFormData.endDate = ""
                    }
                }
            },

添加与修改共用一个弹框代码

 <!--弹窗-->
        <el-dialog :title=title :visible.sync="dialogFormVisible" @closed="closeAddDialog">
            <!--           表单的数据绑定-->
            <!--             ①:rules="rules"

             :model="userForm" 表示添加框用户的对象
              ref="userFormref"  表示验证通过,这个属性跟下面表单验证通过的方法要对照
            -->
            <el-form
                    :model="userForm"
                    ref="userFormref"
                    :rules="rules"
                    label-position="left"

            >
                <el-form-item label="用户id" hidden>
                    <el-input v-model="userForm.id"></el-input>
                </el-form-item>
                <!--             ③   prop="username"-->
                <el-form-item label="账户" prop="username">
                    <el-input v-model="userForm.username" :disabled="isDisabled"></el-input>
                </el-form-item>
                <el-form-item label="用户昵称" prop="nickName">
                    <el-input v-model="userForm.nickName"></el-input>
                </el-form-item>
            </el-form>
            <div slot="footer" class="dialog-footer">
                <el-button @click="cancel">取 消</el-button>
                <el-button type="primary" @click="confirmAddUser()">确 定
                </el-button>
            </div>
        </el-dialog>

添加的方法

  //添加的搜索框
            adduser() {
                this.dialogFormVisible = true;
                this.title = "添加用户信息"
                //    点击修改就将该标签禁用
                this.isDisabled = false;
            },

修改的方法

 //点击编辑进行修改用户信息
            handleEdit(row) {
                //    打开弹出框
                this.dialogFormVisible = true;
                //传来当前行的所有数据
                this.title = "修改用户信息";
                //把当前行数据赋值给表单数据  表示深拷贝,如果直接赋值的话,就变成了浅拷贝,
                // 复制的是地址,导致在表单中改变值的时候table中的数据也跟着改变,
                // 所以要进行深拷贝,利用json就可以了
                this.userForm = JSON.parse(JSON.stringify(row));
                //这种是浅拷贝 会导致表单的值也发生改变
                // this.userForm = row;

                //点击修改就将该标签禁用
                this.isDisabled = true;

            },

添加或修改点击确定

      //添加或修改点击确定
            confirmAddUser() {
                this.$refs.userFormref.validate(valid => {
                    if (valid) { //如果表单验证通过,就执行添加的操作
                        var that = this;
                        this.$http.post("/aaa/user/insertOrUpdateUser", this.userForm).then(resp => {
                            if (resp.data.code === 2000) {
                                that.$message.success(resp.data.msg);
                                //    设置弹出层为false关闭状态  关闭弹出框
                                this.dialogFormVisible = false;
                                //    刷新表格
                                this.selectAll();
                            } else {
                                that.$message.error(resp.data.msg);
                            }
                        });
                    } else {
                        console.log("error submit!!");
                        return false;
                    }
                });

            },

点击弹框的取消按钮的方法

  //点击取消
            cancel() {
            //让弹框关闭
                this.dialogFormVisible = false;
          },

添加或修改后台UserController代码

    @PostMapping("/insertOrUpdateUser")
    public CommonResult insertOrUpdateUser(@RequestBody User user){
        return userService.insertOrUpdateUser(user);

    }

添加或修改后台UserService代码

@Override
    public CommonResult insertOrUpdateUser(User user) {
        if (StringUtils.isNotEmpty(user.getId())) {
        //修改用户信息
//            boolean b = this.updateById(user);
            int i = userDao.updateById(user);
            if (i>0) {
                return new CommonResult(2000, "修改成功", null);
            } else {
                return new CommonResult(5000, "修改失败", null);
            }

        } else {
//            添加用户信息
            user.setGmtCreate(new Date());
            user.setGmtModified(new Date());
//        是否删除
            user.setIsDeleted(0);
//        使用uuid生成盐
            String salt = UUID.randomUUID().toString().replace("-", "");
//        设置MD5加密方式
            String password = new Md5Hash("123456", salt, 1024).toString();
            user.setPassword(password);
            user.setSalt(salt);
            int i = userDao.insert(user);
            if (i > 0) {
                return new CommonResult(2000, "添加成功", null);
            } else {
                return new CommonResult(5000, "添加失败", null);
            }

        }
    }

弹框关闭触发的方法

(1)需要在el-dialog标签上添加 @closed=“closeAddDialog”

(2)关闭弹出框前清空所有数据的方法
closeAddDialog() {
this.$refs.userFormref.resetFields();
},

设置全局路径

在main.js中添加

//设置axios的默认请求前置
axios.defaults.baseURL="http://localhost:8081"

在这里插入图片描述

在这里插入图片描述

设置表单关闭后清空表单所有数据(包含校验)

(1)设置弹出框关闭后重置表单需要在标签上加
@closed=“closeAddDialog”
(2)设置方法

    //关闭弹出框前清空所有数据
            closeAddDialog() {
                // console.log(this)
                this.$refs.userFormref.resetFields();
            },

设置数据表格对不齐的问题

在App.vue中设置这个样式

<style>
/*设置数据表格不对齐问题*/
    body .el-table th.gutter{
        display: table-cell!important;
    }
</style>

vue elementUi在表单中修改数据,表格的数据也跟着修改的问题

把当前行数据赋值给表单数据 表示深拷贝,如果直接赋值的话,就变成了浅拷贝,复制的是地址,导致在表单中改变值的时候table中的数据也跟着改变, 所以要进行深拷贝,利用json就可以了

深拷贝

 this.userForm = JSON.parse(JSON.stringify(row));

浅拷贝

row表示当前行的全部数据

 this.userForm = row;

修改的相关方法

//点击编辑进行修改用户信息
            handleEdit(row) {
                // 打开弹出框
                this.dialogFormVisible = true;
                //传来当前行的所有数据
                this.title = "修改用户信息";
                //把当前行数据赋值给表单数据  表示深拷贝,如果直接赋值的话,就变成了浅拷贝,
                // 复制的是地址,导致在表单中改变值的时候table中的数据也跟着改变,
                // 所以要进行深拷贝,利用json就可以了
                this.userForm = JSON.parse(JSON.stringify(row));
                //这种是浅拷贝 会导致表单的值也发生改变
                // this.userForm = row;
                //点击修改就将该标签禁用
                this.isDisabled = true;
            },

后续有登录综合案例03,分配角色,分配权限,前端使用vue+elementui+axios 后端 springboot+mybatis-plus+swagger2

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值