2.实现基本搜索
2.1.页面分析
2.1.1.页面跳转
在首页的顶部,有一个输入框:
当我们输入任何文本,点击搜索,就会跳转到搜索页search.html
了:
并且将搜索关键字以请求参数携带过来:
我们打开search.html
,在最下面会有提前定义好的Vue实例:
我们打开search.html
,在最下面会有提前定义好的Vue实例:
<script type="text/javascript">
var vm = new Vue({
el: "#searchApp",
data: {
},
components:{
// 加载页面顶部组件
lyTop: () => import("./js/pages/top.js")
}
});
</script>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
2.1.2.发起异步请求
要想在页面加载后,就展示出搜索结果。我们应该在页面加载时,获取地址栏请求参数,并发起异步请求,查询后台数据,然后在页面渲染。
我们在data中定义一个对象,记录请求的参数:
data: {
search:{
key:"", // 搜索页面的关键字
}
}
- 1
- 2
- 3
- 4
- 5
我们通过钩子函数created,在页面加载时获取请求参数,并记录下来。
created(){ // 判断是否有请求参数 if(!location.search){ return; } // 将请求参数转为对象 const search = ly.parse(location.search.substring(1)); // 记录在data的search对象中 this.search = search;
<span class="token comment">// 发起请求,根据条件搜索</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">searchFromServer</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
然后发起请求,搜索数据。
methods:{
searchFromServer(){
// 发起异步请求
ly.http.post("/search/page",this.search)
.then(resp => {
console.log(resp.data);
})
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 我们这里使用
ly
是common.js中定义的工具对象。 - 这里使用的是post请求,这样可以携带更多参数,并且以json格式发送
刷新页面试试:
请求体:
因为后台没有提供接口,所以无法访问。没关系,接下来我们实现后台接口
2.2.后台提供搜索接口
2.2.1.controller
首先分析几个问题:
-
请求方式:Post
-
请求路径:/search/page,不过前面的/search应该是网关的映射路径,因此真实映射路径page,代表分页查询
-
请求参数:json格式,目前只有一个属性:key,搜索关键字,但是搜索结果页一定是带有分页查询的,所以将来肯定会有page属性,因此我们可以用一个对象来接收请求的json数据:
-
public class SearchRequest { private String key;// 搜索条件
<span class="token keyword">private</span> Integer page<span class="token punctuation">;</span><span class="token comment">// 当前页</span> <span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token keyword">final</span> Integer DEFAULT_SIZE <span class="token operator">=</span> <span class="token number">20</span><span class="token punctuation">;</span><span class="token comment">// 每页大小,不从页面接收,而是固定大小</span> <span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token keyword">final</span> Integer DEFAULT_PAGE <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span><span class="token comment">// 默认页</span> <span class="token keyword">public</span> String <span class="token function">getKey</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> key<span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">setKey</span><span class="token punctuation">(</span>String key<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">this</span><span class="token punctuation">.</span>key <span class="token operator">=</span> key<span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">public</span> Integer <span class="token function">getPage</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span><span class="token punctuation">(</span>page <span class="token operator">==</span> null<span class="token punctuation">)</span><span class="token punctuation">{</span> <span class="token keyword">return</span> DEFAULT_PAGE<span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">// 获取页码时做一些校验,不能小于1</span> <span class="token keyword">return</span> Math<span class="token punctuation">.</span><span class="token function">max</span><span class="token punctuation">(</span>DEFAULT_PAGE<span class="token punctuation">,</span> page<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">setPage</span><span class="token punctuation">(</span>Integer page<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">this</span><span class="token punctuation">.</span>page <span class="token operator">=</span> page<span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">public</span> Integer <span class="token function">getSize</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> DEFAULT_SIZE<span class="token punctuation">;</span> <span class="token punctuation">}</span>
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
-
返回结果:作为分页结果,一般都两个属性:当前页数据、总条数信息,我们可以使用之前定义的PageResult类
代码: @RestController @RequestMapping public class SearchController {
<span class="token annotation punctuation">@Autowired</span> <span class="token keyword">private</span> IndexService indexService<span class="token punctuation">;</span> <span class="token comment">/** * 搜索商品 * * @param request * @return */</span> <span class="token annotation punctuation">@PostMapping</span><span class="token punctuation">(</span><span class="token string">"page"</span><span class="token punctuation">)</span> <span class="token keyword">public</span> ResponseEntity<span class="token operator"><</span>PageResult<span class="token generics function"><span class="token punctuation"><</span>Goods<span class="token punctuation">></span></span><span class="token operator">></span> <span class="token function">search</span><span class="token punctuation">(</span><span class="token annotation punctuation">@RequestBody</span> SearchRequest request<span class="token punctuation">)</span> <span class="token punctuation">{</span> PageResult<span class="token generics function"><span class="token punctuation"><</span>Goods<span class="token punctuation">></span></span> result <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>searchService<span class="token punctuation">.</span><span class="token function">search</span><span class="token punctuation">(</span>request<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>result <span class="token operator">==</span> null<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">ResponseEntity</span><span class="token operator"><</span><span class="token operator">></span><span class="token punctuation">(</span>HttpStatus<span class="token punctuation">.</span>NOT_FOUND<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">return</span> ResponseEntity<span class="token punctuation">.</span><span class="token function">ok</span><span class="token punctuation">(</span>result<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
2.2.2.service
public PageResult<Goods> search(SearchRequest request) { Integer page = request.getPage() - 1; Integer size = request.getSize(); //创建查询构建器 NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder(); //过滤 queryBuilder.withSourceFilter(new FetchSourceFilter(new String[]{"id","skus","subTitle"}, null)); //分页 queryBuilder.withPageable(PageRequest.of(page,size)); //过滤 //queryBuilder.withQuery(QueryBuilders.matchQuery("all",request.getKey())); //查询 Page<Goods> result = repository.search(queryBuilder.build()); //解析结果 long total = result.getTotalElements(); Integer totalPage =result.getTotalPages(); List<Goods> goodsList = result.getContent(); return new PageResult<>(total, totalPage, goodsList); }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
注意点:对于过滤字段,如果添加 会报500错误
2.2.3.测试
刷新页面测试:
数据是查到了,但是因为我们只查询部分字段,所以结果json 数据中有很多null,这很不优雅。
解决办法很简单,在application.yml中添加一行配置,json处理时忽略空值:
spring: jackson: default-property-inclusion: non_null # 配置json处理时忽略空值
- 1
- 2
- 3
结果:
2.3.页面渲染
页面已经拿到了结果,接下来就要渲染样式了。
2.3.1.保存搜索结果
首先,在data中定义属性,保存搜索的结果goodList:
var vm = new Vue({ el: "#searchApp", data: { ly, key:"", search:{}, goodList:{}, total: 0, totalPage: 0, selectedSku:{} },
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
在
loadData
的异步查询中,将结果赋值给goodsList
:loadData(){ //发送到后台 ly.http.post("/search/page",this.search).then(resp =>{ //保存分页结果 this.total = resp.data.total; this.totalPage=resp.data.totalPage; this.goodList = resp.data.item;
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>resp<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token keyword">catch</span><span class="token punctuation">(</span>error <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token punctuation">}</span>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
2.3.2.循环展示商品
在search.html的中部,有一个
div
,用来展示所有搜索到的商品:可以看到,
div
中有一个无序列表ul
,内部的每一个li
就是一个商品spu了。我们删除多余的,只保留一个
li
,然后利用vue的循环来展示搜索到的结果:<li class="yui3-u-1-5" v-for="goods in goodList" :key="goods.id" >
- 1
- 2
2.3.3.多sku展示
分析
接下来展示具体的商品信息,来看图:
这里我们可以发现,一个商品位置,是多个sku的信息集合。当用户鼠标选择某个sku,对应的图片、价格、标题会随之改变!
我们先来实现sku的选择,才能去展示不同sku的数据。
可以看到,在列表中默认第一个是被选中的,那我们就需要做两件事情:
- 记录当前被选中的是哪一个sku,记录在哪里比较合适呢?显然是遍历到的goods对象自己内部,因为每一个goods都会有自己的sku信息。
- 在搜索到数据时,先默认把第一个sku作为被选中的,记录下来
初始化sku
我们在查询成功的回调函数中,对goods进行遍历,然后添加一个selected属性,保存被选中的sku:
loadData(){ //发送到后台 ly.http.post("/search/page",this.search).then(resp =>{ //保存分页结果 this.total = resp.data.total; this.totalPage=resp.data.totalPage; //保存当前页商品 resp.data.item.forEach(goods =>{ goods.skus = JSON.parse(goods.skus); goods.selectedSku = goods.skus[0];
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">this</span><span class="token punctuation">.</span>goodList <span class="token operator">=</span> resp<span class="token punctuation">.</span>data<span class="token punctuation">.</span>item<span class="token punctuation">;</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>resp<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token keyword">catch</span><span class="token punctuation">(</span>error <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token punctuation">}</span>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
多sku图片列表
接下来,我们看看多个sku的图片列表位置:
看到又是一个无序列表,这里我们也一样删掉多余的,保留一个
li
,需要注意选中的项有一个样式类:selected我们的代码:
<!--多sku图片列表--> <ul class="skus"> <li :class="{selected: sku.id == goods.selected.id}" v-for="sku in goods.skus" :key="sku.id" @mouseEnter="goods.selected=sku"> <img :src="sku.image"> </li> </ul>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
注意:
- class样式通过 goods.selected的id是否与当前sku的id一致来判断
- 绑定了鼠标事件,鼠标进入后把当前sku赋值到goods.selected
2.3.4.展示sku其它属性代码
div class="goods-list"> <ul class="yui3-g"> <li class="yui3-u-1-5" v-for="goods in goodList" :key="goods.id" > <div class="list-wrap"> <div class="p-img"> <a href="item.html" target="_blank"><img :src="goods.selectedSku.image" height="200"/></a> <ul class="skus"> <li :class="{selected:goods.selectedSku.id == sku.id}" @mouseenter="goods.selectedSku=sku" v-for="sku in goods.skus" :key="sku.id"> <img :src="sku.image"> </li>
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>ul</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>clearfix<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>price<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>strong</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>em</span><span class="token punctuation">></span></span>¥<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>em</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>i</span> <span class="token attr-name">v-text</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>goods.selectedSku.price<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>i</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>strong</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>attr<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>em</span> <span class="token attr-name">v-text</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>goods.selectedSku.title.substring(0,21) + <span class="token punctuation">'</span>..<span class="token punctuation">'</span><span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>em</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>cu<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>em</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>span</span><span class="token punctuation">></span></span>促<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>span</span><span class="token punctuation">></span></span>{{goods.subTitle.substring(0,15)+'..'}}<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>em</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>commit<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>i</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>command<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>已有2000人评价<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>i</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>operate<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>success-cart.html<span class="token punctuation">"</span></span> <span class="token attr-name">target</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>_blank<span class="token punctuation">"</span></span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>sui-btn btn-bordered btn-danger<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>加入购物车<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>a</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>javascript:void(0);<span class="token punctuation">"</span></span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>sui-btn btn-bordered<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>对比<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>a</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>javascript:void(0);<span class="token punctuation">"</span></span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>sui-btn btn-bordered<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>关注<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>a</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>li</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>ul</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
页面效果:
</div> <link href="https://csdnimg.cn/release/phoenix/mdeditor/markdown_views-60ecaf1f42.css" rel="stylesheet"> <div class="more-toolbox"> <div class="left-toolbox"> <ul class="toolbox-list"> <li class="tool-item tool-active is-like "><a href="javascript:;"><svg class="icon" aria-hidden="true"> <use xlink:href="#csdnc-thumbsup"></use> </svg><span class="name">点赞</span> <span class="count"></span> </a></li> <li class="tool-item tool-active is-collection "><a href="javascript:;" data-report-click="{"mod":"popu_824"}"><svg class="icon" aria-hidden="true"> <use xlink:href="#icon-csdnc-Collection-G"></use> </svg><span class="name">收藏</span></a></li> <li class="tool-item tool-active is-share"><a href="javascript:;" data-report-click="{"mod":"1582594662_002"}"><svg class="icon" aria-hidden="true"> <use xlink:href="#icon-csdnc-fenxiang"></use> </svg>分享</a></li> <!--打赏开始--> <!--打赏结束--> <li class="tool-item tool-more"> <a> <svg t="1575545411852" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5717" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M179.176 499.222m-113.245 0a113.245 113.245 0 1 0 226.49 0 113.245 113.245 0 1 0-226.49 0Z" p-id="5718"></path><path d="M509.684 499.222m-113.245 0a113.245 113.245 0 1 0 226.49 0 113.245 113.245 0 1 0-226.49 0Z" p-id="5719"></path><path d="M846.175 499.222m-113.245 0a113.245 113.245 0 1 0 226.49 0 113.245 113.245 0 1 0-226.49 0Z" p-id="5720"></path></svg> </a> <ul class="more-box"> <li class="item"><a class="article-report">文章举报</a></li> </ul> </li> </ul> </div> </div> <div class="person-messagebox"> <div class="left-message"><a href="https://blog.csdn.net/id5555"> <img src="https://profile.csdnimg.cn/8/6/D/3_id5555" class="avatar_pic" username="id5555"> <img src="https://g.csdnimg.cn/static/user-reg-year/1x/3.png" class="user-years"> </a></div> <div class="middle-message"> <div class="title"><span class="tit"><a href="https://blog.csdn.net/id5555" data-report-click="{"mod":"popu_379"}" target="_blank">smallmartial</a></span> </div> <div class="text"><span>发布了94 篇原创文章</span> · <span>获赞 8</span> · <span>访问量 1万+</span></div> </div> <div class="right-message"> <a href="https://im.csdn.net/im/main.html?userName=id5555" target="_blank" class="btn btn-sm btn-red-hollow bt-button personal-letter">私信 </a> <a class="btn btn-sm bt-button personal-watch" data-report-click="{"mod":"popu_379"}">关注</a> </div> </div> </div> </article>