电商项目day11(商品搜索功能实现&排序&结果分页)

今日目标:

    完成关键字搜索功能
    能够实现高亮显示效果
    完成查询分类列表的功能
    完成条件过滤构建功能
    完成分页动态页码展示

一、完成关键字搜索

1.首先构建工程    pinyougou_search_interface    pinyougou_search_service    pinyougou_search_web

参考content的工程,因为也不需要安全框架

2.关键字的需求分析

我们分析输入关键字,可以通过商品或者商家或者title等四个参数进行所有

参数的分析:首先我们的返回的参数可能是itemList   规格  品牌   分类   价格区间    当前页   每页显示的条数,两种方法,一种是自己封装一个类,把这些参数封装起来,还有一种是通过Map实现,因为考虑到还要维护这个类,所以我们采用map的方式进行封装

后端代码实现:

service层的代码实现过程
/**
 * 搜索功能的实现类
 */
@Service
@Transactional
public class SearchServiceImpl implements SearchService {

    @Autowired
    private SolrTemplate solrTemplate;//注意添加solr的配置文件
    @Override
    public Map<String, Object> search(Map searchMap) {
        //创建高亮显示对象
        HighlightQuery query = new SimpleHighlightQuery();//接口我们通过其子类实现即可
 // 一.  1.关键字搜索
        String keywords = (String) searchMap.get("keywords");
        Criteria criteria = null;
        //2.判断关键字是否为空
        if (keywords!=null&&!"".equals(keywords)){
            //不等于空
            //输入关键字条件条件
            criteria = new Criteria("item_keywords").is(keywords);
        }else{
            //关键字为空,查询所有 通过一个表达式  *:*
            criteria = new Criteria().expression("*:*");
        }

        //3.将查询的条件添加到criteria中
        query.addCriteria(criteria);
        //4.这个条件已经封装了,query需要查询的所有条件
        HighlightPage<TbItem> page = solrTemplate.queryForHighlightPage(query, TbItem.class);
        //当前页的信息
        List<TbItem>  content = page.getContent();
        Map<String,Object> resultMap = new HashMap<>();
        resultMap.put("rows",content);
        return resultMap;
    }
}
接口方法;
/**
 * 搜索接口的方法
 */
public interface SearchService {
    //商品的搜索参数   通过map格式,Object是不同的类型,包括品牌,规格,分类 价格区间 每页显示条数 每页记录数
    public Map<String,Object> search(Map searchMap);
}

controller层的实现

@RestController
@RequestMapping("search")
public class SearchController {

    @Reference
    private SearchService searchService;

    /**
     * 搜索功能那的实现
     * @param searchMap
     * @return
     */
    @RequestMapping("searchMap")
    Map <String,Object> search(@RequestBody Map searchMap){
      return  searchService.search(searchMap);
    }
}

前台代码的实现:

controller层

app.controller("searchController",function ($scope,$controller,searchService) {

    //控制器继承代码
    $controller("baseController",{$scope:$scope});

    //构建封装搜索条件的对象
    $scope.searchMap={
      keywords:"",
        category:"",
        brand:"",
        spec:{},//规格属性,需要规格名称和规格选项
        price:"",
        sort:"ASC",
        sortField:"",
        pageNo:1,//当前页
        pageSize:60//每页记录数
    };
    //商品搜索
    $scope.search=function () {
        searchService.search($scope.searchMap).success(function (response) {
            $scope.resultMap=response;
            //构建分页工具条
            //
        })
    }
    
})

service:

//服务层
app.service('searchService',function($http){

    //搜索功能的实现
    this.search=function(searchMap){
        return $http.post('itemsearch/search.do',searchMap);
    }
});

注意:一定要把方法里面的参数写对

二.实现搜索高亮显示

思路分析:我们通过在一个搜索关键字上添加前缀和后缀,以此来显示关键字的高亮,我们把业务模块都写在service层

我们通过分析,在返回值的resultMap中的title没有设置高亮的样式,那么我们继续往上面找,如上图所示,我们通过遍历highlighted来获取,注意判断里面的list集合是否为空,得到值后直接进行赋值操作

后端代码实现:

