1058433796 / graduation-project

为了更好的完成毕设,将有帮助的内容保存在此。
0 stars 0 forks source link

文本标注平台功能实现 #3

Open 1058433796 opened 3 years ago

1058433796 commented 3 years ago

基本功能

1058433796 commented 3 years ago

前端实现

文本导入

用户上传文本后文本内容保存为特定字段,调用api传给后端,由后端将文本导入数据库。 用户上传文本后python保存文本文件到本地(或许可以保存到本地读取内容到数据库后删除文件?),使用uuid1重命名,并在数据库中添加一条记录。 记录中包含id,uid,title,content,highlights。

用户标记

参考 如何用JS实现“划词高亮”的在线笔记功能:https://zhuanlan.zhihu.com/p/63794559

管理审核

前端调用api获取待审核的文本

文本导出

暂定

前端实现-新

文本分词

用户上传待分词文本,设置不进行分词的字典后进行分词,得到分词后的文本。默认分词符为#$#,可以自定义分词符。 允许用户在分词完成后查看分词结果并修改分词。 分词后的文本格式如下: 未分词:你们吃饭了吗 已分词:你们#$#吃饭#$#了#$#吗 存在问题: API分词同时标注词性与实体,如果分词与词性和实体标注分隔开,无法实现 因此只能分词并标注词性/实体后允许用户修改分词方式和标注内容。

词性标注

用户在当前页面上传文本,处理后得到已标注词性文本 标注文本格式(假设空格为分词符): 未标注:你们现在吃饭 了 吗 已标注:你们#n 现在#t 吃饭#v 了#adv 吗#adv

实体标注

与词性标注同理,标注内容变为实体

标签标注

用户手动标注标签,标记完成后将标注格式转换为类似“你们#n早上#t”这种格式,供自动标注使用。

自动标注

上传标签标注后的文本,从文本中读取用户的标注,对原文本进行分词(用户标注的内容不进行分词不可行, 用户可能标注的不是词语 而是句子)、词性标注、实体标注后从分词中筛选出与用户标注的标签词性相同且实体相同的分词,使用某种方式计算分词与标签的相似度,高于一定阈值的分词进行对应的标签标注。

后端实现

使用python尝试连接mysql实现增删查改的功能。

1058433796 commented 2 years ago

用户高亮功能探索

使用web-highlighter插件进行高亮

> 使用ref模板引用选定区域进行高亮
```html
<template>
<h1>Right Page</h1>
  <p ref="text">这是一段话用于测试highlighter是否可以正常工作。希望可以达到预期效果。</p>
</template>

<script setup>
import Highlighter from 'web-highlighter';
import {getCurrentInstance, onMounted} from "vue";
onMounted(() =>{
  const that = getCurrentInstance().ctx
  const highlighter = new Highlighter({
    $root: that.$refs.text
  })
  highlighter.run()
})
</script>
1058433796 commented 2 years ago

暂时记录

onMounted(() =>{
  const that = getCurrentInstance().ctx
  const highlighter = new Highlighter({
    $root: that.$refs.text,
    wrapTag: 'mark'
  })
  // add some listeners to handle interaction, such as hover
  highlighter
      .on('selection:hover', ({id}) => {
        // display different bg color when hover
        highlighter.addClass('highlight-wrap-hover', id);
        // console.log('hover')
      })
      .on('selection:hover-out', ({id}) => {
        // remove the hover effect when leaving
        highlighter.removeClass('highlight-wrap-hover', id);
        // console.log('hover-out')
      })
      .on('selection:create', ({sources}) => {
        // sources = sources.map(hs => ({hs}));
        // save to backend
        // store.save(sources);
        const {startMeta, endMeta} = sources[0]
        // console.log(sources[0].startMeta.parentIndex)
        console.log(startMeta, endMeta)
        const spans = that.$refs.text.children
        const spanArray = [...spans]
        spanArray.filter(tag => {
          tag.tagName.toLowerCase() === 'span'
        })
        // console.log(spanArray)
        console.log('===============================')
        console.log(`parentIdx: ${startMeta.parentIndex}   Text: ${spanArray[startMeta.parentIndex].children.length}`)
        // console.log(spanArray[startMeta.parentIndex].children[0].innerText)
        // console.log(spanArray[endMeta.parentIndex])
      });
  highlighter.run()
})
1058433796 commented 2 years ago

手动实现文本高亮

function onselect(){
  let selObj = window.getSelection();
  if(selObj.isCollapsed)return
  let selRange = selObj.getRangeAt(0);
  const {startOffset, endOffset, startContainer, endContainer} = selRange
  let markTag = document.createElement('mark')
  const tags = [...document.querySelector('#text').children]
  surroundWIthTag('mark', startContainer.parentElement.id, endContainer.parentElement.id)
}
function surroundWIthTag(tag, begTagId, endTagId){
  const tags = [...document.querySelector('#text').children]
  const targetTag = document.createElement(tag)
  for(let t of tags){
    if(t.id === begTagId){
      t.parentElement.insertBefore(targetTag, t)
    }
    if(t.id >= begTagId && t.id <= endTagId){
      targetTag.appendChild(t)
    }
  }
  const label = document.createElement('span')
  label.setAttribute('class', 'label')
  label.innerText = 'person'
  targetTag.appendChild(label)
}

用到的知识

  1. window.getSelection() 获取用户当前鼠标位置或者选中内容
  2. selObj.getRangeAt(0) 获取selection中的第一个Range
  3. insertBefore() pNode.insertBefore(newNode, node) 其中pNode为node的父节点,newNode插入到node前
  4. node.appendChild()将节点插入到node中成为child,放入后原先位置的节点将消失

    效果图

    image

1058433796 commented 2 years ago

高亮文本标签去除

//高亮文本 添加监听事件   this指向高亮文本
// 屏蔽右键菜单
document.ontextmenu = e => false

spanTag.addEventListener('mouseup', (e) =>{
  if(e.button != 2)return
  removeHighlight(spanTag)
})

function removeHighlight(highlightTag){
  // 取消高亮
  // 1. 去除label tag
  // 2. all span insertBefore mark
  // 3. remove mark

  // <mark></mark>
  const markTag = highlightTag.children[0]
  // span1  span2 ... span.label
  const textSpanTags = markTag.childNodes
  // span.label
  const labelTag = textSpanTags[textSpanTags.length - 1]
  labelTag.remove()
  const markParent = markTag.parentElement
  while(textSpanTags.length > 0){
    const child = textSpanTags[0]
    markParent.parentElement.insertBefore(child, markParent)
  }
  highlightTag.remove()
}

用到的方法

  1. node.remove() 将node本身删除
  2. pNode.removeChild(node) 将pNode孩子node删除

    效果图

    删除前 image 删除后 image

1058433796 commented 2 years ago

文本高亮存在的问题

解决方法猜想

1058433796 commented 2 years ago

自动标注实现新思路

时间 2021年12月17日13:56:16