怎么根据字符串纠错后的返回结果进行文本内容高亮显示/结果展示?

文本字符串:'芸南市气象台暴雨橙色色预警信号,目前降雨云团已东北移,对芸南市影响减弱,请主意防范降水过后可能引发的次生灾害'
纠错识别后返回数据为:

{"leader":[],"org":[],word": [[37, "主意", "注意", "word"]], "char": [], "redund": [[9, "色", "", "redund"]], "miss": [[9, "色色", "色黄色", "miss"]], "addr": [[0, "芸南市", "丰南市", "addr_S"]], "name": []}

想根据返回内容进行文字高亮显示
其中"word": [[37, "主意", "注意", "word"]],代表错别词纠错 意思分别为 [位置,原词,结果词,类型]

识别后在页面显示为
<span style="color: #333;font-weight: 700;background-color: orange;">芸南市</span>气象台暴雨橙<span style="color: #333;font-weight: 700;background-color: orange;">色色</span>预警信号,目前降雨云团已东北移,对<span style="color: #333;font-weight: 700;background-color: orange;">芸南市</span>影响减弱,请<span style="color: #333;font-weight: 700;background-color: orange;">主意</span>防范降水过后可能引发的次生灾害
并根据返回结果列表纠错识别结果 有纠错的排前面纠错返回意思如下:
领导人职务纠错:
组织机构纠错:
别词纠错:1
别字纠错:
语法纠错:2(redund-表示语法冗余 / miss表示语法缺失)
地名纠错:1
全文人名纠错:

效果如下:
1669110296820.png
右侧识别后点击效果图如:
3BCFCEA0E2EE136CC5D4B5554122DA84.png
目前的效果是我根据需要写死的
左侧根据@shinak 的写完左侧内容 右侧的内容 我写了循环判断

            let ret = []
            for(let key in data) {  
                let obj = {}
                data[key].forEach((item,index) => {
                    let [pos , olw, resw, type] = item
                    if(type.indexOf('addr') !== -1){
                        obj.name = "地名纠错";obj.type = type; obj.pos = pos;obj.oldpos = olw;obj.corrpos = resw
                    }if(type == 'char'){
                         obj.name = "别字纠错";obj.type = type; obj.pos = pos;obj.oldpos = olw;obj.corrpos = resw
                    }if(type == 'leader'){
                         obj.name = "领导人纠错";obj.type = type; obj.pos = pos;obj.oldpos = olw;obj.corrpos = resw
                    }if(type == 'miss' || type == 'redund'){
                         obj.name = "语法纠错";obj.type = type; obj.pos = pos;obj.oldpos = olw;obj.corrpos = resw
                    }if(type == 'name'){
                         obj.name = "全文人名纠错";obj.type = type; obj.pos = pos;obj.oldpos = olw;obj.corrpos = resw
                    }if(type == 'org'){
                         obj.name = "机构名纠错";obj.type = type; obj.pos = pos;obj.oldpos = olw;obj.corrpos = resw
                    }if(type == 'word'){
                        obj.name = "别词纠错";obj.type = type; obj.pos = pos;obj.oldpos = olw;obj.corrpos = resw
                    }
                }) 
                ret.push(obj)
            }

返回值是:'{"black_list": [], "punc": [[122, ":?", "", "连续使用标点"]], "leader": [], "org": [], "pol": [], "grammar_pc": [], "order": [], "idm": [], "word": [], "char": [], "redund": [], "miss": [], "dapei": [], "number": [], "addr": [], "name": [], "yjdatetime": [[10,"202251201","2023年03月16日","发布时间与当前时间不一致"]], "yjaddr": [[-1,"","","未包含正确的行政区域名称。"]]}'

我用

[...errMap.entries()].forEach(([key, value]) => {
 content =content.replace(eval(`/${value[1]}/g`), `<span style="color: #333;font-weight: 700;background-color: orange;">${value[1]}</span>`);})

后高亮变成了1678951414175.png

阅读 2.1k
2 个回答

根据纠错识别返回的数据对原来的文本字符串内容做替换,然后用类似innerHTML这种能把文本以html的形式插入DOM的api就可以实现效果了

const resp = JSON.parse(`{"leader":[],"org":[],"word": [[37, "主意", "注意", "word"]], "char": [], "redund": [[9, "色", "", "redund"]], "miss": [[9, "色色", "色黄色", "miss"]], "addr": [[0, "芸南市", "丰南市", "addr_S"]], "name": []}`);
const styleMap = new Map([["leader", "css1"], ["org", "css2"], ["word", "css3"], ["char", "css4"], ["redund", "css5"], ["miss", "css6"], ["addr", "css7"], ["name", "css8"]]);
let content = '芸南市气象台暴雨橙色色预警信号,目前降雨云团已东北移,对芸南市影响减弱,请主意防范降水过后可能引发的次生灾害';

Object.keys(resp).forEach(key => resp[key].forEach(err => err[4] = key));
const errMap = new Map();
Object.keys(resp).flatMap(key => resp[key]).forEach((err) => {
  const idx = err[0];
  if(errMap.has(idx)) {
    if(errMap.get(idx)[1].length < err[1].length) {
      errMap.set(idx, err);
    }
  } else {
    errMap.set(idx, err);
  }
});
console.log(errMap);

[...errMap.entries()].forEach(([key, value]) => {
  content = content.replace(eval(`/${value[1]}/g`), `<span style="${styleMap.get(value[4])}">${value[1]}</span>`);
});

console.log(content);

高亮的字符与返回的纠错数据一一对应,只能匹配第一个“芸南市”

function highlightText (item, index) {
  return `<span class="hl" style="color: #333;font-weight: 700;background-color: orange;">${item.content}</span>`
}

function highlightContent () {
  const res = { "leader": [], "org": [], "word": [[37, "主意", "注意", "word"]], "char": [], "redund": [[9, "色", "", "redund"]], "miss": [[9, "色色", "色黄色", "miss"]], "addr": [[0, "芸南市", "丰南市", "addr_S"]], "name": [] }
  const content = '芸南市气象台暴雨橙色色预警信号,目前降雨云团已东北移,对芸南市影响减弱,请主意防范降水过后可能引发的次生灾害'

  // 计算纠错字符
  let wWordsData = [] // wrong words
  for (let key in res) {
    const item = res[key]
    if (Array.isArray(item)) {
      item.forEach(child => {
        const [pos, oWord, cWord, type] = child
        const wordItem = {
          start: pos,
          end: pos + oWord.length,
          extend: {
            oWord,
            cWord,
            type,
          },
          content: oWord
        }
        wWordsData.push(wordItem)
      })
    }
  }

  if (wWordsData.length > 1) {
    // wWordsData 小到大排序
    wWordsData.sort((a, b) => a.start - b.start)
    
    // 合并重合字符
    const wWordsTemp = []
    let prev = wWordsData[0]
    for (let i = 1; i < wWordsData.length; i++) {
      // debugger
      const cur = wWordsData[i]
      // 如果字符重合
      if (cur.start < prev.end) {
        const start = prev.start
        const end = Math.max(prev.end, cur.end)
        prev = {
          start,
          end,
          content: content.slice(start, end),
          words: [...(prev.words || [prev]), cur]
        }
      } else {
        wWordsTemp.push(prev)
        prev = cur
      }
    }
    wWordsTemp.push(prev)
    wWordsData = wWordsTemp
  }
  
  // 纠错字符高量
  wWordsData.forEach((item, index) => {
    item.content = highlightText(item, index)
  })
  
  // 计算未纠错字符
  const cWordsData = [] // correct words
  const addCWordsData = (start, end) => {
    if (start >= end) return
    cWordsData.push({
      start,
      end,
      content: content.slice(start, end)
    })
  }
  let flag = 0
  wWordsData.forEach((item, index) => {
    if (item.start > flag) {
      addCWordsData(flag, item.start)
    }
    flag = item.end
    // last
    if (index === wWordsData.length - 1) {
      addCWordsData(item.end, content.length - 1)
    }
  })

  // 联合所有字符并排序
  const wordsData = [...wWordsData, ...cWordsData]
  wordsData.sort((a, b) => a.start - b.start)
  const article = wordsData.map(item => item.content).join('')
  
  console.log(article, 'article')
  console.log(wordsData, 'wordsData')
}

highlightContent() 
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题