You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1566 lines
44 KiB

This file contains invisible Unicode characters!

This file contains invisible Unicode characters that may be processed differently from what appears below. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to reveal hidden characters.

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# 酒店管理系统开发文档
## 一、技术栈
### 1.数据库mysql5.7
### 2.jdk1.8
### 3.maven+gitee管理项目
### 4.后台模板layuimini+ssm框架
## 二、数据库设计
### 1.部门表
![image-20220416135554136](C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20220416135554136.png)
### 2.员工表
![image-20220416135538343](C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20220416135538343.png)
## 三、环境搭建
### 1.配置spring
### 2.配置springMvc
### 3.配置mybatis
### 4.配置数据源
## 四、项目开发
### 1.相关资料导入
导入layuimini相关代码我们把所有关于后台数据都放入到WEB-INF文件夹下面 但是我们直接访问是访问不了的 所有我们在控制层写一个方法进入到该文件夹
因为是后台 所以我们文件都放入到admin文件夹下面
```java
//专门用来控制 负责跳转后台页面的
@Controller
@RequestMapping("/admin")
public class SystemController {
//去到登录页面
@RequestMapping("/login.html")
public String login(){
return "login";
}
}
```
### 2.实现用户登录功能
#### 1编写实体类
```java
private Integer id;
private String username;
private String password;
private String name;
private String sex;
private Integer deptId;
private Date hireDate;//入职时间
private String salt;//密码加密值
private Date createDate;
private Integer createBy;
private Integer modifyBy;//修改人
private Date modifyDate;
private String remark;//备注
```
#### 2编写mapper相关接口
```java
public Employee findNameLogin(String username);//按用户名查询
```
#### 3编写mapper接口mysql语句
```xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="comxyp.mapper.EmployeeMapper">
<!--根据用户名查询员工信息-->
<select id="findNameLogin" resultType="comxyp.pojo.Employee">
select * from employee_table where username = #{username}
</select>
</mapper>
```
#### 4编写service接口方法
```java
//用户登录
public Employee userLogin(String username,String password);
```
#### 5实现service接口方法
```java
@Service
public class EmployeeServiceImpl implements EmployeeService {
@Autowired
private EmployeeMapper employeeMapper;
@Override
//用户登录
public Employee userLogin(String username,String password) {
Employee employee = employeeMapper.findNameLogin(username);
if(employee!=null){
//与用户输入密码进行比较
if(employee.getPassword().equals(password)){//登录成功
return employee;
}
}
return null;
}
}
```
#### 6编写controller实现
```java
@Controller
@RequestMapping("/employee")
public class EmployeeController {
@Autowired
private EmployeeService employeeService;
@RequestMapping("/login")
@ResponseBody
public String login(String username, String password,String code, HttpSession session){
System.out.println(username);
System.out.println(password);
Map<String,Object> map = new HashMap<>();
Employee employee = employeeService.userLogin(username,password);
if(employee!=null){
//保存用户登录信息
session.setAttribute("user",employee);
map.put("success",true);
} else if(employee==null){
map.put("success",false);
map.put("msg","用户名或者密码错误");
} else if(!code.equals("xSzG")){
map.put("msg","验证码错误");
}
return JSON.toJSONString(map);
}
}
```
#### 7修改login.jsp页面相关代码
```jsp
<div class="layui-container">
<div class="admin-login-background">
<div class="layui-form login-form">
<form class="layui-form" action="">
<div class="layui-form-item logo-title">
<h1>酒店后台管理登录</h1>
</div>
<div class="layui-form-item">
<label class="layui-icon layui-icon-username" for="username"></label>
<input type="text" name="username" id="username" lay-verify="required|account" placeholder="用户名或者邮箱" autocomplete="off" class="layui-input" value="xyp">
</div>
<div class="layui-form-item">
<label class="layui-icon layui-icon-password" for="password"></label>
<input type="password" name="password" id="password" lay-verify="required|password" placeholder="密码" autocomplete="off" class="layui-input" value="123">
</div>
<div class="layui-form-item">
<label class="layui-icon layui-icon-vercode"></label>
<input type="text" name="code" lay-verify="required|captcha" placeholder="图形验证码" autocomplete="off" class="layui-input verification captcha" value="xSzG">
<div class="captcha-img">
<img id="captchaPic" src="${pageContext.request.contextPath}/static/layui/images/captcha.jpg">
</div>
</div>
<div class="layui-form-item">
<input type="checkbox" name="rememberMe" value="true" lay-skin="primary" title="记住密码">
</div>
<div class="layui-form-item">
<button class="layui-btn layui-btn layui-btn-normal layui-btn-fluid" lay-submit="" lay-filter="login">登 入</button>
</div>
</form>
</div>
</div>
</div>
<script src="${pageContext.request.contextPath}/static/layui/lib/jquery-3.4.1/jquery-3.4.1.min.js" charset="utf-8"></script>
<script src="${pageContext.request.contextPath}/static/layui/lib/layui-v2.6.3/layui.js" charset="utf-8"></script>
<script src="${pageContext.request.contextPath}/static/layui/lib/jq-module/jquery.particleground.min.js" charset="utf-8"></script>
<script>
layui.use(['form','layer','jquery'], function () {
var form = layui.form,
layer = layui.layer;
$=layui.jquery;
// 登录过期的时候跳出ifram框架
if (top.location != self.location) top.location = self.location;
// 粒子线条背景
$(document).ready(function(){
$('.layui-container').particleground({
dotColor:'#7ec7fd',
lineColor:'#7ec7fd'
});
});
// 进行登录操作
form.on('submit(login)', function (data) {
//可以获取到表单中所有数据 data = data.field;
//发送登录请求
$.post("${pageContext.request.contextPath}/employee/login",data.field,function (result) {
// console.log(result);
if(result.success){//如果登录成功跳转到后台页面
location.href="home.html";
} else{//登录失败 提示用户
layer.msg(result.msg);
}
},"json");
return false;
});
});
</script>
</body>
```
#### 8浏览器乱码问题解决
当我们把java对象转换为json格式返回到浏览器上时 可能会错写乱码问题 所以我们此时去springMVC中进行配置
第一步把java对象转换为JSON格式 我们要导入相应的坐标
```xml
<!--Fastjson 是一个 Java 库,可以将 Java 对象转换为 JSON 格式,
当然它也可以将 JSON 字符串转换为 Java 对象。.-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.73</version>
</dependency>
```
第二步:在配置
```xml
<!--配置mvc注解驱动-->
<!--能支持springmvc更高级的一些功能 JSR303校验 ajax等-->
<mvc:annotation-driven>
<mvc:message-converters>
<!--@ResponseBody 中文响应乱码 -->
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>
text/plain;charset=UTF-8
</value>
<value>
text/html;charset=UTF-8
</value>
<value>
application/json;charset=UTF-8
</value>
<value>
application/x-www-form-urlencoded;charset=UTF-8
</value>
</list>
</property>
</bean>
<!-- JSON中文请求乱码及解决
HttpMediaTypeNotAcceptableException: Could not find acceptable representation 异常信息-->
<bean id="jacksonMessageConverter"
class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>
application/json;charset=UTF-8
</value>
<value>
application/x-www-form-urlencoded;charset=UTF-8
</value>
</list>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
```
### 3.实现注册功能
#### 1编写mapper相关接口
```java
//保存用户信息
public int saveUser(Employee employee);
```
#### 2表现实现mapper接口Mysql语句
```xml
<!--保存用户-->
<insert id="saveUser" parameterType="comxyp.pojo.Employee">
insert into employee_table(id,username,password,name,sex,deptId,hireDate)
values (#{id},#{username},#{password},#{name},#{sex},#{deptId},#{hireDate})
</insert>
```
#### 3编写service接口方法
```java
//保存用户
public int saveUser(Employee employee);
```
#### 4实现service接口方法
```java
public int saveUser(Employee employee) {
return employeeMapper.saveUser(employee);
}
```
#### 5编写controller实现
```java
@RequestMapping("/register")
@ResponseBody
public String register( String username, String password, String names, String sex,Integer depId){
Map<String,Object> map = new HashMap<>();
Employee employees = new Employee();
employees.setId(null);
employees.setUsername(username);
employees.setPassword(password);
employees.setName(names);
employees.setSex(sex);
employees.setDeptId(depId);
employees.setHireDate(new Date());
Employee employee = employeeService.userLogin(username,password);
int n = employeeService.saveUser(employees);
if(employee!=null){
//保存用户登录信息
//用户名已经存在
map.put("success", false);
map.put("msg", "用户名已经存在");
} else{
if(n>0){
map.put("success", true);
map.put("msg","注册成功");
}
}
return JSON.toJSONString(map);
}
```
#### 6修改registe.jsp页面相关代码
```jsp
<div class="layui-container">
<div class="admin-login-background">
<div class="layui-form login-form">
<form class="layui-form" action="" id="update_frm">
<div class="layui-form-item logo-title">
<h1>酒店后台管理注册</h1>
</div>
<div class="layui-form-item">
<label class="layui-icon layui-icon-username" for="username"></label>
<input type="text" name="username" id="username" lay-verify="required|account" placeholder="用户名或者邮箱" autocomplete="off" class="layui-input" value="">
</div>
<div class="layui-form-item">
<label class="layui-icon layui-icon-password" for="username"></label>
<input type="password" name="password" lay-verify="required|password" placeholder="密码" autocomplete="off" class="layui-input" value="">
</div>
<div class="layui-form-item">
<label class="layui-icon layui-icon-password" ></label>
<input type="text" name="names" lay-verify="required|account" placeholder="姓名" autocomplete="off" class="layui-input" value="">
</div>
<div class="layui-form-item">
<input type="text" name="text" maxlength="2" lay-verify="required|account" placeholder="性别" autocomplete="off" class="layui-input" value="">
</div>
<div class="layui-form-item">
<label class="layui-icon layui-icon-password" ></label>
<input type="text" name="depId" id="depId" lay-verify="required|account" placeholder="部门编号" autocomplete="off" class="layui-input" value="">
</div>
<div class="layui-form-item">
<a href="${pageContext.request.contextPath}/admin/login.html">已有账号?返回登录</a>
</div>
<div class="layui-form-item">
<button class="layui-btn layui-btn layui-btn-normal layui-btn-fluid" lay-submit="" lay-filter="login">注册</button>
</div>
</form>
</div>
</div>
</div>
<script src="${pageContext.request.contextPath}/static/layui/lib/jquery-3.4.1/jquery-3.4.1.min.js" charset="utf-8"></script>
<script src="${pageContext.request.contextPath}/static/layui/lib/layui-v2.6.3/layui.js" charset="utf-8"></script>
<script src="${pageContext.request.contextPath}/static/layui/lib/jq-module/jquery.particleground.min.js" charset="utf-8"></script>
<script>
layui.use(['form','layer','jquery'], function () {
var form = layui.form,
layer = layui.layer,
$=layui.jquery;
// 登录过期的时候跳出ifram框架
if (top.location != self.location) top.location = self.location;
// 进行登录操作
form.on('submit(login)', function (data) {
//可以获取到表单中所有数据 data = data.field;
//发送登录请求
$.post("${pageContext.request.contextPath}/employee/register",data.field,function (result) {
console.log(result);
if(result.success){//如果登录成功跳转到后台页面
location.href="${pageContext.request.contextPath}/admin/login.html";
} else{//登录失败 提示用户
layer.msg(result.msg);
}
},"json");
return false;
});
});
</script>
</body>
```
### 4.实现首页功能
#### 1修改首页的相关内容
导入layuimini的index.html页面进行修改
#### 2退出登录
在控制层编写访问退出登录访问路径
```java
//退出登录
@RequestMapping("/logout.html")
public String logout(HttpSession session){
//清空session
session.removeAttribute("user");
return "redirect:/admin/login.html";
}
```
```jsp
<dd>
<a href="javascript:;" class="login-out">退出登录</a>
</dd>
```
```js
$('.login-out').on("click", function () {
layer.confirm('确定要退出吗?', {icon: 3, title:'提示'}, function(index){
location.href="${pageContext.request.contextPath}/admin/logout.html"
layer.close(index);
});
});
```
#### 3使用拦截器 拦截除登录页面之外的其他页面
拦截器拦截是放在WEB-INF下面页面
为了安全 我们只有登录成功之后 才能访问其他页面 所以 我们使用拦截器
第一步:编写拦截器方法:
```java
public class LoginInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//判断session是否为空
if((request.getSession().getAttribute("user")==null)){
//如果没有登录,则去到登录页面
response.sendRedirect(request.getContextPath()+"/admin/login.html");
return false;//验证失败,进行拦截
}
//验证通过
return true;
}
}
```
第二步去springMvc中进行拦截器配置
```xml
<!--拦截器配置-->
<mvc:interceptors>
<mvc:interceptor>
<!--拦截所有以/admin/开头的访问路径-->
<mvc:mapping path="/admin/**"></mvc:mapping>
<!--排除员工登录的访问路径-->
<mvc:exclude-mapping path="/admin/employee/login"/>
<mvc:exclude-mapping path="/admin/login.html"/>
<!--注入拦截-->
<bean class="comxyp.interceptor.LoginInterceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>
```
#### 4过滤器使用
如果我们要拦截在webapp下面页面 我们使用过滤器 如果没有登录 是不可以访问后台页面的
所以第一步我们新建一个过滤器类:
```java
//自定义过滤器
public class LoginFilter implements Filter {
//初始化方法
@Override
public void init(FilterConfig filterConfig) throws ServletException {
//初始化处理
System.out.println("过滤器初始化");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request= (HttpServletRequest) servletRequest;
HttpServletResponse response= (HttpServletResponse) servletResponse;
HttpSession session=request.getSession();
if(session.getAttribute("user")==null){
//非法请求,直接跳转到登陆界面
//如果没有登录,则去到登录页面
response.sendRedirect(request.getContextPath()+"/admin/login.html");
}else{
//正常登录,放行
filterChain.doFilter(request,response);
}
}
@Override
public void destroy() {
//释放资源
System.out.println("过滤器销毁");
}
}
```
第二步去web.xml中进行过滤器配置
```xml
<!--使用过滤器实现登陆控制-->
<!--filter标签用于声明过滤器对象-->
<filter>
<!--过滤器名称-->
<filter-name>LoginFilter</filter-name>
<!--过滤器完整类名-->
<filter-class>comxyp.filter.LoginFilter</filter-class>
</filter>
<!--filter-mapping用于创建过滤器的映射指定Web应用中哪些URL应用哪一个过滤器进行处理-->
<filter-mapping>
<filter-name>LoginFilter</filter-name>
<!--url-pattern用于指定过滤器应用的URL-->
<!--过滤的页面(自定义),这里对登录界面就不要过滤了-->
<url-pattern>/jsp/*</url-pattern>
</filter-mapping>
```
### 5.菜单设计
#### 1菜单表设计 参照layuimini开发手册
```sql
CREATE TABLE `system_menu` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',
`pid` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '父ID',
`title` varchar(100) NOT NULL DEFAULT '' COMMENT '名称',
`icon` varchar(100) NOT NULL DEFAULT '' COMMENT '菜单图标',
`href` varchar(100) NOT NULL DEFAULT '' COMMENT '链接',
`target` varchar(20) NOT NULL DEFAULT '_self' COMMENT '链接打开方式',
`sort` int(11) DEFAULT '0' COMMENT '菜单排序',
`status` tinyint(1) unsigned NOT NULL DEFAULT '1' COMMENT '状态(0:禁用,1:启用)',
`remark` varchar(255) DEFAULT NULL COMMENT '备注信息',
`create_at` timestamp NULL DEFAULT NULL COMMENT '创建时间',
`update_at` timestamp NULL DEFAULT NULL COMMENT '更新时间',
`delete_at` timestamp NULL DEFAULT NULL COMMENT '删除时间',
PRIMARY KEY (`id`),
KEY `title` (`title`),
KEY `href` (`href`)
) ENGINE=InnoDB AUTO_INCREMENT=250 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='系统菜单表';
```
#### 2参照java示列 java动态生成初始化数据spring框架
设计数据库:
![image-20220416135502349](C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20220416135502349.png)
#### 3编写菜单实体类
```java
private Integer id;
private Integer pid;
private String title;
private String href;
private Integer spread;
private String target;
private String icon;
```
#### 4编写mapper接口
```java
List<Menu> findAll();//查询所有菜单列表
```
#### 5编写mapper.xml对应相关mysql语句
```java
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="comxyp.mapper.MenuMapper">
<!--查询所有菜单列表-->
<select id="findAll" resultType="comxyp.pojo.Menu">
select * from sys_menu;
</select>
</mapper>
```
#### 6编写service层接口
```java
List<Menu> findAll();//查询所有菜单列表
```
#### 7实现service层接口
```java
@Service
public class MenuServiceImpl implements MenuService {
@Autowired
private MenuMapper mapper;
@Override
public List<Menu> findAll() {
return mapper.findAll();
}
```
#### 8编写controller功能
分析原来我们使用加载菜单信息是api中init.json中数据 现在我们用数据库显示构建出来;
```json
{
"homeInfo": {
"title": "首页",
"href": "${pageContext.request.contextPath}/static/layui/page/welcome-1.html?t=1"
},
"logoInfo": {
"title": "LAYUI MINI",
"image": "${pageContext.request.contextPath}/static/layui/images/logo.png",
"href": ""
},
"menuInfo": [
{
"title": "常规管理",
"icon": "fa fa-address-book",
"href": "",
"target": "_self",
"child": [
{
"title": "主页模板",
"href": "",
"icon": "fa fa-home",
"target": "_self",
"child": [
{
"title": "主页一",
"href": "page/welcome-1.html",
"icon": "fa fa-tachometer",
"target": "_self"
},
{
"title": "主页二",
"href": "page/welcome-2.html",
"icon": "fa fa-tachometer",
"target": "_self"
},
{
"title": "主页三",
"href": "page/welcome-3.html",
"icon": "fa fa-tachometer",
"target": "_self"
}
]
},
{
"title": "菜单管理",
"href": "page/menu.html",
"icon": "fa fa-window-maximize",
"target": "_self"
},
{
"title": "系统设置",
"href": "page/setting.html",
"icon": "fa fa-gears",
"target": "_self"
},
{
"title": "表格示例",
"href": "page/table.html",
"icon": "fa fa-file-text",
"target": "_self"
},
{
"title": "表单示例",
"href": "",
"icon": "fa fa-calendar",
"target": "_self",
"child": [
{
"title": "普通表单",
"href": "page/form.html",
"icon": "fa fa-list-alt",
"target": "_self"
},
{
"title": "分步表单",
"href": "page/form-step.html",
"icon": "fa fa-navicon",
"target": "_self"
}
]
},
{
"title": "登录模板",
"href": "",
"icon": "fa fa-flag-o",
"target": "_self",
"child": [
{
"title": "登录-1",
"href": "page/login-1.html",
"icon": "fa fa-stumbleupon-circle",
"target": "_blank"
},
{
"title": "登录-2",
"href": "page/login-2.html",
"icon": "fa fa-viacoin",
"target": "_blank"
},
{
"title": "登录-3",
"href": "page/login-3.html",
"icon": "fa fa-tags",
"target": "_blank"
}
]
},
{
"title": "异常页面",
"href": "",
"icon": "fa fa-home",
"target": "_self",
"child": [
{
"title": "404页面",
"href": "page/404.html",
"icon": "fa fa-hourglass-end",
"target": "_self"
}
]
},
{
"title": "其它界面",
"href": "",
"icon": "fa fa-snowflake-o",
"target": "",
"child": [
{
"title": "按钮示例",
"href": "page/button.html",
"icon": "fa fa-snowflake-o",
"target": "_self"
},
{
"title": "弹出层",
"href": "page/layer.html",
"icon": "fa fa-shield",
"target": "_self"
}
]
}
]
},
{
"title": "组件管理",
"icon": "fa fa-lemon-o",
"href": "",
"target": "_self",
"child": [
{
"title": "图标列表",
"href": "page/icon.html",
"icon": "fa fa-dot-circle-o",
"target": "_self"
},
{
"title": "图标选择",
"href": "page/icon-picker.html",
"icon": "fa fa-adn",
"target": "_self"
},
{
"title": "颜色选择",
"href": "page/color-select.html",
"icon": "fa fa-dashboard",
"target": "_self"
},
{
"title": "下拉选择",
"href": "page/table-select.html",
"icon": "fa fa-angle-double-down",
"target": "_self"
},
{
"title": "文件上传",
"href": "page/upload.html",
"icon": "fa fa-arrow-up",
"target": "_self"
},
{
"title": "富文本编辑器",
"href": "page/editor.html",
"icon": "fa fa-edit",
"target": "_self"
},
{
"title": "省市县区选择器",
"href": "page/area.html",
"icon": "fa fa-rocket",
"target": "_self"
}
]
},
{
"title": "其它管理",
"icon": "fa fa-slideshare",
"href": "",
"target": "_self",
"child": [
{
"title": "多级菜单",
"href": "",
"icon": "fa fa-meetup",
"target": "",
"child": [
{
"title": "按钮1",
"href": "page/button.html?v=1",
"icon": "fa fa-calendar",
"target": "_self",
"child": [
{
"title": "按钮2",
"href": "page/button.html?v=2",
"icon": "fa fa-snowflake-o",
"target": "_self",
"child": [
{
"title": "按钮3",
"href": "page/button.html?v=3",
"icon": "fa fa-snowflake-o",
"target": "_self"
},
{
"title": "表单4",
"href": "page/form.html?v=1",
"icon": "fa fa-calendar",
"target": "_self"
}
]
}
]
}
]
},
{
"title": "失效菜单",
"href": "page/error.html",
"icon": "fa fa-superpowers",
"target": "_self"
}
]
}
]
}
```
第一步:我们需要编写一个菜单节点的工具类 里面放置的是子菜单的信息:
```java
private Integer id;//菜单编号
private Integer pid;//父级菜单编号
private String title;//菜单名称
private String href;//链接地址
private Integer spread;//是否展开
private String target;//打开方式
private String icon;//图标
private List<MenuNode> child;//子菜单集合列表
```
第二步 编写controller层
```java
@Controller
@RequestMapping("/admin/menu")
public class MenuController {
@Autowired
private MenuService menuService;
//加载首页左侧菜单栏 对应着api接口中init.json中的格式
@RequestMapping("/loadMenuList")
@ResponseBody
public String loadMenuList(){
//创建map集合保存菜单信息
Map<String,Object> map = new LinkedHashMap<>();
//创建map集合保存 homeInfo信息
Map<String,Object> homeInfo = new LinkedHashMap<>();
//创建map集合保存 logoInfo信息
Map<String,Object> logoInfo = new LinkedHashMap<>();
//查询所有菜单
List<Menu> list = menuService.findAll();
//创建集合保存菜单关系
List<MenuNode> menuNodeList = new ArrayList<>();
//循环遍历菜单列表 目的是创建菜单之间的层级关系
for(Menu m:list){
//创建菜单节点对象
MenuNode menuNode = new MenuNode();
menuNode.setHref(m.getHref());//链接地址
menuNode.setIcon(m.getIcon());//菜单图标
menuNode.setId(m.getId());//菜单编号
menuNode.setPid(m.getPid());//父级编号
menuNode.setSpread(m.getSpread());//是否展开
menuNode.setTitle(m.getTitle());//菜单标题
menuNode.setTarget(m.getTarget());//打开方式
//将对象添加到集合中
menuNodeList.add(menuNode);
}
//保存homeInfo中信息
homeInfo.put("title","首页");
homeInfo.put("href","/admin/home.jsp");
//保存logoInfo 中信息
logoInfo.put("title","酒店管理系统");//系统标题
logoInfo.put("image","/static/layui/images/logo.png");//logo图标
logoInfo.put("href","/admin/home.html");//首页地址
//将菜单信息添加到MenuInfo集合中
map.put("menuInfo", TreeUtil.toTree(menuNodeList,0));
map.put("homeInfo",homeInfo);
map.put("logoInfo",logoInfo);
//将信息以json格式返回
return JSON.toJSONString(map);
}
}
```
构建父级菜单与子菜单之间关系 我们使用layuimini给我们提供的一个工具类
```java
//构建菜单层级关系
public class TreeUtil {
/**
* 构建菜单层级关系
* @param treeList 菜单列表
* @param pid 父级菜单编号0表示父级菜单 (一级菜单)
* @return
*/
public static List<MenuNode> toTree(List<MenuNode> treeList, Integer pid) {
List<MenuNode> retList = new ArrayList<MenuNode>();
for (MenuNode parent : treeList) {
//如果当前父级菜单编号与循环的菜单列表中的父级菜单编号一致
if (pid == parent.getPid()) {
retList.add(findChildren(parent, treeList));
}
}
return retList;
}
private static MenuNode findChildren(MenuNode parent, List<MenuNode> treeList) {
for (MenuNode child : treeList) {
if (parent.getId() == child.getPid()) {
if (parent.getChild() == null) {
parent.setChild(new ArrayList<MenuNode>());
}
parent.getChild().add(findChildren(child, treeList));
}
}
return parent;
}
}
```
#### 9去首页修改端口默认地址
```js
iniUrl: "${pageContext.request.contextPath}/admin/menu/loadMenuList", // 初始化接口
```
### 6.实现部门管理功能
#### 1设计数据库
![image-20220416140303824](C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20220416140303824.png)
#### 2修改部门管理页面
我们使用layuimini中table.html页面
#### 3去controller中写好访问管理页面地址
```java
//进入部门管理页面
@RequestMapping("/ToDeptManage")
public String ToDeptManage(){
return "dept/deptManage";
}
```
#### 4编写部门管理实体类
```java
private Integer id;
private String deptName;
private String address;
private Date createtime;
private String remark;
```
因为我们要实现分页显示 所以我们单独写一个分页类 对哪一个分页 就继承谁:
```java
//实现分页
public class Vo extends Dept{
private Integer page;//当前页码
private Integer limit;//每页显示数量
```
##### 4.1导入分页插件坐标
```xml
<!--分页插件-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.0.0</version>
</dependency>
```
##### 4.2去mybatis中进行配置
```xml
<!--分页插件配置-->
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor">
<!-- 支持OracleMySQLSQLiteMariaDBHsqldbPostgreSQL -->
<property name="helperDialect" value="mysql"/>
</plugin>
</plugins>
```
#### 5编写mapper接口
```java
//部门相关接口
public interface DeptMapper {
List<Dept> findAll(Vo vo);
}
```
#### 6实现mapper接口方法mysql语句
```java
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="comxyp.mapper.DeptMapper">
<select id="findAll" resultType="comxyp.pojo.Dept">
select * from dept_table
<where>
<if test="deptname!=null and deptname!=''">
and deptname like concat('%',#{deptname},'%')
</if>
</where>
</select>
</mapper>
```
#### 7编写service层接口
```java
public interface DeptService {
List<Dept> findAll(Vo vo);
}
```
#### 8实现接口
```java
@Service
public class DeptServiceImpl implements DeptService {
@Autowired
private DeptMapper deptMapper;
@Override
public List<Dept> findAll(Vo vo) {
return deptMapper.findAll(vo);
}
}
```
#### 9编写controller层功能
##### 9.1因为我们使用的是layuimini 所以它要求我们返回数据有要求 提供了一个工具类:
```java
package comxyp.utils;
/**
* layui 数据表格类
*/
public class DataGridViewResult {
private Integer code=0;//执行状态码
private String msg="";//提示信息
private Long count=0L;//数量
private Object data;//数据
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public Long getCount() {
return count;
}
public void setCount(Long count) {
this.count = count;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
/**
* 创建数据表格对象
* @param count 数据总数量
* @param data 数据集合列表
*/
public DataGridViewResult(Long count, Object data) {
super();
this.count = count;
this.data = data;
}
public DataGridViewResult(Object data) {
super();
this.data = data;
}
public DataGridViewResult() {
}
}
```
##### 9.2编写controller
```java
//部门管理查询显示
@Controller
@RequestMapping("/dept")
public class DeptController {
@Autowired
private DeptService deptService;
@RequestMapping("/deptList")
public DataGridViewResult deptList(Vo vo){
//设置分页信息
PageHelper.startPage(vo.getPage(),vo.getLimit());
//调用分页查询的方法
List<Dept> list = deptService.findAll(vo);
//创建分页对象
PageInfo<Dept> pageInfo = new PageInfo<>(list);
//返回数据
return new DataGridViewResult(pageInfo.getTotal(),pageInfo.getList());
}
}
```
### 7.部门添加
#### 1修改部门列表页面中添加事件
修改相关代码
```js
//监听头部工具栏事件
//toolbar是头部工具栏事件
//currentTableFilter是表格lay-filter过滤器的值
table.on("toolbar(currentTableFilter)",function (obj) {
switch (obj.event) {
case "add"://添加按钮
openAddWindow();//打开添加窗口
break;
}
});
var url;//提交地址
var mainIndex;//打开窗口的索引
/**
* 打开添加窗口
*/
function openAddWindow() {
mainIndex = layer.open({
type: 1,//打开类型
title: "添加部门",//窗口标题
area: ["800px", "400px"],//窗口宽高
content: $("#addOrUpdateWindow"),//引用的内容窗口
success: function () {
//清空表单数据
$("#dataFrm")[0].reset();
//添加的提交请求
url = "${pageContext.request.contextPath}/dept/addDept";
}
});
}
//监听表单提交事件
form.on("submit(doSubmit)",function (data) {
$.post(url,data.field,function(result){
if(result.success){
//刷新数据表格
tableList.reload();
//关闭窗口
layer.close(mainIndex);
}
//提示信息
layer.msg(result.msg);
},"json");
//禁止页面刷新
return false;
});
});
</script>
```
#### 2编写mapper接口
```java
//添加部门
int addDept(Dept dept);
```
#### 3编写mapper.xml中mysql语句
```java
<insert id="addDept" parameterType="comxyp.pojo.Dept">
insert into dept_table(deptname,address,remark) values (#{deptname},#{address},#{remark})
</insert>
```
#### 3编写service接口
```java
//添加部门
int addDept(Dept dept);
```
#### 4实现接口
```java
public int addDept(Dept dept) {
return deptMapper.addDept(dept);
}
```
#### 5编写controller功能
```java
@RequestMapping("/addDept")
@ResponseBody
public String addDept(Dept dept){
Map<String,Object> map = new HashMap<>();
int n= deptService.addDept(dept);
if(n>0){
map.put("success",true);
map.put("msg","添加成功");
} else{
map.put("success", false);
map.put("msg", "添加失败");
}
return JSON.toJSONString(map);
}
```
### 8.部门修改
#### 1修改页面
##### 8.1添加隐藏域 为某一条修改
```jsp
<%-- 隐藏域 --%>
<input type="hidden" name="id">
```
##### 8.2监听行事件 获取某一行的数据
```js
//监听行工具栏事件
table.on("tool(currentTableFilter)",function (obj) {
console.log(obj);
switch (obj.event) {
case "edit"://编辑按钮
openUpdateWindow(obj.data);//打开修改窗口
break;
case "delete"://删除按钮
deleteById(obj.data);
break;
}
});
```
##### 8.3打开修改窗口
```js
/**
* 打开修改窗口
* @param data 当前行的数据
*/
function openUpdateWindow(data) {
mainIndex = layer.open({
type: 1,//打开类型
title: "修改部门",//窗口标题
area: ["800px", "400px"],//窗口宽高
content: $("#addOrUpdateWindow"),//引用的内容窗口
success: function () {
//表单数据回显
form.val("dataFrm",data);//参数1lay-filter值 参数2回显的数据
//修改的提交请求
url = "${pageContext.request.contextPath}/dept/updateDept";
}
});
}
```
#### 2编写mapper接口
```java
//部门修改
int updateDept(Dept dept);
```
#### 3编写mapper.xml中mysql语句
```xml
<!--部门修改-->
<update id="updateDept" parameterType="comxyp.pojo.Dept">
update dept_table
<set>
<if test="deptname!=null and deptname!=''">
deptename = #{deptname},
</if>
<if test="address!=null and address!=''">
address = #{address},
</if>
<if test="remark!=null and remark!=''">
remark = #{remark}
</if>
</set>
where id=#{id}
</update>
```
#### 3编写service接口
```java
//部门修改
int updateDept(Dept dept);
```
#### 4实现接口
```java
public int updateDept(Dept dept) {
return deptMapper.updateDept(dept);
}
```
#### 5编写controller功能
```java
@RequestMapping("/updateDept")
@ResponseBody
public String updateDept(Dept dept){
Map<String,Object> map = new HashMap<>();
int n= deptService.updateDept(dept);
if(n>0){
map.put("success",true);
map.put("msg","添加成功");
} else{
map.put("success", false);
map.put("msg", "添加失败");
}
return JSON.toJSONString(map);
}
```
### 9.部门删除
在删除之前 我们要判断该部门下是否有员工 所以先进行判断检查
##### 9.1编写员工mapper接口 按员工编号查询
```java
/**
* 根据部门编号查询员工数量
* @param deptId
* @return
*/
int getEmployeeCountByDeptId(Integer deptId);
```
##### 9.2 编写相关mysql语句和service接口
```java
<select id="getEmployeeCountByDeptId" resultType="int">
<!-- 根据部门编号查询该部门下的员工数量 -->
select count(1) from employee_table where deptId = #{deptId}
</select>
```
```java
public int getEmployeeCountByDeptId(Integer deptId) {
return employeeMapper.getEmployeeCountByDeptId(deptId);
}
}
```
##### 9.3编写controller层功能
```java
@RequestMapping("/checkDeptHasEmployee")
@ResponseBody
public String checkDeptHasEmployee(Integer id){
Map<String,Object> map = new HashMap<String,Object>();
//调用根据部门编号查询员工数量的方法
if(employeeService.getEmployeeCountByDeptId(id)>0){
map.put("exist",true);//存在
map.put("msg","该部门存在员工信息,无法删除");
}else{
map.put("exist",false);//不存在
}
return JSON.toJSONString(map);
}
```
#### 1修改页面
```js
/**
* 删除部门
* @param data 当前行数据
*/
function deleteById(data) {
//判断当前部门下是否存在员工
$.get("${pageContext.request.contextPath}/dept/checkDeptHasEmployee",{"id":data.id},function(result){
if(result.exist){
//提示用户无法删除
layer.msg(result.msg);
}else{
//提示用户是否删除该部门
layer.confirm("确定要删吗", {icon: 3, title:'提示'}, function(index){
//发送ajax请求进行删除
$.post("${pageContext.request.contextPath}/dept/deleteById",{"id":data.id},function(result){
if(result.success){
//刷新数据表格
tableIns.reload();
}
//提示
layer.msg(result.msg);
},"json");
layer.close(index);
});
}
},"json");
}
```
#### 2编写mapper接口
```java
//删除
int deleteById(Integer id);
```
#### 3编写mapper.xml中mysql语句
```xml
<delete id="deleteById">
delete from dept_table where id=#{id}
</delete>
</mapper>
```
#### 3编写service接口
```java
//删除
int deleteById(Integer id);
```
#### 4实现接口
```java
public int deleteById(Integer id) {
return deptMapper.deleteById(id);
}
```
#### 5编写controller功能
```java
/**
* 删除部门
* @param id
* @return
*/
@RequestMapping("/deleteById")
@ResponseBody
public String deleteById(Integer id){
Map<String,Object> map = new HashMap<String,Object>();
//调用删除部门的方法
if(deptService.deleteById(id)>0){
map.put("success",true);//成功
map.put("msg","删除成功");
}else{
map.put("success",false);//失败
map.put("msg","删除失败");
}
return JSON.toJSONString(map);
}
```