此插件仅适用于 付费 TinyMCE 订阅。

mentions 插件会在用户输入“@”符号后跟用户名开头时显示用户列表。它会通过 mentions_fetch 回调向您的服务器发起查询。

交互式示例

HTML

<textarea id="mentions">
  <p><img style="display: block; margin-left: auto; margin-right: auto;" title="Tiny Logo" src="https://www.tiny.cloud/docs/tinymce/latest/_images/logos/android-chrome-256x256.png" alt="TinyMCE Logo" width="128" height="128"></p>

  <h2 style="text-align: center;">欢迎使用 TinyMCE Mentions 交互式演示!</h2>

  <p>输入“<kbd>@</kbd>”后紧接着输入一个或多个字符。</p>
  
  <p>例如:@a</p>
  
  <p style="text-align: center;">请访问 <a href="https://www.tiny.cloud/pricing">定价页面</a> 以了解更多有关我们 Premium 插件的信息。</p>
  
  <h2>一个可供操作的简单表格</h2>

  <table style="border-collapse: collapse; width: 100%;" border="1">
    <thead>
      <tr style="text-align: left;">
        <th>产品</th>
        <th>成本</th>
        <th>真的吗?</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td style="text-align: center;">TinyMCE Cloud</td>
        <td style="text-align: center;">免费开始使用</td>
        <td style="text-align: center;"><strong>是的!</strong></td>
      </tr>
    </tbody>
  </table>

  <h2>发现了错误?</h2>

  <p>如果您认为发现了错误,请在 <a href="https://github.com/tinymce/tinymce/issues">GitHub 仓库</a> 上创建一个 issue,以向开发者报告。</p>

  <h2>最后……</h2>

  <p>您的应用需要文件上传功能吗?可以考虑将 <a href="https://www.tiny.cloud/docs/tinymce/latest/uploadcare/" target="_blank" rel="noopener noreferrer">Uploadcare</a> 与 TinyMCE 结合使用,以获得快速、现代化的上传体验。</p>
  <p>感谢您支持 TinyMCE。我们希望它能帮助您和您的用户创建优质内容。</p>
  <p>来自 TinyMCE 团队的美好祝愿。</p>

</textarea>

CSS

textarea#mentions {
  height: 350px;
}

.mymention {
  color: gray !important;
}

div.card,
.tox div.card {
  width: 240px;
  background: white;
  border: 1px solid #ccc;
  border-radius: 3px;
  box-shadow: 0 4px 8px 0 rgba(34, 47, 62, .1);
  padding: 8px;
  font-size: 14px;
  font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;
}

div.card::after,
.tox div.card::after {
  content: "";
  clear: both;
  display: table;
}

div.card h1,
.tox div.card h1 {
  font-size: 14px;
  font-weight: bold;
  margin: 0 0 8px;
  padding: 0;
  line-height: normal;
  font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;
}

div.card p,
.tox div.card p {
  font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;
}

div.card img.avatar,
.tox div.card img.avatar {
  width: 48px;
  height: 48px;
  margin-right: 8px;
  float: left;
}

JS

const API_URL = 'https://demouserdirectory.tiny.cloud/v1/users';

const mentions_fetch = async (query, success) => {
  const searchPhrase = query.term.toLowerCase();
  await fetch(`${API_URL}?q=${encodeURIComponent(searchPhrase)}`)
    .then((response) => response.json())
    .then((users) => success(users.data.map((userInfo) => ({
      id: userInfo.id,
      name: userInfo.name,
      image: userInfo.avatar,
      description: userInfo.custom.role
    }))))
    .catch((error) => console.log(error));
};

const mentions_menu_complete = (editor, userInfo) => {
  const span = editor.getDoc().createElement('span');
  span.className = 'mymention';
  span.setAttribute('data-mention-id', userInfo.id);
  span.appendChild(editor.getDoc().createTextNode('@' + userInfo.name));
  return span;
};

const createCard = (userInfo) => {
  const div = document.createElement('div');
  div.innerHTML = (
    '<div class="card">' +
      '<img class="avatar" src="' + userInfo.image + '">' +
      '<h1>' + userInfo.name + '</h1>' +
      '<p>' + userInfo.description + '</p>' +
    '</div>'
  );
  return div;
};

const mentions_select = async (mention, success) => {
  const id = mention.getAttribute('data-mention-id');
  await fetch(`${API_URL}/${id}`)
    .then((response) => response.json())
    .then((userInfo) => {
      const card = createCard({
        id: userInfo.id,
        name: userInfo.name,
        image: userInfo.avatar,
        description: userInfo.custom.role
      });
      success(card);
    })
    .catch((error) => console.error(error));
};

const mentions_menu_hover = async (userInfo, success) => {
  const card = createCard(userInfo);
  success(card);
};

tinymce.init({
    selector: "textarea",
    plugins: [
      "advlist", "anchor", "autolink", "charmap", "code", "fullscreen",
      "help", "image", "insertdatetime", "link", "lists", "media",
      "preview", "searchreplace", "table", "visualblocks", "mentions"
    ],
    toolbar: "undo redo | styles | bold italic underline strikethrough | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image",
    content_style: '.mymention{ color: gray; }',
    mentions_fetch,
    mentions_item_type: 'profile',
    mentions_menu_complete,
    mentions_selector: '.mymention',
    mentions_select,
    mentions_menu_hover,
    tinycomments_mode: 'embedded'
});

有关使用模块打包器打包此插件的信息,请参阅 打包 TinyMCE - 概述。