软件交互设计与开发

《软件交互设计与开发》

课程设计报告

完整项目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>&yen;</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,最终实现了基本功能,自己也很有成就感,我也会不断再学习技术,以后有闲暇时间还会继续完善这个项目。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值