branch_liu
LiuChang 3 months ago
parent 563386b450
commit affd83e652

@ -24,195 +24,216 @@ import java.util.List;
import java.util.UUID; import java.util.UUID;
/** /**
* Description: * Description: 访访访
* *
* @Date: 2020/2/18 16:26 * @Date: 2020/2/18 16:26
* @Author: PeiChen * @Author: PeiChen
*/ */
// 声明这是一个控制器 // 声明这是一个Spring框架中的控制器表明该类可以处理HTTP请求并返回相应的视图或数据
@Controller @Controller
// 映射访问路径为/visitor // 映射访问路径为/visitor,意味着所有以/visitor开头的请求都会被该控制器处理
@RequestMapping("/visitor") @RequestMapping("/visitor")
public class VisitorController { public class VisitorController {
// 自动注入VisitorService服务类 // 自动注入VisitorService服务类通过依赖注入的方式获取VisitorService的实例以便调用其中的业务逻辑方法
private VisitorService visitorService; private VisitorService visitorService;
// 通过Autowired注解自动注入VisitorService // 通过Autowired注解自动注入VisitorService这里是设置属性注入的方法Spring会自动找到VisitorService的实现类并注入进来
@Autowired @Autowired
public void setVisitorService(VisitorService visitorService) { public void setVisitorService(VisitorService visitorService) {
this.visitorService = visitorService; this.visitorService = visitorService;
} }
// 访问路径为/visitor/login的请求处理方法返回注册页面 // 访问路径为/visitor/login的请求处理方法该方法返回注册页面的视图名称通常Spring会根据这个名称去查找对应的视图文件进行渲染展示
@RequestMapping("/login") @RequestMapping("/login")
public String register() { public String register() {
return "regist_visitor"; return "regist_visitor";
} // 返回regist_visitor视图 } // 返回regist_visitor视图此视图应该是用于展示访客注册相关页面内容的具体的页面解析和渲染由Spring的视图解析器根据配置来完成
/** /**
* 访C * 访C
* @param visitor 访 * 访访Visitor访
* @return ModelAndView *
* @throws Exception * @param visitor 访访访
* @return ModelAndView 便Spring
* @throws Exception
*/ */
@RequestMapping("/addLogin") @RequestMapping("/addLogin")
public ModelAndView addVisitor(Visitor visitor) throws Exception { public ModelAndView addVisitor(Visitor visitor) throws Exception {
ModelAndView mv = new ModelAndView(); ModelAndView mv = new ModelAndView();
// 参数校验,如果访客信息不完整,则返回错误信息 // 参数校验,如果访客信息不完整(访客对象为空或者关键属性如姓名、学号、电话、访问地点等为空),则返回错误信息页面
if (visitor == null || visitor.getName() == null || visitor.getSno() == null || visitor.getPhone() == null || visitor.getPlace() == null) { if (visitor == null || visitor.getName() == null || visitor.getSno() == null || visitor.getPhone() == null || visitor.getPlace() == null) {
mv.addObject("error_msg","来访登记失败,请重新登记!"); mv.addObject("error_msg", "来访登记失败,请重新登记!");
mv.setViewName("regist_visitor"); mv.setViewName("regist_visitor");
return mv; return mv;
} }
// 生成访客ID // 生成访客ID使用UUID通用唯一识别码来生成一个唯一的标识符作为访客的ID如果原访客对象中的ID为空或者是空白字符串则进行生成操作
if (visitor.getId() == null || "".trim().equals(visitor.getId())) { if (visitor.getId() == null || "".trim().equals(visitor.getId())) {
String uuid = UUID.randomUUID().toString().replace("-", ""); String uuid = UUID.randomUUID().toString().replace("-", "");
visitor.setId(uuid); visitor.setId(uuid);
} }
// 设置来访时间为当前系统时间 // 设置来访时间为当前系统时间通过SimpleDateFormat格式化当前的日期和时间格式为"yyyy-MM-dd HH:mm:ss"),并设置到访客对象的来访时间属性中
String date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()); String date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
visitor.setBegin_date(date);//设置来访时间为提交来访登记时间 visitor.setBegin_date(date);//设置来访时间为提交来访登记时间
//先设置离开时间为空串,后续注销时再修改为注销时系统时间 // 先设置离开时间为空串,后续注销时再修改为注销时系统时间,初始化访客的离开时间为空字符串,表示访客尚未离开
if (visitor.getEnd_date() == null || "".trim().equals(visitor.getEnd_date())) { if (visitor.getEnd_date() == null || "".trim().equals(visitor.getEnd_date())) {
visitor.setEnd_date(""); visitor.setEnd_date("");
} }
// 添加访客信息到数据库 // 添加访客信息到数据库调用VisitorService中的add方法将完整的访客信息保存到数据库中
visitorService.add(visitor); visitorService.add(visitor);
// 添加访客ID到模型用于页面显示 // 添加访客ID到模型用于页面显示将生成的访客ID添加到ModelAndView对象中以便在后续的视图中可以获取并展示给用户
mv.addObject("id",visitor.getId()); mv.addObject("id", visitor.getId());
mv.setViewName("visitor-success"); // 设置成功页面视图 mv.setViewName("visitor-success"); // 设置成功页面视图,指定成功登记后要展示的视图名称,通常会显示登记成功的相关提示信息
return mv; return mv;
} }
/** /**
* 访 * 访
* @param request HttpServletRequest * 访HttpServletRequest访ID
* @return ModelAndView *
* @throws Exception * @param request HttpServletRequest访ID
* @return ModelAndView
* @throws Exception
*/ */
@RequestMapping("/login_out") @RequestMapping("/login_out")
public ModelAndView logout(HttpServletRequest request) throws Exception { public ModelAndView logout(HttpServletRequest request) throws Exception {
ModelAndView mv = new ModelAndView(); ModelAndView mv = new ModelAndView();
// 获取访客ID // 获取访客ID从HttpServletRequest对象中获取名为"id"的参数值,该参数值代表要注销的访客的唯一标识
String id = request.getParameter("id"); String id = request.getParameter("id");
// 如果ID为空则返回错误信息 // 如果ID为空则返回错误信息页面,提示系统繁忙,让用户稍后再试
if (id == null || "".trim().equals(id)) { if (id == null || "".trim().equals(id)) {
mv.addObject("logout_msg","系统繁忙,请稍后再试!"); mv.addObject("logout_msg", "系统繁忙,请稍后再试!");
mv.setViewName("regist_visitor"); mv.setViewName("regist_visitor");
} }
// 获取当前系统时间 // 获取当前系统时间通过SimpleDateFormat格式化当前的日期和时间格式为"yyyy-MM-dd HH:mm:ss"),用于更新访客记录的注销时间
String date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()); String date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
// 注销访客记录 // 注销访客记录调用VisitorService中的logout方法传入访客ID和当前时间完成在数据库中对访客记录的注销操作可能是更新离开时间等相关操作
visitorService.logout(id,date); visitorService.logout(id, date);
mv.addObject("logout_msg","注销成功"); mv.addObject("logout_msg", "注销成功");
mv.setViewName("regist_visitor"); mv.setViewName("regist_visitor");
return mv; return mv;
} }
/** /**
* 访 * 访
* @param request HttpServletRequest * 访HttpServletRequestHttpServletResponse访IDtruefalse
* @param response HttpServletResponse *
* @throws Exception * @param request HttpServletRequest访ID
* @param response HttpServletResponse
* @throws Exception
*/ */
@RequestMapping("/updateStatus") @RequestMapping("/updateStatus")
public void updateStatus(HttpServletRequest request,HttpServletResponse response) throws Exception { public void updateStatus(HttpServletRequest request, HttpServletResponse response) throws Exception {
request.setCharacterEncoding("utf-8"); request.setCharacterEncoding("utf-8");
// 设置请求的字符编码为UTF-8确保能正确接收和处理包含中文等特殊字符的请求参数
response.setCharacterEncoding("utf-8"); response.setCharacterEncoding("utf-8");
// 设置响应的字符编码为UTF-8保证返回给客户端的数据能正确显示避免出现乱码问题
PrintWriter writer = response.getWriter(); PrintWriter writer = response.getWriter();
// 获取访客ID // 获取响应的输出流的PrintWriter对象用于向客户端发送文本数据这里用于写入操作结果
// 获取访客ID从HttpServletRequest对象中获取名为"id"的参数值,该参数值是要注销的访客记录的标识
String id = request.getParameter("id"); String id = request.getParameter("id");
// 如果ID为空则返回错误信息 // 如果ID为空则返回错误信息,向客户端写入"false"表示注销操作失败
if (id == null || "".trim().equals(id)) { if (id == null || "".trim().equals(id)) {
writer.write("false"); writer.write("false");
return; return;
} }
// 获取当前系统时间 // 获取当前系统时间通过SimpleDateFormat格式化当前的日期和时间格式为"yyyy-MM-dd HH:mm:ss"),用于更新访客记录的注销时间
String date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()); String date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
// 注销访客记录 // 注销访客记录调用VisitorService中的logout方法传入访客ID和当前时间在数据库中执行注销操作比如更新离开时间等相关字段
visitorService.logout(id,date); visitorService.logout(id, date);
writer.write("true"); writer.write("true");
// 向客户端写入"true"表示注销操作成功,客户端可以根据接收到的这个结果进行相应的提示或后续处理
} }
/** /**
* 访 * 访
* @param page * 访HttpServletRequestHttpServletResponse
* @param size *
* @param request HttpServletRequest * @param page 1使
* @param response HttpServletResponse * @param size 访5使
* @return ModelAndView * @param request HttpServletRequest
* @throws Exception * @param response HttpServletResponse
* @return ModelAndView 访便Spring
* @throws Exception
*/ */
@RequestMapping("/findAll") @RequestMapping("/findAll")
public ModelAndView findAll(@RequestParam(name = "page", required = true, defaultValue = "1") int page, @RequestParam(name = "size", required = true, defaultValue = "5") int size,HttpServletRequest request,HttpServletResponse response) throws Exception { public ModelAndView findAll(@RequestParam(name = "page", required = true, defaultValue = "1") int page,
// 设置请求和响应的字符编码为UTF-8 @RequestParam(name = "page", required = true, defaultValue = "5") int size,
HttpServletRequest request, HttpServletResponse response) throws Exception {
// 设置请求的字符编码为UTF-8确保能正确处理包含中文等特殊字符的请求参数
request.setCharacterEncoding("utf-8"); request.setCharacterEncoding("utf-8");
// 设置响应的字符编码为UTF-8保证返回给客户端的数据能正确显示避免出现乱码情况
response.setCharacterEncoding("utf-8"); response.setCharacterEncoding("utf-8");
// 创建ModelAndView对象用于返回视图和数据 // 创建ModelAndView对象用于返回视图和数据该对象可以携带数据并指定要展示的视图名称方便Spring进行后续的视图渲染操作
ModelAndView mv = new ModelAndView(); ModelAndView mv = new ModelAndView();
List<Visitor> visitors = null; List<Visitor> visitors = null;
// 获取请求中的keyword参数 // 获取请求中的keyword参数,该参数用于根据关键词进行访客记录的搜索,如果没有该参数则查询所有记录
String keyword = request.getParameter("keyword"); String keyword = request.getParameter("keyword");
// 如果keyword为空或为空字符串则查询所有访客记录 // 如果keyword为空或为空字符串或者长度为0进一步确保为空的情况则查询所有访客记录调用VisitorService的findAll方法获取所有访客信息分页查询
if (keyword == null || "".trim().equals(keyword) || keyword.length() == 0) { if (keyword == null || "".trim().equals(keyword) || keyword.length() == 0) {
visitors = visitorService.findAll(page,size); visitors = visitorService.findAll(page, size);
}else { } else {
// 否则根据keyword进行搜索 // 否则根据keyword进行搜索调用VisitorService的search方法传入当前页码、每页显示数量以及关键词进行带关键词的分页搜索操作
visitors = visitorService.search(page,size,keyword); visitors = visitorService.search(page, size, keyword);
} }
// 创建分页信息对象 // 创建分页信息对象通过PageInfo对查询到的访客列表进行分页相关信息的封装如总页数、总记录数等信息都会被自动计算并封装在该对象中
PageInfo pageInfo = new PageInfo(visitors); PageInfo pageInfo = new PageInfo(visitors);
// 将分页信息添加到ModelAndView对象中 // 将分页信息添加到ModelAndView对象中,这样在视图中就可以获取并展示分页相关的信息,如页码导航、总记录数等内容
mv.addObject("pageInfo",pageInfo); mv.addObject("pageInfo", pageInfo);
// 设置视图名称为"visitor-list" // 设置视图名称为"visitor-list"指定要返回的视图名称Spring会根据配置找到对应的视图文件进行渲染展示该视图可能用于展示访客记录列表信息
mv.setViewName("visitor-list"); mv.setViewName("visitor-list");
// 返回ModelAndView对象 // 返回ModelAndView对象将携带数据的视图模型返回给Spring框架由框架进行后续的视图渲染和响应返回操作
return mv; return mv;
} }
/** /**
* 访` * 访
* @return ModelAndView 访 * 访访
* @throws Exception *
* @return ModelAndView 访
* @throws Exception
*/ */
@RequestMapping("/log") @RequestMapping("/log")
public ModelAndView log(@RequestParam(name = "page", required = true, defaultValue = "1") int page, @RequestParam(name = "size", required = true, defaultValue = "10") int size) throws Exception { public ModelAndView log(@RequestParam(name = "page", required = true, defaultValue = "1") int page,
// 创建ModelAndView对象用于返回视图和数据 @RequestParam(name = "size", required = true, defaultValue = "10") int size) throws Exception {
// 创建ModelAndView对象用于返回视图和数据该对象可以携带数据并指定要展示的视图名称方便Spring进行后续的视图渲染操作
ModelAndView mv = new ModelAndView(); ModelAndView mv = new ModelAndView();
// 获取访客日志列表 // 获取访客日志列表调用VisitorService的log方法传入当前页码和每页显示数量获取相应分页的访客日志信息
List<Visitor> logs = visitorService.log(page,size); List<Visitor> logs = visitorService.log(page, size);
// 创建分页信息对象 // 创建分页信息对象通过PageInfo对获取到的访客日志列表进行分页相关信息的封装方便在视图中展示分页相关的内容
PageInfo pageInfo = new PageInfo(logs); PageInfo pageInfo = new PageInfo(logs);
// 将分页信息添加到ModelAndView对象中 // 将分页信息添加到ModelAndView对象中,使得视图可以获取并展示如总页数、当前页码等分页相关信息
mv.addObject("pageInfo",pageInfo); mv.addObject("pageInfo", pageInfo);
// 设置视图名称为"visitor-log" // 设置视图名称为"visitor-log"指定要返回的视图名称Spring会根据配置找到对应的视图文件进行渲染展示该视图用于展示访客日志相关信息
mv.setViewName("visitor-log"); mv.setViewName("visitor-log");
// 返回ModelAndView对象 // 返回ModelAndView对象将携带访客日志数据和分页信息的视图模型返回给Spring框架由框架进行后续的视图渲染和响应返回操作
return mv; return mv;
} }
/** /**
* 访 * 访
* @param response HttpServletResponseExcel * 访ExcelHttpServletResponseExcel
* @throws Exception *
* @param response HttpServletResponseExcel
* @throws Exception
*/ */
@RequestMapping("/visitorInfo") @RequestMapping("/visitorInfo")
public void export(HttpServletResponse response) throws Exception { public void export(HttpServletResponse response) throws Exception {
// 获取Excel文件的输入流 // 获取Excel文件的输入流调用VisitorService的getInputStream方法获取访客信息对应的Excel文件的输入流以便后续将文件内容发送给客户端
InputStream is = visitorService.getInputStream(); InputStream is = visitorService.getInputStream();
// 设置响应的内容类型为Excel文件 // 设置响应的内容类型为Excel文件,指定响应的内容类型为"application/vnd.ms-excel"告诉客户端返回的数据是Excel格式的文件以便客户端进行正确的处理如下载或打开操作
response.setContentType("application/vnd.ms-excel"); response.setContentType("application/vnd.ms-excel");
// 设置响应头指示浏览器以附件形式下载文件并设置文件名为visitorInfo.xls // 设置响应头指示浏览器以附件形式下载文件并设置文件名为visitorInfo.xls,通过设置"contentDisposition"头信息,让浏览器以附件形式下载文件,并指定文件名,方便用户保存文件
response.setHeader("contentDisposition","attachment;filename=visitorInfo.xls"); response.setHeader("contentDisposition", "attachment;filename=visitorInfo.xls");
// 获取响应的输出流 // 获取响应的输出流用于将Excel文件的内容写入到响应中发送给客户端
ServletOutputStream outputStream = response.getOutputStream(); ServletOutputStream outputStream = response.getOutputStream();
// 使用IOUtils工具类将输入流的内容复制到输出流 // 使用IOUtils工具类将输入流的内容复制到输出流借助Apache Commons IO库提供的IOUtils工具类方便地将Excel文件的输入流内容复制到响应的输出流中实现文件的发送
IOUtils.copy(is,outputStream); IOUtils.copy(is, outputStream);
} }
} }

