• SSM实战-复选框(checkbox)多标签分类的添加、标签回显与修改


    引言:在一些业务场景,我们会遇到这个问题,比如一个商品或者一个源码有多个标签,根据不同的标签可以查询到对应的源码或者商品?一个学生需要使用复选框选择多个兴趣爱好?那么我们该如何实现这个多标签添加、以及标签回显、修改问题呢?

    本次我们以SSM框架、MySQL数据库、IDEA开发工具为背景,来实现这个功能,由于在这个基础上开发设计,我们主要写核心的功能模块,不一定要按照的我的这个框架和开发工具,只要是SSM或者SPringBoot即可。

    演示视频

    SSM实战-演示多标签复选框的回显、修改功能

    效果图先展示

    首页
    在这里插入图片描述
    添加
    在这里插入图片描述
    实现功能:复选框的添加、回显、修改
    在这里插入图片描述
    修改复选框
    在这里插入图片描述

    实现思路:一个三个实体,label(标签)、code(源码)、labelcode(中间表),需要做一个中间表来存储标签的主键,源码的编号,为什么这里存储源码的主键呢 ,因为在添加标签的时候这个源码的主键无法添加的,因为是数据库自动生成的,所以需要由工具类生成一个源码编号。
    在添加源码的时候先把所有的标签查询出来,然后添加源码的时候把这些标签添加到中间表里面去,这样形成了关联,属于一个多对多的关系。
    修改的时候,比较难实现,这个时候就要使用jquery了,可见jquery的重要性,使用ajax先把所有的标签查询出来,然后清空选中,再根据源码编号查询中间表这个源码相同的源码编号的标签,也就是这个源码选中的标签,来进行比对,如果选中了,就进行回显。修改的时候注意把中间表的原来关联的删掉,然后再新增。

    数据库表设计

    标签表设计
    在这里插入图片描述
    中间表设计
    在这里插入图片描述
    源码表设计

    这个源码表是我做的一个例子,仅供参考,按照你要做的功能来进行设计。
    在这里插入图片描述

    添加、修改表单

    <%@ page language="java" contentType="text/html; charset=UTF-8"
    	pageEncoding="UTF-8"%>
    <%@ page trimDirectiveWhitespaces="true"%>
    <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
    
    <%
    	String path = request.getContextPath();
    	String basePath = request.getScheme() + "://" + request.getServerName() 
    	                   + ":" + request.getServerPort() + path + "/";
    %>
    
    
    <!DOCTYPE html>
    <html>
    <head>
    	<meta charset="utf-8">
    	<title>源码客栈后台系统</title>
    	<meta name="renderer" content="webkit">
    	<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    	<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=0">
    	<link rel="stylesheet" href="${pageContext.request.contextPath}/resource/layuiadmin/layui/css/layui.css" media="all">
    	<link rel="stylesheet" href="${pageContext.request.contextPath}/resource/layuiadmin/style/admin.css" media="all">
    </head>
    <body>
    
    <div class="layui-fluid">
    	<div class="layui-row layui-col-space15">
    		<div class="layui-col-md9">
    
    
    
    			<div class="layui-card">
    				<div class="layui-card-header">${empty param.id?"发布源码":"编辑源码"}</div>
    				<div class="layui-card-body">
    					<span class="msg" style="color:red;">${requestScope.msg}</span>
    					<form class="layui-form"  action="${pageContext.request.contextPath}${empty param.id ?"/code/add.action":"/code/update.action"}" method="post">
    						<div class="layui-row layui-col-space10 layui-form-item">
    
    							<input type="hidden" name="id" id="id"  value="${record.id}">
    							<input type="hidden" name="codeNo" id="codeNo"   value="${record.code_no}">
    							<input type="hidden" name="a_id"   value="${admin.id}">
    							
    							<div class="layui-col-lg3">
    								<label class="layui-form-label">源码分类:</label>
    								<div class="layui-input-block">
    
    									<select name="category_id" lay-verify="required" lay-filter="aihao">
    										<c:if test="${requestScope.categoryList!=null}">
    											<c:forEach items="${requestScope.categoryList}" var="category">
    												<option value="${category.id}" <c:if test="${category.id==record.category_id}">selected</c:if> >${category.name}</option>
    											</c:forEach>
    										</c:if>
    									</select>
    								</div>
    							</div>
    							
    
    						
    
    
    
    				
    
    
    						</div>
    						<div class="layui-row layui-col-space10 layui-form-item">
    						<div class="layui-form-item">
    							<label class="layui-form-label">复选框</label>
    							<div class="layui-input-block" id="checkid">
    								
    							</div>
    						</div>
    						</div>
    
    
    						
    
    						
    
    					
    
    
    					
    
    
    
    						<div class="layui-form-item">
    							<div class="layui-input-block">
    								<button class="layui-btn" type="submit"  id="add" >${empty param.id ?"发布":"修改"}</button>
    
    
    									<button type="button" onclick="location.href='/code/pageList.action'" class="layui-btn layui-btn-normal">返回</button>
    
    								<button type="reset" class="layui-btn layui-btn-primary">重置</button>
    							</div>
    						</div>
    					</form>
    				</div>
    			</div>
    		</div>
    	</div>
    </div>
    
    
    <script src="${pageContext.request.contextPath}/resource/layuiadmin/layui/layui.js"></script>
    <script src="${pageContext.request.contextPath}/resource/js/jquery-3.3.1.js"></script>
    
    <script>
    
    	var id = $("#id").val();
    	if(id != null && id != ""){
    		selectIsCheckList();
    	}
    	init();
    
    	var checkList = null;
    
    	function selectIsCheckList(){
    
    		var codeNo = $("#codeNo").val();
    		$.ajax({
    			cache : true,
    			type : "post",
    			url : "/code/selectLabelByCodeNo",
    			data : {"codeNo":codeNo},
    			async : false,
    			success : function(data) {
    				if (data) {
    					checkList = data;
    				} else {
    					alert("查询失败!");
    				}
    			}
    		})
    
    	}
    	//这里是核心区,霹提供
    	function init(){
    		$("#checkid").html("");
    		var html = "";
    		$.ajax({
    			cache : true,
    			type : "post",
    			url : "/code/selectAllLabel",
    			//data : {"fid":fid},
    			async : false,
    			success : function(data) {
    				if (data) {
    					if(data.length>0){
    
    						var html = "";
    						for(var i=0 ;i <data.length;i++){
    							var re = 0;
    							if(checkList!=null){
    								for(var j=0;j<checkList.length;j++){
    									if(checkList[j].label_id == data[i].id ){
    										re = 1;
    									}
    								}
    
    								if(re == 1){
    									html += "<input type='checkbox' name='label_id' checked value='"+data[i].id+"'title='"+data[i].lname+"'/>";
    								}else{
    									html += "<input type='checkbox' name='label_id' value='"+data[i].id+"'title='"+data[i].lname+"'/>";
    								}
    							}else{
    								html += "<input type='checkbox' name='label_id' value='"+data[i].id+"'title='"+data[i].lname+"'/>";
    							}
    						}
    						$("#checkid").append(html);
    					}
    				} else {
    					alert("查询失败!");
    				}
    			}
    		})
    
    
    	}
    
    </script>
    
    
    
    </body>
    </html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186

    接口层

    //Label接口
    public interface LabelService {
        public List<Label> getLabelList();
    
       
    }
    
    
    //LabelCodeService接口
    public interface LabelCodeService {
    
        public List<LabelCode> getLabelId(String code_no);
        public  boolean addLabelCode(LabelCode r);
        public boolean deleteByCodeNo(String code_no);
    }
    
    
    //CodeService接口
    public interface CodeService {
        public  boolean addCode(Code r);
        public  boolean updateCode(Code r);
    }
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    Mapper层

    这个是核心的查询方法,根据源码编号查询中间表的里的标签信息(包括了ID),其他的增删改查的就不写了,自己根据自己的SSM框架来设计

     <select id="selectByLabelId" parameterType="com.website.entity.Code" resultMap="BaseResultMap">
      /*   select * from t_code where id in (select code_id from  t_label_code where label_id = '1' )*/
      select
      *
      from t_code
      where   code_no in (select code_no from  t_label_code where label_id = #{label_Id,jdbcType=INTEGER} )
      </select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
      <delete id="deleteByCodeNo" parameterType="java.lang.String">
        delete from t_label_code
        where code_no = #{code_no,jdbcType=VARCHAR}
      </delete>
    
    • 1
    • 2
    • 3
    • 4

    实现层

    实现层,可以自己编写,不一定要看我的

    //标签实现层
    @Service
    @Transactional
    public class LabelServiceImpl implements LabelService {
        @Autowired
        private LabelMapper mapper;
        @Override
        public List<Label> getLabelList() {
            return mapper.selectByExample(null);//查询所有
        }
        }
    
       public List<LabelCode> getLabelCodeList() {
            return mapper.selectByExample(null);//查询所有
        }
      //中间表实体实现层。我这里使用的是自动生成的拼写规则根据源码编号查询,看不懂这种写法的请使用自己原来写的查询方法即可
        @Override
        public List<LabelCode> getLabelId(String code_no) {
            LabelCodeExample example = new LabelCodeExample();
            LabelCodeExample.Criteria criteria = example.createCriteria();
             if(StringUtils.isNoneBlank(code_no)){
                    criteria.andCode_noEqualTo(code_no);
                }
    
            List<LabelCode> list = mapper.selectByExample(example);//第2步
    
    
            return list;
        }
    
    //这里是源码的实现层
     @Override
        public boolean addCode(Code record) {
            return mapper.insertSelective(record) > 0 ? true : false;
        }
    
        @Override
        public boolean updateCode(Code record) {
            return mapper.updateByPrimaryKeySelective(record) > 0 ? true : false;
        }
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    控制层

    源码编号生成

    	public static  String getCodeNo() {//生成源码编号
    		  SimpleDateFormat sdf=new SimpleDateFormat("yyyyMMddHHmmss");
    	      String newDate=sdf.format(new Date());
    	      String result="";
    	      Random random=new Random();
    	      for(int i=0;i<2;i++){
    	          result+=random.nextInt(5);
    	      }
    	      return newDate+result;
    	    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    控制层我们主要写CodeController里面的

    import java.sql.Timestamp;
    import java.util.Date;
    import java.util.List;
    @RequestMapping(value = "/code/add.action",method = RequestMethod.POST,produces = "text/html;charset=UTF-8")
        @ResponseBody
        public String add(Code record,HttpServletRequest request){
           Date date = new Date();
            // 得到一个Timestamp格式的时间,存入mysql中的时间格式“yyyy/MM/dd HH:mm:ss”
            Timestamp timeStamp = new Timestamp(date.getTime());
            record.setCreate_time(timeStamp);
            record.setSee_count(0);
             String[] labels=request.getParameterValues("label_id");//获取选中的复选框
             String code_no=WebUtils.getCodeNo();//生成复选框编号
             record.setCode_no(code_no);
             for(String label_id:labels ){//for循环插入中间表,把选到的标签依次插入中间表,同时查询源码编号进行关联
                 //插入标签
                 System.out.println(label_id);
                 LabelCode labelCode=new LabelCode();
                 labelCode.setCode_no(code_no);
                 labelCode.setLabel_id(Integer.parseInt(label_id));
                 labelCodeService.addLabelCode(labelCode);
             }
            if(service.addCode(record)){
                return "<script>location.href='/code/pageList.action';</script>";
                //return "<script>alert('添加成功');location.href='/client/findMyInfo.action';</script>";
            }else{
                return "<script>alert('添加失败');history.go(-1);</script>";
            }
    
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    主要回显实现的是其他的信息。

        //去编辑界面
        @RequestMapping(value = "/code/query.action")
        public String toUpdatecode(Integer id,Model model,Map map){
            System.out.println(id+"******");
            Code record=service.findById(id);
    
           if(null!=record){
               model.addAttribute("record",record);
           }
    
            return "code/edit";
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    这里是核心地区,在编辑页面先把所有的标签查询出来,然后在中间表查询源码里面已经选择了的复选框的标签

    
    
    
        //通过编号查询关联的label
        @RequestMapping(value = "/code/selectAllLabel")
        @ResponseBody
        public  List<Label> selectAllLabel(String codeNo){
            List<Label> labelList=ls.getLabelList();
            return labelList;
        }
    
    
        //通过编号查询关联的label
        @RequestMapping(value = "/code/selectLabelByCodeNo")
        @ResponseBody
        public  List<LabelCode> selectLabelByCodeNo(String codeNo){
    
            List<LabelCode> labelCodeList= labelCodeService.getLabelId(codeNo);
            return labelCodeList;
        }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
         @RequestMapping(value = "/code/update.action",method = RequestMethod.POST,produces = "text/html;charset=UTF-8")
        @ResponseBody
        public String update(Code record,HttpServletRequest request){
            Code c=service.findById(record.getId());
            String filename=c.getPhoto();
            WebUtils.deleteImg(filename);
            String[] labels=request.getParameterValues("label_id");
            
            //修改标签前先删掉原来的中间表关联
          labelCodeService.deleteByCodeNo(c.getCode_no());
               for(String label_id:labels ){
                   //插入标签
                   System.out.println(label_id);
                   LabelCode labelCode=new LabelCode();
                   labelCode.setCode_no(c.getCode_no();
                   labelCode.setLabel_id(Integer.parseInt(label_id));
                   labelCodeService.addLabelCode(labelCode);
               }
    
    
            if(service.updateCode(record)){
                return "<script>alert('修改成功');location.href='/code/pageList.action';</script>";
            }else{
                return "<script>alert('修改失败');history.go(-1);</script>";
            }
    
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    备注:如果需要源码文件,请关注微信公众号:逛逛Java主窗口回复口令fj01领取相关源码文件
    在这里插入图片描述

  • 相关阅读:
    React基础教程:TodoList案例
    基于vue+node+MySQL的导航可视化系统webapp设计
    DSPE-PEG-Silane,DSPE-PEG-SIL,磷脂-聚乙二醇-硅烷修饰二氧化硅颗粒用
    从0开始刷力扣
    PCL点云自定义裁剪的两种思路
    AI语音机器人的重点功能配置之话术
    h5和微信小程序实现拍照功能(其中h5暂时无法调用闪光灯)
    TCP/IP Illustrated Episode 6
    mysql配置项整理
    一文读懂js中的原型链以及new操作符
  • 原文地址:https://blog.csdn.net/liqz666/article/details/125537416