1.设计摘要
随着科技的发展和信息技术的日益普及,很多家长抱着望子成龙的心态,不遗余力的为孩子找合适的家教,而很多在校大学生也希望通过当家教增加一点经济收入,基于这一点家教服务平台将提供更好的管理系统,使家长更加了解学生,也通过这个平台使家教管理者对于大学生方便管理,满足几方面的要求。 实现家教管理者对大学生个人信息、成绩情况、工作时间、工资结算方便有效地管理。
设计的模式及产品目标
用户方面:
对于家长来说,家长普遍希望能给自己的孩子找到一个可以一对一进行补习的教师,且这样的家长数量庞大,是我们移动端开发的主要目标。我们能够为家长提供:按科目进行检索,学生信息查询,与学生进行沟通等功能。家长能够获取学生的性别,年龄,学校,专业,擅长科目,高考成绩等他们关心的信息,按需下单,使他们寻求家教时更方便快捷。
学生方面:
对于学生来说,给学生提供了一个空闲时间自己赚生活费的机会,能够通过上传自己的信息来让更多的家长了解自己,根据自己擅长的科目找到适合自己的岗位,既避免了目前大学生无所事事整天宅在宿舍睡觉打游戏的状况,又让他们发挥长处得到了额外的收入。
2.创新与优势
采取线上交流和支付,线下提供服务的模式。只需很少的管理人员就可以完成很多的人家教需求任务,使得家教管理更加规范化、科学化,人性化,同时还能够动态掌握教员和学员的信息,及时统计相关数据,为家教管理单位提供决策依据,既减少了人员的组织与花费,又提高了家教的服务水平和质量。
3.系统分析
3.1可行性分析
“优教”APP采取线上交流和支付,线下提供服务的模式。只需很少的管理人员就可以完成很多的人家教需求任务,使得家教管理更加规范化、科学化,人性化,同时还能够动态掌握教员和学员的信息,及时统计相关数据,为家教管理单位提供决策依据,既减少了人员的组织与花费,又提高了家教的服务水平和质量。
3.2需求分析
随着经济的发展,多数家庭在子女教育方面呈现出强烈的意识与观念。而且,由于各城市人口基数大,而家庭教育当前实际上又是每个家庭不可或缺的,因而目标性需求群体和潜在性开发群体(家庭)数量巨大,显然这是一个巨大的家庭教育消费群体。在榆次大学城,很多大学生苦于学校偏僻找不到兼职,和外面的市场接触甚少。家长要请家教,但怕来历不明家的教老师。没有一所以学校为核心的家教中心,只是有一些私人的家教中心,但收费昂贵,非一般的家庭能请得起的,收费较低的家教主要是一些来历不明的个人,家长不敢请。所以家教一直处于一个被客观条件压住的水平。
4.系统总体设计
5.系统详细设计与实现
项目采用MVC模式。
数据库用的是MySql,用Navicat界面工具对数据库进行管理,主要是对表结构进行一些修改。
Model:在Eclipse里面分别建立student.java和parent.java文件映射数据库。
View:APICloud 。APICloud是中国领先的"云端一体"的移动应用云服务提供商。 APICloud为开发者从"云"和"端"两个方向提供API。
创建APP的步骤:
(1)端设置 App的图标、状态栏、横竖屏设置、启动页
(2)申请证书(一键创建证书)
(3)代码(APICloud软件中已实现)
(4)模块
(5)云编译
应用名称、选择应用类别、发布平台(Android 、iOS)、类型(测试版、正式版)、全局加密、SVN设置,完成后云编译即可。
Controller:Servlet。Servlet的使用:servlet类中的两个参数:request、response。request:客户端向服务端发出请求response:服务端向客户端返回请求。
6.实现效果
7.系统运行与测试
APP测试的流程:
测试详情:
在测试前端的过程中,发现一些页面排版错乱,图标不恰当等问题。(例如底部导航栏与首页的页面排版)经过分析和进一步的测试,造成这种现象的原因可能是开发人员对各个功能块的理解还不是很完善,另外审美观念有些落后,APP的图标不恰当会造成用户使用过程中的可操作性大大降低,而且也不符合APP的主题。最后通过再次开发,详细阅读已有的代码,查阅开发文档,搞清楚每行代码的作用和所用到的CSS样式,JS脚本,和进行每一个动作后的影响与跳转。自己设计一些合适的图标,应用PhotoShop等工具,对图标进行修改与设计,最终完成前端部分的修改。
测试后端的时候,将测试用例大致分为无效注册,无注册直接登录两大部分,又对这两大部分具体分成若干个小的细节进行逐一测试,(语句覆盖、判定覆盖、条件覆盖、判定条件覆盖、条件组合覆盖、路径覆盖)发现了一些逻辑上的bug,造成这种问题的主要原因可能是在开发过程中没有进行很好的模块测试,最终通过对有问题的模块进行更详细更细节的修改与测试最终得到了想要的效果。
8.项目组成员分工
同学1:注册登录界面及后端代码设计
同学2:首页——检索 发布 分类学科及index设计
同学3:所有——年级选择(导航)
消息——用户消息 系统消息 广播
同学4:所有——附近最热 附近最新
家教个人资料页面
同学5:我的订单 设置 服务中心等页面
9.心得体会
同学1:心得体会
后台开发跟网站设计相差无几,都是前端发出请求后台servlet响应然后调用service执行业务。只不过触发请求都是使用onlick的方式。开发一个应用首先要明确应用的功能点。功能点突出才能应用明确,才能让用户更好地记住你的APP,当然可以适当的配些关联性强的功能,但还是要以突出主功能为主。
同学2:心得体会
我负责完成的是APP开发中的首页设计,属于前端页面设计,这相对于后台数据库开发简单。由于第一周忙于考研复习,所以第二周才算彻底投入课设。第一天实验时,还是对于如何开发前端很不熟悉,不过在其他组员的帮助下,很快入手。前端页面开发其实对于技术要求很低,最重要的还是创新思维,如何设计才能使得自己的主页抓人眼球但又一目了然,这是课设中我面临的最大问题。在下载了其他学习类APP,参考了许多他们的首页设计后,自己顺利完成了自己所负责的模块。
同学3:心得体会
前端页面的开发相比于后端的功能实现相比之下的确简单了一些,但是更加繁琐和细致,首先要确保内容的完整,又要尽可能的简约、朴素,还要有一定的审美观念,想要做好这部分的内容一定要有耐心,要有创意,要能够让用户看到后就打心眼里喜欢,最起码不抵触。想真正能够得心应手,还有很长的路要走。
同学4:心得体会
在进行一个项目的设计过程中,一定要注意学会文档的使用,在开发项目的过程中,我深刻的意识到,文档存在的意义并不是无用的报告,简洁明了的文档不光能记录你当下所做的,还能在繁重的工作中分神思考下一步该做什么时为你节约精力,并且在项目周期内,使整个项目保持一致性。所以,软件开发文档的编写是很有必要的。
同学5:心得体会
我的订单栏目主要是为后端家长方便与家教联系和记录所用,主要用到了MySQL数据库来保存相关信息。设置栏目与原栏目基本相似,使用servlet技术将各页面联系起来,方便用户根据自己喜好来设定app相关内容。服务中心旨在将用jsp技术实现前端注册和登录,以及用户账户的切换。
10.PPT效果展示
11.参考文献
[1] 杨选辉 .网页设计与制作教程.北京:清华大学出版社.2006
[2] 詹国华,潘红等.多媒体网页设计教程,.北京:高等教育出版社.2009
[3] 贾珺.动态网站设计与开发项目教程, 中国电力出版社.2009
12.核心代码
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<meta name="copyright" content="www.apicloud.com" />
<meta name="viewport" content="maximum-scale=1.0,minimum-scale=1.0,user-scalable=0,width=device-width,initial-scale=1.0"/>
<title>首页</title>
<link rel="stylesheet" type="text/css" href="../css/api.css" />
<style>
#main {
display: -webkit-box; -webkit-box-orient: vertical;
}
#header {position: relative; background-color: #fff; border-bottom: 1px solid #e0e0e0;}
.logo {position: absolute; height: 25px; padding: 12px 20px 13px 20px;}
h1 { height: 50px; line-height: 50px; font-size: 20px; color: #000;font-weight: normal;margin: 0 auto; text-align: center; }
.search {
position: absolute; right: 50px; bottom: 0px;
width: 50px; height: 50px;
background: url(../image/actionbar_search.png) no-repeat center center;
-webkit-background-size: 24px 24px;
}
.setting {
position: absolute; right: 0px; bottom: 0px;
width: 50px; height: 50px;
background: url(../image/actionbar_setting.png) no-repeat center center;
-webkit-background-size: 28px 28px;
}
.search-hov {
background-color: rgb(65,61,61);
}
.setting-hov {
background-color: rgb(65,61,61);
}
.navbar {
display: -webkit-box; -webkit-box-orient: horizontal;
position: relative;
height: 50px; box-sizing: border-box;
/*background-color: rgb(231,226.221);*/
background: #fff;
border-bottom: 1px solid #e0e0e0;
}
.navbar-item {
display: block; -webkit-box-flex: 1;
width: 100%; line-height: 50px;
/*color: rgb(148,127,119);*/ font-size: 18px; text-align: center;color: #9B9C9C;
}
.navbar-item-hov {
/*background-color: rgba(236,225,210,0.7);*/
background-color: rgba(254,242,228,0.7);
}
.navbar-item-active {
/*color: rgb(220,111,0);*/
color: #ff6836;
}
#navmark {
position: absolute; left: 0px; bottom: 0px;
/*height: 2px;
background-color: rgb(253,133,0);*/
-webkit-transition: 300ms;
text-align: center;
width: 33%;
}
#navmark img {position: absolute; bottom: 0; height: 8px;}
</style>
</head>
<body>
<div id="main">
<header id="header">
<img class="logo" src="../image/ic_back_u.png" tapmode="" onclick="goback()" />
<h1 id="title">广播</h1>
</header>
<nav class="navbar">
<a id="navbar-item-recommend" class="navbar-item navbar-item-active" tapmode="navbar-item-hov" onclick="setFrameGroupIndex(0);">用户信息</a>
<a id="navbar-item-rank" class="navbar-item" tapmode="navbar-item-hov" onclick="setFrameGroupIndex(1);">系统信息</a>
<a id="navbar-item-favorite" class="navbar-item" tapmode="navbar-item-hov" onclick="setFrameGroupIndex(2);">广播</a>
<mark id="navmark"><img src="../image/quick_action_arrow_up.png"></mark>
</nav>
<section id="content">
</section>
</div>
</body>
<script type="text/javascript" src="../script/api.js"></script>
<script type="text/javascript">
function goback () {
api.closeWin({name:'message'});
}
function setFrameGroupIndex(frameIndex) {
api.setFrameGroupIndex({name:'message',index:frameIndex,scroll:true});
}
function setFrameGroupStatus(frameIndex) {
var title = $api.byId('title');
switch (frameIndex) {
case 0: {
title.innerHTML = '用户消息';
$api.byId('navbar-item-recommend').className = "navbar-item navbar-item-active";
$api.byId('navbar-item-rank').className = "navbar-item";
$api.byId('navbar-item-favorite').className = "navbar-item";
var num = (api.winWidth/3)*frameIndex;
$api.css($api.byId('navmark'), "-webkit-transform:translate(" + num + "px,0)");
break;
}
case 1: {
title.innerHTML = '系统消息';
$api.byId('navbar-item-recommend').className = "navbar-item";
$api.byId('navbar-item-rank').className = "navbar-item navbar-item-active";
$api.byId('navbar-item-favorite').className = "navbar-item";
var num = (api.winWidth/3)*frameIndex;
$api.css($api.byId('navmark'), "-webkit-transform:translate(" + num + "px,0)");
break;
}
case 2: {
title.innerHTML = '广播';
$api.byId('navbar-item-recommend').className = "navbar-item";
$api.byId('navbar-item-rank').className = "navbar-item";
$api.byId('navbar-item-favorite').className = "navbar-item navbar-item-active";
var num = (api.winWidth/3)*frameIndex;
$api.css($api.byId('navmark'), "-webkit-transform:translate(" + num + "px,0)");
break;
}
default:
break;
}
}
apiready = function() {
var header = $api.byId('header');
$api.fixIos7Bar(header);
var headerHeight = $api.byId('header').offsetHeight;
var scrollHeight = $api.dom('.navbar').offsetHeight;
$api.byId('navmark').style.width = api.winWidth/3 + 'px';
api.openFrameGroup({
name: 'message',
background: '#FFF',
rect: {x: 0, y: headerHeight+scrollHeight, w: "auto", h: "auto"},
index: 0,
frames: [
{
name: 'usermsg',
url: './usermsg_frame.html',
bounces: false,
},
{
name: 'systemmsg',
url: './systemmsg_frame.html',
bounces: false,
},
{
name: 'broadcast',
url: './broadcast_frame.html',
bounces: false,
}
]
}, function (ret) {
setFrameGroupStatus(ret.index);
});
};
</script>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>全部分类</title>
<link rel="stylesheet" type="text/css" href="../css/api.css" />
<link rel="stylesheet" type="text/css" href="../css/common.css" />
<style>
html, body {width: 100%;min-height: 100%;background: #f0f0f0;}
.h80 {height: 80px;}
.h40 {height: 40px;}
.h20 {height: 20px;}
.h10 {height: 10px;background: #f0f0f0;}
.h1 {height: 1px;margin-left: 15px;background: #f0f0f0;}
.fr {float: right;}
.fl {float: left;}
.hightitem {background-color: #fff;}
.inwrap {margin: 0 10px;}
/* 2X2样式 */
.row {display: -webkit-box;display: -webkit-flex;}
.col {-webkit-box-flex:1; -webkit-flex:1; flex:1;position: relative;}
.col img {position: absolute; right: 0; width: 80px; top: 0;}
.col .matrixcell {display: table-cell;vertical-align: middle; padding-left: 10px;}
.col .matrixcell .title {margin-bottom: 10px;}
.matrix {display: table;height: inherit;}
/* 1. 2X2 */
.flipcard {height: 30px; line-height: 30px; text-align: center; margin: 5px 5px 3px 5px; color: #000; background-color: #fff; font-size: 14px;}
.darktitle {height: 40px;line-height: 40px;margin-left: 15px;font-size: 14px;color: #666;}
/* 2. 三列 */
.scratch02 .word {margin-top: 10px;margin-left: 10px;}
.scratch02 .word .title{font-size: 18px;}
.scratch02 .word .info{font-size: 12px;color: #666;}
.scratch02 img {position: relative;width: 60px; height: 50px;}
.showposter {text-align: center;margin-top: 5px;padding-bottom: 10px;}
/* 列表 */
.classify {height: 60px;line-height: 60px;background-color: #fff;position: relative;border-bottom: 1px solid #e0e0e0;}
.classify .sublogo {width: 30px;margin-top: 15px;margin-left: 15px;float: left;}
.classify .arrow {position: absolute;vertical-align: top;right: 15px;top:20px;height: 20px;}
.classify .info {line-height: 20px; float: left; height: 60px;margin-left: 10px;}
.classify .info .title {font-size: 15px; color: #000; margin-top: 10px;}
.classify .info .subtitle {font-size: 12px; color: #666; margin-top: 5px;}
.subclass {display: none;}
.subclass .flipcard {margin:0;}
.brb {border-right: 1px solid #e0e0e0;border-bottom: 1px solid #e0e0e0;}
.bb {border-bottom: 1px solid #e0e0e0;}
.presshover {background-color: #FAFAFA;}
</style>
</head>
<body>
<!-- 1 2X2 -->
<div class="darktitle">热门搜索</div>
<div class="row inwrap">
<div class="col flipcard" tapmode="presshover" onclick="openDetail()">数学</div>
<div class="col flipcard" tapmode="presshover" onclick="openDetail()">英语</div>
<div class="col flipcard" tapmode="presshover" onclick="openDetail()">语文</div>
</div>
<div class="row inwrap">
<div class="col flipcard" tapmode="presshover" onclick="openDetail()">物理</div>
<div class="col flipcard" tapmode="presshover" onclick="openDetail()">化学</div>
<div class="col flipcard" tapmode="presshover" onclick="openDetail()">生物</div>
</div>
</body>
<script type="text/javascript" src="../script/api.js"></script>
<script>
function openDetail()
{
api.openWin({
name: 'tuandetail',
url: './tuandetail_header.html',
// delay:200
bounces: false
});
}
</script>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>首页</title>
<link rel="stylesheet" type="text/css" href="../css/api.css" />
<link rel="stylesheet" type="text/css" href="../css/common.css" />
<link rel="stylesheet" href="../css/idangerous.swiper.css">
<style>
html, body {width: 100%;min-height: 100%;background: #f0f0f0;}
.h80 {height: 80px;}
.h40 {height: 40px;}
.h20 {height: 20px;}
.h10 {height: 10px;background: #f0f0f0;}
.h1 {height: 1px;margin-left: 15px;background: #f0f0f0;}
.fr {float: right;}
.fl {float: left;}
.hightitem {background-color: #fff;}
.inwrap {padding-right: 15px;padding-left: 15px;}
/* 2. 价格样式 */
.priceitem {height: 60px; line-height: 60px;border-bottom: 1px solid #ccc;}
.priceitem .price, .priceitem .symbol {color: #FC5500;}
.priceitem .price {font-size: 20px;}
.priceitem .o-price {font-size: 12px; color: #666;}
.priceitem .buynow {background-color: #FC5500; color: #fff; height: 25px; line-height: 25px; border-radius: 3px;padding: 10px 20px;margin-top: 7px;}
/* 3. */
.brief .title {height: 50px;line-height: 50px;font-size: 18px;color: #000;}
.brief .describe {color: #666;font-size: 14px;line-height: 20px;}
.brief .ico {height: 50px;line-height: 50px;font-size: 14px;color: #7AB388;}
.brief .ico img {height: 14px;}
/* 4. */
.goodcomment {height: 50px;line-height: 50px;font-size: 14px;}
.goodcomment img {height: 15px;padding-right: 5px;}
.goodcomment .arrow {float: right;height: 20px;padding-top: 15px;}
.goodcomment .commentnum {font-size: 15px;color: #666;padding-right: 5px;float: right;}
/* 5. */
.darktitle {height: 50px;line-height: 50px;font-size: 14px;color: #666;}
.firstrow {position: relative;}
.secrow {font-size: 14px;color: #666;border-bottom: 1px solid #e0e0e0;padding-bottom: 15px;}
.shopinfo .left {height: 60px;padding: 10px 0;}
.shopinfo .right {position: absolute;top: 0px; right: -15px; padding: 15px;border-left: 1px solid #e0e0e0;}
.shopinfo .right img {height: 36px;}
.shopinfo .shopname {font-size: 20px;}
.moreshop {height: 50px;line-height: 50px;font-size: 14px;}
/* 6. */
.tuanitem {height: 50px;line-height: 50px;font-size: 14px;border-bottom: 1px solid #e0e0e0;}
.tuanitem .tuan02,.tuanitem .tuan03,.tuantotalprice .totalprice01, .tuantotalprice .totalprice02, .tuanrealprice .realprice01, .tuanrealprice .realprice02 {float: right; width: 50px;font-size: 14px;}
.tuantotalprice {margin-top: 10px;}
.tuantotalprice, .tuanrealprice {height: 30px;}
.tuanrealprice .realprice02 {font-size: 16px;color: #FC5500;}
.tuanitem .tuan03, .tuantotalprice .totalprice02, .tuanrealprice .realprice02 {text-align: right;}
.smallitem .averageprice {float: right;}
.smallitem {height: 20px;line-height: 20px;font-size: 14px;}
.recommandtitle {line-height: 25px; font-size: 14px; color: #666;}
.recommanddish {line-height: 22px; font-size: 14px;}
.moredetail {height: 50px;line-height: 50px;font-size: 14px;border-top: 1px solid #e0e0e0;}
.lastitem {padding-bottom: 10px;}
/* 7. */
.buyinfo .infotitle {line-height: 25px;font-size: 14px;color: #666;}
.buyinfo li {line-height: 24px;font-size: 13px;color: #000;}
.buyinfo li img {height: 5px; padding-right: 5px;}
.arrow {float: right;height: 20px;padding-top: 15px;}
/* 8. */
.othertuan {height: 50px;line-height: 50px;}
.othertuan .price, .othertuan .symbol {color: #FC5500;}
.othertuan .price {font-size: 15px;}
.othertuan .o-price {font-size: 12px; color: #666;}
.othertuan .price01 {display: inline-block; width: 30%; vertical-align: top;}
.othertuan .title {width: 50%; white-space: nowrap; text-overflow: ellipsis; word-wrap: normal; overflow: hidden;}
.bb {border-bottom: 1px solid #e0e0e0;}
.presshover {background-color: #FAFAFA;}
.buyhover {background-color: rgba(252, 85, 0, 0.6) !important;}
.swiper-container img {width: 100%;height:100%;}
.home-tuan-list .sex{color:#333;font-size:13px;}
.home-tuan-list .symbol {font-size: 14px; color: #f60; display: block; margin-top: 1px; }
.home-tuan-list .subject {color: #f60; font-size: 14px; line-height: 15px; margin-right: 5px; margin-top: 1px; }
</style>
</head>
<body>
<!-- 1. 头部swipe -->
<div class="swiper-container">
<div class="swiper-wrapper">
<img src="../image/person1.jpg" alt="">
</div>
<div class="pagination"></div>
</div>
<!-- 2. 价格样式 -->
<div class="priceitem hightitem inwrap">
<span class="symbol">¥</span>
<span class="price">100</span>
<div class="buynow fr" tapmode="buyhover" onclick="">立即下单</div>
</div>
<!-- 3. -->
<div class="brief inwrap hightitem">
<div class="title">殷子贤</div> <div class="sex">男</div>
<div class="describe">太原理工大学计算机科学与技术专业学生,成绩优异</div>
<div class="symbol">擅长科目:</div><div class="subject">数学 物理 化学</div>
</div>
<!-- 4 评论 -->
<div class="h20"></div>
<div class="goodcomment inwrap hightitem" tapmode="presshover" onclick=""><img src="../image/tuan_review_bad.png" alt="">8个好评<img src="../image/arrow.png" alt="" class="arrow"><span class="commentnum">共8条评论</span></div>
<!-- 5 适用商户 -->
<div class="darktitle inwrap">住址</div>
<div class="shopinfo inwrap hightitem">
<div class="firstrow ">
<div class="left">
<div class="shopname">太原理工大学</div>
</div>
<div class="right" tapmode="presshover" onclick="callShop()"><img src="../image/ic_phone_big.png" alt="" class="phone"></div>
</div>
<div class="secrow">太原理工大学明向校区明泽苑一号楼</div>
</div>
<!-- 7 购买须知 -->
<div class="darktitle inwrap">下单须知</div>
<div class="buyinfo hightitem inwrap">
<div class="infotitle">空闲时间</div>
<ul>
<li><img src="../image/home_serve_dot.png" alt="">每周一到周五18:00-22:00</li>
</ul>
<div class="infotitle">温馨提示</div>
<ul>
<li class="lastitem"><img src="../image/home_serve_dot.png" alt="">下单前请提前与学生本人联系确认空闲时间</li>
</ul>
</div>
<div class="h20"></div>
</body>
<script type="text/javascript" src="../script/idangerous.swiper.js"></script>
<script>
function callShop() {
api.call({
type: 'tel_prompt',
number: '010-82030128'
});
}
window.onload = function() {
var mySwiper = new Swiper('.swiper-container',{
mode:'horizontal',
loop: true,
speed:750,
pagination: '.pagination'
});
mySwiper.startAutoplay();
}
</script>
</html>
喜欢的点赞收藏加关注私信作者沟通交流