//当前页的信息
        List<TbItem>  content = page.getContent();
        for (TbItem item : content) {
            //处理高亮结果
            List<HighlightEntry.Highlight> highlights = page.getHighlights(item);
            //判断highlightsshif为空
            if (highlights!=null&& highlights.size()>0){
                //获取高亮结果集
                List<String> snipplets = highlights.get(0).getSnipplets();
                //在判断是否为空
                if (snipplets!=null&& snipplets.size()>0){
                    item.setTitle(snipplets.get(0));
                }
            }
        }

注意出现这个问题,html代码直接没有被解析而是直接显示在页面上,这是angularjs出于安全考虑,防止hmtl注入,我们将设置权限

我们写一个filter的过滤器

定义过滤器,处理字符串为HTML标签
//使用方式:<em ng-bind-html="带标签的数据 | trustHtml"></em>
app.filter("trustHtml",function($sce){
	return function(data){
		return $sce.trustAsHtml(data);
	};
});

页面处理:

通过angularjs的一个指令实现:

<em ng-bind-html="entity.title | trustHtml"></em>

效果如图:

三.过滤添加条件

思路分析:在这我们只涉及一些写死的数据提交,也可以通过查询实现,分类,品牌,以及规格的显示,通过模板关联品牌和规格,注意:规格我们需要提交精确的其值,那么我们需要判断要对那个条件进行封装

1.组合查询条件的实现  

前端代码实现:

 //组合条件的查询
    $scope.addFilterCondition=function (key,value) {
        if (key=="category" || key=="price" || key=="brand"){
            $scope.searchMap[key]=value;
        }else{
            $scope.searchMap.spec[key]=value;
        }

        //调用查询方法
        $scope.search();
    }

后台实现:

 //3.将查询的条件添加到criteria中
        query.addCriteria(criteria);
        //三.1.构建分类的查询条件
        String category = (String) searchMap.get("category");
        //2.判断查询条件是否为空
        if (category!=null&&!"".equals(category)){
            //构建分类查询条件
            Criteria categoryCriteria = new Criteria("item_category").is(category);
            //构建过滤条件查询
            FilterQuery filterQuery = new SimpleFilterQuery(categoryCriteria);
            //将查询的条件添加到query 中
            query.addFilterQuery(filterQuery);
        }
        //四.构建品牌查询条件
        String brand = (String)searchMap.get("brand");
        //判断是否为空
        if (brand!=null&&!"".equals(brand)){
            //构建品牌查询提哦案件
            Criteria brandCriteria = new Criteria("item_brand").is(brand);
            //构建过滤条件查询
            FilterQuery filterQuery  = new SimpleFilterQuery(brandCriteria);
            //将查询的条件添加到总的query 中
            query.addFilterQuery(filterQuery);
        }

2.规格的功能的实现,由于我们分装的是一个实体类 spec  所以我们也没有必要在创建一个实体类,我们通过Map格式封装

后台代码实现:

//五.  封装规格
        //获取spec的对象格式
        Map<String,String> specMap = (Map<String, String>) searchMap.get("spec");
        //判断map的结果是否Wie空
        if (specMap!=null){
            //通过遍历它的key值,获得value值,就是规格选项的值
            for (String key: specMap.keySet()){
                //构建品牌查询提哦案件
                Criteria specificationCriteria = new Criteria("item_spec_"+key).is(specMap.get(key));
                //构建过滤条件查询
                FilterQuery filterQuery  = new SimpleFilterQuery(specificationCriteria);
                //将查询的条件添加到总的query 中
                query.addFilterQuery(filterQuery);
            }
        }

3.根据价格实现功能

思路:我们要对字符串进行判断处理,splic("-")   然后通过这个第一个值  0 和最后一个值*  判断

 //六.价格的条件查询
        String price = (String)searchMap.get("price");
        //分析:
        /*
        ('price','0-500')
        ('price','500-1000')
        ('price','1000-1500')
        ('price','2000-3000')
          ('price','3000-*')分析可知通过分隔符分开,然后分割后成为一个数组,最后
          通过临界值判断
         */
        //判断是否为空
        if (price!=null&&!"".equals(price)){
            String[] split = price.split("-");
            //通过价格临界值判断
            if (!"0".equals(split[0])){
                //构建查询条件  大于0这个区间
                Criteria priceCriteria= new Criteria("item_price").greaterThanEqual(split[0]);
                //构建过滤条件查询
                FilterQuery filterQuery  = new SimpleFilterQuery(priceCriteria);
                //将查询的条件添加到总的query 中
                query.addFilterQuery(filterQuery);
            }

            //通过* 判断  小于等于1的这个区间
            if (!"*".equals(split[1])){
                //构建查询条件
                Criteria priceCriteria= new Criteria("item_price").lessThanEqual(split[1]);
                //构建过滤条件查询
                FilterQuery filterQuery  = new SimpleFilterQuery(priceCriteria);
                //将查询的条件添加到总的query 中
                query.addFilterQuery(filterQuery);
            }
        }

 

