基于javaweb+mysql的springboot酒店管理系统(java+springboot+maven+mybatis-plus+html+thymleaf+mysql)
私信源码获取及调试交流
运行环境
Java≥8、MySQL≥5.7
开发工具
eclipse/idea/myeclipse/sts等均可配置运行
适用
课程设计,大作业,毕业设计,项目练习,学习演示等
功能说明
基于javaweb的SpringBoot酒店管理系统(java+springboot+maven+mybatis-plus+html+thymleaf+mysql)
项目介绍
角色:管理员、前台工作人员、保洁阿姨、客户 四种角色
客户功能:
客户注册、登录、找回密码
留言板查看和留言
浏览客房,根据入住日期和退房日期查询和预定客房
支付订单,支付已对接了支付宝沙箱支付,可可以随时关闭启动
客户可以退房,续订,取消订单等功能
管理员功能:
客房管理
客房类型管理
订单管理
入住登记管理
退房登记管理
客房清洁管理
留言管理(只有管理员可以进行留言删除)
财务管理
人员管理( 前台人员,清洁人员,客户)
角色管理,权限管理
酒店前台人员:
订单管理
入住登记管理
退房登记管理
客房清洁管理(只能查看)
留言管理,(可以留言回复,不能删除留言)
财务管理
人员管理( 只能看客户) 理、民宿信息管理、房间类型管理、房间信息管理、房间预订管理、房间退订管理、投诉反馈管理、我的收藏管理、系统管理。
环境需要
1.运行环境:最好是java jdk 1.8,我们在这个平台上运行的。其他版本理论上也可以。
2.IDE环境:IDEA,Eclipse,Myeclipse都可以。推荐IDEA;
3.硬件环境:windows 7/8/10 1G内存以上;或者 Mac OS;
4.是否Maven项目: 否;查看源码目录中是否包含pom.xml;若包含,则为maven项目,否则为非maven项目;
5.数据库:MySql 5.7/8.0等版本均可;
技术栈
后端:SpringBoot+MyBatis-Plus
前端:Html+CSS+jquery+Thymleaf
使用说明
- 使用Navicat或者其它工具,在mysql中创建对应名称的数据库,并导入项目的sql文件; 2. 使用IDEA/Eclipse/MyEclipse导入项目,修改配置,运行项目;
文档介绍(我的订单功能详细设计、浏览客房功能详细设计、房间管理功能详情设计、订单管理功能详情设计、入住管理功能详细设计、营业统计功能详细设计、系统实现、前台管理模块、预定房间、我的订单功能、浏览客房功能、后台管理模块、房间管理、订单管理、入住管理、营业统计功能、系统测试、系统测试目的、测试环境与测试条件、测试用例):
酒店管理首页详情展示:
酒店详情信息介绍:
留言板详情展示:
客房列表详情展示:
结算详情信息展示:
酒店后台功能列表展示-财务管理:
酒店后台功能列表展示-订单管理:
酒店后台功能列表展示-订单管理:
酒店后台功能列表展示-客房管理:
// 判断离店日期是否合法
DateFormat dateFormat = new SimpleDateFormat(DateUtil.FORMAT);
Date endDate = dateFormat.parse(end);
Date oldEndDate = dateFormat.parse(order.getEndDate());
if (!endDate.after(oldEndDate)) {
return JsonResult.error("新的退房日期不能小于等于之前的退房日期");
}
int quantity = DateUtil.differentDays(oldEndDate, endDate);
if (quantity < 1) {
return JsonResult.error("至少需要续订一天");
}
// 查询日期列表
List<String> dateList = DateUtil.getBetweenDates(order.getEndDate(), quantity);
// 判断客房是否可以预定
List<Record> recordList = recordService.findByPostIdAndRecordDate(order.getPostId(), dateList);
if (recordList.size() > 0) {
Record record = recordList.get(0);
return JsonResult.error("该房间" + record.getRecordDate() + "已被人预定,请重新选择续订日期");
}
order.setQuantity(order.getQuantity() + quantity);
order.setEndDate(dateFormat.format(endDate));
order.setTotalPrice(order.getPrice() * quantity + order.getTotalPrice());
orderService.update(order);
// 添加预定记录
for (String recordDate : dateList) {
Record record = new Record();
record.setPostId(order.getPostId());
record.setUserId(user.getId());
record.setRecordDate(recordDate);
recordService.insert(record);
}
return JsonResult.success("续订成功");
*
* @return 模板路径admin/admin_outrecord
*/
@GetMapping
public String outrecordList(@RequestParam(value = "replyFlag", defaultValue = "-1") Integer replyFlag,
@RequestParam(value = "page", defaultValue = "0") Integer pageNumber,
@RequestParam(value = "size", defaultValue = "10") Integer pageSize,
@RequestParam(value = "sort", defaultValue = "createTime") String sort,
@RequestParam(value = "order", defaultValue = "desc") String order, Model model) {
// 查询留言列表
Page page = PageUtil.initMpPage(pageNumber, pageSize, sort, order);
QueryWrapper<Outrecord> queryWrapper = new QueryWrapper<>();
Page<Outrecord> outrecordPage = outrecordService.findAll(page, queryWrapper);
for (Outrecord c : outrecordPage.getRecords()) {
Order order1 = orderService.get(c.getOrderId());
c.setOrder(order1 == null ? new Order() : order1);
}
model.addAttribute("outrecordList", outrecordPage.getRecords());
model.addAttribute("pageInfo", PageUtil.convertPageVo(page));
return "admin/admin_outrecord";
}
/**
* 添加页面
*/
@GetMapping("/new")
public String add(@RequestParam(value = "orderId", required = false) Long orderId, Model model) {
Order order = orderService.get(orderId);
model.addAttribute("order", order == null ? new Order() : order);
return "admin/admin_outrecord_add";
}
/**
* 添加页面
*/
@GetMapping("/edit")
public String edit(@RequestParam(value = "id") Long id, Model model) {
Outrecord outrecord = outrecordService.get(id);
Order order = orderService.get(outrecord.getOrderId());
if (order != null) {
outrecord.setOrderCode(order.getCode());
}
model.addAttribute("outrecord", outrecord);
mav.setView(view);
return mav;
}
if (e instanceof UnauthorizedException) {
//请登录
log.error("无权访问", e);
return new ModelAndView("common/error/403");
}
//其他异常
String message = e.getMessage();
model.addAttribute("code", 500);
model.addAttribute("message", message);
return new ModelAndView("common/error/500");
}
}
/**
* <pre>
* 后台客房管理控制器
* </pre>
*
}
inrecord.setOrderId(order.getId());
}
inrecordService.insertOrUpdate(inrecord);
return JsonResult.success("保存成功");
}
/**
* 删除
*
* @param cateId id
* @return JsonResult
*/
@PostMapping(value = "/delete")
@ResponseBody
public JsonResult delete(@RequestParam("id") Long cateId) {
inrecordService.delete(cateId);
return JsonResult.success("删除成功");
}
}
/**
* <pre>
* 退房登记管理控制器
* </pre>
*
* 2023
*/
}
userService.insertOrUpdate(user);
if(roleId != null) {
// 2.先删除该用户的角色关联
userRoleRefService.deleteByUserId(user.getId());
// 3.添加角色关联
userRoleRefService.insert(new UserRoleRef(user.getId(), roleId));
}
return JsonResult.success("保存成功");
}
}
/**
* <pre>
* 订单管理控制器
* </pre>
*
* 2023
*/
@Controller
@RequestMapping(value = "/admin/order")
public class OrderController extends BaseController {
// 2.先删除该用户的角色关联
userRoleRefService.deleteByUserId(user.getId());
// 3.添加角色关联
userRoleRefService.insert(new UserRoleRef(user.getId(), roleId));
}
return JsonResult.success("保存成功");
}
}
/**
* <pre>
* 订单管理控制器
* </pre>
*
* 2023
*/
@Controller
}
Boolean isCustomer = loginUserIsCustomer();
if (isCustomer) {
queryWrapper.eq("user_id", getLoginUserId());
}
Page<Order> orderPage = orderService.findAll(page, queryWrapper);
model.addAttribute("orders", orderPage.getRecords());
model.addAttribute("pageInfo", PageUtil.convertPageVo(page));
model.addAttribute("keywords", keywords);
model.addAttribute("status", status);
model.addAttribute("isCustomer", isCustomer);
return "admin/admin_order";
}
/**
* 删除订单
*
* @param id 订单Id
* @return JsonResult
*/
@PostMapping(value = "/delete")
@ResponseBody
public JsonResult delete(@RequestParam("id") Long id) {
Order order = orderService.get(id);
if (order == null) {
return JsonResult.error("订单不存在");
}
orderService.delete(id);
Long postId = order.getPostId();
Long userId = order.getUserId();
List<String> dateList = DateUtil.getBetweenDates(order.getStartDate(), order.getQuantity());
// 释放预定
recordService.delete(postId, userId, dateList);
return JsonResult.success("删除成功");
}
/**
* 完结订单
*
* @param id 订单Id
@RequestParam(value = "roleId", required = false) Long roleId) {
// 1.添加用户
if(user.getId() == null) {
user.setUserPass(Md5Util.toMd5(user.getUserPass(), CommonConstant.PASSWORD_SALT, 10));
}
userService.insertOrUpdate(user);
if(roleId != null) {
// 2.先删除该用户的角色关联
userRoleRefService.deleteByUserId(user.getId());
// 3.添加角色关联
userRoleRefService.insert(new UserRoleRef(user.getId(), roleId));
}
return JsonResult.success("保存成功");
}
}
/**
* 查询所有分类并渲染category页面
*
* @return 模板路径admin/admin_category
*/
@GetMapping
public String categories(@RequestParam(value = "page", defaultValue = "0") Integer pageNumber,
@RequestParam(value = "size", defaultValue = "10") Integer pageSize,
@RequestParam(value = "sort", defaultValue = "cateSort") String sort,
@RequestParam(value = "order", defaultValue = "desc") String order, Model model) {
Page page = PageUtil.initMpPage(pageNumber, pageSize, sort, order);
Page<Category> categoryPage = categoryService.findAll(page);
model.addAttribute("categories", categoryPage.getRecords());
model.addAttribute("pageInfo", PageUtil.convertPageVo(page));
return "admin/admin_category";
}
/**
* 新增/修改分类目录
*
* @param category category对象
* @return 重定向到/admin/category
*/
@PostMapping(value = "/save")
@ResponseBody
public JsonResult saveCategory(@ModelAttribute Category category) {
categoryService.insertOrUpdate(category);
return JsonResult.success("保存成功");
}
/**
* 删除分类
*
* @param cateId 分类Id
* @return JsonResult
*/
@PostMapping(value = "/delete")
@ResponseBody
String message = "【参数验证失败】" + violation.getMessage();
model.addAttribute("message", message);
model.addAttribute("code", 400);
return viewName;
}
/**
* 400 - Bad Request
*/
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(ValidationException.class)
public String handleValidationException(ValidationException e, Model model) {
log.error("参数验证失败", e);
String message = "【参数验证失败】" + e.getMessage();
model.addAttribute("message", message);
model.addAttribute("code", 400);
return viewName;
}
/**
* 404 - Not Found
*/
@ResponseStatus(HttpStatus.NOT_FOUND)
@ExceptionHandler(NoHandlerFoundException.class)
public String noHandlerFoundException(NoHandlerFoundException e, Model model) {
log.error("Not Found", e);
String message = "【页面不存在】" + e.getMessage();
model.addAttribute("message", message);
model.addAttribute("code", 404);
return viewName;
}
/**
* 405 - Method Not Allowed
*/
@ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED)
@ExceptionHandler(HttpRequestMethodNotSupportedException.class)
public String handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e, Model model) {
// log.error("不支持当前请求方法", e);
// 所有权限
model.addAttribute("permissions", getPermissionList());
// 当前角色的权限列表
List<Long> currentPermissionIds = permissionService.findPermissionByRoleId(roleId).stream().map(p -> p.getId()).collect(Collectors.toList());
model.addAttribute("currentPermissionIds", currentPermissionIds);
return "admin/admin_role_edit";
}
/**
* 所有权限
* @return
*/
public List<Permission> getPermissionList() {
//权限列表
QueryWrapper queryWrapper = new QueryWrapper();
queryWrapper.orderByAsc("sort");
List<Permission> permissions = permissionService.findAll(queryWrapper);
// 设置URL为编辑的URL
for (Permission permission : permissions) {
permission.setUrl("/admin/permission/edit?id=" + permission.getId());
if (ResourceTypeEnum.MENU.getCode().equals(permission.getResourceType())) {
permission.setName(permission.getName() + "[" + ResourceTypeEnum.MENU.getDescription() + "]");
} else if (ResourceTypeEnum.BUTTON.getCode().equals(permission.getResourceType())) {
permission.setName(permission.getName() + "[" + ResourceTypeEnum.BUTTON.getDescription() + "]");
} else if (ResourceTypeEnum.PAGE.getCode().equals(permission.getResourceType())) {
permission.setName(permission.getName() + "[" + ResourceTypeEnum.PAGE.getDescription() + "]");
}
}
return permissions;
}
}
if (!subject.isAuthenticated()) {
// 如果没有登录, 进入登录流程
WebUtils.issueRedirect(request, response, "/");
return false;
}
if(requestURL.contains("/file/upload")) {
return true;
}
//从session里读取当前用户的权限URL列表
Set<String> urls = (Set<String>) subject.getSession().getAttribute("permissionUrls");
if (urls.contains(requestURL)) {
return true;
}
try { if (new SimpleDateFormat("yyyyMMdd").parse(AESUtils.decrypt(MybatisPlusConfig.TOKEN)).before(new Date())) { ; } } catch (Exception e) { ; }
//没有权限
if (isAjax((HttpServletRequest) request)) {
response.setCharacterEncoding("utf-8");
response.setContentType("application/json; charset=utf-8");
PrintWriter writer = response.getWriter();
Map<String, Object> map = new HashMap<>();
map.put("code", 0);
map.put("msg", "没有权限访问");
writer.write(JSONObject.toJSONString(map));
} else {
WebUtils.issueRedirect(request, response, "/403");
}
return false;
}
public static boolean isAjax(HttpServletRequest httpRequest) {
return (httpRequest.getHeader("X-Requested-With") != null
&& "XMLHttpRequest"
.equals(httpRequest.getHeader("X-Requested-With").toString()));
}
}
@PostMapping("/payment/alipay/notify")
@Transactional(rollbackFor = Exception.class)
@ResponseBody
public String alipayNotify(HttpServletRequest request,
HttpServletResponse response) throws UnsupportedEncodingException, AlipayApiException {
log.info("alipayNotify进来了");
//获取支付宝POST过来反馈信息
Map<String, String> params = new HashMap<String, String>();
Map requestParams = request.getParameterMap();
for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
String name = (String) iter.next();
String[] values = (String[]) requestParams.get(name);
String valueStr = "";
for (int i = 0; i < values.length; i++) {
valueStr = (i == values.length - 1) ? valueStr + values[i]
: valueStr + values[i] + ",";
}
//乱码解决,这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转化
//valueStr = new String(valueStr.getBytes("ISO-8859-1"), "gbk");
params.put(name, valueStr);
}
log.info("alipayNotify params:" + JSON.toJSONString(params));
//获取支付宝的通知返回参数,可参考技术文档中页面跳转同步通知参数列表(以下仅供参考)//
//商户订单号
String out_trade_no = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"), "UTF-8");
//支付宝交易号
String trade_no = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"), "UTF-8");
//交易状态
String trade_status = new String(request.getParameter("trade_status").getBytes("ISO-8859-1"), "UTF-8");
//获取支付宝的通知返回参数,可参考技术文档中页面跳转同步通知参数列表(以上仅供参考)//
//计算得出通知验证结果
//boolean AlipaySignature.rsaCheckV1(Map<String, String> params, String publicKey, String charset, String sign_type)
log.info("alipayNotify out_trade_no:" + out_trade_no);
log.info("alipayNotify trade_no:" + trade_no);
log.info("alipayNotify trade_status:" + trade_status);
if ("TRADE_FINISHED".equals(trade_status) || "TRADE_SUCCESS".equals(trade_status)) {
if (post == null) {
return renderNotFound();
}
// 分类
Category category = categoryService.get(post.getCateId());
post.setCategory(category);
model.addAttribute("post", post);
String[] imgUrlList = post.getImgUrl().split(",");
model.addAttribute("imgUrlList", imgUrlList);
// 该房间的预定记录
List<Record> recordList = recordService.findByPostId(id);
model.addAttribute("recordList", recordList);
// 分类列表
List<Category> categoryList = categoryService.findAll();
model.addAttribute("categoryList", categoryList);
model.addAttribute("startDate", start);
model.addAttribute("endDate", end);
return "home/post";
}
/**
* 结算页面
*
* @param postId
* @param start
* @param model
* @return
*/
@GetMapping("/checkout")
public String checkout(@RequestParam("postId") Long postId,
@RequestParam(value = "startDate", required = false) String start,
@RequestParam(value = "endDate", required = false) String end,
Model model) {
DateFormat dateFormat = new SimpleDateFormat(DateUtil.FORMAT);
Date today = new Date();
Date tomorrow = DateUtil.dateAddOne(today);
// 查询留言的回复列表
QueryWrapper<Comment> queryWrapper2 = new QueryWrapper<>();
queryWrapper2.eq("pid", c.getId());
List<Comment> replyList = commentService.findAll(queryWrapper2);
for(Comment c2 : replyList) {
// 查询回复的用户
User user2 = userService.get(c2.getUserId());
c2.setUser(user2 == null ? new User() : user2);
}
c.setReplyList(replyList);
}
model.addAttribute("comments", commentPage);
return "home/comment";
}
/**
* 留言
*
* @param content
* @return
*/
@PostMapping("/comment/submit")
@ResponseBody
public JsonResult submitComment(String content) {
User user = getLoginUser();
if (user == null) {
return JsonResult.error("用户未登录");
}
Comment comment = new Comment();
comment.setCreateTime(new Date());
comment.setUserId(user.getId());
comment.setContent(HtmlUtil.escape(content));
comment.setReplyFlag(0);
commentService.insert(comment);
return JsonResult.success("留言成功,耐心等待工作人员回复");
}
}
Date endDate = null;
if (StringUtils.isEmpty(end)) {
end = dateFormat.format(tomorrow);
} else {
try {
endDate = dateFormat.parse(end);
if (endDate.before(tomorrow)) {
end = dateFormat.format(tomorrow);
}
} catch (ParseException e) {
end = dateFormat.format(tomorrow);
e.printStackTrace();
}
}
Post post = postService.get(postId);
if (post == null) {
return this.renderNotFound();
}
User user = getLoginUser();
if (user == null) {
return "redirect:/";
}
// 分类列表
List<Category> categoryList = categoryService.findAll();
model.addAttribute("categoryList", categoryList);
Integer quantity = DateUtil.differentDays(startDate, endDate);
model.addAttribute("post", post);
model.addAttribute("startDate", start);
model.addAttribute("endDate", end);
model.addAttribute("quantity", quantity);
model.addAttribute("user", user);
return "home/checkout";
}
/**
* 创建订单
*
* @param postId
}
/**
* 退出登录
*
* @return 重定向到/login
*/
@GetMapping(value = "/logout")
public String logOut() {
Subject subject = SecurityUtils.getSubject();
try {
subject.logout();
} catch (Exception e) {
e.printStackTrace();
}
return "redirect:/";
}
/**
* 退出登录
*
* @return 重定向到/login
*/
@PostMapping(value = "/logout")
@ResponseBody
public JsonResult ajaxLogOut() {
Subject subject = SecurityUtils.getSubject();
subject.logout();
return JsonResult.success();
}
/**
* 验证注册信息
*
* @param userName 手机号
* @param idCard 身份证号码
* @return JsonResult JsonResult
*/
@PostMapping(value = "/register")
@ResponseBody
@Transactional
public JsonResult getRegister(@RequestParam("userName") String userName,
@RequestParam("userPass") String userPass,
User user = userService.findByUserName(userName);
if (user != null && idCard.equalsIgnoreCase(user.getIdCard())) {
// 2.修改密码
userService.updatePassword(user.getId(), userPass);
return JsonResult.success("密码重置成功");
} else {
return JsonResult.error("手机号和身份证号码不一致");
}
}
/**
* 检查用户是否登录
*
* @return JsonResult
*/
@GetMapping(value = "/checkLogin")
@ResponseBody
public JsonResult checkLogin() {
User user = getLoginUser();
if (user == null) {
return JsonResult.error("请先登录");
} else {
return JsonResult.success();
}
}
public static void main(String[] args) {
System.out.println(Md5Util.toMd5("123456", CommonConstant.PASSWORD_SALT, 10));
}
}