Compare commits

...

8 Commits

@ -26,7 +26,7 @@ import java.io.UnsupportedEncodingException;
import java.util.List;
/**
* Description:
* Description: AdminControllerWeb
*
* @Date: 2020/2/10 15:20
* @Author: PeiChen
@ -34,7 +34,10 @@ import java.util.List;
@Controller
public class AdminController {
// 依赖注入AdminService用于调用业务逻辑层相关方法来处理管理员数据
private AdminService adminService;
// 通过@Autowired注解让Spring框架自动注入AdminService的实现类实例
@Autowired
public void setAdminService(AdminService adminService) {
this.adminService = adminService;
@ -42,44 +45,66 @@ public class AdminController {
/**
*
* @param model
* @param admin
* @param session
* @param request
* @return
*
* @param model
* @param admin Admin
* @param session session
* @param request HTTP
* @param response HTTP
* @return "main""login"
* @throws Exception
*/
@RequestMapping(value = "/login")
public String login(Model model, Admin admin, HttpSession session, HttpServletRequest request,HttpServletResponse response) throws Exception {
public String login(Model model, Admin admin, HttpSession session, HttpServletRequest request, HttpServletResponse response) throws Exception {
// 设置请求的字符编码为utf-8防止中文乱码等问题
request.setCharacterEncoding("utf-8");
// 设置响应的字符编码为utf-8确保返回给客户端的数据编码正确
response.setCharacterEncoding("utf-8");
// 获取响应的输出流对象,用于向客户端输出数据(这里主要用于输出错误提示等文本信息)
PrintWriter writer = response.getWriter();
// 如果传入的admin对象为空或者用户名、密码为空则直接返回登录页面
if (admin == null || admin.getUsername() == null || admin.getPassword() == null) {
return "login";
}
// 使用MD5Util工具类对用户输入的密码进行MD5加密以utf-8编码格式增强密码安全性
admin.setPassword(MD5Util.MD5EncodeUtf8(admin.getPassword()));
// 调用adminService的方法根据传入的admin对象包含加密后的密码去数据库查找对应的管理员信息
Admin ad = adminService.findAdmin(admin);
// 如果能查到对应的管理员信息,说明登录成功
if (ad != null) {
//登录信息存入session域
session.setAttribute("adminInfo",ad);
//System.out.println(ad);
//登录成功后的管理员信息存入session域,方便后续在其他请求中获取登录用户信息
session.setAttribute("adminInfo", ad);
// 返回主页面视图名称,通常对应着系统的主界面
return "main";
}
model.addAttribute("msg","用户名或密码错误,请重新输入!");
// 如果没查到,说明用户名或密码错误,向模型中添加错误提示信息
model.addAttribute("msg", "用户名或密码错误,请重新输入!");
// 返回登录页面视图名称,让用户重新输入登录信息
return "login";
}
//拦截后跳转至登录页
// 拦截后跳转至登录页,当用户未登录访问需要登录才能访问的资源时,可能会被拦截到此方法,然后跳转到登录页面
@RequestMapping("/to_login")
public String Login() {
return "login";
}
/**
* 退
n */
* 退使退
*
* @param admin 使Spring MVC
* @param model 使
* @param session invalidate
* @return 退
*/
@RequestMapping(value = "/loginOut")
public String loginOut(Admin admin,Model model,HttpSession session) {
//通过session.invalidate()方法来注销当前的session
public String loginOut(Admin admin, Model model, HttpSession session) {
// 通过session.invalidate()方法来注销当前的session,清除会话相关信息
session.invalidate();
return "login";
@ -87,121 +112,193 @@ public class AdminController {
/**
*
*
* @param page @RequestParam1使
* @param size @RequestParam5使
* @param request HTTP
* @param response HTTP
* @return ModelAndView
* @throws Exception
*/
@RequestMapping(value = "/findAllAdmin")
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, @RequestParam(name = "size", required = true, defaultValue = "5") int size, HttpServletRequest request, HttpServletResponse response) throws Exception {
// 设置请求的字符编码为utf-8
request.setCharacterEncoding("utf-8");
// 设置响应的字符编码为utf-8
response.setCharacterEncoding("utf-8");
// 创建一个ModelAndView对象用于封装要返回给视图的数据以及视图名称
ModelAndView mv = new ModelAndView();
// 用于存放查询到的管理员列表数据初始化为null
List<Admin> admins = null;
// 从请求参数中获取查询关键字如果没有传递该参数则可能为null
String keyword = request.getParameter("keyword");
// 如果关键字为空包括null、空字符串、长度为0等情况则查询所有管理员信息按照分页条件
if (keyword == null || keyword.trim().equals("") || keyword.length() == 0) {
admins = adminService.findAll(page,size);
}else {
admins = adminService.serarchInfo(page,size,keyword);
admins = adminService.findAll(page, size);
} else {
// 如果有关键字,则根据关键字进行模糊查询管理员信息(按照分页条件)
admins = adminService.serarchInfo(page, size, keyword);
}
//PageInfo就是一个封装了分页数据的bean
// 使用PageInfo对查询到的管理员列表数据进行分页相关信息的封装方便在视图层展示分页导航等信息
PageInfo pageInfo = new PageInfo(admins);
mv.addObject("pageInfo",pageInfo);
// 将封装好分页数据的PageInfo对象添加到ModelAndView中以便在视图中可以获取并展示分页数据
mv.addObject("pageInfo", pageInfo);
// 设置要跳转的视图名称为"admin-list",通常对应着展示管理员列表的页面
mv.setViewName("admin-list");
return mv;
}
/**
*
* idadminService
*
* @param request HTTPid
* @throws Exception
*/
@ResponseBody
@RequestMapping(value = "/deleteAdmin")
public void deleteAdmin(HttpServletRequest request) throws Exception {
// 从请求参数中获取要删除的管理员的id
String id = request.getParameter("id");
// 调用adminService的方法根据解析后的管理员id转换为整数类型来删除对应的管理员记录
adminService.deleteAdminById(Integer.parseInt(id));
}
/**
*
* adminService
*
* @param request HTTP
* @param response
* @throws Exception
*/
@RequestMapping(value = "/checkUserName")
public void checkUserName(HttpServletRequest request, HttpServletResponse response) throws Exception {
// 设置请求的字符编码为utf-8
request.setCharacterEncoding("utf-8");
// 设置响应的字符编码为utf-8
response.setCharacterEncoding("utf-8");
// 获取响应的输出流对象,用于向客户端输出校验结果信息
PrintWriter pw = response.getWriter();
//取值
// 从请求参数中获取要校验的用户名
String u_name = request.getParameter("u_name");
//调用service,用户名存在返回true不存在则返回false
// 调用adminService的方法校验用户名是否存在存在返回true不存在返回false
Boolean result = adminService.checkUserName(u_name);
//System.out.println(result);
//回调函数
// 根据校验结果,向客户端输出相应的提示信息
if (result) {
//pw.write("用户名已存在,请重新输入!");
pw.write("账号可用");
}else {
} else {
pw.write("账号不存在");
}
}
@RequestMapping(value = "/adminAdd")
public String adminAdd() {
// 返回添加管理员页面的视图名称,通常对应着展示添加管理员表单的页面
return "admin-add";
}
/**
*
* @param admin
* @param request
* @param response
* @throws Exception
* AdminadminService
*
* @param admin Admin
* @param request HTTP
* @param response
* @throws Exception
*/
@RequestMapping("/addAdmin")
public void addAdmin(Admin admin,HttpServletRequest request,HttpServletResponse response) throws Exception {
public void addAdmin(Admin admin, HttpServletRequest request, HttpServletResponse response) throws Exception {
// 获取响应的输出流对象,用于向客户端输出添加操作的结果信息(成功或失败)
PrintWriter writer = response.getWriter();
// 调用adminService的方法校验用户名是否已存在已存在则check为true不存在为false
Boolean check = adminService.checkUserName(admin.getUsername());
//如果用户名已存在check为true不存在为false
// 如果用户名已存在,向客户端输出"false"表示添加失败,并结束方法执行
if (check) {
writer.write("false");
return;
}
// 如果传入的admin对象为空向客户端输出"false"表示添加失败,并结束方法执行
if (admin == null) {
writer.write("false");
return;
}else {
if(admin.getUsername() == null || "".trim().equals(admin.getUsername())
|| admin.getPassword() == null ||"".trim().equals(admin.getPassword())
} else {
// 进一步校验管理员对象的各个属性是否为空(去除两端空格后为空字符串也算空),只要有一个属性为空,就向客户端输出"false"表示添加失败,并结束方法执行
if (admin.getUsername() == null || "".trim().equals(admin.getUsername())
|| admin.getPassword() == null || "".trim().equals(admin.getPassword())
|| admin.getName() == null || "".trim().equals(admin.getName())
|| admin.getUid() == null || "".trim().equals(admin.getUid())
|| admin.getPhone() == null || "".trim().equals(admin.getPhone())
|| admin.getDescription() == null || "".trim().equals(admin.getDescription())) {
writer.write("false");
return;
writer.write("false");
return;
}
}
// 校验学工号是否已被注册若已被注册返回的Admin对象不为null向客户端输出"false"表示添加失败,并结束方法执行
Admin isNull = adminService.checkUid(admin.getUid());
if (isNull != null) {
writer.write("false");
return;
}
// 使用MD5Util工具类对管理员密码进行MD5加密以utf-8编码格式
admin.setPassword(MD5Util.MD5EncodeUtf8(admin.getPassword()));
// 调用adminService的方法将经过校验和加密密码后的管理员信息添加到数据库
adminService.addAdmin(admin);
// 添加成功后,向客户端输出"true"表示添加成功
writer.write("true");
}
//跳转管理员信息编辑页面,并回显信息
// 跳转管理员信息编辑页面并回显信息根据传入的管理员id从数据库查询对应的管理员信息然后将信息传递到编辑页面进行展示
@RequestMapping("/adminEdit")
public ModelAndView editAdmin(HttpServletRequest request) throws Exception {
// 创建一个ModelAndView对象用于封装要返回给视图的数据以及视图名称
ModelAndView mv = new ModelAndView();
// 从请求参数中获取要编辑的管理员的id
String id = request.getParameter("id");
// 调用adminService的方法根据管理员id查询对应的管理员信息
Admin ad = adminService.findAdminById(Integer.parseInt(id));
mv.addObject("ad",ad);
//mv.addObject("id",id);
// 将查询到的管理员信息添加到ModelAndView中以便在编辑页面可以获取并展示该信息
mv.addObject("ad", ad);
// 设置要跳转的视图名称为"admin-edit",通常对应着展示管理员信息编辑表单的页面
mv.setViewName("admin-edit");
return mv;
}
//修改管理员信息
// 修改管理员信息操作接收一个Admin对象包含修改后的管理员各项信息以及响应对象进行一系列校验后调用adminService的方法更新数据库中的管理员信息
@RequestMapping("/editAdmin")
public void editAdmin(Admin admin,HttpServletResponse response) throws Exception {
public void editAdmin(Admin admin, HttpServletResponse response) throws Exception {
// 获取响应的输出流对象,用于向客户端输出修改操作的结果信息(成功或失败)
PrintWriter writer = response.getWriter();
// 如果传入的admin对象为空向客户端输出"false"表示修改失败,并结束方法执行
if (admin == null) {
writer.write("false");
return;
}else {
if(admin.getUsername() == null || "".trim().equals(admin.getUsername())
} else {
// 校验管理员对象的各个属性是否为空(去除两端空格后为空字符串也算空),只要有一个属性为空,就向客户端输出"false"表示修改失败,并结束方法执行
if (admin.getUsername() == null || "".trim().equals(admin.getUsername())
|| admin.getName() == null || "".trim().equals(admin.getName())
|| admin.getUid() == null || "".trim().equals(admin.getUid())
|| admin.getPhone() == null || "".trim().equals(admin.getPhone())
@ -210,63 +307,46 @@ public class AdminController {
return;
}
}
// 此处注释掉了密码加密代码,可能根据业务需求,修改管理员信息时不一定需要重新加密密码(具体看实际情况)
//admin.setPassword(MD5Util.MD5EncodeUtf8(admin.getPassword()));
// 调用adminService的方法根据传入的修改后的管理员信息更新数据库中的对应记录
adminService.updateAdmin(admin);
//更新成功进行提示信息回显
// 更新成功后,向客户端输出"true"表示更新成功
writer.write("true");
}
/**
*
* AdminadminService
*
* @param admin Admin
* @param response
* @throws Exception
*/
@RequestMapping("/put_power")
public void put_power(Admin admin,HttpServletResponse response) throws Exception {
public void put_power(Admin admin, HttpServletResponse response) throws Exception {
// 获取响应的输出流对象,用于向客户端输出授权操作的结果信息(成功或失败)
PrintWriter writer = response.getWriter();
// 如果传入的admin对象为空向客户端输出"false"表示授权失败,并结束方法执行
if (admin == null) {
writer.write("false");
return;
}
// 校验授权级别是否在合法范围内0到4之间不在则向客户端输出"false"表示授权失败,并结束方法执行
if (admin.getPower() < 0 || admin.getPower() > 4) {
writer.write("false");
return;
}
adminService.put_power(admin);
writer.write("true");
}
/**
*
* @param response
* @throws Exception
*/
@RequestMapping("/exportAdminInfo")
public void exportAdminInfo(HttpServletResponse response) throws Exception {
InputStream is = adminService.getInputStream();
response.setContentType("application/vnd.ms-excel");
response.setHeader("contentDisposition", "attachment;filename=adminsInfo.xls");
ServletOutputStream outputStream = response.getOutputStream();
IOUtils.copy(is,outputStream);
}
/**
*
* @param request
* @param response
* @throws Exception
*/
@RequestMapping("/checkUid")
public void checkUid(HttpServletRequest request,HttpServletResponse response) throws Exception {
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
PrintWriter writer = response.getWriter();
String uid = request.getParameter("uid");
Admin admin = adminService.checkUid(uid);
if (admin != null) {
writer.write("true");//uid已被注册
return;
}
// 调用adminService的方法进行授权相关的数据库操作具体操作由service层实现
adminService.put_power(admin);
// 授权成功后,向客户端输出"true"表示授权成功
writer.write("true");
}
}

@ -9,39 +9,80 @@ import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
/**
* Description:
* Description: Web
* 访访
*
* @Date: 2020/2/14 16:50
* @Author: PeiChen
*/
public class LoginInterceptor implements HandlerInterceptor {
/**
*
*
* @param request HTTPURL
* @param response HTTP
* @param handler Controller使
* @return true访false
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 获取请求的URL
// 获取请求的URL(统一资源标识符),用于判断当前请求的是哪个页面或者资源路径。
String url = request.getRequestURI();
// URL:除了login.jsp是可以公开访问的其它的URL都进行拦截控制
if(url.toLowerCase().indexOf("login")>=0){
// 进行URL判断这里设定的规则是除了包含"login"不区分大小写的URL是可以公开访问的比如登录页面本身其它的URL都要进行拦截控制。
// 如果URL中包含"login"则允许请求继续执行返回true。
if (url.toLowerCase().indexOf("login") >= 0) {
return true;
}
// 获取当前请求对应的HttpSession对象HttpSession用于在服务器端存储用户相关的会话信息比如用户登录后的身份信息等。
HttpSession session = request.getSession();
// 获取Session中的用户登录信息
// 尝试从Session中获取用户登录信息这里假设用户登录成功后将登录的管理员信息Admin对象存入了名为"adminInfo"的Session属性中。
// 通过强制类型转换获取存储在Session中的Admin对象如果不存在则返回null。
Admin admin = (Admin) session.getAttribute("adminInfo");
// 判断Session中是否有用户数据如果有则返回true,继续向下执行
if(admin != null){
// 判断Session中是否获取到了用户数据即Admin对象是否为null如果不为null说明用户已经登录允许请求继续向下执行返回true。
if (admin!= null) {
return true;
}
// 地址栏不符合条件的直接重定向到登录页面
// 如果经过前面的判断地址栏对应的URL不符合可直接访问的条件既不是登录相关页面且用户又未登录
// 则使用响应对象的sendRedirect方法将请求重定向到登录页面这里的"/hellossm/to_login"是登录页面的相对路径,根据实际项目配置可能会不同)。
// 并且返回false表示中断当前请求不再继续执行后续的处理器逻辑。
response.sendRedirect("/hellossm/to_login");
return false;
}
/**
*
*
*
* @param request HTTP
* @param response HTTP
* @param handler
* @param modelAndView
* @throws Exception ModelAndView
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
/**
*
*
*
* @param request HTTP
* @param response HTTP
* @param handler
* @param ex
* @throws Exception
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
}
}

@ -8,6 +8,7 @@ import java.util.List;
/**
* Description:
* 访使MyBatisSQLadmins
*
* @Date: 2020/2/10 15:33
* @Author: PeiChen
@ -16,93 +17,142 @@ import java.util.List;
public interface AdminDao {
/**
*
* @param admin
* @return
* @throws Exception
*
* 使MyBatis@SelectSQL"admins"Admin
*
* @param admin AdminMyBatis#{username}#{password}SQL
* @return AdminnullMyBatis
* @throws Exception SQL
*/
@Select("select * from admins where username = #{username} and password = #{password}")
Admin findAdmin(Admin admin) throws Exception;
/**
* id
* 使@SelectSQL"admins"idAdmin
* #{id}idSQLid
*
* @param id
* @return Adminnull
* @throws Exception
*/
@Select("select * from admins where id = #{id}")
Admin findAdminById(Integer id) throws Exception;
/**
*
* 使@SelectSQL"admins"
* MyBatisPageHelper
*
* @return List<Admin>
* @throws Exception
*/
@Select("select * from admins")
List<Admin> findAll() throws Exception;
/**
*
* @return
* @throws Exception
* 使@SelectSQL"admins"便Excel
*
* @return List<Admin>
* @throws Exception 访
*/
@Select("select * from admins")
List<Admin> exportAdminInfo() throws Exception;
/**
* id
* @param id
* @throws Exception
* 使@DeleteSQLid"admins"
* #{id}idSQL
*
* @param id
* @throws Exception
*/
@Delete("delete from admins where id = #{id}")
void deleteAdminById(Integer id) throws Exception;
/**
*
* @param admin
* @throws Exception
* @UpdateSQLAdmin"admins"id
* 使#{}AdminSQL
*
* @param admin Admin
* @throws Exception
*/
@Update("update admins set username= #{username},name = #{name},uid = #{uid}, phone = #{phone}, description = #{description} where id = #{id}")
void updateAdmin(Admin admin) throws Exception;
/**
*
* @param admin
* @throws Exception
* @InsertSQLAdmin"admins"
* #{}AdminSQL
*
* @param admin Admin
* @throws Exception
*/
@Insert("insert into admins(username,password,name,uid,phone,power,description) values (#{username},#{password},#{name},#{uid},#{phone},#{power},#{description})")
void addAdmin(Admin admin) throws Exception;
/**
*
* 使@SelectSQL"admins"使
* truefalseMyBatis
*
* @param u_name
* @return truefalse
* @throws Exception
*/
@Select("select * from admins where username = #{u_name}")
Boolean checkUserName(String u_name) throws Exception;
/**
* /
* @param uid
* @return
* @throws Exception
* @SelectSQL"admins"/uid/使
* Adminnull/null
*
* @param uid /
* @return /Adminnull
* @throws Exception 访
*/
@Select("select * from admins where uid = #{uid}")
Admin checkUid(String uid) throws Exception;
/**
*
* @param password
* @param id
* @throws Exception
* 使@UpdateSQLid"admins"
* #{password}#{id}SQL
*
* @param password
* @param id
* @throws Exception
*/
@Update("update admins set password = #{password} where id = #{id}")
void updatePassword(String password,Integer id) throws Exception;
void updatePassword(String password, Integer id) throws Exception;
//select * from admins where username like '%p%' or name like '%万%' or power like '%1%' or description like '%管理员%';
//模糊搜索管理员信息查询结果返回一个list集合
/**
*
* 使@SelectLIKESQL"admins"/keyword
* ${keyword}SQL#{keyword}${}#{}SQLList<Admin>
* 使${}SQL
*
* @param keyword
* @return List<Admin>
* @throws Exception
*/
@Select("select * from admins where username like '%${keyword}%' or name like '%${keyword}%' or uid like '%${keyword}%' or phone like '%${keyword}%' or power like '%${keyword}%' or description like '%${keyword}%' ")
List<Admin> serarchInfo(@Param(value="keyword") String keyword) throws Exception;
/**
*
* 0 1 2 3
* @param admin
* @throws Exception
* @UpdateSQLAdminidpower"admins"
* #{power}#{id}AdminSQL
*
* @param admin idpowerAdmin
* @throws Exception
*/
@Update("update admins set power = #{power} where id = #{id} ")
void put_power(Admin admin) throws Exception;
}
}

@ -4,23 +4,54 @@ import java.io.Serializable;
/**
* Description:
* Java
* Serializable便使
*
* @Date: 2020/2/10 15:13
* @Author: PeiChen
*/
public class Admin implements Serializable {
private Integer id; //id 主键自增
private String username; //用户名
private String password; //密码
private String name; //姓名
private String uid; //学/工号
private String phone; //手机号
private int power; //是否开启权限
private String description; //描述
// 管理员的唯一标识,通常对应数据库表中的主键字段,设置为自增类型,用于唯一确定一条管理员记录。
private Integer id;
// 管理员的用户名,用于登录系统等操作,存储用户名相关的字符串信息。
private String username;
// 管理员的密码,用于验证登录身份,存储密码相关的字符串信息,在实际应用中应进行加密存储等安全处理。
private String password;
// 管理员的真实姓名,用于展示和区分不同的管理员个体,存储姓名相关的字符串信息。
private String name;
// 学/工号,用于唯一标识管理员在学校或单位内的身份编号,存储相应的字符串信息。
private String uid;
// 管理员的手机号码,可用于联系管理员等相关用途,存储手机号码的字符串信息。
private String phone;
// 表示管理员是否开启权限的标识,整型变量,具体含义根据业务逻辑确定(例如不同数值对应不同权限级别等)。
private int power;
// 对管理员的相关描述信息,比如岗位描述、职责范围等,存储对应的字符串信息。
private String description;
// 默认的无参构造函数,在一些框架进行对象实例化等操作时可能会用到,例如通过反射机制创建对象时需要默认构造函数。
public Admin() {
}
/**
* Admin便
*
* @param id
* @param username
* @param password
* @param name
* @param uid /
* @param phone
* @param power
* @param description
*/
public Admin(Integer id, String username, String password, String name, String uid, String phone, int power, String description) {
this.id = id;
this.username = username;
@ -32,70 +63,92 @@ public class Admin implements Serializable {
this.description = description;
}
// 获取管理员的唯一标识id的方法供外部类访问该对象的id属性值。
public Integer getId() {
return id;
}
// 设置管理员的唯一标识id的方法供外部类修改该对象的id属性值。
public void setId(Integer id) {
this.id = id;
}
// 获取管理员用户名的方法供外部类访问该对象的username属性值。
public String getUsername() {
return username;
}
// 设置管理员用户名的方法供外部类修改该对象的username属性值。
public void setUsername(String username) {
this.username = username;
}
// 获取管理员密码的方法供外部类访问该对象的password属性值。
public String getPassword() {
return password;
}
// 设置管理员密码的方法供外部类修改该对象的password属性值。
public void setPassword(String password) {
this.password = password;
}
// 获取管理员真实姓名的方法供外部类访问该对象的name属性值。
public String getName() {
return name;
}
// 设置管理员真实姓名的方法供外部类修改该对象的name属性值。
public void setName(String name) {
this.name = name;
}
// 获取管理员学/工号的方法供外部类访问该对象的uid属性值。
public String getUid() {
return uid;
}
// 设置管理员学/工号的方法供外部类修改该对象的uid属性值。
public void setUid(String uid) {
this.uid = uid;
}
// 获取管理员手机号码的方法供外部类访问该对象的phone属性值。
public String getPhone() {
return phone;
}
// 设置管理员手机号码的方法供外部类修改该对象的phone属性值。
public void setPhone(String phone) {
this.phone = phone;
}
// 获取管理员权限标识的方法供外部类访问该对象的power属性值。
public int getPower() {
return power;
}
// 设置管理员权限标识的方法供外部类修改该对象的power属性值。
public void setPower(int power) {
this.power = power;
}
// 获取管理员描述信息的方法供外部类访问该对象的description属性值。
public String getDescription() {
return description;
}
// 设置管理员描述信息的方法供外部类修改该对象的description属性值。
public void setDescription(String description) {
this.description = description;
}
/**
* toString便Admin便
* "Admin{" + = + '}'
*
* @return Admin
*/
@Override
public String toString() {
return "Admin{" +
@ -109,4 +162,4 @@ public class Admin implements Serializable {
", description='" + description + '\'' +
'}';
}
}
}

@ -2,188 +2,237 @@ package cn.ppdxzz.poi;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.hssf.util.HSSFColor;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
/**
* Description:Excel
* ExcelExcel便Web
*
* @Date: 2020/2/16 15:17
* @Author: PeiChen
*/
public class WriteExcel {
//导出表的列名
// 导出表的列名数组用于存储Excel表格每列的标题名称。
private String[] rowName;
//每行作为一个Object对象
private List<Object[]> dataList = new ArrayList<Object[]>();
//构造方法,传入要导出的数据:第一个参数传入一个列名数组第二个参数传入一个list集合Object对象数组
public WriteExcel(String[] rowName,List<Object[]> dataList){
// 每行作为一个Object对象这里使用List来存储多个Object数组每个Object数组代表Excel表格中的一行数据除去列名那一行
private List<Object[]> dataList = new ArrayList<Object[]>();
// 构造方法,传入要导出的数据
// 第一个参数传入一个列名数组用于设置Excel表格的列标题。
// 第二个参数传入一个list集合Object对象数组集合中的每个Object数组对应Excel表格中的一行具体数据。
public WriteExcel(String[] rowName, List<Object[]> dataList) {
this.dataList = dataList;
this.rowName = rowName;
}
/*
*
* */
public InputStream export() throws Exception{
HSSFWorkbook workbook = new HSSFWorkbook(); // 创建工作簿对象
HSSFSheet sheet = workbook.createSheet("sheet1"); // 创建工作表
/**
*
* Excel簿Excel便
*
* @return InputStreamExcel
* @throws Exception 簿IO
*/
public InputStream export() throws Exception {
// 创建工作簿对象这是整个Excel文件的基础容器后续的工作表、单元格等都将添加到这个工作簿中。
HSSFWorkbook workbook = new HSSFWorkbook();
// 创建工作表,这里创建了一个名为"sheet1"的工作表,一个工作簿可以包含多个工作表,此处只创建了一个。
HSSFSheet sheet = workbook.createSheet("sheet1");
// 设置sheet表样式
HSSFCellStyle columnTopStyle = this.getColumnTopStyle(workbook);//获取列头样式对象
HSSFCellStyle style = this.getColumnStyle(workbook); //单元格样式对象
// 获取列头样式对象用于设置Excel表格中列标题那一行单元格的样式。
HSSFCellStyle columnTopStyle = this.getColumnTopStyle(workbook);
// 获取单元格样式对象用于设置Excel表格中除列标题外其他数据单元格的样式。
HSSFCellStyle style = this.getColumnStyle(workbook);
// 定义所需列数
// 定义所需列数通过传入的列名数组长度来确定Excel表格的列数。
int columnNum = rowName.length;
HSSFRow rowRowName = sheet.createRow(0); // 在索引2的位置创建行(最顶端的行开始的第二行)
// 在索引0的位置创建行Excel表格中最顶端的行用于设置列头信息。
HSSFRow rowRowName = sheet.createRow(0);
// 将列头设置到sheet的单元格中
for(int n=0;n<columnNum;n++){
HSSFCell cellRowName = rowRowName.createCell(n); //创建列头对应个数的单元格
cellRowName.setCellType(HSSFCell.CELL_TYPE_STRING); //设置列头单元格的数据类型
// 循环遍历每一列,创建对应的单元格并设置相关属性,包括数据类型、值以及样式等。
for (int n = 0; n < columnNum; n++) {
// 创建列头对应个数的单元格每个单元格对应Excel表格中的一列标题。
HSSFCell cellRowName = rowRowName.createCell(n);
// 设置列头单元格的数据类型为字符串类型,以便后续正确设置列头的文本内容。
cellRowName.setCellType(HSSFCell.CELL_TYPE_STRING);
// 创建一个富文本字符串对象,将列名数组中的对应列名作为文本内容传入,用于设置单元格的值。
HSSFRichTextString text = new HSSFRichTextString(rowName[n]);
cellRowName.setCellValue(text); //设置列头单元格的值
cellRowName.setCellStyle(columnTopStyle); //设置列头单元格样式
// 设置列头单元格的值,即将列名填充到对应的单元格中。
cellRowName.setCellValue(text);
// 设置列头单元格样式,应用之前获取的列头样式对象,使列头具有统一的样式外观。
cellRowName.setCellStyle(columnTopStyle);
}
//将查询出的数据设置到sheet对应的单元格中
for(int i=0;i<dataList.size();i++){
Object[] obj = dataList.get(i); //遍历每个对象
HSSFRow row = sheet.createRow(i+1); //创建所需的行数
for(int j=0; j<obj.length; j++){
HSSFCell cell = null; //设置单元格的数据类型
cell = row.createCell(j,HSSFCell.CELL_TYPE_STRING);
if(!"".equals(obj[j]) && obj[j] != null){
cell.setCellValue(obj[j].toString()); //设置单元格的值
// 将查询出的数据设置到sheet对应的单元格中
// 遍历数据列表将每一行数据填充到Excel表格对应的行和列的单元格中。
for (int i = 0; i < dataList.size(); i++) {
// 取出每一行数据即一个Object数组数组中的每个元素对应Excel表格该行中的一个单元格数据。
Object[] obj = dataList.get(i);
// 创建所需的行数索引从1开始因为0行已经用于列头了每循环一次创建一行对应数据列表中的一行数据。
HSSFRow row = sheet.createRow(i + 1);
// 循环遍历该行数据中的每个元素,将其填充到对应的单元格中。
for (int j = 0; j < obj.length; j++) {
HSSFCell cell = null;
// 设置单元格的数据类型为字符串类型,方便处理各种类型的数据转换为字符串后填充到单元格。
cell = row.createCell(j, HSSFCell.CELL_TYPE_STRING);
if (!"".equals(obj[j]) && obj[j]!= null) {
// 如果数据不为空且不为空字符串,则将其转换为字符串后设置为单元格的值。
cell.setCellValue(obj[j].toString());
}
cell.setCellStyle(style); //设置单元格样式
// 设置单元格样式,应用之前获取的普通单元格样式对象,使数据单元格具有统一的样式。
cell.setCellStyle(style);
}
}
//让列宽随着导出的列长自动适应
// 让列宽随着导出的列长自动适应
// 通过遍历每一列以及每一行中的单元格内容长度,来动态调整每列的宽度,使表格内容能更好地展示。
for (int colNum = 0; colNum < columnNum; colNum++) {
// 先获取当前列的初始宽度并将其转换为以字符为单位除以256方便后续比较和调整。
int columnWidth = sheet.getColumnWidth(colNum) / 256;
// 遍历工作表中的每一行从第0行开始到最后一行查找当前列中最长的单元格内容长度以此来确定该列合适的宽度。
for (int rowNum = 0; rowNum < sheet.getLastRowNum(); rowNum++) {
HSSFRow currentRow;
//如若当前行未被使用过,则新建一行
// 如若当前行未被使用过即为null,则新建一行,以便后续获取单元格进行操作。
if (sheet.getRow(rowNum) == null) {
currentRow = sheet.createRow(rowNum);
} else {
currentRow = sheet.getRow(rowNum);
}
if (currentRow.getCell(colNum) != null) {
if (currentRow.getCell(colNum)!= null) {
HSSFCell currentCell = currentRow.getCell(colNum);
if (currentCell.getCellType() == HSSFCell.CELL_TYPE_STRING) {
// 如果当前单元格的数据类型是字符串类型,则获取其字符串内容的字节长度,以此来衡量其显示宽度。
int length = currentCell.getStringCellValue().getBytes().length;
if (columnWidth < length) {
// 如果当前列宽小于该单元格内容长度对应的宽度,则更新列宽为该单元格内容长度对应的宽度,确保能完整显示内容。
columnWidth = length;
}
}
}
}
if(colNum == 0){
sheet.setColumnWidth(colNum, (columnWidth-2) * 256);
}else{
sheet.setColumnWidth(colNum, (columnWidth+4) * 256);
// 根据列的索引位置,对列宽进行适当的调整(减去或加上一定的偏移量,使表格看起来更美观、合适),然后设置为最终的列宽。
if (colNum == 0) {
sheet.setColumnWidth(colNum, (columnWidth - 2) * 256);
} else {
sheet.setColumnWidth(colNum, (columnWidth + 4) * 256);
}
}
// 生成一个文件名,文件名包含当前时间戳信息(取其中一部分),后缀为".xls"表示生成的是Excel 2003格式的文件。
String fileName = "Excel-" + String.valueOf(System.currentTimeMillis()).substring(4, 13) + ".xls";
// 设置响应头中的文件信息,指定文件名以及表示这是一个附件(用于文件下载场景),告知浏览器以附件形式处理该文件并显示给定的文件名。
String headStr = "attachment; filename=\"" + fileName + "\"";
ByteArrayOutputStream os=new ByteArrayOutputStream();
// 创建一个字节数组输出流对象用于临时存储Excel工作簿写入的文件内容后续将其转换为字节数组再转换为输入流返回。
ByteArrayOutputStream os = new ByteArrayOutputStream();
try {
// 将工作簿的内容写入到字节数组输出流中即将Excel文件内容以字节形式存储到内存中的输出流里。
workbook.write(os);
} catch (IOException e) {
e.printStackTrace();
}
byte[] content=os.toByteArray();
InputStream is=new ByteArrayInputStream(content);
// 将字节数组输出流中的内容转换为字节数组,以便后续创建输入流。
byte[] content = os.toByteArray();
// 根据字节数组创建一个字节输入流对象该输入流指向的内容就是生成的Excel文件内容最终将其返回供外部使用如文件下载等操作
InputStream is = new ByteArrayInputStream(content);
return is;
}
/*
*
/**
*
* Excel
*
* @param workbook 簿簿
* @return HSSFCellStyle
*/
public HSSFCellStyle getColumnTopStyle(HSSFWorkbook workbook) {
// 设置字体
HSSFFont font = workbook.createFont();
//设置字体大小
font.setFontHeightInPoints((short)11);
//字体加粗
// 设置字体大小为11号以指定列头字体的显示大小。
font.setFontHeightInPoints((short) 11);
// 设置字体加粗,使列头文字更加突出、醒目。
font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
//设置字体名字
// 设置字体名字为"Courier New",指定列头文字使用的字体类型。
font.setFontName("Courier New");
//设置样式;
// 设置样式
HSSFCellStyle style = workbook.createCellStyle();
//设置底边框;
// 设置底边框为细边框,定义了单元格底部边框的样式为细线类型。
style.setBorderBottom(HSSFCellStyle.BORDER_THIN);
//设置底边框颜色;
// 设置底边框颜色为黑色,指定了单元格底部边框的颜色。
style.setBottomBorderColor(HSSFColor.BLACK.index);
//设置左边框;
style.setBorderLeft(HSSFCellStyle.BORDER_THIN);
//设置左边框颜色;
// 设置左边框为细边框,确定单元格左边框的样式。
style.setBorderLeft(HSSFColor.BLACK.index);
// 设置左边框颜色为黑色,设定单元格左边框的颜色。
style.setLeftBorderColor(HSSFColor.BLACK.index);
//设置右边框;
style.setBorderRight(HSSFCellStyle.BORDER_THIN);
//设置右边框颜色;
// 设置右边框为细边框,定义单元格右边框的样式。
style.setBorderRight(HSSFColor.BLACK.index);
// 设置右边框颜色为黑色,指定单元格右边框的颜色。
style.setRightBorderColor(HSSFColor.BLACK.index);
//设置顶边框;
style.setBorderTop(HSSFCellStyle.BORDER_THIN);
//设置顶边框颜色;
// 设置顶边框为细边框,确定单元格顶部边框的样式。
style.setBorderTop(HSSFColor.BLACK.index);
// 设置顶边框颜色为黑色,设定单元格顶部边框的颜色。
style.setTopBorderColor(HSSFColor.BLACK.index);
//在样式用应用设置的字体;
// 在样式中应用设置的字体,将之前创建的字体对象应用到该单元格样式中,使字体设置生效。
style.setFont(font);
//设置自动换行;
// 设置自动换行属性为false即单元格内容超过列宽时不自动换行显示根据实际需求可调整
style.setWrapText(false);
//设置水平对齐的样式为居中对齐;
// 设置水平对齐的样式为居中对齐,使列头内容在水平方向上居中显示,看起来更美观。
style.setAlignment(HSSFCellStyle.ALIGN_CENTER);
//设置垂直对齐的样式为居中对齐;
// 设置垂直对齐的样式为居中对齐,让列头内容在垂直方向上也居中显示,整体排版更整齐。
style.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
return style;
}
/*
*
/**
*
* Excel
*
* @param workbook 簿簿
* @return HSSFCellStyle
*/
public HSSFCellStyle getColumnStyle(HSSFWorkbook workbook) {
// 设置字体
HSSFFont font = workbook.createFont();
//设置字体名字
// 设置字体名字为"Courier New",指定数据单元格文字使用的字体类型。
font.setFontName("Courier New");
//设置样式;
// 设置样式
HSSFCellStyle style = workbook.createCellStyle();
//设置底边框;
style.setBorderBottom(HSSFCellStyle.BORDER_THIN);
//设置底边框颜色;
// 设置底边框为细边框,定义了单元格底部边框的样式为细线类型。
style.setBorderBottom(HSSFColor.BLACK.index);
// 设置底边框颜色为黑色,指定了单元格底部边框的颜色。
style.setBottomBorderColor(HSSFColor.BLACK.index);
//设置左边框;
style.setBorderLeft(HSSFCellStyle.BORDER_THIN);
//设置左边框颜色;
// 设置左边框为细边框,确定单元格左边框的样式。
style.setBorderLeft(HSSFColor.BLACK.index);
// 设置左边框颜色为黑色,设定单元格左边框的颜色。
style.setLeftBorderColor(HSSFColor.BLACK.index);
//设置右边框;
style.setBorderRight(HSSFCellStyle.BORDER_THIN);
//设置右边框颜色;
// 设置右边框为细边框,定义单元格右边框的样式。
style.setBorderRight(HSSFColor.BLACK.index);
// 设置右边框颜色为黑色,指定单元格右边框的颜色。
style.setRightBorderColor(HSSFColor.BLACK.index);
//设置顶边框;
style.setBorderTop(HSSFCellStyle.BORDER_THIN);
//设置顶边框颜色;
// 设置顶边框为细边框,确定单元格顶部边框的样式。
style.setBorderTop(HSSFColor.BLACK.index);
// 设置顶边框颜色为黑色,设定单元格顶部边框的颜色。
style.setTopBorderColor(HSSFColor.BLACK.index);
//在样式用应用设置的字体;
// 在样式中应用设置的字体,将之前创建的字体对象应用到该单元格样式中,使字体设置生效。
style.setFont(font);
//设置自动换行;
// 设置自动换行属性为false即单元格内容超过列宽时不自动换行显示根据实际需求可调整
style.setWrapText(false);
//设置水平对齐的样式为居中对齐;
// 设置水平对齐的样式为居中对齐,使数据内容在水平方向上居中显示,看起来更美观。
style.setAlignment(HSSFCellStyle.ALIGN_CENTER);
//设置垂直对齐的样式为居中对齐;
style.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
// 设置垂直对齐的样式为居中对齐,让数据内容在垂直方向上也居中显示,整体排版更整齐。
style.setVerticalAlignment(HSSFColor.BLACK.index);
return style;
}
}
}

@ -1,43 +1,139 @@
package cn.ppdxzz.service;
import cn.ppdxzz.domain.Admin;
import java.io.InputStream;
import java.util.List;
/**
* Description:
* Description:
* AdminServiceImplControllerDao
* 使便
*
* @Date: 2020/2/10 15:27
* @Author: PeiChen
*/
public interface AdminService {
/**
*
* Admin
* Adminnull
*
* @param admin Admin
* @return Adminnull
* @throws Exception
*/
Admin findAdmin(Admin admin) throws Exception;
//通过id查询管理员信息
// 通过id查询管理员信息
/**
* id
* idAdminnull
*
* @param id
* @return Adminnull
* @throws Exception
*/
Admin findAdminById(Integer id) throws Exception;
List<Admin> findAll(int page,int size) throws Exception;
/**
*
* pagesize
*
*
* @param page 1
* @param size
* @return List<Admin>
* @throws Exception 使
*/
List<Admin> findAll(int page, int size) throws Exception;
/**
* id
* idid
*
* @param id
* @throws Exception
*/
void deleteAdminById(Integer id) throws Exception;
/**
*
* Admin
*
*
* @param admin Admin
* @throws Exception
*/
void updateAdmin(Admin admin) throws Exception;
/**
*
* Admin
*
*
* @param admin Admin
* @throws Exception
*/
void addAdmin(Admin admin) throws Exception;
/**
*
* 使
* truefalse
*
* @param u_name
* @return truefalse
* @throws Exception
*/
Boolean checkUserName(String u_name) throws Exception;
//模糊搜索管理员信息查询结果返回一个list集合
List<Admin> serarchInfo(int page,int size,String keyword) throws Exception;
//授权
// 模糊搜索管理员信息查询结果返回一个list集合
/**
*
* pagesizekeyword
* 便
*
* @param page 1
* @param size
* @param keyword
* @return List<Admin>
* @throws Exception 使
*/
List<Admin> serarchInfo(int page, int size, String keyword) throws Exception;
// 授权
/**
*
* Admin
*
*
* @param admin Admin
* @throws Exception
*/
void put_power(Admin admin) throws Exception;
//返回一个携带所有管理员信息数据的InputStream输入流
// 返回一个携带所有管理员信息数据的InputStream输入流
/**
*
* Excel
* InputStream
*
* @return InputStream
* @throws Exception
*/
InputStream getInputStream() throws Exception;
//校验学工号是否被注册
// 校验学工号是否被注册
/**
* /
* ///使
* Adminnullnull/
*
* @param uid /
* @return /Adminnull
* @throws Exception
*/
Admin checkUid(String uid) throws Exception;
}
}

@ -18,7 +18,8 @@ import java.util.ArrayList;
import java.util.List;
/**
* Description:
* Description: AdminService
* AdminDao
*
* @Date: 2020/2/10 15:30
* @Author: PeiChen
@ -26,7 +27,10 @@ import java.util.List;
@Service("adminService")
public class AdminServiceImpl implements AdminService {
// 依赖注入AdminDao接口用于调用持久层的数据库操作方法。
private AdminDao adminDao;
// 通过@Autowired注解让Spring框架自动注入AdminDao的实现类实例实现依赖注入。
@Autowired
public void setAdminDao(AdminDao adminDao) {
this.adminDao = adminDao;
@ -34,9 +38,11 @@ public class AdminServiceImpl implements AdminService {
/**
* findAdmin()
* @param admin
* @return
* @throws Exception
* Admin
*
* @param admin Admin
* @return Adminnull
* @throws Exception
*/
@Override
public Admin findAdmin(Admin admin) throws Exception {
@ -45,9 +51,11 @@ public class AdminServiceImpl implements AdminService {
/**
* id
* @param id
* @return Admin
* @throws Exception
* id
*
* @param id
* @return Adminnull
* @throws Exception
*/
@Override
public Admin findAdminById(Integer id) throws Exception {
@ -56,19 +64,26 @@ public class AdminServiceImpl implements AdminService {
/**
*
* @return
* @throws Exception
* PageHelper
*
* @param page
* @param size
* @return List<Admin>
* @throws Exception 使
*/
@Override
public List<Admin> findAll(int page,int size) throws Exception {
PageHelper.startPage(page,size);
public List<Admin> findAll(int page, int size) throws Exception {
// 启动PageHelper分页功能设置当前页码和每页显示的记录数后续调用持久层查询方法时会自动应用分页逻辑。
PageHelper.startPage(page, size);
return adminDao.findAll();
}
/**
* id
* @param id
* @throws Exception
* idid
*
* @param id
* @throws Exception
*/
@Override
public void deleteAdminById(Integer id) throws Exception {
@ -77,8 +92,10 @@ public class AdminServiceImpl implements AdminService {
/**
*
* @param admin
* @throws Exception
* Admin
*
* @param admin Admin
* @throws Exception
*/
@Override
public void updateAdmin(Admin admin) throws Exception {
@ -87,8 +104,11 @@ public class AdminServiceImpl implements AdminService {
/**
*
* @param admin
* @throws Exception
* 使Spring@Transactional
* Admin
*
* @param admin Admin
* @throws Exception
*/
@Transactional
@Override
@ -96,11 +116,20 @@ public class AdminServiceImpl implements AdminService {
adminDao.addAdmin(admin);
}
/**
*
* 使
* nulltruefalse
*
* @param u_name
* @return truefalse
* @throws Exception
*/
@Override
public Boolean checkUserName(String u_name) throws Exception {
//System.out.println(adminDao.checkUserName(u_name));
//用户名不存在则返回空直接false
if (adminDao.checkUserName(u_name) != null) {
// 用户名不存在则返回空直接false
if (adminDao.checkUserName(u_name)!= null) {
return true;
}
return false;
@ -108,21 +137,28 @@ public class AdminServiceImpl implements AdminService {
/**
*
* @param keyword
* @return
* @throws Exception
* PageHelper
*
* @param page
* @param size
* @param keyword
* @return List<Admin>
* @throws Exception 使
*/
@Override
public List<Admin> serarchInfo(int page,int size,String keyword) throws Exception {
PageHelper.startPage(page,size);
public List<Admin> serarchInfo(int page, int size, String keyword) throws Exception {
// 启动PageHelper分页功能设置当前页码和每页显示的记录数后续调用持久层模糊查询方法时会自动应用分页逻辑。
PageHelper.startPage(page, size);
List<Admin> list = adminDao.serarchInfo(keyword);
return list;
}
/**
*
* @param admin
* @throws Exception
* Admin
*
* @param admin Admin
* @throws Exception
*/
@Override
public void put_power(Admin admin) throws Exception {
@ -131,17 +167,23 @@ public class AdminServiceImpl implements AdminService {
/**
*
* @return
* @throws Exception
* Excel
* WriteExcelExcelWeb
*
* @return InputStreamExcel
* @throws Exception Excel
*/
@Override
public InputStream getInputStream() throws Exception {
//Excel中的每列列名依次对应数据库的字段
String[] title = new String[]{"ID","用户名","密码","姓名","学/工号","手机号","权限","描述"};
// Excel中的每列列名依次对应数据库的字段用于设置导出的Excel表格的列标题。
String[] title = new String[]{"ID", "用户名", "密码", "姓名", "学/工号", "手机号", "权限", "描述"};
// 调用持久层的方法获取数据库中所有管理员的信息得到一个List<Admin>集合集合中的每个Admin对象代表一条管理员记录。
List<Admin> admins = adminDao.exportAdminInfo();
List<Object[]> dataList = new ArrayList<Object[]>();
// 创建一个用于存储每行数据的列表每个元素是一个Object数组代表Excel表格中的一行数据除去列标题行初始化为空列表。
List<Object[]> dataList = new ArrayList<Object[]>();
// 遍历从数据库获取的管理员信息列表将每条管理员记录的各个字段值提取出来整理成Object数组形式添加到数据列表中以便后续生成Excel文件。
for (int i = 0; i < admins.size(); i++) {
Object[] obj = new Object[7];
Object[] obj = new Object[8];
obj[0] = admins.get(i).getId();
obj[1] = admins.get(i).getUsername();
obj[2] = admins.get(i).getPassword();
@ -152,20 +194,25 @@ public class AdminServiceImpl implements AdminService {
obj[7] = admins.get(i).getDescription();
dataList.add(obj);
}
// 创建WriteExcel类的实例传入列名数组和整理好的数据列表用于生成Excel文件。
WriteExcel ex = new WriteExcel(title, dataList);
InputStream in;
// 调用WriteExcel类的export方法生成包含管理员信息的Excel文件对应的输入流将其赋值给变量in。
in = ex.export();
return in;
}
/**
* /
* @param uid
* @return
* @throws Exception
* //使
* Adminnull/null
*
* @param uid /
* @return /Adminnull
* @throws Exception
*/
@Override
public Admin checkUid(String uid) throws Exception {
return adminDao.checkUid(uid);
}
}
}

@ -4,59 +4,112 @@ import java.security.MessageDigest;
/**
* MD5
* MD5
* UTF-8MD5便
*/
public class MD5Util {
/**
*
*
*
* @param b MD5
* @return
*/
private static String byteArrayToHexString(byte b[]) {
// 创建一个StringBuffer对象用于高效地拼接字符串存储最终转换后的十六进制字符串结果。
StringBuffer resultSb = new StringBuffer();
// 遍历字节数组中的每个字节
for (int i = 0; i < b.length; i++)
// 调用byteToHexString方法将每个字节转换为十六进制字符串并添加到resultSb中
resultSb.append(byteToHexString(b[i]));
return resultSb.toString();
}
/**
*
* 44
*
*
* @param b
* @return 2
*/
private static String byteToHexString(byte b) {
// 将字节转换为整数如果字节值是负数Java中字节是有符号的范围是 -128 到 127则通过加上256将其转换为正数范围0 到 255便于后续计算。
int n = b;
if (n < 0)
n += 256;
// 获取该整数的高4位用于对应十六进制的高位数字通过除以16来得到十六进制中每一位代表16的幂次高4位对应的幂次为1
int d1 = n / 16;
// 获取该整数的低4位用于对应十六进制的低位数字通过取模16来得到。
int d2 = n % 16;
// 从预定义的十六进制字符数组中查找对应的字符拼接成十六进制字符串返回高4位在前低4位在后。
return hexDigits[d1] + hexDigits[d2];
}
/**
* MD5
* MD5
* MessageDigestMD5
*
* @param origin MD5
* @param charsetname 使null使
* @return MD5null
*/
private static String MD5Encode(String origin, String charsetname) {
String resultString = null;
try {
// 先将传入的原始字符串赋值给结果字符串变量,这里可以根据实际需求考虑是否进行深拷贝等更严谨的处理(当前代码只是简单赋值)。
resultString = new String(origin);
// 获取MD5算法的MessageDigest实例用于进行MD5摘要计算通过传入"MD5"字符串指定使用MD5算法。
MessageDigest md = MessageDigest.getInstance("MD5");
// 如果未指定字符编码或者字符编码为空字符串则使用默认方式将字符串转换为字节数组后进行MD5摘要计算再将摘要结果转换为十六进制字符串。
if (charsetname == null || "".equals(charsetname))
resultString = byteArrayToHexString(md.digest(resultString.getBytes()));
else
// 如果指定了字符编码则按照指定的字符编码将字符串转换为字节数组然后进行MD5摘要计算并转换为十六进制字符串。
resultString = byteArrayToHexString(md.digest(resultString.getBytes(charsetname)));
} catch (Exception exception) {
// 当前代码只是简单捕获异常,未做详细的异常处理(如记录日志、抛出更具体的异常等),实际应用中可根据需求完善此处逻辑。
}
return resultString.toUpperCase();
}
/**
* UTF-8MD5
* 便使UTF-8MD5Encode
* SaltMD5
*
* @param origin MD5
* @return UTF-8MD5
*/
public static String MD5EncodeUtf8(String origin) {
//盐值Salt加密
//origin = origin + PropertiesUtil.getProperty("password.salt", "");
// 盐值Salt加密
// 以下代码是预留的盐值加密逻辑通过从配置文件PropertiesUtil.getProperty方法调用此处未展示该类的实现中获取盐值
// 将盐值添加到原始字符串后面再进行MD5加密可以使相同的原始字符串在不同的盐值情况下加密结果不同增强安全性。
// 当前代码将其注释掉了,如果需要启用盐值加密,可取消注释并确保配置文件读取等相关逻辑正确实现。
// origin = origin + PropertiesUtil.getProperty("password.salt", "");
return MD5Encode(origin, "utf-8");
}
// 预定义的十六进制字符数组用于在字节转换十六进制字符串时查找对应的字符表示按照十六进制的顺序排列从0到f。
private static final String hexDigits[] = {"0", "1", "2", "3", "4", "5",
"6", "7", "8", "9", "a", "b", "c", "d", "e", "f"};
/**
* MD5
* MD5Util
* MD5EncodeUtf8"123456"MD5便
*
* @param args 使
*/
public static void main(String[] args) {
MD5Util md = new MD5Util();
String psd = md.MD5EncodeUtf8("123456");
System.out.println(psd);
}
}
}

@ -5,22 +5,32 @@
Date: 2020/2/12
Time: 13:06
To change this template use File | Settings | File Templates.
上面这部分是JSP页面的头部注释说明了该文件创建时的相关信息如创建者、创建日期、时间以及提示如何修改模板等内容
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
<!-- 引入Bootstrap的CSS样式文件路径通过表达式语言获取当前页面上下文请求路径拼接而成用于实现页面的基本布局和样式美化 -->
<link rel="stylesheet" href="${pageContext.request.contextPath}/css/bootstrap.css">
<!-- 引入layer组件的CSS样式文件用于实现一些弹出层等样式效果 -->
<link rel="stylesheet" href="${pageContext.request.contextPath}/css/layer.css">
<!-- 引入jQuery库的JavaScript文件这是一个常用的JavaScript库用于简化DOM操作、事件处理等功能 -->
<script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery-3.1.1.js"></script>
<!-- 引入layer组件的JavaScript文件用于在页面中实现弹出层提示等交互功能 -->
<script type="text/javascript" src="${pageContext.request.contextPath}/layer/layer.js"></script>
</head>
<body background="${pageContext.request.contextPath}/images/01.jpg">
<!-- 添加两个换行,用于页面布局上的间隔 -->
<br><br>
<!-- 创建一个水平布局的表单行使用Bootstrap的row和form-horizontal类用于放置各种表单元素 -->
<div class="row form-horizontal">
<!-- 创建一个表单组,用于对一组相关的表单元素进行分组,方便布局和样式设置 -->
<div class="form-group">
<!-- 创建一个用于显示标签的元素设置其占2列宽度基于Bootstrap的网格系统添加控制标签的类以及自定义的form-label类用于显示用户名的文本标签 -->
<label class="col-sm-2 control-label form-label">用户名:</label>
<div class="col-sm-8">
<!-- 创建一个文本输入框添加form-control类用于应用Bootstrap的输入框样式设置name和id属性方便后续通过JavaScript等操作该元素以及提交表单时传递对应的值 -->
<input type="text" class="form-control" name="username" id="username">
</div>
</div>
@ -51,8 +61,11 @@
<div class="form-group">
<label class="col-sm-2 control-label form-label">权限:</label>
<div class="col-sm-8">
<!-- 创建一个下拉选择框添加form-control类应用样式设置name和id属性用于选择用户的权限 -->
<select class="form-control" name="power" id="power">
<!-- 设置默认选中的选项值为0显示文本为“访客” -->
<option value="0" selected>访客</option>
<!-- 使用JSTL标签进行条件判断如果在会话范围sessionScope中的adminInfo对象的power属性大于0则显示宿舍长这个选项 -->
<c:if test="${sessionScope.adminInfo.power > 0}">
<option value="1">宿舍长</option>
</c:if>
@ -75,35 +88,47 @@
</div>
</div>
</div>
<!-- 创建一个新的行,用于放置按钮等操作元素 -->
<div class="row">
<!-- 创建一个表单组并设置按钮组的样式通过col-md-offset-5类设置偏移量使其在页面中水平居中显示基于Bootstrap的列偏移功能 -->
<div class="form-group btn-group col-md-offset-5">
<!-- 创建一个按钮添加btn和btn-primary类用于应用Bootstrap的按钮主色调样式设置点击事件点击时调用toValidate()函数 -->
<button class="btn btn-primary" onclick="toValidate()">确认添加</button>
<!-- 创建一个链接按钮添加btn和btn-default类用于应用Bootstrap的默认按钮样式点击时跳转到查找所有管理员的页面路径通过表达式语言拼接而成 -->
<a type="button" class="btn btn-default" href="${pageContext.request.contextPath}/findAllAdmin">返回列表</a>
</div>
</div>
</body>
<script src="${pageContext.request.contextPath}/js/jquery-3.1.1.js"></script>
<script src="${pageContext.request.contextPath}/js/validate.js"></script>
<script>
$(function () {
//ajax校验用户名是否存在
// 在文档加载完成后执行以下代码这是jQuery的就绪函数确保DOM元素都已加载完毕再执行相关操作
// 当用户名输入框的值发生改变时change事件执行以下函数
$("#username").change(function () {
//取username的值
//用户名输入框id为username)中的值通过jQuery的val()方法获取
var u_name = $(this).val();
//ajax异步请求
// 使用jQuery的$.get()方法发起一个GET类型的Ajax异步请求
// 请求的URL是通过表达式语言拼接而成的路径传递的参数是一个包含用户名u_name的对象请求成功后会执行回调函数
$.get("${pageContext.request.contextPath}/checkUserName",{"u_name":u_name},function (msg) {
//$(".error").html(msg);
// 根据服务器返回的消息msg进行判断如果消息是“账号可用”说明用户名已存在弹出相应提示信息
if (msg == "账号可用") {
layer.msg('用户名已存在');
}else {
} else {
// 否则说明用户名可用,弹出相应提示信息
layer.msg('用户名可用');
}
});
});
});
// 当学/工号输入框的值发生改变时change事件执行以下函数
$("#uid").change(function () {
// 获取学/工号输入框id为uid中的值并去除前后空格trim()方法)
var uid = $("#uid").val().trim();
// 使用jQuery的$.get()方法发起一个GET类型的Ajax异步请求请求的URL是检查学/工号是否已注册的接口(通过表达式语言拼接路径),传递学/工号参数
// 请求成功后会执行回调函数根据返回的数据data进行判断如果data为真说明学/工号已被注册),则弹出相应提示信息
$.get("${pageContext.request.contextPath}/checkUid",{"uid":uid},function (data) {
if (data) {
layer.msg('该学/工号已被注册,请重新输入');
@ -111,12 +136,14 @@
});
});
function toValidate(){
// 创建一个validate对象实例用于对表单进行验证传入一个配置对象
var val = new validate({
/*rules里面是检验规则
*key为需要检验的input的id,
*value为此input对应的检验规则
* key为需要检验的input的id,
* value为此input对应的检验规则
*/
rules:{
// 设置用户名输入框id为username的验证规则为不能为空notEmpty
username:"notEmpty",
name:"notEmpty",
uid:"notEmpty",
@ -126,12 +153,15 @@
},
/*submitFun里面为检验成功后要执行的方法*/
submitFun:function(){
// 如果验证成功调用toSubmit()函数,该函数用于提交表单数据等后续操作
toSubmit();
}
})
}
function toSubmit(){
//增加管理员,异步提交管理员表单
// 以下是用于向服务器提交添加管理员表单数据的函数
// 获取用户名输入框的值,并去除前后空格
var username = $("#username").val().trim();
var password = $("#password").val().trim();
var name = $("#name").val().trim();
@ -139,10 +169,11 @@
var phone = $("#phone").val().trim();
var power = $("#power").val().trim();
var description = $("#description").val().trim();
// 使用jQuery的$.ajax()方法发起一个POST类型的Ajax异步请求
$.ajax({
url: "${pageContext.request.contextPath}/addAdmin",//要请求的服务器url
//这是一个对象表示请求的参数两个参数method=ajax&val=xxx服务器可以通过request.getParameter()来获取
//data:{method:"ajaxTest",val:value},
// 设置请求的URL指向添加管理员的接口通过表达式语言拼接路径
url: "${pageContext.request.contextPath}/addAdmin",
// 设置请求的数据,将各个表单字段的值组成一个对象传递给服务器,服务器可以通过相应的方式获取这些参数
data: {
username:username,
password:password,
@ -152,13 +183,16 @@
power: power,
description: description
},
type: "POST", //请求方式为POST
dataType: "json", //服务器返回的数据是什么类型
success: function(result){ //这个方法会在服务器执行成功时被调用 参数result就是服务器返回的值(现在是json类型)
type: "POST", // 设置请求方式为POST
dataType: "json", // 期望服务器返回的数据类型为JSON格式
success: function(result){ // 当服务器成功处理请求并返回数据时会执行这个回调函数参数result就是服务器返回的值现在是JSON类型
if(result){
// 如果服务器返回的结果为真(通常表示添加成功),弹出添加成功的提示信息
layer.msg('添加成功');
// 使用setTimeout()函数设置一个定时器2秒后执行函数这里是跳转到查找所有管理员的页面通过修改浏览器的当前地址实现
setTimeout(function () {window.location.href='${pageContext.request.contextPath}/findAllAdmin';},2000);
}else {
// 如果服务器返回的结果为假(通常表示添加失败),弹出添加失败的提示信息,并提示联系管理员
layer.msg('添加失败,请联系管理员');
setTimeout(function () {window.location.href='${pageContext.request.contextPath}/findAllAdmin';},2000);
}
@ -166,5 +200,4 @@
});
}
</script>
</body>
</html>
</html>

@ -4,120 +4,153 @@
Date: 2020/2/12
Time: 13:08
To change this template use File | Settings | File Templates.
这部分是JSP页面的头部注释说明了该文件创建时的相关信息如创建者、创建日期、时间以及提示如何修改模板等内容
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>Title</title>
<!-- 引入Bootstrap的CSS样式文件路径通过表达式语言获取当前页面上下文请求路径拼接而成用于实现页面的基本布局和样式美化 -->
<link rel="stylesheet" href="${pageContext.request.contextPath}/css/bootstrap.css">
<!-- 引入layer组件的CSS样式文件用于实现一些弹出层等样式效果 -->
<link rel="stylesheet" href="${pageContext.request.contextPath}/css/layer.css">
<!-- 引入jQuery库的JavaScript文件这是一个常用的JavaScript库用于简化DOM操作、事件处理等功能 -->
<script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery-3.1.1.js"></script>
<!-- 引入layer组件的JavaScript文件用于在页面中实现弹出层提示等交互功能 -->
<script type="text/javascript" src="${pageContext.request.contextPath}/layer/layer.js"></script>
</head>
<body background="${pageContext.request.contextPath}/images/01.jpg">
<!-- 添加两个换行,用于页面布局上的间隔 -->
<br><br>
<!-- 创建一个隐藏的输入框设置id和name属性为“id”通过表达式语言获取并设置其值为“ad.id”推测“ad”是某个从后台传递过来的管理员对象相关的数据这个输入框可能用于存储要编辑的管理员记录的唯一标识方便后续提交表单时传递给服务器 -->
<input type="hidden" id="id" name="id" value="${ad.id}">
<!-- 创建一个水平布局的表单行使用Bootstrap的row和form-horizontal类用于放置各种表单元素 -->
<div class="row form-horizontal">
<!-- 创建一个表单组,用于对一组相关的表单元素进行分组,方便布局和样式设置 -->
<div class="form-group">
<!-- 创建一个用于显示标签的元素设置其占2列宽度基于Bootstrap的网格系统添加控制标签的类以及自定义的form-label类用于显示用户名的文本标签 -->
<label class="col-sm-2 control-label form-label">用户名:</label>
<div class="col-sm-8">
<!-- 创建一个文本输入框设置为只读readonly通过表达式语言获取并设置其值为“ad.username”添加form-control类用于应用Bootstrap的输入框样式设置name和id属性方便后续通过JavaScript等操作该元素以及提交表单时传递对应的值此处设置只读可能表示该用户名不允许在此处修改 -->
<input type="text" readonly value="${ad.username}" class="form-control" name="username" id="username">
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label form-label">姓名:</label>
<div class="col-sm-8">
<!-- 创建一个文本输入框设置为只读通过表达式语言获取并设置其值为“ad.name”添加form-control类用于应用Bootstrap的输入框样式设置name和id属性此处设置只读可能有相应业务逻辑决定暂不允许修改 -->
<input type="text" readonly value="${ad.name}" class="form-control" name="name" id="name">
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label form-label">学/工号:</label>
<div class="col-sm-8">
<!-- 创建一个文本输入框添加form-control类应用样式通过表达式语言获取并设置其值为“ad.uid”设置name和id属性用于输入或显示学/工号,从此处未设置只读来看可能是允许修改该字段内容 -->
<input type="text" class="form-control" value="${ad.uid}" name="uid" id="uid">
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label form-label">手机号:</label>
<div class="col-sm-8">
<!-- 创建一个文本输入框通过表达式语言获取并设置其值为“ad.phone”添加form-control类应用样式设置name和id属性用于输入或显示手机号 -->
<input type="text" value="${ad.phone}" class="form-control" name="phone" id="phone">
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label form-label">描述:</label>
<div class="col-sm-8">
<!-- 创建一个文本输入框通过表达式语言获取并设置其值为“ad.description”添加form-control类应用样式设置name和id属性用于输入或显示管理员相关的描述信息 -->
<input type="text" class="form-control" value="${ad.description}" name="description" id="description">
</div>
</div>
</div>
<!-- 创建一个新的行,用于放置按钮等操作元素 -->
<div class="row">
<!-- 创建一个表单组并设置按钮组的样式通过col-md-offset-5类设置偏移量使其在页面中水平居中显示基于Bootstrap的列偏移功能 -->
<div class="form-group btn-group col-md-offset-5">
<!-- 创建一个按钮添加btn和btn-warning类用于应用Bootstrap的警告色调样式设置点击事件点击时调用toValidate()函数,该按钮用于触发确认修改的操作 -->
<button class="btn btn-warning" onclick="toValidate()">确认修改</button>
<!-- 创建一个链接按钮添加btn和btn-primary类用于应用Bootstrap的主色调样式点击时跳转到查找所有管理员的页面路径通过表达式语言拼接而成用于返回管理员列表页面 -->
<a type="button" href="${pageContext.request.contextPath}/findAllAdmin" class="btn btn-primary">返回列表</a>
</div>
</div>
</body>
<script src="${pageContext.request.contextPath}/js/jquery-3.1.1.js"></script>
<script src="${pageContext.request.contextPath}/js/validate.js"></script>
<script>
function toValidate(){
// 创建一个validate对象实例用于对表单进行验证传入一个配置对象
var val = new validate({
/*rules里面是检验规则
*key为需要检验的input的id,
*value为此input对应的检验规则
* key为需要检验的input的id,
* value为此input对应的检验规则
*/
rules:{
// 设置姓名输入框id为name的验证规则为不能为空notEmpty
name:"notEmpty",
// 设置学/工号输入框id为uid的验证规则为不能为空notEmpty
uid:"notEmpty",
// 设置描述输入框id为description的验证规则为不能为空notEmpty
description:"notEmpty",
// 设置手机号输入框id为phone的验证规则为符合手机号码格式mobile这里应该是在validate.js中自定义的验证规则用于校验手机号合法性
phone:"mobile",
},
/*submitFun里面为检验成功后要执行的方法*/
submitFun:function(){
// 如果验证成功调用toSubmit()函数,该函数用于提交表单数据等后续操作
toSubmit();
}
})
}
function toSubmit(){
//增加管理员,异步提交管理员表单
// 以下是用于向服务器提交修改管理员表单数据的函数
// 获取隐藏输入框id为id中的值并去除前后空格trim()方法),该值是要修改的管理员记录的唯一标识
var id = $("#id").val().trim();
var username = $("#username").val().trim();
var name = $("#name").val().trim();
var uid = $("#uid").val().trim();
var phone = $("#phone").val().trim();
var description = $("#description").val().trim();
// 使用layer组件弹出一个确认框提示用户是否确定要修改当用户点击确认按钮“确定”执行回调函数中的代码回调函数接收一个参数index用于后续操作该弹出层如关闭它
layer.confirm('确定要修改吗',function (index) {
// 判断当前用户的权限通过表达式语言从会话范围获取adminInfo对象的power属性如果小于3推测3及以上为有足够权限修改管理员信息的级别则提示用户权限不足关闭弹出层并且终止后续操作返回false
if (${sessionScope.adminInfo.power < 3}) {//非超级管理员不能修改管理员信息
layer.msg('对不起,您权限不足');
layer.close(index);
return false;
}
$.ajax({
url: "${pageContext.request.contextPath}/editAdmin",//要请求的服务器url
//这是一个对象表示请求的参数两个参数method=ajax&val=xxx服务器可以通过request.getParameter()来获取
//data:{method:"ajaxTest",val:value},
data: {
id:id,
username:username,
name:name,
uid:uid,
phone: phone,
description: description
},
type: "POST", //请求方式为POST
dataType: "json", //服务器返回的数据是什么类型
success: function(result){ //这个方法会在服务器执行成功时被调用 参数result就是服务器返回的值(现在是json类型)
if(result){
layer.msg('修改成功');
setTimeout(function () {window.location.href='${pageContext.request.contextPath}/findAllAdmin';},2000);
}else {
layer.msg('修改失败,请联系管理员');
setTimeout(function () {window.location.href='${pageContext.request.contextPath}/findAllAdmin';},2000);
// 使用jQuery的$.ajax()方法发起一个POST类型的Ajax异步请求
$.ajax({
// 设置请求的URL指向修改管理员信息的接口通过表达式语言拼接路径
url: "${pageContext.request.contextPath}/editAdmin",
// 设置请求的数据,将各个表单字段的值组成一个对象传递给服务器,服务器可以通过相应的方式获取这些参数
data: {
id:id,
username:username,
name:name,
uid:uid,
phone: phone,
description: description
},
type: "POST", // 设置请求方式为POST
dataType: "json", // 期望服务器返回的数据类型为JSON格式
success: function(result){ // 当服务器成功处理请求并返回数据时会执行这个回调函数参数result就是服务器返回的值现在是JSON类型
if(result){
// 如果服务器返回的结果为真(通常表示修改成功),弹出修改成功的提示信息
layer.msg('修改成功');
// 使用setTimeout()函数设置一个定时器2秒后执行函数这里是跳转到查找所有管理员的页面通过修改浏览器的当前地址实现
setTimeout(function () {window.location.href='${pageContext.request.contextPath}/findAllAdmin';},2000);
}else {
// 如果服务器返回的结果为假(通常表示修改失败),弹出修改失败的提示信息,并提示联系管理员
layer.msg('修改失败,请联系管理员');
setTimeout(function () {window.location.href='${pageContext.request.contextPath}/findAllAdmin';},2000);
}
}
}
});
});
});
}
</script>
</body>
</html>
</html>

@ -4,6 +4,7 @@
Date: 2020/2/10
Time: 21:45
To change this template use File | Settings | File Templates.
这部分是JSP页面的头部注释说明了该文件创建时的相关信息如创建者、创建日期、时间以及提示如何修改模板等内容
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
@ -11,38 +12,59 @@
<head>
<meta charset="UTF-8">
<title></title>
<!-- 设置页面渲染引擎为webkit用于在一些浏览器中更好地渲染页面样式等 -->
<meta name="renderer" content="webkit">
<!-- 配置页面兼容模式使其在IE浏览器下以最高级别的标准模式IE=edge以及启用Chrome Framechrome=1来渲染页面以提高兼容性 -->
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<!-- 引入字体相关的CSS样式文件路径通过表达式语言获取当前页面上下文请求路径拼接而成用于页面中字体的显示样式设置 -->
<link rel="stylesheet" href="${pageContext.request.contextPath}/css/font.css">
<!-- 引入xadmin框架的CSS样式文件用于实现该框架下特定的页面布局和样式效果 -->
<link rel="stylesheet" href="${pageContext.request.contextPath}/css/xadmin.css">
<!-- 引入Bootstrap的CSS样式文件用于实现页面基本的布局和样式美化 -->
<link rel="stylesheet" href="${pageContext.request.contextPath}/css/bootstrap.css">
<!-- 引入jQuery库的JavaScript文件这是一个常用的JavaScript库用于简化DOM操作、事件处理等功能 -->
<script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery-3.1.1.js"></script>
<!-- 引入layui框架的JavaScript核心文件layui是一个用于构建页面交互界面的前端框架 -->
<script src="${pageContext.request.contextPath}/lib/layui/layui.js" charset="utf-8"></script>
<!-- 引入xadmin框架的JavaScript文件用于实现该框架相关的功能和交互效果 -->
<script type="text/javascript" src="${pageContext.request.contextPath}/js/xadmin.js"></script>
<!-- 引入Bootstrap的JavaScript文件用于实现Bootstrap框架相关的交互功能比如一些组件的动态效果等 -->
<script type="text/javascript" src="${pageContext.request.contextPath}/js/bootstrap.js"></script>
<!-- 再次引入jQuery库的JavaScript文件此处可能存在重复引入问题可根据实际情况进行优化 -->
<script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery-3.1.1.js"></script>
<!-- 以下是针对IE浏览器版本小于9的情况引入html5shiv库的JavaScript文件用于让IE低版本支持HTML5标签 -->
<!-- 以及引入respond.js库的JavaScript文件用于让IE低版本支持CSS3的媒体查询功能提升页面在低版本IE浏览器下的兼容性 -->
<!--[if lt IE 9]>
<script src="https://cdn.staticfile.org/html5shiv/r29/html5.min.js"></script>
<script src="https://cdn.staticfile.org/respond.js/1.4.2/respond.min.js"></script>
<![endif]-->
<script>
function changePageSize() {
//获取下拉框的值
// 获取下拉框id为changePageSize中用户选择的值,该下拉框通常用于选择每页显示的数据条数
var pageSize = $("#changePageSize").val();
//向服务器发送请求,改变每页显示条数
location.href = "${pageContext.request.contextPath}/findAllAdmin?page=1&size="+ pageSize;
// 通过修改浏览器地址栏的URLlocation.href向服务器发送请求,传递新的每页显示条数参数pageSize同时设置当前页码为1用于改变每页显示条数后刷新页面数据展示
location.href = "${pageContext.request.contextPath}/findAllAdmin?page=1&size=" + pageSize;
}
// 当搜索按钮id为serarch_btn被点击时执行以下函数
$("#serarch_btn").click(function () {
// 获取输入框id为keyword中的用户输入的关键字内容该关键字通常用于在查找管理员数据时进行筛选
var keyword = $("#keyword").val();
location.href="${pageContext.request.contextPath}/findAllAdmin?page=1&size=5&keyword="+keyword;
// 通过修改浏览器地址栏的URL向服务器发送请求传递关键字参数、设置当前页码为1以及每页显示条数为5用于根据关键字进行搜索并刷新页面展示搜索结果
location.href = "${pageContext.request.contextPath}/findAllAdmin?page=1&size=5&keyword=" + keyword;
});
// 当刷新按钮id为refresh代码中未展示该按钮的HTML部分但推测存在此功能按钮被点击时执行以下函数
$("#refresh").click(function () {
// 重置表单id为myform将表单中的输入框等元素的值恢复到初始状态此处假设表单中各元素有相应的重置逻辑实现
$("#myform").reset();
location.href="${pageContext.request.contextPath}/findAllAdmin?page=1&size=5";
// 通过修改浏览器地址栏的URL向服务器发送请求设置当前页码为1以及每页显示条数为5用于刷新页面展示初始的数据列表
location.href = "${pageContext.request.contextPath}/findAllAdmin?page=1&size=5";
});
</script>
</head>
<body>
<%-- 以下这部分代码被注释掉了,原本可能是用于页面导航栏的展示,包含了面包屑导航以及一个刷新按钮,点击刷新按钮可重新加载当前页面 --%>
<%--<div class="x-nav">
<span class="layui-breadcrumb">
<a href="">首页</a>
@ -53,32 +75,46 @@
<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>
</div>--%>
<!-- 使用layui的流体布局容器类layui-fluid使内部元素能自适应页面宽度 -->
<div class="layui-fluid">
<!-- 创建一个layui的行元素并设置列间距为15px用于放置页面中的各种模块 -->
<div class="layui-row layui-col-space15">
<div class="layui-col-md12">
<div class="layui-card">
<div class="layui-card-body ">
<!-- 创建一个表单设置id为myform应用layui的表单样式以及列间距样式用于放置搜索等相关的表单元素 -->
<form id="myform" class="layui-form layui-col-space5">
<!-- 创建一个内联的表单元素块在小屏幕xs尺寸下显示用于放置一个文本输入框 -->
<div class="layui-inline layui-show-xs-block">
<!-- 创建一个文本输入框设置自动补全关闭添加占位提示文字设置name和id属性方便后续传递参数以及操作该元素同时通过表达式语言获取并设置输入框的值如果存在相应参数传入的话 -->
<input class="layui-input" type="text" autocomplete="off" placeholder="请输入关键字" name="keyword" id="keyword" value="${param.keyword}">
</div>
<!-- 创建一个内联的表单元素块在小屏幕xs尺寸下显示用于放置一个搜索按钮 -->
<div class="layui-inline layui-show-xs-block">
<!-- 创建一个layui的按钮设置id为serarch_btn添加相应的提交和过滤属性lay-submit和lay-filter按钮内部通过图标展示搜索的图标样式 -->
<button class="layui-btn" id="serarch_btn" lay-submit="" lay-filter="sreach"><i class="layui-icon">&#xe615;</i></button>
</div>
<!-- 创建一个内联的表单元素块在小屏幕xs尺寸下显示并且设置靠右对齐x-right类推测是自定义的样式类用于控制布局用于放置一个链接按钮 -->
<div class="layui-inline layui-show-xs-block x-right">
<!-- 创建一个layui的常规按钮样式的链接按钮点击可跳转到默认的管理员列表页面设置了固定的每页显示5条数据按钮内部通过图标展示相应的图标样式 -->
<a class="layui-btn layui-btn-normal" href="${pageContext.request.contextPath}/findAllAdmin?page=1&size=5"><i class="layui-icon">&#xe669;</i></a>
</div>
</form>
</div>
<xblock>
<!-- 创建一个添加按钮点击可跳转到添加管理员的页面按钮应用layui的常规按钮样式按钮内部通过图标展示添加的图标样式 -->
<a href="${pageContext.request.contextPath}/adminAdd" class="layui-btn layui-btn-normal"><i class="layui-icon">&#xe654;</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>
<!-- 创建一个靠右对齐的文本元素用于展示总的数据条数信息通过表达式语言获取并展示总数据条数pageInfo.total -->
<span class="x-right" style="line-height:40px">共有数据:${pageInfo.total} 条</span>
</xblock>
<div class="layui-card-body">
<!-- 创建一个layui的表格应用layui的表格和表单样式用于展示管理员数据列表 -->
<table class="layui-table layui-form">
<thead>
<tr style="text-align: center">
<!-- 表格表头部分分别设置各列的标题如ID、用户名等并且设置文本居中对齐 -->
<th style="text-align: center">ID</th>
<th style="text-align: center">用户名</th>
<th style="text-align: center">姓名</th>
@ -92,35 +128,43 @@
<%
int j = 1;
%>
<!-- 使用JSTL的<>标签循环遍历从服务器端获取的管理员数据列表pageInfo.list每次循环将一个管理员对象赋值给admin变量 -->
<c:forEach items="${pageInfo.list}" var="admin">
<tr id="light" style="text-align: center">
<td><%=j++%></td>
<td>${admin.username}</td>
<td>${admin.name}</td>
<td>${admin.uid}</td>
<td>${admin.phone}</td>
<td>${admin.power}</td>
<td>${admin.description}</td>
<td class="td-manage">
<a title="编辑" href="${pageContext.request.contextPath}/adminEdit?id=${admin.id}">
<i class="layui-icon">&#xe642;</i>
</a>
<a title="授权" onclick="put_power(this,${admin.id},${sessionScope.adminInfo.power})" href="javascript:;">
<i class="layui-icon">&#xe672;</i>
</a>
<a title="删除" onclick="member_del(this,${admin.id},${sessionScope.adminInfo.power})" href="javascript:;">
<i class="layui-icon">&#xe640;</i>
</a>
</td>
</c:forEach>
</tr>
<tr id="light" style="text-align: center">
<!-- 在表格行中展示数据ID列通过Java代码片段<%=j++%>)自增序号来显示序号,其他列通过表达式语言展示管理员对象的各个属性值,如用户名、姓名等 -->
<td><%=j++%></td>
<td>${admin.username}</td>
<td>${admin.name}</td>
<td>${admin.uid}</td>
<td>${admin.phone}</td>
<td>${admin.power}</td>
<td>${admin.description}</td>
<td class="td-manage">
<!-- 创建一个编辑操作的链接按钮点击可跳转到编辑管理员信息的页面通过传递管理员的id参数来指定要编辑的对象按钮内部通过图标展示编辑的图标样式 -->
<a title="编辑" href="${pageContext.request.contextPath}/adminEdit?id=${admin.id}">
<i class="layui-icon">&#xe642;</i>
</a>
<!-- 创建一个授权操作的链接按钮点击时调用put_power函数并传递当前管理员的id以及当前用户的权限信息用于判断是否有权限进行授权操作按钮内部通过图标展示授权的图标样式 -->
<a title="授权" onclick="put_power(this,${admin.id},${sessionScope.adminInfo.power})" href="javascript:;">
<i class="layui-icon">&#xe672;</i>
</a>
<!-- 创建一个删除操作的链接按钮点击时调用member_del函数并传递当前管理员的id以及当前用户的权限信息用于判断是否有权限进行删除操作按钮内部通过图标展示删除的图标样式 -->
<a title="删除" onclick="member_del(this,${admin.id},${sessionScope.adminInfo.power})" href="javascript:;">
<i class="layui-icon">&#xe640;</i>
</a>
</td>
</tr>
</c:forEach>
</tbody>
</table>
</div>
<div class="pull-left">
<div class="form-group form-inline">
<!-- 展示分页相关信息,如总页数、当前页码等文本信息,并且通过表达式语言获取相应的数据进行展示 -->
共&nbsp;${pageInfo.pages}&nbsp;页&emsp;当前页:${pageInfo.pageNum}&nbsp;/&nbsp;${pageInfo.pages}&emsp; 每页
<!-- 创建一个下拉框用于选择每页显示的条数添加表单控制类样式设置id属性当下拉框的值改变时调用changePageSize函数来改变每页显示条数 -->
<select class="form-control" id="changePageSize" onchange="changePageSize()">
<!-- 下拉框中的各个选项,通过表达式语言获取当前每页显示条数作为默认选中项,并设置其他可选的每页显示条数选项 -->
<option value="1">${pageInfo.size}</option>
<option value="5">5</option>
<option value="10">10</option>
@ -130,129 +174,42 @@
</div>
</div>
<c:choose>
<c:when test="${pageInfo.pages < 5}">
<c:set var="begin" value="1">
</c:set>
<c:set var="end" value="${pageInfo.pages}">
</c:set>
</c:when>
<c:when test="${pageInfo.pageNum <= 3}">
<c:set var="begin" value="1">
</c:set>
<c:set var="end" value="5">
</c:set>
</c:when>
<c:when test="${pageInfo.pageNum > 3 and pageInfo.pageNum <= pageInfo.pages-2}">
<c:set var="begin" value="${pageInfo.pageNum - 2}">
</c:set>
<c:set var="end" value="${pageInfo.pageNum + 2}">
</c:set>
</c:when>
<c:otherwise>
<c:set var="begin" value="${pageInfo.pages - 4}">
</c:set>
<c:set var="end" value="${pageInfo.pages}">
</c:set>
</c:otherwise>
<c:when test="${pageInfo.pages < 5}">
<!-- 当总页数小于5时设置分页导航的起始页码begin和结束页码end都为1到总页数用于展示所有页码链接 -->
<c:set var="begin" value="1">
</c:set>
<c:set var="end" value="${pageInfo.pages}">
</c:set>
</c:when>
<c:when test="${pageInfo.pageNum <= 3}">
<!-- 当当前页码小于等于3时设置分页导航的起始页码为1结束页码为5通常用于在前面几页时展示固定范围的页码链接 -->
<c:set var="begin" value="1">
</c:set>
<c:set var="end" value="5">
</c:set>
</c:when>
<c:when test="${pageInfo.pageNum > 3 and pageInfo.pageNum <= pageInfo.pages-2}">
<!-- 当当前页码大于3且小于等于总页数减2时设置分页导航的起始页码为当前页码减2结束页码为当前页码加2用于在中间页码范围时动态展示周边的页码链接 -->
<c:set var="begin" value="${pageInfo.pageNum - 2}">
</c:set>
<c:set var="end" value="${pageInfo.pageNum + 2}">
</c:set>
</c:when>
<c:otherwise>
<!-- 当当前页码大于总页数减2时即接近尾页时设置分页导航的起始页码为总页数减4结束页码为总页数用于展示尾页附近的页码链接 -->
<c:set var="begin" value="${pageInfo.pages - 4}">
</c:set>
<c:set var="end" value="${pageInfo.pages}">
</c:set>
</c:otherwise>
</c:choose>
<div class="layui-card-body x-right" style="height: min-content">
<div class="page">
<div>
<!-- 创建一个首页链接按钮,点击可跳转到第一页,传递每页显示条数以及关键字参数(如果有),按钮应用相应的样式类 -->
<a class="next" href="${pageContext.request.contextPath}/findAllAdmin?page=1&size=${pageInfo.pageSize}&keyword=${param.keyword}">首页</a>
<!-- 当当前页码大于1时创建一个上一页链接按钮点击可跳转到上一页传递相应的参数按钮应用相应的样式类 -->
<c:if test="${pageInfo.pageNum > 1}">
<a class="prev" href="${pageContext.request.contextPath}/findAllAdmin?page=${pageInfo.pageNum-1}&size=${pageInfo.pageSize}&keyword=${param.keyword}">上一页</a>
<a class="prev" href="${pageContext.request.contextPath}/findAllAdmin?page=${pageInfo.pageNum-1}&size=${pageInfo.pageSize}&keyword=${param.keyword}">上一页</a>
</c:if>
<c:forEach var="i" begin="${begin}" end="${end}" step="1">
<c:if test="${pageInfo.pageNum == i}">
<span class="current">${i}</span>
</c:if>
<c:if test="${pageInfo.pageNum != i}">
<a class="num" href="${pageContext.request.contextPath}/findAllAdmin?page=${i}&size=${pageInfo.pageSize}&keyword=${param.keyword}">${i}</a>
</c:if>
</c:forEach>
<c:if test="${pageInfo.pageNum < pageInfo.pages}">
<a class="next" href="${pageContext.request.contextPath}/findAllAdmin?page=${pageInfo.pageNum+1}&size=${pageInfo.pageSize}&keyword=${param.keyword}">下一页</a>
</c:if>
<a class="next" href="${pageContext.request.contextPath}/findAllAdmin?page=${pageInfo.pages}&size=${pageInfo.pageSize}&keyword=${param.keyword}">尾页</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
//删除操作
function member_del(obj,id,power){
layer.confirm('确认要删除吗?',function(index){
if ( power < 3){
layer.msg('对不起,您没有权限!');
return false;
}
//发异步删除数据
$.get("${pageContext.request.contextPath}/deleteAdmin",{"id":id},function (data) {
if(data = true){
layer.msg('删除成功!',{icon:1,time:2000});
setTimeout(function () {window.location.href='${pageContext.request.contextPath}/findAllAdmin';},2000);
}else {
layer.msg('删除失败!',{icon:1,time:2000});
setTimeout(function () {window.location.href='${pageContext.request.contextPath}/findAllAdmin';},2000);
}
});
});
}
//授权操作
function put_power(obj,id,power) {
//验证是否拥有权限
if (power < 3) {
layer.msg('对不起,您没有权限!');
return false;
}
//prompt层
layer.prompt({title: '输入授权密码,完成身份校验', formType: 1}, function(password, index){
if (password != 123) {
layer.msg('授权密码有误,身份验证失败');
layer.close(index);
return false;
}
layer.close(index);
layer.prompt({title: '输入权限级别,并确认授权', formType: 1}, function(level, index){
if (level < 0 || level > 4) {
layer.msg('授权等级输入有误,请重新输入!')
return false;
}
if (level > power) {
layer.msg('对不起,您权限不足!')
layer.close(index);
return false;
}
$.get("${pageContext.request.contextPath}/put_power",{"id":id,"power":level},function (data) {
if(data){
layer.msg('授权成功!');
layer.close(index);
setTimeout(function () {window.location.href='${pageContext.request.contextPath}/findAllAdmin';},2000);
}else {
layer.msg('授权失败,请联系管理员!');
layer.close(index);
}
});
layer.close(index);
});
});
}
//导出Excel操作
function exportInfo(power) {
if (power < 3) {
layer.msg('对不起,您权限不足!');
return false;
}
layer.confirm('确定导出管理员数据吗?',function (index) {
location.href="${pageContext.request.contextPath}/exportAdminInfo";
layer.close(index);
});
}
</script>
</body>
</html>
<!-- 使用JSTL的标签循环生成页码链接按钮根据前面设置的起始页码begin

@ -4,20 +4,29 @@
Date: 2020/2/10
Time: 10:32
To change this template use File | Settings | File Templates.
这部分是JSP页面头部的注释主要说明了该文件创建时相关信息例如创建者、创建日期、时间以及提示如何修改模板等内容方便后续对代码来源及修改情况进行追溯。
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<!-- 引入自定义的用于用户登录页面的CSS样式文件路径通过JSP表达式语言${pageContext.request.contextPath})获取当前页面上下文请求路径后拼接而成,目的是为登录页面设置特定的样式风格,使其符合设计要求。 -->
<link rel="stylesheet" href="${pageContext.request.contextPath}/css/usersLogin.css">
<!-- 引入页面图标文件指定图标大小为32x32像素用于在浏览器的标签页等位置显示特定的图标增强页面的辨识度和品牌性如果是对应特定项目的话。 -->
<link rel="icon" href="${pageContext.request.contextPath}/images/favicon.ico" sizes="32x32" />
<!-- 引入自定义的通用样式文件根据media属性中指定的“screen”可知主要用于屏幕显示相关的样式设置同样通过页面请求路径拼接来获取样式文件位置用于页面整体通用样式的规范和美化。 -->
<link rel="stylesheet" media="screen" href="${pageContext.request.contextPath}/css/style.css">
<!-- 引入用于重置页面默认样式的CSS文件类型声明为“text/css”路径也是基于请求路径拼接它能清除浏览器自带的一些默认样式让页面在不同浏览器下展示效果更趋一致。 -->
<link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath}/css/reset.css"/>
<!-- 引入jQuery库的JavaScript文件jQuery是一个广泛使用的JavaScript库能极大地简化DOM操作、事件处理等常见的前端开发任务方便后续编写交互逻辑。 -->
<script src="${pageContext.request.contextPath}/js/jquery-3.1.1.js"></script>
<!-- 引入layer组件的JavaScript文件layer组件常用于在页面中弹出提示框、模态框等交互效果这里引入是为了后续展示如登录验证提示等相关信息。 -->
<script src="${pageContext.request.contextPath}/layer/layer.js" type="text/javascript"></script>
<!-- 引入自定义的与登录相关的JavaScript文件可能包含一些登录业务特有的逻辑处理代码等通过请求路径拼接来定位文件辅助实现登录页面的各种功能。 -->
<script src="${pageContext.request.contextPath}/js/login.js"></script>
<title>登录页面--LOGIN</title>
<%--<script type="text/javascript">
<%-- 以下这段JavaScript代码被注释掉了原本的功能是在页面加载完成通过$(function () {...}) 这种jQuery的就绪函数来确保DOM加载完毕监听用户名输入框id为“username”的内容变化事件change事件。当用户名输入框的值改变时会获取输入框的值通过$(this).val()获取然后发起一个GET类型的Ajax异步请求到服务器端的“checkUserName”接口路径通过表达式语言拼接而成传递用户名参数{"u_name":u_name}并根据服务器返回的消息msg进行判断如果消息不是“账号可用”就弹出提示“账号不存在”的信息框。不过当前处于注释状态未生效。 --%>
<%--<script type="text/javascript">
$(function () {
//ajax校验用户名是否存在
$("#username").change(function () {
@ -26,64 +35,88 @@
//ajax异步请求
$.get("${pageContext.request.contextPath}/checkUserName",{"u_name":u_name},function (msg) {
//$(".error").html(msg);
if (msg != "账号可用") {
if (msg!= "账号可用") {
layer.msg('账号不存在');
}
});
});
});
</script>--%>
</script>--%>
</head>
<body>
<!-- 创建一个HTML表单通过action属性指定表单提交的目标URL这里使用表达式语言拼接出指向登录处理的后端接口路径设置表单名称为“myform”提交方法为“post”用于将用户输入的登录信息发送到服务器端进行验证处理。 -->
<form action="${pageContext.request.contextPath}/login" name="myform" method="post">
<div id="particles-js">
<div class="login">
<div class="login-top">
后台登录
</div>
<div class="login-center clearfix">
<div class="login-center-img"><img src="${pageContext.request.contextPath}/images/name.png"/></div>
<div class="login-center-input">
<input type="text" id="username" name="username" placeholder="请输入您的用户名" onfocus="this.placeholder=''" onblur="this.placeholder='请输入您的用户名'"/>
<div class="login-center-input-text">用户名</div>
<!-- 创建一个具有特定效果可能与粒子特效相关需结合引入的js文件进一步确定一般用于页面背景装饰等的容器id为“particles-js”作为登录相关元素的父容器营造出独特的页面视觉效果。 -->
<div id="particles-js">
<!-- 创建一个登录框相关的容器应用了“login”类推测在对应的CSS文件中有对这个类定义的样式规则用于包裹登录框内的各个部分如标题、输入框、按钮等来实现登录框整体的布局和样式呈现。 -->
<div class="login">
<!-- 登录框顶部区域的容器,用于显示如“后台登录”这样的标题文本,给用户明确提示当前登录的是后台系统。 -->
<div class="login-top">
后台登录
</div>
</div>
<div class="login-center clearfix">
<div class="login-center-img"><img src="${pageContext.request.contextPath}/images/password.png"/></div>
<div class="login-center-input">
<input type="password" id="password" name="password" placeholder="请输入您的密码" onfocus="this.placeholder=''" onblur="this.placeholder='请输入您的密码'"/>
<div class="login-center-input-text">密码</div>
<!-- 创建登录框中间区域的容器并应用“clearfix”类用于清除浮动在CSS中通过这个类设置相关样式确保内部的浮动元素布局正常避免出现排版混乱问题用于放置用户名相关的输入框等元素使其在水平方向上合理排列。 -->
<div class="login-center clearfix">
<!-- 创建一个用于放置用户名图标的容器,里面嵌入一个图片元素,通过指定的路径(使用表达式语言拼接获取)加载用户名对应的图标图片,用于在视觉上标识这是用户名输入的区域。 -->
<div class="login-center-img"><img src="${pageContext.request.contextPath}/images/name.png"/></div>
<!-- 创建一个用于放置用户名输入框的容器,包含实际的输入框元素和相关提示文本元素,用于用户输入用户名以及显示相应提示信息。 -->
<div class="login-center-input">
<!-- 创建一个文本输入框设置id为“username”方便后续通过JavaScript代码获取其值和操作设置name属性为“username”用于在表单提交时作为参数名传递给服务器添加占位提示文字“请输入您的用户名”并且通过onfocus和onblur事件来控制当输入框获取焦点用户点击输入框准备输入时和失去焦点用户鼠标离开输入框后时占位文字的显示和隐藏提升用户体验。 -->
<input type="text" id="username" name="username" placeholder="请输入您的用户名" onfocus="this.placeholder=''" onblur="this.placeholder='请输入您的用户名'"/>
<!-- 创建一个用于显示用户名提示文本的容器初始显示“用户名”字样可能通过后续的JavaScript交互逻辑比如输入框获取焦点时隐藏等来改变其显示状态进一步辅助用户了解该输入框的用途。 -->
<div class="login-center-input-text">用户名</div>
</div>
</div>
<!-- 再次创建登录框中间区域的容器(结构与上面用户名部分类似),用于放置密码相关的输入框等元素,将密码相关的输入和提示信息组织在一起,方便用户操作和查看。 -->
<div class="login-center clearfix">
<!-- 创建一个用于放置密码图标的容器,嵌入对应的密码图标图片,从指定路径(通过表达式语言获取)加载,用于直观地提示用户此处是输入密码的地方。 -->
<div class="login-center-img"><img src="${pageContext.request.contextPath}/images/password.png"/></div>
<!-- 创建一个用于放置密码输入框的容器,同样包含实际输入框和提示文本元素,用于密码的输入及相关提示展示。 -->
<div class="login-center-input">
<!-- 创建一个密码输入框设置id为“password”方便操作name为“password”用于表单提交传参添加占位提示文字“请输入您的密码”通过onfocus和onblur事件控制占位文字的显示和隐藏与用户名输入框的交互方式类似符合常规的用户输入习惯。 -->
<input type="password" id="password" name="password" placeholder="请输入您的密码" onfocus="this.placeholder=''" onblur="this.placeholder='请输入您的密码'"/>
<!-- 创建一个用于显示密码提示文本的容器,初始显示“密码”字样,后续可根据交互逻辑改变显示状态,辅助用户识别该输入框功能。 -->
<div class="login-center-input-text">密码</div>
</div>
</div>
<!-- 创建一个登录按钮相关的容器应用“login-button”类在CSS中有对应的样式定义用于设置按钮的外观样式如颜色、大小、边框等设置点击事件点击时调用“check()”函数,通过这个函数来进行登录前的输入信息验证等操作,决定是否能提交表单。 -->
<div class="login-button" onclick="check()">
登录
</div>
<!-- 创建一个用于显示提示信息的文本元素设置文本居中对齐、颜色为红色通过表达式语言获取并显示“msg”变量的值推测是后端传递过来的错误提示等信息比如登录失败原因等并且添加一些空格用于排版让提示信息在页面上展示更清晰美观方便用户查看。 -->
<span style="text-align: center;color: red;"><br>&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;${msg}</span>
</div>
<div class="login-button" onclick="check()">
登录
</div>
<span style="text-align: center;color: red;"><br>&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;${msg}</span>
<!-- 创建一个用于显示特定动画效果的元素比如旋转平面动画效果需结合相关CSS和JavaScript代码来看具体效果可能是作为页面的一个加载动画或者装饰性动画元素目前为空的div其具体显示内容和动画效果由对应的样式和脚本控制。 -->
<div class="sk-rotating-plane"></div>
</div>
<div class="sk-rotating-plane"></div>
</div>
</form>
<!-- 引入用于实现粒子效果的JavaScript库文件路径通过表达式语言获取当前页面上下文请求路径拼接而成它负责在页面中展示出粒子相关的特效为登录页面营造出独特的视觉氛围增强页面的观赏性和交互感。 -->
<script src="${pageContext.request.contextPath}/js/particles.min.js"></script>
<!-- 引入用于初始化页面相关功能可能与粒子效果以及登录页面整体功能结合相关比如初始化粒子效果的参数、绑定页面元素的一些交互事件等的JavaScript文件同样通过请求路径拼接来定位文件保障页面各项功能正常运行。 -->
<script src="${pageContext.request.contextPath}/js/app.js"></script>
<script type="text/javascript">
function check() {
// 获取用户名输入框id为“username”中的值并使用trim()方法去除前后空格,确保获取到的用户名数据干净、规范,便于后续验证和使用。
var username = $("#username").val().trim();
// 获取密码输入框id为“password”中的值同样使用trim()方法去除前后空格,得到准确的密码输入内容,准备进行密码相关的格式等验证。
var password = $("#password").val().trim();
// 判断用户名是否为空null、空字符串或者长度为0都视为空如果是这种情况就使用layer组件弹出提示信息“请输入用户帐号”并且终止后续表单提交操作通过返回false来阻止表单提交提醒用户必须输入用户名才能进行登录。
if (username == null || username == "" || username.length == 0) {
layer.msg('请输入用户帐号');
return false;
}
// 判断密码是否为空如果为空同样使用layer组件弹出提示“请输入登录密码”并终止表单提交要求用户输入密码才能继续登录流程。
if (password == null || password == "" || password.length == 0) {
layer.msg('请输入登录密码');
return false;
}
// 判断密码长度是否小于4或者大于20如果满足这个条件说明密码格式不符合要求这里限定密码长度在4 - 20位字符之间则使用layer组件弹出提示信息“密码格式有误4 - 20位字符同时终止表单提交引导用户输入符合格式规范的密码。
if (password.length < 4 || password.length > 20) {
layer.msg('密码格式有误4-20位字符');
layer.msg('密码格式有误4 - 20位字符');
return false;
}
// 如果前面的所有验证都通过用户名和密码都不为空且密码长度符合要求就提交表单通过表单对象的submit()方法将用户在表单中输入的用户名和密码等数据发送到后端的登录处理接口由表单的action属性指定的路径进行后续的登录验证操作。
document.myform.submit();
}
</script>
</body>
</html>
</html>

@ -5,32 +5,44 @@
Date: 2020/2/10
Time: 15:58
To change this template use File | Settings | File Templates.
这部分是JSP页面头部的注释说明了该文件创建时的相关信息如创建者、创建日期、时间以及提示如何修改模板等内容。
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<!doctype html>
<html>
<head>
<title>管理员端平台</title>
<!-- 引入字体相关的CSS样式文件路径通过表达式语言获取当前页面上下文请求路径拼接而成用于页面中字体的显示样式设置。 -->
<link rel="stylesheet" href="${pageContext.request.contextPath}/css/font.css">
<!-- 引入xadmin框架的CSS样式文件用于实现该框架下特定的页面布局和样式效果。 -->
<link rel="stylesheet" href="${pageContext.request.contextPath}/css/xadmin.css">
<!-- 引入特定的灰色管理员主题的CSS样式文件从文件名推测是主题相关样式用于设置页面整体的主题风格使其呈现出灰色调的管理员界面风格这是一条注释对引入的这个文件作用做了简单说明。 -->
<link rel="stylesheet" href="${pageContext.request.contextPath}/css/theme2571.min.css"><%--灰色管理员主题 --%>
<!-- 引入jQuery库的JavaScript文件这是一个常用的JavaScript库用于简化DOM操作、事件处理等功能。 -->
<script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery-3.1.1.js"></script>
<!-- 引入layui框架的JavaScript核心文件layui是一个用于构建页面交互界面的前端框架。 -->
<script src="${pageContext.request.contextPath}/lib/layui/layui.js" charset="utf-8"></script>
<!-- 引入xadmin框架的JavaScript文件用于实现该框架相关的功能和交互效果。 -->
<script type="text/javascript" src="${pageContext.request.contextPath}/js/xadmin.js"></script>
<script>
// 是否开启刷新记忆tab功能
// var is_remember = false;
// 上面这行代码定义了一个变量is_remember用于控制是否开启刷新记忆tab的功能但目前被注释掉了可能后续根据需求决定是否启用这个功能若启用则需要去掉注释并进行相应的逻辑实现。
</script>
</head>
<body class="index">
<!-- 顶部开始 -->
<div class="container">
<!-- 页面左上角的logo部分点击链接可以跳转到指定的网址这里是"http://ppdxzz.cn"),显示的文本是"皮皮的小猪仔",用于品牌展示或者作为返回首页等功能的入口(取决于具体业务逻辑)。 -->
<div class="logo">
<a href="http://ppdxzz.cn">皮皮的小猪仔</a></div>
<!-- 用于展开左侧栏的按钮部分,点击按钮(<a>标签包裹),图标(<i>标签应用特定的图标字体类,这里是"iconfont"并通过Unicode编码指定具体图标样式"&#xe699;"来显示展开图标会触发相应的展开左侧栏的操作具体操作可能在相关的JavaScript代码中实现比如显示隐藏左侧菜单的DOM元素等标题属性"展开左侧栏"用于鼠标悬停时提示用户该按钮的功能。 -->
<div class="left_open">
<a><i title="展开左侧栏" class="iconfont">&#xe699;</i></a>
</div>
<!-- 页面右上角的导航栏部分使用layui的导航组件layui-nav类lay-filter属性用于后续对导航栏进行一些筛选、事件绑定等操作虽然这里为空字符串但按照layui框架规范预留了该属性里面包含多个菜单项<li>标签表示一个菜单项)。 -->
<ul class="layui-nav right" lay-filter="">
<!-- 第一个菜单项,显示文本为"我的消息",点击后会展开二级菜单(通过<dl>和<dd>标签构建二级菜单结构),用于展示不同类型的消息相关选项。 -->
<li class="layui-nav-item">
<a href="javascript:;">我的消息</a>
<dl class="layui-nav-child">
@ -46,6 +58,7 @@
</dd>
</dl>
</li>
<!-- 第二个菜单项显示当前登录管理员的姓名通过表达式语言从会话范围获取adminInfo对象的name属性来展示点击后同样展开二级菜单提供个人信息查看、切换帐号、退出等功能选项。 -->
<li class="layui-nav-item">
<a href="javascript:;">${sessionScope.adminInfo.name}</a>
<dl class="layui-nav-child">
@ -58,6 +71,7 @@
<a href="${pageContext.request.contextPath}/loginOut">退出</a></dd>
</dl>
</li>
<!-- 第三个菜单项显示文本包含一个友情链接的图标通过layui-icon类以及特定的Unicode编码"&#xe64c;"来显示图标样式)和"友情链接"文字,点击后可跳转到指定的网址(这里是"http://ppdxzz.cn"),用于引导用户访问相关的友情链接页面。 -->
<li class="layui-nav-item to-index">
<a href="http://ppdxzz.cn"><i class="layui-icon">&#xe64c;</i>友情链接</a>
</li>
@ -69,22 +83,26 @@
<div class="left-nav">
<div id="side-nav">
<ul id="nav">
<!-- 使用JSTL的标签进行条件判断如果管理员的权限通过表达式语言从会话范围获取adminInfo对象的power属性大于2推测权限值越大权限越高大于2表示有较高权限比如超级管理员等则显示以下菜单项用于学生管理相关功能入口。 -->
<c:if test="${sessionScope.adminInfo.power > 2}">
<li>
<a href="javascript:;">
<i class="iconfont left-nav-li" lay-tips="学生管理">&#xe6b8;</i>
<cite>学生管理</cite>
<i class="iconfont nav_right">&#xe697;</i>
</a>
<ul class="sub-menu">
<li>
<a onclick="xadmin.add_tab('学生信息','${pageContext.request.contextPath}/student/findAll')">
<i class="iconfont">&#xe6a7;</i>
<cite>学生信息</cite></a>
</li>
</ul>
</li>
<li>
<a href="javascript:;">
<!-- 使用特定的图标字体类iconfont并通过Unicode编码指定图标样式"&#xe6b8;"来显示一个图标lay-tips属性用于鼠标悬停时提示用户该菜单项对应的功能是"学生管理"<cite>标签内显示菜单项的文本名称"学生管理",另一个图标("&#xe697;")可能用于表示展开收起子菜单等操作(具体由样式控制)。 -->
<i class="iconfont left-nav-li" lay-tips="学生管理">&#xe6b8;</i>
<cite>学生管理</cite>
<i class="iconfont nav_right">&#xe697;</i>
</a>
<ul class="sub-menu">
<li>
<!-- 通过调用xadmin框架提供的add_tab函数在xadmin.js中应该有定义添加一个名为"学生信息"的tab页点击该菜单项后会跳转到对应的URL通过表达式语言拼接出查找所有学生信息的接口路径"${pageContext.request.contextPath}/student/findAll"),用于展示学生信息列表等相关功能。 -->
<a onclick="xadmin.add_tab('学生信息','${pageContext.request.contextPath}/student/findAll')">
<i class="iconfont">&#xe6a7;</i>
<cite>学生信息</cite></a>
</li>
</ul>
</li>
</c:if>
<!-- 再次使用标签判断如果管理员权限等于2推测是普通管理员之类的角色则显示以下不同的学生管理相关菜单项其URL拼接了根据当前管理员姓名查找学生信息的参数可能用于普通管理员查看其负责管理的学生信息。 -->
<c:if test="${sessionScope.adminInfo.power == 2}">
<li>
<a href="javascript:;">
@ -101,25 +119,26 @@
</ul>
</li>
</c:if>
<!-- 类似前面的权限判断如果管理员权限大于2显示以下管理员管理相关的菜单项包含管理员列表查看以及权限管理目前权限管理点击调用power函数从后面定义的函数来看是提示功能暂未开放等功能入口。 -->
<c:if test="${sessionScope.adminInfo.power > 2}">
<li>
<a href="javascript:;">
<i class="iconfont left-nav-li" lay-tips="管理员管理">&#xe726;</i>
<cite>管理员管理</cite>
<i class="iconfont nav_right">&#xe697;</i></a>
<ul class="sub-menu">
<li>
<a onclick="xadmin.add_tab('管理员列表','${pageContext.request.contextPath}/findAllAdmin')">
<i class="iconfont">&#xe6a7;</i>
<cite>管理员列表</cite></a>
</li>
<li>
<a onclick="power()">
<i class="iconfont">&#xe6a7;</i>
<cite>权限管理</cite></a>
</li>
</ul>
</li>
<li>
<a href="javascript:;">
<i class="iconfont left-nav-li" lay-tips="管理员管理">&#xe726;</i>
<cite>管理员管理</cite>
<i class="iconfont nav_right">&#xe697;</i></a>
<ul class="sub-menu">
<li>
<a onclick="xadmin.add_tab('管理员列表','${pageContext.request.contextPath}/findAllAdmin')">
<i class="iconfont">&#xe6a7;</i>
<cite>管理员列表</cite></a>
</li>
<li>
<a onclick="power()">
<i class="iconfont">&#xe6a7;</i>
<cite>权限管理</cite></a>
</li>
</ul>
</li>
</c:if>
<li>
<a href="javascript:;">
@ -127,6 +146,7 @@
<cite>宿舍管理</cite>
<i class="iconfont nav_right">&#xe697;</i></a>
<ul class="sub-menu">
<!-- 根据不同的管理员权限显示不同的宿舍管理相关菜单项。如果权限大于2高权限可以查看所有宿舍列表点击后通过xadmin框架的add_tab函数添加名为"宿舍列表"的tab页并跳转到查找所有宿舍信息的接口路径。 -->
<c:if test="${sessionScope.adminInfo.power > 2}">
<li>
<a onclick="xadmin.add_tab('宿舍列表','${pageContext.request.contextPath}/dorm/findAll')">
@ -134,7 +154,8 @@
<cite>宿舍列表</cite></a>
</li>
</c:if>
<%--普通管理员只能看到自己所带宿舍的人员信息--%>
<!-- 如果权限等于2普通管理员则查看自己所带宿舍的人员信息URL中拼接了根据当前管理员的唯一标识uid查找宿舍信息的参数通过add_tab函数添加tab页来展示相关信息。 -->
<%--普通管理员只能看到自己所带宿舍的人员信息--%>
<c:if test="${sessionScope.adminInfo.power == 2}">
<li>
<a onclick="xadmin.add_tab('宿舍列表','${pageContext.request.contextPath}/dorm/byTeacher?uid=${sessionScope.adminInfo.uid}')">
@ -142,7 +163,8 @@
<cite>宿舍列表</cite></a>
</li>
</c:if>
<%--宿舍长只能看到自己所在宿舍的人员信息--%>
<!-- 如果权限等于1宿舍长则只能看到自己所在宿舍的人员信息以及宿舍信息分别通过不同的URL拼接了管理员的uid参数和add_tab函数来添加相应的tab页展示对应信息。 -->
<%--宿舍长只能看到自己所在宿舍的人员信息--%>
<c:if test="${sessionScope.adminInfo.power == 1}">
<li>
<a onclick="xadmin.add_tab('宿舍信息','${pageContext.request.contextPath}/dorm/look?uid=${sessionScope.adminInfo.uid}')">
@ -157,51 +179,52 @@
</c:if>
</ul>
</li>
<!-- 如果管理员权限大于2显示以下访客管理相关的菜单项包含访客信息查看、来访登记目前点击提示暂不支持网页端登记通过tip函数实现提示功能、访客日志查看等功能入口每个功能通过add_tab函数添加相应的tab页并跳转到对应的接口路径有的还拼接了分页等参数。 -->
<c:if test="${sessionScope.adminInfo.power > 2}">
<li>
<a href="javascript:;">
<i class="iconfont left-nav-li" lay-tips="访客管理">&#xe6f5;</i>
<cite>访客管理</cite>
<i class="iconfont nav_right">&#xe6f5;</i></a>
<ul class="sub-menu">
<li>
<a onclick="xadmin.add_tab('访客信息','${pageContext.request.contextPath}/visitor/findAll')">
<i class="iconfont">&#xe6a7;</i>
<cite>访客信息</cite>
</a>
</li>
<li>
<a onclick="tip()" href="javascript:;">
<i class="iconfont">&#xe6a7;</i>
<cite>来访登记(手机端)</cite>
</a>
</li>
<li>
<a onclick="xadmin.add_tab('访客日志','${pageContext.request.contextPath}/visitor/log?page=1&size=10')">
<i class="iconfont">&#xe6a7;</i>
<cite>访客日志</cite>
</a>
</li>
</ul>
</li>
<li>
<a href="javascript:;">
<i class="iconfont left-nav-li" lay-tips="系统统计">&#xe6ce;</i>
<cite>系统统计</cite>
<i class="iconfont nav_right">&#xe697;</i></a>
<ul class="sub-menu">
<li>
<a onclick="power()">
<i class="iconfont">&#xe6a7;</i>
<cite>曲线统计</cite></a>
</li>
<li>
<a onclick="power()">
<i class="iconfont">&#xe6a7;</i>
<cite>实时流量统计</cite></a>
</li>
</ul>
</li>
<li>
<a href="javascript:;">
<i class="iconfont left-nav-li" lay-tips="访客管理">&#xe6f5;</i>
<cite>访客管理</cite>
<i class="iconfont nav_right">&#xe6f5;</i></a>
<ul class="sub-menu">
<li>
<a onclick="xadmin.add_tab('访客信息','${pageContext.request.contextPath}/visitor/findAll')">
<i class="iconfont">&#xe6a7;</i>
<cite>访客信息</cite>
</a>
</li>
<li>
<a onclick="tip()" href="javascript:;">
<i class="iconfont">&#xe6a7;</i>
<cite>来访登记(手机端)</cite>
</a>
</li>
<li>
<a onclick="xadmin.add_tab('访客日志','${pageContext.request.contextPath}/visitor/log?page=1&size=10')">
<i class="iconfont">&#xe6a7;</i>
<cite>访客日志</cite>
</a>
</li>
</ul>
</li>
<li>
<a href="javascript:;">
<i class="iconfont left-nav-li" lay-tips="系统统计">&#xe6ce;</i>
<cite>系统统计</cite>
<i class="iconfont nav_right">&#xe697;</i></a>
<ul class="sub-menu">
<li>
<a onclick="power()">
<i class="iconfont">&#xe6a7;</i>
<cite>曲线统计</cite></a>
</li>
<li>
<a onclick="power()">
<i class="iconfont">&#xe6a7;</i>
<cite>实时流量统计</cite></a>
</li>
</ul>
</li>
</c:if>
</ul>
</div>
@ -218,6 +241,7 @@
</ul>
<div class="layui-tab-content"><%--中间的空白面板--%>
<div class="layui-tab-item layui-show o_div" >
<!-- 根据管理员权限判断如果权限大于2通过>标签引入名为"welcome.jsp"的页面,可能用于展示高权限管理员登录后的欢迎页面或者一些重要信息等内容,具体取决于"welcome.jsp"页面的实现。 -->
<c:if test="${sessionScope.adminInfo.power > 2}">
<jsp:include page="welcome.jsp"></jsp:include>
</c:if>
@ -234,13 +258,5 @@
<!-- 底部结束 -->
</body>
<script>
function tip() {
layer.msg('目前暂不支持网页端登记');
return false;
}
function power() {
layer.msg('该功能暂未开放');
return false;
}
</script>
</html>
function tip() {}
</script>

@ -4,36 +4,48 @@
Date: 2019/12/18
Time: 14:05
To change this template use File | Settings | File Templates.
这部分是HTML页面头部的注释说明了该文件创建时的相关信息如创建者、创建日期、时间以及提示如何修改模板等内容方便后续对代码来源及修改情况进行追溯。
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>欢迎页面</title>
<!-- 引入layui框架的CSS样式文件路径通过表达式语言获取当前页面上下文请求路径拼接而成layui是一个用于构建页面交互界面的前端框架这里引入的CSS文件用于设置页面基于layui框架的样式风格。 -->
<link rel="stylesheet" href="${pageContext.request.contextPath}/lib/layui/css/layui.css" />
<!-- 引入jQuery库的JavaScript文件这是一个常用的JavaScript库用于简化DOM操作、事件处理等功能方便后续编写页面的交互逻辑。 -->
<script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery-3.1.1.js"></script>
</head>
<body>
<!-- 创建一个字段集fieldset元素应用layui的相关样式类layui-elem-field和layui-field-title用于对页面中的相关内容进行分组展示设置顶部外边距为30px使其与上方元素有一定间隔内部包含一个用于显示标题的<legend>元素,这里标题为“系统时间”,用于提示该部分内容的主题。 -->
<fieldset class="layui-elem-field layui-field-title" style="margin-top: 30px;">
<legend>系统时间</legend>
</fieldset>
<!-- 创建一个引用块blockquote元素应用layui的相关样式类layui-elem-quote并设置id为“mytime”这个元素用于后续通过JavaScript代码动态显示系统时间初始时为空等待脚本填充内容。 -->
<blockquote class="layui-elem-quote" id="mytime"></blockquote>
<!-- 再次创建一个字段集元素同样应用layui的样式类设置顶部外边距为20px用于对下一部分内容进行分组内部标题为“控制面板”提示接下来展示的内容与系统控制面板相关。 -->
<fieldset class="layui-elem-field layui-field-title" style="margin-top: 20px;">
<legend>控制面板</legend>
</fieldset>
<!-- 创建一个具有内边距和背景颜色设置的<div>元素,用于作为控制面板相关内容的容器,营造出一个视觉上区分开的区域,背景颜色设置为#F2F2F2浅灰色使其更突出显示。 -->
<div style="padding: 20px; background-color: #F2F2F2;">
<!-- 创建一个layui的行元素并设置列间距为15px基于layui的网格布局系统用于在水平方向上合理排列内部的各个模块使其分布更规整。 -->
<div class="layui-row layui-col-space15">
<!-- 创建一个占6列宽度基于layui的网格系统中md尺寸中等屏幕尺寸下的布局规则的列元素用于放置一个卡片式的模块。 -->
<div class="layui-col-md6">
<div class="layui-card">
<!-- 创建卡片的头部区域应用layui的卡片头部样式类显示文本“CPU利用率”用于提示该卡片内展示的内容主题。 -->
<div class="layui-card-header">CPU利用率</div>
<div class="layui-card-body">
<!-- 在卡片的主体区域内简单显示文本“CPU利用率”这里可能后续需要进一步完善比如通过JavaScript等方式动态获取并展示实际的CPU利用率数据等内容。 -->
CPU<br/>利用率
</div>
</div>
</div>
<!-- 再次创建一个占6列宽度的列元素同样放置一个卡片式模块结构与上面类似用于展示“系统出入流量”相关信息不过目前主体区域也只是简单显示文本有待进一步完善功能来展示真实数据。 -->
<div class="layui-col-md6">
<div class="layui-card">
<div class="layui-card-header">系统出入流量</div>
@ -43,6 +55,7 @@
</div>
</div>
<!-- 又创建一个占6列宽度的列元素及对应的卡片模块用于展示某个“模块”相关信息目前显示“模块待更新”文本推测后续可能会根据业务需求完善此处比如显示模块的版本、更新提示等具体内容。 -->
<div class="layui-col-md6">
<div class="layui-card">
<div class="layui-card-header">模块</div>
@ -52,6 +65,7 @@
</div>
</div>
<!-- 最后再创建一个占6列宽度的列元素及卡片模块同样显示“模块待更新”文本结构和功能与上一个模块类似可能是多个需要展示和更新管理的模块在页面上的布局体现。 -->
<div class="layui-col-md6">
<div class="layui-card">
<div class="layui-card-header">模块</div>
@ -65,16 +79,25 @@
</div>
<script>
function showTime(){
var nowtime =new Date();
var year=nowtime.getFullYear();
var month=nowtime.getMonth()+1;
var date=nowtime.getDate();
// 创建一个Date对象用于获取当前的系统时间信息它会包含年、月、日、时、分、秒等详细时间数据。
var nowtime = new Date();
// 通过Date对象的getFullYear()方法获取当前的年份例如2024年等。
var year = nowtime.getFullYear();
// 通过Date对象的getMonth()方法获取当前的月份注意返回值是0 - 11所以需要加1才是我们日常使用的1 - 12月的表示方式。
var month = nowtime.getMonth() + 1;
// 通过Date对象的getDate()方法获取当前的日期即一个月中的第几天范围是1 - 31。
var date = nowtime.getDate();
// 通过Date对象的getHours()方法获取当前的小时数范围是0 - 23。
var h = nowtime.getHours();
// 通过Date对象的getMinutes()方法获取当前的分钟数范围是0 - 59。
var m = nowtime.getMinutes();
// 通过Date对象的getSeconds()方法获取当前的秒数范围是0 - 59。
var s = nowtime.getSeconds();
document.getElementById("mytime").innerText=year+"年"+month+"月"+date+"日"+" "+h+"时"+m+"分"+s+"秒";
// 将获取到的年、月、日、时、分、秒等时间信息组合成一个格式化后的字符串并通过DOM操作使用document.getElementById获取id为“mytime”的元素然后设置其innerText属性将这个时间字符串显示在页面上对应的引用块元素中实现动态显示系统当前时间的功能。
document.getElementById("mytime").innerText = year + "年" + month + "月" + date + "日" + " " + h + "时" + m + "分" + s + "秒";
}
setInterval("showTime()",1000);
// 使用JavaScript的setInterval函数每隔1000毫秒即1秒调用一次showTime函数从而实现每隔1秒更新一次页面上显示的系统时间达到实时显示当前时间的效果。
setInterval("showTime()", 1000);
</script>
</body>
</html>
</html>

@ -1,16 +1,63 @@
/*
* @font-faceCSS使使
* 'iconfont'
*/
@font-face {
/*
* 使'iconfont'
*/
font-family: 'iconfont';
/*
* 使CSS.eot
*.eotInternet Explorer使
*/
src: url('../fonts/iconfont.eot');
/*
* Internet ExplorerIE.eot
* ?#iefixIE'embedded-opentype'.eot
*/
src: url('../fonts/iconfont.eot?#iefix') format('embedded-opentype'),
/*
* .woff.woff广
*/
url('../fonts/iconfont.woff') format('woff'),
/*
* .ttf.ttfTrueType
*/
url('../fonts/iconfont.ttf') format('truetype'),
/*
* .svg.svgSVG使
* #iconfontSVGSVG使
*/
url('../fonts/iconfont.svg#iconfont') format('svg');
}
/*
* CSS使'iconfont'
*/
.iconfont{
font-family:"iconfont" !important;
font-size:16px;font-style:normal;
/*
* 'iconfont'!important
*/
font-family:"iconfont"!important;
/*
* 16使
*/
font-size:16px;
/*
* normal使
*/
font-style:normal;
/*
* WebKitChromeSafari齿使
*/
-webkit-font-smoothing: antialiased;
/*
* WebKit0.2
*/
-webkit-text-stroke-width: 0.2px;
/*
* MozillaFirefox使GeckoWebKit -moz-osx- 使Mac
*/
-moz-osx-font-smoothing: grayscale;
}
}

@ -2,7 +2,9 @@
/* Functional styling;
* These styles are required for noUiSlider to function.
* You don't need to change these rules to apply your design.
*/
* nouiSlider */
/* 针对.noUi-target类以及其内部所有元素设置一些交互相关的属性禁止长按弹出菜单、去除点击高亮颜色、禁止用户选择文本等操作同时设置盒模型为border-box使得元素的尺寸计算包含边框和内边距 */
.noUi-target,
.noUi-target * {
-webkit-touch-callout: none;
@ -16,10 +18,14 @@
-moz-box-sizing: border-box;
box-sizing: border-box;
}
/* 设置.noUi-target类元素一般是滑块的外层容器为相对定位并且设置文本方向从左到右ltr这符合常规的页面布局习惯 */
.noUi-target {
position: relative;
direction: ltr;
}
/* 设置.noUi-base类元素一般是滑块的基础部分比如轨道等宽度和高度都占满父容器并且设置相对定位以及较高的z-index值使其在堆叠顺序中处于较上层方便后续元素基于它进行定位注释中的“Fix 401”可能是针对某个特定问题的修复说明具体需结合相关开发背景理解 */
.noUi-base {
width: 100%;
height: 100%;
@ -27,6 +33,8 @@
z-index: 1;
/* Fix 401 */
}
/* 设置.noUi-connect类元素一般是滑块轨道上表示已选择范围的连接部分为绝对定位使其占满整个.noUi-target元素即滑块外层容器的内部空间通过设置上下左右都为0来实现 */
.noUi-connect {
position: absolute;
right: 0;
@ -34,59 +42,82 @@
left: 0;
bottom: 0;
}
/* 设置.noUi-origin类元素可能与滑块的起始位置等相关概念对应为绝对定位并且初始高度和宽度都设置为0后续可能会通过JavaScript等动态改变其尺寸和位置来实现滑块的功能逻辑 */
.noUi-origin {
position: absolute;
height: 0;
width: 0;
}
/* 设置.noUi-handle类元素即滑块的手柄部分为相对定位并且设置较高的z-index值使其在堆叠顺序中处于较上层能显示在轨道等元素之上 */
.noUi-handle {
position: relative;
z-index: 1;
}
.noUi-state-tap .noUi-connect,
.noUi-state-tap .noUi-origin {
/* 当.noUi-target元素处于点击状态.noUi-state-tap类存在时对其内部的.noUi-connect和.noUi-origin元素设置过渡效果当它们的位置属性top、right、bottom、left改变时会有平滑的过渡动画过渡时间为0.3秒 */
.noUi-state-tap.noUi-connect,
.noUi-state-tap.noUi-origin {
-webkit-transition: top 0.3s, right 0.3s, bottom 0.3s, left 0.3s;
transition: top 0.3s, right 0.3s, bottom 0.3s, left 0.3s;
}
/* 当.noUi-target元素处于拖动状态.noUi-state-drag类存在时将其内部所有元素的鼠标指针样式强制设置为继承父元素的样式这样可以确保在拖动过程中鼠标指针样式符合预期不会出现异常 */
.noUi-state-drag * {
cursor: inherit !important;
cursor: inherit!important;
}
/* Painting and performance;
* Browsers can paint handles in their own layer.
*/
* 使3D */
.noUi-base,
.noUi-handle {
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
/* Slider size and handle placement;
*/
* */
/* 当滑块为水平布局(.noUi-horizontal类存在时设置滑块的高度为18px */
.noUi-horizontal {
height: 18px;
}
.noUi-horizontal .noUi-handle {
/* 当滑块为水平布局时,对其内部的.noUi-handle类元素滑块手柄进行样式设置设置宽度、高度、水平和垂直方向的偏移量使其在滑块轨道上处于合适的位置 */
.noUi-horizontal.noUi-handle {
width: 34px;
height: 28px;
left: -17px;
top: -6px;
}
/* 当滑块为垂直布局(.noUi-vertical类存在时设置滑块的宽度为18px */
.noUi-vertical {
width: 18px;
}
.noUi-vertical .noUi-handle {
/* 当滑块为垂直布局时,对其内部的.noUi-handle类元素滑块手柄进行样式设置设置宽度、高度、水平和垂直方向的偏移量使其在滑块轨道上处于合适的位置 */
.noUi-vertical.noUi-handle {
width: 28px;
height: 34px;
left: -6px;
top: -17px;
}
/* Styling;
*/
* */
/* 设置.noUi-target类元素滑块外层容器的背景颜色、边框圆角、边框样式以及内部阴影效果使其呈现出一种特定的外观风格 */
.noUi-target {
background: #FAFAFA;
border-radius: 4px;
border: 1px solid #D3D3D3;
box-shadow: inset 0 1px 1px #F0F0F0, 0 3px 6px -5px #BBB;
}
/* 设置.noUi-connect类元素滑块轨道上表示已选择范围的连接部分的背景颜色、边框圆角以及内部阴影效果并且设置其背景颜色改变时有过渡动画过渡时间为450毫秒用于实现一些交互时的视觉效果 */
.noUi-connect {
background: #3FB8AF;
border-radius: 4px;
@ -94,14 +125,21 @@
-webkit-transition: background 450ms;
transition: background 450ms;
}
/* Handles and cursors;
*/
* */
/* 当滑块可拖动(.noUi-draggable类存在时一般是水平滑块的情况设置鼠标指针样式为左右拉伸的样式符合水平拖动操作的视觉提示 */
.noUi-draggable {
cursor: ew-resize;
}
.noUi-vertical .noUi-draggable {
/* 当滑块为垂直可拖动(.noUi-vertical类且.noUi-draggable类存在时即垂直滑块情况设置鼠标指针样式为上下拉伸的样式符合垂直拖动操作的视觉提示 */
.noUi-vertical.noUi-draggable {
cursor: ns-resize;
}
/* 设置.noUi-handle类元素滑块手柄的边框样式、边框圆角、背景颜色以及多种阴影效果使其呈现出立体、有质感的外观并且将默认鼠标指针样式设置为默认样式default */
.noUi-handle {
border: 1px solid #D9D9D9;
border-radius: 3px;
@ -109,11 +147,16 @@
cursor: default;
box-shadow: inset 0 0 1px #FFF, inset 0 1px 7px #EBEBEB, 0 3px 6px -3px #BBB;
}
/* 当.noUi-handle类元素处于激活状态.noUi-active类存在时比如正在被点击或拖动时改变其阴影效果呈现出一种不同的视觉反馈用于提示用户当前正在操作滑块手柄 */
.noUi-active {
box-shadow: inset 0 0 1px #FFF, inset 0 1px 7px #DDD, 0 3px 6px -3px #BBB;
}
/* Handle stripes;
*/
* :before:after */
/* 在.noUi-handle类元素滑块手柄的:before伪元素上设置样式创建一个竖条样式用于模拟手柄上的条纹装饰效果设置其内容为空因为只是用于装饰、显示为块状元素、设置高度、宽度、背景颜色以及位置等属性 */
.noUi-handle:before,
.noUi-handle:after {
content: "";
@ -125,69 +168,98 @@
left: 14px;
top: 6px;
}
/* 同样在.noUi-handle类元素滑块手柄的:after伪元素上设置样式创建另一个竖条样式位置与:before略有不同共同构成手柄上的条纹装饰效果 */
.noUi-handle:after {
left: 17px;
}
.noUi-vertical .noUi-handle:before,
.noUi-vertical .noUi-handle:after {
/* 当滑块为垂直布局时,对.noUi-handle类元素滑块手柄的:before和:after伪元素重新设置样式将竖条变为横条通过改变宽度和高度属性以及位置来实现以适配垂直方向的手柄外观 */
.noUi-vertical.noUi-handle:before,
.noUi-vertical.noUi-handle:after {
width: 14px;
height: 1px;
left: 6px;
top: 14px;
}
.noUi-vertical .noUi-handle:after {
/* 针对垂直布局下的.noUi-handle类元素滑块手柄的:after伪元素进一步调整其位置使其与:before伪元素配合形成合适的横条装饰效果 */
.noUi-vertical.noUi-handle:after {
top: 17px;
}
/* Disabled state;
*/
[disabled] .noUi-connect {
* */
/* 当元素处于禁用状态([disabled]选择器匹配时),对.noUi-connect类元素滑块轨道上表示已选择范围的连接部分设置背景颜色使其呈现出一种表示不可用的视觉效果 */
[disabled].noUi-connect {
background: #B8B8B8;
}
/* 当元素处于禁用状态时,对.noUi-target、.noUi-handle以及.noUi-handle类元素分别对应滑块外层容器、滑块手柄等设置鼠标指针样式为不允许操作的样式not-allowed提示用户当前滑块不可用 */
[disabled].noUi-target,
[disabled].noUi-handle,
[disabled] .noUi-handle {
[disabled].noUi-handle {
cursor: not-allowed;
}
/* Base;
*
*/
* .noUi-pipsborder-box */
.noUi-pips,
.noUi-pips * {
-moz-box-sizing: border-box;
box-sizing: border-box;
}
/* 设置.noUi-pips类元素一般是用于放置刻度标记、数值显示等内容的容器为绝对定位并且设置文字颜色 */
.noUi-pips {
position: absolute;
color: #999;
}
/* Values;
*
*/
* */
/* 设置.noUi-value类元素一般用于显示具体的数值为绝对定位并且设置文本不换行、文本水平居中对齐确保数值能正确显示在相应位置 */
.noUi-value {
position: absolute;
white-space: nowrap;
text-align: center;
}
/* 设置.noUi-value-sub类元素可能是用于显示数值的副标题、辅助信息等比如小数部分等的文字颜色和字体大小使其与主数值有一定的视觉区分 */
.noUi-value-sub {
color: #ccc;
font-size: 10px;
}
/* Markings;
*
*/
* 线 */
/* 设置.noUi-marker类元素一般是滑块上的刻度线等标记为绝对定位并且设置背景颜色用于呈现出刻度线的外观 */
.noUi-marker {
position: absolute;
background: #CCC;
}
/* 设置.noUi-marker-sub类元素可能是细分刻度线等更小的标记的背景颜色使其与普通刻度线有一定视觉区分 */
.noUi-marker-sub {
background: #AAA;
}
/* 设置.noUi-marker-large类元素可能是较大的重要刻度线等标记的背景颜色同样用于视觉区分突出显示重要刻度 */
.noUi-marker-large {
background: #AAA;
}
/* Horizontal layout;
*
*/
* */
/* 设置.noUi-pips-horizontal类元素水平布局下的刻度标记等容器的内边距、高度、垂直位置以及宽度使其在水平滑块下方合适的位置显示 */
.noUi-pips-horizontal {
padding: 10px 0;
height: 80px;
@ -195,66 +267,61 @@
left: 0;
width: 100%;
}
/* 当滑块为水平布局时,对.noUi-value类元素数值显示部分进行位置调整通过3D变换将其在水平和垂直方向上移动到合适位置使其能准确显示在对应的刻度位置上方 */
.noUi-value-horizontal {
-webkit-transform: translate3d(-50%, 50%, 0);
transform: translate3d(-50%, 50%, 0);
}
/* 当滑块为水平布局时,对.noUi-marker-horizontal类元素水平布局下的刻度线等标记进行样式设置设置其宽度、高度以及左右外边距等使其呈现出水平方向的刻度线外观 */
.noUi-marker-horizontal.noUi-marker {
margin-left: -1px;
width: 2px;
height: 5px;
}
/* 当滑块为水平布局时,对.noUi-marker-horizontal类元素水平布局下的细分刻度线等标记进行样式设置调整其高度使其与普通刻度线有一定视觉区分 */
.noUi-marker-horizontal.noUi-marker-sub {
height: 10px;
}
/* 当滑块为水平布局时,对.noUi-marker-horizontal类元素水平布局下的较大刻度线等标记进行样式设置调整其高度使其更加突出显示与其他刻度线区分开来 */
.noUi-marker-horizontal.noUi-marker-large {
height: 15px;
}
/* Vertical layout;
*
*/
* */
/* 设置.noUi-pips-vertical类元素垂直布局下的刻度标记等容器的内边距、高度、垂直和水平位置使其在垂直滑块右侧合适的位置显示 */
.noUi-pips-vertical {
padding: 0 10px;
height: 100%;
top: 0;
left: 100%;
}
/* 当滑块为垂直布局时,对.noUi-value类元素数值显示部分进行位置调整通过3D变换将其在水平和垂直方向上移动到合适位置使其能准确显示在对应的刻度位置右侧并且设置左边距使其与刻度线等有合适的间距 */
.noUi-value-vertical {
-webkit-transform: translate3d(0, 50%, 0);
transform: translate3d(0, 50%, 0);
padding-left: 25px;
}
/* 当滑块为垂直布局时,对.noUi-marker-vertical类元素垂直布局下的刻度线等标记进行样式设置设置其宽度、高度以及上下外边距等使其呈现出垂直方向的刻度线外观 */
.noUi-marker-vertical.noUi-marker {
width: 5px;
height: 2px;
margin-top: -1px;
}
/* 当滑块为垂直布局时,对.noUi-marker-vertical类元素垂直布局下的细分刻度线等标记进行样式设置调整其宽度使其与普通刻度线有一定视觉区分 */
.noUi-marker-vertical.noUi-marker-sub {
width: 10px;
}
/* 当滑块为垂直布局时,对.noUi-marker-vertical类元素垂直布局下的较大刻度线等标记进行样式设置调整其宽度使其更加突出显示与其他刻度线区分开来 */
.noUi-marker-vertical.noUi-marker-large {
width: 15px;
}
.noUi-tooltip {
display: block;
position: absolute;
border: 1px solid #D9D9D9;
border-radius: 3px;
background: #fff;
color: #000;
padding: 5px;
text-align: center;
white-space: nowrap;
}
.noUi-horizontal .noUi-tooltip {
-webkit-transform: translate(-50%, 0);
transform: translate(-50%, 0);
left: 50%;
bottom: 120%;
}
.noUi-vertical .noUi-tooltip {
-webkit-transform: translate(0, -50%);
transform: translate(0, -50%);
top: 50%;
right: 120%;
}
width: 15px;}

@ -1,64 +1,75 @@
html,body{
width:100%;
height:100%;
/* 设置html和body元素的宽度和高度都占满整个视口确保页面能铺满浏览器窗口 */
html,body{
width:100%;
height:100%;
}
/* 设置canvas元素的显示方式为块级元素并且在垂直方向上与父元素底部对齐常用于图形绘制等相关场景比如一些基于canvas的动画、特效展示等 */
canvas{
display:block;
vertical-align:bottom;
display:block;
vertical-align:bottom;
}
/* 类名为.count-particles的元素样式用于统计粒子相关的显示设置 */
/* 设置背景颜色为深黑色绝对定位指定其在页面中的位置距离顶部48px左侧0px设置宽度为80px文字颜色为特定的亮色字体大小为相对父元素的0.8em,文本左对齐,设置首行缩进,行高,底部内边距等样式,并且指定字体族以及加粗字体样式 */
.count-particles{
background: #000022;
position: absolute;
top: 48px;
left: 0;
width: 80px;
color: #13E8E9;
font-size: .8em;
text-align: left;
text-indent: 4px;
line-height: 14px;
padding-bottom: 2px;
font-family: Helvetica, Arial, sans-serif;
font-weight: bold;
background: #000022;
position: absolute;
top: 48px;
left: 0;
width: 80px;
color: #13E8E9;
font-size:.8em;
text-align: left;
text-indent: 4px;
line-height: 14px;
padding-bottom: 2px;
font-family: Helvetica, Arial, sans-serif;
font-weight: bold;
}
/* 类名为.js-count-particles的元素样式可能用于通过JavaScript动态控制的粒子计数相关元素设置字体大小为相对父元素的1.1em,相对.count-particles类中的字体大小有所增大用于突出显示等目的 */
.js-count-particles{
font-size: 1.1em;
font-size: 1.1em;
}
/* 对id为stats以及类名为count-particles的元素设置样式禁止用户选择文本内容在一些交互场景下避免用户误操作选择文本并且设置顶部和左侧的外边距为5px使其在页面中有一定的间距 */
#stats,
.count-particles{
-webkit-user-select: none;
margin-top: 5px;
margin-left: 5px;
-webkit-user-select: none;
margin-top: 5px;
margin-left: 5px;
}
/* 对id为stats的元素设置样式设置其边框右上角和左上角的圆角半径为3px右下角和左下角的圆角半径为0并且设置超出部分隐藏常用于一些需要展示特定形状且不希望内容溢出的容器元素比如统计信息展示框等 */
#stats{
border-radius: 3px 3px 0 0;
overflow: hidden;
border-radius: 3px 3px 0 0;
overflow: hidden;
}
/* 对类名为count-particles的元素设置样式设置其边框右下角和左下角的圆角半径为3px右上角和左上角的圆角半径为0与#stats元素的边框圆角设置配合可能用于形成一个完整的、有特定外观的容器样式 */
.count-particles{
border-radius: 0 0 3px 3px;
border-radius: 0 0 3px 3px;
}
/* 对id为particles-js的元素设置样式通常用于承载粒子效果的容器 */
/* 设置宽度和高度都占满父容器一般就是整个页面可视区域相对定位设置背景图片指定其在水平和垂直方向上都居中显示设置背景图片铺满整个容器根据容器大小自动缩放并且不重复显示使其作为页面的背景铺满整个页面同时让其在水平方向上自动居中通过设置左右外边距为auto实现 */
#particles-js{
width: 100%;
height: 100%;
position: relative;
background-image: url(../images/bg.jpg);
background-position: 50% 50%;
background-size: cover;
background-repeat: no-repeat;
margin-left: auto;
margin-right: auto;
width: 100%;
height: 100%;
position: relative;
background-image: url(../images/bg.jpg);
background-position: 50% 50%;
background-size: cover;
background-repeat: no-repeat;
margin-left: auto;
margin-right: auto;
}
/* 类名为sk-rotating-plane的元素样式一般用于实现旋转动画效果的元素 */
/* 初始设置为不显示display: none指定宽度和高度设置自动水平居中通过设置左右外边距为auto实现背景颜色为白色定义动画名称、持续时间以及循环播放且缓动效果为ease-in-out设置较高的z-index值使其能显示在其他元素之上绝对定位并且通过设置top和left属性以及负外边距来使其在页面中垂直和水平方向上都居中显示 */
.sk-rotating-plane {
display: none;
display: none;
width: 80px;
height: 80px;
margin: auto;
@ -72,42 +83,182 @@ canvas{
margin-left: -40px;
margin-top: -80px;
}
/* 当类名为sk-rotating-plane的元素同时具有active类时将其显示出来display: block可能通过JavaScript动态添加active类来控制其显示隐藏实现特定的交互效果 */
.sk-rotating-plane.active{display: block;}
/* 定义名为sk-rotating-plane的关键帧动画 */
/* 在动画的不同阶段0%、50%、100%设置元素的3D旋转效果通过transform属性以及不同浏览器前缀来兼容各种浏览器实现一个围绕X轴和Y轴旋转的动画效果用于呈现旋转的视觉效果 */
@keyframes sk-rotating-plane{
0% {
-webkit-transform: perspective(120px) rotateX(0deg) rotateY(0deg);
transform: perspective(120px) rotateX(0deg) rotateY(0deg);
}
50% {
-webkit-transform: perspective(120px) rotateX(-180.1deg) rotateY(0deg);
transform: perspective(120px) rotateX(-180.1deg) rotateY(0deg);
}
100% {
-webkit-transform: perspective(120px) rotateX(-180deg) rotateY(-179.9deg);
transform: perspective(120px) rotateX(-180deg) rotateY(-179.9deg);
}
0% {
-webkit-transform: perspective(120px) rotateX(0deg) rotateY(0deg);
transform: perspective(120px) rotateX(0deg) rotateY(0deg);
}
50% {
-webkit-transform: perspective(120px) rotateX(-180.1deg) rotateY(0deg);
transform: perspective(120px) rotateX(-180.1deg) rotateY(0deg);
}
100% {
-webkit-transform: perspective(120px) rotateX(-180deg) rotateY(-179.9deg);
transform: perspective(120px) rotateX(-180deg) rotateY(-179.9deg);
}
}
/* 定义名为login-small的关键帧动画 */
/* 在动画的开始0%和结束100%阶段设置元素的缩放效果通过不同浏览器前缀的transform属性来兼容各种浏览器实现从原始大小缩放到较小尺寸的动画效果可能用于登录框等元素的隐藏或缩小展示等交互场景 */
@keyframes login-small{
0%{
transform: scale(1);-moz-transform: scale(1); /* Firefox 4 */-webkit-transform: scale(1); /* Safari 和 Chrome */-o-transform: scale(1); /* Opera */-ms-transform:scale(1); /* IE 9 */
}
100%{
transform: scale(0.2);-moz-transform: scale(0.1); /* Firefox 4 */-webkit-transform: scale(0.2); /* Safari 和 Chrome */-o-transform: scale(0.1); /* Opera */-ms-transform:scale(0.1); /* IE 9 */
}
}
.login{z-index: 2;position:absolute;width: 350px;border-radius: 5px;height: 500px;background: white;box-shadow: 0px 0px 5px #333333;top: 50%;left: 50%;margin-top: -250px;margin-left: -175px;transition: all 1s;-moz-transition: all 1s; /* Firefox 4 */-webkit-transition: all 1s; /* Safari 和 Chrome */-o-transition: all 1s; /* Opera */}
.login-top{font-size: 24px;margin-top: 100px;padding-left: 40px;box-sizing: border-box;color: #333333;margin-bottom: 50px;}
.login-center{width: 100%;box-sizing: border-box;padding: 0 40px;margin-bottom: 30px;}
.login-center-img{width: 20px;height: 20px;float: left;margin-top: 5px;}
.login-center-img>img{width: 100%;}
.login-center-input{float: left;width: 230px;margin-left: 15px;height: 30px;position: relative;}
.login-center-input input{z-index: 2;transition: all 0.5s;padding-left: 10px;color: #333333;width: 100%;height: 30px;border: 0;border-bottom: 1px solid #cccccc;border-top: 1px solid #ffffff;border-left: 1px solid #ffffff;border-right: 1px solid #ffffff;box-sizing: border-box;outline: none;position: relative;}
.login-center-input input:focus{border: 1px solid dodgerblue;}
.login-center-input-text{background: white;padding: 0 5px;position: absolute;z-index: 0;opacity: 0;height: 20px;top: 50%;margin-top: -10px;font-size: 14px;left: 5px;color: dodgerblue;line-height: 20px;transition: all 0.5s;-moz-transition: all 0.5s; /* Firefox 4 */-webkit-transition: all 0.5s; /* Safari 和 Chrome */-o-transition: all 0.5s; /* Opera */}
.login-center-input input:focus~.login-center-input-text{top: 0;z-index: 3;opacity: 1;margin-top: -15px;}
.login.active{-webkit-animation: login-small 0.8s ; animation: login-small 0.8s ;animation-fill-mode:forwards;-webkit-animation-fill-mode:forwards}
.login-button{cursor: pointer;width: 250px;text-align: center;height: 40px;line-height: 40px;background-color: dodgerblue;border-radius: 5px;margin: 0 auto;margin-top: 50px;color: white;}
0%{
transform: scale(1);
-moz-transform: scale(1); /* Firefox 4 */
-webkit-transform: scale(1); /* Safari 和 Chrome */
-o-transform: scale(1); /* Opera */
-ms-transform:scale(1); /* IE 9 */
}
100%{
transform: scale(0.2);
-moz-transform: scale(0.1); /* Firefox 4 */
-webkit-transform: scale(0.2); /* Safari 和 Chrome */
-o-transform: scale(0.1); /* Opera */
-ms-transform:scale(0.1); /* IE 9 */
}
}
/* 类名为login的元素样式一般用于登录框相关的整体布局和外观设置 */
/* 设置较高的z-index值使其能显示在其他元素之上绝对定位指定宽度、边框圆角、高度以及背景颜色为白色添加阴影效果使其有立体感通过设置top和left属性以及负外边距来使其在页面中垂直和水平方向上都居中显示并且设置所有属性改变时的过渡效果用于实现一些动画过渡效果比如显示隐藏、大小改变等操作时的平滑过渡 */
.login{
z-index: 2;
position:absolute;
width: 350px;
border-radius: 5px;
height: 500px;
background: white;
box-shadow: 0px 0px 5px #333333;
top: 50%;
left: 50%;
margin-top: -250px;
margin-left: -175px;
transition: all 1s;
-moz-transition: all 1s; /* Firefox 4 */
-webkit-transition: all 1s; /* Safari 和 Chrome */
-o-transition: all 1s; /* Opera */
}
/* 类名为login-top的元素样式一般是登录框顶部区域比如用于显示登录标题等内容 */
/* 设置字体大小、顶部外边距、文本左对齐时的左侧内边距,指定文字颜色以及底部外边距,用于调整其在登录框内的布局和外观显示 */
.login-top{
font-size: 24px;
margin-top: 100px;
padding-left: 40px;
box-sizing: border-box;
color: #333333;
margin-bottom: 50px;
}
/* 类名为login-center的元素样式一般是登录框中间部分用于放置输入框等登录相关的表单元素 */
/* 设置宽度占满父容器设置盒模型为border-box尺寸计算包含边框和内边距设置左右内边距并且设置底部外边距用于调整其内部元素的布局和整体在登录框中的位置 */
.login-center{
width: 100%;
box-sizing: border-box;
padding: 0 40px;
margin-bottom: 30px;
}
/* 类名为login-center-img的元素样式一般用于登录框中输入框左侧的图标等图片元素 */
/* 设置宽度、高度,使其向左浮动,并且设置顶部外边距,用于调整其在登录框中输入框左侧的位置和显示效果 */
.login-center-img{
width: 20px;
height: 20px;
float: left;
margin-top: 5px;
}
/* 类名为login-center-img内部的img元素样式设置图片宽度占满父元素即.login-center-img元素确保图片能正确显示 */
.login-center-img>img{
width: 100%;
}
/* 类名为login-center-input的元素样式一般是登录框中输入框相关的外层容器样式 */
/* 设置向左浮动,指定宽度、左侧外边距以及高度,并且设置相对定位,方便内部输入框等元素进行相对定位布局 */
.login-center-input{
float: left;
width: 230px;
margin-left: 15px;
height: 30px;
position: relative;
}
/* 类名为login-center-input内部的input元素样式一般就是实际的输入框样式 */
/* 设置较高的z-index值使其能显示在一些提示文字等元素之上设置所有属性改变时的过渡效果设置文本输入的内边距、文字颜色、宽度、高度以及边框样式只保留底部边框其他边框设置为透明去除默认的轮廓线outline: none并且设置相对定位方便与其他相关元素如提示文字进行交互布局 */
.login-center-input input{
z-index: 2;
transition: all 0.5s;
padding-left: 10px;
color: #333333;
width: 100%;
height: 30px;
border: 0;
border-bottom: 1px solid #cccccc;
border-top: 1px solid #ffffff;
border-left: 1px solid #ffffff;
border-right: 1px solid #ffffff;
box-sizing: border-box;
outline: none;
position: relative;
}
/* 当类名为login-center-input内部的input元素获取焦点时:focus伪类改变其边框样式为实线且颜色为特定的亮色dodgerblue用于提示用户当前输入框处于激活状态 */
.login-center-input input:focus{
border: 1px solid dodgerblue;
}
/* 类名为login-center-input-text的元素样式一般用于登录框中输入框的提示文字相关样式 */
/* 设置背景颜色为白色设置内边距绝对定位初始透明度为0隐藏状态设置高度、垂直方向上的位置通过top和margin-top属性使其垂直居中指定字体大小、文字颜色以及行高并且设置所有属性改变时的过渡效果用于实现提示文字在输入框获取焦点等情况下的显示隐藏动画效果 */
.login-center-input-text{
background: white;
padding: 0 5px;
position: absolute;
z-index: 0;
opacity: 0;
height: 20px;
top: 50%;
margin-top: -10px;
font-size: 14px;
left: 5px;
color: dodgerblue;
line-height: 20px;
transition: all 0.5s;
-moz-transition: all 0.5s; /* Firefox 4 */
-webkit-transition: all 0.5s; /* Safari 和 Chrome */
-o-transition: all 0.5s; /* Opera */
}
/* 当类名为login-center-input内部的input元素获取焦点时对其同级的.login-center-input-text元素进行样式改变使其向上移动到输入框顶部提高z-index值显示在输入框上方并且设置透明度为1完全显示通过调整外边距使其垂直位置更合适用于实现输入框获取焦点时提示文字上移显示的交互效果 */
.login-center-input input:focus~.login-center-input-text{
top: 0;
z-index: 3;
opacity: 1;
margin-top: -15px;
}
/* 当类名为login的元素具有active类时应用名为login-small的动画效果并且设置动画结束后保持最后一帧的状态animation-fill-mode:forwards以及-webkit-animation-fill-mode:forwards可能用于实现登录框缩小隐藏等特定交互效果 */
.login.active{
-webkit-animation: login-small 0.8s ;
animation: login-small 0.8s ;
animation-fill-mode:forwards;
-webkit-animation-fill-mode:forwards;
}
/* 类名为login-button的元素样式一般用于登录框中的登录按钮样式 */
/* 设置鼠标指针样式为指针形状cursor: pointer指定宽度、文本水平居中对齐、高度以及行高设置背景颜色为特定的亮色设置边框圆角并且设置自动水平居中通过设置左右外边距为auto实现指定文字颜色为白色用于呈现出一个美观的登录按钮外观 */
.login-button{
cursor: pointer;
width: 250px;
text-align: center;
height: 40px;
line-height: 40px;
background-color: dodgerblue;
border-radius: 5px;
margin: 0 auto;
margin-top: 50px;
color: white;
}

@ -1,63 +1,97 @@
/*
* minimobile.js v0.0.1 by chenyaowen
* 在保留作者签名的情况下允许使用与商业用途
* 该文件是一个用于移动端页面布局相关功能的JavaScript代码库包含了一些处理页面缩放适配以及常见UI组件功能的代码例如处理viewport设置侧栏显示隐藏返回顶部功能进度条展示等
*/
if(!window.Zepto && !window.jQuery){
// 检查页面是否引入了Zepto.js或者jQuery.js如果都没引入则在控制台输出提示信息因为后续代码依赖这两个库之一。
if (!window.Zepto &&!window.jQuery) {
console.log("minimobile 是基于Zepto.js 或者 jQuery.js 的请检查页面是否已在miniMobile之前引入")
}
;(function(win, lib) {
//摘自淘宝移动端
}
// 立即执行函数用于创建一个局部作用域避免全局变量污染同时接收window对象和一个名为lib的对象如果不存在则创建一个空对象作为参数在函数内部进行相关页面适配等功能的实现。
;(function (win, lib) {
// 获取当前页面的document对象后续会用于操作页面元素、获取页面相关属性等操作。
var doc = win.document;
// 获取页面根元素(<html>元素),很多页面样式和布局相关的设置会基于这个元素来操作,例如设置页面字体大小等属性。
var docEl = doc.documentElement;
// 通过选择器查找页面中name属性为"viewport"的meta标签viewport元标签常用于控制页面在移动端的缩放、布局等显示相关设置。
var metaEl = doc.querySelector('meta[name="viewport"]');
// 通过选择器查找页面中name属性为"flexible"的meta标签从代码逻辑看用于获取一些和页面缩放比例相关的自定义配置信息。
var flexibleEl = doc.querySelector('meta[name="flexible"]');
// 用于存储设备像素比devicePixelRatio相关的缩放因子初始化为0后续会根据不同情况计算并赋值。
var dpr = 0;
// 用于存储页面的缩放比例初始化为0会根据meta标签内容或者设备类型等情况来确定具体值。
var scale = 0;
// 用于存储定时器的标识在处理页面resize和pageshow等事件时通过定时器来延迟执行一些操作避免频繁触发导致性能问题初始化为null或未定义取决于JavaScript环境
var tid;
// 创建一个名为flexible的对象用于存储页面适配相关的一些属性和方法如果外部传入的lib对象中已经存在flexible属性则使用传入的否则创建一个新的空对象赋值给lib.flexible。
var flexible = lib.flexible || (lib.flexible = {});
var designPixel = 750;//设计稿件尺寸
if (metaEl) {
console.warn('将根据已有的meta标签来设置缩放比例');
// 定义设计稿件的尺寸单位可能是像素这里设定为750用于后续根据页面实际宽度计算缩放比例等相关操作使页面在不同设备上能按比例适配显示。
var designPixel = 750;
// 如果页面中存在name为"viewport"的meta标签则根据其content属性内容来获取初始缩放比例并计算出对应的设备像素比dpr
if (metaEl) {
console.warn('将根据已有的meta标签来设置缩放比例');
// 通过正则表达式匹配获取content属性中initial-scale的值该值表示页面初始缩放比例。
var match = metaEl.getAttribute('content').match(/initial\-scale=([\d\.]+)/);
if (match) {
// 将匹配到的初始缩放比例字符串转换为浮点数赋值给scale变量。
scale = parseFloat(match[1]);
// 根据缩放比例计算设备像素比设备像素比是物理像素与逻辑像素的比例关系例如scale为0.5则dpr为2表示物理像素是逻辑像素的2倍。
dpr = parseInt(1 / scale);
}
} else if (flexibleEl) {
// 获取name为"flexible"的meta标签的content属性内容用于进一步解析获取相关缩放比例配置信息。
var content = flexibleEl.getAttribute('content');
if (content) {
// 通过正则表达式匹配尝试获取content属性中initial-dpr的值用于设置设备像素比dpr
var initialDpr = content.match(/initial\-dpr=([\d\.]+)/);
// 通过正则表达式匹配尝试获取content属性中maximum-dpr的值同样用于设置设备像素比dpr可能会覆盖前面initialDpr的设置取决于具体匹配情况。
var maximumDpr = content.match(/maximum\-dpr=([\d\.]+)/);
if (initialDpr) {
// 将匹配到的initial-dpr的值转换为浮点数赋值给dpr变量用于设置设备像素比。
dpr = parseFloat(initialDpr[1]);
scale = parseFloat((1 / dpr).toFixed(2));
// 根据设备像素比计算缩放比例并保留两位小数赋值给scale变量。
scale = parseFloat((1 / dpr).toFixed(2));
}
if (maximumDpr) {
// 同理如果匹配到了maximum-dpr的值更新设备像素比dpr和缩放比例scale
dpr = parseFloat(maximumDpr[1]);
scale = parseFloat((1 / dpr).toFixed(2));
scale = parseFloat((1 / dpr).toFixed(2));
}
}
}
if (!dpr && !scale) {
// 如果经过前面的步骤都没有确定dpr和scale的值即都为0则根据设备类型是iPhone还是其他安卓设备等来设置默认的设备像素比dpr和缩放比例scale
if (!dpr &&!scale) {
// 通过正则表达式判断当前设备是否为安卓系统。
var isAndroid = win.navigator.appVersion.match(/android/gi);
// 通过正则表达式判断当前设备是否为iPhone。
var isIPhone = win.navigator.appVersion.match(/iphone/gi);
// 获取当前设备的设备像素比,即物理像素与逻辑像素的实际比例关系。
var devicePixelRatio = win.devicePixelRatio;
if (isIPhone) {
if (devicePixelRatio >= 3 && (!dpr || dpr >= 3)) {
if (isIPhone) {
// 如果是iPhone设备根据设备像素比来设置合适的设备像素比dpr例如设备像素比大于等于3且之前未设置或设置的dpr大于等于3则设置dpr为3以此类推。
if (devicePixelRatio >= 3 && (!dpr || dpr >= 3)) {
dpr = 3;
} else if (devicePixelRatio >= 2 && (!dpr || dpr >= 2)){
} else if (devicePixelRatio >= 2 && (!dpr || dpr >= 2)) {
dpr = 2;
} else {
dpr = 1;
}
} else {
} else {
// 如果不是iPhone设备一般为安卓等其他设备默认设置设备像素比dpr为1。
dpr = 1;
}
// 根据设备像素比dpr计算缩放比例scale两者互为倒数关系。
scale = 1 / dpr;
}
// 将计算得到的设备像素比dpr设置为页面根元素<html>元素的data-dpr属性值方便在CSS等地方通过属性选择器等方式根据不同的设备像素比来应用不同的样式规则。
docEl.setAttribute('data-dpr', dpr);
// 如果页面中不存在name为"viewport"的meta标签则动态创建一个这样的meta标签并设置其content属性用于控制页面的缩放、用户缩放是否可用等显示相关设置然后将其添加到页面中合适的位置一般是<head>标签内)。
if (!metaEl) {
metaEl = doc.createElement('meta');
metaEl.setAttribute('name', 'viewport');
@ -71,46 +105,65 @@
}
}
function refreshRem(){
// 定义一个用于刷新页面根元素字体大小rem单位的函数根据页面宽度、设计稿件尺寸以及设备像素比等信息来动态计算并设置根元素的字体大小实现页面的自适应布局效果。
function refreshRem() {
// 获取页面根元素(<html>元素的可视宽度不包含滚动条等占据的宽度单位为像素后续会基于这个宽度来计算rem值。
var width = docEl.getBoundingClientRect().width;
if (width / dpr > designPixel) { //如果分辨率不是1那么获取的物理宽度应该乘以分辨率才是最终可用的width
// 如果设备像素比dpr不为1说明物理像素和逻辑像素不一致那么需要将获取到的物理宽度乘以设备像素比得到真正用于计算rem的可用宽度这样能保证在不同分辨率设备上布局的准确性。
if (width / dpr > designPixel) {
width = width * dpr;
}
var rem = width / (designPixel/100); //计算最终还原到设计图上的比例,从而设置到文档上
// 根据设计稿件尺寸designPixel和当前页面可用宽度width计算rem值这里是将页面宽度按照设计稿件尺寸等比例缩放例如设计稿件宽度是750px页面当前宽度是375px则rem值会相应变小实现页面元素按比例缩放显示。
var rem = width / (designPixel / 100);
// 将计算得到的rem值设置为页面根元素<html>元素的字体大小单位为px通过设置根元素字体大小为rem单位页面中使用rem单位的元素尺寸等会根据根元素字体大小动态变化从而实现自适应布局。
docEl.style.fontSize = rem + 'px';
// 将计算得到的rem值存储到flexible对象和全局的win对象即window对象方便其他地方可以访问和使用这个rem值例如用于将px单位转换为rem单位等操作。
flexible.rem = win.rem = rem;
}
win.addEventListener('resize', function() {
// 监听页面的resize事件当页面大小发生改变时触发当触发该事件时先清除之前可能存在的定时器避免重复执行或频繁执行刷新rem的操作然后设置一个新的定时器延迟300毫秒后调用refreshRem函数来重新计算并更新页面根元素的字体大小实现页面在大小改变后的自适应布局调整。
win.addEventListener('resize', function () {
clearTimeout(tid);
tid = setTimeout(refreshRem, 300);
}, false);
win.addEventListener('pageshow', function(e) {
// 监听页面的pageshow事件当页面显示时触发比如浏览器前进、后退等操作导致页面重新显示时如果页面是从缓存中加载显示通过e.persisted判断同样先清除之前的定时器再设置新定时器延迟300毫秒调用refreshRem函数来更新页面布局确保页面在各种显示场景下都能正确自适应。
win.addEventListener('pageshow', function (e) {
if (e.persisted) {
clearTimeout(tid);
tid = setTimeout(refreshRem, 300);
}
}, false);
// 如果页面已经加载完成document.readyState为'complete'则直接设置页面body元素的字体大小为16乘以设备像素比dpr的像素值这是一种基础的字体大小设置通常配合rem单位的自适应布局使用确保文字显示大小合适。
if (doc.readyState === 'complete') {
doc.body.style.fontSize = 16 * dpr + 'px';
} else {
doc.addEventListener('DOMContentLoaded', function(e) {
// 如果页面还未加载完成则监听DOMContentLoaded事件当页面DOM结构加载完成但可能资源如图片等还未完全加载时触发在该事件触发时设置页面body元素的字体大小同样为16乘以设备像素比dpr的像素值。
doc.addEventListener('DOMContentLoaded', function (e) {
doc.body.style.fontSize = 16 * dpr + 'px';
}, false);
}
// 首次加载页面时调用refreshRem函数初始化页面根元素的字体大小确保页面一开始就能以正确的自适应布局显示。
refreshRem();
// 将计算得到的设备像素比dpr存储到flexible对象和全局的win对象即window对象方便其他地方获取和使用设备像素比信息例如在处理高清图片显示等场景下可能会用到。
flexible.dpr = win.dpr = dpr;
// 将refreshRem函数存储到flexible对象上方便外部可以手动调用该函数来刷新页面的rem值实现手动触发页面自适应布局调整例如在某些动态改变页面布局结构的情况下可以使用。
flexible.refreshRem = refreshRem;
flexible.rem2px = function(d) {
// 定义一个方法用于将rem单位的数值转换为px单位的数值接收一个参数d可以是数字或者以rem结尾的字符串先将其转换为浮点数然后乘以当前的rem值通过this.rem获取this指向flexible对象如果传入的参数是字符串且以rem结尾则在返回结果后面加上'px'单位,方便在样式设置等场景下直接使用。
flexible.rem2px = function (d) {
var val = parseFloat(d) * this.rem;
if (typeof d === 'string' && d.match(/rem$/)) {
val += 'px';
}
return val;
}
flexible.px2rem = function(d) {
// 定义一个方法用于将px单位的数值转换为rem单位的数值接收一个参数d可以是数字或者以px结尾的字符串先将其转换为浮点数然后除以当前的rem值通过this.rem获取this指向flexible对象如果传入的参数是字符串且以px结尾则在返回结果后面加上'rem'单位方便在样式设置等场景下直接使用例如在根据设计稿尺寸计算元素的rem单位尺寸时会用到。
flexible.px2rem = function (d) {
var val = parseFloat(d) / this.rem;
if (typeof d === 'string' && d.match(/px$/)) {
val += 'rem';
@ -119,114 +172,40 @@
}
})(window, window['lib'] || (window['lib'] = {}));
/*
* asideUi 侧栏
* 以下代码定义了一个名为asideUi的jQuery或Zepto插件取决于页面引入的是哪个库用于创建一个具有特定交互效果的侧边栏组件例如可以通过点击切换侧边栏的显示隐藏状态并且可以配置一些属性如大小是否显示遮罩位置以及动画过渡时间等
*/
;
(function($) {
$.fn.asideUi = function(options) {
var defaults = {
size: '100%',
hasmask: true,
position: 'left',
sidertime: 300
};
var val = $.extend(defaults, options);
var obj = function() {},
_self = this,
thisMask = $("<div class='ui-aside-mask'></div>"),
thisCss = {},
thisCss2 = {};
thisCss[val.position] = '-' + val.size;
this.css({
'top': (val.position == "bottom") ? "auto" : 0,
'bottom': 0
});
thisCss2[val.position] = 0;
_self.css(thisCss);
obj.toggle = function() {
if(_self.hasClass('ui-aside-open')) {
_self.removeClass('ui-aside-open');
_self.animate(thisCss, val.sidertime);
$('.ui-aside-mask').animate({
'opacity': 0
}, 100, function() {
$(this).remove();
});
} else {
_self.addClass('ui-aside-open');
_self.animate(thisCss2, val.sidertime);
if(val.hasmask) {
$('body').append(thisMask);
$(".ui-aside-mask").animate({
'opacity': 1
}, 100);
}
}
}
thisMask.tap(function() {
obj.toggle();
})
return obj;
};
})(window.Zepto || window.jQuery)
/*
* 返回顶部
*/
function goTop(acceleration, time) {
acceleration = acceleration || 0.1;
time = time || 16;
var x1 = 0;
var y1 = 0;
var x2 = 0;
var y2 = 0;
var x3 = 0;
var y3 = 0;
if(document.documentElement) {
x1 = document.documentElement.scrollLeft || 0;
y1 = document.documentElement.scrollTop || 0;
}
if(document.body) {
x2 = document.body.scrollLeft || 0;
y2 = document.body.scrollTop || 0;
}
var x3 = window.scrollX || 0;
var y3 = window.scrollY || 0;
// 滚动条到页面顶部的水平距离
var x = Math.max(x1, Math.max(x2, x3));
// 滚动条到页面顶部的垂直距离
var y = Math.max(y1, Math.max(y2, y3));
// 滚动距离 = 目前距离 / 速度, 因为距离原来越小, 速度是大于 1 的数, 所以滚动距离会越来越小
var speed = 1 + acceleration;
window.scrollTo(Math.floor(x / speed), Math.floor(y / speed));
// 如果距离不为零, 继续调用迭代本函数
if(x > 0 || y > 0) {
var invokeFunction = "goTop(" + acceleration + ", " + time + ")";
window.setTimeout(invokeFunction, time);
}
}
(function ($) {
// 通过$.fn向jQuery或Zepto的原型对象上添加一个名为asideUi的方法这样就可以在选择器选中的元素上调用该方法来创建侧边栏组件实例接收一个options参数用于传入配置选项。
$.fn.asideUi = function (options) {
// 定义默认的配置选项对象,包含侧边栏的大小(默认为'100%'可以是具体的宽度值或者百分比等、是否显示遮罩默认为true、显示位置默认为'left',还可以是'right'、'bottom'等以及侧边栏展开收起的动画过渡时间默认为300毫秒
var defaults = {
size: '100%',
hasmask: true,
position: 'left',
sidertime: 300
};
// 使用$.extend方法将传入的options参数与默认的配置选项defaults进行合并返回合并后的配置对象这样既可以使用默认配置又可以通过传入的参数覆盖部分默认配置。
var val = $.extend(defaults, options);
// 创建一个空的函数对象,后续会在这个对象上添加一些方法用于操作侧边栏的显示隐藏等功能,目前只是一个占位,方便代码组织和扩展。
var obj = function () { };
// 将当前调用asideUi方法的jQuery或Zepto对象即选中的元素集合赋值给_self变量方便在后续代码中引用例如设置选中元素的样式、添加移除类名等操作。
var _self = this;
// 创建一个用于作为侧边栏遮罩层的<div>元素,添加一个名为'ui-aside-mask'的类名后续可以通过CSS样式来设置其外观如透明度、背景色等以及交互效果如点击隐藏侧边栏等
var thisMask = $("<div class='ui-aside-mask'></div>");
// 创建一个空对象thisCss用于存储侧边栏的初始样式设置主要是控制侧边栏的显示位置和隐藏状态相关样式后续会根据配置的侧边栏位置等信息来设置具体的样式属性。
var thisCss = {};
// 创建另一个空对象thisCss2用于存储侧边栏展开后的样式设置同样是控制侧边栏的位置相关样式与thisCss相对应用于在侧边栏切换显示隐藏时应用不同的样式实现动画过渡效果。
var thisCss2 = {};
/*
* ui-progress进度条
*/
;
(function($) {
$.fn.progressUi = function(options) {
var defaults = {
skin: ''
};
var val = $.extend(defaults, options);
var attrs = {
max: this.attr('max') || 0,
value: this.attr("value") || 0
},
doms = $('<div class="ui-progressBox"></div>');
domsContent = $('<div class="progress-content ' + val.skin + '"></div>');
this.wrap(doms);
domsContent.animate({
'width': attrs.value / attrs.max * 100 + '%',
});
doms.prepend(domsContent);
};
})(window.Zepto || window.jQuery)
// 根据配置的侧边栏位置val.position设置侧边栏的初始位置样式例如如果位置是'left'则将其left属性设置为负的侧边栏大小val.size实现将侧边栏隐藏在屏幕左侧的效果通过CSS的left属性负值来隐藏元素其他位置同理。
thisCss[val.position] = '-' + val.size;
// 设置侧边栏的top和bottom属性根据侧边栏的显示位置val.position来决定top属性是否自动如果是'bottom'位置则top为'auto'其他位置top为0同时设置bottom属性为0用于控制侧边栏在垂直方向上的定位。
this.css({
'top': (val.position == "bottom")? "auto" : 0,
'bottom': 0
});}})
// 根据

@ -1,19 +1,33 @@
(function() {
// 立即执行函数,用于创建一个局部作用域,避免全局变量污染,在这个函数内部定义了一个基础的类继承机制以及一些与表单验证相关的功能代码。
(function () {
/**
* 所有类的基类提供继承机制
* 这里通过一些巧妙的代码逻辑实现了一个简单的类继承模式允许创建类并能方便地继承其他类的属性和方法同时处理了在子类中调用父类同名方法的情况通过 _super 机制
*/
var initializing = false, fnTest = /xyz/.test(function() {xyz;}) ? /\b_super\b/ : /.*/;
this.Class = function() {};
Class.extend = function(prop) {
// 用于检测当前JavaScript环境是否支持在函数内部通过名字访问函数自身的代码用于判断是否是严格模式等情况根据检测结果确定后续用于检测函数中是否包含 _super 关键字的正则表达式。
var initializing = false, fnTest = /xyz/.test(function () { xyz; })? /\b_super\b/ : /.*/;
// 创建一个名为 Class 的全局函数在严格模式下这里的this指向全局对象非严格模式下指向调用者的上下文对象一般在浏览器环境下是 window 对象),这个函数后续作为创建类的构造函数,初始时它只是一个空函数,后续会通过扩展功能来完善类的创建逻辑。
this.Class = function () { };
// 为 Class 函数添加一个 extend 方法用于实现类的继承功能通过传入一个包含属性和方法的对象prop来定义子类要扩展或重写的内容。
Class.extend = function (prop) {
// 获取当前类(调用 extend 方法的类)的原型对象,也就是父类的原型,后续用于在子类中访问父类的方法等操作,实现继承关系中的方法复用和重写逻辑。
var _super = this.prototype;
// 设置 initializing 为 true表示正在初始化一个新的类在继承过程中创建子类的原型对象阶段用于后续在构造函数中判断是否是初始化阶段避免一些不必要的操作比如重复调用初始化方法等
initializing = true;
// 通过使用 new 操作符调用当前类this 指向调用 extend 的类,也就是父类)的构造函数来创建一个新的对象,这个对象将作为子类的原型对象,它会继承父类原型上的属性和方法。
var prototype = new this();
// 完成子类原型对象的创建后,将 initializing 重新设置为 false表示初始化阶段结束。
initializing = false;
for ( var name in prop) {
prototype[name] = typeof prop[name] == "function"
&& typeof _super[name] == "function" && fnTest.test(prop[name]) ?
(function(name, fn) {
return function() {
// 遍历传入的属性对象prop中的每个属性一般是方法或新定义的属性进行相应的处理判断是普通属性赋值还是函数属性的特殊处理涉及到父类同名函数的调用情况
for (var name in prop) {
// 判断当前属性prop[name]是否是函数类型并且父类原型上是否存在同名的函数属性_super[name]),同时还要检测该函数的代码中是否包含 _super 关键字(通过 fnTest 正则表达式判断),如果满足这些条件,则进行特殊的函数包装处理,用于实现子类中调用父类同名函数的功能。
prototype[name] = typeof prop[name] == "function"
&& typeof _super[name] == "function" && fnTest.test(prop[name])?
// 如果满足上述条件,返回一个新的函数,这个函数内部实现了先临时保存当前对象的 _super 属性(可能是之前保存的父类同名函数引用),然后将 _super 属性指向父类的同名函数,接着调用传入的函数(也就是子类重写的函数),在调用完成后恢复 _super 属性的原始值,最后返回函数执行的结果,这样就巧妙地实现了在子类函数中通过 this._super 调用父类同名函数的功能。
(function (name, fn) {
return function () {
var tmp = this._super;
this._super = _super[name];
@ -25,155 +39,177 @@
};
})(name, prop[name]) : prop[name];
}
// 创建一个新的函数(作为子类的构造函数),在这个构造函数中,如果当前不是处于初始化阶段(即不是在创建子类原型对象过程中),并且子类定义了 init 方法(一般用于初始化操作),则调用子类的 init 方法,并传入相应的参数,实现子类实例化时的初始化逻辑。
function Class() {
if (!initializing && this.init)
this.init.apply(this, arguments);
}
// 将前面创建并处理好的原型对象prototype赋值给新创建的子类构造函数Class的原型属性这样通过这个构造函数创建的实例就能继承原型对象上的属性和方法了。
Class.prototype = prototype;
// 修复子类构造函数的 constructor 属性,将其指向正确的子类构造函数本身,确保在使用 instanceof 等操作时能正确识别对象的构造函数类型。
Class.prototype.constructor = Class;
// 将 extend 方法也添加到子类的构造函数上,使得子类也能继续通过调用 extend 方法来实现进一步的继承,形成继承链,这里通过 arguments.callee 引用当前的 extend 函数本身来实现这个功能不过在严格模式下arguments.callee 是不允许使用的,代码可能需要调整)。
Class.extend = arguments.callee;
// 返回创建好的子类构造函数,外部可以通过调用这个构造函数来创建子类的实例对象,完成类的继承和实例化操作。
return Class;
};
})();
// 使用前面定义的 Class 类及继承机制创建一个名为 validate 的类,它继承自 Class主要用于实现表单验证相关的功能比如验证表单字段是否符合特定的规则、显示错误提示等。
var validate = Class
.extend({
defaultCfg:{
rules:{},
submitFun:function(){},
errorLabel:'<label style="color:red"></label>',
errorFun:function(){}
},
init:function(cfg){
this.cfg = $.extend({},this.defaultCfg,cfg);
this.flag=0;
this.toAction(this);
if(this.flag==0){
for(var i in this.cfg.rules){
$("#"+i).unbind("keyup");
}
this.cfg.submitFun();
.extend({
// 默认配置对象包含了验证相关的各种默认设置如验证规则rules、提交表单时执行的函数submitFun、用于显示错误信息的HTML标签模板errorLabel以及出现错误时执行的函数errorFun等属性。
defaultCfg: {
rules: {},
submitFun: function () { },
errorLabel: '<label style="color:red"></label>',
errorFun: function () { }
},
// 初始化方法,在创建 validate 类的实例时会被调用(如果不是处于类继承的初始化阶段,也就是 new 操作实例化时会执行),用于初始化验证相关的配置信息以及绑定一些事件处理等操作。
init: function (cfg) {
// 使用 jQuery 的 extend 方法将传入的配置对象cfg与默认配置对象defaultCfg进行合并得到最终的配置对象并赋值给 this.cfg这样既可以使用默认配置又能通过传入的参数覆盖部分默认配置。
this.cfg = $.extend({}, this.defaultCfg, cfg);
// 初始化一个标志变量flag为0用于记录表单验证过程中是否出现错误等情况后续根据这个标志来决定是否执行提交表单等操作。
this.flag = 0;
// 调用 toAction 方法并传入当前实例对象this开始进行表单验证相关的操作比如遍历验证规则并对相应的表单字段进行验证。
this.toAction(this);
// 如果验证过程中没有出现错误flag 仍然为0则解除表单字段的 keyup 事件绑定可能是之前绑定的用于实时验证的事件这里在全部验证通过后解除避免重复验证等不必要的操作然后执行提交表单的函数submitFun提交表单数据等操作具体由这个函数的实现决定
if (this.flag == 0) {
for (var i in this.cfg.rules) {
$("#" + i).unbind("keyup");
}
},
toAction:function(that){
for(var i in that.cfg.rules){
this.toVal("#"+i,that.cfg.rules[i]);
}
},
toVal:function(ele,constant){
validateConstant[constant].test($(ele).val())?
this.toRemoveError(ele):this.toShowError(ele,errorMsg[constant]);
this.cfg.submitFun();
}
},
// 用于执行表单验证的主要方法接收一个表示当前验证实例的对象that在这个方法内部会遍历配置的验证规则并针对每个规则调用 toVal 方法对相应的表单字段进行验证操作。
toAction: function (that) {
for (var i in that.cfg.rules) {
this.toVal("#" + i, that.cfg.rules[i]);
}
},
// 具体验证单个表单字段的方法接收一个表单字段的选择器ele一般是类似 "#inputId" 的形式表示通过ID选择元素以及对应的验证规则常量constant用于确定使用哪种验证规则来验证该字段根据验证结果调用相应的方法来显示或移除错误提示信息。
toVal: function (ele, constant) {
// 调用 validateConstant 对象中对应的验证规则函数(通过 constant 作为键来查找),传入表单字段的值(通过 jQuery 获取元素的值)进行验证,如果验证通过(返回 true则调用 toRemoveError 方法移除该字段的错误提示信息,否则调用 toShowError 方法显示相应的错误提示信息(传入错误提示消息,通过 errorMsg 对象根据验证规则常量获取)。
validateConstant[constant].test($(ele).val())?
this.toRemoveError(ele) : this.toShowError(ele, errorMsg[constant]);
},
toRemoveError:function(ele){
var that = this;
if($(ele).closest(".form-group").attr("not-allow")){
$(ele).removeAttr("style").closest(".form-group").removeAttr("style")
.removeAttr("not-allow");
$(ele).next().remove();
$(ele).keyup(function(){
ele = ele.replace("#","");
that.toVal("#"+ele,that.cfg.rules[ele]);
});
}
},
toShowError:function(ele,message){
var error = $(this.cfg.errorLabel).text(message);
if(!$(ele).closest(".form-group").attr("not-allow")){
$(ele).after(error);
$(ele).css("border","1px solid red").closest(".form-group")
.css("color","red").attr("not-allow","true");
$(ele).keyup(function(){
ele = ele.replace("#","");
that.toVal("#"+ele,that.cfg.rules[ele]);
});
}
this.flag++;
var that = this;
},
// 用于移除表单字段错误提示信息的方法接收一个表单字段的选择器ele首先获取当前验证实例对象通过 this 赋值给 that 变量),然后判断该字段所在的表单组元素(通过 closest 方法查找父级的.form-group 元素)是否有 "not-allow" 属性,如果有则表示之前添加过错误提示等限制属性,现在需要移除这些属性,恢复表单字段和表单组的原始样式(通过 removeAttr 方法移除相关样式属性),同时移除该字段后面的错误提示标签(通过 next 方法找到并 remove 方法移除),最后重新绑定 keyup 事件,当用户再次输入内容时重新进行验证(调用 toVal 方法)。
toRemoveError: function (ele) {
var that = this;
if ($(ele).closest(".form-group").attr("not-allow")) {
$(ele).removeAttr("style").closest(".form-group").removeAttr("style")
.removeAttr("not-allow");
$(ele).next().remove();
$(ele).keyup(function () {
ele = ele.replace("#", "");
that.toVal("#" + ele, that.cfg.rules[ele]);
});
}
})
},
// 用于显示表单字段错误提示信息的方法接收一个表单字段的选择器ele以及对应的错误提示消息message首先根据配置的错误标签模板cfg.errorLabel创建一个包含错误消息的 <label> 标签元素(通过 jQuery 的 text 方法设置文本内容),然后判断该字段所在的表单组元素是否已经有 "not-allow" 属性(如果没有则表示之前没有添加过错误提示,需要添加),如果没有则将错误提示标签添加到表单字段后面(通过 after 方法),同时设置表单字段和表单组的样式为红色边框、红色文字等错误提示样式(通过 css 方法设置样式属性,并通过 attr 方法添加 "not-allow" 属性表示已经添加了错误提示),最后重新绑定 keyup 事件当用户再次输入内容时重新进行验证并且每次显示错误提示时会将标志变量flag加1表示出现了错误情况后续可以根据这个标志来判断是否能提交表单等操作。
toShowError: function (ele, message) {
var error = $(this.cfg.errorLabel).text(message);
if (!$(ele).closest(".form-group").attr("not-allow")) {
$(ele).after(error);
$(ele).css("border", "1px solid red").closest(".form-group")
.css("color", "red").attr("not-allow", "true");
$(ele).keyup(function () {
ele = ele.replace("#", "");
that.toVal("#" + ele, that.cfg.rules[ele]);
});
}
this.flag++;
var that = this;
}
})
// 定义一个名为 validateConstant 的对象,用于存储各种表单字段验证的正则表达式或验证函数,通过不同的键(验证规则常量,如 "notEmpty"、"password" 等)来对应不同的验证逻辑,用于验证表单输入是否符合相应的格式要求。
var validateConstant = {
"notEmpty" : /^.+$/,// 合法字符
"password" : /^[0-9A-Za-z]{1,18}$/,// 密码
"rightfulString" : /^[A-Za-z0-9_-]+$/,// 合法字符
"number" : /^\d+$/,// 数字
"endlish" : /^[A-Za-z]+$/,// 纯英文
"numberEnglish" : /^[A-Za-z0-9]+$/,// 英文和数字
"float" : /^[+]?\d+(\.\d+)?$/,// 浮点型
"money" : /(^[1-9]\d{0,9}(\.\d{1,2})?$)/,
"chinese" : "/^[\u4e00-\u9fa5]+$/",// 纯中文
"mobile" : /^(((13[0-9]{1})|(15[0-9]{1})|(18[0-9]{1})|(17[0-9]{1})|(14[0-9]{1}))+\d{8})$/,// 手机号
"tel" : /^(\d{3,4}-?)?\d{7,9}$/g,// 电话
"qq" : /^[1-9]\d{4,12}$/,// qq
"zipCode" : /^[0-9]{6}$/,// 邮政编码
"email" : /^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+(.[a-zA-Z0-9_-])+/,// 邮箱
"positive":/^[1-9][0-9]+$/,//大于0的数字
"checkIdCard" : function(idcard) {// 校验身份证
var area={11:"北京",12:"天津",13:"河北",14:"山西",15:"内蒙古",21:"辽宁",22:"吉林",23:"黑龙江",31:"上海",32:"江苏",33:"浙江",34:"安徽",35:"福建",36:"江西",
37:"山东",41:"河南",42:"湖北",43:"湖南",44:"广东",45:"广西",46:"海南",50:"重庆",51:"四川",52:"贵州",53:"云南",54:"西藏",61:"陕西",62:"甘肃",
63:"青海",64:"宁夏",65:"新疆",71:"台湾",81:"香港",82:"澳门",91:"国外"}
var idcard,Y,JYM;
var S,M;
var idcard_array = new Array();
idcard_array = idcard.split("");
//地区检验
if(area[parseInt(idcard.substr(0,2))]==null){
return false;
"notEmpty": /^.+$/,// 合法字符,该正则表达式表示只要输入有内容(至少包含一个字符)就算符合要求,用于验证字段不能为空。
"password": /^[0-9A-Za-z]{1,18}$/,// 密码验证密码格式要求由数字、大小写字母组成长度在1到18位之间。
"rightfulString": /^[A-Za-z0-9_-]+$/,// 合法字符,验证输入是否是由大小写字母、数字、下划线和短横线组成的合法字符串。
"number": /^\d+$/,// 数字,验证输入是否只包含数字。
"endlish": /^[A-Za-z]+$/,// 纯英文,验证输入是否只包含英文字母。
"numberEnglish": /^[A-Za-z0-9]+$/,// 英文和数字,验证输入是否只包含英文字母和数字。
"float": /^[+]?\d+(\.\d+)?$/,// 浮点型,验证输入是否是合法的浮点数格式,可以包含正负号、整数部分和可选的小数部分。
"money": /(^[1-9]\d{0,9}(\.\d{1,2})?$)/,
"chinese": "/^[\u4e00-\u9fa5]+$/",// 纯中文验证输入是否只包含中文字符通过Unicode编码范围来判断不过这里的正则表达式写法有点问题外面的双引号应该去掉正确的是 /^[\u4e00-\u9fa5]+$/.
"mobile": /^(((13[0-9]{1})|(15[0-9]{1})|(18[0-9]{1})|(17[0-9]{1})|(14[0-9]{1}))+\d{8})$/,// 手机号,验证输入是否是符合常见手机号码格式的字符串。
"tel": /^(\d{3,4}-?)?\d{7,9}$/g,// 电话,验证输入是否是符合常见电话号码格式(可以包含区号,用 - 连接,也可以没有区号)的字符串,注意这里的 /g 表示全局匹配标志,在验证时会匹配所有符合的内容(不过在这个场景下一般只验证一个电话号码,是否需要全局匹配可根据实际情况调整)。
"qq": /^[1-9]\d{4,12}$/,// qq验证输入是否是符合QQ号码格式数字开头长度在5到13位之间的数字字符串。
"zipCode": /^[0-9]{6}$/,// 邮政编码验证输入是否是6位数字的邮政编码格式。
"email": /^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+(.[a-zA-Z0-9_-])+/,// 邮箱,验证输入是否是符合常见邮箱格式(包含用户名、@符号、域名等部分,这里只是简单的格式验证,不是非常严格)的字符串。
"positive": /^[1-9][0-9]+$/,//大于0的数字验证输入是否是大于0的整数数字开头且不是0后面可以跟其他数字
"checkIdCard": function (idcard) {// 校验身份证定义一个函数用于验证身份证号码的合法性根据身份证号码的位数15位或18位以及对应的出生日期、地区编码、校验位等规则来进行详细的验证返回 true 表示验证通过false 表示验证不通过。
var area = { 11: "北京", 12: "天津", 13: "河北", 14: "山西", 15: "内蒙古", 21: "辽宁", 22: "吉林", 23: "黑龙江", 31: "上海", 32: "江苏", 33: "浙江", 34: "安徽", 35: "福建", 36: "江西",
37: "山东", 41: "河南", 42: "湖北", 43: "湖南", 44: "广东", 45: "广西", 46: "海南", 50: "重庆", 51: "四川", 52: "贵州", 53: "云南", 54: "西藏", 61: "陕西", 62: "甘肃",
63: "青海", 64: "宁夏", 65: "新疆", 71: "台湾", 81: "香港", 82: "澳门", 91: "国外" }
var idcard, Y, JYM;
var S, M;
var idcard_array = new Array();
idcard_array = idcard.split("");
//地区检验,通过截取身份证号码的前两位,在 area 对象中查找对应的地区名称,如果查找不到则表示地区编码不合法,返回 false。
if (area[parseInt(idcard.substr(0, 2))] == null) {
return false;
}
//身份号码位数及格式检验
switch(idcard.length){
case 15:
if ( (parseInt(idcard.substr(6,2))+1900) % 4 == 0 || ((parseInt(idcard.substr(6,2))+1900) % 100 == 0 && (parseInt(idcard.substr(6,2))+1900) % 4 == 0 )){
ereg=/^[1-9][0-9]{5}[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|[1-2][0-9]))[0-9]{3}$/;
//测试出生日期的合法性
} else {
ereg=/^[1-9][0-9]{5}[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|1[0-9]|2[0-8]))[0-9]{3}$/;
//测试出生日期的合法性
}
if(ereg.test(idcard)){
return true;
}else{
return false;
}
break;
case 18:
//18位身份号码检测
//出生日期的合法性检查
//闰年月日:((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|[1-2][0-9]))
//平年月日:((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|1[0-9]|2[0-8]))
if ( parseInt(idcard.substr(6,4)) % 4 == 0 || (parseInt(idcard.substr(6,4)) % 100 == 0 && parseInt(idcard.substr(6,4))%4 == 0 )){
//身份号码位数及格式检验根据身份证号码的长度15位或18位分别进行不同的格式和合法性验证主要涉及出生日期的合法性检查以及18位身份证的校验位计算等操作。
switch (idcard.length) {case 15:
if ( (parseInt(idcard.substr(6,2))+1900) % 4 == 0 || ((parseInt(idcard.substr(6,2))+1900) % 100 == 0 && (parseInt(idcard.substr(6,2))+1900) % 4 == 0 )){
ereg=/^[1-9][0-9]{5}[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|[1-2][0-9]))[0-9]{3}$/;
//测试出生日期的合法性
} else {
ereg=/^[1-9][0-9]{5}[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|1[0-9]|2[0-8]))[0-9]{3}$/;
//测试出生日期的合法性
}
if(ereg.test(idcard)){
return true;
}else{
return false;
}
break;
case 18:
//18位身份号码检测
//出生日期的合法性检查
//闰年月日:((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|[1-2][0-9]))
//平年月日:((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|1[0-9]|2[0-8]))
if ( parseInt(idcard.substr(6,4)) % 4 == 0 || (parseInt(idcard.substr(6,4)) % 100 == 0 && parseInt(idcard.substr(6,4))%4 == 0 )){
ereg=/^[1-9][0-9]{5}19[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|[1-2][0-9]))[0-9]{3}[0-9Xx]$/;
//闰年出生日期的合法性正则表达式
} else {
//闰年出生日期的合法性正则表达式
} else {
ereg=/^[1-9][0-9]{5}19[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|1[0-9]|2[0-8]))[0-9]{3}[0-9Xx]$/;
//平年出生日期的合法性正则表达式
}
if(ereg.test(idcard)){//测试出生日期的合法性
//计算校验位
S = (parseInt(idcard_array[0]) + parseInt(idcard_array[10])) * 7 + (parseInt(idcard_array[1]) + parseInt(idcard_array[11])) * 9
+ (parseInt(idcard_array[2]) + parseInt(idcard_array[12])) * 10 + (parseInt(idcard_array[3]) + parseInt(idcard_array[13])) * 5
+ (parseInt(idcard_array[4]) + parseInt(idcard_array[14])) * 8 + (parseInt(idcard_array[5]) + parseInt(idcard_array[15])) * 4
+ (parseInt(idcard_array[6]) + parseInt(idcard_array[16])) * 2 + parseInt(idcard_array[7]) * 1 + parseInt(idcard_array[8]) * 6
+ parseInt(idcard_array[9]) * 3 ;
Y = S % 11;
M = "F";
JYM = "10X98765432";
M = JYM.substr(Y,1);//判断校验位
//平年出生日期的合法性正则表达式
}
if(ereg.test(idcard)){//测试出生日期的合法性
//计算校验位
S = (parseInt(idcard_array[0]) + parseInt(idcard_array[10])) * 7 + (parseInt(idcard_array[1]) + parseInt(idcard_array[11])) * 9
+ (parseInt(idcard_array[2]) + parseInt(idcard_array[12])) * 10 + (parseInt(idcard_array[3]) + parseInt(idcard_array[13])) * 5
+ (parseInt(idcard_array[4]) + parseInt(idcard_array[14])) * 8 + (parseInt(idcard_array[5]) + parseInt(idcard_array[15])) * 4
+ (parseInt(idcard_array[6]) + parseInt(idcard_array[16])) * 2 + parseInt(idcard_array[7]) * 1 + parseInt(idcard_array[8]) * 6
+ parseInt(idcard_array[9]) * 3 ;
Y = S % 11;
M = "F";
JYM = "10X98765432";
M = JYM.substr(Y,1);//判断校验位
if(M == idcard_array[17].toUpperCase()) {
return true; //检测ID的校验位
return true; //检测ID的校验位
}else{
return false;
}
}else{
return false;
}
break;
default:
return false;
break;
}
break;
default:
return false;
break;
}
}
}
var errorMsg = {

Loading…
Cancel
Save