• 【JavaWeb项目】一个众筹网站的开发(八)后台页面详细设置


    一、user.jsp改造

    删除引入菜单

    抽取导航栏 nav-bar.jsp,删除引入导航栏

    删除引入main.jsp的到好烂

    数据库里添加url

    报错,url不对

     

     没有/

     

     url正确

    action="${ctp}/permission/user/login"

    <a href="${c_menu.url }">

    <%@page import="com.atguigu.scw.manager.constant.Constants"%>
    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
    <%@taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
    <div class="col-sm-3 col-md-2 sidebar">
        <div class="tree">
            <ul style="padding-left: 0px;" class="list-group">
                <li class="list-group-item tree-closed"><a href="${ctp }/main.html"><i
                        class="glyphicon glyphicon-dashboard"></i> 控制面板</a></li>
                <!-- 遍历菜单 -->
                <c:forEach items="<%=session.getAttribute(Constants.USER_MENUS) %>" var="p_menu">
                    <li class="list-group-item tree-closed"><span>
                        <i class="${p_menu.icon }"></i> ${p_menu.name } 
                            <span class="badge" style="float: right">${fn:length(p_menu.childs)}</span></span>
                        <ul style="margin-top: 10px; display: none;">
                        <c:forEach items="${p_menu.childs}" var="c_menu">
                            <li style="height: 30px;"><a href="${ctp }/${c_menu.url }"><i
                                    class="${c_menu.icon }"></i> ${c_menu.name }</a></li>
                        </c:forEach>
                        </ul>
                    </li>
                
                </c:forEach>
            </ul>
        </div>
    </div>

    在controller里实现分页逻辑

    package com.atguigu.scw.manager.controller.permission;
    //处理所有/permission/user下的请求
    @RequestMapping("/permission/user")
    @Controller
    public class UserController {
    
        private final String MANAGER_MAIN = "manager/main";
        @Autowired
        UserService userService;
    
        /**
         * 用户列表页面显示
         * 
         * @Description (TODO这里用一句话描述这个方法的作用)
         * @return
         */
        @RequestMapping("/list")
        public String users(@RequestParam(value = "pn", defaultValue = "1") Integer pn,
                @RequestParam(value = "ps", defaultValue = "10") Integer ps, Model model) {
            // 有表单提交,防止重复提交,建议额外写一个转发方法重定向到页面
            // 没有表单提交就直接转发到目标页面
            // 分页获取用户的逻辑
            System.out.println("分页获取用户的逻辑");
            PageHelper.startPage(pn, ps);
            // 拿到分页查出的结果
            List<TUser> list = userService.getAll();
            // 去页面显示的数据
            PageInfo<TUser> info = new PageInfo<TUser>(list, 5);
            model.addAttribute("user_info", info);// 直接转到页面
            return "manager/permission/user";
        }
    
        @RequestMapping("/login")
        public String login(TUser user, HttpSession session) {
           // 省略
        }
    
        // /permission/user/reg
        @RequestMapping("/reg")
        public String reg(TUser user, Model model, HttpSession session) {
           // 省略
        }
    }

    Mybatis的插件 PageHelper 分页查询使用方法  https://blog.csdn.net/maoyuanming0806/article/details/77720754

    pageHelper.startPage(m,n),只对最近的一次查询有效,之前不是很理解什么是最近的一次查询。

    原来mapper代理对象.selectXXX(),这个方法就是查询。

    比如说:

    pageHelper.startPage(1,30);

    List<Item> list = ItemMapper.selectByExample(example);

    也就是分页只针对这次获得的list有效。

    PageHelper.startPage(pageNum, pageSize);
    pageNum :当前页数
    pageSize :一页大小
    调用该方法后,在此方法后面的第一个mybaits查询语句就会按照这个进行分页
    PageInfo pageInfo=new PageInfo(shippingList);
    则对第一次查询的集合传入,可以获得更多的页面操作信息,封装在PageInfo 这个类上

    PageInfo pageInfo = new PageInfo(list,5);

    使用pageInfo包装查询后的结果,封装了详细的查询数据,其中参数5是页码导航连续显示的页数

    用到了UserService的getAll方法

    在接口中添加方法,在实现类中实现方法

    public interface UserService {
    
        public boolean register(TUser user);
    
        public TUser login(TUser user);
    
        public List<TUser> getAll();
    }

    实现类

    package com.atguigu.scw.manager.service.impl;
    
    
    @Service
    public class UserServiceImpl implements UserService {
    
        @Autowired
        TUserMapper userMapper;
    
        public boolean register(TUser user) {
            // 省略
        }
    
        public TUser login(TUser user) {
            // 省略
        }
    
        public List<TUser> getAll() {
    
            return userMapper.selectByExample(null);
        }
    
    }

    user.jsp

                <tbody>
                  <c:forEach items="${user_info.list}" var="user">
                    <tr>
                    <!-- varStatus="" 当前遍历的所有信息,索引 -->
                    <!-- 取出用户的实际ID -->
                      <td>${user.id }</td>
                      <td><input type="checkbox"></td>
                      <td>${user.loginacct }</td>
                      <td>${user.username }</td>
                      <td>${user.email }</td>
                      <td>
                          <button type="button" class="btn btn-success btn-xs"><i class=" glyphicon glyphicon-check"></i></button>
                          <button type="button" class="btn btn-primary btn-xs"><i class=" glyphicon glyphicon-pencil"></i></button>
                          <button type="button" class="btn btn-danger btn-xs"><i class=" glyphicon glyphicon-remove"></i></button>
                      </td>
                    </tr>
                   </c:forEach>
                  </tbody>

    <tfoot> <tr > <td colspan="6" align="center"> <ul class="pagination"> <li><a href="${ctp}/permission/user/list?pn=1">首页</a></li> <c:if test="${user_info.hasPreviousPage}"> <li><a href="${ctp}/permission/user/list?pn=${user_info.prePage }">上一页</a></li> </c:if> <!-- 遍历连续显示的页面navigatepageNums: int[] --> <c:forEach items="${user_info.navigatepageNums }" var="pn"> <!-- 是当前页 --> <c:if test="${pn == user_info.pageNum }"> <li class="active"><a href="${ctp}/permission/user/list?pn=${pn}">${pn } <span class="sr-only">(current)</span></a></li> </c:if> <!-- 不是当前页 --> <c:if test="${pn != user_info.pageNum }"> <li><a href="${ctp}/permission/user/list?pn=${pn }">${pn }</a></li> </c:if> </c:forEach> <c:if test="${user_info.hasNextPage}"> <li><a href="${ctp}/permission/user/list?pn=${user_info.nextPage }">下一页</a></li> </c:if> <li><a href="${ctp}/permission/user/list?pn=${user_info.pages }">末页</a></li> </ul> </td> </tr> </tfoot>

    tbody标签就是显示的用户信息

    tfoot标签中就是下面的导航

    逻辑就是,点击用户维护按钮,会有请求到/permission/user/list,UserController的usrers处理该请求,使用PageHelpler插件,设置每页显示多少,通过新定义的getAll()方法从数据库获得用户信息,放在PageInfo对象中,在model中添加该对象往前台传数据,命名位user_info,最后转到user.jsp。

    user.jsp接收到user_info,遍历该对象的list,显示用户的信息

    在页脚,如果没有前一页就是首页,没有后一页就是末页,遍历首页和末页中正在连续显示的页面,这些页面中是当前的页面就高亮显示。

    二、页面样式优化

    当再次点击 用户维护 的时候

    url链接重叠

     菜单抽取中设置的url不对

    <a href="${ctp }/${c_menu.url }"><i class="${c_menu.icon }"></i> ${c_menu.name }</a>

    应改为当前项目下,这样才会最终是绝对路径,否则上面是相对路径,出现url重叠的现象

    <a href="${ctp }/${c_menu.url }"><i class="${c_menu.icon }"></i> ${c_menu.name }</a>

    来到页面后我们发现菜单是闭合的

    我们想要展开,且当前菜单红色显示

    查看网页源码

    <!-- 遍历菜单 -->
                        
                        <li class="list-group-item tree-closed">
                            <span><i class="glyphicon glyphicon glyphicon-tasks"></i> 权限管理 
                            <span class="badge" style="float:right">3</span></span> 
                            <ul style="margin-top:10px;display:none;">
                                
                                <li style="height:30px;">
                                    <a href="/manager-web/permission/user/list"><i class="glyphicon glyphicon-user"></i> 用户维护</a> 
                                </li>
                                
                                <li style="height:30px;">
                                    <a href="/manager-web/"><i class=""></i> 角色维护</a> 
                                </li>
                                
                                <li style="height:30px;">
                                    <a href="/manager-web/"><i class=""></i> 许可维护</a> 
                                </li>
                            
                            </ul>
                        </li>

    <ul style="margin-top:10px;display:none;">我们发现展示是none

    <a href="/manager-web/permission/user/list"><i class="glyphicon glyphicon-user"></i> 用户维护</a> 子在a链接里

    因此要展示ul,且在a链接中设置字体颜色,编写js

       <script type="text/javascript">
               // 省略// 当前页面所在的那个超链接red:color
                // 它的父list-group-item tree-closed是没有的
                // 找到当前页面的a链接
                // 使用css为某个元素加样式 list-group-item
                $("a[href='${ctp }/permission/user/list']").css("color", "red");
                $("a[href='${ctp }/permission/user/list']").parent(".list-group-item").removeClass("tree-closed");
                $("a[href='${ctp }/permission/user/list']").parent().parent("ul").show(100);
        
    
            </script>

     还要设置最上面的导航栏

    在nav-bar.jsp中改为

     <div><a class="navbar-brand" style="font-size:32px;" href="#">众筹平台 - ${navinfo }</a></div>

     在user.jsp中添加这个navinfl变量

    <body>
            <%pageContext.setAttribute("navinfo", "用户维护"); %>
      ...

    同理在需要该变量的各个页面设置即可

    
    

    抽取页面显示效果

    我们想各个页面都是菜单展开,当前菜单红色的设置,因此将共同的显示效果进行抽取

    把js抽取抽来存放到common-js.jsp

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <script>
    changePageStyle("${curUrl }");
    function changePageStyle(url) {
        //只有超链接在变化
         $("a[href='${ctp }/"+url+"']").css("color", "red");
         $("a[href='${ctp }/"+url+"']").parent(".list-group-item").removeClass("tree-closed");
         $("a[href='${ctp }/"+url+"']").parent().parent("ul").show(100);
    }
    </script>

    user.jsp中使用时只需要

    设置curUrl并引入该jsp文件

     <%
              pageContext.setAttribute("navinfo", "用户维护");
              pageContext.setAttribute("curUrl", "permission/user/list");
            %>
    ...
    <%@include file="/WEB-INF/includes/common-js.jsp" %>

    <%@include file="/WEB-INF/includes/common-js.jsp" %>要插在<script>标签以外

    三、带查询条件的分页

    是一个form表单

    指定action,表单提交的方向

    指定提交方式为post

    <form class="form-inline" role="form" style="float:left;" action="${ctp }/permission/user/list" method="post">
      <div class="form-group has-feedback">
        <div class="input-group">
          <div class="input-group-addon">查询条件</div>
          <input class="form-control has-success" 
          type="text" name="sp"
          placeholder="请输入查询条件">
        </div>
      </div>
      <button type="submit" class="btn btn-warning"><i class="glyphicon glyphicon-search"></i> 查询</button>
    </form>

    controller

     @RequestMapping("/list")
        public String users(@RequestParam(value = "pn", defaultValue = "1") Integer pn,
                @RequestParam(value = "ps", defaultValue = "10") Integer ps, Model model,
                @RequestParam(value = "searchParam", defaultValue = "") String search) {
            // 有表单提交,防止重复提交,建议额外写一个转发方法重定向到页面
            // 没有表单提交就直接转发到目标页面
            // 分页获取用户的逻辑
            System.out.println("分页获取用户的逻辑");
            PageHelper.startPage(pn, ps);
            // 拿到分页查出的结果,不带条件的
            // List<TUser> list = userService.getAll();
            // 带条件的查询,将条件作为用户名或用户昵称的查询条件
            // select * from t_user where loginacct like ? or username=?
    
            // 第一次创建的条件,默认使用and连接
            TUserExample example = new TUserExample();
            Criteria criteria1 = example.createCriteria();
            Criteria criteria2 = example.createCriteria();
            if (!search.trim().equals("")) {
                criteria1.andLoginacctLike("%" + search + "%");
                criteria2.andUsernameLike("%" + search + "%");
            }
            example.or(criteria2);
            List<TUser> list = userService.getAllByCondition(example);
    
            // 去页面显示的数据
            PageInfo<TUser> info = new PageInfo<TUser>(list, 5);
            model.addAttribute("user_info", info);
            for (TUser tUser : list) {
                System.out.println(tUser);
            }
    
            // 直接转到页面
            return "manager/permission/user";
        }

    service层定义方法

    接口

    public interface UserService {
    
        public boolean register(TUser user);
    
        public TUser login(TUser user);
    
        public List<TUser> getAll();
    
        public List<TUser> getAllByCondition(TUserExample example);
    }

    实现类

      public List<TUser> getAllByCondition(TUserExample example) {
    
            return userMapper.selectByExample(example);
        }

    存在的问题是:查询条件不能回显,且当切换页面的时候,重新回到了不查询的状态,即查询状态无法维持

    原因:当换页的时候,每个页的按钮都有转向的url,现在的url没有查询参数,因此切换的时候不会带查询条件

    解决:给分页超链接绑上单击事件

    // 为所有分页连接绑定单击事件,让其动态带上分页查询参数
                $(".pagination").find("a").click(function(){
                    // 1.获取查询表单的查询参数
                    //$("input[name='searchParam']").val();
                    // 不禁用默认行为,而是为超链接多拼装上查询条件
                    // 为超链接动态拼上查询条件
                    var href = $(this).attr("href")+"&sp="+$("input[name='sp']").val();
                    $(this).attr("href", href);
                    
                });

    回显

    controller里添加

     model.addAttribute("sp", search);

    往前端传递search,名字为sp

    查询框添加value

      <input class="form-control has-success" 
          type="text" name="sp"
          placeholder="请输入查询条件" value=${sp }>

    四、批量删除

    首先实现全选全不选

    user.jsp

    <div class="table-responsive">
                <table class="table  table-bordered">
                  <thead>
                    <tr >
                      <th width="30">#</th>
                      <th width="30"><input id="checkall_btn" type="checkbox"></th>
                      <th>账号</th>
                      <th>名称</th>
                      <th>邮箱地址</th>
                      <th width="100">操作</th>
                    </tr>
                  </thead>
                  <tbody>
                  <c:forEach items="${user_info.list}" var="user">
                    <tr>
                    <!-- varStatus="" 当前遍历的所有信息,索引 -->
                    <!-- 取出用户的实际ID -->
                      <td>${user.id }</td>
                      <td><input type="checkbox" class="single_check"></td>
                      <td>${user.loginacct }</td>
                      <td>${user.username }</td>
                      <td>${user.email }</td>
                      <td>
                          <button type="button" class="btn btn-success btn-xs"><i class=" glyphicon glyphicon-check"></i></button>
                          <button type="button" class="btn btn-primary btn-xs"><i class=" glyphicon glyphicon-pencil"></i></button>
                          <button type="button" class="btn btn-danger btn-xs"><i class=" glyphicon glyphicon-remove"></i></button>
                      </td>
                    </tr>
                   </c:forEach>
                  </tbody>

    js实现全选

    放在common-js.jsp中

    // 做全选全不选功能
    // 传入全选按钮对象
    function check_reverse(check_all_btn, check_btn) {
        check_all_btn.click(function(){
            // 如果是原生的属性,使用prop获取比较好
            var flag = $(this).prop("checked");
            check_btn.prop("checked", $(this).prop("checked"))                    
        });
        check_btn.click(function(){
            // 当check_btn点满以后check_all_btn勾上,否则不选中
            // 获取被选中的checkbtn个数
            var flag = check_btn.filter(":checked").length == check_btn.length;
            check_all_btn.prop("checked", flag);
        });
    }

    删除

    在user.jsp中获得id,并拼接成url

    button的class设置为deleteAllBtn

    js处理该button的点击

    ...
    <button type="button" class="btn btn-danger deleteAllBtn" style="float:right;margin-left:10px;">
    <i class=" glyphicon glyphicon-remove">
    </i> 删除</button>
    
    ...
    
     check_reverse($("#checkall_btn"), $(".single_check"));
                $(".deleteAllBtn").click(function () {
                    // 点击删除按钮,先拿到要删除的所有员工的id
                    var delUrl = "${ctp}/permission/user/del?ids="
                    var ids = "";
                    $(".single_check:checked").each(function () {
                        // 取出自定义的id属性
                        ids += $(this).attr("del_id")+","; // 1,2,3,
                    })
                    //剔除最后一个逗号 1,2,3
                    delUrl += ids.substring(0, ids.length-1);
                    //让浏览器访问这个删除链接
                    if(confirm("确认删除【"+ids+"】这些员工吗?")){
                        location.href = delUrl;
                    }
                    return false;
                });

    转到controller里进行处理

    package com.atguigu.scw.manager.controller.permission;
    
    //处理所有/permission/user下的请求
    @RequestMapping("/permission/user")
    @Controller
    public class UserController {
    
        private final String MANAGER_MAIN = "manager/main";
        @Autowired
        UserService userService;
    
        /**
                 * 用户删除
         */
        @RequestMapping("/del")
        public String userDelete(@RequestParam(value = "ids", defaultValue = "") String ids) {
            if (!ids.trim().equals("")) {
    
                userService.deleteBatchOrSingle(ids);
    
            }
            // 删除完成重新查询所有数据
            return "redirect:/permission/user/list";
        }
    
        /**
         * 用户列表页面显示
         * 
         * @Description (TODO这里用一句话描述这个方法的作用)
         * @return
         */
        @RequestMapping("/list")
        public String users(@RequestParam(value = "pn", defaultValue = "1") Integer pn,
                @RequestParam(value = "ps", defaultValue = "10") Integer ps, Model model,
                @RequestParam(value = "sp", defaultValue = "") String search) {
            // 省略
        }
    
        @RequestMapping("/login")
        public String login(TUser user, HttpSession session) {
            // 省略
        }
    
        // /permission/user/reg
        @RequestMapping("/reg")
        public String reg(TUser user, Model model, HttpSession session) {
            // 省略
        }
    }
    userService接口增加deleteBatchOrSingle(ids)方法

    接口

    public interface UserService {
    
        public boolean register(TUser user);
    
        public TUser login(TUser user);
    
        public List<TUser> getAll();
    
        public List<TUser> getAllByCondition(TUserExample example);
    
        public void deleteBatchOrSingle(String ids);
    }

    实现类中实现方法

       public void deleteBatchOrSingle(String ids) {
    
            if (ids.contains(",")) {
                String[] split = ids.split(",");
                List<Integer> list = new ArrayList<Integer>();
                for (String s : split) {
                    int i = 0;
                    try {
                        i = Integer.parseInt(s);
                    } catch (NumberFormatException e) {
                    }
                    list.add(i);
                }
                TUserExample example = new TUserExample();
                Criteria criteria = example.createCriteria();
                // 删除id所在的集合
                criteria.andIdIn(list);
                userMapper.deleteByExample(example);
            } else {
                userMapper.deleteByPrimaryKey(Integer.parseInt(ids));
            }
        }

    五、角色分配页面

    从用户页面点击分配角色,来到分配角色页面,左侧是未分配角色列表,右侧是已分配角色列表

    数据库角色

    user.jsp配置下分配权限按钮

     <tbody>
                  <c:forEach items="${user_info.list}" var="user">
                    <tr>
                    <!-- varStatus="" 当前遍历的所有信息,索引 -->
                    <!-- 取出用户的实际ID -->
                      <td>${user.id }</td>
                      <td><input type="checkbox" class="single_check" del_id=${user.id }></td>
                      <td>${user.loginacct }</td>
                      <td>${user.username }</td>
                      <td>${user.email }</td>
                      <td>
                          <button u_id="${user.id }" type="button" class="btn btn-success btn-xs assignBtn">
                          <i class=" glyphicon glyphicon-check"></i></button>
                          <button type="button" class="btn btn-primary btn-xs">
                          <i class=" glyphicon glyphicon-pencil"></i></button>
                          <button type="button" class="btn btn-danger btn-xs">
                          <i class=" glyphicon glyphicon-remove"></i></button>
                      </td>
                    </tr>
                   </c:forEach>
                  </tbody>

    js

      // 点击权限分配来到权限分配页面
                $(".assignBtn").click(function(){
                    // 必须将用户id带给后台 自定义用attr
                    var id = $(this).attr("u_id");
                    // 去权限列分配页面
                    var url = "${ctp}/permission/user/toAssignRole?uid="+id;
                    location.href=url;
                })

    location.href

    自定义属性

    定义响应/permission/user/toAssignRole的controller

    UserController中添加

        @Autowired
        RoleService roleService;


    // 去权限分配页面 @RequestMapping("/toAssignRole") public String toAssignRolePage(@RequestParam(value = "uid") Integer uid, Model model) { System.out.println("要去权限分配页面,用户id:" + uid); // 1.查出所有权限 List<TRole> roles = roleService.getAllRole(); // 2.查出当前用户拥有的权限 // List<TRole> userRole = roleService.getUserRole(uid); Map<Integer, TRole> map = new HashMap<Integer, TRole>(); for (TRole tRole : userRole) { map.put(tRole.getId(), tRole); } // 3.用户未分配权限 List<TRole> unRoles = new ArrayList<TRole>(); for (TRole tRole : roles) { if (!map.containsKey(tRole.getId())) { // 用户已拥有的权限 unRoles.add(tRole); } } model.addAttribute("unroles", unRoles); model.addAttribute("roles", userRole); // 来到权限分配页 return "manager/permission/assignRole"; }

    定义RoleService接口

    package com.atguigu.scw.manager.service;
    
    import java.util.List;
    
    import com.atguigu.scw.manager.bean.TRole;
    
    public interface RoleService {
    
        public List<TRole> getAllRole();
    
        public List<TRole> getUserRole(Integer userId);
    }

    实现方法

    package com.atguigu.scw.manager.service.impl;
    
    import java.util.List;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    import com.atguigu.scw.manager.bean.TRole;
    import com.atguigu.scw.manager.dao.TRoleMapper;
    import com.atguigu.scw.manager.service.RoleService;
    
    @Service
    public class RoleServiceImpl implements RoleService {
    
        @Autowired
        TRoleMapper roleMapper;
    
        public List<TRole> getAllRole() {
    
            return roleMapper.selectByExample(null);
        }
    
        public List<TRole> getUserRole(Integer userId) {
            // select t.id,t.name from t_role t left join t_user_role u_r ON t.`id`=u_r.`roleid`
            // left join t_user u on u. `id`=u_r.`userid`
            // WHERE u.`id`=?
    
            return roleMapper.getUserRole(userId);
        }
    }

    TRoleMapper.xml中增加自己以方法

    <select id="getUserRole" resultMap="BaseResultMap">
             select t.id,t.name from t_role t left join t_user_role u_r ON t.`id`=u_r.`roleid`
             left join t_user u on u.`id`=u_r.`userid`
             where u.`id`=#{uid}
      </select>

    连接查询

    select 我们本意要查的字段from这个表

    left join 其他表 on a 关联表

    跳转到assignRole.jsp

    <div class="panel panel-default">
                  <div class="panel-body">
                    <form role="form" class="form-inline">
                      <div class="form-group">
                        <label for="exampleInputPassword1">未分配角色列表</label><br>
                        <select class="form-control unroles" multiple size="10" style="100px;overflow-y:auto;">
                          <c:forEach items="${unroles }" var="role">
                            <option value="${role.id }">${role.name }</option>
                           
                          </c:forEach>
                        </select>
                      </div>
                      <div class="form-group">
                            <ul>
                                <li class="btn btn-default glyphicon glyphicon-chevron-right"></li>
                                <br>
                                <li class="btn btn-default glyphicon glyphicon-chevron-left" style="margin-top:20px;"></li>
                            </ul>
                      </div>
                      <div class="form-group" style="margin-left:40px;">
                        <label for="exampleInputPassword1">已分配角色列表</label><br>
                        <select class="form-control roles_select" multiple size="10" style="100px;overflow-y:auto;">
                            <c:forEach items="${roles }" var="role">
                            <option value="${role.id }">${role.name }</option>
                           
                          </c:forEach>
                  
                        </select>
                      </div>
                    </form>
                  </div>
                </div>

    分别对应

     

    js

     $(".glyphicon-chevron-right").click(function () {
                    
                    var rids = ""
                        $(".unroles :selected").each(function(){
                            rids += $(this).val()+",";
                        });
                    // 去掉最后的,
                    rids = rids.substring(0, rids.length-1);
                    
                    
                    // 选中的添加到权限中
                    // 发送请求给后台,数据库完成操作
                    // 必须带上权限id的拼串和userid
                        var uid = "${param.uid }"    
                        $.get("${ctp }/permission/user/assignrole?opt=add&uid="+uid+"&rids="+rids,function(){
                            // 选中并且分配成功的过去
                            $(".unroles :selected").appendTo(".roles_select");
                        })
                    });
                    
                $(".glyphicon-chevron-left").click(function () {
                    var uid = "${param.uid }"
                    var rids = ""
                        $(".roles_select :selected").each(function(){
                            rids += $(this).val()+",";
                        });
                    // 去掉最后的,
                    rids = rids.substring(0, rids.length-1);
                    
                    // 发送请求移除
                     $.get("${ctp }/permission/user/assignrole?opt=remove&uid="+uid+"&rids="+rids,function(){
                    //显示移除的效果 
                    $(".roles_select :selected").appendTo(".unroles");
                     });
                });

    EL表达式${param.xxx}可以从url中获取参数放在页面中直接使用

    比如:一个网址:127.0.0.1/test/testparam?test1=3&test2=sss

    用${param.test1}就可以直接获取到test1的值,也就是3

    用${param.test2}就可以直接获取到test2的值,也就是sss

    ${param.xxx} 就等价于 request.getparam("xxx"),也就是服务器从页面或者客户端获取的内容

    定义响应/permission/user/assignrole的controller

    控制器处理请求:

    查出当前用户为拥有的权限

    查出当前用户已拥有的权限

    查出的结果放在页面

     UserController中添加

        @Autowired
        UserRoleService urService;
    
        // 添加角色 如果返回值为空,默认请求地址就会当成页面地址
        // public void UserRole(@RequestParam("rids") String rids, @RequestParam("uid") Integer uid) {
        // 加@ResponseBody注解后,return "成功!"相当于out.write("成功")
        @ResponseBody
        @RequestMapping("/assignrole")
        public String UserRole(@RequestParam("rids") String rids, @RequestParam("uid") Integer uid,
                @RequestParam("opt") String opt) {
            if ("add".equals(opt)) {
                // 为某个用户添加一些角色
                urService.addRole(rids, uid);
                System.out.println("成功");
            } else if ("remove".equals(opt)) {
                // 移除角色
                urService.removeRole(rids, uid);
                System.out.println("删除完成");
            }
    
            return "";
        }

    创建接口,实现方法

    package com.atguigu.scw.manager.service;
    
    public interface UserRoleService {
    
        // 给用户添加角色
        public void addRole(String ids, Integer userId);
    
        // 移除用户的某些角色
        public void removeRole(String ids, Integer userId);
    }

    实现方法

    package com.atguigu.scw.manager.service.impl;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    import com.atguigu.scw.manager.bean.TUserRole;
    import com.atguigu.scw.manager.bean.TUserRoleExample;
    import com.atguigu.scw.manager.bean.TUserRoleExample.Criteria;
    import com.atguigu.scw.manager.dao.TUserRoleMapper;
    import com.atguigu.scw.manager.service.UserRoleService;
    
    @Service
    public class UserRoleServiceImpl implements UserRoleService {
    
        @Autowired
        TUserRoleMapper userRoleMapper;
    
        public void addRole(String ids, Integer userId) {
            // 没有包含逗号,直接添加
            if (ids.contains(",")) {
                String[] split = ids.split(",");
                for (String rid : split) {
                    // 创建一个中间表的数据对象
                    TUserRole role = new TUserRole();
    
                    int i = Integer.parseInt(rid);
                    role.setRoleid(i);
                    role.setUserid(userId);
                    userRoleMapper.insertSelective(role);
                }
            } else {
                TUserRole role = new TUserRole();
                int i = Integer.parseInt(ids);
                role.setRoleid(i);
                role.setUserid(userId);
                userRoleMapper.insertSelective(role);
            }
        }
    
        public void removeRole(String ids, Integer userId) {
            if (ids.contains(",")) {
                String[] split = ids.split(",");
                for (String rid : split) {
                    int i = Integer.parseInt(rid);
                    TUserRoleExample example = new TUserRoleExample();
                    Criteria criteria = example.createCriteria();
                    criteria.andRoleidEqualTo(i);
                    criteria.andUseridEqualTo(userId);
                    userRoleMapper.deleteByExample(example);
                }
            } else {
    
                int i = Integer.parseInt(ids);
                TUserRoleExample example = new TUserRoleExample();
                Criteria criteria = example.createCriteria();
                criteria.andRoleidEqualTo(i);
                criteria.andUseridEqualTo(userId);
                userRoleMapper.deleteByExample(example);
            }
        }
    
    }

    六、角色维护

    新建控制器

     t_permission

     role.jsp设置导航栏、菜单等

    先把分页部分做好

    tbody

    tfoot

                                    <tbody>
                                        <c:forEach items="${role_info.list }" var="role">
                                            <tr>
                                                <td>${role.id }</td>
                                                <td><input type="checkbox"></td>
                                                <td>${role.name }</td>
                                                <td>
                                                    <button type="button" rid="${role.id }"
                                                        class="btn btn-success btn-xs assignPermissionModelBtn">
                                                        <i class=" glyphicon glyphicon-check"></i>
                                                    </button>
                                                    <button type="button" class="btn btn-primary btn-xs">
                                                        <i class=" glyphicon glyphicon-pencil"></i>
                                                    </button>
                                                    <button type="button" class="btn btn-danger btn-xs">
                                                        <i class=" glyphicon glyphicon-remove"></i>
                                                    </button>
                                                </td>
                                            </tr>
                                        </c:forEach>
    
                                    </tbody>
                                    <tfoot>
                                        <tr>
                                            <td colspan="6" align="center">
                                                <ul class="pagination">
                                                    <!-- 即使点击分页连接也应该带上查询条件的值 -->
                                                    <!-- 给分页超链接绑定单击事件; -->
                                                    <li><a href="${ctp}/permission/role/list?pn=1">首页</a></li>
                                                    <c:if test="${role_info.hasPreviousPage}">
                                                        <li><a
                                                            href="${ctp}/permission/role/list?pn=${role_info.prePage}">上一页</a></li>
                                                    </c:if>
    
                                                    <!-- 遍历连续显示的页面 navigatepageNums : int[]-->
                                                    <c:forEach items="${role_info.navigatepageNums}" var="pn">
                                                        <c:if test="${pn == role_info.pageNum }">
                                                            <li class="active"><a
                                                                href="${ctp}/permission/role/list?pn=${pn}">${pn } <span
                                                                    class="sr-only">(current)</span></a></li>
                                                        </c:if>
                                                        <c:if test="${pn != role_info.pageNum }">
                                                            <li><a href="${ctp}/permission/role/list?pn=${pn}">${pn }</a></li>
                                                        </c:if>
                                                    </c:forEach>
    
                                                    <c:if test="${role_info.hasNextPage}">
                                                        <li><a
                                                            href="${ctp}/permission/role/list?pn=${role_info.nextPage}">下一页</a></li>
                                                    </c:if>
                                                    <li><a
                                                        href="${ctp}/permission/role/list?pn=${role_info.pages}">末页</a></li>
                                                </ul>
                                            </td>
                                        </tr>
    
                                    </tfoot>

    RoleContrller里写处理逻辑

    package com.atguigu.scw.manager.controller.permission;
    
    // 处理角色维护模块
    @RequestMapping("/permission/role")
    @Controller
    public class RoleController {
    
        @Autowired
        RoleService roleService;
        // 来到角色维护页面
        @RequestMapping("/list")
        public String toRolePage(@RequestParam(value = "pn", defaultValue = "1") Integer pn,
                @RequestParam(value = "ps", defaultValue = "10") Integer ps, Model model,
                @RequestParam(value = "sp", defaultValue = "") String search) {
            PageHelper.startPage(pn, ps);
            List<TRole> role = roleService.getAllRole();
            PageInfo<TRole> info = new PageInfo<TRole>(role, 5); // 连续显示5页
            model.addAttribute("role_info", info);
            
            return "manager/permission/role";
        }
    }

    bootstrap的模态框

    在模态框里展示权限树

    <!-- 模态框 -->
        <div class="modal fade" id="permissModel" tabindex="-1" role="dialog"
            aria-labelledby="myModalLabel">
            <div class="modal-dialog" role="document">
                <div class="modal-content">
                    <div class="modal-header">
                        <button type="button" class="close" data-dismiss="modal"
                            aria-label="Close">
                            <span aria-hidden="true">&times;</span>
                        </button>
                        <h4 class="modal-title" id="myModalLabel">分配权限</h4>
                    </div>
                    <div class="modal-body">
                        <!-- 展示权限树 -->
                        <div>
                            <ul id="permissionTree" class="ztree"></ul>
                        </div>
                    </div>
                    <div class="modal-footer">
                        <button type="button" class="btn btn-default" data-dismiss="modal">关闭</button>
                        <button type="button" class="btn btn-primary" id="addPermissionBtn">分配权限</button>
                    </div>
                </div>
            </div>
        </div>

     js

    ztree的js和cs文件放入cs-file.jsp、js-file.jsp

    //保存ztree对象的
            var ztreeObject;
            //用户角色分配权限-
            //点击按钮-打开模态框-查出所有的权限-在模态框中树形显示-将当前用户拥有的权限选中
            /* $("tbody .btn-success").click(function() {
                window.location.href = "assignPermission.html";
            }); */
            //点击分配权限按钮,
            //模态框的按钮
            
            $(".assignPermissionModelBtn").click(function() {
                var options = {
                    backdrop : 'static',
                    show : true
                }
    
                //"permissionTree"刷出权限树
                //js的this会经常飘逸
                initPermissionTree($(this).attr("rid"));
                //getUser(1)
                //勾选当前角色的权限
                //打开模态框
                $('#permissModel').modal(options);
                //将角色id保存到模态框的哪个属性中;
               
            });
    
            //treeId:是权限树ul的id
            //treeNode:当前节点信息
            function showIcon(treeId, treeNode) {
                //console.log(treeId);
                //treeNode里面有一个tId;
                //这个tid用来拼串以后就是图标显示位置的元素id和名字显示位置的元素id
                //tId:"permissionTree_3"
                //<span id="permissionTree_2_span">用户维护</span>
                //<span id="permissionTree_2_ico" ></span>
                //console.log(treeNode);
                //改图标;找到当前元素图标显示的节点,将这个节点的class设置为当前节点的icon
                $("#" + treeNode.tId + "_ico").removeClass()
                        .addClass(treeNode.icon);
            }
    
       function initPermissionTree(rid) {
                var setting = {
                    data : {
                        simpleData : {
                            enable : true,
                            idKey : "id",
                            pIdKey : "pid",
                        },
                        key : {
                            url : "haha"
                        }
                    },
                    view : {
                        //自定义显示的效果
                        addDiyDom : showIcon
                    },
                    check : {
                        enable : true
                    }
                };
    
                //从数据库查出的所有权限节点数据
                //发送ajax请求获取到所有权限的json数据
                $.getJSON("${ctp}/permission/role/json", function(nodes) {
                    //console.log(nodes);
                    //给每一个节点修改或者添加一些属性
                    $.each(nodes, function() {
                        if (this.pid == 0) {
                            this.open = true;
                        }
                    })
                    //如果不是用var声明的变量,这个变量就默认变为全局的
                    //把初始化好的ztree对象传递给外界使用,可以通用操作这个对象,来改变树
                    //ztree为了不影响下面的操作是异步展示数据的
                    ztreeObject = $.fn.zTree.init($("#permissionTree"), setting,
                            nodes);
                    checkcurPermisson(rid);
                })
            }

     RoleController处理

    // 处理角色维护模块
    @RequestMapping("/permission/role")
    @Controller
    public class RoleController {
    
        @Autowired
        RoleService roleService;
        
        @Autowired
        TPermissionService permissionService;
    
        // 返回所有权限的json数据
        // 返回所有权限的list
        @ResponseBody
        @RequestMapping("/json")
        public List<TPermission> getAllPermission() {
            // 返回所有的权限
            return  permissionService.getPermissions();
        }
        
        
        // 来到角色维护页面
        @RequestMapping("/list")
        public String toRolePage(@RequestParam(value = "pn", defaultValue = "1") Integer pn,
                @RequestParam(value = "ps", defaultValue = "10") Integer ps, Model model,
                @RequestParam(value = "sp", defaultValue = "") String search) {
            PageHelper.startPage(pn, ps);
            List<TRole> role = roleService.getAllRole();
            PageInfo<TRole> info = new PageInfo<TRole>(role, 5); // 连续显示5页
            model.addAttribute("role_info", info);
    
            return "manager/permission/role";
        }
        
        
        
    }

    TPermissionService接口添加方法,并实现

    package com.atguigu.scw.manager.service.impl;
    
    
    @Service
    public class TPermissionServiceImpl implements TPermissionService {
    
        @Autowired
        TPermissionMapper mapper;
    
        public List<TPermission> getAllMenus() {
            // 省略
        }
    
        public List<TPermission> getPermissions() {
            
            return mapper.selectByExample(null);
        }
    
    }

     

    七、分配权限

     已有的权限应该打勾

    控制器里增加

     RoleController

       // /permission/role/perm/4
        @ResponseBody
        @RequestMapping("/perm/{id}")
        public List<TPermission> getRolePermission(@PathVariable("id")Integer rid) {
            List<TPermission> permissions = permissionService.getRolePermission(rid);
            return permissions;
        }
        

    接口中增加方法,并实现该方法

    package com.atguigu.scw.manager.service;
    

    public interface TPermissionService { // 拿到所有菜单 public List<TPermission> getAllMenus(); public List<TPermission> getPermissions(); public List<TPermission> getRolePermission(Integer rid); }

    实现方法

      // 查询角色对应的权限
        public List<TPermission> getRolePermission(Integer rid) {
            return mapper.getRolePermission(rid);
    
        }

    TPermissionMapper中增加查询方法

    List<TPermission> getRolePermission(Integer rid);

    实现

     配置mybatis的mapper文件

    TPermissionMapper.xml

     <!-- List<TPermission> getRolePermission -->
      <select id="getRolePermission" resultMap="BaseResultMap">
          SELECT p.* FROM t_permission p
          LEFT JOIN t_role_permission rp ON rp.`permissionid`=p.`id`
          WHERE rp.`roleid`=#{rid}
      </select>

    js

    <script type="text/javascript">
            $(function() {
                $(".list-group-item").click(function() {
                    if ($(this).find("ul")) {
                        $(this).toggleClass("tree-closed");
                        if ($(this).hasClass("tree-closed")) {
                            $("ul", this).hide("fast");
                        } else {
                            $("ul", this).show("fast");
                        }
                    }
                });
            });
        
            //保存ztree对象的
            var ztreeObject;
            //用户角色分配权限-
            //点击按钮-打开模态框-查出所有的权限-在模态框中树形显示-将当前用户拥有的权限选中
            /* $("tbody .btn-success").click(function() {
                window.location.href = "assignPermission.html";
            }); */
            //点击分配权限按钮,
            //模态框的按钮
            $("#addPermissionBtn").click(function(){
                //1、获取当前我们已经选中的权限
                var nodes = ztreeObject.getCheckedNodes(true);
                //2、将这些权限的id和角色的id发给程序
                var permission_ids = "";
                $.each(nodes,function(){
                    permission_ids += this.id+",";
                });
                var rid = $(this).attr("rid");
                //3、使用程序保存这个角色对应的权限的值
                //写程序;删除对应的东西即可
                $.get("${ctp}/permission/role/update?pids="+permission_ids+"&rid="+rid,function(){
                    alert("权限分配成功");
                    $('#permissModel').modal("hide");
                })
            });
            
            $(".assignPermissionModelBtn").click(function() {
                var options = {
                    backdrop : 'static',
                    show : true
                }
    
                //"permissionTree"刷出权限树
                //js的this会经常飘逸
                initPermissionTree($(this).attr("rid"));
                //getUser(1)
                //勾选当前角色的权限
                //打开模态框
                $('#permissModel').modal(options);
                //将角色id保存到模态框的哪个属性中;
                //打开模态框将角色id传递给model里面的权限分配按钮
                $('#addPermissionBtn').attr("rid",$(this).attr("rid"));
            });
    
            //treeId:是权限树ul的id
            //treeNode:当前节点信息
            function showIcon(treeId, treeNode) {
                //console.log(treeId);
                //treeNode里面有一个tId;
                //这个tid用来拼串以后就是图标显示位置的元素id和名字显示位置的元素id
                //tId:"permissionTree_3"
                //<span id="permissionTree_2_span">用户维护</span>
                //<span id="permissionTree_2_ico" ></span>
                //console.log(treeNode);
                //改图标;找到当前元素图标显示的节点,将这个节点的class设置为当前节点的icon
                $("#" + treeNode.tId + "_ico").removeClass()
                        .addClass(treeNode.icon);
            }
    
            ///传入角色id,将当前角色拥有的权限勾选
            function checkcurPermisson(rid) {
                //   /permission/role/perm/4
                $.getJSON("${ctp}/permission/role/perm/" + rid, function(data) {
                    //查出的当前角色拥有的权限
                    //ztree对象的方法;checkNode;
                    //三个参数:
                    //第一个参数就是要勾选的节点
                    //第二个参数就是勾选与否
                    //第三个参数是是否和父节点级联互动
                    //第四个参数是勾选状态变化后,是否调用之前用(callback)规定的回调函数
                    $.each(data, function() {
                        //console.log(this);
                        //从ztree中获取到要勾选的对象;
                        var node = ztreeObject.getNodeByParam("id", this.id, null);
                        ztreeObject.checkNode(node, true, false);
                    })
                })
            }
    
            function initPermissionTree(rid) {
                var setting = {
                    data : {
                        simpleData : {
                            enable : true,
                            idKey : "id",
                            pIdKey : "pid",
                        },
                        key : {
                            url : "haha"
                        }
                    },
                    view : {
                        //自定义显示的效果
                        addDiyDom : showIcon
                    },
                    // 图标前的选中框开启
                    check : {
                        enable : true
                    }
                };
    
                //从数据库查出的所有权限节点数据
                //发送ajax请求获取到所有权限的json数据
                $.getJSON("${ctp}/permission/role/json", function(nodes) {
                    //console.log(nodes);
                    //给每一个节点修改或者添加一些属性 父菜单pid为0
                    $.each(nodes, function() {
                        if (this.pid == 0) {
                            this.open = true;
                        }
                    })
                    //如果不是用var声明的变量,这个变量就默认变为全局的
                    //把初始化好的ztree对象传递给外界使用,可以通用操作这个对象,来改变树
                    //ztree为了不影响下面的操作是异步展示数据的
                    ztreeObject = $.fn.zTree.init($("#permissionTree"), setting, nodes);
                    checkcurPermisson(rid);
                })
            }
        </script>

     分配权限数据读取

    <div class="modal-footer">
         <button type="button" class="btn btn-default" data-dismiss="modal">关闭</button>
         <button type="button" class="btn btn-primary" id="addPermissionBtn">分配权限</button>
    </div>
    //点击分配权限按钮,
            //模态框的按钮
            $("#addPermissionBtn").click(function(){
                //1、获取当前我们已经选中的权限
                var nodes = ztreeObject.getCheckedNodes(true);
                //2、将这些权限的id和角色的id发给程序
                var permission_ids = "";
                $.each(nodes,function(){
                    permission_ids += this.id+",";
                });
                var rid = $(this).attr("rid");
                //3、使用程序保存这个角色对应的权限的值
          
                })
            });
            
            $(".assignPermissionModelBtn").click(function() {
                var options = {
                    backdrop : 'static',
                    show : true
                }
    
                //"permissionTree"刷出权限树
                //js的this会经常飘逸
                initPermissionTree($(this).attr("rid"));
                //getUser(1)
                //勾选当前角色的权限
                //打开模态框
                $('#permissModel').modal(options);
                //将角色id保存到模态框的哪个属性中;
                //打开模态框将角色id传递给model里面的权限分配按钮
                $('#addPermissionBtn').attr("rid",$(this).attr("rid"));
            });

     更新角色权限

    RoleController

    package com.atguigu.scw.manager.controller.permission;
    // 处理角色维护模块
    @RequestMapping("/permission/role")
    @Controller
    public class RoleController {
    
        @Autowired
        RoleService roleService;
    
        @Autowired
        TPermissionService permissionService;
    
        /**
                 *  更新角色权限
         * 1.先删除当前角色的所有权限
         * 2.在新增之前选中的所有权限
         */
        @ResponseBody // ajax请求
        @RequestMapping("/update")
        public String deleteRolePermission(@RequestParam("pids")String pids,
                @RequestParam("rid")Integer rid) {
            boolean flag = permissionService.updatePermission(pids, rid);
            return "ok";
        }
        
       // 省略
    
    }

    接口增加上面方法,实现该方法

    package com.atguigu.scw.manager.service;
    
    import java.util.List;
    
    import com.atguigu.scw.manager.bean.TPermission;
    
    public interface TPermissionService {
    
        // 拿到所有菜单
        public List<TPermission> getAllMenus();
    
        public List<TPermission> getPermissions();
    
        public List<TPermission> getRolePermission(Integer rid);
    
        public boolean updatePermission(String pids, Integer rid);
    }

    实现方法

    package com.atguigu.scw.manager.service.impl;
    
    @Service
    public class TPermissionServiceImpl implements TPermissionService {
    
        @Autowired
        TPermissionMapper mapper;
    
        @Autowired
        TRolePermissionMapper rolePermissionMapper;
        
       // 省略
    
        public boolean updatePermission(String pids, Integer rid) {
    
            // 1.删除当前角色的所有权限
            TRolePermissionExample example = new TRolePermissionExample();
            Criteria criteria = example.createCriteria();
            criteria.andRoleidEqualTo(rid);
            rolePermissionMapper.deleteByExample(example);
            // 2.新增
            String[] split = pids.split(",");
            if (split != null && split.length>=1) {
                for (String pid : split) {
                    int i = Integer.parseInt(pid);
                    TRolePermission permission = new TRolePermission();
                    // 设置角色id
                    permission.setRoleid(rid);
                    // 设置权限id
                    permission.setPermissionid(i);
                    // 保存角色权限关系
                    rolePermissionMapper.insertSelective(permission);
                }
                return true;
            }
            return false;
        }
    
    }

    js

    $("#addPermissionBtn").click(function(){
                //1、获取当前我们已经选中的权限
                var nodes = ztreeObject.getCheckedNodes(true);
                //2、将这些权限的id和角色的id发给程序
                var permission_ids = "";
                $.each(nodes,function(){
                    permission_ids += this.id+",";
                });
                var rid = $(this).attr("rid");
                //3、使用程序保存这个角色对应的权限的值
                //写程序;删除对应的东西即可
                $.get("${ctp}/permission/role/update?pids="+permission_ids+"&rid="+rid,function(){
                    alert("权限分配成功");
                    $('#permissModel').modal("hide");
                })
            });

    后续完成

    几个同类的增删改查:

    1.项目分类 每个项目属于一类 类别的增删改查

    2.项目标签(目前做独立的)

    每个分类下有一些标签,小分类(spu)

    和分类没联系

     经常使用的技巧:

    1)抽取页面

    2)利用某个按钮获取某个元素设置自定义属性来给回调函数带值

    <button uid="${user.id}"></button>

    $("#btn").click(function(){

    // 用户id

    $(this).attr("uid")

    })

    3)给某个元素绑定属性值

    绑定:jQuery.data(element,[key],[value])

    获取: 当前jQuery对象.key

    4)写一个功能的流程:

    • 从登陆注册写起
    • 具体某一个功能,分清楚整个跳转逻辑
    • 搭出整个跳转流程
    • 分析执行功能要给服务器带什么数据       想尽办法把页面带给服务器的数据组装好
    • 服务器 收到数据进行增删改查分析       原则:能用mbg生成的dao自带的CRUD就用自带的,不能就给这个dao新增方法
    • 梳理清楚流程,脑海中必须有实现出的最终效果
  • 相关阅读:
    Python3基础 str swapcase 英文字母大小写反转
    Python3基础 str split 用指定的字符将字符串分割
    Python3基础 str partition 以参数字符串切分字符串,只切分为三部分
    Python3基础 str lstrip 去掉字符串左边的空格
    Python3基础 str format 输出花括号{}
    Python3基础 str format 位置参数与关键字参数
    Python3基础 str format 四舍六入五凑偶 保留一位小数
    Python3基础 str for 输出字符串中的每个字符
    Python3基础 str find+index 是否存在指定字符串,有则返回第一个索引值
    Python3基础 str endswith 是否以指定字符串结束
  • 原文地址:https://www.cnblogs.com/aidata/p/11488665.html
Copyright © 2020-2023  润新知