You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

将quill-mention生成的HTML Span转换为@data-id格式并支持还原

1. Quill-Mention HTML 转 @data-id 格式

通过解析HTML DOM定位所有带mention类的<span>标签,将其替换为@<data-id>格式,同时保留原有HTML结构:

function convertMentionHtmlToIdFormat(htmlStr) {
  const parser = new DOMParser();
  const doc = parser.parseFromString(htmlStr, 'text/html');
  
  const mentionSpans = doc.querySelectorAll('span.mention');
  
  mentionSpans.forEach(span => {
    const dataId = span.getAttribute('data-id');
    if (dataId) {
      const textNode = document.createTextNode(`@${dataId}`);
      span.parentNode.replaceChild(textNode, span);
    }
  });
  
  return doc.body.innerHTML;
}

// 示例调用
const originalHtml = '<p>Hi <span class="mention" data-index="0" data-denotation-char="@" data-id="58963f62-3417-481f-9d46-4f5625e9a1ab" data-value="test1 "><span contenteditable="false"><span class="ql-mention-denotation-char">@</span>test1 </span></span> Hi <span class="mention" data-index="0" data-denotation-char="@" data-id="58963f62-3417-481f-9d46-4f5625e9a1cd" data-value="test2 "><span contenteditable="false"><span class="ql-mention-denotation-char">@</span>test2 </span></span> </p>';
const convertedText = convertMentionHtmlToIdFormat(originalHtml);
console.log(convertedText);
// 输出: <p>Hi @58963f62-3417-481f-9d46-4f5625e9a1ab Hi @58963f62-3417-481f-9d46-4f5625e9a1cd </p>
2. @data-id 格式还原为 Quill-Mention HTML

还原时需匹配文本中的@<UUID>格式内容,替换为Quill-Mention标准<span>结构,需提前准备id到用户信息的映射表:

function convertIdFormatToMentionHtml(convertedStr, userMap) {
  const parser = new DOMParser();
  const doc = parser.parseFromString(convertedStr, 'text/html');
  
  function traverseNodes(node) {
    if (node.nodeType === Node.TEXT_NODE) {
      const text = node.textContent;
      const regex = /@([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})/g;
      let match;
      const fragments = [];
      let lastIndex = 0;
      
      while ((match = regex.exec(text)) !== null) {
        if (match.index > lastIndex) {
          fragments.push(document.createTextNode(text.slice(lastIndex, match.index)));
        }
        
        const userId = match[1];
        const userInfo = userMap[userId];
        if (userInfo) {
          const mentionSpan = document.createElement('span');
          mentionSpan.className = 'mention';
          mentionSpan.setAttribute('data-index', '0');
          mentionSpan.setAttribute('data-denotation-char', userInfo.denotationChar || '@');
          mentionSpan.setAttribute('data-id', userId);
          mentionSpan.setAttribute('data-value', userInfo.value);
          
          const contentSpan = document.createElement('span');
          contentSpan.setAttribute('contenteditable', 'false');
          
          const denotationSpan = document.createElement('span');
          denotationSpan.className = 'ql-mention-denotation-char';
          denotationSpan.textContent = userInfo.denotationChar || '@';
          
          contentSpan.appendChild(denotationSpan);
          contentSpan.appendChild(document.createTextNode(userInfo.displayName));
          mentionSpan.appendChild(contentSpan);
          
          fragments.push(mentionSpan);
        } else {
          fragments.push(document.createTextNode(match[0]));
        }
        
        lastIndex = regex.lastIndex;
      }
      
      if (lastIndex < text.length) {
        fragments.push(document.createTextNode(text.slice(lastIndex)));
      }
      
      if (fragments.length > 0) {
        const parent = node.parentNode;
        fragments.forEach(frag => parent.insertBefore(frag, node));
        parent.removeChild(node);
      }
    } else if (node.nodeType === Node.ELEMENT_NODE) {
      Array.from(node.childNodes).forEach(traverseNodes);
    }
  }
  
  traverseNodes(doc.body);
  return doc.body.innerHTML;
}

// 示例调用
const userMap = {
  '58963f62-3417-481f-9d46-4f5625e9a1ab': {
    value: 'test1 ',
    displayName: 'test1 ',
    denotationChar: '@'
  },
  '58963f62-3417-481f-9d46-4f5625e9a1cd': {
    value: 'test2 ',
    displayName: 'test2 ',
    denotationChar: '@'
  }
};

const restoredHtml = convertIdFormatToMentionHtml(convertedText, userMap);
console.log(restoredHtml);
// 输出与原始HTML结构一致

内容的提问来源于stack exchange,提问作者Sahil

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 10:14:56