目录
一、前言
1.什么是表格
2.表格的使用范围
二、案例实现
1.案例分析
①根据需求找到文档源码
②查询结果在实体中没有该属性
2.dao层编写
①BaseDao工具类
②UserDao编写
3.Servlet编写
①R工具类的介绍
②Useraction编写
4.jsp页面搭建
①userManage.jsp
②userEdit.jsp
③userManage.js
④userEdit.js
5.案例效果演示
①查询
②新增
③修改
④删除
一、前言
Layui之动态选项卡&iframe使用(附源码)
在上一次前端框架Layui分享选项卡的使用中,可以看到点击左侧右侧找不到路径(因为还未编写),所以这次基于上次的内容进行编写对用户管理页面进行增删改查操作。
因为这里的url页面我项目中还没有编写,所以404是必然的,不用管他!!!
1.什么是表格
表格(Table)是Web开发中常用的一种数据展示方式,用于以行和列的形式呈现结构化数据。表格由单元格(cell)组成,每个单元格可以包含文本、图像、链接等内容。
HTML中的表格通过<table>标签来定义,<tr>表示表格的行,<td>表示表格的单元格。可以使用<th>标签定义表格的表头(header)。
下面是一个简单的HTML表格示例:
<table><tr><th>姓名</th><th>年龄</th></tr><tr><td>小明</td><td>20</td></tr><tr><td>小红</td><td>22</td></tr> </table>
在这个示例中,表格有两列(姓名和年龄),第一行是表头,下面两行是数据行。每个单元格中的内容被包含在<td>标签中,而表头单元格则使用<th>标签。
通过使用表格,我们可以清晰地组织和显示大量的数据,例如展示员工列表、商品价格表、课程时间表等。可以使用CSS对表格进行样式化,调整表格的边框样式、背景颜色、字体样式等,以满足特定的设计要求。
需要注意的是,在使用表格时,应根据具体的需求选择合适的数据结构和布局方式。在某些情况下,使用表格可能不是最佳的解决方案,可以考虑使用其他的数据展示方式,例如列表、卡片布局等。
2.表格的使用范围
表格在Web开发中被广泛应用于不同场景,以下是一些表格的常见使用范围:
- 1. 数据展示:表格是一种常见的数据展示形式,适用于展示结构化的数据集合。例如,可以使用表格展示面向用户的数据,如员工列表、产品目录、订单信息等。
- 2. 数据分析:表格可以用于以表格形式展示、比较和分析数据。通过对表格进行排序、过滤和计算,可以更好地理解和解读数据。数据分析工具和报表系统通常使用表格来呈现结果。
- 3. 排名和比较:表格可以用于比较不同项的属性或指标,从而进行排名和排序。例如,可以使用表格展示运动员的成绩排名、学生的考试成绩等。表格可以根据特定的字段对数据进行排序,方便查找和对比。
- 4. 表单输入:表格常用于用户输入和编辑数据的场景。例如,可以使用表格来创建注册表单、调查问卷等。每个表格单元格可以包含各种输入字段(如文本框、复选框、下拉菜单等),方便用户输入和提交数据。
- 5. 日程安排和时间表:表格可以用于展示日程安排、课程时间表、会议日程等。每个单元格可以表示一个时间段,每一行代表一个时间点或一个实体(如人员、地点等)。
- 6. 响应式布局:表格可以通过CSS和响应式设计技术进行适应性布局,使其在不同屏幕尺寸下保持良好的显示效果。通过使用滚动、隐藏列、自适应宽度等功能,可以在小屏幕设备上显示较大的表格。
需要注意的是,在使用表格时应考虑数据的复杂性和可读性。对于大型数据集或复杂的数据结构,可以使用分页、筛选和搜索功能来改善用户体验。另外,合理地使用样式和交互效果可以提升表格的可用性和美观性。
二、案例实现
1.案例分析
①根据需求找到文档源码
Layui
这一次我们运用的组件是表格所以在官网中找到想要的组件内容进行“cv”操作即可。
②查询结果在实体中没有该属性
我们可以观察到表中有字段rid(角色身份),但是数据展示的时候需要将数字转换成相对应的字符,所以我们查询表的时候就要追加一个字段用来显示角色身份,但是我们eclipse的实体中并没有该属性,如果再写一个的以后遇到这种问题还是需要进行编写比较麻烦,所以我们可以采用Map集合的方式进行保存数据。
跟多细节在编写过程中慢慢讲解,下面请欣赏小编所写代码!!!
2.dao层编写
①BaseDao工具类
package com.zking.util;import java.lang.reflect.Field; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map;/*** 所有Dao层的父类 BookDao UserDao OrderDao ...* * @author Administrator** @param <T>*/ public class BaseDao<T> {/*** 适合多表联查的数据返回* @param sql* @param pageBean* @return* @throws SQLException* @throws InstantiationException* @throws IllegalAccessException*/public List<Map<String, Object>> executeQuery(String sql, PageBean pageBean)throws SQLException, InstantiationException, IllegalAccessException {List<Map<String, Object>> list = new ArrayList<>();Connection con = DBAccess.getConnection();PreparedStatement pst = null;ResultSet rs = null;/** 是否需要分页? 无需分页(项目中的下拉框,查询条件教员下拉框,无须分页) 必须分页(项目中列表类需求、订单列表、商品列表、学生列表...)*/if (pageBean != null && pageBean.isPagination()) {// 必须分页(列表需求)String countSQL = getCountSQL(sql);pst = con.prepareStatement(countSQL);rs = pst.executeQuery();if (rs.next()) {pageBean.setTotal(String.valueOf(rs.getObject(1)));}// 挪动到下面,是因为最后才处理返回的结果集// -- sql=SELECT * FROM t_mvc_book WHERE bname like '%圣墟%'// -- pageSql=sql limit (page-1)*rows,rows 对应某一页的数据// -- countSql=select count(1) from (sql) t 符合条件的总记录数String pageSQL = getPageSQL(sql, pageBean);// 符合条件的某一页数据pst = con.prepareStatement(pageSQL);rs = pst.executeQuery();} else {// 不分页(select需求)pst = con.prepareStatement(sql);// 符合条件的所有数据rs = pst.executeQuery();}// 获取源数据ResultSetMetaData md = rs.getMetaData();int count = md.getColumnCount();Map<String, Object> map = null;while (rs.next()) {map = new HashMap<>();for (int i = 1; i <= count; i++) { // map.put(md.getColumnName(i), rs.getObject(i));map.put(md.getColumnLabel(i), rs.getObject(i));}list.add(map);}return list;}/*** * @param sql* @param attrs* map中的key* @param paMap* jsp向后台传递的参数集合* @return* @throws SQLException* @throws NoSuchFieldException* @throws SecurityException* @throws IllegalArgumentException* @throws IllegalAccessException*/public int executeUpdate(String sql, String[] attrs, Map<String, String[]> paMap) throws SQLException,NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {Connection con = DBAccess.getConnection();PreparedStatement pst = con.prepareStatement(sql);for (int i = 0; i < attrs.length; i++) {pst.setObject(i + 1, JsonUtils.getParamVal(paMap, attrs[i]));}return pst.executeUpdate();}/*** 批处理* @param sqlLst* @return*/public static int executeUpdateBatch(String[] sqlLst) {Connection conn = null;PreparedStatement stmt = null;try {conn = DBAccess.getConnection();// 设置不自动提交conn.setAutoCommit(false);for (String sql : sqlLst) {stmt = conn.prepareStatement(sql);stmt.executeUpdate();}conn.commit();} catch (Exception e) {try {conn.rollback();} catch (SQLException e1) {e1.printStackTrace();throw new RuntimeException(e1);}e.printStackTrace();throw new RuntimeException(e);} finally {DBAccess.close(conn, stmt, null);}return sqlLst.length;}/*** 通用的增删改方法* * @param book* @throws Exception*/public int executeUpdate(String sql, T t, String[] attrs) throws Exception {// String[] attrs = new String[] {"bid", "bname", "price"};Connection con = DBAccess.getConnection();PreparedStatement pst = con.prepareStatement(sql);// pst.setObject(1, book.getBid());// pst.setObject(2, book.getBname());// pst.setObject(3, book.getPrice());/** 思路: 1.从传进来的t中读取属性值 2.往预定义对象中设置了值* * t->book f->bid*/for (int i = 0; i < attrs.length; i++) {Field f = t.getClass().getDeclaredField(attrs[i]);f.setAccessible(true);pst.setObject(i + 1, f.get(t));}return pst.executeUpdate();}/*** 通用分页查询* * @param sql* @param clz* @return* @throws Exception*/public List<T> executeQuery(String sql, Class<T> clz, PageBean pageBean) throws Exception {List<T> list = new ArrayList<T>();Connection con = DBAccess.getConnection();;PreparedStatement pst = null;ResultSet rs = null;/** 是否需要分页? 无需分页(项目中的下拉框,查询条件教员下拉框,无须分页) 必须分页(项目中列表类需求、订单列表、商品列表、学生列表...)*/if (pageBean != null && pageBean.isPagination()) {// 必须分页(列表需求)String countSQL = getCountSQL(sql);pst = con.prepareStatement(countSQL);rs = pst.executeQuery();if (rs.next()) {pageBean.setTotal(String.valueOf(rs.getObject(1)));}// 挪动到下面,是因为最后才处理返回的结果集// -- sql=SELECT * FROM t_mvc_book WHERE bname like '%圣墟%'// -- pageSql=sql limit (page-1)*rows,rows 对应某一页的数据// -- countSql=select count(1) from (sql) t 符合条件的总记录数String pageSQL = getPageSQL(sql, pageBean);// 符合条件的某一页数据pst = con.prepareStatement(pageSQL);rs = pst.executeQuery();} else {// 不分页(select需求)pst = con.prepareStatement(sql);// 符合条件的所有数据rs = pst.executeQuery();}while (rs.next()) {T t = clz.newInstance();Field[] fields = clz.getDeclaredFields();for (Field f : fields) {f.setAccessible(true);f.set(t, rs.getObject(f.getName()));}list.add(t);}return list;}/*** 将原生SQL转换成符合条件的总记录数countSQL* * @param sql* @return*/private String getCountSQL(String sql) {// -- countSql=select count(1) from (sql) t 符合条件的总记录数return "select count(1) from (" + sql + ") t";}/*** 将原生SQL转换成pageSQL* * @param sql* @param pageBean* @return*/private String getPageSQL(String sql, PageBean pageBean) {// (this.page - 1) * this.rows// pageSql=sql limit (page-1)*rows,rowsreturn sql + " limit " + pageBean.getStartIndex() + "," + pageBean.getRows();} }
小贴士:
结合上面的案例需求,这里重构了executeQuery,可以发现这里的返回值不再是集合实体而是list集合里面存放Map集合,这样就算来再多字段我们也不用重新编写我们的实体类,直接调用该方法,利用Map进行存储即可。
②UserDao编写
package com.xw.dao;import java.util.List; import java.util.Map;import com.xw.entity.User; import com.zking.util.BaseDao; import com.zking.util.PageBean; import com.zking.util.StringUtils;/*** 用户* * @author 索隆**/ public class UserDao extends BaseDao<User> {// 分页模糊查询public List<User> list(User user, PageBean pageBean) throws Exception {// sql语句编写String sql = "select * from t_oa_user where 1=1";// 获取参数long id = user.getId();String name = user.getName();// 进行参数非空判断if (StringUtils.isNotBlank(name)) {sql += " and name like '%" + name + "%'";}// 如果bid不等于0说明传递过来了bid,此时的bid是有值的if (id != 0) {sql += "and id=" + id;}return super.executeQuery(sql, User.class, pageBean);}// 新增public int add(User User) throws Exception {int n=0;// sql语句编写String sql = "insert into t_oa_user (name,loginName,pwd)values(?,?,?)";n = super.executeUpdate(sql, User, new String[] { "name", "loginName", "pwd" });return n;}// 删除public int del(User User) throws Exception {// sql语句编写String sql = "delete from t_oa_user where id=?";return super.executeUpdate(sql, User, new String[] { "id" });}// 修改public int edit(User User) throws Exception {// sql语句编写String sql = "update t_oa_user set name=?,loginName=?,pwd=? where id=?";return super.executeUpdate(sql, User, new String[] { "name", "loginName", "pwd", "id" });}// 登录校验public User login(User User) throws Exception {// sql语句编写String sql = "select * from t_oa_user where loginName='" + User.getLoginName() + "' and pwd='" + User.getPwd()+ "' ";List<User> list = super.executeQuery(sql, User.class, null);if (list != null && list.size() == 1) {return list.get(0);} else {return null;}}//不包含原表字段的分页模糊查询public List<Map<String, Object>> userRole(User user, PageBean pageBean) throws Exception {// sql语句编写String sql = "select u.*,\r\n" + "(CASE \r\n" + " WHEN u.rid='1' THEN '管理员'\r\n" + " WHEN u.rid='2' THEN '发起者'\r\n" + " WHEN u.rid='3' THEN '审批者'\r\n" + " WHEN u.rid='4' THEN '参与者'\r\n" + " WHEN u.rid='5' THEN '会议室管理员'\r\n" + "\r\n" + " ELSE\r\n" + " '其他'\r\n" + "END ) rname\r\n" + "from t_oa_user u WHERE 1=1";// 获取参数String name = user.getName();// 进行参数非空判断if (StringUtils.isNotBlank(name)) {sql += " and name like '%" + name + "%'";}return super.executeQuery(sql,pageBean);}}
注意:这里的返回就是已经重构的executeQuery不要搞混了哦!!
3.Servlet编写
①R工具类的介绍
我们可以查看官网的表格内容显示的JSON格式是什么样子的,发现有以上几个属性:
code,msg,count,data
- code:只能填写“0”(别人的Layui规则)
- mag:没实际含义,可随意填写
- count:查询到的条数
- data:实体内容
我们想要在页面显示数据,那么就必须要满足它的JSON格式,我们就可以利用R工具类来简化我们的代码,不然每次遇到这种场景就需要手动创建Map集合然后.put添加属性的方式造数据。
package com.zking.util;import java.util.HashMap;public class R extends HashMap{public R data(String key, Object value) {this.put(key, value);return this;}public static R ok(int code, String msg) {R r = new R();r.data("success", true).data("code", code).data("msg", msg);return r;}public static R error(int code, String msg) {R r = new R();r.data("success", false).data("code", code).data("msg", msg);return r;}public static R ok(int code, String msg,Object data) {R r = new R();r.data("success", true).data("code", code).data("msg", msg).data("data", data);return r;}public static R ok(int code, String msg, long count, Object data) {R r = new R();r.data("success", true).data("code", code).data("msg", msg).data("count", count).data("data", data);return r;} }
这里也重构了和多次ok的方法,方便我们利用于不同的场景。
②Useraction编写
package com.xw.web;import java.util.List; import java.util.Map;import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession;import com.xw.entity.User; import com.xw.dao.UserDao; import com.zking.framework.ActionSupport; import com.zking.framework.ModelDriver; import com.zking.util.PageBean; import com.zking.util.R; import com.zking.util.ResponseUtil;public class Useraction extends ActionSupport implements ModelDriver<User> {User user = new User();UserDao userdao = new UserDao();/*** 登录验证* * @param req* @param resp* @throws Exception*/public void login(HttpServletRequest req, HttpServletResponse resp) throws Exception {User login = userdao.login(user);// 保存域对象if (login != null) {HttpSession session = req.getSession();session.setAttribute("user", login);}ResponseUtil.writeJson(resp, login);}/*** 注册新增用户* * @param req* @param resp* @throws Exception*/public void register(HttpServletRequest req, HttpServletResponse resp) throws Exception {int i = userdao.add(user);if (i > 0) {ResponseUtil.writeJson(resp, i);} else {ResponseUtil.writeJson(resp, null);}}/**带分类管理的模糊查询* @param req* @param resp* @throws Exception*/public void UserRole(HttpServletRequest req, HttpServletResponse resp) throws Exception {// 初始化pageBeanPageBean pageBean = new PageBean();pageBean.setRequest(req);//调用带分页查询的方法List<Map<String, Object>> userRole = userdao.userRole(user, pageBean);//利用R工具类制造出符合要求的json格式数据ResponseUtil.writeJson(resp, R.ok(0, "查询成功", pageBean.getTotal(), userRole));}/**删除用户* @param req* @param resp* @throws Exception*/public void del(HttpServletRequest req, HttpServletResponse resp) throws Exception {//调用删除的方法int del = userdao.del(user);//利用R工具类制造出符合要求的json格式数据ResponseUtil.writeJson(resp, R.ok(0, "删除成功"));}/**修改用户* @param req* @param resp* @throws Exception*/public void edit(HttpServletRequest req, HttpServletResponse resp) throws Exception {//调用修改的方法int del = userdao.edit(user);//利用R工具类制造出符合要求的json格式数据ResponseUtil.writeJson(resp, R.ok(0, "修改成功"));}/**新增用户* @param req* @param resp* @throws Exception*/public void add(HttpServletRequest req, HttpServletResponse resp) throws Exception {//调用新增的方法int del = userdao.add(user);//利用R工具类制造出符合要求的json格式数据ResponseUtil.writeJson(resp, R.ok(0, "新增成功"));}@Overridepublic User getModel() {return user;}}
4.jsp页面搭建
一定要注意我们的层级结构
①userManage.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%><%@ include file="/common/static.jsp"%> <!DOCTYPE> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>用户管理</title> <script type="text/javascript" src="static/js/system/userManage.js"></script> </head><body> <!-- 搜索栏 --><div class="layui-form-item"><div class="layui-inline"><label class="layui-form-label">用户名:</label><div class="layui-input-inline"><input type="text" id="name" placeholder="请输入用户名" autocomplete="off" class="layui-input"></div></div><div class="layui-inline"><div class="layui-input-inline"><button id="btn_search" type="button" class="layui-btn layui-btn-normal"><i class="layui-icon layui-icon-search"></i>查询</button><button id="btn_add" type="button" class="layui-btn">新增</button></div></div></div><table class="layui-hide" id="test" lay-filter="test"></table><script type="text/html" id="barDemo"><a class="layui-btn layui-btn-xs" lay-event="edit">编辑</a><a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del">删除</a> </script><script></script></body> </html>
②userEdit.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%> <%@ include file="/common/static.jsp"%> <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <script type="text/javascript" src="static/js/system/userEdit.js"></script> <title>用户新增</title> </head> <style> .layui-form-select dl{max-height:150px; } </style> <body> <div style="padding:10px;"><form class="layui-form layui-form-pane" lay-filter="user"><input type="hidden" name="id"/><div class="layui-form-item"><label class="layui-form-label">用户名称</label><div class="layui-input-block"><input type="text" id="name" name="name" autocomplete="off" placeholder="请输入用户名" class="layui-input"></div></div><div class="layui-form-item"><label class="layui-form-label">用户角色</label><div class="layui-input-block"><select name="rid"><option value="">---请选择---</option><option value="1">管理员</option><option value="2">发起者</option><option value="3">审批者</option><option value="4">参与者</option><option value="5">会议管理员</option></select></div></div><div class="layui-form-item"><label class="layui-form-label">登录账号</label><div class="layui-input-block"><input type="text" name="loginName" lay-verify="required" placeholder="请输入账号" autocomplete="off" class="layui-input"></div></div><div class="layui-form-item"><label class="layui-form-label">登录密码</label><div class="layui-input-block"><input type="password" name="pwd" placeholder="请输入密码" autocomplete="off" class="layui-input"></div></div></form> </div> </body> </html>
将JSP页面的逻辑代码分离
③userManage.js
var table,$,layer; var row;layui.use(['table','jquery','layer'], function(){table = layui.table,layer=layui.layer,$=layui.jquery;initTable();//为查询按钮设置点击事件$("#btn_search").click(function(){query();})//为新增按钮设置点击事件$("#btn_add").click(function(){row=null;edit('新增');})});//新增/修改的点击事件 function edit(title){layer.open({type: 2, //layer提供了5种层类型。可传入的值有:0(信息框,默认)1(页面层)2(iframe层)3(加载层)4(tips层)title:title,area: ['660px', '340px'], //宽高skin: 'layui-layer-rim', //样式类名content: 'jsp/system/userEdit.jsp', //书本编辑页面btn:['保存','关闭'],yes: function(index, layero){//调用子页面中提供的getData方法,快速获取子页面的form表单数据let data= $(layero).find("iframe")[0].contentWindow.getData();console.log(data);//判断title标题let methodName="add";if(title=="编辑")methodName="edit";$.post('user.action?methodName='+methodName,data,function(rs){if(rs.success){//关闭对话框layer.closeAll();//调用查询方法刷新数据query();}else{layer.msg(rs.msg,function(){});}},'json');},btn2: function(index, layero){layer.closeAll();}}); }//查询的点击事件 function query(){//表格的重载table.reload('test', {where: { //设定异步数据接口的额外参数,任意设name: $("#name").val()}//默认limit需要改成我们自己工具类的名字,request: {pageName: 'page ' //页码的参数名称,默认:page,limitName: 'rows' //每页数据量的参数名,默认:limit}}); //只重载数据 }//将分页查询方法封装 function initTable(){table.render({elem: '#test',url:'user.action?methodName=UserRole',toolbar: '#toolbarDemo' //开启头部工具栏,并为其绑定左侧模板,defaultToolbar: ['filter', 'exports', 'print', { //自定义头部工具栏右侧图标。如无需自定义,去除该参数即可title: '提示',layEvent: 'LAYTABLE_TIPS',icon: 'layui-icon-tips'}],title: '用户数据表',cols: [[{type: 'checkbox', fixed: 'left'},{field:'id', title:'ID', width:80, fixed: 'left', unresize: true, sort: true},{field:'loginName', title:'账户名', width:120, edit: 'text'},{field:'name', title:'真实姓名', width:150, edit: 'text', templet: function(res){return '<em>'+ res.name +'</em>'}},{field:'pwd', title:'密码', width:80, edit: 'text', sort: true},{field:'rname', title:'身份', width:100},{fixed: 'right', title:'操作', toolbar: '#barDemo', width:150}]],page: true});//监听行工具事件table.on('tool(test)', function(obj){row = obj.data;if(obj.event === 'del'){layer.confirm('确认删除吗?', {icon: 3, title:'提示'}, function(index){$.post('user.action',{'methodName':'del','id':row.id},function(rs){if(rs.success){//调用查询方法刷新数据query();}else{layer.msg(rs.msg,function(){});}},'json');layer.close(index);});} else if(obj.event === 'edit'){edit('编辑');}}); }
④userEdit.js
let layer,form,$; layui.use(['layer','form','jquery'],function(){layer=layui.layer,form=layui.form,$=layui.jquery;initData(); });function initData(){console.log(parent.row);if(null!=parent.row){//因为layui.each内部的逻辑问题导致的所以要先深拷贝一份然后再去val//parent.row:表格行对象form.val('user',$.extend({}, parent.row||{}));$('#name').attr('readonly','readonly');} }function getData(){return form.val('user'); }
5.案例效果演示
①查询
②新增
③修改
④删除
到这里我的分享就结束了,欢迎到评论区探讨交流!!
如果觉得有用的话还请点个赞吧 ♥ ♥