若依 ruoyi-vue SpringBoot highlight-textarea 输入框敏感词关键词高亮标红(二)

参考文章,非常感谢大佬的分享
实现可高亮的输入框 — HighlightTextarea
GitHub:highlight-textarea

可看作者上一篇文章
若依 ruoyi-vue SpringBoot聊天敏感词过滤sensitive-word(一)

效果图

在这里插入图片描述

审核时,输入框高亮敏感词,并且能编辑
在这里插入图片描述

前端代码

列表高亮
      <el-table-columnlabel="标题"align="center"prop="publishTitle":show-overflow-tooltip="true"><template slot-scope="scope"><span v-html="highlightPublishTitle(scope.row)"></span></template></el-table-column>

    highlightPublishTitle(row){let text = row.publishTitlefor (const word of row.titleSensitiveWord) {const regex = new RegExp(word, 'g')text = text.replace(regex, `<span style="color: red;">${word}</span>`)}return text},
编辑表单输入框高亮
        <el-form-item label="标题" prop="publishTitle"><highlight-textareav-if="open"style="width: 100%;"placeholder="请输入":text="form.publishTitle"type="input"@change="(value) => {form.publishTitle = value}":highlightKey="form.titleSensitiveWord"></highlight-textarea></el-form-item>
引用组件
import HighlightTextarea from '@/components/HighlightTextarea/index.vue';components: { HighlightTextarea },
npm安装
npm install less@^4.2.0 less-loader@^7.3.0
组件
<template><div class="highlight-box"><template v-if="type === 'textarea'"><div v-if="value"class="textarea-outer"ref="textareaOuter":style="{'height': `${maxHeight}px`}"><div ref="outerInner" class="outer-inner"v-html="highlightHtml(value)"></div></div><textarearef="textareaBox":style="{'height': `${maxHeight}px`}":placeholder="placeholder"@keyup.enter="syncScrollTop"v-model.trim="value"></textarea></template><template v-if="type === 'input'"><div v-if="value"class="input-outer"v-html="highlightHtml(value)"></div><input type="text":placeholder="placeholder"v-model.trim="value"/></template></div>
</template><script>
export default {name: 'HighlightTextarea',data() {return {value: ''}},props: {placeholder: {type: String,required: false,default: '请输入'},text: {type: String,required: false,default: ''},highlightKey: {type: Array,require: false,default: () => []},type: {type: String,required: true,default: 'textarea'},maxHeight: {type: Number,required: false,default: 220}},created() {this.value = this.text.replace(/(^\s*)|(\s*$)/g, '').replace(/<br \/>|<br\/>|<br>/g, '\n')},mounted() {this.scrollMousewheel()},computed: {},watch: {value(newValue) {this.$emit('change', newValue)}},methods: {highlightHtml(str) {if ((!str || !this.highlightKey || this.highlightKey.length === 0) && this.type !== 'textarea') {return str}let rebuild = strif (this.highlightKey.filter(item => ~str.indexOf(item)).length) {let regStr = ''let regExp = nullthis.highlightKey.forEach(list => {regStr = this.escapeString(list)regExp = new RegExp(regStr, 'g')rebuild = rebuild.replace(regExp, `<span>${list}</span>`)})}if (this.type === 'textarea') {rebuild = rebuild.replace(/\n/g, '<br/>').replace(/\s/g, '&nbsp;')// textarea有滚动条时,div底部不能和textarea重合,故加一个<br/>const wrap = this.$refs.textareaBoxif (wrap && wrap.scrollHeight > this.maxHeight) {rebuild = rebuild + '<br/>'}}return rebuild},syncScrollTop() {const wrap = this.$refs.textareaBoxconst outerWrap = this.$refs.textareaOuterconst outerInner = this.$refs.outerInnerif (wrap.scrollHeight > this.maxHeight && outerInner.scrollHeight !== wrap.scrollHeight) {outerInner.style.height = `${wrap.scrollHeight}px`}if (wrap.scrollTop !== outerWrap.scrollTop) {outerWrap.scrollTop = wrap.scrollTop}},scrollMousewheel() {if (this.type === 'input') {return}this.$nextTick(() => {this.eventHandler('add')})},// 处理字符串中可能对正则有影响的字符escapeString(value) {const characterss = ['(', ')', '[', ']', '{', '}', '^', '$', '|', '?', '*', '+', '.']let str = value.replace(new RegExp('\\\\', 'g'), '\\\\')characterss.forEach(function(characters) {let r = new RegExp('\\' + characters, 'g')str = str.replace(r, '\\' + characters)})return str},eventHandler(type) {const wrap = this.$refs.textareaBoxif (wrap) {let mousewheelevt = (/Firefox/i.test(navigator.userAgent))? 'DOMMouseScroll' : 'mousewheel'wrap[`${type}EventListener`](mousewheelevt, this.syncScrollTop)wrap[`${type}EventListener`]('scroll', this.syncScrollTop)}}},destroyed() {this.eventHandler('remove')}
}
</script><style lang="less">
@width: 500px;
.highlight-box {font-family: 'Franklin Gothic Medium', 'Arial Narrow', Arial, sans-serif;position: relative;display: flex;font-size: 12px;width: @width;position: relative;color: #333333;background: #ffffff;border-radius: 5px;overflow: hidden;.textarea-outer,.input-outer {box-sizing: border-box;width: @width;position: absolute;top: 0;left: 0;right: 0;border: 1px solid transparent;border-top: 0;// 鼠标事件失效 ie6-10不支持pointer-events: none;cursor: text;span {color: #F27C49;}&:hover {border-color: #4C84FF;}}.textarea-outer {overflow-y: auto;line-height: 20px;word-break: break-all;.outer-inner {padding: 5px 8px;width: 100%;box-sizing: border-box;}}textarea {width: @width;line-height: 20px;resize: none;}.input-outer,input {width: @width;height: 28px;line-height: 28px;}.input-outer {bottom: 0;padding: 0 8px;overflow: hidden;white-space: nowrap;text-overflow: ellipsis;}textarea,input {font-family: 'Franklin Gothic Medium', 'Arial Narrow', Arial, sans-serif;font-size: 12px;// position: relative;// z-index: 2;// 光标的颜色color: #333333;// 文本颜色text-shadow: 0 0 0 rgba(0, 0, 0, 0);-webkit-text-fill-color: transparent;background: transparent;border-radius: 5px;border: 1px solid #E0E0E0;padding: 4px 8px;box-sizing: border-box;&::placeholder {-webkit-text-fill-color: #999999;}&:hover {border-color: #4C84FF;}&:focus {border-color: #4C84FF;box-shadow: 0 0 0 2px #DBE4FF;outline: none;}}
}
</style>

后端代码

触发敏感词记录
 /*** 敏感词检查**/public void sensitiveWordCheck(SubPublishing subPublishing) {List<TzLySensitiveWordRecord> recordList = new ArrayList<>();Date nowDate = DateUtils.getNowDate();//找出标题的敏感词List<String> titleList = SensitiveWordHelper.findAll(subPublishing.getPublishTitle());TzLySensitiveWordRecord dbTitle = sensitiveWordRecordService.selectTzLySensitiveWordRecordByMessageIdAndSource(subPublishing.getId(), HYZR_TITLE);//插入if (ObjectUtil.isNull(dbTitle) && CollectionUtils.isNotEmpty(titleList)) {TzLySensitiveWordRecord record = new TzLySensitiveWordRecord();record.setWordId(null);// 敏感词IDrecord.setWord(StrUtil.join(",", titleList)); //敏感词record.setMessageId(subPublishing.getId());// 主键IDrecord.setUserId(Long.valueOf(subPublishing.getCreatorId()));// 发送人IDrecord.setUserName(subPublishing.getCreatorName());// 发送人姓名record.setMobile(subPublishing.getCreatorTel());// 发送人手机号record.setSendTime(nowDate);// 发送时间record.setIsDeleted(0);// 是否删除record.setCreatedDate(nowDate);// 创建时间record.setCreatedBy(Long.valueOf(subPublishing.getCreatorId()));// 创建人record.setSource(HYZR_TITLE);//消息来源 会员值日record.setMessage(subPublishing.getPublishTitle()); //记录实际发送消息record.setReplaceMessage(subPublishing.getPublishTitle()); //记录替换的消息recordList.add(record);//更新} else if (ObjectUtil.isNotNull(dbTitle)) {dbTitle.setWord(StrUtil.join(",", titleList)); //敏感词dbTitle.setLastModifiedDate(nowDate);// 修改时间dbTitle.setLastModifiedBy(Long.valueOf(subPublishing.getCreatorId()));// 修改人dbTitle.setMessage(subPublishing.getPublishTitle()); //记录实际发送消息dbTitle.setReplaceMessage(subPublishing.getPublishTitle()); //记录替换的消息recordList.add( dbTitle);}TzLySensitiveWordRecord dbContent = sensitiveWordRecordService.selectTzLySensitiveWordRecordByMessageIdAndSource(subPublishing.getId(), HYZR_CONTENT);if (CollectionUtils.isNotEmpty(recordList)) {sensitiveWordRecordService.saveOrUpdateBatch(recordList);}}

回显敏感词记录

        SubPublishing subPublishing = this.getById(id);//查询是否触发敏感词Map<String, TzLySensitiveWordRecord> sensitiveWordRecordMap = sensitiveWordRecordService.selectListByMessageId(id).stream().collect(Collectors.toMap(TzLySensitiveWordRecord::getSource, o -> o));if (!sensitiveWordRecordMap.isEmpty()) {TzLySensitiveWordRecord title = sensitiveWordRecordMap.get(HYZR_TITLE);if (ObjectUtil.isNotNull(title)) {subPublishing.setTitleSensitiveWord(StrUtil.split(title.getWord(), ","));}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/374275.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vue3 + tsx 表格 Action 单独封装组件用法

前言 先上图看右侧列 action 的 UI 效果&#xff1a; 正常来说&#xff0c;如果一个表格的附带 action 操作&#xff0c;我们一般会放在最右侧的列里面实现&#xff0c;这个时候有些UI 框架支持在 SFC 模板里面定义额外的 solt&#xff0c;当然如果不支持&#xff0c;更通用的…

LabVIEW实现LED显示屏视觉检测

为了满足LED显示屏在生产过程中的严格质量检测需求&#xff0c;引入自动化检测系统是十分必要的。传统人工检测方式存在检测强度高、效率低、准确性差等问题&#xff0c;自动化检测系统则能显著提高检测效率和准确性。视觉检测系统的构建主要包含硬件和软件两个部分。 视觉系统…

新兴市场游戏产业爆发 传音以技术抢抓机遇 ​

随着年轻人口的增加以及互联网的普及,非洲、中东等新兴市场正迎来游戏产业的大爆发,吸引着全球游戏企业玩家在此开疆辟土。中国出海企业代表传音以新兴市场需求为中心,秉持本地化创新理念不断加强游戏等关键领域技术攻关凭借移动终端设备为全球玩家带来极致游戏体验,收获了消费…

谷粒商城实战笔记-26-分布式组件-SpringCloud-Gateway网关核心概念原理

微服务架构中&#xff0c;API网关扮演着至关重要的角色&#xff0c;它不仅作为微服务间的通信桥梁&#xff0c;还负责安全、监控、限流等职责。 一&#xff0c;网关的发展历程 SpringCloud的网关经历了两代的迭代和更替。 第一代网关是早期的Zuul&#xff0c;由 Netflix 开发…

kafka 消费者

消费者 消费者。消费者连接到Kafka上并接收消息&#xff0c;进而进行相应的业务逻辑处理。 消费组 消费者负责订阅Kafka中的主题&#xff0c;并且从订阅的主题上拉取消息。 消费组&#xff1a;每个消费者都有一个对应的消费组&#xff0c;每一个分区只能被一个消费组中的一个…

深入了解Rokid UXR2.0 SDK内置的Unity AR Glass开发组件

本文将了解到Rokid AR开发组件 一、RKCameraRig组件1.脚本属性说明2.如何使用 二、PointableUI组件1.脚本属性说明2.如何使用 三、PointableUICurve组件1.脚本属性说明2.如何使用 四、RKInput组件1.脚本属性说明2.如何使用 五、RKHand组件1.脚本属性说明2.如何使用3.如何禁用手…

昇思25天学习打卡营第17天|基于 MindSpore 实现 BERT 对话情绪识别

基于 MindSpore 实现 BERT 对话情绪识别 BERT介绍 BERT&#xff08;Bidirectional Encoder Representations from Transformers&#xff09;是一种基于Transformer架构的预训练语言模型&#xff0c;由谷歌在2018年提出。从以下6个方面来介绍BERT&#xff1a; 1. 预训练和微调&…

Linux C语言基础 day8

目录 思维导图&#xff1a; 学习目标&#xff1a; 学习内容&#xff1a; 1. 字符数组 1.1 二维字符数组 1.1.1 格式 1.1.2 初始化 1.1.3 二维字符数组输入输出、求最值、排序 2. 函数 2.1 概念 关于函数的相关概念 2.2 函数的定义及调用 2.2.1 定义函数的格式 2.3…

GaussDB关键技术原理:高性能(五)

GaussDB关键技术原理&#xff1a;高性能&#xff08;四&#xff09;从USTORE存储引擎、计划缓存计划技术、数据分区与分区剪枝、列式存储和向量化引擎、SMP并行执行等五方面对高性能关键技术进行解读&#xff0c;本篇将从LLVM动态查询编译执行、SQL-BYPASS执行优化、线程池化、…

k8s核心操作_Ingress统一网关入口_域名访问配置_ingress域名转发规则配置_根据域名访问不同服务---分布式云原生部署架构搭建026

上一节我们已经把 ingress 安装好了可以看到 kubectl get svc -A 可以看到 出现了ingress-nginx 的service,在ingre-nginx这个命名空间中,有两个,一个是 ingress-nginx-controller 开了两个一个是对应http,一个对应https 一个是 ingress-nginx-controller-admission 对…

14.爬虫---Selenium 经典动态渲染工具的使用

14.Selenium 经典动态渲染工具的使用 1.查看chrome浏览器版本2.ChromeDriver 安装3.Selenium 安装4.验证安装5.基本用法5.1启动浏览器5.2导航到页面5.3查找元素5.3.1单个元素 find_element5.3.2多个元素 find_elements 5.4 执行操作5.5 动作链ActionChains5.6 执行 JavaScript …

修BUG:程序包javax.servlet.http不存在

貌似昨晚上并没有成功在tomcat上面运行&#xff0c;而是直接运行了网页。 不知道为啥又报错这个。。。 解决方案&#xff1a; https://developer.baidu.com/article/details/2768022 就整了这一步就行了 而且我本地就有这个tomcat就是加进去了。 所以说啊&#xff0c;是不是&a…

C语言 | Leetcode C语言题解之第227题基本计算题II

题目&#xff1a; 题解&#xff1a; int calculate(char* s) {int n strlen(s);int stk[n], top 0;char preSign ;int num 0;for (int i 0; i < n; i) {if (isdigit(s[i])) {num num * 10 (int)(s[i] - 0);}if (!isdigit(s[i]) && s[i] ! || i n - 1) {s…

二分法求函数的零点 信友队

题目ID&#xff1a;15713 必做题 100分 时间限制: 1000ms 空间限制: 65536kB 题目描述 有函数&#xff1a;f(x) 已知f(1.5) > 0&#xff0c;f(2.4) < 0 且方程 f(x) 0 在区间 [1.5,2.4] 有且只有一个根&#xff0c;请用二分法求出该根。 输入格式 &#xff08;无…

【Linux进阶】文件系统8——硬链接和符号连接:ln

在Linux下面的链接文件有两种&#xff0c; 一种是类似Windows的快捷方式功能的文件&#xff0c;可以让你快速地链接到目标文件&#xff08;或目录)&#xff1b;另一种则是通过文件系统的inode 链接来产生新文件名&#xff0c;而不是产生新文件&#xff0c;这种称为硬链接&…

sql注入时间盲注

基于时间的盲注 也叫延时注入。通过观察页面&#xff0c;既没有回显数据库内容&#xff0c;又没有报错信息也没有布尔类型状态&#xff0c;那么我们可以考虑用“绝招”--延时注入。延时注入就是根据页面的响应时间来判断是否存在注入&#xff0c;一点一点注入出数据库的信息。我…

HTML+CSS+JS 实现3D风吹草动效果(B站视频)

效果&#xff1a; 代码&#xff1a; <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewport" content"widthdevice-width, initial-scale1.0" /><title>3D effect&…

Python 爬虫与 Java 爬虫:相似之处、不同之处和选项

在信息时代&#xff0c;网络上可用的数据量巨大且不断增长。为了从这些数据中提取有用的信息&#xff0c;爬虫已成为一种重要的技术。Python 和 Java 都是流行的编程语言&#xff0c;都具有强大的爬虫功能。本文将深入探讨 Python 爬虫和 Java 爬虫之间的差异&#xff0c;以帮助…

PCIe驱动开发(1)— 开发环境搭建

PCIe驱动开发&#xff08;1&#xff09;— 开发环境搭建 一、前言 二、Ubuntu安装 参考: VMware下Ubuntu18.04虚拟机的安装 三、QEMU安装 参考文章&#xff1a;QEMU搭建X86_64 Ubuntu虚拟系统环境 四、安装Ubuntu 下载地址&#xff1a;https://old-releases.ubuntu.com…

【错题集-编程题】买卖股票的最好时机(四)(动态规划)

力扣对应题目链接&#xff1a;188. 买卖股票的最佳时机 IV - 力扣&#xff08;LeetCode&#xff09; 牛客对应题目链接&#xff1a;买卖股票的最好时机(四)_牛客题霸_牛客网 (nowcoder.com) 一、分析题目 1、状态表示 为了更加清晰的区分买入和卖出&#xff0c;我们换成有股…