搜索关键词标红功能
今年做的一个需求,先看效果图。
先讲一下实现方式,前端输入关键词查询,后端返回html模板,前端通过v-html渲染
查到的数据是分页式,v-html的样式需要使用/deep/声明
下面是组件代码
html
<template>
<div class="result-box">
<div id="box-top"></div>
<div class="search-list" v-for="(item, index) in searchWordsList">
<div class="report-title">
<img
class="icon mini"
v-show="item.reportSource === 1"
src="../../assets/2023/icon_02.png"
alt=""
/>
<img
class="icon"
v-show="item.reportSource === 2"
src="../../assets/2023/icon_01.png"
alt=""
/>
<div class="h5-icon" v-show="item.reportSource === 3">H5</div>
<div class="reportName-html" @click="OpenDetails(item, index)" v-html="item.reportNameDescription">
</div>
<el-tag
style="cursor: pointer;"
v-show="item.hasAuth && item.isActive!=3"
@click="GoSelect(item, index)"
type="success"
size="mini"
>
直接运行
</el-tag>
<el-tag
style="cursor: pointer;"
v-show="item.hasAuth && item.isActive==3"
type="warning"
size="mini"
>
禁用
</el-tag>
<el-tag v-show="!item.hasAuth" type="info" size="mini">
未授权
</el-tag>
</div>
<div class="html-template" v-html="item.description"></div>
<div class="report-path">{{ item.catalogPath }}</div>
</div>
</div>
</template>
<script>
export default {
props: {
searchWordsList: {
type: Array,
default: () => [],
},
id: {
type: Number
}
},
data() {
return {
templateCode: '<div class="desc">描述描述描述<span>标红</span></div>',
}
},
created() {},
mounted() {},
watch: {
searchWordsList(n, o) {
console.log('搜索结果变化', n)
this.GoListTop()
},
},
methods: {
// 打开详情
OpenDetails(data, index) {
if (data.hasDetail) {
this.$emit('OpenDetails', data, data.reportId, index)
} else {
this.$message.warning('暂无可看详情')
}
},
// 打开报表
GoSelect(data, index) {
if (data.hasAuth) {
this.$emit('StartReport', data, index)
} else {
this.$message.warning('暂无权限')
}
},
GoListTop() {
document.querySelector('#box-top').scrollIntoView({
behavior: 'smooth',
})
},
},
}
</script>
<style lang="less" scoped>
.search-list {
width: 100%;
border-bottom: 1px solid rgba(34, 34, 34, 0.1);
margin-bottom: 10px;
.report-title {
width: 100%;
height: 20px;
font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #3e86ff;
line-height: 20px;
display: flex;
align-items: center;
margin-bottom: 2px;
.icon {
width: 18px;
height: 18px;
display: block;
margin-right: 8px;
&.mini {
width: 16px;
}
}
.h5-icon {
width: 18px;
height: 18px;
background: #eaf2ff;
border-radius: 3px;
font-size: 12px;
font-family: SourceHanSansCN-Bold, SourceHanSansCN;
font-weight: bold;
color: #3f86ff;
text-align: center;
line-height: 18px;
margin-right: 8px;
}
.reportName-html {
// width: 100%;
position: relative;
/deep/.reportName {
border-bottom: #3e86ff 1px solid;
cursor: pointer;
> span {
color: red;
}
}
}
}
.html-template {
width: 100%;
position: relative;
/deep/.desc {
width: 100%;
font-size: 12px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: rgba(34, 34, 34, 0.7);
line-height: 20px;
margin-bottom: 5px;
white-space: pre-line; // 合并空白符序列,但保留换行符
> span {
color: red;
}
}
}
.report-path {
color: #929292;
font-size: 12px;
margin-bottom: 9px;
}
}
</style>