Editor

新建文件、文件夹

  • 创建文件夹:可以在菜单栏中的 我的空间团队空间开放空间 点击右边的菜单按钮去创建文件夹
  • 创建文件:方法同上,当然你也可以在你创建的文件夹点击右边的菜单按钮去创建文件

AI功能

目前我们的编辑器已经成功接入了 Kimi 的 AI 能力,当然你也可以接入其他模型,例如 OpenAI, Gemini 等,借助 AI 我们提供了如下功能:

  • 支持划线翻译,支持将选区内容翻译为英文或中文
  • 支持改进写作,支持改进或提高选区内容
  • 支持修正语法,支持修正选区内容的语法
  • 支持语句扩写,支持扩写选区内容
  • 支持语句缩写,支持缩写选区内容
  • 支持文档续写,支持通过文档上下文进行续写
  • 支持将AI生成的内容插入到文档
  • 支持将选区内容替换为AI生成的内容
  • 支持通过输入命令对选区内容进行提问或做其他你想要做的事,非常的灵活,这样就不局限于我们提供的几个快捷命令,你可以自定义命令

文档大纲功能

TODO

文档评论

首先,我们的文档评论包括以下功能:

  • 创建评论,创建之后评论引用内容会自动高亮
  • 一块内容支持创建多个评论
  • 评论编辑功能
  • 评论删除功能
  • 评论回复功能

对于文档的评论,这里我介绍下我的实现方式: 当选中一块内容生成评论时,我们会先判断这块内容是否已经有 threadId,如果没有,我们会在这块内容上生成一个 threadId,那后续在这块内容再创建评论使用的 threadId 还是之前生成的,不会重新创建,这样就可以实现选中内容快高亮所有评论了。 而且还有一个好处就是在删除这块内容的时候,我们就可以删除这块内容的所有评论了。

因此评论的类结构设计如下:

export interface IdeaComment {
  id: number;
  pid: number;
  docxId?: number;
  threadId: string;
  commentId: string;
  user?: User;
  quotedContent: string;
  content: string;
  replies: IdeaComment[];
  createAt: string;
  updatedAt?: string;
}

其中,pid 如果不为 null,则说明该评论为回复,threadId 和 commentId 都是前端使用 uuid 生成的,threadId 的值即为 data-thread-id。

另外,在实现的过程中还有一些点需要注意:

  • 一个评论下所有编辑取消时评论回复输入框才能显示,
  • 多个评论之间编辑和回复不互斥,单个评论编辑和回复互斥
  • 多个评论之间编辑和编辑不互斥,单个评论编辑和编辑不互斥,就同时可以对一个主评论下多个回复进行编辑

文档导出为 Word 和 PDF

文档导出为 word 和 pdf 是通过后端完成的,分别用到的工具为 poi 和 itext,下面是前端的处理流程

  1. 前端发起导出请求
const handleDownloadWord = async () => {
  const editor = window.editor;
  if (!editor || !menuId) {
    return;
  }

  const fileName = title || '未命名文档';
  const html = getHtml(editor, fileName);

  try {
    const data: any = await exportWord({ html: html, menuId: menuId });
    download(data, 'application/msword', `${fileName}.doc`);
  } catch (error) {
    toast.error('下载失败' + error);
  }
};

export function download(data: any, type: string, fileName: string) {
  // type: 'application/pdf;charset=utf-8' 表示 pdf,如果是 word则设置为msword, excel 为 excel
  const blob = new Blob([data], { type: type });
  // 创建链接并模拟点击来启动下载
  const link = document.createElement('a');
  // 根据解析后的 blob 对象创建 url 对象
  const downloadUrl = window.URL.createObjectURL(blob);
  // 下载链接
  link.href = downloadUrl;
  link.setAttribute('download', fileName); // 设置下载文件名
  document.body.appendChild(link);
  link.click();

  // 清理
  URL.revokeObjectURL(downloadUrl);
  link.remove();
}

export async function exportWord(ideaFile: IdeaFile) {
  return request.post('/export/word', ideaFile, {
    responseType: 'arraybuffer',
  });
}

注意,这里我使用的是 Axios,需要设置 responseType: 'arraybuffer'

  1. 后端处理导出 word 和 pdf

关于后端处理导出 Word 和 PDF 文档请查看 这里

文档版本管理

TODO

协同编辑

TODO