1 Commits

Author SHA1 Message Date
a68a2be8ad 提交 2025-01-24 14:37:13 +08:00
3 changed files with 194 additions and 123 deletions

View File

@@ -1152,7 +1152,51 @@ export default {
initEditorButton(vueInstance, ed) {
ed.ui.registry.addButton('copyButton', {
text: 'Copy',
onAction: function () {
var edSelection = ed.selection;
const selectedNode = edSelection.getNode(); // 获取选中的节点
let outerDiv = selectedNode;
while (outerDiv && outerDiv.tagName !== 'DIV') {
outerDiv = outerDiv.parentNode;
}
// 如果找到的 div 节点存在
if (outerDiv) {
const dataId = outerDiv.getAttribute('main-id');
console.log('dataId at line 1258:', dataId)
window.copiedContent=dataId
// alert('内容已复制',dataId);
// vueInstance.$emit('onAddRow', dataId);
}
// alert('内容已复制');
}
});
// 自定义粘贴按钮
ed.ui.registry.addButton('pasteButton', {
text: 'Paste',
onAction: function () { var edSelection = ed.selection;
const selectedNode = edSelection.getNode(); // 获取选中的节点
let outerDiv = selectedNode;
while (outerDiv && outerDiv.tagName !== 'DIV') {
outerDiv = outerDiv.parentNode;
}
// 如果找到的 div 节点存在
if (outerDiv) {
const dataId = outerDiv.getAttribute('main-id');
if(window.copiedContent&&window.copiedContent!='dataId'){
vueInstance.$emit('onSort', dataId,window.copiedContent);
}else{
alert('没有复制的内容');
}
// alert('内容已复制',dataId);
// vueInstance.$emit('onAddRow', dataId);
}
// 将存储的复制内容插入到当前光标位置
}
});
ed.ui.registry.addMenuButton('customDropdown', {
text: 'Set Title', // 下拉框标题
fetch: function (callback) {
@@ -1531,37 +1575,29 @@ export default {
},
inTinymceButtonClass() {
setTimeout(function () {
// 查找该按钮并添加 className
const commentaddbutton = document.querySelector('.tox-toolbar .tox-toolbar__group .tox-tbtn[data-mce-name="commentadd"]');
if (commentaddbutton) {
commentaddbutton.classList.add('tinymce-custom-button-commentadd');
}
const addrowbutton = document.querySelector('.tox-toolbar .tox-toolbar__group .tox-tbtn[data-mce-name="addrow"]');
if (addrowbutton) {
addrowbutton.classList.add('tinymce-custom-button-addrow');
}
const deletebutton = document.querySelector('.tox-toolbar .tox-toolbar__group .tox-tbtn[data-mce-name="delete"]');
if (deletebutton) {
deletebutton.classList.add('tinymce-custom-button-delete');
}
const editbutton = document.querySelector('.tox-toolbar .tox-toolbar__group .tox-tbtn[data-mce-name="edit"]');
if (editbutton) {
editbutton.classList.add('tinymce-custom-button-edit');
}
const savebutton = document.querySelector('.tox-toolbar .tox-toolbar__group .tox-tbtn[data-mce-name="save"]');
if (savebutton) {
savebutton.classList.add('tinymce-custom-button-save');
}
const button = document.querySelector('.tox-toolbar .tox-toolbar__group .tox-tbtn[data-mce-name="customblue"]');
if (button) {
button.classList.add('tinymce-custom-button-blue');
}
const removebutton = document.querySelector('.tox-toolbar .tox-toolbar__group .tox-tbtn[data-mce-name="removeblue"]');
if (removebutton) {
removebutton.classList.add('tinymce-custom-button-removeblue');
}
// 使用 querySelectorAll 获取所有符合条件的按钮
const buttons = [
{ selector: '.tox-tbtn[data-mce-name="commentadd"]', className: 'tinymce-custom-button-commentadd' },
{ selector: '.tox-tbtn[data-mce-name="addrow"]', className: 'tinymce-custom-button-addrow' },
{ selector: '.tox-tbtn[data-mce-name="delete"]', className: 'tinymce-custom-button-delete' },
{ selector: '.tox-tbtn[data-mce-name="edit"]', className: 'tinymce-custom-button-edit' },
{ selector: '.tox-tbtn[data-mce-name="save"]', className: 'tinymce-custom-button-save' },
{ selector: '.tox-tbtn[data-mce-name="customblue"]', className: 'tinymce-custom-button-blue' },
{ selector: '.tox-tbtn[data-mce-name="removeblue"]', className: 'tinymce-custom-button-removeblue' }
];
// 遍历每个按钮并为每个按钮添加类
buttons.forEach(item => {
const buttonElements = document.querySelectorAll(item.selector);
buttonElements.forEach(button => {
if (!button.classList.contains(item.className)) { // 防止重复添加
button.classList.add(item.className);
}
});
});
}, 100); // 延迟执行,确保按钮渲染完成
}
// 通用递归方法

View File

@@ -86,7 +86,7 @@
</div> -->
<common-word
:key="Main_List"
:key="new Date().getTime()"
v-if="htmlContent"
ref="commonWord"
:value="htmlContent"
@@ -94,6 +94,7 @@
:comments="comments"
:wordStyle="wordStyle"
@onDrop="onDrop"
@onSort="onSort"
@saveContent="saveContent"
@editComment="editComment"
@loaded="loadedWord"
@@ -179,6 +180,7 @@
<el-form ref="editMes" :model="lineStyle" label-width="115px">
<el-form-item label="Table Title :">
<common-content
:id="`editor-${new Date().getTime()}-${lineStyle.am_id}-${lineStyle.amt_id}-title`"
:isAutomaticUpdate="true"
:value="lineStyle.title"
@getContent="getContent"
@@ -194,7 +196,6 @@
<font style="color: #f56c6c; margin-right: 5px">*</font>
Table :
</span>
<common-table
@getContent="getContent"
v-if="threeVisible"
@@ -205,6 +206,7 @@
</el-form-item>
<el-form-item label="Bottom Title :">
<common-content
:id="`editor-${new Date().getTime()}-${lineStyle.am_id}-${lineStyle.amt_id}-note`"
:isAutomaticUpdate="true"
:value="lineStyle.note"
@getContent="getContent"
@@ -231,8 +233,8 @@
>
<el-form ref="editMes" :model="commentForm" label-width="115px">
<el-form-item label="Select Content:" v-if="commentForm.content">
<p style="background: #eef0f4; line-height: 20px; padding: 10px; box-sizing: border-box">
{{ commentForm.content }}
<p style="background: #eef0f4; line-height: 20px; padding: 10px; box-sizing: border-box" v-html="commentForm.content">
</p>
</el-form-item>
<el-form-item label="Word">
@@ -628,6 +630,21 @@ export default {
}
});
},
async onSort(mainId,sortId) {
console.log('mainId at line 633:', mainId)
console.log('sortId at line 633:', sortId)
var that = this;
// await that.$api
// .post(that.urlList.sort, {
// article_id: this.articleId
// })
// .then(async (res) => {
// if (res.code == 0) {
// this.ManuscirptContent = res.data.list;
// // this.$refs.commonWordHtmlTypeSetting.getCommentList();
// }
// });
},
changeComment() {
this.isShowComment = !this.isShowComment;
},
@@ -884,8 +901,8 @@ export default {
});
},
async onAddRow(mainId) {
console.log('data at line 886:', mainId)
console.log('data at line 886:', mainId);
await this.$api
.post(this.urlList.addRow, {
am_id: mainId,

View File

@@ -60,38 +60,46 @@
</font>
</div>
<div
id="drop-target"
@dragover="handleDragOver"
@dragenter="handleDragEnter"
@dragleave="handleDragLeave"
@drop="handleDrop"
@click="initializeEditor(item.am_id, 'table', item)"
class="thumbnailTableBox wordTableHtml table_Box pMain myeditabledivTable drop-target"
v-else-if="item.type == 2"
:main-state="item.state"
:remark="item.checks.length > 0 ? 1 : 0"
:contenteditable="!readonly && !isPreview"
:data-id="item.amt_id"
:type="item.type"
:id="'editor' + item.am_id"
:main-id="item.am_id"
>
<font class="font" :style="`width: ${item.width ? `${item.width}px` : '100%'}`">
<span v-html="item.table.title ? item.table.title : ''"></span>
</font>
id="drop-target"
@dragover="handleDragOver"
@dragenter="handleDragEnter"
@dragleave="handleDragLeave"
@drop="handleDrop"
@click="initializeEditor(item.am_id, 'table', item)"
class="thumbnailTableBox wordTableHtml table_Box pMain myeditabledivTable drop-target"
v-else-if="item.type == 2"
:main-state="item.state"
:remark="item.checks.length > 0 ? 1 : 0"
:contenteditable="!readonly && !isPreview"
:data-id="item.amt_id"
:type="item.type"
:id="'editor' + item.am_id"
:main-id="item.am_id"
>
<!-- 标题部分 -->
<font class="font" :style="`width: ${item.width ? `${item.width}px` : '100%'}`">
<span v-html="highlightText(item.table.title || '', item.checks)"></span>
</font>
<table border="1" style="width: auto; border-collapse: collapse; text-align: center">
<tr v-for="(row, i) in JSON.parse(item.table.table_data)">
<td :colspan="`${cell.colspan || 1}`" :rowspan="`${cell.rowspan || 1}`" v-for="(cell, i1) in row">
<span v-html="cell.text"></span>
</td>
</tr>
</table>
<!-- 表格部分 -->
<table border="1" style="width: auto; border-collapse: collapse; text-align: center">
<tr v-for="(row, i) in JSON.parse(item.table.table_data)" :key="i">
<td
v-for="(cell, i1) in row"
:key="i1"
:colspan="`${cell.colspan || 1}`"
:rowspan="`${cell.rowspan || 1}`">
<span v-html="highlightText(cell.text || '', item.checks)"></span>
</td>
</tr>
</table>
<!-- 备注部分 -->
<font class="font" :style="`width: ${item.width ? `${item.width}px` : '100%'}`">
<span v-html="highlightText(item.table.note || '', item.checks)"></span>
</font>
</div>
<font class="font" :style="`width: ${item.width ? `${item.width}px` : '100%'}`">
<span v-html="item.table.note ? item.table.note : ''"></span
></font>
</div>
<div
id="drop-target"
@@ -130,6 +138,7 @@
class="commentList"
>
<li
v-for="(item, index) in commentList"
class="comment-item annotation"
:data-target="`main-${item.am_id}`"
@@ -155,6 +164,7 @@
box-sizing: border-box;
border-bottom: 1px solid rgba(243, 213, 213);
"
:style="commont.estate == 1? 'background:#13bc200f;' : ''"
v-for="(commont, commentIndex) in item.comment"
@click="highlightLeftComment(commont.amc_id, item.am_id)"
>
@@ -714,10 +724,10 @@ export default {
image_advtab: false, // 禁用图片高级选项卡(防止自动调整大小)
valid_elements: '*[*]',
plugins: 'forecolor code paste table image resize searchreplace dragdrop',
plugins: 'forecolor code paste table image resize dragdrop',
menubar: false,
toolbar: _this.isEditComment ? ['commentAdd |delete| level1 level2 level3|addRow|Edit'] : ['delete|addRow| Edit'],
toolbar: _this.isEditComment ? ['commentAdd |delete| level1 level2 level3|addRow|copyButton pasteButton|Edit'] : ['delete|addRow|copyButton pasteButton| Edit'],
end_container_on_empty_block: true,
content_css: 'default ',
content_style: `${tableStyle + this.wordStyle}
@@ -773,7 +783,7 @@ export default {
image_advtab: false, // 禁用图片高级选项卡(防止自动调整大小)
valid_elements: '*[*]',
plugins: 'forecolor code paste table image resize searchreplace',
plugins: 'forecolor code paste table image resize ',
content_style: `${tableStyle + this.wordStyle}
@@ -858,7 +868,7 @@ export default {
table_resize_bars: true,
valid_elements: '*[*]',
image_advtab: false, // 禁用图片高级选项卡(防止自动调整大小)
plugins: 'forecolor code paste table image resize searchreplace',
plugins: 'forecolor code paste table image resize ',
content_style: `${tableStyle + this.wordStyle}
`,
@@ -988,13 +998,18 @@ export default {
const formattedDate = `${year}-${month}-${day} ${hours}:${minutes}`;
return formattedDate;
},
goToListComment(data) {
console.log('data at line 993:', data)
this.goToComment(data.am_id)
},
divOnScroll() {
if (!this.isPreview) {
// const scrollTop = scrollDiv.scrollTop; // 获取垂直滚动距离
this.scrollPosition = this.$refs.scrollDiv.scrollTop;
localStorage.setItem('scrollPosition', this.scrollPosition);
console.log('this.scrollPosition at line 980:', this.scrollPosition);
// console.log('this.scrollPosition at line 980:', this.scrollPosition);
// 检查每个编辑器是否在可视区域内
for (const key in this.editors) {
const editorElement = document.getElementById(key);
@@ -1044,62 +1059,65 @@ export default {
return emptyContentIndexes;
},
escapeRegExp(string) {
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
},
highlightText(text, annotations) {
if (!this.isPreview) {
let tempText = text;
if (!this.isPreview) {
let tempText = text;
// 1. 使用占位符替代批注内容
const placeholders = [];
annotations.forEach((annotation, index) => {
if (annotation.content == '') {
return tempText;
}
const placeholder = `{{remark_placeholder_${index}}}`; // 占位符
const regExp = new RegExp(`(${annotation.content})`, 'gi'); // 全局匹配批注内容
// 如果批注内容存在,替换成占位符
if (tempText.includes(annotation.content)) {
tempText = tempText.replace(regExp, placeholder);
placeholders.push({ placeholder, annotation, index });
}
});
// 2. 为占位符添加高亮
placeholders.forEach(({ placeholder, annotation, index }) => {
const regExp = new RegExp(placeholder, 'gi');
tempText = tempText.replace(regExp, (match) => {
// 随机生成浅色透明背景颜色
const randomColor = this.getRandomLightColor();
let highlightedText = `
<span class="remarkbg"
ref="remark_${annotation.amc_id}"
style="background-color: ${randomColor} !important;
position: relative !important;
border-left: 2px solid #cd5454 !important;
border-right: 2px solid #cd5454 !important;"
comment-Id="${annotation.amc_id}"
>
${annotation.content}
<span class="positionRemarkIndex"
style="position: absolute; top: -14px; right: -10px; font-size: 0.8em; color: red;">
${index + 1}
</span>
</span>
`;
return highlightedText;
});
});
// 3. 返回处理后的文本
// 1. 使用占位符替代批注内容
const placeholders = [];
annotations.forEach((annotation, index) => {
if (annotation.content == '') {
return tempText;
} else {
return text;
}
},
const escapedContent = this.escapeRegExp(annotation.content); // 转义正则表达式中的特殊字符
const placeholder = `{{remark_placeholder_${index}}}`; // 占位符
const regExp = new RegExp(`(${escapedContent})`, 'gi'); // 全局匹配批注内容
// 如果批注内容存在,替换成占位符
if (tempText.includes(annotation.content)) {
tempText = tempText.replace(regExp, placeholder);
placeholders.push({ placeholder, annotation, index });
}
});
// 2. 为占位符添加高亮
placeholders.forEach(({ placeholder, annotation, index }) => {
const regExp = new RegExp(placeholder, 'gi');
tempText = tempText.replace(regExp, (match) => {
const randomColor = this.getRandomLightColor();
return `
<span
class="remarkbg"
style="background-color: ${randomColor};
position: relative;
display: inline-block;
white-space: nowrap;
overflow-wrap: anywhere;
border-left: 2px solid #cd5454;
border-right: 2px solid #cd5454;"
comment-Id="${annotation.amc_id}"
>
${annotation.content}
<span class="positionRemarkIndex"
style="position: absolute; top: -14px; right: -10px; font-size: 0.8em; color: red;">
${index + 1}
</span>
</span>
`;
});
});
// 3. 返回处理后的文本
return tempText;
} else {
return text;
}
},
getCommentsData() {
if (!this.isPreview) {