| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> Java知识库 -> 【毕业设计开源】基于SSM的实体商城商户在线租赁以及信息管理系统的设计与实现 -> 正文阅读 |
|
[Java知识库]【毕业设计开源】基于SSM的实体商城商户在线租赁以及信息管理系统的设计与实现 |
毕业时写的毕业设计,因为毕业后论文还有可能被复查,若大家的论文是原创,建议大家毕业几年后再进行开源 本设计包含了 多人在线聊天室,微信扫码支付,在线签字,PDF合同在线生成,商户评分,基本的商铺信息管理,合同管理,新闻和公告管理,用户管理等功能,具体功能请参看论文中截图 在我国城市化高速发展的今天,各种规模的商城相继出现。商城需要招商,进驻商家进行经营,商城的商铺需要出租和管理,商城各经营场所的招商信息,公告信息和活动信息的发布,进驻商家的各种信息的管理,都是人工手动进行管理的,既没有效率又容易出错,查找起来更是相当的麻烦。基于上述原因,需要借助于一款基于Web的商城商户信息管理系统,便于商铺的在线出租和对商城,商家,商铺的信息的查询与管理,有利于营造良好的商城营商环境,减轻商城管理人员的工作强度,因此设计一款基于Web的商城商户信息管理系统具有较好的实用价值。 IntelliJ IDEA:是java编程语言开发的集成环境。在业界被公认为最好的java开发工具,尤其在智能代码助手、代码自动提示、重构、J2EE支持、各类版本工具(git、svn等)、JUnit、CVS整合、代码分析、 创新的GUI设计等方面的功能可以说是非常优秀的。 SSM框架:由Spring,SpringMVC,MyBatis组成的框架集,是一个优秀的web项目框架,是继SSH之后,目前比较主流的Java EE企业级框架。Spring的目的就是用来替代更加重量级的的企业级Java技术,用来简化java的开发难度。SpringMVC是在Spring框架内置的MVC实现的一个子框架,可以轻松的实现MVC架构的程序设计。MyBatis 是一个持久层框架,他可以灵活的书写SQL语句,他让我们省略了大部分的JDBC代码、设置参数和获取结果集的代码。只使用简单的XML 和注解来映射基本数据类型、Map 接口和POJO 到数据库记录。 Maven:基于项目对象模型(POM project object model)的一个强大的项目管理工具,可以通过pom.xml文件配置智能的管理jar包 WebSocket:是一种在单个TCP连接上进行全双工通信的协议,允许服务端主动向客户端推送数据。本设计使用WebSocket技术实现聊天大厅的功能。 Druid连接池:阿里巴巴开源平台上的一个项目,能够提供强大的监控和扩展功能,可以替换DBCP和C3P0连接池,提供了一个高效、功能强大、可扩展性好的数据库连接池。 2 需求分析 2.1 可行性分析 2.1.1 技术可行性 SSM框架是spring MVC,spring和mabatis框架的整合,是标准的MVC模式,将整个系统划分为表现层,controller层,service层,DAO层四层,是一个成熟的企业级应用开发框架,而且在性能方面,要优于大部分编程语言,跨平台性更是实现了一次编译,到处运行。 2.1.2 经济可行性 传统模式的店铺租赁,需要提前查看选定商铺,然后联系出租方,约定时间后,需要双方同时到达同一个地方,仔细阅读合同后,进行签字并支付现金。然后管理者手动进行记录,这种方式既费时又费力。将挑选店铺,签订合同,支付等集合在一起的本系统,可以省去这些麻烦,并且管理者可以更好的进行管理。 2.1.3 操作可行性 系统使用常见的,用户熟悉的友好界面,使用常见的编辑框,按钮等组件,不仅界面美观,而且容易操作,只要是会操作电脑即可使用。本系统简化了许多的操作逻辑,大部分操作只需要点击鼠标即可操作完成。 2.2?流程分析 图3-1?用户流程图 图3-2?管理员流程图 基于Web的商城商户信息管理系统,采用MVC设计模式,整体使用Maven管理项目,后端使用SSM框架(Spring,SpringMVC,Mybits),前端使用HTML5,Layui,jQuery,CSS3,聊天大厅使用WebSocket技术,数据库使用MySQL配合阿里的Druid连接池,使用Spring声明式事务管理,设计并实现的一个集商铺在线出租,商铺搜索,合同在线手写签字,合同在线生成,在线支付,聊天大厅,入驻商家展示评分,用户管理,商家管理,商铺管理,首页Banner管理,商城公告活动的发布和管理,合同审核等功能的系统。 基于Web的商城商户信息管理系统主要分为三个部分 1.管理部分:超级管理员对管理员的管理,管理员对用户的管理,管理员对商铺的管理,管理员对商家的管理,管理员对合同的管理,管理员对活动和公告的管理。 2.用户部分:用户查看商铺,用户租赁商铺,用户签订合同,用户对租赁的商铺的管理,用户之间的聊天 3.顾客部分:顾客可以对商家进行评论留言和评分,可以浏览店铺排行榜 图2-1 系统功能图 图2-2?用户E-R图 图2-3?管理员E-R图 图2-4?商铺E-R图 图2-5?公告E-R图 图2-6?合同E-R图 图2-7?总E-R图
表2-2 管理员表(admin)
表2-3 商铺表(shops)
表2-4 合同表(contract)
表2-5 公告和活动表(announcement)
表2-6 轮播图信息表(banner)
表2-7 评论表(comment)
表2-8 聊天记录表(chatgroup)
3.1?用户部分 功能描述: 用户注册是用户通过手机号或者邮箱,注册为系统用户,填写用户名,手机时,使用Ajax后台判断是否已经注册过,并给出提示,避免重复注册。使用手机号码注册时,填入手机号,点击获取验证码按钮,验证码就会发送到手机,填入验证码即可注册成功。使用邮箱注册时,填入自己的邮箱地址,点击获取验证码,验证码就会发送到你的邮箱中,填入邮箱中的验证码即可注册成功。 图3-1?用户注册界面图 ? 图3-2?注册用户名已存在 Service层: public ResultInfo register(User user) { ???// 校验用户名 ???User u1 = userDao.findByUsername(user.getUsername()); ???if (u1 != null) { ??????return new ResultInfo(false, "用户名已存在"); ???} ???// 校验手机号 ???User u2 = userDao.findByTelephone(user.getTelephone()); ???if (u2 != null) { ??????return new ResultInfo(false, "手机号已存在"); ???} ???// 校验邮箱 ???User u3 = userDao.findByEmail(user.getEmail()); ???if (u3 != null) { ??????return new ResultInfo(false, "邮箱已存在..."); ???} ???// 密码加密 ???String md5Password = Md5Utils.encodeByMd5(user.getPassword()); ???user.setPassword(md5Password); ???// 保存用户 ???userDao.save(user); ???return new ResultInfo(true); } Controller层 // 用户注册 ????@RequestMapping(value ="/register",produces = "application/json;charset=utf-8") ????@ResponseBody ????public ResultInfo register(User user, String smscode,String emailcode,Integer type) { ????????if(type==1) { ????????????// 手机验证码 ????????????String sessionCode = (String) session.getAttribute("smsCode_" + user.getTelephone()); ????????????if (sessionCode == null || !sessionCode.equals(smscode)) { ????????????????return new ResultInfo(false, "手机验证码错误!"); ????????????} ????????}else if(type==2) ????????{ ??//邮箱验证码 ????????????String sessionCode = (String) session.getAttribute("emailCode_" + user.getEmail()); ????????????if (sessionCode == null || !sessionCode.equals(emailcode)) { ????????????????return new ResultInfo(false, "邮箱验证码错误!"); ????????????} ????????}else{ ????????????return new ResultInfo(false, "其他错误!"); ????????} ????????// 调用service完成注册 ?昵称默认为用户ID ????????user.setNickname("用户"+user.getUid()); ????????ResultInfo resultInfo = userService.register(user); ????????// 进行判断和页面跳转 ????????if (resultInfo.getCode()==0) { ????????????// 注册成功,清除session的验证码 session.removeAttribute("smsCode_"+user.getTelephone()); ????????????session.removeAttribute("emailCode_" + user.getEmail()); ????????????return new ResultInfo(true); ????????} else { ????????????// 注册失败 ????????????return resultInfo; ????????} } 功能描述: 用户使用注册的用户名和密码登录系统,或者使用注册时的手机号,通过短信验证码登录系统。登录页面使用Ajax方式后台异步发送请求,在收到结果后可以直接提示成功或失败,不需要再跳转到其他页面,使用手机登录时,输入注册时使用的手机号,然后点击获取验证码按钮,验证码短信就会发送到手机上,输入验证码即可登录到系统。忘记密码可以使用此功能登录。或者使用密码找回功能找回密码。 图3-3?用户账号登录界面图 ? 图3-4?用户手机登录界面图 Service层 密码登录: public ResultInfo pwdLogin(User user) { User u1 = userDao.findByUsername(user.getUsername()); if (null==u1) { return new ResultInfo(false, "此用户不存在"); } String md5Pwd = Md5Utils.encodeByMd5(user.getPassword()); if (!md5Pwd.equals(u1.getPassword())) { return new ResultInfo(false, "密码不正确"); } return new ResultInfo(true, "登录成功", u1); } 短信验证码登录: public ResultInfo smsLogin(String telephone) { User u1 = userDao.findByTelephone(telephone); if (u1 == null) { return new ResultInfo(false, "此手机号未注册"); } return new ResultInfo(true, "登录成功", u1); } Controller层 密码登录: /** ?????* 密码登录 ?????* @param user 用户信息 ?????* @param code 图形验证码 ?????* @return ResultInfo ?????*/ ????@RequestMapping(value = "/pwdLogin",produces = "application/json;charset=utf-8") ????@ResponseBody ????public ResultInfo pwdLogin(User user,String code) ????{ ????????String sessionCode = session.getAttribute("imgCode").toString(); ????????if(code!=null && !"".equals(code) && code.toUpperCase().equals(sessionCode)) { ????????????ResultInfo resultInfo = userService.pwdLogin(user); ????????????if (resultInfo.getCode()==0) { ????????????????session.setAttribute("User", resultInfo.getData()); ????????????????session.removeAttribute("imgCode"); ????????????} ????????????return resultInfo; ????????}else{ ????????????return new ResultInfo(false,"验证码错误!"); ????????} } 手机验证码登录: /** ?????* 手机登录 ?????* @param telephone 电话 ?????* @param smscode 验证码 ?????* @return ResultInfo ?????*/ ????@RequestMapping(value = "/smsLogin",produces = "application/json;charset=utf-8") ????@ResponseBody ????public ResultInfo smsLogin(String telephone,String smscode) ????{ ????????String code = (String) session.getAttribute("smsCode_" + telephone); ????????if(code!=null && !"".equals(code) && code.equals(smscode)) { ????????????ResultInfo resultInfo = userService.smsLogin(telephone); ????????????// 写入session ????????????if (resultInfo.getCode()==0) { ????????????????session.setAttribute("User", resultInfo.getData()); ????????????????session.removeAttribute("smsCode_"+telephone); ????????????} ????????????return resultInfo; ????????}else{ ????????????return new ResultInfo(false,"验证码错误!"); ????????} ????} 功能描述: 用户忘记密码后通过此功能可找回密码,可以通过注册时使用的手机找回,也可以使用注册时使用的邮箱找回,在使用手机找回时,输入注册时使用的手机号,点击获取验证码按钮,手机将会收到一条验证码信息,输入验证码后进入下一步,通过邮箱找回时,点击获取验证码按钮,邮箱将会收到验证码,输入验证码信息也可进入下一步。 图3-5?找回密码界面图 输入验证码后,就来到了此界面,自动查询出手机或邮箱绑定的用户名,防止用户因忘记用户名而无法登录,然后在下方输入新的密码,确认新的密码,点击重置密码按钮即可重置完成密码操作。 图3-6?确认找回密码界面图 Service层 public User forget(User user) { if(user.getTelephone()!=null) { return userDao.findByTelephone(user.getTelephone()); }else if(user.getEmail()!=null) { return userDao.findByEmail(user.getEmail()); } return null; } Controller层 ????@RequestMapping("/forget") ????public String forget(User user, String smscode,String emailcode,Integer type) { ????????Integer smsId = 1; ????????Integer emailId = 2; ????????if(user==null||type==null) ????????{ ????????????request.setAttribute("errormsg","非法访问!"); ????????????return "/error.jsp"; ????????} ????????if(type.equals(smsId)) { ????????????// 手机验证码 ????????????String sessionCode = (String) session.getAttribute("smsCode_" + user.getTelephone()); ????????????if (sessionCode == null || !sessionCode.equals(smscode)) { ????????????????request.setAttribute("errormsg","手机验证码错误!"); ????????????????return "/error.jsp"; ????????????} ????????}else if(type.equals(emailId)) ????????{ ??//邮箱验证码 ????????????String sessionCode = (String) session.getAttribute("emailCode_" + user.getEmail()); ????????????if (sessionCode == null || !sessionCode.equals(emailcode)) { ????????????????request.setAttribute("errormsg","邮箱验证码错误!"); ????????????????return "/error.jsp"; ????????????} ????????}else{ ????????????request.setAttribute("errormsg","其他错误!"); ????????????return "/error.jsp"; ????????} ????????session.setAttribute("fUser",userService.forget(user)); ????????return "/forgetChange.jsp"; ????} ????/** ?????* 找回密码第二步,改密码 ?????* @param password 新密码 ?????* @return ResultInfo ?????*/ ????@RequestMapping(value = "/forgetChange", produces = "application/json;charset=utf-8") ????@ResponseBody ????public ResultInfo forgetChange(String password,String rePassword) { ????????if(!password.equals(rePassword)) { ????????????return new ResultInfo(false,"两次密码不一致!"); ????????} ????????User user = (User) session.getAttribute("fUser"); ????????if(user==null) ????????{ ????????????return new ResultInfo(false,"非法请求!"); ????????} ????????user.setPassword(Md5Utils.encodeByMd5(password)); ????????userService.updateInfo(user); ????????session.removeAttribute("fUser"); ????????return new ResultInfo(true); } 3.2?个人中心 功能描述: 在此页面,可以查看和修改用户的基本信息。包括姓名,手机号,邮箱,性别,身份证等信息,采用Ajax的方式提交到服务器,可以在页面上通过信息框提示是否更新成功,不必跳转页面。 图3-7?个人信息界面图 Controller层 ????@RequestMapping(value = "/updateInfo", produces = "application/json;charset=utf-8") ????@ResponseBody ????public ResultInfo updateInfo(User user){ ????????userService.updateInfo(user); ????????//重新写入session ????????User u1 = userService.findByUid(user.getUid()); ????????session.setAttribute("User", u1); ????????return new ResultInfo(true); } 功能描述: 更换头像功能,可以更换用户的头像图片,首先点击上传头像按钮,弹出选择文件对话框,选中要上传的头像图片,点击确定,方框中就会显示选择的图片,此时,头像图片并未上传至服务器,而是读取了文件的内容,将其显示在浏览器中,当点击提交头像时,图片才被送到服务器中保存。 图3-8?更换头像界面图 Controller层 ????@RequestMapping(value = "/updatePic", produces = "application/json;charset=utf-8") ????@ResponseBody ????public ResultInfo updatePic(MultipartFile file) throws IOException { ????????if (!file.isEmpty()) { ????????????User user = (User) session.getAttribute("User"); ????????????if (user != null) { ????????????????String picPath = "/pic/" + user.getUid() + ".jpg"; ????????????????File myFile = new File(request.getServletContext().getRealPath("/") + picPath); ????????????????file.transferTo(myFile); ????????????????user.setPic(picPath); ????????????????userService.updateInfo(user); ????????????????//重新写入session ????????????????User u1 = userService.findByUid(user.getUid()); ????????????????session.setAttribute("User", u1); ????????????????return new ResultInfo(true); ????????????} ????????????return new ResultInfo(false); ????????} ????????return new ResultInfo(false); } 前端 layui.use('upload', function(){ var $ = layui.jquery ????????,upload = layui.upload; //头像上传 var uploadInst = upload.render({ ??elem: '#test1' ??,url: '${pageContext.request.contextPath}/user/updatePic' //上传接口 ??,bindAction:'#test2'//执行文件上传动作 ??,auto: false ??,choose:function (obj) { ????obj.preview(function(index, file, result){ ??????$('#demo1').attr('src', result); //图片转为base64赋给src属性 ????}); ??} ??,done: function(res){ ????//如果上传失败 ????if(res.code > 0){ ??????return layer.msg('上传失败'); ????} ????//上传成功 ????$('#touxiang').attr('src', '${pageContext.request.contextPath}/${User.pic}?'+new Date().getTime()); ????$('#htouxiang').attr('src', '${pageContext.request.contextPath}/${User.pic}?'+new Date().getTime()); ????return layer.msg('上传成功'); ??} ??,error: function(){ ????//失败重传 ????var demoText = $('#demoText'); ????demoText.html('<span style="color: #FF5722;">上传失败</span> <a class="layui-btn layui-btn-xs demo-reload">重试</a>'); ????demoText.find('.demo-reload').on('click', function(){ ??????uploadInst.upload(); ????}); ??} }); }) 功能描述: 用户的修改密码功能,输入自己的旧密码,然后输入新密码,确认新密码,点击确认修改按钮,即可成功修改密码。修改密码后,登录信息将失效,需要重新登录,自动打开登录窗口,并提示用户重新登录。 图3-9?修改密码界面图 Controller层 @RequestMapping(value = "/updatePass", produces = "application/json;charset=utf-8") @ResponseBody public ResultInfo updatePass(String oldPassword,String newPassword,String againPassword) { ????ResultInfo result; ????if (!newPassword.equals(againPassword)) { ????????result = new ResultInfo(false, "两次密码输入不一致!"); ????} else { ????????User user = (User) session.getAttribute("User"); ????????if (user != null) { ????????????if (user.getPassword().equals(Md5Utils.encodeByMd5(oldPassword))) { ????????????????if (oldPassword.equals(newPassword)) { ????????????????????result = new ResultInfo(false, "旧密码不能与新密码一致!"); ????????????????} else { ????????????????????user.setPassword(Md5Utils.encodeByMd5(newPassword)); ????????????????????userService.updateInfo(user); ????????????????????session.removeAttribute("User"); ????????????????????result = new ResultInfo(true); ????????????????} ????????????} else { ????????????????result = new ResultInfo(false, "旧密码输入错误!"); ????????????} ????????} else { ????????????result = new ResultInfo(false, "非法请求!"); ????????} ????} ????return result; } 功能描述: 用户合同管理功能,在此页面中,可以看到当前用户所签订的所有合同信息,包括(合同编号,合同商铺,开始时间,终止时间,成交价格,合同状态),并且可以下载合同源文件。合同状态分别为 未付款,审核中,已生效,已过期 四个状态。由系统内的定时任务自动管理,每十分钟刷新一次状态。在已生效和已过期状态时,可以下载合同,未支付状态时,可以跳转到付款页面。 图3-10?我的合同界面图 Controller层 ????@RequestMapping("/userHetong") ????public String userHetong(){ ????????User user = (User) session.getAttribute("User"); ????????if (user == null){ ????????????return "redirect:/index.jsp"; ????????}else{ ????????????List<Contract> contracts = contractService.findByUserid(user.getUid()); ????????????request.setAttribute("contracts",contracts); ????????????return "/home_hetong.jsp"; ????????} } 功能描述: 用户商铺管理功能,在此页面中,可以看到用户正在经营的商铺信息,包括商铺编号,商铺名称,商铺位置,商铺面积 ,商铺类型,营业时间 ,商铺评分等信息。评分由顾客评价后给出的评分根据一定算法进行计算,用户只能看到分数。同时,用户可以编辑商铺的信息,包括名称,类型,营业时间,简介,详细介绍,封面图,图集等内容。在租赁商铺后可以更新为自己所经营的信息。 图3-11?我的商铺界面图 Controller层 ????@RequestMapping("/userShop") ????public String userShop(){ ????????User user = (User) session.getAttribute("User"); ????????if (user == null){ ????????????return "redirect:/index.jsp"; ????????}else{ ????????????List<Shop> shops = shopService.findShopsByUid(user.getUid()); ????????????request.setAttribute("shops",shops); ????????????return "/home_shop.jsp"; ????????} } ????@RequestMapping("/editShop/{sid}") ????public String editShop(@PathVariable("sid") Integer sid) ????{ ????????User user = (User) session.getAttribute("User"); ????????if(user==null) ????????{ ????????????return "/Login.jsp"; ????????} ????????Shop shop = shopService.findShopsBySid(sid); ????????if(shop.getUserid()==user.getUid()) ????????{ ????????????request.setAttribute("Shop",shop); ????????????return "/home_shop_edit.jsp"; ????????} ????????return null; ????} ????@RequestMapping(value = "/setShop", produces = "application/json;charset=utf-8") ????@ResponseBody ????public ResultInfo setShop(Shop shop){ ????????User user = (User) session.getAttribute("User"); ????????if(user==null) ????????{ ????????????return new ResultInfo(false); ????????} ????????return shopService.update(shop); ????} 3.3?商铺租赁 功能描述: 展示当前正在出租的商铺信息,包括位置,价格,面积,详细介绍等。可选择租赁期限,点击立即租赁,即可进入商铺租赁流程。若当前未登录账号,则弹出账号登录模态框,登录账号后依然停留在本页面,可以继续操作。 图3-12?商铺列表页图 图3-13?商铺详情页图 ShopsController层 @RequestMapping("/rent") public String rent(@RequestParam(defaultValue = "1") Integer pageNum, @RequestParam(defaultValue = "12") Integer pageSize) { ????PageBean pageBean = shopsService.listRent(pageNum, pageSize); ????request.setAttribute("pb", pageBean); ????return "/rent_list.jsp"; } ShopSevice层 public PageBean listRent(Integer pageNum, Integer pageSize) { Integer total = shopsDao.findRentCount(); Integer index = (pageNum - 1) * pageSize; List<Shop> list = shopsDao.findRentByPage(index, pageSize); return new PageBean(total, list, pageNum, pageSize); } 前端 <div class="layui-row layui-col-space10"> ??<s:if test="${empty pb.data}"> ????<div style="text-align: center;padding-top: 50px">暂无商家</div> ??</s:if> ??<s:forEach items="${pb.data}" var="shop"> ????<div class="layui-col-md3 layui-col-sm4"> ??????<div class="item"> ????????<a href="${pageContext.request.contextPath}/detail/${shop.sid}"> ??????????<img width="100%" height="200px" src="${pageContext.request.contextPath}${shop.pic}"> ????????</a> ????????<a href="${pageContext.request.contextPath}/detail/${shop.sid}"> ??????????<div style="height:47px;padding: 2px"> ????????????<p class="text">${shop.sname}</p> ????????????<div class="layui-row"> ??????????????<div class="layui-col-xs8 layui-col-md9 layui-col-lg10"> ????????????????<b>${shop.stime}</b> ??????????????</div> ??????????????<div class="layui-col-xs4 layui-col-md3 layui-col-lg2" style="text-align: right;color: red"> ????????????????<b>${shop.score}</b> ??????????????</div> ????????????</div> ??????????</div> ????????</a> ??????</div> ????</div> ??</s:forEach> </div> 功能描述: 租赁商铺时,选择好商铺和租赁时间,点击立即租赁后,即可进入在线签署租赁合同页面,生成合同内容,用户在详细阅读合同后,在下方签字处手写签字,然后点击提交,即可完成签署合同。用户提交后,后台使用itext组件,生成PDF文档,并将签名插入到指定位置,保存在/pdf目录下。同时修改商铺状态为已被租赁,然后跳转到支付页面,用户进行支付操作。若用户未完成支付操作,没有商铺操作权限,若用户10分钟后仍未完成支付,商铺将被系统回收,重置为租赁状态。 图3-14?签署合同页图 Controller层 @RequestMapping("/create") public String nameimg(Integer sid,String starttime,String endtime, String namepic,Double price) { ????User user = (User) session.getAttribute("User"); ????if(user!=null && !"".equals(namepic)) ????{ ????????Shop shop = shopsService.findShopsBySid(sid); ????????String picPath = "upload\\" + Md5Utils.encodeByMd5(namepic) + ".png"; ????????String realPicPath = request.getServletContext().getRealPath("/") + picPath; ????????Base64Util.base64ToImage(namepic,realPicPath); ????????String path = "pdf/"+UUID.randomUUID()+".pdf"; ????????String savepath = request.getServletContext().getRealPath("/") +path; ????????Contract contract = new Contract(); ????????contract.setId(UuidUtils.getUuid()); ????????contract.setName(user.getNickname()); ????????contract.setUserid(user.getUid()); ????????contract.setShopid(shop.getSid()); ????????contract.setStarttime(starttime); ????????contract.setEndtime(endtime); ????????contract.setContract(path); ????????contract.setState(0); ????????contract.setPrice(price); ????????/*添加合同记录 并 修改店铺状态和userid*/ ????????contractService.add(contract,shop,user); ????????try{ ????????????PdfUtil.createPDF(user.getNickname(),shop.getLocation(),shop.getArea(),starttime,endtime,price.toString(),NumToCnUtil.toChinese(price.toString()),realPicPath,savepath); ????????}catch (Exception e) ????????{ ????????????request.setAttribute("errormsg","合同生成失败!"); ????????????return "/error.jsp"; ????????} ????????return "redirect:/contract/pay/"+contract.getId(); ????} ????return "/error.jsp"; } Service层 public void add(Contract contract, Shop shop, User user) { contractDao.save(contract); shop.setState(2); shop.setUserid(user.getUid()); shopsDao.update(shop); } 前端 $(function () { ??$("#box").jSignature();//初始化画板 }); layui.use('form', function(){ ??var form = layui.form; ??//监听表单提交 ??form.on('submit(tijiao)', function (data) { ????var datapair = $("#box").jSignature("getData","image"); ????$("#namepic").val(datapair[1]); ????return true; ??}); }); function chongxie(){ ??$("#box").jSignature("reset"); ??$("#image").attr('src',''); } 功能描述: 本功能调用微信支付完成,签完合同后,弹出支付页面,用户使用手机扫码在线支付。在支付时,后台使用定时器每秒钟查询一次支付状态,若支付成功,跳转到成功页面,在线支付完成。若超时10分钟未支付,页面提示超时,订单将被删除,商铺被回收,重新置为租赁状态。若支付成功,商铺进入审核状态,后台管理员审核通过后,即可正常使用。 图3-15?在线支付页图 Controller层 @RequestMapping("/pay/{id}") public String pay(@PathVariable("id") String id) { ????Contract contract = contractService.findByid(id); ????if(contract!=null) ????{ ????????String payurl = PayUtils.createOrder(id,contract.getPrice()*100); //支付金额 单位:分 ????????request.setAttribute("payUrl",payurl); ????????request.setAttribute("contract",contract); ????????return "/pay.jsp"; ????}else{ ????????request.setAttribute("errormsg","订单不存在!"); ????????return "/error.jsp"; ????} } /** ?* 支付成功回调 ?* @return ?* @throws Exception ?*/ @RequestMapping(value = "/payNotify", produces = MediaType.APPLICATION_XML_VALUE) @ResponseBody public Map<String, String> payNotify() throws Exception { ????ServletInputStream inputStream = request.getInputStream(); ????XmlMapper xmlMapper = new XmlMapper(); ????Map param = xmlMapper.readValue(inputStream, Map.class); ????contractService.updateState(param); ????Map<String, String> result = new HashMap<>(10); ????result.put("return_code", "SUCCESS"); ????result.put("return_msg", "OK"); ????return result; } /** ?* 查看支付状态 ?*/ @RequestMapping(value = "/checkPay",produces = "application/json;charset=utf-8") @ResponseBody public ResultInfo checkPay(String id) { ????Contract contract = contractService.findByid(id); ????if (contract.getState() == 1) { ????????return new ResultInfo(true); ????} else { ????????return new ResultInfo(false); ????} } Service层 public void updateState(Map param) { //支付成功通知的订单号 String orderId = (String) param.get("out_trade_no"); Contract contract = contractDao.findById(orderId); contract.setState(3); contractDao.update(contract); } 前端 生成二维码 ??var qr = window.qr = new QRious({ ????element: document.getElementById('qrious'), ????size: 300, ????value: '${payUrl}' ??}); 10分钟倒计时 var num=60*10; setInterval(function () { ??// 发送ajax请求,查询是否支付成功 ??var url = '${pageContext.request.contextPath}/contract/checkPay?id=${contract.id}'; ??$.get(url, function (resp) { ????if (resp.code==0) { ??????location.href = '${pageContext.request.contextPath}/success.jsp'; ????} ??}); ??num--; ??$('#jishiqi').html(parseINT(num/60)+'分'+num%60+'秒后失效,请及时付款!') }, 1000); 超时跳转到错误页 setTimeout(function () { ??location.href = '${pageContext.request.contextPath}/error.jsp'; }, 600000); 3.4?商家展示 功能描述: 列表页展示入驻的全部商家,分页显示,按照评分从高到低排名,也可以按商家分类展示。详情页展示已经在本商城入驻的商家信息,包括简介,商家位置,分类,营业时间,商家评分,详细介绍等。 图3-16?商家列表页图 图3-17?商家详情页图 Controller层 商家列表 @RequestMapping("/shop") public String shop(@RequestParam(defaultValue = "1") Integer pageNum, @RequestParam(defaultValue = "12") Integer pageSize,@RequestParam(defaultValue = "-1") Integer type) { ????PageBean pageBean; ????if(type==-1) ????{ ????????pageBean = shopsService.listShop(pageNum, pageSize); ????}else{ ????????pageBean = shopsService.listShop(pageNum, pageSize,type); ????} ????request.setAttribute("pb", pageBean); ????return "/shop_list.jsp"; } 商家详情 @RequestMapping("/detail/{sid}") public String detail(@PathVariable("sid") Integer sid) { ????Shop shop = shopsService.findShopsBySid(sid); ????request.setAttribute("shop", shop); ????if(shop.getState()==1) ????{ ????????List<Comment> comments = commentService.findByShopid(sid); ????????request.setAttribute("Comments", comments); ????????return "/shop_detail.jsp"; ????}else{ ????????return "/rent_detail.jsp"; ????} } Service层 public PageBean listShop(Integer pageNum, Integer pageSize) { Integer total = shopsDao.findShopCount(); Integer index = (pageNum - 1) * pageSize; List<Shop> list = shopsDao.findShopByPage(index, pageSize); return new PageBean(total, list, pageNum, pageSize); } 功能描述: 顾客可以对已经入驻的商家进行留言评论和评分,商家评分根据顾客的评分按照评分公式自动计算,商家无法修改。若评分小于等于1星,商家将被警告。 图3-18?商家详情页评论图 Controller层 @RequestMapping(value="/shop/comment",produces = "application/json") @ResponseBody public ResultInfo comment(Comment comment) { ????commentService.save(comment); ????return new ResultInfo(true); } Service层 public void save(Comment comment) { ????comment.setTime(new Date()); ????commentDao.save(comment); } 前端 <form class="layui-form layui-form-pane" action=""> ??<input name="shopid" type="hidden" value="${shop.sid}"> ??<input id="score" name="score" type="hidden" value="5"> ??<input id="content" name="content" type="hidden"> ??<div class=""> ????<div id="myEditor" style="display: none;"></div> ????<div class="layui-inline"> ??????<label class="layui-form-label">姓名:</label> ??????<div class="layui-input-inline"> ????????<input style="width: 150px" name="name" lay-verify="required" autocomplete="off" class="layui-input"> ??????</div> ????</div> ????<div class="layui-inline"> ??????<label style="margin-top: 3px" class="layui-form-label">评分:</label> ??????<div ?id="myPingFen"></div> ????</div> ????<div style="width: 200px;float:right" id="send" class="layui-btn" lay-submit lay-filter="pinglun-tijiao" >提交</div> ??</div> </form> <br><br> <div class="layui-card-header"> ??评论列表 </div> <s:if test="${empty Comments}"> ??<div id="noping" class="layui-card"> ????<div class="layui-card-body">暂无评论,快来评论吧!</div> ??</div> </s:if> <div id="pinglist"> <s:forEach items="${Comments}" var="Comment"> ??<div class="layui-card"> ????<div class="layui-card-header"><b>${Comment.name}</b><img src="${pageContext.request.contextPath}/imgs/star/${Comment.score}.png" alt=""> ??( ${Comment.score}分 ) ?????<i style="color: #BBBBBB">${Comment.time}</i></div> ????<div class="layui-card-body">${Comment.content}</div> ??</div> </s:forEach> </div> 3.5?聊天大厅 聊天大厅使用WebSocket技术,实现聊天信息的实时传输。 图3-19?聊天大厅图 功能描述: 此处配置WebSocket的监听路径,聊天大厅连接此处监听的路径,可以向此路径发送数据,服务器监听向此路径发送的数据,收到数据后进行处理。 WebSocketConfig 配置 public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { registry.addHandler(webSocketMessageHandler(),"/websocket").addInterceptors(new MyWebSocketHandshakeInterceptor()); registry.addHandler(webSocketMessageHandler(), "/sockjs/websocket").addInterceptors(new MyWebSocketHandshakeInterceptor()).withSockJS(); } 功能描述: 在websocket连接前,对websocket的session进行处理,添加httpsession里的有关用户登录认证的字段:User,以便在聊天大厅获取用户名等信息,将websocket的用户和网站用户联系起来。 WebSocketHandshakeInterceptor?握手拦截器 public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, ???????????????????????????????Map<String, Object> attributes) throws Exception { ????//Before Handshake--websocket 握手之前的方法 ????if (request instanceof ServletServerHttpRequest) { ????????ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) request; ????????HttpSession httpSession = servletRequest.getServletRequest().getSession(false); ????????if (httpSession != null) { ????????????attributes.put("httpsession",httpSession); ????????????User user = (User) httpSession.getAttribute("User"); ????????????if (user != null) { ????????????????attributes.put("userid", String.valueOf(user.getUid())); ????????????}else{ ????????????????attributes.put("userid", "0"); ????????????} ????????} ????} ????return super.beforeHandshake(request, response, wsHandler, attributes); } 功能描述: 处理收到的聊天消息,定义了自己的发送规则,服务器向客户端发送消息时,使用mtype标志,mtype为1时,表示用户发送聊天消息。mtype为2时,表示系统发送提示信息。mtype为3时,表示用户上线。mtype为4时,表示用户下线。mtype为5时,表示发送在线用户列表。客户端向服务器发送消息时,使用ttype标志,ttype值为“消息”时,表示发送的是聊天消息。 WebSocketMessageHandler?消息处理器 @Component public class WebSocketMessageHandler extends TextWebSocketHandler { ????@Autowired private ChatGroupService chatGroupService; ????private static final Map<String, ChatUser> USERS = new ConcurrentHashMap<>(); ????/** ?????* 建立连接后的处理 ?????*/ ????@Override ????public void afterConnectionEstablished(WebSocketSession session) throws Exception { ????????HttpSession httpsession = (HttpSession) session.getAttributes().get("httpsession"); ????????if(httpsession!=null) ????????{ ????????????User user = (User) httpsession.getAttribute("User"); ????????????if(user!=null) { ????????????????ChatUser chatuser = new ChatUser(); ????????????????chatuser.setUser(user); ????????????????chatuser.setSession(session); ????????????????USERS.put(String.valueOf(chatuser.getUser().getUid()), chatuser); ????????????????putChatList(String.valueOf(chatuser.getUser().getUid())); ????????????????putOnline(chatuser); ????????????} ????????} ????????super.afterConnectionEstablished(session); ????} ????/** ?????* 向所有用户发送用户下线 ?????* @param cu ChatUser ?????*/ ????private void putOffline(ChatUser cu) ????{ ????????HashMap<String,Object> map = new HashMap<>(10); ????????map.put("mtype",4); ????????map.put("username",cu.getUser().getUsername()); ????????sendMessageToAllUsers(JSONUtils.toJSONString(map)); ????} ????/** ?????* 向所有用户发送用户上线 ?????* @param cu ChatUser ?????*/ ????private void putOnline(ChatUser cu) ????{ ????????HashMap<String,Object> map = new HashMap<>(10); ????????map.put("mtype",3); ????????map.put("username",cu.getUser().getUsername()); ????????map.put("nickname",cu.getUser().getNickname()); ????????map.put("pic",cu.getUser().getPic()); ????????sendMessageToAllUsers(JSONUtils.toJSONString(map),String.valueOf(cu.getUser().getUid())); ????} ????/** ?????* 向指定用户发送在线用户列表 ?????* @param uid 用户ID ?????*/ ????private void putChatList(String uid){ ????????Map<String,Object> map = new HashMap<>(10); ????????Map<String,Object> map2 = new HashMap<>(10); ????????map.put("mtype",5); ????????map.put("count",USERS.size()); ????????Integer i=0; ????????for(Map.Entry<String, ChatUser> entry : USERS.entrySet()){ ????????????Map<String,Object> map3 = new HashMap<>(10); ????????????map3.put("nickname",entry.getValue().getUser().getNickname()); ????????????map3.put("username",entry.getValue().getUser().getUsername()); ????????????map3.put("pic",entry.getValue().getUser().getPic()); ????????????map2.put(String.valueOf(i),map3); ????????????i++; ????????} ????????map.put("data",map2); ????????String json = ?JSONUtils.toJSONString(map); ????????try { ????????????USERS.get(uid).getSession().sendMessage(convertWebSocketTextMessage(json)); ????????} catch (IOException e) { ????????????e.printStackTrace(); ????????} ????} ????/** ?????* 连接关闭后的处理 ?????* @param session 被关闭的session ?????* @param status 状态 ?????* @throws Exception 发送失败异常 ?????*/ ????@Override ????public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception { ????????String userid = (String) session.getAttributes().get("userid"); ????????//通知全部用户有人下线 ????????if(userid!=null) ????????{ ????????????putOffline(USERS.get(userid)); ????????????USERS.remove(userid); ????????} ????????super.afterConnectionClosed(session, status); ????} ????/** ?????* 文本消息处理 ?????* @param session 发送者session ?????* @param message 发送内容 ?????*/ ????@Override ????protected void handleTextMessage(WebSocketSession session, TextMessage message){ ????????String typeMsg = "消息"; ????????String userid = (String) session.getAttributes().get("userid"); ????????String payload = message.getPayload(); ????????@SuppressWarnings("unchecked") ????????HashMap<String, Object> map = (HashMap<String, Object>) JSONUtils.parse(payload); ????????String ttype = (String) map.get("ttype"); ????????if(typeMsg.equals(ttype)) ????????{ ????????????Date d = new Date(); ????????????SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); ????????????map.put("date",sdf.format(d)); ????????????map.put("mtype",1); ????????????putMessages(userid,map); ????????} ????} ????/** ?????* 向指定用户发送消息 ?????* @param userid 用户id ?????* @param map 消息 ?????*/ ????private void putMessages(String userid, Map<String,Object> map) ????{ ????????//保存聊天记录到数据库 ????????ChatHistory chatHistory = new ChatHistory(); ????????chatHistory.setNickname((String) map.get("nickname")); ????????chatHistory.setUsername((String) map.get("username")); ????????chatHistory.setPic((String) map.get("pic")); ????????chatHistory.setContent((String) map.get("content")); ????????chatHistory.setDate((String) map.get("date")); ????????chatGroupService.save(chatHistory); ????????for(Map.Entry<String, ChatUser> entry : USERS.entrySet()){ ????????????WebSocketSession session = entry.getValue().getSession(); ????????????if (session.isOpen()) { ????????????????try { ????????????????????map.put("isSelf",entry.getKey().equals(userid)); ??????????????????session.sendMessage(convertWebSocketTextMessage(JSONUtils.toJSONString(map))); ????????????????} catch (IOException e) { ????????????????????e.printStackTrace(); ????????????????} ????????????} ????????} ????} ????private TextMessage convertWebSocketTextMessage(String textMessage) { ????????return new TextMessage(textMessage); ????} ????/** ?????* 发送消息给所有用户 ?????* @param textMessage 消息 ?????*/ ????private void sendMessageToAllUsers(String textMessage) { ????????for(Map.Entry<String, ChatUser> entry : USERS.entrySet()){ ????????????WebSocketSession session = entry.getValue().getSession(); ????????????if (session.isOpen()) { ????????????????try { ????????????????????session.sendMessage(convertWebSocketTextMessage(textMessage)); ????????????????} catch (IOException e) { ????????????????????e.printStackTrace(); ????????????????} ????????????} ????????} ????} } 功能描述: 聊天大厅页面连接服务器,然后可以发送消息给服务器。使用两种连接方式,一种是HTML5的Websocket连接,若用户的浏览器不知吹HTML5,则使用SockJS来模拟Websocket连接,这样就可以兼容多种浏览器。因为Websocket无活动60秒后会自动断开连接,所以前端使用javascript设置一个定时器,每55秒发送一次心跳数据,用来保持Websocket连接,服务器无需回复这个信息。 var?wsPath='ws://${pageContext.request.getServerName()}:${pageContext.request.getServerPort()}${pageContext.request.contextPath}/'; var socket; try { ????if ('WebSocket' in window) { ????????socket = new WebSocket(wsPath+"websocket"); ????} else { ????????socket = new SockJS(wsPath+"sockjs/websocket"); ????} } catch (e) { ????console.log('创建连接失败!'+e); } socket.onmessage=function(ev){ var obj = eval('('+ev.data+')'); ?????addMessage(obj) }; setInterval(function () { ????var str = JSON.stringify({ ????????ttype:'心跳' ????}); ????socket.send(str); },55000); 功能描述: 用户在输入框输入内容后,点击发送按钮,聊天大厅使用JS判断用户是否登录,消息内容是否为空,通过后把消息内容拼接成json格式,然后通过Websocket发送给服务器。消息可以支持文字,表情,超链接,图片等格式。 $("#send").click(function(){ ????var u = '${User}'; ????if(u=='') { ????????layer.msg("您不能发送消息,请登录!"); ????????return false; ????} ????var txt = layedit.getContent(index); ????if(txt==''||txt==' ') { ????????layer.msg("消息不能为空!"); ????????return false; ????} ????var str = JSON.stringify({ ????????nickname:nickname, ????????username:username, ????????pic:pic, ????????content:txt, ????????ttype:'消息' ????}); ????if(isEmpty(txt)) ????{ ????????layer.msg("没有输入内容!"); ????}else { ????????socket.send(str); ????????layedit.setContent(index,''); ????} }); 功能描述: 客户端收到消息后,判断消息类型,mtype为1时代表是聊天消息。将接收到的聊天消息格式化后,填充到消息模板里,然后追加到容器中,显示在页面上,同时判断这条消息是不是自己发的,如果是,则不播放消息提示音,如果不是则播放收到消息的提示音,提醒用户收到消息。 var audio= new Audio("${pageContext.request.contextPath}/audio/default.mp3"); if(msg.mtype==1) { ????var box = $("#msgtmp").clone(); ????box.show(); ????box.appendTo("#chatContent"); ????box.find('[ff="nickname"]').html(msg.isSelf? ('<i>'+msg.date+'</i>'+msg.nickname+' ('+msg.username+')'):(msg.nickname+' ('+msg.username+')'+'<i>'+msg.date+'</i>')); ????box.find('[ff="pic"]').html('<img src="'+msg.pic+'">'); ????box.find('[ff="msgdate"]').html(msg.date); ????box.find('[ff="content"]').html(msg.content); ????box.addClass(msg.isSelf? 'layim-chat-mine':''); ????scroll_To(1000); ????//不是自己发的消息播放叮咚声 ????if(!msg.isSelf) ????{ ????????audio.play(); ????} } 3.6?定时任务 定时任务主要处理的是长时间未支付的合同和计算过期合同,使用Spring框架的@Scheduled注解实现。定时任务是每隔一段时间自动运行一次的任务,启动后无需人工管理,即可自动执行。 功能描述: 定时处理超过支付时间但是仍未支付的合同订单。每10分钟扫描一次,若有超时未支付的合同订单,将相关联的商铺重新置为租赁状态,然后删除这个合同,将相关联的用户置为空。 private void timeOutTiming(){ ????SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); ????List<Contract> cons = contractService.findByNoPay(); ????for (Contract con : cons) { ????????String starttime = con.getStarttime(); ????????try{ ????????????long startDate = format.parse(starttime).getTime(); ????????????long nowDate = System.currentTimeMillis(); ????????????long minute = (nowDate-startDate)/1000/60; ????????????if(minute>=10) ????????????{ ????????????????//十分钟未支付,删除合同并恢复租赁 ????????????????contractService.delete(con.getId()); ????????????} ????????}catch (Exception e){ ????????????e.printStackTrace(); ????????} ????} } Service层 public ResultInfo delete(String id) { //改为租赁状态 shopsDao.updateState(contractDao.findById(id).getShopid(),0); shopsDao.updateUid(contractDao.findById(id).getShopid(),0); contractDao.delete(id); return new ResultInfo(true); } 功能描述: 定时处理到期合同,合同到期后,将商铺重置为过期审核状态,供后台管理员审核和修改,然后将合同置为过期状态,将相关联的用户置为空。 private void expiredTiming(){ ????SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); ????List<Contract> cons = contractService.findByValid(); ????for (Contract con : cons) { ????????String endtime = con.getEndtime(); ????????try{ ????????????long endDate = format.parse(endtime).getTime(); ????????????long nowDate = System.currentTimeMillis(); ????????????long expired = nowDate-endDate; ????????????if(expired>0){ ????????????????//合同过期 恢复租赁状态 ????????????????contractService.updateStateById(con.getId(),2); ????????????} ????????}catch (Exception e){ ????????????e.printStackTrace(); ????????} ????} } Service层 public void updateStateById(String id,Integer state) { Contract contract = contractDao.findById(id); contract.setId(id); contract.setState(state); contractDao.update(contract); //店铺租赁过期状态 shopsDao.updateState(contract.getShopid(),2); shopsDao.updateUid(contract.getShopid(),0); } 3.7?后台管理 功能描述: 对用户提交的合同进行审核,在后台可以查看合同全部内容,验证合同内容和签字是否规范。对签字不规范的合同可以进行驳回处理,对签字规范的合同进行通过处理。 图3-20?最新合同审核页图 图3-21?合同查看 Controller层 private boolean check(){ ????Admin admin = (Admin) session.getAttribute("Admin"); ????return admin != null; } @RequestMapping(value = "/data/getCheckCont",produces = "application/json;charset=utf-8") @ResponseBody public PageBean getCheckCont(@RequestParam(defaultValue = "1")Integer page, @RequestParam(defaultValue = "10")Integer limit) { ????if(check()) { ????????return contractService.findCheckByPage(page, limit); ????} ????return null; } @RequestMapping(value = "/data/setYesCont",produces = "application/json;charset=utf-8") @ResponseBody public ResultInfo setYesCont(Contract contract) { ????if(check()) { ????????Contract contract1 = contractService.findByid(contract.getId()); ????????Shop shop = shopsService.findShopsBySid(contract1.getShopid()); ????????shop.setState(1); ????????shopsService.addOrUpdate(shop); ????????contract.setState(1); ????????return contractService.addOrUpdate(contract); ????} ????return new ResultInfo(false,"没有操作权限!"); } @RequestMapping(value = "/data/setNoCont",produces = "application/json;charset=utf-8") @ResponseBody public ResultInfo setNoCont(Contract contract) { ????if(check()) { ????????contract.setState(4); ????????return contractService.addOrUpdate(contract); ????} ????return new ResultInfo(false,"没有操作权限!"); } Service层 public ResultInfo addOrUpdate(Contract contract) { ????Contract c = contractDao.findById(contract.getId()); ????try { ????????if (c == null) { ????????????contractDao.save(contract); ????????} else { ????????????contractDao.update(contract); ????????} ????????return new ResultInfo(true); ????}catch (Exception e){ ????????return new ResultInfo(false); ????} } public PageBean findCheckByPage(Integer pageNum, Integer pageSize) { ????Integer count = contractDao.findCheckCount(); ????Integer index = (pageNum - 1) * pageSize; ????List<Contract> data = contractDao.findCheckByPage(index, pageSize); ????return new PageBean(count, data, pageNum, pageSize); } 功能描述: 管理员对过期的商铺进行审核,重新设置商铺的相关信息,然后将商铺状态改为租赁状态,在网站上进行出租。先点击修改按钮,在弹出的窗口中重新设置店铺信息,然后点击出租按钮,即可进行出租。 图3-22?过期商铺审核页图 图3-23?过期商铺审核编辑页图 Controller层 @RequestMapping(value = "/data/getCheckRent",produces = "application/json;charset=utf-8") @ResponseBody public PageBean getCheckRent(@RequestParam(defaultValue = "1")Integer page, @RequestParam(defaultValue = "10")Integer limit) { ????if(check()) { ????????return shopsService.listCheckRent(page, limit); ????} ????return null; } @RequestMapping(value = "/data/setToRent",produces = "application/json;charset=utf-8") @ResponseBody public ResultInfo setToRent(Shop shop) { ????if(check()) { ????????return shopsService.updateState(shop.getSid(),0); ????} ????return new ResultInfo(false,"没有操作权限!"); } Service层 public PageBean listCheckRent(Integer pageNum, Integer pageSize) { Integer total = shopsDao.findCheckRentCount(); Integer index = (pageNum - 1) * pageSize; List<Shop> list = shopsDao.findCheckRentByPage(index, pageSize); return new PageBean(total, list, pageNum, pageSize); } 功能描述: 管理员对商城注册用户的管理,可以添加用户,修改用户信息,删除用户等。 图3-24?用户管理页图 图3-25?用户管理修改页图 Controller层 @RequestMapping(value = "/data/getUser",produces = "application/json;charset=utf-8") @ResponseBody public PageBean getUser(@RequestParam(defaultValue = "1")Integer page, @RequestParam(defaultValue = "10")Integer limit) { ????if(check()) { ????????return userService.findByPage(page, limit); ????} ????return null; } @RequestMapping(value = "/data/setUser",produces = "application/json;charset=utf-8") @ResponseBody public ResultInfo setUser(User user) { ????if(check()) { ????????return userService.addOrUpdateUser(user); ????} ????return new ResultInfo(false,"没有操作权限!"); } @RequestMapping(value = "/data/delUser",produces = "application/json;charset=utf-8") @ResponseBody public ResultInfo delUser(Integer id) { ????if(check()) { ????????return userService.delUser(id); ????} ????return new ResultInfo(false,"没有操作权限!"); } Service层 public PageBean findByPage(Integer pageNum, Integer pageSize) { Integer count = userDao.findCount(); Integer index = (pageNum - 1) * pageSize; List<User> data = userDao.findByPage(index, pageSize); return new PageBean(count, data, pageNum, pageSize); } public ResultInfo addOrUpdateUser(User user) { User u = userDao.findByUid(user.getUid()); try { if (u == null) { user.setPassword(Md5Utils.encodeByMd5("123456")); userDao.save(user); } else { userDao.update(user); } return new ResultInfo(true); }catch (Exception e){ return new ResultInfo(false); } } public ResultInfo delUser(Integer id) { userDao.delete(id); return new ResultInfo(true); } 功能描述: 超级管理员对管理员的管理,可以添加管理员,修改管理员信息,删除管理员等。 图3-26?管理员管理页图 图3-27?管理员管理修改页图 Controller层 @RequestMapping(value = "/data/getAdmin",produces = "application/json;charset=utf-8") @ResponseBody public PageBean getAdmin(@RequestParam(defaultValue = "1")Integer page, @RequestParam(defaultValue = "10")Integer limit) { ????if(check()) { ????????return adminService.findByPage(page, limit); ????} ????return null; } @RequestMapping(value = "/data/setAdmin",produces = "application/json;charset=utf-8") @ResponseBody public ResultInfo setAdmin(Admin admin) { ????if(isSuper()) { ????????return adminService.addOrUpdate(admin); ????} ????return new ResultInfo(false,"没有操作权限!"); } @RequestMapping(value = "/data/delAdmin",produces = "application/json;charset=utf-8") @ResponseBody public ResultInfo delAdmin(Integer id) { ????if(isSuper()) { ????????return adminService.delete(id); ????} ????return new ResultInfo(false,"没有操作权限!"); } 前端 layui.use('table', function(){ ??var table = layui.table; ??table.on('tool(demo)', function(obj){ ????var data = obj.data; ?if(obj.event === 'del'){ ??????layer.confirm('真的要删除吗?', function(index){ ????????$.post('${pageContext.request.contextPath}/data/delAdmin?id='+data.id, {}, function(str){ ???????? if(str.code === 0) ???????? { ???????? obj.del(); ???????? layer.alert("删除成功"); ???????? }else(str.code === 1); ???????? { ???????? layer.alert(str.msg); ???????? } ???????? }); ????????layer.close(index); ??????}); ????} else if(obj.event === 'edit'){ ????????layer.open({ ?????? ??type: 2, ?????? ??title:'修改管理员', ?????? ??area: ['350px', '300px'], ?????? ??content: 'AdminForm.jsp?type=1&id='+data.id+'&username='+data.username+'&password='+data.password+'&quanxian='+data.quanxian ?????? }); ????} ??}); ?? ??var $ = layui.$, active = { ????addAdmin: function(){ //获取选中数据 ???? layer.open({ ???????? ??type: 2, ???????? ??title:'添加管理员', ???????? area: ['350px', '300px'], ???????? ??content: 'AdminForm.jsp' ???????? }); ????} ??}; 功能描述: 管理员管理已在商城入驻的商家,可以修改商家的全部信息,删除商家等 图3-28?商家管理页图 图3-29?商家管理修改页图 Controller层 @RequestMapping(value = "/data/getShop",produces = "application/json;charset=utf-8") @ResponseBody public PageBean getShop(@RequestParam(defaultValue = "1")Integer page, @RequestParam(defaultValue = "10")Integer limit) { ????if(check()) { ????????return shopsService.listShop(page, limit); ????} ????return null; } @RequestMapping(value = "/data/setShop",produces = "application/json;charset=utf-8") @ResponseBody public ResultInfo setShop(Shop shop) { ????if(check()) { ????????return shopsService.addOrUpdate(shop); ????} ????return new ResultInfo(false,"没有操作权限!"); } @RequestMapping(value = "/data/delShop",produces = "application/json;charset=utf-8") @ResponseBody public ResultInfo delShop(Integer id) { ????if(check()) { ????????return shopsService.delete(id); ????} ????return new ResultInfo(false,"没有操作权限!"); } @RequestMapping(value = "/data/ShopForm") public String shopForm(Integer id) { ????if(check()) { ????????Shop shop = shopsService.findShopsBySid(id); ????????request.setAttribute("Shop",shop); ????????return "/admin/page/ShopForm.jsp"; ????} ????return null; } Service层 public PageBean listShop(Integer pageNum, Integer pageSize) { Integer total = shopsDao.findShopCount(); Integer index = (pageNum - 1) * pageSize; List<Shop> list = shopsDao.findShopByPage(index, pageSize); return new PageBean(total, list, pageNum, pageSize); } public Shop findShopsBySid(Integer sid) { return shopsDao.findBySid(sid); } 功能描述: 管理员对商铺的管理,包括正在出租的商铺和已经营业的商铺。可以添加新商铺,修改商铺,删除商铺。 图3-30?商铺管理页图 图3-31?商铺管理修改页图 Controller层 @RequestMapping(value = "/data/getRent",produces = "application/json;charset=utf-8") @ResponseBody public PageBean getRent(@RequestParam(defaultValue = "1")Integer page, @RequestParam(defaultValue = "10")Integer limit) { ????if(check()) { ????????return shopsService.listRent(page, limit); ????} ????return null; } @RequestMapping(value = "/data/setRent",produces = "application/json;charset=utf-8") @ResponseBody public ResultInfo setRent(Shop shop) { ????if(check()) { ????????return shopsService.addOrUpdate(shop); ????} ????return new ResultInfo(false,"没有操作权限!"); } @RequestMapping(value = "/data/delRent",produces = "application/json;charset=utf-8") @ResponseBody public ResultInfo delRent(Integer id) { ????if(check()) { ????????return shopsService.delete(id); ????} ????return new ResultInfo(false,"没有操作权限!"); } @RequestMapping(value = "/data/RentForm") public String rentForm(Integer id) { ????if(check()) { ????????Shop shop = shopsService.findShopsBySid(id); ????????request.setAttribute("Shop",shop); ????????return "/admin/page/RentForm.jsp"; ????} ????return null; } 前端 layui.use('table', function(){ ??var table = layui.table; ??table.on('tool(demo)', function(obj){ ????var data = obj.data; ????if(obj.event === 'del'){ ??????layer.confirm('真的要删除吗?', function(index){ ????????$.post('${pageContext.request.contextPath}/data/delRent?id='+data.sid, {}, function(str){ ???????? if(str.code === 0) ???????? { ???????? obj.del(); ???????? layer.alert("删除成功"); ???????? }else if(str.code === 1) ???????? { ???????? layer.alert("找不到数据,删除失败"); ???????? }else if(str.code === 2) ???????? { ???????? layer.alert("权限不足,删除失败"); ???????? } ???????? }); ????????layer.close(index); ??????}); ????} else if(obj.event === 'edit'){ ????????layer.open({ ?????? ??type: 2, ?????? ??title:'修改商铺', ??????????area: ['100%', '100%'], ?????? ??content: '${pageContext.request.contextPath}/data/RentForm?id='+data.sid ?????? }); ????} ??}); 功能描述: 管理员对已经签订的合同的管理,可以查看合同,也可以删除合同。 图3-32?合同管理页图 图3-33?合同查看页图 Controller层 @RequestMapping(value = "/data/getCont",produces = "application/json;charset=utf-8") @ResponseBody public PageBean getCont(@RequestParam(defaultValue = "1")Integer page, @RequestParam(defaultValue = "10")Integer limit) { ????if(check()) { ????????return contractService.findByPage(page, limit); ????} ????return null; } @RequestMapping(value = "/data/setCont",produces = "application/json;charset=utf-8") @ResponseBody public ResultInfo setCont(Contract contract) { ????if(check()) { ????????return contractService.addOrUpdate(contract); ????} ????return new ResultInfo(false,"没有操作权限!"); } @RequestMapping(value = "/data/delCont",produces = "application/json;charset=utf-8") @ResponseBody public ResultInfo delCont(String id) { ????if(check()) { ????????return contractService.delete(id); ????} ????return new ResultInfo(false,"没有操作权限!"); } ? 功能描述: 对网站首页轮播图的管理,可以添加和修改,删除轮播图,并且能够管理轮播图指向的链接,若指向链接为空,则不使用链接。可以选择上传本地的图片,也可以使用网络图片。 图3-34?首页轮播图管理页图 图3-35?首页轮播图修改页图 Controller层 @RequestMapping(value = "/data/getBanner",produces = "application/json;charset=utf-8") @ResponseBody public PageBean getBanner(@RequestParam(defaultValue = "1")Integer page, @RequestParam(defaultValue = "10")Integer limit) { ????if(check()) { ????????return bannerService.findByPage(page, limit); ????} ????return null; } @RequestMapping(value = "/data/setBanner",produces = "application/json;charset=utf-8") @ResponseBody public ResultInfo setBanner(Banner banner) { ????if(check()) { ????????return bannerService.addOrUpdate(banner); ????} ????return new ResultInfo(false,"没有操作权限!"); } @RequestMapping(value = "/data/delBanner",produces = "application/json;charset=utf-8") @ResponseBody public ResultInfo delBanner(Integer id) { ????if(check()) { ????????return bannerService.delete(id); ????} ????return new ResultInfo(false,"没有操作权限!"); } 功能描述: 对商城活动和公告的管理,可以发布活动和公告招商等信息,信息将展示在首页显眼的位置。管理员可以添加新的活动和公告,修改活动和公告,删除活动和公告。 图3-36?公告和活动管理页图 图3-37?公告和活动修改页图 Controller层 @RequestMapping(value = "/data/getAnno",produces = "application/json;charset=utf-8") @ResponseBody public PageBean getAnno(@RequestParam(defaultValue = "1")Integer page, @RequestParam(defaultValue = "10")Integer limit) { ????if(check()) { ????????return announcementService.findByPage(page, limit); ????} ????return null; } @RequestMapping(value = "/data/setAnno",produces = "application/json;charset=utf-8") @ResponseBody public ResultInfo setAnno(Announcement announcement) { ????if(check()) { ????????return announcementService.addOrUpdate(announcement); ????} ????return new ResultInfo(false,"没有操作权限!"); } @RequestMapping(value = "/data/delAnno",produces = "application/json;charset=utf-8") @ResponseBody public ResultInfo delAnno(Integer id) { ????if(check()) { ????????return announcementService.delete(id); ????} ????return new ResultInfo(false,"没有操作权限!"); } @RequestMapping(value = "/data/AnnoForm") public String annoForm(Integer id) { ????if(check()) { ????????Announcement announcement = announcementService.findById(id); ????????request.setAttribute("Anno",announcement); ????????return "/admin/page/AnnoForm.jsp"; ????} ????return null; } 事务就是把一系列的动作当成一个独立的工作单元,这些动作要么全部完成,要么全部不起作用。Spring中的事务分为编程式事务和声明式事务,本系统使用的是声明式事务,Spring也推荐使用声明式事务。声明式事务是将事务管理代码从业务方法中分离出来,以声明的方式来实现事务管理。通过在xml文件中写一段配置实现,在需要使用事务时在指定方法或者类中添加@Transactional注解即可,方法执行之前启动事务,遇到运行时错误时自动回滚,没有遇到错误则提交事务。 XML配置 <aop:aspectj-autoproxy expose-proxy="true" /> <tx:annotation-driven transaction-manager="txManager" /> <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> ????<property name="dataSource" ref="dataSource" /> </bean> <tx:advice id="txAdvice" transaction-manager="txManager"> ????<tx:attributes> ????????<tx:method name="save*" propagation="REQUIRED" /> ????????<tx:method name="add*" propagation="REQUIRED" /> ????????<tx:method name="update*" propagation="REQUIRED" /> ????????<tx:method name="del*" propagation="REQUIRED" /> ????????<tx:method name="reg*" propagation="REQUIRED" /> ????????<tx:method name="*" read-only="true" /> ????</tx:attributes> </tx:advice> <aop:config expose-proxy="true"> ????<aop:pointcut id="txPointcut" ??????????????????expression="execution(* com.qiang.mall.service.*.*(..))" /> ????<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut" /> </aop:config>
表4-1 ?用户账号登录测试用例表
表4-2??用户手机登录测试用例表
表4-3??功能测试表 至此,毕业设计全部完成,.......... 源码下载地址:https://download.csdn.net/download/sunqiang4/21180240 打不开就是在审核 |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/23 9:26:04- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |