确保gulimall-search 服务开启注册中心并加入到nacos中
gulimall-search 服务下:
动静分离
给gulimall-search服务加入依赖Thymeleaf依赖
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-thymeleafartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-devtoolsartifactId>
dependency>
将2.分布式高级篇/代码/html/搜索页
路径下的 index.html首页复制到 gulimall-search服务src/main/resources/templates
路径下
将2.分布式高级篇/代码/html/搜索页
路径下的 所有其他静态资源复制到 nginx 的
hgw@HGWdeAir search % pwd
/Users/hgw/Documents/Software/mydata/nginx/html/static/search
hgw@HGWdeAir search % ll
total 0
drwxrwxr-x@ 4 hgw staff 128B 3 22 2020 css
drwxrwxr-x@ 12 hgw staff 384B 3 22 2020 font
drwxrwxr-x@ 68 hgw staff 2.1K 3 22 2020 image
drwxrwxr-x@ 86 hgw staff 2.7K 3 22 2020 img
drwxrwxr-x@ 4 hgw staff 128B 3 22 2020 js
drwxrwxr-x@ 3 hgw staff 96B 3 22 2020 sass
修改index.html 的静态资源请求路径
href=" --> href="/static/search/
src=" --> src="/static/search/
配置 Nginx 和 网关
修改本地的 hosts文件 vim /etc/hosts
# Gulimall Host Start
127.0.0.1 gulimall.cn
127.0.0.1 search.gulimall.cn
# Gulimall Host End
配置Nginx(将search下的请求转给网关)
hgw@HGWdeAir conf.d % pwd
/Users/hgw/Documents/Software/mydata/nginx/conf/conf.d
hgw@HGWdeAir conf.d % vim gulimall.conf
server {
listen 80;
server_name gulimall.cn *.gulimall.cn;
重启nginx容器:docker restart nginx
配置网关
修改gulimall-gateway服务 /src/main/resources
路径下的 application.yml
- id: gulimall_host_route
uri: lb://gulimall-product
predicates:
- Host=gulimall.cn
- id: gulimall_search_route
uri: lb://gulimall-search
predicates:
- Host=search.gulimall.cn
访问 :http://search.gulimall.cn/ ,成功跳转
调整页面跳转
修改gulimall-search服务中的index.html文件名修改为 list.html
,并
修改的list.html中首页的请求路径为:http://gulimall.cn
修改nginx 静态资源路径下的mydata/nginx/html/static/index/js
下的 catalogLoader.js 中的gmall请求为你自己的请求:
var cata3link = $("+ctg3.id+"\" style=\"color: #999;\">" + ctg3.name + "");
搜索 search()
,进行修改
<a href="javascript:search();"><img src="/static/index/img/img_09.png" /></a>
function search() {
var keyword=$("#searchText").val()
window.location.href="http://search.gulimall.cn/list.html?keyword="+keyword;
}
调整页面跳转
修改gulimall-search服务中的index.html文件名修改为 list.html
,并
修改的list.html中首页的请求路径为:http://gulimall.cn
修改nginx 静态资源路径下的mydata/nginx/html/static/index/js
下的 catalogLoader.js 中的gmall请求为你自己的请求:
var cata3link = $("+ctg3.id+"\" style=\"color: #999;\">" + ctg3.name + "");
搜索 search()
,进行修改
<a href="javascript:search();"><img src="/static/index/img/img_09.png" /></a>
function search() {
var keyword=$("#searchText").val()
window.location.href="http://search.gulimall.cn/list.html?keyword="+keyword;
}
搜索条件分析
商品检索三个入口:
完整查询参数:catalog3Id=225&keyword=小米&sort=saleCount_desc/asc&hasStock=0/1&brandId=1&brandId=2&attrs=1_其他:安卓&attrs=2_5寸
封装页面所有可能传递过来的查询条件
com.atguigu.gulimall.search.vo
路径下
@Data
public class SearchParam {
private String keyword; // 页面传递过来的检索参数,相当于全文匹配关键字
private Long catalog3Id; // 三级分类的id
/**
* sort=saleCount_desc/asc
* sort=skuPrice_asc/desc
* sort=hotScore_asc/desc
*/
private String sort; // 排序条件
/**
* 好多的过滤条件
* hasStock、skuPrice区间、brandId、catalog3Id、
* hasStock=0/1
* skuPrice=1_500/_500/500_
* brandId=1
*
*/
private Integer hasStock=1; // 是否只显示有货 v 0(无库存) 1(有库存)
private String skuPrice; // 价格区间查询
private List<Long> brandId; // 按照品牌进行查询,可以多选
private List<String> attrs; // 按照属性进行筛选
private Integer pageNum=1; // 页码 默认第1页
}
封装检索返回结果
com.atguigu.gulimall.search.vo
路径下
public class SearchResult {
// 查询到的所有商品信息
private List<SkuEsModel> products;
/**
* 分页信息
*/
private Integer pageNum; // 当前页码
private Long total; // 总记录数
private Integer totalPages;// 总页码
private List<Integer> pageNavs; // 导航页码
private List<BrandVo> brands; // 当前查询到的结果,所有涉及到的品牌
private List<CatalogVo> ctatLogs; // 当前查询到的结果,所有涉及到的分类
private List<AttrVo> attrs; // 当前查询到的结果,所有涉及到的属性
//==================以上返回给页面的所有信息====================
/**
* 品牌
*/
@Data
public static class BrandVo{
private Long brandId;
private String brandName;
private String brandImg;
}
/**
* 分类
*/
@Data
public static class CatalogVo{
private Long catalogId;
private String catalogName;
}
/**
* 属性
*/
@Data
public static class AttrVo{
private Long attrId;
private String attrName;
private List<String> attrValue;
}
}
GET gulimall_product/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"skuTitle": "华为"
}
}
],
"filter": [
{
"term": {
"catalogId": "225"
}
},
{
"terms": {
"brandId": [
"9",
"7",
"10"
]
}
},
{
"nested": {
"path": "attrs",
"query": {
"bool": {
"must": [
{
"term": {
"attrs.attrId": {
"value": "8"
}
}
},
{
"terms": {
"attrs.attrValue": [
"海斯 (Hisilicon)",
"以官网信息为准"
]
}
}
]
}
}
}
},
{
"term": {
"hasStock": {
"value": "true"
}
}
},
{
"range": {
"skuPrice": {
"gte": 0,
"lte": 6000
}
}
}
]
}
},
"sort": [
{
"skuPrice": {
"order": "desc"
}
}
],
"from": 0,
"size": 1,
"highlight": {
"fields": {"skuTitle": {}},
"pre_tags": "",
"post_tags": ""
},
"aggs": {
"brand_agg": {
"terms": {
"field": "brandId",
"size": 10
},
"aggs": {
"brand_name_agg": {
"terms": {
"field": "brandName",
"size": 10
}
},
"brand_img_agg":{
"terms": {
"field": "brandImg",
"size": 10
}
}
}
},
"catelog_agg": {
"terms": {
"field": "catalogId",
"size": 10
},
"aggs": {
"catalog_name_agg": {
"terms": {
"field": "catalogName",
"size": 10
}
}
}
},
"attrs_agg": {
"nested": {
"path": "attrs"
},
"aggs": {
"attr_id_agg": {
"terms": {
"field": "attrs.attrId",
"size": 10
},
"aggs": {
"attr_name_agg": {
"terms": {
"field": "attrs.attrName",
"size": 10
}
},
"attr_value_agg": {
"terms": {
"field": "attrs.attrValue",
"size": 10
}
}
}
}
}
}
}
}
这里由于需要使用到
brandName
进行检索,需要修改映射,在此进行数据迁移
删掉映射里的所有:
"index" : false,
"doc_values" : false
创建一个新的映射
PUT gulimall_product
{
"mappings": {
"properties": {
"attrs": {
"type": "nested",
"properties": {
"attrId": {
"type": "long"
},
"attrName": {
"type": "keyword"
},
"attrValue": {
"type": "keyword"
}
}
},
"brandId": {
"type": "long"
},
"brandImg": {
"type": "keyword"
},
"brandName": {
"type": "keyword"
},
"catalogId": {
"type": "long"
},
"catalogName": {
"type": "keyword"
},
"hasStock": {
"type": "boolean"
},
"hotScore": {
"type": "long"
},
"saleCount": {
"type": "long"
},
"skuId": {
"type": "long"
},
"skuImg": {
"type": "keyword"
},
"skuPrice": {
"type": "keyword"
},
"skuTitle": {
"type": "text",
"analyzer": "ik_smart"
},
"spuId": {
"type": "keyword"
}
}
}
}
数据转移
# 迁移数据
POST _reindex
{
"source": {
"index": "product"
},
"dest": {
"index": "gulimall_product"
}
}
修改 gulimall-search 服务中 sku数据在es中的索引 的常量
package com.atguigu.gulimall.search.constant;
public class EsConstant {
public static final String PRODUCT_INDEX = "gulimall_product"; // sku数据在es中的索引
}
总方法:
@Service
public class MallSearchServiceImpl implements MallSearchService {
@Autowired
private RestHighLevelClient client;
@Override
public SearchResult search(SearchParam param) {
// 动态的构建出查询的DSL语句
SearchResult result = null;
// 1、准备检索请求
SearchRequest searchRequest = buildSearchRequrest(param);
try {
// 2、执行检索请求
SearchResponse response = client.search(searchRequest, GulimallElasticSearchConfig.COMMON_OPTIONS);
// 3、分析相应数据并封装成需要的指定格式
result = buildSearchResult(response,param);
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
准备检索请求
/**
* 准备检索请求
* 模糊匹配:过滤(按照属性、分类、品牌、价格区间、库存)、排序、分页、高亮,聚合分析
* @return SearchRequest
*/
private SearchRequest buildSearchRequrest(SearchParam param) {
// 构建DSL语句的
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
/**
* 查询:模糊匹配,过滤(按照分类、品牌、属性、库存、价格区间)
*/
// 1、构建bool-query
BoolQueryBuilder boolBuilder = QueryBuilders.boolQuery();
// 1.1、match-模糊匹配
if (!StringUtils.isEmpty(param.getKeyword())) {
boolBuilder.must(QueryBuilders.matchQuery("skuTitle", param.getKeyword()));
}
// 1.2、filter-过滤(按照分类、品牌、属性、库存、价格区间)
// 1.2.1、按照三级分类id查询
if (param.getCatalog3Id() != null) {
boolBuilder.filter(QueryBuilders.termQuery("catalogId", param.getCatalog3Id()));
}
// 1.2.2、按照品牌id查询
if (param.getBrandId() != null && param.getBrandId().size()>0) {
boolBuilder.filter(QueryBuilders.termsQuery("brandId", param.getBrandId()));
}
// 1.2.3、按照所有指定的属性进行查询
if (param.getAttrs()!=null && param.getAttrs().size()>0) {
for (String attrStr : param.getAttrs()) {
// attrs=1_其他:安卓&attrs=2_5寸:1.5寸
BoolQueryBuilder nestedBoolBuilder = QueryBuilders.boolQuery();
String[] s = attrStr.split("_");
String attrId = s[0]; // 检索的属性id
String[] attrValues = s[1].split(":"); // 这个属性检索用的值
nestedBoolBuilder.must(QueryBuilders.termQuery("attrs.attrId",attrId));
nestedBoolBuilder.must(QueryBuilders.termsQuery("attrs.attrValue",attrValues));
// 每一个必须都得生成一个嵌入式的查询nested
NestedQueryBuilder nestedQuery = QueryBuilders.nestedQuery("attrs", nestedBoolBuilder, ScoreMode.None);
boolBuilder.filter(nestedQuery);
}
}
// 1.2.4、按照是否拥有库存进行查询
if (param.getHasStock() != null) {
boolBuilder.filter(QueryBuilders.termQuery("hasStock", param.getHasStock()==1));
}
// 1.2.5、按照价格区间进行查询
if (!StringUtils.isEmpty(param.getSkuPrice())){
// 1_500/_500/500_
RangeQueryBuilder rangeQuery = QueryBuilders.rangeQuery("skuPrice");
String[] s = param.getSkuPrice().split("_");
if (s.length==2){
// 区间
rangeQuery.gte(s[0]).lte(s[1]);
} else if (s.length == 1) {
if (param.getSkuPrice().startsWith("_")) {
rangeQuery.lte(s[0]);
}
if (param.getSkuPrice().endsWith("_")) {
rangeQuery.gte(s[0]);
}
}
boolBuilder.filter(rangeQuery);
}
// 把以前的所有条件都拿来进行封装
sourceBuilder.query(boolBuilder);
/**
* 排序、分页、高亮
*/
// 2、排序
if (!StringUtils.isEmpty(param.getSort())){
String sort = param.getSort();
// sort=saleCount_desc/asc
String[] s = sort.split("_");
SortOrder order = s[1].equalsIgnoreCase("asc")?SortOrder.ASC:SortOrder.DESC;
sourceBuilder.sort(s[0], order);
}
// 3、分页
sourceBuilder.from((param.getPageNum()-1)*EsConstant.PRODUCT_PAGESIZE);
sourceBuilder.size(EsConstant.PRODUCT_PAGESIZE);
// 4、高亮
if (!StringUtils.isEmpty(param.getKeyword())) {
HighlightBuilder highlightBuilder = new HighlightBuilder();
highlightBuilder.field("skuTitle");
highlightBuilder.preTags("");
highlightBuilder.postTags("");
sourceBuilder.highlighter(highlightBuilder);
}
/**
* 聚合分析
*/
// 5.1、品牌聚合
TermsAggregationBuilder brand_agg = AggregationBuilders.terms("brand_agg");
brand_agg.field("brandId").size(50);
brand_agg.subAggregation(AggregationBuilders.terms("brand_name_agg").field("brandName").size(1)); // 品牌聚合的子聚合
brand_agg.subAggregation(AggregationBuilders.terms("brand_img_agg").field("brandImg").size(1));
// TODO 1、聚合brand
sourceBuilder.aggregation(brand_agg);
// 5.2、分类聚合
TermsAggregationBuilder catalog_agg = AggregationBuilders.terms("catalog_agg").field("catalogId").size(20);
catalog_agg.subAggregation(AggregationBuilders.terms("catalog_name_agg").field("catalogName").size(1));
// TODO 2、聚合catalog
sourceBuilder.aggregation(catalog_agg);
// 5.3、属性聚合
NestedAggregationBuilder attrs_agg = AggregationBuilders.nested("attrs_agg", "attrs"); // 嵌入聚合
// 聚合出当前所有的attrId
TermsAggregationBuilder attr_id_agg = AggregationBuilders.terms("attr_id_agg").field("attrs.attrId");
// 聚合分析出当前attr_id对应的名字
attr_id_agg.subAggregation(AggregationBuilders.terms("attr_name_agg").field("attrs.attrName").size(1));
// 聚合分析出当前attr_id对应所有可能的属性值attrValue
attr_id_agg.subAggregation(AggregationBuilders.terms("attr_value_agg").field("attrs.attrValue").size(50));
attrs_agg.subAggregation(attr_id_agg);
// TODO 3、聚合attr
sourceBuilder.aggregation(attrs_agg);
SearchRequest searchRequest = new SearchRequest(new String[]{EsConstant.PRODUCT_INDEX}, sourceBuilder);
return searchRequest;
}
构建结果数据
/**
* 构建结果数据
* @param response 执行检索请求获得的响应数据
* @return 封装成需要的指定格式并返回
*/
private SearchResult buildSearchResult(SearchResponse response, SearchParam param) {
SearchResult result = new SearchResult();
// 1、返回的所有查询到的商品
SearchHits hits = response.getHits();
List<SkuEsModel> esModels = new ArrayList<>();
if (hits.getHits()!=null && hits.getHits().length>0) {
for (SearchHit hit : hits.getHits()) {
String sourceAsString = hit.getSourceAsString();
SkuEsModel esModel = JSON.parseObject(sourceAsString, SkuEsModel.class);
if (!StringUtils.isEmpty(param.getKeyword())) {
HighlightField skuTitle = hit.getHighlightFields().get("skuTitle");
String string = skuTitle.getFragments()[0].string();
esModel.setSkuTitle(string);
}
esModels.add(esModel);
}
}
result.setProducts(esModels);
// 2、当前所有商品涉及到的所有属性信息
List<SearchResult.AttrVo> attrVos = new ArrayList<>();
ParsedNested attrs_agg = response.getAggregations().get("attrs_agg");
ParsedLongTerms attr_id_agg = attrs_agg.getAggregations().get("attr_id_agg");
for (Terms.Bucket bucket : attr_id_agg.getBuckets()) {
SearchResult.AttrVo attrVo = new SearchResult.AttrVo();
// 1、得到属性的id
long attrId = bucket.getKeyAsNumber().longValue();
// 2、得到属性的名字
String attrName = ((ParsedStringTerms) bucket.getAggregations().get("attr_name_agg")).getBuckets().get(0).getKeyAsString();
// 3、得到属性的所有值
List<String> attrValues = ((ParsedStringTerms) bucket.getAggregations().get("attr_value_agg")).getBuckets().stream().map(item -> {
String keyAsString = ((Terms.Bucket) item).getKeyAsString();
return keyAsString;
}).collect(Collectors.toList());
attrVo.setAttrId(attrId);
attrVo.setAttrName(attrName);
attrVo.setAttrValue(attrValues);
attrVos.add(attrVo);
}
result.setAttrs(attrVos);
// 3、保存当前商品所涉及的所有品牌信息
List<SearchResult.BrandVo> brandVos = new ArrayList<>();
ParsedLongTerms brand_agg = response.getAggregations().get("brand_agg");
for (Terms.Bucket bucket : brand_agg.getBuckets()) {
SearchResult.BrandVo brandVo = new SearchResult.BrandVo();
// 1、得到品牌的id
long brandId = bucket.getKeyAsNumber().longValue();
// 2、得到品牌的name
String brandName = ((ParsedStringTerms) bucket.getAggregations().get("brand_name_agg")).getBuckets().get(0).getKeyAsString();
// 3、得到品牌的img
String brandImg = ((ParsedStringTerms) bucket.getAggregations().get("brand_img_agg")).getBuckets().get(0).getKeyAsString();
brandVo.setBrandId(brandId);
brandVo.setBrandImg(brandName);
brandVo.setBrandImg(brandImg);
brandVos.add(brandVo);
}
result.setBrands(brandVos);
// 4、保存当前商品所涉及的所有分类信息
List<SearchResult.CatalogVo> catalogVos = new ArrayList<>();
ParsedLongTerms catalog_agg = response.getAggregations().get("catalog_agg");
List<? extends Terms.Bucket> buckets = catalog_agg.getBuckets();
for (Terms.Bucket bucket : buckets) {
SearchResult.CatalogVo catalogVo = new SearchResult.CatalogVo();
// 得到分类id
catalogVo.setCatalogId(bucket.getKeyAsNumber().longValue());
// 得到分类name
ParsedStringTerms catalog_name_agg = bucket.getAggregations().get("catalog_name_agg");
String catalog_name = catalog_name_agg.getBuckets().get(0).getKeyAsString();
catalogVo.setCatalogName(catalog_name);
catalogVos.add(catalogVo);
}
result.setCtatLogs(catalogVos);
// 5、分页信息
// 分页信息-页码
result.setPageNum(param.getPageNum());
// 分页信息-总记录数
long total = hits.getTotalHits().value;
result.setTotal(total);
// 分页信息-总页码 (总记录数 对 每页数求余数)
int totalPages = (int)total%EsConstant.PRODUCT_PAGESIZE==0 ? ((int)total/EsConstant.PRODUCT_PAGESIZE) : ((int)total/EsConstant.PRODUCT_PAGESIZE+1);
result.setTotalPages(totalPages);
// 分页信息-导航栏
List<Integer> pageNavs = new ArrayList<>();
for (int i = 1; i <= totalPages; i++) {
pageNavs.add(i);
}
result.setPageNavs(pageNavs);
return result;
}
页面基本渲染
修改排序内容
盒子下的三个div, 只留下一个
- 修改价格
- 修改图片的路径
- 修改skuTitle
-
修改品牌
- 删掉多余 li
- 进行修改
-
修改规格属性
-
增加分类信息
<div class="JD_banner w">
<div class="JD_nav">
<div class="JD_selector">
<div class="title">
<h3><b>手机b><em>商品筛选em>h3>
<div class="st-ext">共 <span>10135span>个商品 div>
div>
<div class="JD_nav_logo">
<div class="JD_nav_wrap">
<div class="sl_key">
<span><b>品牌:b>span>
div>
<div class="sl_value">
<div class="sl_value_logo">
<ul>
<li th:each="brand:${result.brands}">
<a href="/static/search/#">
<img th:src="${brand.brandImg}" alt="">
<div th:text="${brand.brandName}">
华为(HUAWEI)
div>
a>
li>
ul>
div>
div>
<div class="sl_ext">
<a href="/static/search/#">
更多
<i style='background: url("image/search.ele.png")no-repeat 3px 7px'>i>
<b style='background: url("image/search.ele.png")no-repeat 3px -44px'>b>
a>
<a href="/static/search/#">
多选
<i>+i>
<span>+span>
a>
div>
div>
<div class="JD_pre">
<div class="sl_key">
<span><b>分类:b>span>
div>
<div class="sl_value">
<ul>
<li th:each="catalog:${result.ctatLogs}"><a href="/static/search/#" th:text="${catalog.catalogName}">分类a>li>
ul>
div>
<div class="sl_ext">
<a href="/static/search/#">
更多
<i style='background: url("image/search.ele.png")no-repeat 3px 7px'>i>
<b style='background: url("image/search.ele.png")no-repeat 3px -44px'>b>
a>
<a href="/static/search/#">
多选
<i>+i>
<span>+span>
a>
div>
div>
<div class="JD_pre" th:each="attr:${result.attrs}">
<div class="sl_key">
<span th:text="${attr.attrName}">屏幕尺寸:span>
div>
<div class="sl_value">
<ul>
<li th:each="val:${attr.attrValue}"><a href="/static/search/#" th:text="${val}">5.56英寸及以上a>li>
ul>
div>
div>
div>
<div class="JD_show">
<a href="/static/search/#">
<span>
更多选项( CPU核数、网络、机身颜色 等)
span>
a>
div>
div>
<div class="JD_banner_main">
<div class="JD_con_left">
<div class="JD_con_left_bar">
<div class="JD_con_one">
<div class="mt">
<h3>商品精选h3>
<span>广告span>
div>
<div class="mc">
<ul>
<li>
<a href="/static/search/#" title="vivo X9s 全网通 4GB+64GB 磨砂黑 移动联通电信4G手机 双卡双待"><img src="/static/search/img/59bf3c47n91d65c73.jpg" alt="">a>
<a href="/static/search/#" title="【预约版】华为 HUAWEI 畅享7S 全面屏双摄 4GB +64GB 黑色 移动联通电信4G手机 双卡双待">
<em>华为 HUAWEI nova 2S 全面屏四摄 6GB +64GB 曜石黑 移动联通电信4G手机 双卡双待em>
a>
<div class="mc_price">
<strong class="price">
<span class="J-p-5963064">¥2999.00span>
strong>
<span class="mc-ico" title="购买本商品送赠品">
<i class="goods-icons">赠品i>
span>
div>
<div class="mc_rev">
已有
<a href="/static/search/#" class="number">12466a>
人评价
div>
li>
<li>
<a href="/static/search/#" title="vivo X9s 全网通 4GB+64GB 磨砂黑 移动联通电信4G手机 双卡双待"><img src="/static/search/img/59bf3c47n91d65c73.jpg" alt="">a>
<a href="/static/search/#" title="【预约版】华为 HUAWEI 畅享7S 全面屏双摄 4GB +64GB 黑色 移动联通电信4G手机 双卡双待">
<em>华为 HUAWEI nova 2S 全面屏四摄 6GB +64GB 曜石黑 移动联通电信4G手机 双卡双待em>
a>
<div class="mc_price">
<strong class="price">
<span class="J-p-5963064">¥2999.00span>
strong>
<span class="mc-ico" title="购买本商品送赠品">
<i class="goods-icons">赠品i>
span>
div>
<div class="mc_rev">
已有
<a href="/static/search/#" class="number">12466a>
人评价
div>
li>
<li>
<a href="/static/search/#" title="vivo X9s 全网通 4GB+64GB 磨砂黑 移动联通电信4G手机 双卡双待"><img src="/static/search/img/593ba628n8794c6a6.jpg" alt="">a>
<a href="/static/search/#" title="【预约版】华为 HUAWEI 畅享7S 全面屏双摄 4GB +64GB 黑色 移动联通电信4G手机 双卡双待">
<em>诺基亚 7 (Nokia 7) 4GB+64GB 黑色 全网通 双卡双待 移动联通电信4G手机em>
a>
<div class="mc_price">
<strong class="price">
<span class="J-p-5963064">¥1799.00span>
strong>
<span class="mc-ico" title="购买本商品送赠品">
<i class="goods-icons">赠品i>
span>
div>
<div class="mc_rev">
已有
<a href="/static/search/#" class="number">15600a>
人评价
div>
li>
<li>
<a href="/static/search/#" title="vivo X9s 全网通 4GB+64GB 磨砂黑 移动联通电信4G手机 双卡双待"><img src="/static/search/img/5919637an271a1301.jpg" alt="">a>
<a href="/static/search/#" title="【预约版】华为 HUAWEI 畅享7S 全面屏双摄 4GB +64GB 黑色 移动联通电信4G手机 双卡双待">
<em>vivo Xplay6 全网通 6GB+64GB 磨砂黑 移动联通电信4G手机 双卡双待em>
a>
<div class="mc_price">
<strong class="price">
<span class="J-p-5963064">¥3498.00span>
strong>
<span class="mc-ico" title="购买本商品送赠品">
<i class="goods-icons">赠品i>
span>
div>
<div class="mc_rev">
已有
<a href="/static/search/#" class="number">5369a>
人评价
div>
li>
ul>
div>
div>
<div class="JD_con_one">
<div class="mt">
<h3>达人选购h3>
div>
<div class="mc">
<ul>
<li>
<a href="/static/search/#" title="vivo X9s 全网通 4GB+64GB 磨砂黑 移动联通电信4G手机 双卡双待"><img src="/static/search/img/59bf3c47n91d65c73.jpg" alt="">a>
<a href="/static/search/#">
<em>华为 HUAWEI nova 2S 全面屏四摄 6GB +64GB 曜石黑 移动联通电信4G手机 双卡双待em>
a>
<div class="mc_price">
<strong class="price">
<span class="J-p-5963064">¥2999.00span>
strong>
div>
li>
<li>
<a href="/static/search/#" title="vivo X9s 全网通 4GB+64GB 磨砂黑 移动联通电信4G手机 双卡双待"><img src="/static/search/img/59bf3c47n91d65c73.jpg" alt="">a>
<a href="/static/search/#">
<em>华为 HUAWEI nova 2S 全面屏四摄 6GB +64GB 曜石黑 移动联通电信4G手机 双卡双待em>
a>
<div class="mc_price">
<strong class="price">
<span class="J-p-5963064">¥2999.00span>
strong>
div>
li>
<li>
<a href="/static/search/#" title="vivo X9s 全网通 4GB+64GB 磨砂黑 移动联通电信4G手机 双卡双待"><img src="/static/search/img/593ba628n8794c6a6.jpg" alt="">a>
<a href="/static/search/#">
<em>诺基亚 7 (Nokia 7) 4GB+64GB 黑色 全网通 双卡双待 移动联通电信4G手机em>
a>
<div class="mc_price">
<strong class="price">
<span class="J-p-5963064">¥1799.00span>
strong>
div>
li>
<li>
<a href="/static/search/#" title="vivo X9s 全网通 4GB+64GB 磨砂黑 移动联通电信4G手机 双卡双待"><img src="/static/search/img/5919637an271a1301.jpg" alt="">a>
<a href="/static/search/#">
<em>vivo Xplay6 全网通 6GB+64GB 磨砂黑 移动联通电信4G手机 双卡双待em>
a>
<div class="mc_price">
<strong class="price">
<span class="J-p-5963064">¥3498.00span>
strong>
div>
li>
ul>
div>
div>
<div class="JD_con_one" style="border:none;">
<div class="mt">
<h3>商品精选h3>
<span>广告span>
div>
<div class="mc">
<ul>
<li>
<a href="/static/search/#"><img src="/static/search/img/599a806bn9d829c1c.jpg" alt="">a>
li>
<li>
<a href="/static/search/#"><img src="/static/search/img/593e4de0n5ff878a4.jpg" alt="">a>
li>
ul>
div>
div>
div>
div>
<div class="JD_con_right">
<div class="filter">
<div class="filter_top">
<div class="filter_top_left">
<a href="/static/search/#">综合排序a>
<a href="/static/search/#">销量a>
<a href="/static/search/#">价格a>
<a href="/static/search/#">评论分a>
<a href="/static/search/#">上架时间a>
div>
<div class="filter_top_right">
<span class="fp-text">
<b>1b><em>/em><i>169i>
span>
<a href="/static/search/#" class="prev"><a>
<a href="/static/search/#" class="next"> > a>
div>
div>
<div class="filter_bottom">
<div class="filter_bottom_left">
<div class="fs-cell">收货地div>
<div class="dizhi">
<div class="dizhi_show">
<em>北京朝阳区三环以内em>
<b>b>
div>
div>
<div class="dizhi_con">
<ul id="tab">
<li id="tab1" value="1">北京 <img src="/static/search/image/[email protected]" alt="">li>
<li id="tab2" value="2">朝阳 <img src="/static/search/image/[email protected]" alt="">li>
<li id="tab3" value="3">三环以内 <img src="/static/search/image/[email protected]" alt="">li>
ul>
<div id="container">
<div id="content1" style="z-index: 1;">
<a href="/static/search/#">北京a>
<a href="/static/search/#">上海a>
<a href="/static/search/#">天津a>
<a href="/static/search/#">重庆a>
<a href="/static/search/#">河北a>
<a href="/static/search/#">山西a>
<a href="/static/search/#">河南a>
<a href="/static/search/#">辽宁a>
<a href="/static/search/#">吉林a>
<a href="/static/search/#">黑龙江a>
<a href="/static/search/#">内蒙古a>
<a href="/static/search/#">江苏a>
<a href="/static/search/#">山东a>
<a href="/static/search/#">安徽a>
<a href="/static/search/#">浙江a>
<a href="/static/search/#">福建a>
<a href="/static/search/#">湖北a>
<a href="/static/search/#">湖南a>
<a href="/static/search/#">广东a>
<a href="/static/search/#">广西a>
<a href="/static/search/#">江西a>
<a href="/static/search/#">四川a>
<a href="/static/search/#">海南a>
<a href="/static/search/#">贵州a>
<a href="/static/search/#">云南a>
<a href="/static/search/#">西藏a>
<a href="/static/search/#">陕西a>
<a href="/static/search/#">甘肃a>
<a href="/static/search/#">青海a>
<a href="/static/search/#">宁夏a>
<a href="/static/search/#">新疆a>
<a href="/static/search/#">港澳a>
<a href="/static/search/#">台湾a>
<a href="/static/search/#">钓鱼岛a>
<a href="/static/search/#">海外a>
div>
<div id="content2">
<a href="/static/search/#">朝阳区a>
<a href="/static/search/#">海淀区a>
<a href="/static/search/#">西城区a>
<a href="/static/search/#">东城区a>
<a href="/static/search/#">大兴区a>
<a href="/static/search/#">丰台区a>
<a href="/static/search/#">昌平区a>
<a href="/static/search/#">顺义区a>
div>
<div id="content3">
<a href="/static/search/#">三环以内a>
<a href="/static/search/#">管庄a>
<a href="/static/search/#">北苑a>
<a href="/static/search/#">定福庄a>
<a href="/static/search/#">三环到四环之间a>
<a href="/static/search/#">四环到五环之间a>
<a href="/static/search/#">五环到六环之间a>
div>
div>
div>
div>
<div class="filter_bottom_right">
<ul>
<li>
<a href="/static/search/#">
<i>i>
谷粒商城配送
a>
li>
<li>
<a href="/static/search/#">
<i>i>
京尊达 a>
li>
<li>
<a href="/static/search/#">
<i>i>
货到付款
a>
li>
<li>
<a href="/static/search/#">
<i>i>
仅显示有货
a>
li>