创建批注:
继续批注:
右侧批注列表:
1、功能与应用:
- 文本注释:recogito-js可以将注释功能添加到网页上,或者作为构建完全自定义注释应用程序的工具箱。
- 图像注释:除了文本注释外,它还支持为网页中的图像添加绘图、注释和标签功能。
- PDF注释:通过@recogito/recogito-react-pdf插件,它还能够支持在React中注释PDF文档。
2、官网及示例
官网:https://github.com/recogito/recogito-js/wiki/API-Reference
示例:https://recogito.github.io/recogito-js/
3、需求:
前面的文章提到过很多的tinyMCE、Vditor、cherryMarkdown、wangEditor等等markdown和富文本编辑器,在这些编辑器生成的文本内容的预览基础上要加上批注功能,用户选中文本后就要弹出批注弹窗,确认批注后右侧会相应展示出批注内容,同时在右侧进行批注的编辑、删除
4、安装与使用:
npm i @recogito/recogito-js@1.8.2
以下示例为文本注释功能:
import { Recogito } from "@recogito/recogito-js";
import "@recogito/recogito-js/dist/recogito.min.css";
// 初始化批注
const initRecogito = () => {
getAnnoList();
r = new Recogito({
content: document.querySelector(".artDetail"), // 批注区域
readOnly: false, // 是否只读
locale: "auto", // 可选择语言 auto会根据浏览器设置选择语言
});
r.setServerTime(Date.now()); // 设置批注日期
r.setAuthInfo({ // 这里设置每个批注携带的默认信息
id: useUserStore().userId,
displayName: useUserStore().nickName,
});
// 创建批注事件
r.on("createAnnotation", async function (annotation, overrideId) {
// 定义一个getInitAnnotate方法拿到创建的这个批注信息
let newAnno = getInitAnnotate("create", annotation);
// 因为批注插件不管有没有输入内容都会创建,这里要求了没有批注内容时不允许新建批注
if (!newAnno.annotationContent?.trim()?.length) {
getAnnoList(); // 刷新批注列表避免页面出现空批注内容
return proxy.$modal.msgWarning("请先输入批注内容");
}
// 将批注信息存入后端
submitAnnotation(newAnno)
.then(({ data }) => {
recogitoList.value.push(data); // 在页面右侧回展示批注信息
proxy.$modal.msgSuccess("新增成功!");
})
.catch((err) => {
getAnnoList();// 刷新批注列表避免页面出现空批注内容
});
});
// 在已有批注基础上补充批注
r.on("updateAnnotation", function (annotation, previous) {
let newAnno = getInitAnnotate("update", annotation);
if (!newAnno.annotationContent?.trim()?.length) {
getAnnoList();
return proxy.$modal.msgWarning("请先输入批注内容");
}
submitAnnotation(newAnno)
.then(({ data }) => {
// 补充批注时
let index = recogitoList.value.findIndex((item) => item.id === data.id);
recogitoList.value[index] = data;
proxy.$modal.msgSuccess("新增成功!");
})
.catch((err) => {
getAnnoList();
});
});
};
// 更改批注参数
const getInitAnnotate = (title, newAnno, pkId) => {
let data = {};
// 创建批注时
if (title === "create") {
data.annotationContent = newAnno.body[0]?.value;
data.textContent = newAnno.target.selector.find(
(item) => item.type === "TextQuoteSelector"
)?.exact;
// 修改批注时
} else if (title === "update") {
data.annotationContent = newAnno.body[newAnno.body?.length - 1]?.value;
} else {
// 通过外部input框编辑批注
let annoBody = newAnno.body.find((item) => item.pkId === pkId);
data.annotationContent = annoBody?.iptValue;
data.pkId = pkId;
}
let annoPosition = newAnno.target.selector.find(
(item) => item.type === "TextPositionSelector"
);
// 按照后端入参要求组装批注内容的结构
data.annotationId = newAnno.id;
data.createdBy = useUserStore().name;
data.endCoordinate = annoPosition.end;
data.startCoordinate = annoPosition.start;
data.knwlgId = artDetails.value.pkId;
data.knwlgNo = artDetails.value.knwlgNo;
return data;
};
// 获取批注列表并回显
const getAnnoList = () => {
getAnnotationList({ knwlgId: artDetails.value.pkId })
.then((res) => {
recogitoList.value = res.data; // 批注列表
setTimeout(() => {
r.clearAnnotations(); //清除所有批注
r.setAnnotations(recogitoList.value); // 设置已有批注内容
}, 500);
})
.catch(() => {});
};
// 根据批注id在点击右侧批注列表激活文本域内批注弹窗
const selectAnnotation = (id) => {
let domList = document.querySelectorAll(".r6o-annotation");
let activeTop =
Array.from(domList).find(
(item) => item.dataset.id === id && item.innerText?.length
)?.offsetTop - 5;
document.querySelector(".article-container").scrollTop = activeTop;
r.selectAnnotation(id);
};