四.排序功能实现

需求:

实现如下图:

查询操作实现,新品和价格排序

 

 

 

 

这个是上一个模块移除的内容,点击已经添加的条件,实现移除的功能

思路:我们通过点击传过来的的key值,删除value注意还要判断是spec,因为这个是对象,我们通过这个delete   方法删除这个key以及value

//移除查询条件操作  //通过key移除值
$scope.removeSearchItem=function (key) {

    if (key=="category" || key=="price" || key=="brand"){
        $scope.searchMap[key]="";
    }else{
      delete  $scope.searchMap.spec[key];
    }
    //调用查询方法
    $scope.search();
}

五.搜索分页功能实现

思想:通过传过来pageNo当前页,pageSize总页数,作为条件,后台做处理,然后返回给前台

 

后台代码:

 //八.构建分页查询
        Integer pageNo = (Integer) searchMap.get("pageNo");
        Integer pageSize = (Integer) searchMap.get("pageSize");
        query.setOffset((pageNo-1)*pageSize);//设置分页起始值
        query.setRows(pageSize);//设置总页数
//最后还的封装一下
 Map<String,Object> resultMap = new HashMap<>();
        resultMap.put("rows",content);
        resultMap.put("totalpagee",page.getTotalPages());//总页数
        resultMap.put("pageNo",pageNo);//当前页
        return resultMap;

前台代码实现:

   //构建分页工具条代码
    buildPageLabel=function(){
        $scope.pageLabel = [];// 新增分页栏属性,存放分页的页面
        var maxPageNo = $scope.resultMap.totalPages;// 得到最后页码

        // 定义属性,显示省略号
        $scope.firstDot = true;
        $scope.lastDot = true;

        var firstPage = 1;// 开始页码
        var lastPage = maxPageNo;// 截止页码

        if ($scope.resultMap.totalPages > 5) { // 如果总页数大于5页,显示部分页码
            if ($scope.resultMap.pageNo <= 3) {// 如果当前页小于等于3
                lastPage = 5; // 前5页
                // 前面没有省略号
                $scope.firstDot = false;

            } else if ($scope.searchMap.pageNo >= lastPage - 2) {// 如果当前页大于等于最大页码-2
                firstPage = maxPageNo - 4; // 后5页
                // 后面没有省略号
                $scope.lastDot = false;
            } else {// 显示当前页为中心的5页
                firstPage = $scope.searchMap.pageNo - 2;
                lastPage = $scope.searchMap.pageNo + 2;
            }
        } else {
            // 页码数小于5页  前后都没有省略号
            $scope.firstDot = false;
            $scope.lastDot = false;
        }
        // 循环产生页码标签
        for (var i = firstPage; i <= lastPage; i++) {
            $scope.pageLabel.push(i);
        }
    }


    //分页查询
    $scope.queryForPage=function(pageNo){
        $scope.searchMap.pageNo=pageNo;

        //执行查询操作
        $scope.search();

    }

    //分页页码显示逻辑分析:
    // 1,如果页面数不足5页,展示所有页号
    // 2,如果页码数大于5页
    // 1) 如果展示最前面的5页,后面必须有省略号.....
    // 2) 如果展示是后5页,前面必须有省略号
    // 3) 如果展示是中间5页,前后都有省略号

    // 定义函数,判断是否是第一页
    $scope.isTopPage = function() {
        if ($scope.searchMap.pageNo == 1) {
            return true;
        } else {
            return false;
        }
    }
    // 定义函数,判断是否最后一页
    $scope.isLastPage = function() {
        if ($scope.searchMap.pageNo == $scope.resultMap.totalPages) {
            return true;
        } else {
            return false;
        }
    }

六.总结

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

奋斗的小巍

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值