9-1 首页后台的开发
Dao层:
/**
* 根据传入的查询条件(头条名查询头条)
*
* @param headLineCondition
* @return
*/
List<HeadLine> queryHeadLine(@Param("headLineCondition") HeadLine headLineCondition);
<select id="queryHeadLine" resultType="com.doit.o2o.entity.HeadLine">
SELECT line_id,line_name,line_link,line_img,priority,enable_status,create_time,last_edit_time
FROM tb_head_line
<where>
<if test="headLineCondition.enableStatus!=null">
and enable_status = #{headLineCondition.enableStatus}
</if>
</where>
ORDER BY priority DESC
</select>
Service层:
/**
* 根据传入的条件返回指定的头条列表
* @param headLineCondition
* @return
* @throws IOException
*/
List<HeadLine> getHeadLineList(HeadLine headLineCondition) throws IOException;
@Service
public class HeadLineServiceImpl implements HeadLineService{
@Autowired
private HeadLineDao headLineDao;
@Override
public List<HeadLine> getHeadLineList(HeadLine headLineCondition) throws IOException {
return headLineDao.queryHeadLine(headLineCondition);
}
}
Controller层:
@Controller
@RequestMapping("/frontend")
public class MainPageController {
@Autowired
private ShopCategoryService shopCategoryService;
@Autowired
private HeadLineService headLineService;
/**
* 初始化前端展示系统的主页信息,包括获取一级店铺类别列表一级头条列表
* @return
*/
@RequestMapping(value="/listmainpageinfo",method=RequestMethod.GET)
@ResponseBody
private Map<String,Object> listMainPageInfo(){
Map<String,Object> modelMap = new HashMap<String,Object>();
List<ShopCategory> shopCategoryList= new ArrayList<ShopCategory>();
List<HeadLine> headLineList= new ArrayList<HeadLine>();
try{
//获取一级店铺类别列表(即parentId为空的ShopCategory)
shopCategoryList = shopCategoryService.getShopCategoryList(null);
modelMap.put("shopCategoryList", shopCategoryList);
}catch(Exception e){
modelMap.put("success", false);
modelMap.put("errMsg", e.getMessage());
return modelMap;
}
try{
//获取状态可用(1)的头条列表
HeadLine headLineCondition = new HeadLine();
headLineCondition.setEnableStatus(1);
headLineList = headLineService.getHeadLineList(headLineCondition);
modelMap.put("headLineList", headLineList);
}catch(Exception e){
modelMap.put("success", false);
modelMap.put("errMsg", e.getMessage());
return modelMap;
}
modelMap.put("success", true);
return modelMap;
}
}
9-2 首页前端的开发上
index.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>我的生活</title>
<meta name="viewport" content="initial-scale=1, maximum-scale=1">
<link rel="shortcut icon" href="/favicon.ico">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<link rel="stylesheet"
href="//g.alicdn.com/msui/sm/0.6.2/css/sm.min.css">
<link rel="stylesheet"
href="//g.alicdn.com/msui/sm/0.6.2/css/sm-extend.min.css">
<link rel="stylesheet" href="../resources/css/frontend/index/index.css">
</head>
<body>
<div class="page-group">
<div class="page">
<header class="bar bar-nav">
<!-- <a class="button button-link button-nav pull-left" href="/demos/card" data-transition='slide-out'>
<span class="icon icon-left"></span>
返回
</a> -->
<h1 class="title">My School O2O</h1>
</header>
<nav class="bar bar-tab">
<a class="tab-item active" href="#"> <span
class="icon icon-home"></span> <span class="tab-label">首页</span>
</a> <a class="tab-item" href="#" id='me'> <span class="icon icon-me"></span>
<span class="tab-label">我</span>
</a>
</nav>
<div class="content">
<!-- 这里是页面内容区 -->
<div class="swiper-container index-banner" data-space-between='10'>
<div class="swiper-wrapper">
<!-- <div class="swiper-slide img-wrap">
<img class="banner-img" src="//gqianniu.alicdn.com/bao/uploaded/i4//tfscom/i1/TB1n3rZHFXXXXX9XFXXXXXXXXXX_!!0-item_pic.jpg_320x320q60.jpg" alt="">
</div>
<div class="swiper-slide img-wrap">
<img class="banner-img" src="//gqianniu.alicdn.com/bao/uploaded/i4//tfscom/i4/TB10rkPGVXXXXXGapXXXXXXXXXX_!!0-item_pic.jpg_320x320q60.jpg" alt="">
</div>
<div class="swiper-slide img-wrap">
<img class="banner-img" src="//gqianniu.alicdn.com/bao/uploaded/i4//tfscom/i1/TB1kQI3HpXXXXbSXFXXXXXXXXXX_!!0-item_pic.jpg_320x320q60.jpg" alt="">
</div> -->
</div>
<div class="swiper-pagination"></div>
</div>
<div class='total-shop-button'>
<a href="/o2o/frontend/shoplist" external>全部商店</a>
</div>
<!-- 一级类别展示区域 -->
<div class="row">
<!-- <div class="col-50 shop-classify">
<div class='word'>
<p class='shop-title'>本期推荐</p>
<p class='shop-desc'>近期相关活动、新款上市、旅游资讯</p>
</div>
<div class='shop-classify-img-warp'>
<img class='shop-img' src="static/index/display13.png">
</div>
</div> -->
</div>
</div>
</div>
<!--侧边栏 -->
<div class="panel-overlay"></div>
<div class="panel panel-right panel-reveal" id="panel-left-demo">
<div class="content-block">
<p>
<a href="/o2o/frontend/myrecord" class="close-panel">消费记录</a>
</p>
<p>
<a href="/o2o/frontend/mypoint" class="close-panel">我的积分</a>
</p>
<p>
<a href="/o2o/frontend/pointrecord" class="close-panel">积分兑换记录</a>
</p>
<!-- Click on link with "close-panel" class will close panel -->
</div>
</div>
</div>
<script type='text/javascript'
src='//g.alicdn.com/sj/lib/zepto/zepto.min.js' charset='utf-8'></script>
<script type='text/javascript'
src='//g.alicdn.com/msui/sm/0.6.2/js/sm.min.js' charset='utf-8'></script>
<script type='text/javascript'
src='//g.alicdn.com/msui/sm/0.6.2/js/sm-extend.min.js' charset='utf-8'></script>
<script type='text/javascript' src='../resources/js/frontend/index.js'
charset='utf-8'></script>
</body>
</html>
index.js
$(function() {
//定义访问后台,获取头条列表以及一级类别列表的URL
var url = '/o2o/frontend/listmainpageinfo';
//访问后台,获取头条列表以及一级类别列表
$.getJSON(url, function (data) {
if (data.success) {
//获取后台传递过来的头条列表
var headLineList = data.headLineList;
var swiperHtml = '';
//遍历头条列表,并拼接出轮播图组
headLineList.map(function (item, index) {
swiperHtml += ''
+ '<div class="swiper-slide img-wrap">'
+ '<a href="'+item.lineLink
+ '"external><img class="banner-img" src="'+ item.lineImg
+'" alt="'+ item.lineName +'"></a>'+ '</div>';
});
//将轮播图组赋值给前端HTML控件
$('.swiper-wrapper').html(swiperHtml);
$(".swiper-container").swiper({
//设定轮播图轮换时间为1秒
autoplay: 1000,
//用户对轮播图进行操作时,是否自动停止autoplay
autoplayDisableOnInteraction: false
});
//获取后台传递过来的大类列表
var shopCategoryList = data.shopCategoryList;
var categoryHtml = '';
//遍历大类列表,并拼接出两两(col-50)一行的类别
shopCategoryList.map(function (item, index) {
categoryHtml += ''
+ '<div class="col-50 shop-classify" data-category='+ item.shopCategoryId +'>'
+ '<div class="word">'
+ '<p class="shop-title">'+ item.shopCategoryName +'</p>'
+ '<p class="shop-desc">'+ item.shopCategoryDesc +'</p>'
+ '</div>'
+ '<div class="shop-classify-img-warp">'
+ '<img class="shop-img" src="'+ item.shopCategoryImg +'">'
+ '</div>'
+ '</div>';
});
//将拼接好的类别赋值给前端HTML控件进行展示
$('.row').html(categoryHtml);
}
});
//若点击"我的",则显示侧栏
$('#me').click(function () {
$.openPanel('#panel-left-demo');
});
$('.row').on('click', '.shop-classify', function (e) {
var shopCategoryId = e.currentTarget.dataset.category;
var newUrl = '/o2o/frontend/shoplist?parentId=' + shopCategoryId;
window.location.href = newUrl;
});
});
index.css
.index-banner {
height: 35%;
padding-bottom: 0.4rem;
}
.img-wrap {
overflow: hidden;
}
.banner-img {
width: 100%;
height: 100%;
}
.total-shop-button {
height: 1.5rem;
line-height: 1.5rem;
padding-left: 0.85rem;
margin-bottom: 0.4rem;
position: relative;
cursor: pointer;
}
.total-shop-button:before {
content: '';
display: inline-block;
position: absolute;
left: 0;
width: 0.15rem;
height: 1.5rem;
background-color: #0894ec;
}
.shop-classify {
height: 3.3rem;
padding: 0.2rem;
cursor: pointer;
}
.shop-classify > .word {
width: 65%;
height: 100%;
overflow: hidden;
float: left;
}
.shop-classify > .word > p {
margin: 0;
}
.shop-classify > .word > .shop-title {
margin: 0;
font-size: 0.8rem;
}
.shop-classify > .word > .shop-desc {
margin: 0;
font-size: 0.4rem;
}
// .shop-classify > .shop-img {
// width: 2.4rem;
// height: 2.4rem;
// margin-left: 0.2rem;
// display: inline-block;
// }
.shop-classify > .shop-classify-img-warp {
width: 30%;
height: 100%;
margin-left: 0.2rem;
display: inline-block;
}
.shop-classify > .shop-classify-img-warp > .shop-img {
width: 100%;
height: 100%;
}
9-3 首页前端的开发下
新建FrontendController:
package com.doit.o2o.web.frontend;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
@RequestMapping("/frontend")
public class FrontendController {
@RequestMapping(value="index",method=RequestMethod.GET)
private String index(){
return "frontend/index";
}
}
在server.xml文件中最后添加:
<Context docBase="F:\\projectdev\\upload" path="/upload"/>
使得对本地服务器/upload路径下的访问映射到指定的文件目录F:\projectdev\upload下。
9-4 docBase与upload的含义
略
9-5 店铺列表页后端的开发
Controller层:
package com.doit.o2o.web.frontend;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import com.doit.o2o.dto.ShopExecution;
import com.doit.o2o.entity.Area;
import com.doit.o2o.entity.Shop;
import com.doit.o2o.entity.ShopCategory;
import com.doit.o2o.service.AreaService;
import com.doit.o2o.service.ShopCategoryService;
import com.doit.o2o.service.ShopService;
import com.doit.o2o.util.HttpServletRequestUtil;
@Controller
@RequestMapping("/frontend")
public class ShopListController {
@Autowired
private ShopService shopService;
@Autowired
private ShopCategoryService shopCategoryService;
@Autowired
private AreaService areaService;
/**
* 返回商品列表页里的ShopCategory列表(二级或一级),以及区域信息列表
* @param request
* @return
*/
@RequestMapping(value = "/listshopspageinfo", method = RequestMethod.GET)
@ResponseBody
private Map<String,Object> listShopsPageInfo(HttpServletRequest request){
Map<String,Object> modelMap = new HashMap<String,Object>();
//试着从前端请求中获取parentId
long parentId = HttpServletRequestUtil.getLong(request, "parentId");
List<ShopCategory> shopCategoryList = null;
if(parentId!=-1){
//如果parentId存在,则取出该一级ShopCategory下的二级ShopCategory列表
try{
ShopCategory shopCategoryCondition = new ShopCategory();
ShopCategory parent = new ShopCategory();
parent.setShopCategoryId(parentId);
shopCategoryCondition.setParent(parent);
shopCategoryList = shopCategoryService.getShopCategoryList(shopCategoryCondition);
}catch(Exception e){
modelMap.put("success", false);
modelMap.put("errMsg", e.getMessage());
}
}else{
try{
//如果parentId不存在,则取出一级ShopCategory(用户在首页选择的是全部商店列表)
shopCategoryList = shopCategoryService.getShopCategoryList(null);
}catch(Exception e){
modelMap.put("success", false);
modelMap.put("errMsg", e.getMessage());
}
}
modelMap.put("shopCategoryList", shopCategoryList);
List<Area> areaList = null;
try {
//获取区域列表信息
areaList = areaService.getAreaList();
modelMap.put("areaList", areaList);
modelMap.put("success", true);
return modelMap;
} catch (Exception e) {
modelMap.put("success", false);
modelMap.put("errMsg", e.getMessage());
}
return modelMap;
}
@RequestMapping(value="/listshops",method=RequestMethod.GET)
@ResponseBody
private Map<String,Object> listShops(HttpServletRequest request){
Map<String,Object> modelMap= new HashMap<String,Object>();
//获取页码
int pageIndex = HttpServletRequestUtil.getInt(request, "pageIndex");
//获取一页需要显示的数据条数
int pageSize = HttpServletRequestUtil.getInt(request, "pageSize");
//非空判断
if ((pageIndex > -1) && (pageSize > -1)) {
//试着获取一级类别Id
long parentId = HttpServletRequestUtil.getLong(request, "parentId");
//试着获取特定二级类别Id
long shopCategoryId = HttpServletRequestUtil.getLong(request,
"shopCategoryId");
//试着获取区域Id
int areaId = HttpServletRequestUtil.getInt(request, "areaId");
//试着获取模糊查询的名字
String shopName = HttpServletRequestUtil.getString(request,
"shopName");
//获取组合之后的查询条件
Shop shopCondition = compactShopCondition4Search(parentId,
shopCategoryId, areaId, shopName);
//根据查询条件和分页信息获取店铺信息列表,并返回总数
ShopExecution se = shopService.getShopList(shopCondition,
pageIndex, pageSize);
modelMap.put("shopList", se.getShopList());
modelMap.put("count", se.getCount());
modelMap.put("success", true);
} else {
modelMap.put("success", false);
modelMap.put("errMsg", "empty pageSize or pageIndex");
}
return modelMap;
}
/**
* 组合查询条件,并将条件封装到ShopCondition对象里返回
* @param parentId
* @param shopCategoryId
* @param areaId
* @param shopName
* @return
*/
private Shop compactShopCondition4Search(long parentId,
long shopCategoryId, int areaId, String shopName) {
Shop shopCondition = new Shop();
if (parentId != -1L) {
//查询某个一级ShopCategory下面的所有二级ShopCatery里面的店铺列表
ShopCategory childCategory = new ShopCategory();
ShopCategory parentCategory = new ShopCategory();
parentCategory.setShopCategoryId(parentId);
childCategory.setParent(parentCategory);
shopCondition.setShopCategory(childCategory);
}
if (shopCategoryId != -1L) {
//查询某个二级ShopCategory下面的店铺列表
ShopCategory shopCategory = new ShopCategory();
shopCategory.setShopCategoryId(shopCategoryId);
shopCondition.setShopCategory(shopCategory);
}
if (areaId != -1L) {
//查询位于某个区域Id下的店铺列表
Area area = new Area();
area.setAreaId(areaId);
shopCondition.setArea(area);
}
if (shopName != null) {
//查询名字里包含shopName的店铺列表
shopCondition.setShopName(shopName);
}
//前端展示的店铺都是审核成功的店铺
shopCondition.setEnableStatus(1);
return shopCondition;
}
}
9-6 店铺列表页前端的开发上
shoplist.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>商店列表</title>
<meta name="viewport" content="initial-scale=1, maximum-scale=1">
<link rel="shortcut icon" href="/favicon.ico">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<link rel="stylesheet"
href="//g.alicdn.com/msui/sm/0.6.2/css/sm.min.css">
<link rel="stylesheet"
href="//g.alicdn.com/msui/sm/0.6.2/css/sm-extend.min.css">
<link rel="stylesheet"
href="../resources/css/frontend/shoplist/shoplist.css">
</head>
<body>
<div class="page-group">
<div class="page">
<header class="bar bar-nav">
<a class="button button-link button-nav pull-left" external
href="index" data-transition='slide-out'> <span
class="icon icon-left"></span> 返回
</a>
<h1 class="title">商店列表</h1>
</header>
<div class="bar bar-header-secondary">
<div class="searchbar">
<a class="searchbar-cancel">取消</a>
<!-- 搜索栏 -->
<div class="search-input">
<label class="icon icon-search" for="search"></label> <input
type="search" id='search' placeholder='输入关键字...' />
</div>
</div>
</div>
<nav class="bar bar-tab">
<a class="tab-item" href="/o2o/frontend/index" external> <span
class="icon icon-home"></span> <span class="tab-label">首页</span>
</a> <a class="tab-item" href="#" id="me"> <span
class="icon icon-me"></span> <span class="tab-label">我</span>
</a>
</nav>
<div class="content infinite-scroll infinite-scroll-bottom"
data-distance="100">
<!-- 类别列表展示区 -->
<div class="shoplist-button-div" id="shoplist-search-div">
<!-- <a href="#" class="button">所有货物</a>
<a href="#" class="button">吃的</a>
<a href="#" class="button">喝的</a>
<a href="#" class="button">Usual Button 1</a>
<a href="#" class="button">Usual Button 1</a>
<a href="#" class="button">Usual Button 1</a> -->
</div>
<div class="select-wrap">
<!-- 区域列表展示区 -->
<select class="select" id="area-search"></select>
</div>
<!-- 店铺列表在此添加 -->
<div class="list-div shop-list">
<!-- <div class="card">
<div class="card-header">传统火锅店</div>
<div class="card-content">
<div class="list-block media-list">
<ul>
<li class="item-content">
<div class="item-media">
<img src="http://gqianniu.alicdn.com/bao/uploaded/i4//tfscom/i3/TB10LfcHFXXXXXKXpXXXXXXXXXX_!!0-item_pic.jpg_250x250q60.jpg" width="44">
</div>
<div class="item-inner">
<div class="item-subtitle"></div>
</div>
</li>
</ul>
</div>
</div>
<div class="card-footer">
<span>2015/01/15</span>
<span>5 评论</span>
</div>
</div> -->
</div>
<div class="infinite-scroll-preloader">
<div class="preloader"></div>
</div>
</div>
</div>
</div>
<!--侧边栏 -->
<div class="panel-overlay"></div>
<div class="panel panel-right panel-reveal" id="panel-left-demo">
<div class="content-block">
<p>
<a href="/o2o/frontend/myrecord" class="close-panel">消费记录</a>
</p>
<p>
<a href="/o2o/frontend/mypoint" class="close-panel">我的积分</a>
</p>
<p>
<a href="/o2o/frontend/pointrecord" class="close-panel">积分兑换记录</a>
</p>
<!-- Click on link with "close-panel" class will close panel -->
</div>
</div>
<script type='text/javascript'
src='//g.alicdn.com/sj/lib/zepto/zepto.min.js' charset='utf-8'></script>
<script type='text/javascript'
src='//g.alicdn.com/msui/sm/0.6.2/js/sm.min.js' charset='utf-8'></script>
<script type='text/javascript'
src='//g.alicdn.com/msui/sm/0.6.2/js/sm-extend.min.js' charset='utf-8'></script>
<script type='text/javascript'
src='../resources/js/common/common.js' charset='utf-8'></script>
<script type='text/javascript'
src='../resources/js/frontend/shoplist.js' charset='utf-8'></script>
</body>
</html>
9-7 店铺列表页前端的开发下
shoplist.js:
$(function() {
var loading = false;
//分页允许返回的最大条数,超过此数则禁止访问后台
var maxItems = 999;
//一页返回的最大条数
var pageSize = 10;
//获取店铺列表的URL
var listUrl = '/o2o/frontend/listshops';
//获取店铺类别列表以及区域列表的URL
var searchDivUrl = '/o2o/frontend/listshopspageinfo';
//页码
var pageNum = 1;
//从地址栏URL里尝试获取parentId shop category id
var parentId = getQueryString('parentId');
var areaId = '';
var shopCategoryId = '';
var shopName = '';
/**
* 获取店铺类别列表以及区域列表信息
* @returns
*/
function getSearchDivData() {
//如果传入了parentId,则取出此一级类别下面的所有二级类别
var url = searchDivUrl + '?' + 'parentId=' + parentId;
$
.getJSON(
url,
function(data) {
if (data.success) {
//获取后台返回过来的店铺类别列表
var shopCategoryList = data.shopCategoryList;
var html = '';
html += '<a href="#" class="button" data-category-id=""> 全部类别 </a>';
//遍历店铺类别列表,并拼接出a标签集
shopCategoryList
.map(function(item, index) {
html += '<a href="#" class="button" data-category-id='
+ item.shopCategoryId
+ '>'
+ item.shopCategoryName
+ '</a>';
});
//将拼接好的类别标签嵌入前台的html组件里
$('#shoplist-search-div').html(html);
var selectOptions = '<option value="">全部街道</option>';
//获取后台返回过来的区域信息列表
var areaList = data.areaList;
//遍历区域信息列表,拼接出option标签集
areaList.map(function(item, index) {
selectOptions += '<option value="'
+ item.areaId + '">'
+ item.areaName + '</option>';
});
//将标签集添加进area列表里
$('#area-search').html(selectOptions);
}
});
}
//渲染出店铺类别列表以及区域列表以供搜索
getSearchDivData();
/**
* 获取分页展示的店铺列表信息
* @param pageSize
* @param pageIndex
* @returns
*/
function addItems(pageSize, pageIndex) {
// 拼接出查询的URL,赋空值默认就去掉这个的限制,有值就代表按这个条件查询
var url = listUrl + '?' + 'pageIndex=' + pageIndex + '&pageSize='
+ pageSize + '&parentId=' + parentId + '&areaId=' + areaId
+ '&shopCategoryId=' + shopCategoryId + '&shopName=' + shopName;
//设定加载符,若还在后台取数据则不能再次访问后台,避免多次重复加载
loading = true;
//访问后台获取相应查询条件下的店铺列表
$.getJSON(url, function(data) {
if (data.success) {
//获取当前查询条件下店铺的总数
maxItems = data.count;
var html = '';
//遍历店铺列表,拼接出卡片集合
data.shopList.map(function(item, index) {
html += '' + '<div class="card" data-shop-id="'
+ item.shopId + '">' + '<div class="card-header">'
+ item.shopName + '</div>'
+ '<div class="card-content">'
+ '<div class="list-block media-list">' + '<ul>'
+ '<li class="item-content">'
+ '<div class="item-media">' + '<img src="'
+ item.shopImg + '" width="44">' + '</div>'
+ '<div class="item-inner">'
+ '<div class="item-subtitle">' + item.shopDesc
+ '</div>' + '</div>' + '</li>' + '</ul>'
+ '</div>' + '</div>' + '<div class="card-footer">'
+ '<p class="color-gray">'
+ new Date(item.lastEditTime).Format("yyyy-MM-dd")
+ '更新</p>' + '<span>点击查看</span>' + '</div>'
+ '</div>';
});
//将卡片集合添加到目标HTML组件里
$('.list-div').append(html);
//获取目前为止已显示的卡片总数,包含之前已经加载的
var total = $('.list-div .card').length;
//若总数达到跟按照此查询条件列出来的总数一致,则停止后台的加载
if (total >= maxItems) {
// // 加载完毕,则注销无限加载事件,以防不必要的加载
// $.detachInfiniteScroll($('.infinite-scroll'));
// // 删除加载提示符
// $('.infinite-scroll-preloader').remove();
// 隐藏加载提示符
$('.infinite-scroll-preloader').hide();
}else{
$('.infinite-scroll-preloader').show();
}
//否则页码加1,继续load出新的店铺
pageNum += 1;
//加载结束,可以再次加载了
loading = false;
//刷新页面,显示新加载的店铺
$.refreshScroller();
}
});
}
// 预先加载20条
addItems(pageSize, pageNum);
//下滑屏幕自动进行分页搜索
$(document).on('infinite', '.infinite-scroll-bottom', function() {
if (loading)
return;
addItems(pageSize, pageNum);
});
//点击店铺的卡片进入该店铺的详情页
$('.shop-list').on('click', '.card', function(e) {
var shopId = e.currentTarget.dataset.shopId;
window.location.href = '/o2o/frontend/shopdetail?shopId=' + shopId;
});
//选择新的店铺类别之后,重置页码,清空原先的店铺列表,按照新的类别去查询
$('#shoplist-search-div').on(
'click',
'.button',
function(e) {
if (parentId) {// 如果传递过来的是一个父类下的子类
shopCategoryId = e.target.dataset.categoryId;
//若之前已选定了别的category,则移除其选定效果,改成选定新的
if ($(e.target).hasClass('button-fill')) {
$(e.target).removeClass('button-fill');
shopCategoryId = '';
} else {
$(e.target).addClass('button-fill').siblings()
.removeClass('button-fill');
}
//由于查询条件改变,清空店铺列表再进行查询
$('.list-div').empty();
//重置页码
pageNum = 1;
addItems(pageSize, pageNum);
} else {// 如果传递过来的父类为空,则按照父类查询
parentId = e.target.dataset.categoryId;
if ($(e.target).hasClass('button-fill')) {
$(e.target).removeClass('button-fill');
parentId = '';
} else {
$(e.target).addClass('button-fill').siblings()
.removeClass('button-fill');
}
//由于查询条件改变,清空店铺列表再进行查询
$('.list-div').empty();
//重置页码
pageNum = 1;
addItems(pageSize, pageNum);
parentId = '';
}
});
//需要查询的店铺名字发生变化后,重置页码,清空原先的店铺列表,按照新的名字去查询
$('#search').on('change', function(e) {
shopName = e.target.value;
$('.list-div').empty();
pageNum = 1;
addItems(pageSize, pageNum);
});
//区域信息发生变化后,重置页码,清空原先的店铺列表,按照新的区域去查询
$('#area-search').on('change', function() {
areaId = $('#area-search').val();
$('.list-div').empty();
pageNum = 1;
addItems(pageSize, pageNum);
});
//点击后打开右侧栏
$('#me').click(function() {
$.openPanel('#panel-left-demo');
});
//初始化页面
$.init();
});
shoplist.css :
.infinite-scroll-preloader {
margin-top: -5px;
}
.shoplist-button-div {
margin: 0 .3rem;
}
.shoplist-button-div > .button {
width: 30%;
height: 1.5rem;
line-height: 1.5rem;
display: inline-block;
margin: 1%;
overflow: hidden;
}
.select-wrap {
margin: 0 .5rem;
}
.select {
border: 1px solid #0894ec;
color: #0894ec;
background-color: #efeff4;
width: 100%;
height: 1.5rem;
font-size: .7rem;
}
9-8 店铺详情页的开发上
Controller层:
package com.doit.o2o.web.frontend;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import com.doit.o2o.dto.ProductExecution;
import com.doit.o2o.entity.Product;
import com.doit.o2o.entity.ProductCategory;
import com.doit.o2o.entity.Shop;
import com.doit.o2o.service.ProductCategoryService;
import com.doit.o2o.service.ProductService;
import com.doit.o2o.service.ShopService;
import com.doit.o2o.util.HttpServletRequestUtil;
@Controller
@RequestMapping("/frontend")
public class ShopDetailContoller {
@Autowired
private ShopService shopService;
@Autowired
private ProductCategoryService productCategoryService;
@Autowired
private ProductService productService;
/**
* 获取店铺信息以及该店铺下面的商品类别列表
* @param request
* @return
*/
@RequestMapping(value="/listshopdetailpageinfo",method=RequestMethod.GET)
@ResponseBody
private Map<String,Object> listShopDetailPageInfo(HttpServletRequest request){
Map<String, Object> modelMap = new HashMap<String, Object>();
long shopId = HttpServletRequestUtil.getLong(request, "shopId");
Shop shop = null;
List<ProductCategory> productCategoryList = null;
if (shopId != -1) {
//获取店铺Id为shopId的店铺信息
shop = shopService.getByShopId(shopId);
//获取店铺下面的商品类别列表
productCategoryList = productCategoryService.getProductCategoryList(shopId);
modelMap.put("shop", shop);
modelMap.put("productCategoryList", productCategoryList);
modelMap.put("success", true);
} else {
modelMap.put("success", false);
modelMap.put("errMsg", "empty shopId");
}
return modelMap;
}
/**
* 依据查询条件分页列出该店铺下面的所有商品
* @param request
* @return
*/
@RequestMapping(value = "/listproductsbyshop", method = RequestMethod.GET)
@ResponseBody
private Map<String, Object> listProductsByShop(HttpServletRequest request) {
Map<String, Object> modelMap = new HashMap<String, Object>();
//获取页码
int pageIndex = HttpServletRequestUtil.getInt(request, "pageIndex");
//获取一页需要显示的条数
int pageSize = HttpServletRequestUtil.getInt(request, "pageSize");
//获取店铺Id
long shopId = HttpServletRequestUtil.getLong(request, "shopId");
//空值判断
if ((pageIndex > -1) && (pageSize > -1) && (shopId > -1)) {
//尝试获取商品类别Id
long productCategoryId = HttpServletRequestUtil.getLong(request,
"productCategoryId");
//尝试获取模糊查找的商品名
String productName = HttpServletRequestUtil.getString(request,
"productName");
//组合查询
Product productCondition = compactProductCondition4Search(shopId,
productCategoryId, productName);
//按照传入的查询条件以及分页信息返回相应商品列表以及总数
ProductExecution pe = productService.getProductList(
productCondition, pageIndex, pageSize);
modelMap.put("productList", pe.getProductList());
modelMap.put("count", pe.getCount());
modelMap.put("success", true);
} else {
modelMap.put("success", false);
modelMap.put("errMsg", "empty pageSize or pageIndex or shopId");
}
return modelMap;
}
private Product compactProductCondition4Search(long shopId,
long productCategoryId, String productName) {
Product productCondition = new Product();
Shop shop = new Shop();
shop.setShopId(shopId);
productCondition.setShop(shop);
if (productCategoryId != -1L) {
ProductCategory productCategory = new ProductCategory();
productCategory.setProductCategoryId(productCategoryId);
productCondition.setProductCategory(productCategory);
}
if (productName != null) {
productCondition.setProductName(productName);
}
productCondition.setEnableStatus(1);
return productCondition;
}
}
9-9 店铺详情页的开发下
shopdetail.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>商店详情</title>
<meta name="viewport" content="initial-scale=1, maximum-scale=1">
<link rel="shortcut icon" href="/favicon.ico">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<link rel="stylesheet"
href="//g.alicdn.com/msui/sm/0.6.2/css/sm.min.css">
<link rel="stylesheet"
href="//g.alicdn.com/msui/sm/0.6.2/css/sm-extend.min.css">
<link rel="stylesheet"
href="../resources/css/frontend/shopdetail/shopdetail.css">
</head>
<body>
<div class="page-group">
<div class="page">
<header class="bar bar-nav">
<a class="button button-link button-nav pull-left" external href="#"
onClick="javascript :history.back(-1);" data-transition='slide-out'>
<span class="icon icon-left"></span> 返回
</a>
<h1 class="title" id="shop-name">店铺详情</h1>
</header>
<nav class="bar bar-tab">
<a class="tab-item" href="/o2o/frontend/index" external> <span
class="icon icon-home"></span> <span class="tab-label">首页</span>
</a> <a class="tab-item" href="#" id="me"> <span
class="icon icon-me"></span> <span class="tab-label">我</span>
</a>
</nav>
<div class="content infinite-scroll infinite-scroll-bottom"
data-distance="100">
<!-- 这里是页面内容区 -->
<div class="shop-detail-dev">
<div class="card">
<div valign="bottom"
class="card-header color-white no-border no-padding">
<img class='card-cover' id="shop-cover-pic" src="" alt="">
</div>
<div class="card-content">
<div class="card-content-inner">
<p class="color-gray">
<span id="shop-update-time"></span>
</p>
<p id="shop-desc"></p>
</div>
</div>
<div class="card-footer">
<!-- <a href="#" class="link">赞</a> -->
<!-- <a href="#" class="link">更多</a> -->
</div>
</div>
</div>
<!-- 商品类别列表展示区 -->
<div class="shopdetail-button-div" id="shopdetail-button-div">
<!-- <a href="#" class="button">所有货物</a>
<a href="#" class="button">吃的</a>
<a href="#" class="button">喝的</a>
<a href="#" class="button">Usual Button 1</a>
<a href="#" class="button">Usual Button 1</a>
<a href="#" class="button">Usual Button 1</a> -->
</div>
<!-- 商品名字搜索区 -->
<div class="detail-search">
<div class="searchbar">
<a class="searchbar-cancel">取消</a>
<div class="search-input">
<label class="icon icon-search" for="search"></label> <input
type="search" id='search' placeholder='输入关键字...' />
</div>
</div>
</div>
<!-- 商品列表展示区 -->
<div class="list-div">
<!-- <div class="card">
<div class="card-header">传统火锅店</div>
<div class="card-content">
<div class="list-block media-list">
<ul>
<li class="item-content">
<div class="item-media">
<img src="http://gqianniu.alicdn.com/bao/uploaded/i4//tfscom/i3/TB10LfcHFXXXXXKXpXXXXXXXXXX_!!0-item_pic.jpg_250x250q60.jpg" width="44">
</div>
<div class="item-inner">
<div class="item-subtitle"></div>
</div>
</li>
</ul>
</div>
</div>
<div class="card-footer">
<span>2015/01/15</span>
<span>5 评论</span>
</div>
</div> -->
</div>
<div class="infinite-scroll-preloader">
<div class="preloader"></div>
</div>
</div>
</div>
<!--侧边栏 -->
<div class="panel-overlay"></div>
<div class="panel panel-right panel-reveal" id="panel-left-demo">
<div class="content-block">
<p>
<a href="/o2o/frontend/myrecord" class="close-panel">消费记录</a>
</p>
<p>
<a href="/o2o/frontend/mypoint" class="close-panel">我的积分</a>
</p>
<p>
<a href="/o2o/frontend/pointrecord" class="close-panel">积分兑换记录</a>
</p>
<!-- Click on link with "close-panel" class will close panel -->
</div>
</div>
</div>
<script type='text/javascript'
src='//g.alicdn.com/sj/lib/zepto/zepto.min.js' charset='utf-8'></script>
<script type='text/javascript'
src='//g.alicdn.com/msui/sm/0.6.2/js/sm.min.js' charset='utf-8'></script>
<script type='text/javascript'
src='//g.alicdn.com/msui/sm/0.6.2/js/sm-extend.min.js' charset='utf-8'></script>
<script type='text/javascript'
src='../resources/js/common/common.js' charset='utf-8'></script>
<script type='text/javascript'
src='../resources/js/frontend/shopdetail.js' charset='utf-8'></script>
</body>
</html>
shopdetail.js:
$(function() {
var loading = false;
//分页允许返回的最大条数,超过此数则禁止访问后台
var maxItems = 20;
//默认一页返回的商品数
var pageSize = 10;
//列出商品列表的URL
var listUrl = '/o2o/frontend/listproductsbyshop';
//默认的页码
var pageNum = 1;
//从地址栏里获取shopId
var shopId = getQueryString('shopId');
var productCategoryId = '';
var productName = '';
//获取本店信息以及商品类别信息列表的URL
var searchDivUrl = '/o2o/frontend/listshopdetailpageinfo?shopId='
+ shopId;
function getSearchDivData() {
var url = searchDivUrl;
$
.getJSON(
url,
function(data) {
if (data.success) {
var shop = data.shop;
$('#shop-cover-pic').attr('src', shop.shopImg);
$('#shop-update-time').html(
new Date(shop.lastEditTime)
.Format("yyyy-MM-dd"));
$('#shop-name').html(shop.shopName);
$('#shop-desc').html(shop.shopDesc);
$('#shop-addr').html(shop.shopAddr);
$('#shop-phone').html(shop.phone);
//获取后台返回的该店铺的商品列表
var productCategoryList = data.productCategoryList;
var html = '';
//遍历商品列表,生成可以点击搜索相应商品类别下的商品的a标签
productCategoryList
.map(function(item, index) {
html += '<a href="#" class="button" data-product-search-id='
+ item.productCategoryId
+ '>'
+ item.productCategoryName
+ '</a>';
});
//将商品类别a标签绑定到相应的HTML组件中
$('#shopdetail-button-div').html(html);
}
});
}
//渲染出店铺基本信息以及商品类别列表以供搜索
getSearchDivData();
/**
* 获取分页展示的商品列表信息
* @param pageSize
* @param pageIndex
* @returns
*/
function addItems(pageSize, pageIndex) {
// 拼接处查询的URL,赋空值默认就去掉这个条件的限制
var url = listUrl + '?' + 'pageIndex=' + pageIndex + '&pageSize='
+ pageSize + '&productCategoryId=' + productCategoryId
+ '&productName=' + productName + '&shopId=' + shopId;
//设定加载符,若还在后台取数据则不能再次访问后台,避免多次重复加载
loading = true;
//访问后台获取相应查询条件下的商品列表
$.getJSON(url, function(data) {
if (data.success) {
//获取当前查询条件下的商品的总数
maxItems = data.count;
var html = '';
//遍历商品列表,拼接出卡片集合
data.productList.map(function(item, index) {
html += '' + '<div class="card" data-product-id='
+ item.productId + '>'
+ '<div class="card-header">' + item.productName
+ '</div>' + '<div class="card-content">'
+ '<div class="list-block media-list">' + '<ul>'
+ '<li class="item-content">'
+ '<div class="item-media">' + '<img src="'
+ item.imgAddr + '" width="44">' + '</div>'
+ '<div class="item-inner">'
+ '<div class="item-subtitle">' + item.productDesc
+ '</div>' + '</div>' + '</li>' + '</ul>'
+ '</div>' + '</div>' + '<div class="card-footer">'
+ '<p class="color-gray">'
+ new Date(item.lastEditTime).Format("yyyy-MM-dd")
+ '更新</p>' + '<span>点击查看</span>' + '</div>'
+ '</div>';
});
//将卡片集合添加到目标HTML组件里
$('.list-div').append(html);
//获取目前为止已显示的卡片总数,包含之前已经加载的
var total = $('.list-div .card').length;
if (total >= maxItems) {
// // 加载完毕,则注销无限加载事件,以防不必要的加载
// $.detachInfiniteScroll($('.infinite-scroll'));
// // 删除加载提示符
// $('.infinite-scroll-preloader').remove();
// 隐藏加载提示符
$('.infinite-scroll-preloader').hide();
}else{
$('.infinite-scroll-preloader').show();
}
//否则页码加1,继续load出新的店铺
pageNum += 1;
//加载结束,可以再次加载了
loading = false;
//刷新页面,显示新加载的店铺
$.refreshScroller();
}
});
}
//预先加载10条商品信息
addItems(pageSize, pageNum);
//下滑屏幕自动进行分页搜索
$(document).on('infinite', '.infinite-scroll-bottom', function() {
if (loading)
return;
addItems(pageSize, pageNum);
});
//选择新的商品类别之后,重置页码,清空原先的商品列表,按照新的类别去查询
$('#shopdetail-button-div').on(
'click',
'.button',
function(e) {
//获取商品类别Id
productCategoryId = e.target.dataset.productSearchId;
if (productCategoryId) {
//若之前已选定了别的category,则移除其选定效果,改成选定新的
if ($(e.target).hasClass('button-fill')) {
$(e.target).removeClass('button-fill');
productCategoryId = '';
} else {
$(e.target).addClass('button-fill').siblings()
.removeClass('button-fill');
}
$('.list-div').empty();
pageNum = 1;
addItems(pageSize, pageNum);
}
});
//点击商品的卡片进入该商品的详情页
$('.list-div')
.on(
'click',
'.card',
function(e) {
var productId = e.currentTarget.dataset.productId;
window.location.href = '/o2o/frontend/productdetail?productId='
+ productId;
});
//需要查询的商品名字发生变化后,重置页码,清空原先的商品列表,按照新的名字查询
$('#search').on('change', function(e) {
productName = e.target.value;
$('.list-div').empty();
pageNum = 1;
addItems(pageSize, pageNum);
});
//点击后打开右侧栏
$('#me').click(function() {
$.openPanel('#panel-left-demo');
});
$.init();
});
shopdetail.css:
.detail-search {
height: 2.2rem;
padding-right: .5rem;
padding-left: .5rem;
background-color: #f7f7f8;
}
.infinite-scroll-preloader {
margin-top: -5px;
}
.shopdetail-button-div {
margin: 0 .3rem;
}
.shopdetail-button-div > .button {
width: 30%;
height: 1.5rem;
line-height: 1.5rem;
display: inline-block;
margin: 1%;
overflow: hidden;
}
9-10 商品详情页的开发
Controller层:
package com.doit.o2o.web.frontend;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import com.doit.o2o.entity.Product;
import com.doit.o2o.service.ProductService;
import com.doit.o2o.util.HttpServletRequestUtil;
@Controller
@RequestMapping("/frontend")
public class ProductDetailController {
@Autowired
private ProductService productService;
@RequestMapping(value = "/listproductdetailpageinfo", method = RequestMethod.GET)
@ResponseBody
private Map<String, Object> listProductDetailPageInfo(
HttpServletRequest request) {
Map<String, Object> modelMap = new HashMap<String, Object>();
long productId = HttpServletRequestUtil.getLong(request, "productId");
Product product = null;
if (productId != -1) {
product = productService.getProductById(productId);
modelMap.put("product", product);
modelMap.put("success", true);
} else {
modelMap.put("success", false);
modelMap.put("errMsg", "empty productId");
}
return modelMap;
}
}
productdetail.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>商品详情</title>
<meta name="viewport" content="initial-scale=1, maximum-scale=1">
<link rel="shortcut icon" href="/favicon.ico">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<link rel="stylesheet"
href="//g.alicdn.com/msui/sm/0.6.2/css/sm.min.css">
<link rel="stylesheet"
href="//g.alicdn.com/msui/sm/0.6.2/css/sm-extend.min.css">
<link rel="stylesheet"
href="../resources/css/frontend/productdetail/productdetail.css">
</head>
<body>
<div class="page-group">
<div class="page">
<header class="bar bar-nav">
<a class="button button-link button-nav pull-left" external href="#"
onClick="javascript :history.back(-1);" data-transition='slide-out'>
<span class="icon icon-left"></span> 返回
</a>
<h1 class="title">商品详情</h1>
</header>
<nav class="bar bar-tab">
<a class="tab-item" href="/o2o/frontend/index" external> <span
class="icon icon-home"></span> <span class="tab-label">首页</span>
</a> <a class="tab-item" href="#" id="me"> <span
class="icon icon-me"></span> <span class="tab-label">我</span>
</a>
</nav>
<div class="content infinite-scroll infinite-scroll-bottom"
data-distance="100">
<!-- 这里是页面内容区 -->
<div class="shop-detail-dev">
<div class="card">
<div valign="bottom"
class="card-header color-white no-border no-padding">
<img id="product-img" class='card-cover' src="" alt="">
</div>
<div class="card-content">
<div class="card-content-inner">
<p class="color-gray">
<span id="product-time">2015/01/15</span>
</p>
<p id="product-name"></p>
<p id="product-desc"></p>
</div>
</div>
<div class="card-footer" id="imgList">
<!-- <a href="#" class="link">赞</a> -->
<!-- <a href="#" class="link">更多</a> -->
</div>
</div>
</div>
<div class="list-div"></div>
</div>
</div>
<div class="panel-overlay"></div>
<div class="panel panel-right panel-reveal" id="panel-left-demo">
<div class="content-block">
<p>
<a href="/o2o/frontend/myrecord" class="close-panel">消费记录</a>
</p>
<p>
<a href="/o2o/frontend/mypoint" class="close-panel">我的积分</a>
</p>
<p>
<a href="/o2o/frontend/pointrecord" class="close-panel">积分兑换记录</a>
</p>
<!-- Click on link with "close-panel" class will close panel -->
</div>
</div>
</div>
<script type='text/javascript'
src='//g.alicdn.com/sj/lib/zepto/zepto.min.js' charset='utf-8'></script>
<script type='text/javascript'
src='//g.alicdn.com/msui/sm/0.6.2/js/sm.min.js' charset='utf-8'></script>
<script type='text/javascript'
src='//g.alicdn.com/msui/sm/0.6.2/js/sm-extend.min.js' charset='utf-8'></script>
<script type='text/javascript'
src='../resources/js/common/common.js' charset='utf-8'></script>
<script type='text/javascript'
src='../resources/js/frontend/productdetail.js' charset='utf-8'></script>
</body>
</html>
productdetail.js:
$(function() {
var productId = getQueryString('productId');
var productUrl = '/o2o/frontend/listproductdetailpageinfo?productId='
+ productId;
$
.getJSON(
productUrl,
function(data) {
if (data.success) {
var product = data.product;
$('#product-img').attr('src', product.imgAddr);
$('#product-time').text(
new Date(product.lastEditTime)
.Format("yyyy-MM-dd"));
$('#product-name').text(product.productName);
$('#product-desc').text(product.productDesc);
var imgListHtml = '';
product.productImgList.map(function(item, index) {
imgListHtml += '<div> <img src="'
+ item.imgAddr + '"/></div>';
});
// // 生成购买商品的二维码供商家扫描
// imgListHtml += '<div> <img src="/o2o/frontend/generateqrcode4product?productId='
// + product.productId + '"/></div>';
// $('#imgList').html(imgListHtml);
}
});
$('#me').click(function() {
$.openPanel('#panel-left-demo');
});
$.init();
});
productdetail.css:
.shopdetail-button-div {
margin: 0 .3rem;
}
.shopdetail-button-div > .button {
width: 30%;
height: 1.5rem;
line-height: 1.5rem;
display: inline-block;
margin: 1%;
overflow: hidden;
}
9-11 前端展示系统bug修复
略
9-12 前端展示系统开发总结
略