自定义评论面板
# 开发自定义评论面板时需要注意以下问题:
# 1、如何插入自定义面板?
websdk 给目标元素设置了 id 为 left_menu,用户可根据 id 找到目标元素,将自定义面板插入到页面中,详情请见下方示例 1 和 2。
# 2、自定义面板样式如何处理?
面板样式由用户自定义。
# 3、自定义面板能使用哪些组件?
自定义面板对组件没有硬性要求,websdk 适用于常见的前端框架,如 vue、angular、react 等,用户可使用惯用的组件库,根据使用场景选择合适的组件。 该样例是基于原生 js 和 html 开发的。
# 4、自定义面板如何绘制批注?
该问题涉及三个前端 SDK 接口:绘制批注、完成绘制的回调及删除批注。 (1)ZwSetDrawCommentBubble:触发绘制批注。 (2)ZwEvtDrawCommentBubble:批注绘制完成后的回调,此处会接收到批注的信息。以圆形批注为例,绘制结束后返回圆的位置信息、批注颜色、唯一标识符 id 等信息。 (3)ZwSetDeleteBubbles:删除绘制的批注,例如在输入框中删除圆形批注后,需要调用该方法同步清除画布中绘制的圆形批注。 其他批注相关的接口,例如批注的定位、气泡高亮、取消气泡高亮、中断气泡的绘制等接口,请查看**“前端接口对象及方法”**。
# 5、评论列表?
评论列表需用户自行开发,该样例仅演示了如何自定义评论面板,不包含评论列表。
# 该示例主要演示如何自定义评论面板。
1、自定义评论面板:编写 html,根据应用场景将需要的批注工具和评论字段添加上去,请查看示例代码。
<!-- 如右侧区域所示,在左上方增加一个自定义评论面板的按钮,用来打开或关闭“自定义评论面板”。 -->
<button
id="comment_btn"
style="width: 110px;position: fixed;top: 9px;right: 0;"
>
自定义评论面板
</button>
<div id="custom_Comment" class="custom-area">
<!-- 自定义评论面板的内容 -->
<!-- websdk包中index.html包含了自定义评论面板的样例代码 -->
……
</div>
2、插入自定义面板:根据 id 找到目标元素,将 html 片段插入到目标元素前。
<!-- 给“自定义评论面板按钮”绑定点击事件,点击后能展开或隐藏自定义面板 -->
let comment_btn = document.getElementById("comment_btn");
comment_btn.addEventListener('click', function () {
<!-- 判断自定义面板是否需要隐藏 -->
let custom_Comment = document.getElementById("custom_Comment");
if (custom_Comment && custom_Comment.style.display && custom_Comment.style.display !== 'none') {
custom_Comment.style.display = 'none';
return;
}
<!-- ************插入自定义面板开始************ -->
<!-- main_c是右侧整个区域的元素id,left_menu是左侧面板的id -->
let main_c = document.getElementById("main_c");
let left_menu = document.getElementById("left_menu");
<!-- 获取自定义评论面板的Dom -->
let newNode = custom_Comment.cloneNode(custom_Comment);
custom_Comment.remove();
newNode.style.display = 'block';
newNode.style.height = left_menu.style.height;
<!-- 将自定义评论面板插入到main_c区域中left_menu的前面 -->
main_c.insertBefore(newNode, left_menu);
<!-- ************插入自定义面板结束************ -->
<!-- 其他业务代码开始 -->
<!-- websdk包中index.html包含了自定义评论面板的样例代码 -->
……
<!-- 其他业务代码结束 -->
}, 0);
});
3、样例简介 websdk 包中 index.html 的样例代码包含了批注工具的使用、颜色的交互选择、@功能、快捷回复等基本功能,供用户参考。 点击“提交”按钮,将评论批注信息提取出来,用户根据实际场景保存即可。点击取消按钮将清空输入的评论内容。
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<base href="/pages/" />
<title>Html Demo</title>
</head>
<style>
body {
margin: 0;
overflow: hidden;
}
.custom-area {
display: none;
width: 330px;
background-color: #535353;
border-right: 1px solid #424242;
border-bottom: 1px solid #424242;
color: #fff;
}
.panel-title {
background-color: #424242;
color: #ddd;
height: 25px;
line-height: 25px;
font-weight: bold;
}
.custom-comment-tool {
height: 35px;
border-bottom: 1px solid #424242;
margin-bottom: 10px;
}
.custom-comment-tool svg {
cursor: pointer;
font-size: 20px;
margin-right: 5px;
}
.component {
height: 24px;
line-height: 24px;
}
.align-center {
display: flex;
align-items: center;
}
label {
width: 80px;
}
.width-220 {
width: 220px;
}
.comment-input-box {
height: 85px;
width: 222px;
}
.fast-reply {
display: flex;
justify-content: end;
align-items: center;
}
.fast-reply div {
cursor: pointer;
font-size: 12px;
margin-right: 5px;
}
.quick-reply {
display: none;
position: absolute;
margin-top: 100px;
border: 1px solid #535353;
background-color: #535353;
height: auto;
/* padding: 2px 5px 2px 5px; */
}
.quick-reply option:hover {
background-color: #424242;
}
.comment-input::-webkit-scrollbar {
width: 10px;
height: 10px;
}
.comment-input::-webkit-scrollbar-thumb {
border-radius: 10px;
background-color: #000000;
}
.comment-input::-webkit-scrollbar-track {
background-color: #363636;
}
.comment-input::-webkit-scrollbar-corner {
width: 10px;
height: 10px;
background-color: #535353;
}
.comment-input-box,
.comment-input,
textarea {
border-radius: 5px;
}
.comment-input {
height: 60px;
overflow-y: auto;
}
.comment-input-box,
.comment-input,
textarea,
select {
outline: none;
border: 1px solid #424242;
background-color: #424242;
}
.comment-input-box:hover,
.comment-input-box:focus,
textarea:hover,
textarea:focus,
select:hover,
select:focus {
border-color: #40a9ff;
}
.flex-end {
display: flex;
justify-content: flex-end;
}
button {
margin-right: 10px;
width: 60px;
height: 32px;
cursor: pointer;
border-radius: 3px;
}
.default {
border: 1px solid #535353;
background: #535353;
}
.default:hover {
border: 1px solid rgba(66, 66, 66, 0.2);
background: rgba(66, 66, 66, 0.2);
}
.primary {
border: 1px solid #424242;
background: #424242;
}
.primary:hover {
border: 1px solid #1890ff;
background: #1890ff;
}
.margin-left-15 {
margin-left: 15px;
}
.margin-bottom-15 {
margin-bottom: 15px;
}
.palette-box:hover .palette {
display: block;
}
.select-color {
width: 18px;
height: 18px;
border-radius: 9px;
margin-top: -3px;
cursor: pointer;
background-color: red;
}
.palette {
position: absolute;
margin-left: -125px;
padding-top: 2px;
display: none;
}
.rectangle {
height: 24px;
width: 24px;
cursor: pointer;
}
.rectangle:hover {
border: 2px solid #fff;
}
.bg-red {
background-color: red;
}
.bg-yellow {
background-color: yellow;
}
.bg-green {
background-color: green;
}
.bg-cyan {
background-color: cyan;
}
.bg-blue {
background-color: blue;
}
.bg-color1 {
background-color: rgba(255, 0, 255, 1);
}
.member-list-box {
display: none;
margin-left: 64px;
}
.member-list {
border: 1px solid #999;
background: #424242;
margin: 0px 2px 15px 15px;
}
.userName {
margin: 5px 10px 5px 10px;
}
.userName-box:hover {
background-color: #535353;
cursor: pointer;
}
</style>
<script
type="text/javascript"
src="../assets/ZwCloud2DSDK/ZwCloud2D.js"
></script>
<body id="wholeFrame">
<div id="container" style="width: 100vw; height: 100vh"></div>
<button
id="comment_btn"
style="width: 110px; position: fixed; top: 9px; right: 0"
>
自定义评论面板
</button>
<div id="custom_Comment" class="custom-area">
<div class="panel-title">
<span class="margin-left-15">评论</span>
</div>
<div class="align-center custom-comment-tool">
<span class="margin-left-15" style="width: 80px">批注工具:</span>
<svg
id="circle_comment"
class="icon custom-comment-panel"
aria-hidden="true"
>
<use xlink:href="#icon-zw-comment-circle"></use>
</svg>
<svg
id="juxing_comment"
class="icon custom-comment-panel"
aria-hidden="true"
>
<use xlink:href="#icon-zw-rectangle"></use>
</svg>
<svg
id="yunxian_comment"
class="icon custom-comment-panel"
aria-hidden="true"
>
<use xlink:href="#icon-zw-revcloud"></use>
</svg>
<svg
id="zidingyi_comment"
class="icon custom-comment-panel"
aria-hidden="true"
>
<use xlink:href="#icon-zw-custom-shape"></use>
</svg>
<svg
id="jiantou_comment"
class="icon custom-comment-panel"
aria-hidden="true"
>
<use xlink:href="#icon-zw-comment-arrow"></use>
</svg>
<svg
id="tuding_comment"
class="icon custom-comment-panel"
aria-hidden="true"
>
<use xlink:href="#icon-zw-thumbtack"></use>
</svg>
<div class="palette-box">
<div class="select-color" id="selectedColor"></div>
<div id="palette" class="palette">
<div class="flex-end">
<div class="rectangle bg-red"></div>
<div class="rectangle bg-yellow"></div>
<div class="rectangle bg-green"></div>
<div class="rectangle bg-cyan"></div>
<div class="rectangle bg-blue"></div>
<div class="rectangle bg-color1"></div>
</div>
</div>
</div>
</div>
<div style="padding: 5px 10px 0 15px">
<div style="display: flex" class="margin-bottom-15">
<label>评论内容</label>
<div class="comment-input-box">
<div
contenteditable="true"
id="commentInput"
class="comment-input width-220"
></div>
<div class="fast-reply">
<div id="triggerQuickReply" style="color: #40a9ff">快捷回复</div>
<div id="quickReply" class="component quick-reply">
<option class="select-quick-reply">快捷回复01快捷回复01</option>
<option class="select-quick-reply">快捷回复02</option>
<option class="select-quick-reply">
快捷回复03快捷回复03快捷回复03
</option>
</div>
</div>
</div>
</div>
<div>
<div class="member-list-box" id="memberList">
<div class="member-list">
<div class="userName-box">
<div class="userName">张三</div>
</div>
<div class="userName-box">
<div class="userName">李四</div>
</div>
<div class="userName-box">
<div class="userName">王五</div>
</div>
</div>
</div>
</div>
<div class="align-center margin-bottom-15">
<label>问题等级</label>
<select id="select" class="component width-220" required>
<option value="轻微">轻微</option>
<option value=" 严重">严重</option>
<option value=" 严重">严重</option>
</select>
</div>
<div style="display: flex; margin-bottom: 10px">
<label>备注</label>
<div></div>
<textarea
rows="5"
id="textarea"
required
class="width-220"
style="resize: none"
></textarea>
</div>
<div class="flex-end">
<button class="default" id="cancel">取消</button>
<button class="primary" id="submit">提交</button>
</div>
</div>
</div>
<script type="module">
// 初始化配置
const initializeViewer = async () => {
try {
// 设置云服务连接配置
window.ZwCloud2D.ZwDataProcessor.ZwSetConnectUrl(
process.env.HTML_APP_ZW_URL
);
// 设置认证令牌
window.ZwCloud2D.ZwDataProcessor.ZwSetToken(
process.env.HTML_APP_ZW_TOKEN
);
// 初始化编辑器
await window.ZwCloud2D.ZwEditor.ZwInit(
document.getElementById("container")
);
} catch (error) {
console.error("初始化失败:", error);
// 可以添加错误处理逻辑
}
};
initializeViewer().then(() => {
// 从路由参数获取文档ID
const params = new URLSearchParams(location.search);
const docId = params.get("docId");
if (docId) {
// 配置要加载的文档
window.ZwCloud2D.ZwDataProcessor.ZwSetLoadDwg(docId);
// 加载文档
window.ZwCloud2D.ZwDataProcessor.ZwLoad();
}
// 初始化面板
initPanel();
});
/*************自定义评论面板 样例开始*************/
// 批注颜色选项
let paletteColors = [
{
str: "rgba(255,0,0,1)", //red
num: 0xffff0000,
},
{
str: "rgba(255,255,0,1)", //yellow
num: 0xffffff00,
},
{
str: "rgba(0,128,0,1)", //green
num: 0xff008000,
},
{
str: "rgba(0,255,255,1)", //cyan
num: 0xff00ffff,
},
{
str: "rgba(0,0,255,1)", //blue
num: 0xff0000ff,
},
{
str: "rgba(255,0,255,1)",
num: 0xffff00ff,
},
];
memberList = [
{
memberId: "1",
memberName: "张三",
},
{
memberId: "2",
memberName: "李四",
},
{
memberId: "3",
memberName: "王五",
},
{
memberId: "4",
memberName: "小李",
},
];
// 记录@符号的位置
let focusNode = null;
let focusOffset = 0;
let clickAtMemberEl = undefined;
let selectedColor = { str: "red", num: 0xffff0000 };
let allInputMarks = {};
function initPanel() {
let comment_btn = document.getElementById("comment_btn");
comment_btn.addEventListener("click", function () {
let custom_Comment = document.getElementById("custom_Comment");
if (
custom_Comment &&
custom_Comment.style.display &&
custom_Comment.style.display !== "none"
) {
custom_Comment.style.display = "none";
return;
}
let main_c = document.getElementById("main_c");
custom_Comment.style.display = "block";
main_c.insertBefore(custom_Comment, null);
setTimeout(() => {
let inputEl = document.getElementById("commentInput");
// 使用后退格键删除的时候需要删除增加的富文本
inputEl.addEventListener("keydown", (e) => {
if (e.code === "Digit2" && e.shiftKey) {
const selection = window.getSelection();
if (selection !== null) {
// 记录@符号的位置
focusNode = selection.focusNode;
focusOffset = selection.focusOffset;
setDisplay("memberList");
}
} else if (e.code === "Backspace") {
setDisplay("quickReply", false);
setDisplay("memberList", false);
deleteRichText();
} else if (e.code === "Delete") {
setDisplay("quickReply", false);
setDisplay("memberList", false);
deleteRichText();
} else if (e.ctrlKey && (e.keyCode === 67 || e.keyCode === 88)) {
// 禁止复制和剪切
e.preventDefault();
} else if (
e.code === "ArrowLeft" ||
e.code === "ArrowRight" ||
e.code === "ArrowDown" ||
e.code === "ArrowUp"
) {
if (target) {
const range = document.createRange();
range.selectNodeContents(target);
const selection = window.getSelection();
if (selection !== null) {
if (selection.rangeCount > 0) {
selection.removeAllRanges();
}
selection.addRange(range);
selection.selectAllChildren(target);
}
}
}
});
inputEl.addEventListener("click", (e) => {
setDisplay("quickReply", false);
setDisplay("memberList", false);
let target = e.target;
if (
target.className === "atFont" ||
target.className === "bubble" ||
target.nodeName === "svg" ||
target.nodeName === "use"
) {
const selection = window.getSelection();
if (selection && selection.rangeCount <= 0) {
return;
}
const range = selection.getRangeAt(0);
range.selectNode(target);
selection && selection.selectAllChildren(target);
clickAtMemberEl = target;
} else {
clickAtMemberEl = undefined;
}
});
let commandEles = document.getElementsByClassName(
"custom-comment-panel"
);
for (let index = 0; index < commandEles.length; index++) {
const element = commandEles[index];
element &&
element.addEventListener("click", (e) => {
let id = element.id;
triggerCommand(id);
});
}
let selectColorEles = document.getElementsByClassName("rectangle");
for (let index = 0; index < selectColorEles.length; index++) {
const element = selectColorEles[index];
element &&
element.addEventListener("click", (e) => {
selectColor(index);
});
}
let cancelBtn = document.getElementById("cancel");
cancelBtn &&
cancelBtn.addEventListener("click", (e) => {
cancel();
});
let submitBtn = document.getElementById("submit");
submitBtn &&
submitBtn.addEventListener("click", (e) => {
submit();
});
let triggerQuickReplyBtn =
document.getElementById("triggerQuickReply");
triggerQuickReplyBtn &&
triggerQuickReplyBtn.addEventListener("click", (e) => {
setDisplay("quickReply");
});
let selectQuickReplyEles =
document.getElementsByClassName("select-quick-reply");
for (let index = 0; index < selectQuickReplyEles.length; index++) {
const element = selectQuickReplyEles[index];
element &&
element.addEventListener("click", (e) => {
switch (index) {
case 0:
selectQuickReply("快捷回复01快捷回复01");
break;
case 1:
selectQuickReply("快捷回复02");
break;
case 2:
selectQuickReply("快捷回复03快捷回复03快捷回复03");
break;
default:
break;
}
});
}
let userNameEles = document.getElementsByClassName("userName");
for (let index = 0; index < userNameEles.length; index++) {
const element = userNameEles[index];
element &&
element.addEventListener("click", (e) => {
selectMember(index);
});
}
custom_Comment = document.getElementById("custom_Comment");
custom_Comment &&
custom_Comment.addEventListener("click", (e) => {
closeAllDivs();
});
}, 0);
});
}
// 点击批注工具,触发绘制
function triggerCommand(id) {
let svgEl = document.getElementById(id);
if (svgEl) {
svgEl.style.color = selectedColor.str;
}
let command = "circle_v";
let svgIcon = "#icon-yuanxin";
switch (id) {
case "circle_comment":
command = "circle_v";
svgIcon = "#icon-zw-comment-circle";
break;
case "juxing_comment":
command = "rectangle_v";
svgIcon = "#icon-zw-rectangle";
break;
case "yunxian_comment":
command = "revcloud_v;2";
svgIcon = "#icon-zw-revcloud";
break;
case "zidingyi_comment":
command = "pline_v";
svgIcon = "#icon-zw-custom-shape";
break;
case "jiantou_comment":
command = "leader_v";
svgIcon = "#icon-zw-comment-arrow";
break;
case "tuding_comment":
command = "bubble_v";
svgIcon = "#icon-zw-thumbtack";
break;
default:
break;
}
ZwCloud2D.ZwDataManager.ZwSetDrawCommentBubble(command, selectedColor);
// 批注结束后,将数据回填到输入框中:例如圆形批注结束后,将圆形图标回填到输入框中
ZwCloud2D.ZwMessageCallback.ZwEvtDrawCommentBubble = (data) => {
// 绘制结束后清除批注工具的颜色
svgEl.style.color = "";
console.log("ZwEvtDrawCommentBubble: ", data);
if (data.data && data.data.id) {
allInputMarks[data.data.id] = data.data;
allInputMarks[data.data.id].type = data.type;
let el = document.getElementById("commentInput");
let newHtml =
'<svg class="icon bubble" contenteditable="false" id="' +
data.data.id +
'" style="color:' +
data.data.color +
';" aria-hidden="true" style="margin-right: 5px;cursor:pointer;"><use xlink:href="' +
svgIcon +
'"></use></svg>';
el.innerHTML += " " + newHtml + " ";
}
};
}
// 选择颜色
function selectColor(index) {
selectedColor = paletteColors[index];
let target = document.getElementById("selectedColor");
if (target) {
target.style.backgroundColor = selectedColor.str;
}
}
function closeAllDivs() {
setDisplay("quickReply", false);
setDisplay("memberList", false);
}
// 设置面板显示或隐藏
function setDisplay(id, show) {
let target = document.getElementById(id);
if (
(target && target.style.display && target.style.display !== "none") ||
show === false
) {
target.style.display = "none";
} else {
target.style.display = "block";
}
if (id === "quickReply") {
setDisplay("memberList", false);
}
stopPropagaton();
}
// 快捷回复
function selectQuickReply(params) {
let commentInput = document.getElementById("commentInput");
commentInput.innerHTML += " " + params + " ";
let target = document.getElementById("quickReply");
target.style.display = "none";
stopPropagaton();
}
function stopPropagaton(params) {
let e = window.event;
if (e.stopPropagaton) {
e.stopPropagation();
} else {
e.cancelBubble = true;
}
}
// 选择@的用户
function selectMember(index) {
let obj = memberList[index];
const selection = window.getSelection();
if (selection !== null) {
let inputEl = document.getElementById("commentInput");
if (inputEl === null || (selection && selection.rangeCount <= 0))
return;
const range = selection.getRangeAt(0);
// 选中输入的@符号
let offset = focusOffset + 1;
range.setStart(focusNode, offset - 1);
range.setEnd(focusNode, offset);
// 删除输入的@符号
range.deleteContents();
// 创建元素节点
const element = document.createElement("span");
element.style.color = "orange";
element.className = "atFont";
element.setAttribute("id", obj.memberId);
element.setAttribute("contenteditable", "false");
element.innerText = `@${obj.memberName}`;
// 创建一个空元素
const emptyEl = document.createElement("span");
emptyEl.innerHTML = " ";
let frag = document.createDocumentFragment();
frag.appendChild(element);
let lastNode;
if (emptyEl && emptyEl.firstChild) {
lastNode = frag.appendChild(emptyEl.firstChild);
}
range.insertNode(frag);
lastNode && selection.extend(lastNode, 1);
selection.collapseToEnd();
// 聚焦输入框
inputEl && inputEl.focus();
// 关闭选项
setDisplay("memberList", false);
}
}
/**
* 选中后删除
*/
function clickToDelete() {
let atInput = document.getElementById("commentInput");
if (clickAtMemberEl) {
atInput && atInput.removeChild(clickAtMemberEl);
let id = clickAtMemberEl.id;
if (id && id.length === 36) {
ZwCloud2D.ZwDataManager.ZwSetDeleteBubbles([id]);
delete allInputMarks[id];
}
clickAtMemberEl = undefined;
return true;
}
return false;
}
// 删除富文本
function deleteRichText() {
let isMobile = false;
let atInput = document.getElementById("commentInput");
const selection = window.getSelection();
if (!clickToDelete()) {
if (atInput && selection !== null && selection.rangeCount > 0) {
const range = selection.getRangeAt(0);
let removeNode = null;
let startContainer = range.startContainer;
if (!startContainer.parentElement) {
return;
}
if (startContainer.parentElement.className !== "atFont") {
//移动端光标移动发生在删除之前
if (isMobile) {
removeNode = startContainer.nextElementSibling;
} else {
//获取当前锚点元素
//富文本前后会带有 借此判断是否是需要执行手动删除
let anchorNode = selection.anchorNode;
if (anchorNode && selection.anchorOffset === 1) {
//是否为文字node
if (anchorNode.nodeType === 3) {
if (anchorNode.textContent) {
//判断是否包含
let text = anchorNode.textContent;
if (text.charCodeAt(0) === 160) {
removeNode = startContainer.previousSibling;
}
}
}
}
}
if (removeNode) {
//删除元素node
let id = removeNode.id
? removeNode.id
: removeNode.firstChild
? removeNode.firstChild.id
: undefined;
if (id && id.length === 36) {
// this.mGs.deleteBubble([id]);
ZwCloud2D.ZwDataManager.ZwSetDeleteBubbles([id]);
if (removeNode) {
//删除多余的
if (
removeNode.nextSibling &&
removeNode.nextSibling.textContent.charCodeAt(0) === 160
) {
let newText = removeNode.nextSibling.nodeValue.slice(1);
removeNode.nextSibling.nodeValue = newText;
}
// 同时删除@和name
selection.selectAllChildren(removeNode);
atInput.removeChild(removeNode);
}
}
}
} else if (startContainer.parentElement.className === "atFont") {
removeNode = startContainer.parentElement;
if (removeNode) {
// 同时删除@和name
selection.selectAllChildren(removeNode);
atInput.removeChild(removeNode);
}
}
}
}
}
function checkSpecialChar(src) {
let notAllowedChars = /[\\/:*"<>#~$%^&*(){}|]/g;
notAllowedChars.lastIndex = 0;
if (src && notAllowedChars.test(src)) {
return true;
}
return false;
}
function getMarkById(id) {
let res = null;
for (const key in allInputMarks) {
if (Object.prototype.hasOwnProperty.call(allInputMarks, key)) {
const mark = allInputMarks[key];
if (mark.id === id) {
res = JSON.parse(JSON.stringify(mark));
break;
}
}
}
if (res) {
switch (res.type) {
case 0: //BubbleType.Pin:
res.pt = [res.pt.mX, res.pt.mY, res.pt.mZ];
break;
case 1: //BubbleType.Circle:
res.center = [res.center.mX, res.center.mY, res.center.mZ];
res.endPt = [res.endPt.mX, res.endPt.mY, res.endPt.mZ];
break;
case 2: //BubbleType.Rectangle:
res.points = [
res.points[0].mX,
res.points[0].mY,
res.points[0].mZ,
res.points[1].mX,
res.points[1].mY,
res.points[1].mZ,
];
break;
case 3: //BubbleType.Polyline:
let arr = [];
res.points.forEach((element) => {
arr.push(element.mX, element.mY, element.mZ);
});
res.points = arr;
break;
case 4: //BubbleType.Leader:
let pts = [];
res.points.forEach((element) => {
pts.push(element.mX, element.mY, element.mZ);
});
res.points = pts;
let polygonPts = [];
res.polygonPts.forEach((element) => {
polygonPts.push(element.mX, element.mY, element.mZ);
});
res.polygonPts = polygonPts;
break;
case 6: //BubbleType.Image:
res.originPoint = [res.origin.mX, res.origin.mY, res.origin.mZ];
res.uvector = [res.uVec.mX, res.uVec.mY, res.uVec.mZ];
res.vvector = [res.vVec.mX, res.vVec.mY, res.vVec.mZ];
break;
case 5: //BubbleType.Revcloud:
res.originPt = [
res.originPt.mX,
res.originPt.mY,
res.originPt.mZ,
];
res.diagonalPt = [
res.diagonalPt.mX,
res.diagonalPt.mY,
res.diagonalPt.mZ,
];
break;
default:
break;
}
}
return res;
}
// 提交评论
function submit() {
let input = document.getElementById("commentInput");
if (input === null) {
return false;
}
let inputContent = {};
let str = input.innerHTML;
let matchRegSpan = /<span.*?<\/span> /g;
let matchBracketsFront = /<span/g;
let matchBracketsBack = /<\/span>/g;
if (str) {
let spanArr = str.match(matchRegSpan);
// 指定开头和结尾,获取中间部分 /(?<=指定开头").*?(?=指定结尾)/g
let matchId = /id="(?:[^"\\]|\\.)*"/g;
let id = "";
let ids = [];
spanArr &&
spanArr.forEach((span) => {
id = span.match(matchId);
if (id && id[0]) {
ids.push(id[0].slice(4, id[0].length - 1));
}
});
if (ids.length > 0) {
inputContent.atUserIds = "";
inputContent.atUserIds += ids.join(",");
inputContent.withAt = "YES";
}
let marks = [];
let strArr = str.split(" ");
let template = "";
let realContent = "";
let userIds = [];
let hasSpecialChar = false;
for (let index = 0; index < strArr.length; index++) {
const substr = strArr[index];
if (substr) {
let tempArr = [];
if (substr.indexOf('<div class="bubble"') > -1) {
tempArr = substr.split('<div class="bubble"');
} else if (substr.indexOf('<svg class="icon') > -1) {
tempArr = substr.split('<svg class="icon');
}
if (tempArr.length === 2) {
template += tempArr[0];
}
let bracketsFront = substr
.split(matchBracketsFront)
.filter((item) => {
return item !== "";
});
if (bracketsFront.length > 0) {
for (
let innerindex = 0;
innerindex < bracketsFront.length;
innerindex++
) {
const element = bracketsFront[innerindex];
let ids = element.match(matchId);
if (ids && ids[0]) {
let id = ids[0].slice(4, ids[0].length - 1);
if (id && id.length === 36) {
// 气泡多了一层<div>
if (element.indexOf("</svg></div>") > -1) {
tempArr = element.split("</svg></div>");
} else {
// 其他类型的气泡
tempArr = element.split("</svg>");
}
if (checkSpecialChar(tempArr[1])) {
hasSpecialChar = true;
break;
}
template += "#";
let res = getMarkById(id);
res && marks.push(res);
if (tempArr.length === 2) {
template += tempArr[1];
}
} else {
tempArr = element.split("</span>");
if (checkSpecialChar(tempArr[1])) {
hasSpecialChar = true;
break;
}
// @字符串
template += "$";
userIds.push(id);
if (tempArr.length === 2) {
template += tempArr[1];
}
}
} else {
if (checkSpecialChar(element)) {
hasSpecialChar = true;
break;
}
template += element;
realContent += element;
}
}
if (hasSpecialChar) {
break;
}
}
}
}
if (hasSpecialChar) {
console.log("不能包含特殊字符");
return false;
}
if (marks.length > 0) {
inputContent.withMark = "YES";
inputContent.mark = JSON.stringify(marks);
}
inputContent.content = template;
inputContent.realContent = realContent;
if (inputContent.content.length > 1000) {
console.log("字符长度不超过1000");
return false;
}
console.log("inputContent: ", inputContent);
let commentList = {
code: 0,
data: {
rows: [inputContent],
},
};
// 测试ZwSetCommentData接口
// ZwCloud2D.ZwDataManager.ZwSetCommentData({ commentList: commentList });
}
let select = document.getElementById("select");
console.log("select:", select.value);
let textarea = document.getElementById("textarea");
console.log("textarea:", textarea.value);
}
// 取消评论
function cancel() {
let input = document.getElementById("commentInput");
if (input === null) {
return false;
}
input.innerHTML = "";
for (const key in allInputMarks) {
if (Object.hasOwnProperty.call(allInputMarks, key)) {
const element = allInputMarks[key];
if (element.id && element.id.length === 36) {
ZwCloud2D.ZwDataManager.ZwSetDeleteBubbles([element.id]);
}
}
}
allInputMarks = {};
}
/*************自定义评论面板 样例结束*************/
</script>
</body>
</html>