《软件交互设计与开发》
课程设计报告
完整项目gitee路径:https://gitee.com/zust-li-zhixiang/travel.web/commit/71a0ac5bde33fb4c57e851e0bd35ca78fbfe87c5
设计题目: | 云南旅游web |
---|---|
学院: | |
专业班级: | 软件工程 |
学号: | |
学生姓名: | |
指导教师: | |
设计时间: | 2022.11-2023.2 |
-
一、项目背景
云南省有着丰富的旅游资源,因疫情影响,近几年来云南的风景胜地一直无人问津,每个人心中都有着一个“仗剑闯天涯”的旅游梦,也有很多人了解过云南,它也的确是旅游去处的不二之选,四季如春的气候,不挑季节;处处美景,山河壮丽。随着今年疫情的褪去,大家心中那股“走遍天下大好河山”的旅游热火逐渐燃起。
而我作为云南那方土地的儿女,我深知它的美,也极力推荐大家走入云南,但是了解到因为云南省位置偏僻,位置方向不熟悉,风景名胜不出名,成为了云南旅游的阻力。
所以借助本次课程设计,我将写一个“云南旅游网”来帮助不熟悉云南的朋友了解云南,走向云南,也为我家乡的旅游业献一份力!
-
二、需求分析
2.1 系统功能需求
1、登录注册
网页需要基本的登录注册功能,让用户有自己的账户,便于浏览后下次想要找到历史信息可以再次登录账户。
2、数据信息展示
页面主体部分作为旅游网的信息展示区,可以根据地区分类展示数据,在每一个类别下展示该地区的旅游景点。数据太多的话可以分页展示,每一页展示五条数据,这样页面简洁给用户有较好的体验感。我们修改数据可以直接在数据库中修改。
3、搜索旅游路线
用户有自己想去的地方,或者相对感兴趣的几个地点,可以通过搜索框搜索出具体内容,方便高效查找出用户想要浏览的信息,以及多个地区的比较。
4、点击查看详情
当用户看到感兴趣的信息时,我们需要提供详细信息给他深入了解,此时就需要有查看详情的功能。在该页面下可以存放相关地区的一些风景照、附近还有哪些旅游景点、以及该地的地理位置等等。
2.2 系统技术需求
1、前端页面:html、css、js …
前台页面通过html编写的,单独编写了header.html,每个页面都加载header 下面div中放具体内容,编码简单方便。css通过外链式单独编写,使代码结构更加简单明了。
2、后台服务器:servlet、service、dao …
后台逻辑基本是:根据要实现的功能先写servlet,servlet调用service然后通过数据层dao来编写sql语句实现对数据库的修改和查询。Servlet最后拿到后台数据将其序列化为json传到前台便于交互。
3、异步交互:Ajax
我采用的异步交互的方式,前端页面是用html写的,所以采用异步交互的方式,要将后台对象给它序列化为json返回到客户端,客户端再通过ajax的方式拿到服务器端的数据
-
三、系统详细设计与实现
3.1 系统总体功能
通过浏览器访问网址,了解云南风景名胜。各个地区分类展示数据,从数据库读出数据,以分页的方式展示各个地区的著名旅游景点。用户可以登陆注册,查看感兴趣地区的详细介绍和相关风景,以及搜索感兴趣的地点信息。
3.2 系统功能
1、注册表单
为实现注册功能,用户可通过访问到主页面后,点击右上角注册功能,填写表单信息进行注册。提交后的用户信息通过后台保存到数据库相应的表中,以便后面的登录作信息比对。注册成功后,提示激活用户信息,通过后台给用户填写的邮箱发送邮件,当用户点击邮件中的超链接后,表示已经激活,此时,将数据库的用户表中是否激活的字段改为“Y”以便后面登陆时判断用户是否激活。
核心代码: function checkUsername() { //1.获取用户名值 var username = $("#username").val(); //2.定义正则 var reg_username = /^\w{8,20}$/; //3.判断,给出提示信息 var flag = reg_username.test(username); if(flag){ //用户名合法 $("#username").css("border",""); }else{ //用户名非法,加一个红色边框 $("#username").css("border","1px solid red"); } return flag; } //校验密码 function checkPassword() { //1.获取密码值 var password = $("#password").val(); //2.定义正则 var reg_password = /^\w{8,20}$/; //3.判断,给出提示信息 var flag = reg_password.test(password); if(flag){ //密码合法 $("#password").css("border",""); }else{ //密码非法,加一个红色边框 $("#password").css("border","1px solid red"); } return flag; } //校验邮箱 function checkEmail(){ //1.获取邮箱 var email = $("#email").val(); //2.定义正则 itcast@163.com var reg_email = /^\w+@\w+\.\w+$/; //3.判断 var flag = reg_email.test(email); if(flag){ $("#email").css("border",""); }else{ $("#email").css("border","1px solid red"); } return flag; } $(function () { //当表单提交时,调用所有的校验方法 $("#registerForm").submit(function(){ //1.发送数据到服务器 if(checkUsername() && checkPassword() && checkEmail()){ //校验通过,发送ajax请求,提交表单的数据 username=zhangsan&password=123 $.post("registUserServlet",$(this).serialize(),function(data){ //处理服务器响应的数据 data {flag:true,errorMsg:"注册失败"} if(data.flag){ //注册成功,跳转成功页面 location.href="register_ok.html"; }else{ //注册失败,给errorMsg添加提示信息 $("#errorMsg").html(data.errorMsg); } }); } //2.不让页面跳转 return false; //如果这个方法没有返回值,或者返回为true,则表单提交,如果返回为false,则表单不提交 }); //当某一个组件失去焦点是,调用对应的校验方法 $("#username").blur(checkUsername); $("#password").blur(checkPassword); $("#email").blur(checkEmail); });
2、登录、退出
用户注册完成后可以实现登录功能,通过填写用户名,密码进行登录。登录时后端验证,通过数据库中用户名比对用户密码是否正确。登录成功后跳转到首页,此时页面右上角显示“欢迎回来,xxx”,此功能是通过取出数据库中的用户名 添加到页面中。
登录注册旁边有退出按钮,当点击后,跳转到登录页面即可。
核心代码: $(function () { //1.给登录按钮绑定单击事件 $("#btn_sub").click(function () { //2.发送ajax请求,提交表单数据 $.post("loginServlet",$("#loginForm").serialize(),function (data) { //data : {flag:false,errorMsg:''} if(data.flag){ //登录成功 location.href="index.html"; }else{ //登录失败 $("#errorMsg").html(data.errorMsg); } }); }); });
$.get("findUserServlet", {}, function (data) { //{uid:1,name:'李四'} var msg = "欢迎回来," + data.name; $("#span_username").html(msg); });
3、搜索
可通过页面头部的搜索框输入内容进行搜索。后台得到输入的内容,在数据库相应的表中执行sql语句,进行搜索,返回的json语句传回前台,通过发送ajax请求显示相应内容到页面上。
后台代码: public void pageQ(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //接受参数 String currentPageStr = request.getParameter("currentPage"); String pageSizeStr = request.getParameter("pageSize"); String cidStr = request.getParameter("cid"); //接收rname,线路查询时输入的名称 String rname = request.getParameter("rname"); if ("null".equals(rname)) { rname = null; } else { rname = new String(rname.getBytes("iso-8859-1"), "utf-8"); } //2、处理参数 int cid = 0; //类别id if (cidStr != null && cidStr.length() > 0 && !"null".equals(cidStr)) { cid = Integer.parseInt(cidStr); } int currentPage = 0; //当前页码,默认为1 if (currentPageStr != null && currentPageStr.length() > 0) { currentPage = Integer.parseInt(currentPageStr); } else { currentPage = 1; } int pageSize = 0; //每页显示条数,默认每页显示5条 if (pageSizeStr != null && pageSizeStr.length() > 0) { pageSize = Integer.parseInt(pageSizeStr); } else { pageSize = 5; } //3、调用service查询PageBean对象 PageBean<Route> pb = routeService.pageQ(cid, currentPage, pageSize, rname); //4、将PageBean对象序列化为json,返回 writeValue(pb, response); }
前端核心代码: $(function () { /*var search = location.search; //该方法得到 ?后面的字符串 ?cid=6 //alert(search); var cid = search.split("=")[1]; //切割得到id值*/ var cid = getParameter("cid"); //获取rname的参数值 var rname = getParameter("rname"); if (rname) { rname = window.decodeURIComponent(rname); //解码 } //当页面加载完成后,调用load方法,发送ajax请求加载数据 load(cid, null, rname); });
4、分页展示
主体内容是从数据库中取出,再加载到页面中,内容有标题,图片地址,描述,通过取出的总数据条数,计算出要分为多少页来展示,然后在页面底部生成对应的页码按钮,每个按钮(即每一页)展示5条数据,通过循环取出数据展示出即可。
核心代码: function load(cid, currentPage, rname) { //发送Ajax请求,请求route/pageQ,传递cid $.get("route/pageQ", {cid: cid, currentPage: currentPage, rname: rname}, function (pb) { //解析pagebean数据,展示到页面上 //1、分页工具条的数据展示 $("#totalPage").html(pb.totalPage); //展示总页面数 $("#totalCount").html(pb.totalCount); //总记录数 var lis = ""; var firstPage = '<li><a href="javascript:load(' + cid + ',1,\'' + rname + '\')">首页</a></li>'; //计算“上一页”的页码 var beforeNum = pb.currentPage - 1; if (beforeNum <= 0) { beforeNum = 1; } var prePage = '<li class="threeword"><a href="javascript:load(' + cid + ',' + beforeNum + ',\'' + rname + '\')">上一页</a></li>'; lis += firstPage; lis += prePage; for (var i = 1; i <= pb.totalPage; i++) { var li; //判断currentPage是否等于i,当前页加黄 if (pb.currentPage == i) { li = '<li class="curPage"><a href="javascript:load(' + cid + ',' + i + ',\'' + rname + '\')">' + i + '</a></li>'; } else { li = '<li><a href="javascript:load(' + cid + ',' + i + ',\'' + rname + '\')">' + i + '</a></li>'; } lis += li; } //计算最后一页的页码 var lastNum = pb.totalPage; //计算nextPage的页码 var nextNum; if (pb.currentPage >= lastNum) { nextNum = pb.currentPage; } else { nextNum = pb.currentPage + 1; } var nextPage = '<li class="threeword"><a href="javascript:load(' + cid + ',' + nextNum + ',\'' + rname + '\')">下一页</a></li>'; var lastPage = '<li class="threeword"><a href="javascript:load(' + cid + ',' + lastNum + ',\'' + rname + '\')">末页</a></li>'; lis += nextPage; lis += lastPage; //将lis的内容设置到 ul 中 $("#pageNum").html(lis); //2、列表数据的展示 var liss = ""; for (var i = 0; i < pb.list.length; i++) { var route = pb.list[i]; var lii = '<li>\n' + ' <div class="img"><img src="' + route.rimage + '" style="width: 299px;"></div>\n' + ' <div class="text1">\n' + ' <p>' + route.rname + '</p>\n' + ' <br/>\n' + ' <p>' + route.routeIntroduce + '</p>\n' + ' </div>\n' + ' <div class="price">\n' + ' <p class="price_num">\n' + ' <span>¥</span>\n' + ' <span>' + route.price + '</span>\n' + ' <span>起</span>\n' + ' </p>\n' + ' <p><a href="route_detail.html?rid=' + route.rid + '">查看详情</a></p>\n' + ' </div>\n' + ' </li>'; liss += lii; } $("#route").html(liss); //定位到页面顶部 window.scrollTo(0, 0); });
5、图片详情
页面中的每条信息都可以查看详情,里面存放该地的一些风景照片。数据库中建了单独的表,根据数据id存放了多条图片地址,根据id分别加载到对应的“详情”里。多条图片的展示通过 当鼠标移到右边的小图上时,左边的div中显示出该图片,可以移动鼠标实现动态浏览的功能。
-
四、总结
通过本次课程设计,我自己写出了完整的项目,而且通过此次课程设计介绍自己的家乡,也觉得是一件很有意义的事,动手实践也巩固了学习的内容,在代码的乐趣中学到知识,也充实了假期生活。
项目通过不断修改、参考学习、debug,最终实现了基本功能,自己也很有成就感,我也会不断再学习技术,以后有闲暇时间还会继续完善这个项目。