@ -11,46 +11,62 @@ import java.util.List;
/** /**
* Description:访 * Description:访
* 访访MyBatisSQL
* 访visitors
* *
* @Date: 2020/2/18 16:27 * @Date: 2020/2/18 16:27
* @Author: PeiChen * @Author: PeiChen
*/ */
// 声明这是一个数据访问对象接口 // 声明这是一个数据访问对象接口在Spring框架中使用 @Repository 注解标记该接口为数据访问层组件,便于进行依赖注入和管理
@Repository @Repository
public interface VisitorDao { public interface VisitorDao {
/** /**
* 访 * 访
* @param visitor 访访 * 访访MyBatis @Insert SQL
* @throws Exception * 访
*
* @param visitor 访访ID访访访
* SQLvisitors
* @throws Exception SQL
*/ */
@Insert("insert into visitors(id,name,sno,phone,place,begin_date,end_date,visit_result) values(#{id},#{name},#{sno},#{phone},#{place},#{begin_date},#{end_date},#{visit_result})") @Insert("insert into visitors(id,name,sno,phone,place,begin_date,end_date,visit_result) values(#{id},#{name},#{sno},#{phone},#{place},#{begin_date},#{end_date},#{visit_result})")
void add(Visitor visitor) throws Exception; void add(Visitor visitor) throws Exception;
/** /**
* 访 * 访
* @return 访 * 访访begin_date访
* @throws Exception * MyBatis @Select SQL访
*
* @return 访Visitor访
* @throws Exception
*/ */
@Select("select * from visitors order by begin_date desc") @Select("select * from visitors order by begin_date desc")
List<Visitor> findAll() throws Exception; List<Visitor> findAll() throws Exception;
/** /**
* 访访 * 访访
* @param id 访 * 访访MyBatis @Update SQL
* @param end_date 访 * 访IDend_date
* @throws Exception *
* @param id 访访visitorsid
* @param end_date 访访end_date
* @throws Exception
*/ */
@Update("update visitors set end_date = #{end_date} where id = #{id}") @Update("update visitors set end_date = #{end_date} where id = #{id}")
void logout(@Param(value = "id") String id,@Param(value = "end_date") String end_date) throws Exception; void logout(@Param(value = "id") String id, @Param(value = "end_date") String end_date) throws Exception;
/** /**
* 访 * 访
* @param keyword * 访访
* @return 访 * 访begin_date
* @throws Exception * MyBatis @Select SQL访
*
* @param keyword 访
* @return 访Visitor访
* @throws Exception
*/ */
@Select("select * from visitors where name like '%${keyword}%' or sno like '%${keyword}%' or phone like '%${keyword}%' or place like '%${keyword}%' or begin_date like '%${keyword}%' or end_date like '%${keyword}%' or visit_result like '%${keyword}%' order by begin_date desc ") @Select("select * from visitors where name like '%${keyword}%' or sno like '%${keyword}%' or phone like '%${keyword}%' or place like '%${keyword}%' or begin_date like '%${keyword}%' or end_date like '%${keyword}%' or visit_result like '%${keyword}%' order by begin_date desc ")
List<Visitor> search(@Param(value = "keyword") String keyword) throws Exception; List<Visitor> search(@Param(value = "keyword") String keyword) throws Exception;
} }

@ -4,37 +4,48 @@ import java.io.Serializable;
/** /**
* Description:访 * Description:访
* 访Serializable便 * 访Serializable便
* @Date: 2020/2/18 16:29 * @Date: 2020/2/18 16:29
* @Author: PeiChen * @Author: PeiChen
*/ */
public class Visitor implements Serializable { public class Visitor implements Serializable {
private String id;//uuid 全球唯一id // uuid 全球唯一id用于唯一标识每个访客记录在数据库操作等场景中可作为主键来区分不同访客
private String name;//访客姓名 private String id;
private String sno;//访客学号 // 访客姓名,用于记录访客的具体称呼,方便后续识别和查询访客相关信息
private String phone;//联系方式 private String name;
private String place;//访问地址 // 访客学号,若访客是学生等有学号标识的群体,可通过该字段存储学号信息,便于按学号进行相关业务操作(如查询、统计等)
private String begin_date;//来访时间 private String sno;
private String end_date;//离开时间 // 联系方式,存储访客的电话号码等联系信息,方便在需要时与访客进行沟通联系
private String visit_result;//到访原因 private String phone;
// 访问地址,记录访客访问的具体地点,例如访问的具体校区、办公楼、房间号等信息
private String place;
// 来访时间,用于记录访客到达访问地点的具体时间,格式通常遵循一定的日期时间格式(如 yyyy-MM-dd HH:mm:ss
private String begin_date;
// 离开时间,记录访客离开访问地点的时间,初始可能为空字符串,在访客离开时更新为实际离开时间,同样一般遵循日期时间格式
private String end_date;
// 到访原因,用于描述访客前来访问的事由,例如参加会议、拜访某人等具体原因说明
private String visit_result;
/** /**
* *
* Visitor
*
*/ */
public Visitor() { public Visitor() {
} }
/** /**
* 访 * 访
* @param id 访ID * 访便访
* @param name 访 *
* @param sno 访 * @param id 访ID访IDid访
* @param phone 访 * @param name 访访name访
* @param place 访访 * @param sno 访访sno便
* @param begin_date 访访 * @param phone 访访phone便
* @param end_date 访 * @param place 访访访访place访
* @param visit_result 访访 * @param begin_date 访访访begin_date访
* @param end_date 访访end_date
* @param visit_result 访访访访visit_result便访
*/ */
public Visitor(String id, String name, String sno, String phone, String place, String begin_date, String end_date, String visit_result) { public Visitor(String id, String name, String sno, String phone, String place, String begin_date, String end_date, String visit_result) {
this.id = id; this.id = id;
@ -47,75 +58,158 @@ public class Visitor implements Serializable {
this.visit_result = visit_result; this.visit_result = visit_result;
} }
// 以下是属性的getter和setter方法 // 以下是属性的getter和setter方法用于获取和设置对象的各个属性值遵循JavaBean规范方便外部类对对象属性进行访问和修改操作。
/**
* 访ID
*
* @return 访ID访
*/
public String getId() { public String getId() {
return id; return id;
} }
/**
* 访ID
*
* @param id 访ID访id
*/
public void setId(String id) { public void setId(String id) {
this.id = id; this.id = id;
} }
/**
* 访
*
* @return 访访
*/
public String getName() { public String getName() {
return name; return name;
} }
/**
* 访
*
* @param name 访访name
*/
public void setName(String name) { public void setName(String name) {
this.name = name; this.name = name;
} }
/**
* 访
*
* @return 访访
*/
public String getSno() { public String getSno() {
return sno; return sno;
} }
/**
* 访
*
* @param sno 访访sno
*/
public void setSno(String sno) { public void setSno(String sno) {
this.sno = sno; this.sno = sno;
} }
/**
* 访
*
* @return 访访
*/
public String getPhone() { public String getPhone() {
return phone; return phone;
} }
/**
* 访
*
* @param phone 访访phone
*/
public void setPhone(String phone) { public void setPhone(String phone) {
this.phone = phone; this.phone = phone;
} }
/**
* 访访
*
* @return 访访访访
*/
public String getPlace() { public String getPlace() {
return place; return place;
} }
/**
* 访访
*
* @param place 访访访place访
*/
public void setPlace(String place) { public void setPlace(String place) {
this.place = place; this.place = place;
} }
/**
* 访访
*
* @return 访访访访
*/
public String getBegin_date() { public String getBegin_date() {
return begin_date; return begin_date;
} }
/**
* 访访
*
* @param begin_date 访访访begin_date访
*/
public void setBegin_date(String begin_date) { public void setBegin_date(String begin_date) {
this.begin_date = begin_date; this.begin_date = begin_date;
} }
/**
* 访
*
* @return 访访
*/
public String getEnd_date() { public String getEnd_date() {
return end_date; return end_date;
} }
/**
* 访
*
* @param end_date 访访end_date
*/
public void setEnd_date(String end_date) { public void setEnd_date(String end_date) {
this.end_date = end_date; this.end_date = end_date;
} }
/**
* 访访
*
* @return 访访访访
*/
public String getVisit_result() { public String getVisit_result() {
return visit_result; return visit_result;
} }
/**
* 访访
*
* @param visit_result 访访访visit_result访
*/
public void setVisit_result(String visit_result) { public void setVisit_result(String visit_result) {
this.visit_result = visit_result; this.visit_result = visit_result;
} }
/** /**
* toString访 * toString访
* @return 访 * 使System.out.println访访
* 便访
*
* @return 访 "Visitor{" + + '}'访
*/ */
@Override @Override
public String toString() { public String toString() {
@ -130,4 +224,4 @@ public class Visitor implements Serializable {
", visit_result='" + visit_result + '\'' + ", visit_result='" + visit_result + '\'' +
'}'; '}';
} }
} }

@ -7,6 +7,9 @@ import java.util.List;
/** /**
* Description:访访 * Description:访访
* 访
* 访
* 访
* *
* @Date: 2020/2/18 18:27 * @Date: 2020/2/18 18:27
* @Author: PeiChen * @Author: PeiChen
@ -15,52 +18,91 @@ public interface VisitorService {
/** /**
* 访 * 访
* @param visitor 访访 * 访访Visitor
* @throws Exception *
*
* @param visitor 访访访访访访
* 访
* @throws Exception
* 便
*/ */
void add(Visitor visitor) throws Exception; void add(Visitor visitor) throws Exception;
/** /**
* 访 * 访
* @param page * 访访
* @param size *
* @return 访 *
* @throws Exception * @param page
* page1
* @param size 访size1010访
* 访
* @return 访Visitor访访
* 访访访
* @throws Exception
*
*/ */
List<Visitor> findAll(int page,int size) throws Exception; List<Visitor> findAll(int page, int size) throws Exception;
/** /**
* *
* @param page * 访访
* @param size *
* @param keyword *
* @return 访 * @param page
* @throws Exception *
* @param size 访
* 2020访
* @param keyword 访访
* 访"张三""张三"访
* @return 访Visitor访
* 访便访
* @throws Exception
*
*/ */
List<Visitor> search(int page,int size,String keyword) throws Exception; List<Visitor> search(int page, int size, String keyword) throws Exception;
/** /**
* 访 * 访
* @param id 访 * 访访
* @param end_date 访 *
* @throws Exception *
* @param id 访访访
* 使UUID访
* @param end_date 访 "yyyy-MM-dd HH:mm:ss"
* 访访访
* @throws Exception
*
*/ */
void logout(String id,String end_date) throws Exception; void logout(String id, String end_date) throws Exception;
/** /**
* 访 * 访
* @return 访 * 访访Excel
* @throws Exception *
*
* @return 访访
* 访访
*
* @throws Exception 访
*
*/ */
InputStream getInputStream() throws Exception; InputStream getInputStream() throws Exception;
/** /**
* 访 * 访
* @param page * 访访
* @param size *
* @return 访 *
* @throws Exception * @param page 访
* page2访
* @param size 访访
* size1515访
* @return 访Visitor访访访
* 访访访便访访
* @throws Exception
*
*/ */
List<Visitor> log(int page,int size) throws Exception; List<Visitor> log(int page, int size) throws Exception;
} }

