继0730,我们对项目做最后的升级
一、删除功能
1、新增复选框辅助删除条目的选择
修改我们的list.jsp和list.js在列表的第一列增加一列选择框
2、给复选框添加全选与行点击选择功能
在行选择功能中,因为此时的选择框还未生成,所以我们将事件委托给他的父类“#tab”
//全选与取消全选
$("#checkAll").click(function (){
let checked = $(this).prop("checked");
$("#tab>tbody>tr>td:first-child>:checkbox").prop("checked",checked);
});
//点击行选中 事件委托
$("#tab").on("click","tr>td:not(:first-child)",function (){
let $tr = $(this).parent();
const $chk = $tr.children().first().children()
const check = $chk.prop("checked");
$chk.prop("checked",!check);
})
3、给删除按钮添加事件
let $checked = $("#tab tr>td:first-child>:checked")获取当前全部被选择的选择框的状态,如果存在选中,使用layer.confirm创建一个带有“确定”和“取消”按钮的确认对话框。
通过.each将$checked中的每个data-id值都存到ids中,将ids传给函数delectById.
//删除按钮事件
$("#del").click(function (){
let $checked = $("#tab tr>td:first-child>:checked")
//console.log($checked);
if($checked.length === 0){
layer.msg("请选择要删除的学生");
}else{
layer.confirm("你确定你要删除选中的行吗", function (handler){
//删除所有选中的行
let ids = [];
$checked.each(function (idx,item){
console.log(idx,item);
ids.push(parseInt($(item).attr("data-id")));
});
console.log(ids);
deleteByIds(ids, function (count){
if(count>0){
layer.msg("成功删除"+count+"行数据");
findAll(currentPage,limits);
}else{
layer.msg("删除失败");
}
});
layer.close(handler)
});
}
})
4、创建函数delectById将ids值传到后端
以post形式传到delete地址下,通过后端删除后返回给回调函数rows值,再将rows传回给按钮。
//参数为id数组
function deleteByIds(ids, cb=$.noop) {
//请求、响应模型
$.ajax({
url: ctx + "/student/delete",
method: "post",
//添加此属性,表示可以向后台传递数组参数
traditional: true,
data: {
ids
},
success: function (resp){
cb(resp.rows);
}
})
}
5、select接收请求向下调用
list.js->select->service->dao --->selcet->list.js->list.jsp
private void delete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取请求参数中的ids
String[] strIds = req.getParameterValues("ids");
//将ids转换为List<Integer>
List<Integer> ids = new ArrayList<>();
for(int i=0;i<strIds.length;i++) ids.add(Integer.parseInt(strIds[i]));
//调用studentService的deleteByIds方法删除数据,返回删除的行数
int rows = studentService.deleteByIds(ids);
//将删除的行数封装到map中
Map<String, Object> map = Map.of("rows", rows);
ServletUtil.renderJson(resp,map);
}
在dao中编写sql语句访问数据库
public int deleteByIds(List<Integer> ids) {
//sparing提供的模板工具类
JdbcTemplate jdbcTemplate = Global.getTemplate();
//判断ids是否为空
if(ids == null || ids.isEmpty()) return -1;
//创建StringBuilder对象
StringBuilder sb = new StringBuilder();
//使用repeat方法重复添加"?,"
sb.append("?,".repeat(ids.size()));
//截取最后一个","
String ph = sb.substring(0, sb.length()-1);
//拼接删除语句
String delsql = "delete from t_student where id in ("+ph+")";
//执行删除语句
int rows = jdbcTemplate.update(delsql, ids.toArray());
return rows;
}
成功获取删除条数,将rows编写成json语句返回前端,这里我们新建一个工具类ServletUtil用于返回json
package com.situ.util;
import com.alibaba.fastjson2.JSON;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
public class ServletUtil {
//将对象转换为json字符串并写入响应流
public static void renderJson(HttpServletResponse resp, Object obj) throws IOException {
//设置响应的内容类型为json
resp.setContentType("application/json;charset=UTF-8");
//获取响应的输出流
PrintWriter out = resp.getWriter();
//将map转换为json字符串并写入响应流
out.write(JSON.toJSONString(obj));
//刷新响应流
out.flush();
}
}
二、新增功能
1.为新增按钮添加事件
按钮打开一个悬浮窗,窗内显示add页面,
- 参数说明:
handler
: 当前弹窗的索引(index),用于关闭弹窗。$jq
: 表示弹窗的 jQuery 对象(包含整个 layer DOM 结构)。
- 在弹窗中查找
iframe
元素。 - 获取其原生 DOM 元素(
[0]
)。 - 然后通过
.contentWindow
获取 iframe 内部页面的 window 对象。 - 这样就可以调用 iframe 内部的 JavaScript 函数了。
- 调用 iframe 内部页面的
submit()
函数。 submit
函数接收一个回调函数作为参数,用于接收提交结果(success
是布尔值)。- 如果
success
为true
:- 显示“新增成功”提示。
- 调用
findAll(...)
刷新当前学生列表。 - 关闭弹窗(
layer.close(handler)
)。
- 如果
success
为false
:- 提示用户“新增失败”,并检查数据。
$("#add").click(function (){
layer.open({
title: "新增学生",
type: 2,
area: ["800px","600px"],
btn: ["确定","取消"],
content: ctx + "/student/add",
yes: function (handler, $jq){
const win= $jq.find("iframe")[0].contentWindow;
win.submit(function (success){
if(success){
layer.msg("新增成功");
findAll(currentPage,limits);
layer.close(handler);
}else {
layer.msg("新增失败,请修改不合格数据");
}
});
}
})
});
2、新建add功能的jsp、css、js
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="jakarta.tags.core"%>
<c:set var="cxt" value="${pageContext.request.contextPath}"/>
<html>
<head>
<base href="${cxt}/">
<title>新增学生数据</title>
<link rel="stylesheet" href="assets/modules/student/css/add.css">
<link rel="stylesheet" href="assets/lib/layui/css/layui.css">
<script src="assets/lib/jquery/jquery-3.7.1.min.js"></script>
<script src="assets/modules/student/js/add.js"></script>
<script src="assets/lib/layui/layui.js"></script>
<script>
const ctx = "${cxt}";
</script>
</head>
<body>
<form id="student-form" action="">
<div>
<label for="stuId">学号:</label>
<input type="text" name="stuId" id="stuId" autocomplete="off" placeholder="请输入学号">
</div>
<div>
<label for="name">姓名:</label>
<input type="text" name="name" id="name" autocomplete="off" placeholder="请输入姓名">
</div>
<div>
<label for="pinyin">拼音:</label>
<input type="text" name="pinyin" id="pinyin" autocomplete="off" placeholder="请输入拼音">
</div>
<div>
<label for="sex">性别:</label>
<input type="radio" name="sex" id="male" value="男" checked>
<label for="male">男</label>
<input type="radio" name="sex" id="female" value="女">
<label for="female">女</label>
</div>
<div>
<label for="birthday">出生日期:</label>
<input type="text" name="birthday" id="birthday" autocomplete="off" placeholder="请输入出生日期" readonly>
</div>
<div>
<label for="phone">手机号:</label>
<input type="text" name="phone" id="phone" autocomplete="off" placeholder="请输入手机号">
</div>
<div>
<label for="email">邮箱:</label>
<input type="text" name="email" id="email" autocomplete="off" placeholder="请输入邮箱">
</div>
</form>
</body>
</html>
body{
padding: 10px;
}
#student-form>div{
margin: 20px 0;
height: 50px;
}
#student-form>div>label:first-child{
display: inline-block;
width: 100px;
text-align: right;
}
#student-form>div>input:not(#male,#female){
outline: none;
width: 300px;
height: 30px;
margin-left: 10px;
border: 1px solid #ccc;
border-radius: 5px;
padding-left: 10px;
}
#student-form>div>label{
display: inline-block;
font-size: 20px;
font-weight: bold;
text-align: center;
}
$(()=>{
//渲染出生日期
layui.use(function () {
const laydate = layui.laydate;
laydate.render({
elem: "#birthday",
type: "date"
});
});
});
function submit(cb = $.noop){
let stuId = $("#stuId").val();
let name = $("#name").val();
let pinyin = $("#pinyin").val();
let birthday = $("#birthday").val();
let phone = $("#phone").val();
let email = $("#email").val();
let sex = $(":input[name=sex]:checked").val();
// console.log(sex);
//前端校验:js校验
if (stuId.trim() === "") {
layer.msg("学号不可为空");
return;
}
if (name.trim() === "") {
layer.msg("姓名不可为空");
return;
}
let pat = /^\d{4}-\d{2}-\d{2}$/;
if (!pat.test(birthday)) {
layer.msg("出生日期格式不正确");
return;
}
pat = /^\d{11}$/;
if (!pat.test(phone)) {
layer.msg("手机号格式不正确");
return;
}
$.ajax({
url: "student/add",
type: "post",
data: {
stuId,
name,
pinyin,
birthday,
phone,
email,
sex
},
success: function (resp){
cb(resp.success)
}
})
}
3、submit函数实现将“增加”内容发送到后端进行写入
servlet将传入的信息保存到Student对象中,并向下传递调用
private void add(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("UTF-8");
String stuId = req.getParameter("stuId");
String name = req.getParameter("name");
String pinyin = req.getParameter("pinyin");
String sex = req.getParameter("sex");
String birthday = req.getParameter("birthday");
String phone = req.getParameter("phone");
String email = req.getParameter("email");
//后端校验
if (!StringUtils.hasText(stuId)){
ServletUtil.renderJson(resp, Map.of("error", "学号不可为空"));
return;
}
if(!StringUtils.hasText(name)){
ServletUtil.renderJson(resp, Map.of("error", "姓名不可为空"));
return;
}
if(!phone.matches("^\\d{11}$")){
ServletUtil.renderJson(resp, Map.of("error", "手机号格式不正确"));
return;
}
Student student = new Student();
student.setStuId(stuId);
student.setName(name);
student.setPinyin(pinyin);
if(!sex.equals("男") && !sex.equals("女")){
ServletUtil.renderJson(resp, Map.of("error", "性别只能是男或女"));
}
student.setSex(sex);
try {
LocalDate ld = LocalDate.parse(birthday, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
student.setBirthday(ld);
} catch (Exception e) {
ServletUtil.renderJson(resp, Map.of("error", "出生日期不正确"));
}
student.setPhone(phone);
student.setEmail(email);
boolean success = studentService.save(student);
ServletUtil.renderJson(resp, Map.of("success", success));
}
Dao
public int save(Student student) {
JdbcTemplate jdbcTemplate = Global.getTemplate();
String sql = "insert into t_student (stu_id, name, pinyin, sex, birthday, phone, email) values(?,?,?,?,?,?,?)";
int rows = jdbcTemplate.update(sql, student.getStuId(), student.getName(), student.getPinyin(), student.getSex(), student.getBirthday(), student.getPhone(), student.getEmail());
return rows;
}
三、修改功能
修改功能类似于增加功能,也需要新建jsp、css、js,在list.js中实现按钮功能
这里的url将id值传给了servlet中的doGet,get转发到jsp,jsp设为全局常量,js就可以获取id值
$("#edit").click(function (){
let $checked = $("#tab tr>td:first-child>:checked");
if($checked.length === 0) layer.msg("请选择要编辑的学生");
else if($checked.length > 1) layer.msg("一次只能编辑一个学生");
else{
let $id = $checked.attr("data-id");
layer.open({
title: "修改学生",
type: 2,
area: ["800px","600px"],
btn: ["确定","取消"],
content: ctx + "/student/edit?id="+ $id,
yes: function (handler, $jq){
const win= $jq.find("iframe")[0].contentWindow;
win.submit(function (success){
if(success){
layer.msg("修改成功");
findAll(currentPage,limits);
layer.close(handler);
}else {
layer.msg("修改失败,请修改不合格数据");
}
});
}
})
}
});
在js中设置findId函数用于向后端请求寻找目标id的数据,回调函数用于后端返回对应值
$(()=>{
findById(id)
//渲染出生日期
layui.use(function () {
const laydate = layui.laydate;
laydate.render({
elem: "#birthday",
type: "date"
});
});
});
//查询指定id学生的信息
function findById(id){
$.ajax({
url: "student/id",
method:"get",
data:{
id
},
success: function (resp){
const stu = resp.student;
$("#stuId").val(stu.stuId);
$("#name").val(stu.name);
$("#pinyin").val(stu.pinyin);
$("#birthday").val(stu.birthday);
$("#phone").val(stu.phone);
$("#email").val(stu.email);
$(":radio[name=sex][value="+stu.sex+"]").prop("checked",true);
}
})
}
//修改数据提交
function submit(cb = $.noop){
let stuId = $("#stuId").val();
let name = $("#name").val();
let pinyin = $("#pinyin").val();
let birthday = $("#birthday").val();
let phone = $("#phone").val();
let email = $("#email").val();
let sex = $(":input[name=sex]:checked").val();
// console.log(sex);
//前端校验:js校验
if (stuId.trim() === "") {
layer.msg("学号不可为空");
return;
}
if (name.trim() === "") {
layer.msg("姓名不可为空");
return;
}
let pat = /^\d{4}-\d{2}-\d{2}$/;
if (!pat.test(birthday)) {
layer.msg("出生日期格式不正确");
return;
}
pat = /^\d{11}$/;
if (!pat.test(phone)) {
layer.msg("手机号格式不正确");
return;
}
$.ajax({
url: "student/edit",
type: "post",
data: {
id,
stuId,
name,
pinyin,
birthday,
phone,
email,
sex
},
success: function (resp){
cb(resp.success)
}
})
}
servlet中的doGet方法,调用findById方法
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String action = req.getPathInfo();
if("/list".equals(action)){
//List<Student> students = studentService.findAll();
//req.setAttribute("students", students);
//String page = req.getParameter("page");
//String limit = req.getParameter("limit");
req.getRequestDispatcher("/WEB-INF/jsp/student/list.jsp").forward(req,resp);
} else if("/add".equals(action)){
req.getRequestDispatcher("/WEB-INF/jsp/student/add.jsp").forward(req,resp);
} else if("/edit".equals(action)) {//编辑
String id = req.getParameter("id");
req.setAttribute("id", id);
req.getRequestDispatcher("/WEB-INF/jsp/student/edit.jsp").forward(req, resp);
} else if("/id".equals(action)) {//根据id查询
String id = req.getParameter("id");
Student stu = studentService.findById(Integer.parseInt(id));
ServletUtil.renderJson(resp, Map.of("student", stu));
}
}
public Student findById(Integer id) {
JdbcTemplate jdbcTemplate = Global.getTemplate();
String sql = "select id, stu_id, name, sex, birthday, pinyin, phone, email, qq, wechat from t_student where id = ?";
Student student = jdbcTemplate.queryForObject(sql, rowMapper, id);
return student;
}
将对应id的目标数据显示在浮窗中
信息修改后点击确定按钮,调用submit函数,在后端进行修改sql语句
private void edit(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("UTF-8");
String id = req.getParameter("id");
String stuId = req.getParameter("stuId");
String name = req.getParameter("name");
String pinyin = req.getParameter("pinyin");
String sex = req.getParameter("sex");
String birthday = req.getParameter("birthday");
String phone = req.getParameter("phone");
String email = req.getParameter("email");
//后端校验
if (!StringUtils.hasText(stuId)){
ServletUtil.renderJson(resp, Map.of("error", "学号不可为空"));
return;
}
if(!StringUtils.hasText(name)){
ServletUtil.renderJson(resp, Map.of("error", "姓名不可为空"));
return;
}
if(!phone.matches("^\\d{11}$")){
ServletUtil.renderJson(resp, Map.of("error", "手机号格式不正确"));
return;
}
if(!sex.equals("男") && !sex.equals("女")){
ServletUtil.renderJson(resp, Map.of("error", "性别只能是男或女"));
}
Student student = new Student();
student.setId(Integer.parseInt(id));
student.setStuId(stuId);
student.setName(name);
student.setPinyin(pinyin);
student.setSex(sex);
try {
LocalDate ld = LocalDate.parse(birthday, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
student.setBirthday(ld);
} catch (Exception e) {
ServletUtil.renderJson(resp, Map.of("error", "出生日期不正确"));
}
student.setPhone(phone);
student.setEmail(email);
boolean success = studentService.edit(student);
ServletUtil.renderJson(resp, Map.of("success", success));
}
public int edit(Student student) {
JdbcTemplate jdbcTemplate = Global.getTemplate();
String sql = "update t_student set stu_id = ?, name = ?, pinyin = ?, sex = ?, birthday = ?, phone = ?, email = ? where id = ?";
int rows = jdbcTemplate.update(sql, student.getStuId(), student.getName(), student.getPinyin(), student.getSex(), student.getBirthday(), student.getPhone(), student.getEmail(), student.getId());
return rows;
}