1.实现了上架对商品上架和下架操作之后将solr中数据的同步
pyg_shop_web商家模块:
GoodsController.java中
@RequestMapping("/updateStatus")
public Result updateStatus(Long[] ids, String status) {
try {
goodsService.updateStatus(ids, status);
//如果商品上架或者是下架,就去把数据添加到solr中或者从solr中移除
if ("5".equals(status)) {
//就是上架,就要把新的SKU数据添加到solr中
itemSearchService.importItems(ids);
}
if ("6".equals(status)) {
//就是下架,将solr中对应的SKU数据删除
itemSearchService.removeItems(ids);
}
return new Result(true, "修改商品状态成功");
} catch (Exception e) {
e.printStackTrace();
return new Result(false, "修改商品状态失败");
}
}
因为用到了dubbo中的itemSearchService对象,所以就要在pyg_shop_web模块的pom文件中加入依赖
<dependency>
<groupId>com.fighting</groupId>
<artifactId>pyg_search_interface</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
在ItemSearchServiceImpl.java中写对两个对应的方法
//上架,就要把新的SKU数据添加到solr中
@Override
public void importItems(Long[] ids) {//参数传入的是商品的id,要把商品对应的所有SKU的数据都增
TbItemExample example = new TbItemExample();
example.createCriteria().andGoodsIdIn(Arrays.asList(ids));
List<TbItem> itemList = tbItemMapper.selectByExample(example);
solrTemplate.saveBeans(itemList);
solrTemplate.commit();
}
//下架,将solr中对应的SKU数据删除
@Override
public void removeItems(Long[] ids) {//参数传入的是商品的id,要把商品对应的所有SKU的数据都删
TbItemExample example = new TbItemExample();
example.createCriteria().andGoodsIdIn(Arrays.asList(ids));
List<TbItem> itemList = tbItemMapper.selectByExample(example);
for (TbItem item : itemList) {
solrTemplate.deleteById(item.getId().toString());
}
solrTemplate.commit();
}
因为用到了tbItemMapper这个对象去数据库中进行查询对应的所有SKU,所以在pyg_search_service模块的pom文件中加入依赖
<dependency>
<groupId>com.fighting</groupId>
<artifactId>pyg_dao</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
2.实现了SKU商品title(标题)的高亮显示
ItemSearchServiceImpl.java中的itemSearch方法:
//设置高亮选项部分
//首先声明高亮选项
HighlightOptions options = new HighlightOptions();
//添加需要高亮的域
options.addField("item_title");
//设置如何添加高亮
options.setSimplePrefix("<em style='color:red'>");
options.setSimplePostfix("</em>");
SimpleHighlightQuery simpleHighlightQuery = new SimpleHighlightQuery();
simpleHighlightQuery.setHighlightOptions(options);
//现在从solr中查询出来的数据中item_title域中并没有添加上需要高亮的内容,要从snipplets中获取
//将查询出来的数据在想要高亮的部分添加上高亮的效果
for (TbItem item : itemList) {
List<HighlightEntry.Highlight> highlights = highlightPage.getHighlights(item);
if (highlights != null && highlights.size() > 0) {//防止取第一个元素出现空值
List<String> snipplets = highlights.get(0).getSnipplets();
if (snipplets != null && snipplets.size() > 0) {//防止取第一个元素出现空值
item.setTitle(snipplets.get(0));
}
}
}
searchController.js中
//angularjs的过滤器'$sce安全规格的指令,名字是trustHtml
app.filter('trustHtml', ['$sce', function ($sce) {
return function (data) {
return $sce.trustAsHtml(data);
}
}]);
search.html中,这样不用写标题也行
<!--页面标题部分需要调用过滤器-->
<div class="attr" ng-bind-html="item.title | trustHtml">
<!--<em>{{item.title}}</em>-->
</div>
3.实现了过滤查询增加分类条件
search.html中:
<div class="type-wrap">
<div class="fl key">分类</div>
<div class="fl value"><button href="#" ng-click="addFilterCondition('category','手机')">手机</button></div>
<div class="fl value"><button href="#" ng-click="addFilterCondition('category','平板电脑')">平板电脑</button></div>
<div class="fl value"><button href="#" ng-click="addFilterCondition('category','电视')">电视</button></div>
<div class="fl value"><button href="#" ng-click="addFilterCondition('category','电子书')">电子书</button></div>
<div class="fl value"><button href="#" ng-click="addFilterCondition('category','电影票')">电影票</button></div>
<div class="fl ext"></div>
</div>
searchController.js中:
//实现过滤查询
$scope.addFilterCondition = function (key, value) {
//将传过来的key和value传入到searchMap中
if (key == 'brand' || key == 'category' || key == 'price') {
//如果选的是商品分类或者品牌
$scope.searchMap[key] = value;
} else {
//如果选的是规格
$scope.searchMap.spec[key] = value;//{'brand':'三星',spec:{屏幕尺寸:'40寸'}}
}
//再调用查询方法
$scope.itemSearch();
}
ItemSearchServiceImpl.java中的itemSearch方法:
//接收页面的商品分类
String category = (String) searchMap.get("category");
if (category != null && category.length() > 0) {
//增加过滤查询条件
SimpleFilterQuery filterQuery = new SimpleFilterQuery();
//将查询条件封装到Criteria中,参数是对应的域(过滤查询的域一般是普通域)
Criteria criteria = new Criteria("item_category");
//设置查询条件
criteria = criteria.contains(category);
filterQuery.addCriteria(criteria);
//过滤查询
simpleHighlightQuery.addFilterQuery(filterQuery);
}
4.实现了过滤查询增加品牌条件
search.html中:
<div class="fl key brand">品牌</div>
<div class="value logos">
<ul class="logo-list">
<li><a href="#" ng-click="addFilterCondition('brand','三星')">三星</a></li>
<li><a href="#" ng-click="addFilterCondition('brand','小米')">小米</a></li>
<li><a href="#" ng-click="addFilterCondition('brand','苹果')">苹果</a></li>
<li><a href="#" ng-click="addFilterCondition('brand','联想')">联想</a></li>
<li><a href="#" ng-click="addFilterCondition('brand','锤子')">锤子</a></li>
<li><a href="#" ng-click="addFilterCondition('brand','TCL')">TCL</a></li>
</ul>
</div>
ItemSearchServiceImpl.java中的itemSearch方法:
//接收页面的商品的品牌分类
String brand = (String) searchMap.get("brand");
if (brand != null && brand.length() > 0) {
//增加过滤查询条件
SimpleFilterQuery filterQuery = new SimpleFilterQuery();
//将查询条件封装到Criteria中,参数是对应的域(过滤查询的域一般是普通域)
Criteria criteria = new Criteria("item_brand");
//设置查询条件
criteria = criteria.contains(brand);
filterQuery.addCriteria(criteria);
//过滤查询
simpleHighlightQuery.addFilterQuery(filterQuery);
}
5.实现了过滤搜索增加规格条件
在TbItem.java这个pojo对象增加一个字段
@Dynamic //动态域需要增加注解,记得生成getter,setter方法
@Field("item_spec_*") //对应得字段
private Map<String,String> specMap; //注意泛型中的String类型
pyg_solr_util模块中SolrUtil.java工具类中修改向solr中导入数据的方法,然后从新执行导入数据,新的数据会覆盖旧的数据
@Test
public void importItemData(){
//获取所有SKU列表的信息
List<TbItem> itemList = itemMapper.selectByExample(null);
for(TbItem item:itemList){
System.out.println(item.getId()+" "+ item.getTitle()+ " "+item.getPrice());
Map<String,String> specMap = JSON.parseObject(item.getSpec(), Map.class);//从数据库中提取规格json字符串转换为map
item.setSpecMap(specMap);
}
//将所有的SKU列表信息保存到solr的域中
solrTemplate.saveBeans(itemList);
//提交
solrTemplate.commit();
}
重新导入成功后solr中每条item数据显示的效果
search.html部分
<div class="type-wrap">
<div class="fl key">机身内存</div>
<div class="fl value">
<ul class="type-list">
<li><a href="#" ng-click="addFilterCondition('机身内存','8G')">8G</a></li>
<li><a href="#" ng-click="addFilterCondition('机身内存','16G')">16G</a></li>
<li><a href="#" ng-click="addFilterCondition('机身内存','32G')">32G</a></li>
<li><a href="#" ng-click="addFilterCondition('机身内存','64G')">64G</a></li>
</ul>
</div>
<div class="fl ext"></div>
</div>
<div class="type-wrap">
<div class="fl key">网络</div>
<div class="fl value">
<ul class="type-list">
<li><a href="#" ng-click="addFilterCondition('网络','联通3G')">联通3G</a></li>
<li><a href="#" ng-click="addFilterCondition('网络','联通4G')">联通4G</a></li>
<li><a href="#" ng-click="addFilterCondition('网络','移动3G')">移动3G</a></li>
<li><a href="#" ng-click="addFilterCondition('网络','移动4G')">移动4G</a></li>
</ul>
</div>
<div class="fl ext"></div>
</div>
ItemSearchServiceImpl.java中的itemSearch方法:
//接收页面传过来的规格
Map<String, String> mapSpec = (Map<String, String>) searchMap.get("spec");
if (mapSpec != null) {
for (String key : mapSpec.keySet()) {
SimpleFilterQuery filterQuery = new SimpleFilterQuery();
Criteria criteria = new Criteria("item_spec_" + key);//根据动态生成的域查找
criteria = criteria.contains(mapSpec.get(key));
filterQuery.addCriteria(criteria);
simpleHighlightQuery.addFilterQuery(filterQuery);
}
}
6.实现了过滤搜索增加价格条件
search.html页面:
<div class="fl key">价格</div>
<div class="fl value">
<ul class="type-list">
<li><a href="#" ng-click="addFilterCondition('price','0-500')">0-500元</a></li>
<li><a href="#" ng-click="addFilterCondition('price','500-1000')">500-1000元</a></li>
<li><a href="#" ng-click="addFilterCondition('price','1000-1500')">1000-1500元</a></li>
<li><a href="#" ng-click="addFilterCondition('price','1500-2000')">1500-2000元</a></li>
<li><a href="#" ng-click="addFilterCondition('price','2000-3000')">2000-3000元</a></li>
<li><a href="#" ng-click="addFilterCondition('price','3000-*')">3000元以上</a></li>
</ul>
</div>
<div class="fl ext">
</div>
ItemSearchServiceImpl.java中的itemSearch方法:
//接收页面传过来的价格
String price=(String)searchMap.get("price");
if(price!=null&&price.length()>0){
String[] priceArr = price.split("-");
SimpleFilterQuery filterQuery = new SimpleFilterQuery();
Criteria criteria=new Criteria("item_price");
criteria=criteria.greaterThanEqual(priceArr[0]);
filterQuery.addCriteria(criteria);
simpleHighlightQuery.addFilterQuery(filterQuery);
if(!"*".equals(priceArr[1])){
SimpleFilterQuery filterQuery2 = new SimpleFilterQuery();
Criteria criteria2 = new Criteria("item_price");
criteria2=criteria2.lessThanEqual(priceArr[1]);
filterQuery2.addCriteria(criteria2);
simpleHighlightQuery.addFilterQuery(filterQuery2);
}
}
7.实现了搜索SKU商品按价格排序展示
search.html页面:
<li>
<a href="#" ng-click="sortSearch('ASC')">价格⬆</a>
</li>
<li>
<a href="#" ng-click="sortSearch('DESC')">价格⬇</a>
</li>
searchController.js中
//实现页面商品排序是升序还是降序
$scope.sortSearch = function (value) {
$scope.searchMap.sort = value;
$scope.itemSearch();
}
别忘了定义完方法之后给对象初始化,默认升序
//初始化searchMap
$scope.searchMap = {keyWords: '三星', spec: {}, sort: "ASC"};
ItemSearchServiceImpl.java中的itemSearch方法:
//接收页面传递过来的价格
String sort= (String) searchMap.get("sort");
if("ASC".equals(sort)){
//按价格升序排列
Sort s = new Sort(Sort.Direction.ASC, "item_price");
simpleHighlightQuery.addSort(s);
}else {
//按价格降序排列
Sort s = new Sort(Sort.Direction.DESC, "item_price");
//直接将排序条件赋给simpleHighlightQuery对象
simpleHighlightQuery.addSort(s);
}
8.实现了把过滤查询增加的条件放到页面的面包屑上并完成搜索(纯前端):
search.html页面:
<ul class="tags-choose">
<li ng-if="searchMap.category != null" class="tag">{{searchMap.category}}<i class="sui-icon icon-tb-close" ng-click="removeSearchItem('category')"></i></li>
<li ng-if="searchMap.brand != null" class="tag">{{searchMap.brand}}<i class="sui-icon icon-tb-close" ng-click="removeSearchItem('brand')"></i></li>
<li ng-repeat="(key,value) in searchMap.spec" class="tag">{{key}}:{{value}}<i class="sui-icon icon-tb-close" ng-click="removeSearchItem(key)"></i></li>
<li ng-if="searchMap.price != null" class="tag">{{searchMap.price}}<i class="sui-icon icon-tb-close" ng-click="removeSearchItem('price')"></i></li>
</ul>
searchController.js中,给关闭按钮绑定的方法
//实现点击面包屑关闭后取消上面显示的条件
$scope.removeSearchItem = function (key) {
if (key == 'brand' || key == 'category' || key == 'price') {
delete $scope.searchMap[key];
} else {
delete $scope.searchMap.spec[key];
}
$scope.itemSearch();
}
9.实现了商品数据的分页显示
search.html中:
引入相关样式文件
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" />
<title>产品列表页</title>
<meta content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no" name="viewport">
<link rel="icon" href="assets/img/favicon.ico">
<script src="plugins/jquery/jquery.min.js"></script>
<script src="plugins/bootstrap/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="plugins/bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="css/webbase.css" />
<link rel="stylesheet" type="text/css" href="css/pages-list.css" />
<link rel="stylesheet" type="text/css" href="css/widget-cartPanelView.css" />
<script src="plugins/angularjs/angular.min.js"></script>
<script type="text/javascript" src="plugins/angularjs/pagination.js"></script>
<link rel="stylesheet" href="plugins/angularjs/pagination.css">
<script type="text/javascript" src="js/base_pagination.js"> </script>
<script src="js/service/searchService.js" ></script>
<script src="js/controller/searchController.js" ></script>
</head>
引入分页控件和分页控件配置
<div class="fr page">
<tm-pagination conf="paginationConf" />
<div class="sui-pagination pagination-large "></div>
</div>
searchController.js中:
引入分页控件配置
//分页控件配置
$scope.paginationConf = {
currentPage: 1,
totalItems: 10,
itemsPerPage: 10,
perPageOptions: [10, 20, 30, 40, 50],
onChange: function () {
$scope.searchMap.pageNum=$scope.paginationConf.currentPage
$scope.searchMap.pageSize=$scope.paginationConf.itemsPerPage;
$scope.itemSearch();//重新加载
}
};
ItemSearchServiceImpl.java中的itemSearch方法:
//设置分页
Integer pageNum=(Integer)searchMap.get("pageNum");
Integer pageSize=(Integer)searchMap.get("pageSize");
//设置起始记录位置
simpleHighlightQuery.setOffset((pageNum - 1) * pageSize);
//设置每页记录数
simpleHighlightQuery.setRows(pageSize);
//页面需要返回一个总记录数
因为页面的分页配置需要获取一个totalItems(总记录数)
searchController.js中返回总记录数并赋值:
//查询SKU商品
$scope.itemSearch = function () {
searchService.itemSearch($scope.searchMap).success(
function (response) {
$scope.itemList = response.content;
//还返回一个总记录数
$scope.paginationConf.totalItems=response.total;
}
)
}
规律:页面商品价格的排序和设置分页还有搜索栏中去复制域中搜索都是将条件添加给了HighlightOptions,其它的过滤查询增加的条件都添加给了SimpleHighlightQuery