@ -14,18 +14,24 @@ import java.util.List;
/** /**
* Description:访VisitorService * Description:访VisitorService
* 访VisitorDao访
* PageHelperWriteExcelExcel
* *
* @Date: 2020/2/18 18:50 * @Date: 2020/2/18 18:50
* @Author: PeiChen * @Author: PeiChen
*/ */
// 使用 @Service 注解将该类标记为Spring框架中的服务层组件并指定了组件的名称为 "visitorService",方便在依赖注入时使用
@Service("visitorService") @Service("visitorService")
public class VisitorServiceImpl implements VisitorService { public class VisitorServiceImpl implements VisitorService {
// 定义一个VisitorDao类型的成员变量用于后续调用数据访问层的方法来操作数据库中的访客数据
private VisitorDao visitorDao; private VisitorDao visitorDao;
/** /**
* AutowiredVisitorDao * AutowiredVisitorDao
* @param visitorDao 访访 * @AutowiredSpringVisitorDao
* 使便访
* @param visitorDao 访访SpringVisitorDao
*/ */
@Autowired @Autowired
public void setVisitorDao(VisitorDao visitorDao) { public void setVisitorDao(VisitorDao visitorDao) {
@ -34,63 +40,95 @@ public class VisitorServiceImpl implements VisitorService {
/** /**
* 访 * 访
* @param visitor 访访 * VisitorService访Visitor
* @throws Exception * VisitorDao访
*
* @param visitor 访访访访
* @throws Exception
*/ */
@Override @Override
public void add(Visitor visitor) throws Exception { public void add(Visitor visitor) throws Exception {
// 调用VisitorDao的add方法将传入的访客对象visitor的信息插入到数据库中实现来访登记功能将访客信息持久化
visitorDao.add(visitor); visitorDao.add(visitor);
} }
/** /**
* 访 * 访
* @return 访 * VisitorService访访
* @throws Exception * PageHelperVisitorDao访
*
* @return 访Visitor访访
* @throws Exception
*/ */
@Override @Override
public List<Visitor> findAll(int page, int size) throws Exception { public List<Visitor> findAll(int page, int size) throws Exception {
// 使用PageHelper插件进行分页 // 使用PageHelper插件进行分页传入当前页码page和每页显示的记录数size参数该插件会自动拦截后续的数据库查询操作
PageHelper.startPage(page,size); // 根据设置的分页参数对查询结果进行分页处理,使得返回的结果是符合分页要求的访客记录列表
PageHelper.startPage(page, size);
// 调用VisitorDao的findAll方法从数据库中查询所有访客记录由于前面已经设置了分页这里返回的结果将是分页后的访客记录列表
// 按照来访时间降序排列由VisitorDao的findAll方法中的SQL语句决定排序方式
return visitorDao.findAll(); return visitorDao.findAll();
} }
/** /**
* 访 * 访
* @param page * VisitorService访访
* @param size * PageHelperVisitorDao访
* @param keyword *
* @return 访 * @param page
* @throws Exception * @param size 访
* @param keyword 访
* @return 访Visitor访访
* @throws Exception
*/ */
@Override @Override
public List<Visitor> search(int page, int size, String keyword) throws Exception { public List<Visitor> search(int page, int size, String keyword) throws Exception {
// 使用PageHelper插件进行分页 // 使用PageHelper插件进行分页传入当前页码page和每页显示的记录数size参数让插件为后续的数据库查询操作添加分页逻辑
PageHelper.startPage(page,size); // 确保返回符合分页要求的查询结果
PageHelper.startPage(page, size);
// 调用VisitorDao的search方法传入搜索关键字keyword从数据库中查询所有符合关键字模糊匹配条件的访客记录
// 并且按照来访时间降序排列由VisitorDao的search方法中的SQL语句决定排序方式最终返回分页后的符合条件的访客记录列表
return visitorDao.search(keyword); return visitorDao.search(keyword);
} }
/** /**
* 访访 * 访访
* @param id 访 * VisitorService访访
* @param end_date 访 * VisitorDao访访
* @throws Exception *
* @param id 访访UUID
* @param end_date 访 yyyy-MM-dd HH:mm:ss
* 访访
* @throws Exception
*/ */
@Override @Override
public void logout(String id, String end_date) throws Exception { public void logout(String id, String end_date) throws Exception {
visitorDao.logout(id,end_date); // 调用VisitorDao的logout方法传入访客的唯一标识符id和离开时间end_date在数据库中执行更新操作
// 将对应访客记录的离开时间字段更新为传入的end_date值实现访客记录的注销功能即标记访客已经离开
visitorDao.logout(id, end_date);
} }
/** /**
* 访Excel * 访Excel
* @return 访 * VisitorService访Excel访
* @throws Exception * WriteExcelExcelExcel便
*
* @return 访访ExcelExcel
* 访Excel
* @throws Exception Excel
*
*/ */
@Override @Override
public InputStream getInputStream() throws Exception { public InputStream getInputStream() throws Exception {
//Excel中的每列列名依次对应数据库的字段 // Excel中的每列列名依次对应数据库的字段定义一个字符串数组用于指定要导出到Excel文件中的列标题
String[] title = new String[]{"ID","姓名","学号","联系方式","访问地址","来访时间","离开时间","来访原因"}; // 这些标题与数据库中访客表的字段名相对应方便在Excel文件中清晰展示访客记录的各项信息
String[] title = new String[]{"ID", "姓名", "学号", "联系方式", "访问地址", "来访时间", "离开时间", "来访原因"};
// 调用VisitorDao的findAll方法从数据库中获取所有访客记录得到一个包含所有访客信息的列表后续将基于这些数据来填充Excel文件内容
List<Visitor> visitors = visitorDao.findAll(); List<Visitor> visitors = visitorDao.findAll();
// 创建一个List<Object[]>类型的列表用于存储整理后的访客数据每个Object[]数组代表一行数据,
// 数组中的元素依次对应Excel文件中的每列数据与前面定义的title列名顺序对应方便后续将数据批量写入Excel文件
List<Object[]> datalist = new ArrayList<>(); List<Object[]> datalist = new ArrayList<>();
// 遍历从数据库中获取到的所有访客记录列表visitors将每条访客记录的数据按照指定顺序整理到Object[]数组中并添加到datalist列表中
for (int i = 0; i < visitors.size(); i++) { for (int i = 0; i < visitors.size(); i++) {
Object[] obj = new Object[8]; Object[] obj = new Object[8];
obj[0] = visitors.get(i).getId(); obj[0] = visitors.get(i).getId();
@ -103,22 +141,32 @@ public class VisitorServiceImpl implements VisitorService {
obj[7] = visitors.get(i).getVisit_result(); obj[7] = visitors.get(i).getVisit_result();
datalist.add(obj); datalist.add(obj);
} }
// 使用WriteExcel类将数据写入Excel文件 // 使用WriteExcel类将数据写入Excel文件创建一个WriteExcel类的实例传入列标题title和整理好的数据列表datalist
WriteExcel excel = new WriteExcel(title,datalist); // 该类内部会实现将数据按照指定格式写入到Excel文件的逻辑并返回该Excel文件对应的输入流
WriteExcel excel = new WriteExcel(title, datalist);
// 调用WriteExcel类实例的export方法获取包含访客记录数据的Excel文件的输入流以便后续在控制器层将该输入流通过响应流发送给客户端
// 实现访客记录的导出功能客户端可以将接收到的输入流保存为本地的Excel文件进行查看和分析
return excel.export(); return excel.export();
} }
/** /**
* 访 * 访
* @param page * VisitorService访访
* @param size * PageHelperVisitorDao访
* @return 访 *
* @throws Exception * @param page 访
* @param size 访
* @return 访Visitor访访
* 访访访访
* @throws Exception
*/ */
@Override @Override
public List<Visitor> log(int page,int size) throws Exception { public List<Visitor> log(int page, int size) throws Exception {
// 使用PageHelper插件进行分页 // 使用PageHelper插件进行分页传入当前页码page和每页显示的记录数size参数该插件会自动拦截后续的数据库查询操作
PageHelper.startPage(page,size); // 根据设置的分页参数对查询结果进行分页处理,使得返回的结果是符合分页要求的访客日志记录列表
PageHelper.startPage(page, size);
// 调用VisitorDao的findAll方法从数据库中查询所有访客日志记录由于前面已经设置了分页这里返回的结果将是分页后的访客日志记录列表
// 按照来访时间降序排列由VisitorDao的findAll方法中的SQL语句决定排序方式
return visitorDao.findAll(); return visitorDao.findAll();
} }
} }

@ -6,98 +6,135 @@
To change this template use File | Settings | File Templates. To change this template use File | Settings | File Templates.
--%> --%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!-- 声明该JSP页面的内容类型是HTML格式字符编码采用UTF-8表明页面中使用Java语言编写服务器端逻辑 -->
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!-- 引入JSTLJavaServer Pages Standard Tag Library的核心标签库设置前缀为“c”方便后续在JSP页面中使用其提供的各种标签进行逻辑判断、循环遍历等操作 -->
<html class="x-admin-sm"> <html class="x-admin-sm">
<head> <head>
<!-- 设置页面字符编码为UTF-8 --> <!-- 设置页面字符编码为UTF-8,确保页面在浏览器中能正确显示各种字符,避免出现乱码情况 -->
<meta charset="UTF-8"> <meta charset="UTF-8">
<title></title> <title></title>
<!-- 设置页面渲染引擎为webkit --> <!-- 设置页面渲染所使用的引擎为webkit它能让页面在支持webkit的浏览器中以相应的渲染方式呈现提供较好的页面展示效果 -->
<meta name="renderer" content="webkit"> <meta name="renderer" content="webkit">
<!-- 确保在IE浏览器中使用最新版本的渲染模式并优先使用Chrome框架 --> <!-- 声明页面在IE浏览器中的兼容模式使页面在IE浏览器中以其最高版本的模式进行渲染若安装了Chrome Frame则优先使用Chrome Frame来渲染以增强兼容性和展示效果 -->
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<!-- 引入CSS文件设置页面样式 --> <!-- 引入自定义的字体样式表路径通过EL表达式结合pageContext对象获取项目相对路径用于设置页面中文字的字体、字号、颜色等样式相关属性 -->
<link rel="stylesheet" href="${pageContext.request.contextPath}/css/font.css"> <link rel="stylesheet" href="${pageContext.request.contextPath}/css/font.css">
<!-- 引入自定义的xadmin样式表通过EL表达式结合pageContext获取相对路径用于构建页面整体的xadmin风格布局与样式比如页面的整体色调、各组件的样式等 -->
<link rel="stylesheet" href="${pageContext.request.contextPath}/css/xadmin.css"> <link rel="stylesheet" href="${pageContext.request.contextPath}/css/xadmin.css">
<!-- 引入Bootstrap框架的样式表同样借助EL表达式结合pageContext获取路径Bootstrap可以帮助快速搭建页面的响应式布局以及提供各种常用的UI组件样式 -->
<link rel="stylesheet" href="${pageContext.request.contextPath}/css/bootstrap.css"> <link rel="stylesheet" href="${pageContext.request.contextPath}/css/bootstrap.css">
<!-- 引入JavaScript文件为页面添加交互功能 -->
<!-- 引入jQuery库其路径通过EL表达式结合pageContext获取项目相对路径jQuery是一个常用的JavaScript库方便在页面中操作DOM元素、处理事件、发起AJAX请求等 -->
<script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery-3.1.1.js"></script> <script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery-3.1.1.js"></script>
<!-- 引入layui框架的JavaScript文件指定字符编码为utf-8layui用于构建页面交互效果提供了丰富的UI组件和交互功能便于开发者打造具有良好用户体验的页面 -->
<script src="${pageContext.request.contextPath}/lib/layui/layui.js" charset="utf-8"></script> <script src="${pageContext.request.contextPath}/lib/layui/layui.js" charset="utf-8"></script>
<!-- 引入自定义的xadmin相关的JavaScript文件通过EL表达式结合pageContext获取路径这个文件可能包含了针对xadmin页面特有的交互逻辑和功能实现 -->
<script type="text/javascript" src="${pageContext.request.contextPath}/js/xadmin.js"></script> <script type="text/javascript" src="${pageContext.request.contextPath}/js/xadmin.js"></script>
<!-- 引入Bootstrap的JavaScript文件通过EL表达式结合pageContext获取路径用于实现Bootstrap框架相关的交互功能例如一些组件的动态效果等 -->
<script type="text/javascript" src="${pageContext.request.contextPath}/js/bootstrap.js"></script> <script type="text/javascript" src="${pageContext.request.contextPath}/js/bootstrap.js"></script>
<!-- 引入layer弹窗插件的JavaScript文件通过EL表达式结合pageContext获取路径layer插件常用于在页面中弹出提示框、确认框、加载层等交互效果增强用户与页面的交互性 -->
<script type="text/javascript" src="${pageContext.request.contextPath}/layer/layer.js"></script> <script type="text/javascript" src="${pageContext.request.contextPath}/layer/layer.js"></script>
<!-- 对于IE9以下版本的浏览器引入兼容性脚本 --> <!--[if lt IE 9] -->
<!--[if lt IE 9]> <!-- 条件注释针对IE浏览器版本小于9的情况引入html5shiv库其作用是让旧版本的IE浏览器能够支持HTML5的新标签使得页面在这些旧浏览器中能正常解析HTML5相关的结构 -->
<script src="https://cdn.staticfile.org/html5shiv/r29/html5.min.js"></script> <script src="https://cdn.staticfile.org/html5shiv/r29/html5.min.js"></script>
<!-- 引入respond.js库用于让旧版本IE浏览器支持CSS3媒体查询确保页面在不同设备尺寸下的样式适配能在旧IE浏览器中正常工作 -->
<script src="https://cdn.staticfile.org/respond.js/1.4.2/respond.min.js"></script> <script src="https://cdn.staticfile.org/respond.js/1.4.2/respond.min.js"></script>
<![endif]--> <![endif]-->
<!-- 定义JavaScript函数用于改变每页显示的数据条数 -->
<script> <script>
function changePageSize() { function changePageSize() {
//获取下拉框的值 // 获取id为changePageSize的下拉框元素的值这个值代表了用户期望设置的每页显示数据的条数
// 通过jQuery选择器$("#changePageSize")选中该下拉框元素,再使用.val()方法获取其当前选中的值
var pageSize = $("#changePageSize").val(); var pageSize = $("#changePageSize").val();
//向服务器发送请求改变每页显示条数并重置页码为1 // 通过修改浏览器地址栏的URL向服务器发送请求请求的路径是/visitor/findAll传递参数page=1表示显示第一页
// size为获取到的下拉框的值以此改变每页显示的条数实现用户切换每页显示数据量的功能
// 这里利用了location.href属性来重定向页面到指定的URL
location.href = "${pageContext.request.contextPath}/visitor/findAll?page=1&size="+ pageSize; location.href = "${pageContext.request.contextPath}/visitor/findAll?page=1&size="+ pageSize;
} }
$("#serarch_btn").click(function () { $("#serarch_btn").click(function () {
// 获取id为keyword的输入框元素的值通常这个值是用户输入的用于搜索的关键词例如访客姓名、学号等
// 通过jQuery选择器$("#keyword")选中该输入框元素,再使用.val()方法获取其当前输入的值
var keyword = $("#keyword").val(); var keyword = $("#keyword").val();
// 根据关键词搜索重置页码为1每页显示5条记录 // 通过修改浏览器地址栏的URL向服务器发送请求请求的路径是/visitor/findAll传递参数page=1表示显示第一页
// size=5表示每页显示5条记录keyword为获取到的搜索关键词用于根据用户输入的关键词进行搜索并展示相应的访客信息
// 同样利用location.href属性来重定向页面到指定的带有搜索参数的URL
location.href="${pageContext.request.contextPath}/visitor/findAll?page=1&size=5&keyword="+keyword; location.href="${pageContext.request.contextPath}/visitor/findAll?page=1&size=5&keyword="+keyword;
}); });
$("#refresh").click(function () { $("#refresh").click(function () {
// 尝试重置id为myform的表单元素此处重置方式可能不准确更准确的写法可能是$("#myform")[0].reset(); ),目的是将表单内的输入框等元素的值重置为初始状态,
// 例如清空用户输入的搜索关键词等内容不过当前写法依赖于具体的表单库是否支持这样直接调用reset方法可能存在兼容性问题
$("#myform").reset(); $("#myform").reset();
// 重置表单并请求第一页的数据每页显示5条记录 // 通过修改浏览器地址栏的URL向服务器发送请求请求的路径是/visitor/findAll传递参数page=1表示显示第一页
// size=5表示每页显示5条记录达到刷新页面数据的效果即将页面恢复到初始的显示状态展示第一页且每页显示5条记录的数据情况
// 借助location.href属性来实现页面重定向到相应的URL
location.href="${pageContext.request.contextPath}/visitor/findAll?page=1&size=5"; location.href="${pageContext.request.contextPath}/visitor/findAll?page=1&size=5";
}); });
</script> </script>
</head> </head>
<body> <body>
<%-- 以下这部分代码被注释掉了,原本可能是用于展示页面导航相关元素,包含面包屑导航以及一个刷新按钮,点击按钮可刷新页面,但当前处于注释状态,不会在页面中显示生效 --%>
<%--<div class="x-nav"> <%--<div class="x-nav">
<span class="layui-breadcrumb"> <span class="layui-breadcrumb">
<a href="">首页</a> <a href="">首页</a>
<a href="">演示</a> <a href="">演示</a>
<a> <a>
<cite>导航元素</cite></a> <cite>导航元素</cite></a>
</span> </span>
<a class="layui-btn layui-btn-small" style="line-height:1.6em;margin-top:3px;float:right" onclick="location.reload()" title="刷新"> <a class="layui-btn layui-btn-small" style="line-height:1.6em;margin-top:3px;float:right" onclick="location.reload()" title="刷新">
<i class="layui-icon layui-icon-refresh" style="line-height:30px"></i></a> <i class="layui-icon layui-icon-refresh" style="line-height:30px"></i></a>
</div>--%> </div>--%>
<%-- 页面主体部分使用LayUI流体布局 --%> <!-- 使用layui-fluid类创建一个流体布局容器使得内部的元素可以根据页面宽度自适应排列常用于实现响应式布局 -->
<div class="layui-fluid"> <div class="layui-fluid">
<!-- 创建一个layui的行元素layui-col-space15表示设置列间距为15像素用于对内部的列元素进行布局管理 -->
<div class="layui-row layui-col-space15"> <div class="layui-row layui-col-space15">
<!-- 创建一个占12列的layui列元素在layui的栅格系统中一行默认分为12列这里表示占满一整行 -->
<div class="layui-col-md12"> <div class="layui-col-md12">
<!-- 创建一个layui卡片组件用于将内部的内容以卡片的形式展示通常有边框、阴影等样式效果使页面结构更清晰美观 -->
<div class="layui-card"> <div class="layui-card">
<%-- 表单区域,用于搜索 --%> <!-- 创建卡片的主体内容区域,用于放置表单相关元素 -->
<div class="layui-card-body "> <div class="layui-card-body ">
<!-- 创建一个id为myform的表单应用layui的表单样式类layui-form并且设置列间距为5像素用于布局表单内的各个元素 -->
<form id="myform" class="layui-form layui-col-space5"> <form id="myform" class="layui-form layui-col-space5">
<%-- 搜索框 --%> <!-- 创建一个行内块元素layui-show-xs-block表示在小屏幕如手机端下显示该元素方便在不同屏幕尺寸下进行布局控制 -->
<div class="layui-inline layui-show-xs-block"> <div class="layui-inline layui-show-xs-block">
<!-- 创建一个文本输入框设置自动补全关闭autocomplete="off"添加提示占位文本“请输入关键字”指定name和id属性
并且其值通过EL表达式从请求参数中获取名为keyword的值如果有的话方便实现根据用户输入的关键字进行搜索功能 -->
<input class="layui-input" type="text" autocomplete="off" placeholder="请输入关键字" name="keyword" id="keyword" value="${param.keyword}"> <input class="layui-input" type="text" autocomplete="off" placeholder="请输入关键字" name="keyword" id="keyword" value="${param.keyword}">
</div> </div>
<%-- 搜索按钮 --%> <!-- 创建一个按钮应用layui的按钮样式类layui-btn指定id为serarch_btn此处可能有拼写错误正确应为search_btn
并设置了layui表单相关的提交和过滤属性lay-submit和lay-filter按钮内包含一个layui图标点击该按钮可能触发表单提交或者搜索操作 -->
<div class="layui-inline layui-show-xs-block"> <div class="layui-inline layui-show-xs-block">
<button class="layui-btn" id="serarch_btn" lay-submit="" lay-filter="sreach"><i class="layui-icon">&#xe615;</i></button> <button class="layui-btn" id="serarch_btn" lay-submit="" lay-filter="sreach"><i class="layui-icon">&#xe615;</i></button>
</div> </div>
<%-- 重置按钮(回到第一页) --%> <!-- 创建一个链接样式的按钮应用layui的正常样式类layui-btn-normal点击后跳转到指定路径路径通过EL表达式结合pageContext生成
用于获取所有访客信息并设置每页显示5条数据按钮内包含一个layui图标可能用于实现回到第一页且每页显示固定条数数据的功能通常作为重置按钮的一种体现 -->
<div class="layui-inline layui-show-xs-block x-right"> <div class="layui-inline layui-show-xs-block x-right">
<a class="layui-btn layui-btn-normal" href="${pageContext.request.contextPath}/visitor/findAll?page=1&size=5"><i class="layui-icon">&#xe669;</i></a> <a class="layui-btn layui-btn-normal" href="${pageContext.request.contextPath}/visitor/findAll?page=1&size=5"><i class="layui-icon">&#xe669;</i></a>
</div> </div>
</form> </form>
</div> </div>
<%-- 导出按钮和总数据条数显示 --%> <!-- 自定义的<xblock>标签具体功能可能由相关的CSS或JavaScript根据业务逻辑来定义在这里用于包裹导出按钮和总数据条数显示相关的元素 -->
<xblock> <xblock>
<a onclick="exportInfo(${sessionScope.adminInfo.power})" class="layui-btn layui-btn-warm" href="javascript:;"><i class="layui-icon">&#xe67c;</i>导出</a> <!-- 创建一个链接样式按钮点击时调用exportInfo函数并传入管理员权限值从会话中获取按钮显示为“导出”包含一个layui图标用于触发导出访客数据的相关操作 -->
<a onclick="exportInfo(${sessionScope.adminInfo.power})" class="layui-btn layui-btn-warm" href="javascript:;"><i class="layui-icon">&#xe67c;</i>导出</a>
<!-- 显示总的访客数据条数信息设置了行高为40px的样式靠右对齐通过x-right类实现用于向用户展示当前访客数据的总量情况 -->
<span class="x-right" style="line-height:40px">共有数据:${pageInfo.total} 条</span> <span class="x-right" style="line-height:40px">共有数据:${pageInfo.total} 条</span>
</xblock> </xblock>
<%-- 数据表格区域 --%> <!-- 创建另一个卡片主体内容区域,可能用于展示不同部分的内容,这里用于放置访客信息表格 -->
<div class="layui-card-body"> <div class="layui-card-body">
<!-- 创建一个使用layui样式的表格同时应用layui的表单样式方便后续可能的表单相关交互操作比如行内编辑等 -->
<table class="layui-table layui-form"> <table class="layui-table layui-form">
<thead> <thead>
<tr style="text-align: center"> <tr style="text-align: center">
<!-- 创建表格的表头行,设置文本居中显示 -->
<th style="text-align: center">ID</th> <th style="text-align: center">ID</th>
<th style="text-align: center">姓名</th> <th style="text-align: center">姓名</th>
<th style="text-align: center">学号</th> <th style="text-align: center">学号</th>
@ -106,34 +143,41 @@
<th style="text-align: center">来访时间</th> <th style="text-align: center">来访时间</th>
<th style="text-align: center">离开时间</th> <th style="text-align: center">离开时间</th>
<th style="text-align: center">到访原因</th> <th style="text-align: center">到访原因</th>
<!-- 如果管理员权限大于2则显示操作列 --> <!-- 通过JSTL的条件判断如果管理员权限大于2则显示操作列,用于放置针对访客记录的操作按钮(比如删除、修改等操作) -->
<c:if test="${sessionScope.adminInfo.power > 2}"> <c:if test="${sessionScope.adminInfo.power > 2}">
<th style="text-align: center">操作</th> <th style="text-align: center">操作</th>
</c:if> </c:if>
</tr>
</thead> </thead>
<tbody> <tbody>
<%-- 使用JSP脚本循环遍历访客列表 --%>
<% <%
int j = 1; // 初始化计数器,用于行编号 // 在JSP脚本片段中定义一个局部变量j并初始化为1用于给表格中的数据行编号混合使用了JSP脚本片段和JSTL标签库来构建表格数据展示
int j = 1;
%> %>
<!-- 遍历分页后的访客列表 --> <!-- 使用JSTL的forEach标签循环遍历pageInfo.list中的数据通常是分页后的访客列表集合每次循环将当前元素赋值给visitor变量方便在表格中展示各个访客的详细信息 -->
<c:forEach items="${pageInfo.list}" var="visitor"> <c:forEach items="${pageInfo.list}" var="visitor">
<tr id="light" style="text-align: center"> <tr id="light" style="text-align: center">
<!-- 在表格行数据中第一列显示行号通过JSP脚本片段输出变量j的值并在每次循环后自增1实现逐行编号的效果 -->
<td><%=j++%></td> <td><%=j++%></td>
<!-- 通过EL表达式从名为visitor的对象中获取姓名属性值展示访客的姓名信息 -->
<td>${visitor.name}</td> <td>${visitor.name}</td>
<!-- 通过EL表达式从名为visitor的对象中获取学号属性值展示访客的学号信息 -->
<td>${visitor.sno}</td> <td>${visitor.sno}</td>
<td>${visitor.phone}</td> <!-- 通过EL表达式从名为visitor的对象中获取联系方式属性值展示访客的联系方式信息 -->
<td>${visitor.place}</td> <td>${visitor.place}</td>
<!-- 通过EL表达式从名为visitor的对象中获取来访时间属性值展示访客的来访时间信息 -->
<td>${visitor.begin_date}</td> <td>${visitor.begin_date}</td>
<%-- 判断访客是否已离开 --%> <!-- 通过JSTL的条件判断访客的离开时间是否为空如果为空则显示“尚未离开”用于提示访客当前是否还在访问中 -->
<c:if test="${visitor.end_date == null || visitor.end_date == ''}"> <c:if test="${visitor.end_date == null || visitor.end_date == ''}">
<td>尚未离开</td> <td>尚未离开</td>
</c:if> </c:if>
<c:if test="${visitor.end_date != ''}"> <!-- 如果离开时间不为空则通过EL表达式获取并显示具体的离开时间 -->
<c:if test="${visitor.end_date!= ''}">
<td>${visitor.end_date}</td> <td>${visitor.end_date}</td>
</c:if> </c:if>
<td>${visitor.visit_result}</td> <td>${visitor.visit_result}</td>
<!-- 如果管理员权限大于2则显示注销按钮 --> <!-- 通过JSTL的条件判断如果管理员权限大于2则显示操作列中的具体操作按钮这里定义一个链接点击时调用toUpdate函数并传入访客的id
按钮显示为一个图标,提示文本为“注销访客”,用于触发注销访客记录的相关操作 -->
<c:if test="${sessionScope.adminInfo.power > 2}"> <c:if test="${sessionScope.adminInfo.power > 2}">
<td class="td-manage"> <td class="td-manage">
<a title="注销访客" onclick="toUpdate('${visitor.id}');" href="javascript:;"> <a title="注销访客" onclick="toUpdate('${visitor.id}');" href="javascript:;">
@ -146,114 +190,283 @@
</tbody> </tbody>
</table> </table>
</div> </div>
<%-- 分页控制区域 --%> <!-- 设置该元素向左浮动,常用于布局排版,使其在页面中向左对齐排列 -->
<div class="pull-left"> <div class="pull-left">
<!-- 创建一个表单组,设置为行内表单样式,方便在一行内展示多个表单相关元素 -->
<div class="form-group form-inline"> <div class="form-group form-inline">
<!-- 显示分页相关信息,如总页数、当前页码等,告知用户当前的分页情况 -->
共&nbsp;${pageInfo.pages}&nbsp;页&emsp;当前页:${pageInfo.pageNum}&nbsp;/&nbsp;${pageInfo.pages}&emsp; 每页 共&nbsp;${pageInfo.pages}&nbsp;页&emsp;当前页:${pageInfo.pageNum}&nbsp;/&nbsp;${pageInfo.pages}&emsp; 每页
<!-- 下拉菜单选择每页显示条数 --> <!-- 创建一个下拉菜单应用表单控件的样式类form-control绑定了id为changePageSize当下拉框选项改变时会调用changePageSize函数来改变每页显示条数 -->
<select class="form-control" id="changePageSize" onchange="changePageSize()"> <select class="form-control" id="changePageSize" onchange="changePageSize()">
<!-- 为下拉菜单添加各个选项,每个<option>标签代表一个可选择的每页显示条数的值,
初始显示的值通过EL表达式从pageInfo对象中获取相关属性值用户可选择不同的选项来改变每页显示的数据量 -->
<option value="1">${pageInfo.size}</option> <option value="1">${pageInfo.size}</option>
<option value="5">5</option> <option value="5">5</option>
<option value="10">10</option> <option value="10">10</option>
// 这是一个下拉菜单中的选项(<option>)标签,表示当用户选择该项时,
// 对应的值为10意味着每页显示10条数据用于设置每页显示数据量的可选项之一
<option value="15">15</option> <option value="15">15</option>
// 同样是下拉菜单中的选项标签选择该项则表示每页显示15条数据是提供给用户选择每页数据条数的一个选项
<option value="20">20</option> <option value="20">20</option>
// 下拉菜单中的选项标签若用户选择此项每页将显示20条数据作为可配置每页显示数量的一个选项
</select> 条 </select> 条
<!-- 结束下拉菜单标签,“条”字可能是用于在页面上更友好地提示用户该下拉菜单是用于选择每页显示数据的条数 -->
</div> </div>
// 结束一个外层的div容器这个div可能用于布局包裹与每页显示条数选择相关的元素等
</div> </div>
<%-- 分页按钮逻辑控制 --%> // 结束另一个外层的div容器可能在页面布局层级中处于更上层具体作用需结合整体页面结构来看
<!-- 分页按钮逻辑控制 -->
// 这是一个HTML注释用于说明下面的代码块主要是用于控制分页按钮的显示逻辑方便后续阅读和维护代码
<c:choose> <c:choose>
// 使用JSTLJavaServer Pages Standard Tag Library的标签开始一个条件选择结构
// 类似于Java中的switch语句用于根据不同条件执行不同的逻辑分支
<c:when test="${pageInfo.pages < 5}"> <c:when test="${pageInfo.pages < 5}">
// 标签表示一个具体的条件分支这里的条件是判断pageInfo对象中的pages属性通常表示总页数是否小于5
// 如果满足该条件,则执行此分支内的代码
<c:set var="begin" value="1"> <c:set var="begin" value="1">
// 使用标签在JSP页面中设置一个名为“begin”的变量值设置为1
// 这个变量可能后续用于确定分页页码显示的起始范围等相关逻辑
</c:set> </c:set>
<c:set var="end" value="${pageInfo.pages}"> <c:set var="end" value="${pageInfo.pages}">
// 同样使用标签设置一个名为“end”的变量其值设置为pageInfo对象中的pages属性值即总页数
// 用于配合“begin”变量来确定分页页码显示的范围
</c:set> </c:set>
</c:when> </c:when>
<c:when test="${pageInfo.pageNum <= 3}"> <c:when test="${pageInfo.pageNum <= 3}">
// 另一个条件分支判断pageInfo对象中的pageNum属性通常表示当前页码是否小于等于3
// 如果满足该条件,则执行此分支内的代码,用于设置不同情况下分页页码显示的范围
<c:set var="begin" value="1"> <c:set var="begin" value="1">
// 设置名为“begin”的变量值为1为后续确定分页页码显示范围做准备
</c:set> </c:set>
<c:set var="end" value="5"> <c:set var="end" value="5">
// 设置名为“end”的变量值为5结合“begin”变量来确定在当前页码小于等于3这种情况下分页页码显示的范围
</c:set> </c:set>
</c:when> </c:when>
<c:when test="${pageInfo.pageNum > 3 and pageInfo.pageNum <= pageInfo.pages-2}"> <c:when test="${pageInfo.pageNum > 3 and pageInfo.pageNum <= pageInfo.pages - 2}">
// 又一个条件分支判断当前页码pageInfo.pageNum大于3并且小于等于总页数减2时执行此分支内的代码
// 用于根据当前页码在特定区间时设置分页页码显示的范围
<c:set var="begin" value="${pageInfo.pageNum - 2}"> <c:set var="begin" value="${pageInfo.pageNum - 2}">
// 根据当前页码动态计算“begin”变量的值将其设置为当前页码减2以此来确定合适的分页页码显示起始范围
</c:set> </c:set>
<c:set var="end" value="${pageInfo.pageNum + 2}"> <c:set var="end" value="${pageInfo.pageNum + 2}">
// 根据当前页码动态计算“end”变量的值设置为当前页码加2与“begin”变量配合确定分页页码显示的范围
</c:set> </c:set>
</c:when> </c:when>
<c:otherwise> <c:otherwise>
// otherwise标签表示当上述所有条件都不满足时执行的代码分支相当于Java中switch语句的default分支
<c:set var="begin" value="${pageInfo.pages - 4}"> <c:set var="begin" value="${pageInfo.pages - 4}">
// 设置名为“begin”的变量值为总页数减4用于确定在其他情况之外的分页页码显示起始范围
</c:set> </c:set>
<c:set var="end" value="${pageInfo.pages}"> <c:set var="end" value="${pageInfo.pages}">
// 设置名为“end”的变量值为总页数与“begin”变量配合确定分页页码显示的范围
</c:set> </c:set>
</c:otherwise> </c:otherwise>
</c:choose> </c:choose>
<div class="layui-card-body x-right" style="height: min-content"> <div class="layui-card-body x-right" style="height: min-content">
<div class="page"> // 创建一个使用layui样式的卡片主体内容区域layui-card-body并应用了x-right类可能用于控制布局靠右显示等
<div> // 设置了高度样式为min-content使该区域的高度根据其内部内容自适应最小化高度占用
<a class="next" href="${pageContext.request.contextPath}/visitor/findAll?page=1&size=${pageInfo.pageSize}&keyword=${param.keyword}">首页</a>
<c:if test="${pageInfo.pageNum > 1}"> <div class="page">
<a class="prev" href="${pageContext.request.contextPath}/visitor/findAll?page=${pageInfo.pageNum-1}&size=${pageInfo.pageSize}&keyword=${param.keyword}">上一页</a> // 创建一个自定义类名为“page”的<div>容器,可能用于专门放置分页相关的按钮等元素,进行布局分组
</c:if>
<c:forEach var="i" begin="${begin}" end="${end}" step="1"> <div>
<c:if test="${pageInfo.pageNum == i}"> // 再创建一个内层的<div>容器,用于进一步细化分页按钮等元素的布局
<span class="current">${i}</span>
</c:if> <a class="next" href="${pageContext.request.contextPath}/visitor/findAll?page=1&size=${pageInfo.pageSize}&keyword=${param.keyword}">首页</a>
<c:if test="${pageInfo.pageNum != i}"> // 创建一个链接应用了名为“next”的类可能有对应的CSS样式用于外观控制
<a class="num" href="${pageContext.request.contextPath}/visitor/findAll?page=${i}&size=${pageInfo.pageSize}&keyword=${param.keyword}">${i}</a> // href属性通过EL表达式拼接出具体的URL路径用于跳转到访客信息列表的第一页同时传递了每页显示条数pageInfo.pageSize和搜索关键词param.keyword等参数
</c:if> // 链接显示的文本为“首页”,方便用户点击回到第一页
</c:forEach>
<!-- 下一页链接,当不是最后一页时显示 --> <c:if test="${pageInfo.pageNum > 1}">
<c:if test="${pageInfo.pageNum < pageInfo.pages}"> // 使用JSTL的条件判断标签判断pageInfo对象中的pageNum属性当前页码是否大于1
<a class="next" href="${pageContext.request.contextPath}/visitor/findAll?page=${pageInfo.pageNum+1}&size=${pageInfo.pageSize}&keyword=${param.keyword}">下一页</a> // 如果满足该条件,则执行此标签内包含的代码,用于判断是否显示上一页按钮
</c:if>
<!-- 尾页链接 --> <a class="prev" href="${pageContext.request.contextPath}/visitor/findAll?page=${pageInfo.pageNum - 1}&size=${pageInfo.pageSize}&keyword=${param.keyword}">上一页</a>
<a class="next" href="${pageContext.request.contextPath}/visitor/findAll?page=${pageInfo.pages}&size=${pageInfo.pageSize}&keyword=${param.keyword}">尾页</a> // 创建一个链接应用“prev”类可能对应特定样式href属性通过EL表达式拼接出URL路径
</div> // 用于跳转到上一页当前页码减1同时传递每页显示条数和搜索关键词等参数链接显示文本为“上一页”方便用户进行翻页操作
</div>
</c:if>
<c:forEach var="i" begin="${begin}" end="${end}" step="1">
// 使用JSTL的forEach循环标签开始一个循环循环变量为“i”循环的起始值为之前设置的“begin”变量的值
// 结束值为“end”变量的值步长为1即依次遍历从“begin”到“end”范围的每一个值用于生成分页页码链接
<c:if test="${pageInfo.pageNum == i}">
// 在循环内部再次使用条件判断标签判断当前页码pageInfo.pageNum是否等于循环变量“i”的值
// 如果相等,则执行此标签内的代码,用于对当前页码进行特殊样式显示等处理
<span class="current">${i}</span>
// 创建一个span标签应用了“current”类可能有对应的突出显示当前页码的样式并通过EL表达式显示循环变量“i”的值
// 用于将当前页码以特定样式展示出来,与其他页码区分开
</c:if>
<c:if test="${pageInfo.pageNum!= i}">
// 另一个条件判断标签判断当前页码是否不等于循环变量“i”的值如果不相等则执行此标签内的代码
// 用于生成普通的页码链接(非当前页码的情况)
<a class="num" href="${pageContext.request.contextPath}/visitor/findAll?page=${i}&size=${pageInfo.pageSize}&keyword=${param.keyword}">${i}</a>
// 创建一个链接应用“num”类可能对应普通页码链接的样式href属性通过EL表达式拼接出URL路径
// 用于跳转到对应页码循环变量“i”表示的页码同时传递每页显示条数和搜索关键词等参数链接内通过EL表达式显示循环变量“i”的值作为页码显示内容方便用户点击跳转到相应页码
</c:if>
</c:forEach>
<!-- 下一页链接,当不是最后一页时显示 -->
// 这是一个HTML注释说明下面的代码是用于在不是最后一页的情况下显示下一页的链接
<c:if test="${pageInfo.pageNum < pageInfo.pages}">
// 使用JSTL的条件判断标签判断当前页码pageInfo.pageNum是否小于总页数pageInfo.pages
// 如果满足该条件,则执行此标签内的代码,用于判断是否显示下一页链接
<a class="next" href="${pageContext.request.contextPath}/visitor/findAll?page=${pageInfo.pageNum + 1}&size=${pageInfo.pageSize}&keyword=${param.keyword}">下一页</a>
// 创建一个链接(<a>标签应用“next”类href属性通过EL表达式拼接出URL路径用于跳转到下一页当前页码加1
// 同时传递每页显示条数和搜索关键词等参数,链接显示文本为“下一页”,方便用户进行翻页操作
</c:if>
<!-- 尾页链接 -->
// 这是一个HTML注释说明下面的代码是用于显示尾页的链接
<a class="next" href="${pageContext.request.contextPath}/visitor/findAll?page=${pageInfo.pages}&size=${pageInfo.pageSize}&keyword=${param.keyword}">尾页</a>
// 创建一个链接应用“next”类href属性通过EL表达式拼接出URL路径用于跳转到最后一页总页数对应的页码
// 同时传递每页显示条数和搜索关键词等参数,链接显示文本为“尾页”,方便用户直接跳转到最后一页
</div> </div>
</div> // 结束内层的<div>容器,该容器用于放置分页相关的各个链接按钮等元素
</div>
</div> </div>
</div> // 结束类名为“page”的<div>容器,其整体用于对分页相关元素进行布局分组
<script> </div>
//导出Excel操作 // 结束应用了layui样式和特定布局类x-right等的卡片主体内容区域的<div>容器
function exportInfo(power) {
// 检查当前用户的权限等级如果权限小于3则没有导出权限 </div>
if (power < 3) { // 结束外层的一个<div>容器,其在页面布局层级中有相应的位置和作用(结合整体结构确定)
// 使用layer插件显示提示信息告知用户没有权限
layer.msg('对不起,您没有权限导出访客记录'); </div>
return false; // 结束另一个外层的<div>容器,同样在页面布局中处于一定层级,与整体页面结构相关
}
// 弹出确认框询问用户是否确定要导出所有访客数据 </div>
layer.confirm('确定导出所有访客数据吗?',function (index) { // 结束可能是更外层的一个<div>容器,是页面布局中的一部分
// 当用户点击确定时重定向到导出访客信息的URL
location.href="${pageContext.request.contextPath}/visitor/visitorInfo"; </div>
layer.close(index); // 关闭确认框 // 结束最外层的一个div容器完成整个页面主体部分的布局结构
});
</div>
// 结束包含页面主体流体布局layui-fluid的div容器该容器实现了页面的整体流体布局效果
</div>
// 结束包含页面主体行布局layui-row的div容器该行布局内设置了列间距等用于管理列元素的布局
</div>
// 结束包含页面主体列布局layui-col-md12的div容器该列布局占满中等屏幕及以上尺寸下的一行
</div>
// 结束layui卡片layui-card组件的div容器卡片组件用于以卡片形式展示内部内容使页面结构更清晰美观
</body>
// 结束HTML页面的body部分body内包含了页面实际展示的所有内容元素
<script>
// 开始JavaScript代码块用于定义在页面中可执行的客户端脚本逻辑
//导出Excel操作
// 这是一个JavaScript函数的注释说明下面定义的函数主要用于处理导出Excel相关的操作
function exportInfo(power) {
// 定义一个名为exportInfo的JavaScript函数接收一个名为power的参数该参数可能用于表示用户权限等相关信息
// 用于在函数内部根据权限判断是否允许执行导出操作
// 检查当前用户的权限等级如果权限小于3则没有导出权限
if (power < 3) {
// 使用if条件语句判断传入的权限值power是否小于3如果小于3则表示用户没有导出权限执行下面的代码块
// 使用layer插件显示提示信息告知用户没有权限
layer.msg('对不起,您没有权限导出访客记录');
// 调用layer插件提供的msg方法弹出一个提示框显示“对不起您没有权限导出访客记录”的提示信息告知用户当前操作权限不足
return false;
// 函数执行到此处直接返回false表示导出操作不被允许终止函数后续的执行
} }
// 弹出确认框询问用户是否确定要导出所有访客数据
layer.confirm('确定导出所有访客数据吗?',function (index) {
// 调用layer插件提供的confirm方法弹出一个确认框显示“确定导出所有访客数据吗”的提示信息
// 同时传入一个回调函数当用户点击确认框上的按钮时会执行该回调函数回调函数接收一个参数index用于后续操作确认框如关闭等
// 当用户点击确定时重定向到导出访客信息的URL
location.href="${pageContext.request.contextPath}/visitor/visitorInfo";
// 当用户在确认框中点击确定按钮后通过修改浏览器的location.href属性重定向到指定的URL路径
// 该路径通过EL表达式拼接出用于导出访客信息的具体地址触发实际的导出操作具体由服务器端逻辑处理
// 注销访客记录 layer.close(index); // 关闭确认框
function toUpdate(id) { // 调用layer插件提供的close方法传入之前接收的index参数用于关闭弹出的确认框完成导出操作相关的交互流程
// 使用layer组件的confirm方法弹出确认框询问用户是否确定要注销此访客记录
layer.confirm('确定要注销此访客记录吗',function (index) { });
// 用户点击确定后关闭确认框 }
layer.close(index);
// 发送异步请求到服务器端更新访客状态 // 注销访客记录
$.get("${pageContext.request.contextPath}/visitor/updateStatus",{"id":id},function (data) { // 这是一个JavaScript函数的注释说明下面定义的函数主要用于处理注销访客记录相关的操作
// 根据服务器返回的数据判断操作是否成功 function toUpdate(id) {
if (data) { // 定义一个名为toUpdate的JavaScript函数接收一个名为id的参数该参数通常用于表示要注销的访客记录的唯一标识
// 成功时显示成功消息并在2秒后刷新页面 // 用于在函数内部向服务器发送请求来更新对应访客记录的状态
layer.msg('注销成功');
setTimeout(function () {window.location.href='${pageContext.request.contextPath}/visitor/findAll';},2000); // 使用layer组件的confirm方法弹出确认框询问用户是否确定要注销此访客记录
}else { layer.confirm('确定要注销此访客记录吗',function (index) {
// 失败时显示错误消息并在2秒后刷新页面 // 调用layer插件提供的confirm方法弹出一个确认框显示“确定要注销此访客记录吗”的提示信息
layer.msg('系统繁忙,请联系系统管理员'); // 同时传入一个回调函数当用户点击确认框上的按钮时会执行该回调函数回调函数接收一个参数index用于后续操作确认框如关闭等
setTimeout(function () {window.location.href='${pageContext.request.contextPath}/visitor/findAll';},2000);
} // 用户点击确定后关闭确认框
}); layer.close(index);
// 当用户在确认框中点击确定按钮后调用layer插件提供的close方法传入之前接收的index参数关闭弹出的确认框
// 发送异步请求到服务器端更新访客状态
$.get("${pageContext.request.contextPath}/visitor/updateStatus",{"id":id},function (data) {
// 使用jQuery库提供的$.get方法发送一个GET类型的异步请求请求的URL地址通过EL表达式拼接出指向用于更新访客状态的服务器端接口/visitor/updateStatus
// 同时传递一个名为“id”的参数其值为传入函数的id参数表示要更新状态的访客记录的标识
// 并传入一个回调函数当服务器端返回响应数据后会执行该回调函数回调函数接收一个参数data代表服务器返回的数据
// 根据服务器返回的数据判断操作是否成功
if (data) {
// 使用if条件语句判断服务器返回的数据data是否为真值具体真值的判断依据由服务器端返回的数据格式和逻辑决定
// 如果为真值,则表示更新操作成功,执行下面的代码块
// 成功时显示成功消息并在2秒后刷新页面
layer.msg('注销成功');
// 调用layer插件提供的msg方法弹出一个提示框显示“注销成功”的提示信息告知用户操作已成功
setTimeout(function () {window.location.href='${pageContext.request.contextPath}/visitor/findAll';},2000);
// 使用JavaScript的setTimeout函数设置一个定时器在2000毫秒2秒后执行传入的回调函数
// 回调函数内通过修改浏览器的window.location.href属性重定向到指定的URL路径/visitor/findAll实现刷新页面的效果
// 重新加载访客信息列表页面,展示更新后的访客数据情况
}else {
// 如果服务器返回的数据为假值(不符合成功的判断条件),则表示更新操作失败,执行下面的代码块
// 失败时显示错误消息并在2秒后刷新页面
layer.msg('系统繁忙,请联系系统管理员');
// 调用layer插件提供的msg方法弹出一个提示框显示“系统繁忙请联系系统管理员”的提示信息告知用户操作失败及相应的解决建议
setTimeout(function () {window.location.href='${pageContext.request.contextPath}/visitor/findAll';},2000);
// 同样使用setTimeout函数设置定时器在2秒后重定向到访客信息列表页面/visitor/findAll刷新页面
// 以便用户可以查看操作失败后的当前访客数据情况,或者再次尝试操作
}
}); });
} });
}
</script> </script>
</body> </body>
</html> </html>

@ -6,89 +6,108 @@
To change this template use File | Settings | File Templates. To change this template use File | Settings | File Templates.
--%> --%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!-- 声明该JSP页面的内容类型为text/html即HTML格式字符编码采用UTF-8表明页面将以HTML格式展示并且在服务器端使用Java语言编写相关逻辑 -->
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!-- 引入JSTLJavaServer Pages Standard Tag Library的核心标签库设置前缀为“c”方便后续在JSP页面中使用其提供的各种标签进行如条件判断、循环遍历等操作 -->
<html> <html>
<head> <head>
<%-- 设置页面的字符编码为UTF-8 --%> <!-- 设置页面的字符编码为utf-8确保浏览器能正确解析并显示页面中的各种字符防止出现乱码现象 -->
<meta charset="utf-8"> <meta charset="utf-8">
<%-- 设置页面渲染引擎为webkit --%> <!-- 设置页面渲染所使用的引擎为webkit让页面在支持webkit的浏览器中按照该引擎的规则进行渲染有助于呈现出期望的页面样式和交互效果 -->
<meta name="renderer" content="webkit"> <meta name="renderer" content="webkit">
<!-- 确保在IE浏览器中使用最新版本的渲染模式并优先使用Chrome框架 --> <!-- 声明页面在IE浏览器中的兼容模式使页面在IE浏览器中以其最高可用版本的模式来渲染如果安装了Chrome Frame插件则优先使用该插件进行渲染以此增强页面在IE浏览器中的兼容性和显示效果 -->
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<!-- 设置响应式布局,使页面适应不同尺寸的设备 --> <!-- 设置页面的视口viewport属性width=device-width表示页面宽度跟随设备宽度自适应initial-scale=1设置初始缩放比例为1
maximum-scale=1限制最大缩放比例为1用于确保页面在移动设备等不同屏幕尺寸下能有合适的展示效果 -->
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<!-- 页面标题 -->
<title>Title</title> <title>Title</title>
<!-- 引入layui框架的CSS样式表路径通过EL表达式结合pageContext对象获取项目相对路径用于为页面应用layui框架提供的各种样式构建页面的外观布局 -->
<!-- 引入layui框架的CSS样式文件 -->
<link rel="stylesheet" href="${pageContext.request.contextPath}/lib/layui/css/layui.css"> <link rel="stylesheet" href="${pageContext.request.contextPath}/lib/layui/css/layui.css">
<!-- 引入layui框架中layer模块的默认CSS样式表用于为layer弹出层等相关组件设置特定的样式使其展示效果符合预期 -->
<link rel="stylesheet" href="${pageContext.request.contextPath}/lib/layui/css/modules/layer/default/layer.css"> <link rel="stylesheet" href="${pageContext.request.contextPath}/lib/layui/css/modules/layer/default/layer.css">
<!-- 引入jQuery库用于DOM操作和事件处理 --> <!-- 引入jQuery库其路径通过EL表达式结合pageContext获取项目相对路径jQuery是常用的JavaScript库方便在页面中操作DOM元素、处理页面事件、发起AJAX异步请求等操作 -->
<script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery-3.1.1.js"></script> <script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery-3.1.1.js"></script>
</head> </head>
<body> <body>
<!-- 使用layui框架定义一个字段集作为访客时间线的标题部分 --> <!-- 创建一个fieldset字段集元素应用layui的相关样式类layui-elem-field和layui-field-title用于对页面中的相关内容进行分组和标题显示
设置了顶部外边距为30px使其在页面中有一定的间距看起来更美观 -->
<fieldset class="layui-elem-field layui-field-title" style="margin-top: 30px;"> <fieldset class="layui-elem-field layui-field-title" style="margin-top: 30px;">
<!-- 在字段集中创建一个legend图例元素用于显示该组内容的标题这里显示的标题是“访客时间线” -->
<legend>访客时间线</legend> <legend>访客时间线</legend>
</fieldset> </fieldset>
<!-- 定义时间线组件 --> <!-- 创建一个无序列表ul元素应用layui的时间线样式类layui-timeline用于以时间线的形式展示访客相关的信息 -->
<ul class="layui-timeline"> <ul class="layui-timeline">
<!-- 单个时间线项,代表当前的时间点 --> <!-- 创建一个列表项li元素作为时间线中的一个节点应用layui的时间线项目样式类layui-timeline-item -->
<li class="layui-timeline-item"> <li class="layui-timeline-item">
<!-- 创建一个图标i元素应用layui的图标样式类layui-icon以及时间轴样式类layui-timeline-axis显示特定的图标这里图标对应的字符编码为“”具体图标样式由layui框架定义用于表示时间线的节点标记 -->
<i class="layui-icon layui-timeline-axis"></i> <i class="layui-icon layui-timeline-axis"></i>
<!-- 创建一个div元素用于包裹时间线节点的具体内容应用layui的文本样式类layui-text使内部文本能按照layui框架的默认文本样式显示 -->
<div class="layui-timeline-content layui-text"> <div class="layui-timeline-content layui-text">
<!-- 动态显示当前日期 --> <!-- 创建一个标题h3元素应用layui的时间线标题样式类layui-timeline-title并设置了id为“mytime”用于后续通过JavaScript操作来动态更新显示的时间内容 -->
<h3 class="layui-timeline-title" id="mytime"></h3> <h3 class="layui-timeline-title" id="mytime"></h3>
<!-- 显示访客日志统计信息 -->
<p> <p>
<!-- 显示访客日志的统计信息先是显示“访客日志共计”字样然后通过EL表达式展示pageInfo对象中total属性的值通常表示总日志条数接着显示“条”以及其他相关的日志显示数量等信息
例如当前显示的条数通过pageInfo对象的size属性获取用于让用户对访客日志的整体情况和当前展示情况有清晰的了解 -->
访客日志共计:&nbsp;${pageInfo.total}&nbsp;条&emsp;当前显示:${pageInfo.size}&nbsp;条&emsp;&emsp; 访客日志共计:&nbsp;${pageInfo.total}&nbsp;条&emsp;当前显示:${pageInfo.size}&nbsp;条&emsp;&emsp;
<!-- 如果不是第一页,则显示上一页链接 --> <!-- 通过JSTL的if条件判断标签判断pageInfo对象中的pageNum属性通常表示当前页码是否大于1如果大于1则表示不是第一页执行标签内的代码显示“上一页”的链接 -->
<c:if test="${pageInfo.pageNum > 1}"> <c:if test="${pageInfo.pageNum > 1}">
<!-- 创建一个超链接a元素href属性通过EL表达式拼接出具体的URL路径用于跳转到上一页当前页码减1每页显示10条数据size=10链接显示的文本为“上一页”方便用户进行翻页操作 -->
<a href="${pageContext.request.contextPath}/visitor/log?page=${pageInfo.pageNum - 1}&size=10">上一页</a>&emsp;&emsp; <a href="${pageContext.request.contextPath}/visitor/log?page=${pageInfo.pageNum - 1}&size=10">上一页</a>&emsp;&emsp;
</c:if> </c:if>
<!-- 如果不是最后一页,则显示下一页链接 --> <!-- 通过JSTL的if条件判断标签判断pageInfo对象中的pageNum属性是否小于总页数pageInfo.pages如果小于总页数则表示不是最后一页执行标签内的代码显示“下一页”的链接 -->
<c:if test="${pageInfo.pageNum < pageInfo.pages}"> <c:if test="${pageInfo.pageNum < pageInfo.pages}">
<!-- 创建一个超链接a元素href属性通过EL表达式拼接出具体的URL路径用于跳转到下一页当前页码加1每页显示10条数据size=10链接显示的文本为“下一页”方便用户进行翻页操作 -->
<a href="${pageContext.request.contextPath}/visitor/log?page=${pageInfo.pageNum + 1}&size=10">下一页</a> <a href="${pageContext.request.contextPath}/visitor/log?page=${pageInfo.pageNum + 1}&size=10">下一页</a>
</c:if> </c:if>
</p> </p>
<!-- 遍历分页后的访客日志列表 -->
<ul> <ul>
<!-- 使用JSTL的forEach循环标签开始循环遍历pageInfo.list中的数据通常是分页后的访客日志列表集合每次循环将当前元素赋值给log变量方便在列表中展示各个访客日志的详细信息 -->
<c:forEach items="${pageInfo.list}" var="log"> <c:forEach items="${pageInfo.list}" var="log">
<!-- 判断是否有离开时间,如果无则显示“尚未离开” --> <!-- 通过JSTL的if条件判断标签判断访客日志对象log中的end_date属性是否为空字符串如果为空字符串则表示访客尚未离开执行标签内的代码显示相应的访客日志信息 -->
<c:if test="${log.end_date == ''}"> <c:if test="${log.end_date == ''}">
<!-- 创建一个列表项li元素用于展示访客的具体日志信息按照指定格式显示访客姓名、访问时间、访问地点、访问事因以及尚未离开的提示信息 -->
<li>【${log.name}】于&nbsp;${log.begin_date}&nbsp;访问了${log.place},事因${log.visit_result},目前尚未离开</li> <li>【${log.name}】于&nbsp;${log.begin_date}&nbsp;访问了${log.place},事因${log.visit_result},目前尚未离开</li>
</c:if> </c:if>
<!-- 如果有离开时间,则正常显示来访和离开时间 --> <!-- 通过JSTL的if条件判断标签判断访客日志对象log中的end_date属性是否不为空字符串如果不为空字符串则表示访客已经离开执行标签内的代码显示相应的访客日志信息 -->
<c:if test="${log.end_date != ''}"> <c:if test="${log.end_date!= ''}">
<!-- 创建一个列表项li元素用于展示访客的具体日志信息按照指定格式显示访客姓名、访问时间、访问地点、访问事因以及离开时间等信息 -->
<li>【${log.name}】于&nbsp;${log.begin_date}&nbsp;访问了${log.place},事因${log.visit_result},并与${log.end_date}离开</li> <li>【${log.name}】于&nbsp;${log.begin_date}&nbsp;访问了${log.place},事因${log.visit_result},并与${log.end_date}离开</li>
</c:if> </c:if>
</c:forEach> </c:forEach>
</ul> </ul>
</div> </div>
</li> </li>
<!-- 另一个时间线项,表示日志开启的时间点 --> <!-- 创建另一个列表项li元素作为时间线中的另一个节点同样应用layui的时间线项目样式类layui-timeline-item -->
<li class="layui-timeline-item"> <li class="layui-timeline-item">
<!-- 创建一个图标i元素应用layui的图标样式类layui-icon以及时间轴样式类layui-timeline-axis显示特定的图标这里图标对应的字符编码为“”具体图标样式由layui框架定义用于表示时间线的节点标记 -->
<i class="layui-icon layui-timeline-axis"></i> <i class="layui-icon layui-timeline-axis"></i>
<!-- 创建一个div元素用于包裹时间线节点的具体内容应用layui的文本样式类layui-text使内部文本能按照layui框架的默认文本样式显示 -->
<div class="layui-timeline-content layui-text"> <div class="layui-timeline-content layui-text">
<!-- 创建一个标题div元素应用layui的时间线标题样式类layui-timeline-title显示固定的文本“2020.02.21日志开启”,用于标记日志开始的时间点等相关信息 -->
<div class="layui-timeline-title">2020.02.21日志开启</div> <div class="layui-timeline-title">2020.02.21日志开启</div>
</div> </div>
</li> </li>
</ul> </ul>
<!-- JavaScript脚本用于动态更新页面上的当前时间 -->
<script> <script>
// 定义showTime函数用于获取并显示当前日期
function showTime(){ function showTime(){
var nowtime =new Date(); // 获取当前时间 // 创建一个Date对象用于获取当前的日期和时间信息
var year=nowtime.getFullYear(); // 获取年份 var nowtime =new Date();
var month=nowtime.getMonth()+1; // 获取月份注意月份从0开始 // 通过Date对象的getFullYear方法获取当前的年份信息
var date=nowtime.getDate(); // 获取日 var year=nowtime.getFullYear();
// 将日期格式化后设置到页面中的元素中 // 通过Date对象的getMonth方法获取当前的月份信息注意返回值是0 - 11所以需要加1才是实际的月份
document.getElementById("mytime").innerText=year+"年"+month+"月"+date+"日"; var month=nowtime.getMonth()+1;
// 通过Date对象的getDate方法获取当前的日期信息即一个月中的第几天
var date=nowtime.getDate();
// 通过JavaScript的DOM操作获取id为“mytime”的元素对应页面中的h3标题元素并设置其内部文本内容为按照指定格式拼接的当前日期信息
// 用于在页面上动态显示当前的时间(年、月、日)
document.getElementById("mytime").innerText=year+"年"+month+"日"+date+"日";
} }
// 每隔一分钟调用一次showTime函数更新时间 // 使用JavaScript的setInterval函数每隔一段时间这里是1000 * 60毫秒即60秒执行一次传入的函数这里是showTime函数
// 实现每隔60秒更新一次页面上显示的时间通过调用showTime函数来更新id为“mytime”的元素显示的日期内容
setInterval("showTime()",1000*60); setInterval("showTime()",1000*60);
</script> </script>
</body> </body>
</html> </html>

@ -8,32 +8,34 @@
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!-- <!--
指令标签,用于设置页面的内容类型、字符编码和编程语言。 指令标签,用于设置页面的内容类型、字符编码和编程语言。
contentType: 设置响应的MIME类型和字符编码为UTF-8 contentType: 设置响应的MIME类型为"text/html"表示这是一个HTML格式的页面内容同时设置字符编码为UTF-8确保页面中的中文等特殊字符能正确显示避免出现乱码情况
language: 声明页面使用的编程语言是Java。 language: 声明页面使用的编程语言是Java意味着在这个JSP页面中可以嵌入Java代码片段或者使用基于Java的各种标签库等功能来实现动态页面内容生成等操作
--> -->
<html> <html>
<head> <head>
<!-- <!--
定义页面标题,当用户访问此页面时,浏览器标签页会显示“登记成功”。 定义页面标题,当用户访问此页面时,浏览器标签页会显示“登记成功”,这个标题简洁明了地告知用户当前页面所对应的操作结果状态
--> -->
<title>登记成功</title> <title>登记成功</title>
</head> </head>
<body> <body>
<!-- <!--
使用HTML的<h4>标签显示一条消息给用户,告知他们来访登记已经成功。 使用HTML的<h4>标签显示一条消息给用户,<h4>标签表示四级标题,在这里用于突出显示重要的提示信息,告知他们来访登记已经成功,
样式属性text-align: center; 使文本居中显示 style="text-align: center;" 是内联样式属性设置,通过设置"text-align"为"center",使得该标题文本在水平方向上居中显示,提升页面的美观度和可读性
--> -->
<h4 style="text-align: center;">恭喜您,来访登记成功!</h4> <h4 style="text-align: center;">恭喜您,来访登记成功!</h4>
<!-- <!--
HTML换行标签用于在“恭喜您来访登记成功”消息后添加一个空行以增加视觉上的间隔。 HTML换行标签用于在“恭喜您来访登记成功”消息后添加一个空行它是一个单标签作用就是在页面布局中产生一个换行效果
以增加视觉上的间隔,使得页面内容看起来更加清晰、有条理,避免不同内容之间过于紧凑。
--> -->
<br> <br>
<!-- <!--
创建一个超链接,允许用户点击以执行注销登记操作。 创建一个超链接使用HTML的<a>标签来实现,允许用户点击以执行注销登记操作,
href属性指定了链接的目标URL其中包含了注销登记的操作路径和当前用户的ID作为参数。 href属性指定了链接的目标URL通过EL表达式 "${pageContext.request.contextPath}/visitor/login_out?id=${id}" 动态生成链接地址,
样式属性text-align: center; 使链接文本居中显示。 其中 "${pageContext.request.contextPath}" 用于获取当前应用的上下文路径(通常是项目部署后的根路径部分),"/visitor/login_out" 是具体指向执行注销登记操作的后端接口路径,
--> "id=${id}" 表示将当前用户对应的ID作为参数传递给注销登记的接口这里的${id}应该是在页面渲染前通过相应的模型数据或者请求属性等方式设置好具体的值),
样式属性text-align: center; 同样是内联样式设置,使链接文本在水平方向上居中显示,保持页面整体的布局风格统一,方便用户查看和操作。
-->
<a href="${pageContext.request.contextPath}/visitor/login_out?id=${id}" style="text-align: center;">注销登记</a> <a href="${pageContext.request.contextPath}/visitor/login_out?id=${id}" style="text-align: center;">注销登记</a>
</body> </body>
</html> </html>
Loading…
Cancel
Save