<>nlp标注系统前端功能实现

<>简介

由于目前是在AI部门任职前端,需要给部门的标注人员做一个标注系统。做之前感觉挺简单,真正编码的时候发现有些细节的地方还挺复杂的。

简单做一下需求分析,列举一下主要功能点:

* 导入原始数据(json),例如: [ { "text": "【最终指导】20首开PPN001,目前边际3.99,
3.9以内已有超一半的量,预期3.8,请大家于17点前反馈我最终标位。", "labels": [] }, { "text":
"【明日9:30】19赣州城投SCP002,目前全场2倍,仍有量在途,边际4.03%,边际倍数1.4倍,引导小区间【3.20-3.50%】,请大家慎重考虑修改,并于明早9:30前反馈一轮,感谢支持",
"labels": [] }, ]
* 导出处理完的数据,例如: [ { "id": 103, "text": "【最终指导】20首开PPN001,目前边际3.99,
3.9以内已有超一半的量,预期3.8,请大家于17点前反馈我最终标位。", "markUser": "1", "auditUser": "1",
"labels": [ [ 22, 31, "aaa" ] ] }, { "id": 104, "text":
"【明日9:30】19赣州城投SCP002,目前全场2倍,仍有量在途,边际4.03%,边际倍数1.4倍,引导小区间【3.20-3.50%】,请大家慎重考虑修改,并于明早9:30前反馈一轮,感谢支持",
"markUser": "1", "auditUser": "1", "labels": [ [ 21, 26, "aaa" ] ] }, ]
* 我们需要给导入的每一段文本加上标签进行标注,例如我们给【17点前】标注为”最后时间“.这里最难处理!
* 每个项目有一个标签列表,可以手动填写,也可以导入json,如下:

<>开始编码

由于此文的重点就是标注功能,所以其他功能点就不作过多阐述。
标注功能我们看下实际效果:

<>第一步:获取选中区间

开始做的时候我觉得直接给选中区域添加span标签去处理,后面发现当添加了span后,window.getSection()返回的startIndex 和
endIndex是不准确的,它是以同层级标签里的内容为基准的。什么意思呢?比如我现在有这样一个元素
<div> 123456789 </div>
当我选中345之后,window.getSection().getRangeAt(0)返回的startIndex 和 endIndex是2和5,结构变成了这样
<div> <span>12</span> <span>345</span> <span>6789</span> </div>
当我再次选中67,返回的startIndex 和 endIndex是0和1,
而不是我想要的5和8,竟然是以选中所处的span里面内容为基准的,不是我想要的始终以外层div返回。这里我找了下资料,发现如下黑科技可以返回我想要的:
export const getRange = (node) => { let selection; if (window.getSelection) {
selection = window.getSelection(); } else if (document.getSelection) {
selection = document.getSelection(); } // If nothing is selected. if
(selection.rangeCount <= 0) { return null; } const range =
selection.getRangeAt(0); const preSelectionRange = range.cloneRange();
preSelectionRange.selectNodeContents(node);
preSelectionRange.setEnd(range.startContainer, range.startOffset); const start
= [...preSelectionRange.toString()].length; const end = start +
[...range.toString()].length; console.log('setSpanInfo start end', start, end);
return { start, end }; }
这里的node就是外层div的dom节点。可始终返回选中区域以外层div为基准的start和end

<>第二步:生成div的子元素

我们称初始文本为initText

当选中一段区间,我们要给此区间不同的样式,标注上选中的标签,这个部分比较简单,就不做过多详述。关键在于我们生成的子元素列表,也就是由span元素组成的列表,这里该如何处理。
要考虑几个问题:
1. 选中区域的start跟initText的第一个元素重合或者跟所处span的第一个元素重合,该怎么截取。
2. 选中区域在所处span中间
3. 选中区域end跟所处span最后一个元素重合
4. 选中区域跟所处span内容完全重合
这里要考虑的就是数组的截取处理,能考虑到这几个情况,编程就不难。
<>第三步:删除某个标签

新增的我们搞定了,拿删除的就比较顺手了,考虑情况如下:
1. start一致且end一致
2. start 一致 end不一致
3. start 不一致而 end一致
4. start end都不一致
不一样的是,添加是截取数组,删除是合并数组
<>第四步: 完善其他功能

搞定了上面的标注,基本上这个需求就剩下缝缝补补了。这个页面其他的功能如下:
1、添加事件监听选择标签
2、把标注了的列表过滤出来,显示在下方,这里是导出数据所需要的
3、翻页

bingo!!!

技术
下载桌面版
GitHub
Gitee
SourceForge
百度网盘(提取码:draw)
云服务器优惠
华为云优惠券
腾讯云优惠券
阿里云优惠券
Vultr优惠券
站点信息
问题反馈
邮箱:[email protected]
吐槽一下
QQ群:766591547
关注微信