Merge branch 'master' of https://git.nuttyreading.com/wangjinlei/tougao_web into Editorial-Board
This commit is contained in:
@@ -1149,9 +1149,9 @@ a {
|
|||||||
mso-border-top-alt: none !important;
|
mso-border-top-alt: none !important;
|
||||||
border-bottom: none !important;
|
border-bottom: none !important;
|
||||||
mso-border-bottom-alt: none !important;
|
mso-border-bottom-alt: none !important;
|
||||||
border: 1px dashed #dcdfe6 !important;
|
/* border: 1px dashed #dcdfe6 !important;
|
||||||
border-left: 1px dashed #dcdfe6 !important;
|
border-left: 1px dashed #dcdfe6 !important;
|
||||||
border-right: 1px dashed #dcdfe6 !important;
|
border-right: 1px dashed #dcdfe6 !important; */
|
||||||
word-break: keep-all !important;
|
word-break: keep-all !important;
|
||||||
/* text-align: justify !important; */
|
/* text-align: justify !important; */
|
||||||
}
|
}
|
||||||
@@ -1283,7 +1283,7 @@ a {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.word-container table tbody tr td {
|
.word-container table tbody tr td {
|
||||||
text-align: left !important;
|
text-align: center !important;
|
||||||
border-left: none !important;
|
border-left: none !important;
|
||||||
mso-border-left-alt: none !important;
|
mso-border-left-alt: none !important;
|
||||||
border-right: none !important;
|
border-right: none !important;
|
||||||
@@ -1292,9 +1292,9 @@ a {
|
|||||||
mso-border-top-alt: none !important;
|
mso-border-top-alt: none !important;
|
||||||
border-bottom: none !important;
|
border-bottom: none !important;
|
||||||
mso-border-bottom-alt: none !important;
|
mso-border-bottom-alt: none !important;
|
||||||
border: 1px dashed #dcdfe6 !important;
|
/* border: 1px dashed #dcdfe6 !important;
|
||||||
border-left: 1px dashed #dcdfe6 !important;
|
border-left: 1px dashed #dcdfe6 !important;
|
||||||
border-right: 1px dashed #dcdfe6 !important;
|
border-right: 1px dashed #dcdfe6 !important; */
|
||||||
word-break: keep-all !important;
|
word-break: keep-all !important;
|
||||||
white-space: pre-wrap !important;
|
white-space: pre-wrap !important;
|
||||||
/* text-align: justify !important; */
|
/* text-align: justify !important; */
|
||||||
|
|||||||
102
src/common/js/TableUtils.js
Normal file
102
src/common/js/TableUtils.js
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
/**
|
||||||
|
* 表格数据处理工具
|
||||||
|
*/
|
||||||
|
export const TableUtils = {
|
||||||
|
/**
|
||||||
|
* 判断是否为表头行
|
||||||
|
* @param {number} rowIndex
|
||||||
|
* @param {Array} table
|
||||||
|
*/
|
||||||
|
isHeaderRow(rowIndex, table) {
|
||||||
|
if (!table || table.length === 0) return false;
|
||||||
|
const head = table[0];
|
||||||
|
// 健壮性检查:确保第一行第一个单元格存在且有rowspan
|
||||||
|
const headerSpan = (head && head[0] && head[0].rowspan) ? head[0].rowspan : 1;
|
||||||
|
return rowIndex < headerSpan;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 拆分表头和表体
|
||||||
|
*/
|
||||||
|
splitTable(tableList) {
|
||||||
|
if (!Array.isArray(tableList) || tableList.length === 0) {
|
||||||
|
return { header: [], content: [] };
|
||||||
|
}
|
||||||
|
|
||||||
|
const header = [];
|
||||||
|
const content = [];
|
||||||
|
let cellIdCounter = 0;
|
||||||
|
|
||||||
|
tableList.forEach((row, rowIndex) => {
|
||||||
|
if (Array.isArray(row)) {
|
||||||
|
row.forEach((cell) => {
|
||||||
|
if (cell && typeof cell === 'object') {
|
||||||
|
cell.cellId = `cell-${cellIdCounter++}`;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.isHeaderRow(rowIndex, tableList)) {
|
||||||
|
header.push(row);
|
||||||
|
} else {
|
||||||
|
content.push(row);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return { header, content };
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理合并单元格后的逻辑行 ID(用于斑马纹等)
|
||||||
|
*/
|
||||||
|
addRowIdToData(content) {
|
||||||
|
if (!content || content.length === 0) return { rowData: [], rowIds: [] };
|
||||||
|
|
||||||
|
const data = JSON.parse(JSON.stringify(content));
|
||||||
|
const rowIdMap = {};
|
||||||
|
const usedRows = new Set();
|
||||||
|
let idCounter = 0;
|
||||||
|
|
||||||
|
// 1. 建立逻辑行映射
|
||||||
|
for (let i = 0; i < data.length; i++) {
|
||||||
|
if (usedRows.has(i)) continue;
|
||||||
|
|
||||||
|
const rowId = `row-${idCounter++}`;
|
||||||
|
rowIdMap[i] = rowId;
|
||||||
|
usedRows.add(i);
|
||||||
|
|
||||||
|
const row = data[i];
|
||||||
|
for (let j = 0; j < row.length; j++) {
|
||||||
|
const cell = row[j];
|
||||||
|
if (cell && cell.rowspan > 1) {
|
||||||
|
for (let k = 1; k < cell.rowspan; k++) {
|
||||||
|
const nextRowIndex = i + k;
|
||||||
|
if (nextRowIndex < data.length && !rowIdMap[nextRowIndex]) {
|
||||||
|
rowIdMap[nextRowIndex] = rowId;
|
||||||
|
usedRows.add(nextRowIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 注入 rowId 并提取唯一 ID 列表
|
||||||
|
const seenIds = [];
|
||||||
|
data.forEach((row, i) => {
|
||||||
|
const rowId = rowIdMap[i];
|
||||||
|
row.rowId = rowId; // 直接赋值给行对象
|
||||||
|
row.forEach(cell => {
|
||||||
|
if (cell) cell.rowId = rowId;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (rowId && !seenIds.includes(rowId)) {
|
||||||
|
seenIds.push(rowId);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 取奇数或偶数 ID 用于斑马纹(根据你的需求 index % 2 === 0)
|
||||||
|
const rowIds = seenIds.filter((_, index) => index % 2 === 0);
|
||||||
|
|
||||||
|
return { rowData: data, rowIds };
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -1307,16 +1307,19 @@ export default {
|
|||||||
},
|
},
|
||||||
handleImageAdd(type) {
|
handleImageAdd(type) {
|
||||||
this.picStyle = { note: '', picUrl: '', title: '' };
|
this.picStyle = { note: '', picUrl: '', title: '' };
|
||||||
|
this.picStyle1 = { note: '', picUrl: '', title: '' };
|
||||||
this.picStyle.visiTitle = 'Add Figure';
|
this.picStyle.visiTitle = 'Add Figure';
|
||||||
this.pictVisible = true;
|
this.pictVisible = true;
|
||||||
},
|
},
|
||||||
handleTableAdd(type) {
|
handleTableAdd(type) {
|
||||||
this.lineStyle = { note: '', table_data: '', html_data: '' };
|
this.lineStyle = { note: '', table_data: '', html_data: '' };
|
||||||
|
this.lineStyle1 = { note: '', table_data: '', html_data: '' };
|
||||||
this.lineStyle.visiTitle = 'Add Table';
|
this.lineStyle.visiTitle = 'Add Table';
|
||||||
this.threeVisible = true;
|
this.threeVisible = true;
|
||||||
},
|
},
|
||||||
addUploadWordTable(data) {
|
addUploadWordTable(data) {
|
||||||
this.lineStyle = { note: '', table: data.table_data, html_data: data.html_data };
|
this.lineStyle = { note: '', table: data.table_data, html_data: data.html_data };
|
||||||
|
this.lineStyle1 = { note: '', table: data.table_data, html_data: data.html_data };
|
||||||
|
|
||||||
this.lineStyle.visiTitle = 'Add Table';
|
this.lineStyle.visiTitle = 'Add Table';
|
||||||
this.threeVisible = true;
|
this.threeVisible = true;
|
||||||
@@ -1330,13 +1333,18 @@ export default {
|
|||||||
this.pictVisible = true;
|
this.pictVisible = true;
|
||||||
} else if (type == 'table') {
|
} else if (type == 'table') {
|
||||||
this.lineStyle = {};
|
this.lineStyle = {};
|
||||||
this.lineStyle = {
|
this.lineStyle1 = {};
|
||||||
|
// 1. 提取处理逻辑
|
||||||
|
const formattedData = {
|
||||||
...data,
|
...data,
|
||||||
table: JSON.parse(data.table_data),
|
table: JSON.parse(data.table_data),
|
||||||
html_data: data.html_data,
|
// 如果 data 中已经包含了 html_data, note, title,且不需要特殊处理,
|
||||||
note: data.note,
|
// 解构赋值 (...data) 其实已经把它们带进来了。
|
||||||
title: data.title
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 2. 统一赋值
|
||||||
|
this.lineStyle = formattedData;
|
||||||
|
this.lineStyle1 = { ...formattedData }; // 使用浅拷贝确保两个变量指向不同引用(如果需要独立修改)
|
||||||
this.lineStyle.visiTitle = 'Edit Table';
|
this.lineStyle.visiTitle = 'Edit Table';
|
||||||
this.threeVisible = true;
|
this.threeVisible = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -135,6 +135,9 @@
|
|||||||
<template slot="comment">
|
<template slot="comment">
|
||||||
<div style="" class="commentList annotations"></div>
|
<div style="" class="commentList annotations"></div>
|
||||||
</template>
|
</template>
|
||||||
|
<template slot="refrences">
|
||||||
|
<div style="" class="" main-id="References">222</div>
|
||||||
|
</template>
|
||||||
</common-word>
|
</common-word>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -603,6 +606,7 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
|
|
||||||
async copyArray(data) {
|
async copyArray(data) {
|
||||||
try {
|
try {
|
||||||
// 将数组内容转换为字符串,使用换行符分隔
|
// 将数组内容转换为字符串,使用换行符分隔
|
||||||
@@ -1524,7 +1528,7 @@ export default {
|
|||||||
for (let i = 0; i < this.Main_List.length; i++) {
|
for (let i = 0; i < this.Main_List.length; i++) {
|
||||||
this.Main_List[i].text = this.Main_List[i].content;
|
this.Main_List[i].text = this.Main_List[i].content;
|
||||||
this.Main_List[i].getnum = 0;
|
this.Main_List[i].getnum = 0;
|
||||||
// this.Main_List[i].checked = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// setTimeout(async () => {
|
// setTimeout(async () => {
|
||||||
|
|||||||
@@ -1,26 +1,20 @@
|
|||||||
<template>
|
<template>
|
||||||
|
<div class="ManuscirptList">
|
||||||
|
|
||||||
|
|
||||||
|
<div class="arrlist">
|
||||||
|
<ul class="catalogue-ul">
|
||||||
|
<li class="catalogue-li">
|
||||||
<div
|
<div
|
||||||
style=""
|
@click="goToListComment(item.am_id,'content')"
|
||||||
class="ManuscirptList"
|
|
||||||
>
|
|
||||||
|
|
||||||
<div
|
|
||||||
style=""
|
|
||||||
class="arrlist"
|
|
||||||
>
|
|
||||||
<ul style="width: 100%; height: auto">
|
|
||||||
|
|
||||||
|
|
||||||
<li >
|
|
||||||
<div style="">
|
|
||||||
<div @click="goToListComment(item.am_id,'content')"
|
|
||||||
v-for="(item, index) in catalogueList"
|
v-for="(item, index) in catalogueList"
|
||||||
|
:key="index"
|
||||||
:class="['catalogue-item', 'level-' + item.level]"
|
:class="['catalogue-item', 'level-' + item.level]"
|
||||||
style=""
|
|
||||||
>
|
>
|
||||||
|
<div class="title-content-wrapper">
|
||||||
<div class="title-content" v-html="item.content"></div>
|
<div class="title-content" v-html="item.content"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
@@ -86,7 +80,7 @@ export default {
|
|||||||
|
|
||||||
|
|
||||||
this.catalogueList = this.content.filter(item => {
|
this.catalogueList = this.content.filter(item => {
|
||||||
return item.is_h1 == 1 || item.is_h2 == 1 || item.is_h3 == 1;
|
return item.is_h1 == 1 || item.is_h2 == 1 ;
|
||||||
}).map(item => {
|
}).map(item => {
|
||||||
// 增加一个 level 字段进行标记
|
// 增加一个 level 字段进行标记
|
||||||
let level = 1;
|
let level = 1;
|
||||||
@@ -98,8 +92,8 @@ this.catalogueList = this.content.filter(item => {
|
|||||||
};
|
};
|
||||||
})
|
})
|
||||||
this.catalogueList=[...this.catalogueList,{
|
this.catalogueList=[...this.catalogueList,{
|
||||||
am_id:'reference',
|
am_id:'References',
|
||||||
content:'<b><i>References</i></b>',
|
content:'References',
|
||||||
|
|
||||||
level:1,
|
level:1,
|
||||||
}]
|
}]
|
||||||
@@ -478,57 +472,146 @@ console.log(this.catalogueList,'catalogueList')
|
|||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.ManuscirptList {
|
.ManuscirptList {
|
||||||
padding-top: 20px;
|
height: 100%;
|
||||||
|
padding: 0;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
background: #f5f5f5 !important;
|
background-color: #f5f5f5 !important; /* Word 导航栏通常是白色的 */
|
||||||
|
border-right: 1px solid #e1e1e1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
.catalogue-item{
|
|
||||||
width: 90%;
|
/* 模拟 Word 导航标题 */
|
||||||
white-space: nowrap; /* 强制不换行 */
|
.word-navigation-header {
|
||||||
overflow: hidden; /* 隐藏超出部分 */
|
padding: 12px 16px 0 16px;
|
||||||
text-overflow: ellipsis; /* 超出部分显示... */
|
|
||||||
box-sizing: border-box;
|
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: rgb(51, 51, 51);
|
color: #333;
|
||||||
|
font-family: "Segoe UI", "Microsoft YaHei", sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
.word-tabs {
|
||||||
|
display: flex;
|
||||||
|
margin-top: 10px;
|
||||||
|
border-bottom: 1px solid #e1e1e1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.word-tabs span {
|
||||||
|
padding: 4px 12px;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #666;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
padding: 4px 0px;
|
position: relative;
|
||||||
margin-left: 16px;
|
}
|
||||||
font-family: "Charis SIL";
|
|
||||||
word-wrap: break-word;
|
.word-tabs span.active {
|
||||||
|
color: #2b579a; /* Word 经典蓝色 */
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.word-tabs span.active::after {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
bottom: -1px;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
height: 2px;
|
||||||
|
background-color: #2b579a;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 列表容器 */
|
||||||
|
.arrlist {
|
||||||
|
flex: 1;
|
||||||
|
overflow-y: auto;
|
||||||
|
padding-top: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.catalogue-ul {
|
||||||
|
width: 100%;
|
||||||
|
list-style: none;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 基础条目样式 - 模拟 Word 悬浮效果 */
|
||||||
|
.catalogue-item {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
padding: 6px 16px;
|
||||||
|
cursor: pointer;
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
box-sizing: border-box;
|
||||||
|
transition: background-color 0.1s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.catalogue-item:hover {
|
||||||
|
background-color: #eff3f9; /* Word 淡淡的选中蓝 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Word 样式的左侧小箭头 */
|
||||||
|
.word-icon-arrow {
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
border-left: 5px solid #666;
|
||||||
|
border-top: 4px solid transparent;
|
||||||
|
border-bottom: 4px solid transparent;
|
||||||
|
margin-right: 8px;
|
||||||
|
margin-top: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title-content-wrapper {
|
||||||
|
flex: 1;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
.title-content,
|
|
||||||
.title-content span,
|
/* 重点:Word 常用排版字体 */
|
||||||
.title-content b {
|
.title-content {
|
||||||
display: inline; /* 强制内部标签不换行 */
|
font-weight: bold !important;
|
||||||
font-weight: inherit; /* 继承父级的粗细设置,或者根据需要自定 */
|
font-style: normal !important;
|
||||||
font-size: inherit;
|
font-size: 15px;
|
||||||
}
|
line-height: 1.3;
|
||||||
.catalogue-item:hover {
|
white-space: nowrap;
|
||||||
background-color: #e6f7ff;
|
overflow: hidden;
|
||||||
color: #1890ff;
|
text-overflow: ellipsis;
|
||||||
|
/* Times New Roman 增加学术感 */
|
||||||
|
font-family: "Times New Roman", "Charis SIL", "serif";
|
||||||
|
color: #333;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 一级标题:加粗,无缩进 */
|
/* 保持 v-html 内部样式 */
|
||||||
|
::v-deep .title-content b { font-weight: bold; }
|
||||||
|
::v-deep .title-content i { font-style: italic; }
|
||||||
|
|
||||||
|
/* --- Word 风格的层级缩进 --- */
|
||||||
|
|
||||||
|
/* 1级标题 */
|
||||||
.level-1 {
|
.level-1 {
|
||||||
font-weight: bold;
|
padding-left: 16px;
|
||||||
|
/* font-style: italic; */
|
||||||
padding-left: 0;
|
|
||||||
/* margin-top: 8px; */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 二级标题:标准字体,缩进 20px */
|
/* 2级标题 */
|
||||||
.level-2 {
|
.level-2 {
|
||||||
|
padding-left: 36px;
|
||||||
padding-left: 20px;
|
}
|
||||||
color: #555;
|
.level-2 .title-content {
|
||||||
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 三级标题:稍细字体,缩进 40px */
|
/* 3级标题 */
|
||||||
.level-3 {
|
.level-3 {
|
||||||
|
padding-left: 56px;
|
||||||
|
}
|
||||||
|
.level-3 .title-content {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
padding-left: 40px;
|
/* 隐藏滚动条 */
|
||||||
color: #888;
|
.arrlist::-webkit-scrollbar {
|
||||||
font-style: italic; /* 模仿 Word 的一些三级样式 */
|
width: 5px;
|
||||||
|
}
|
||||||
|
.arrlist::-webkit-scrollbar-thumb {
|
||||||
|
background: #cdcdcd;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -9,7 +9,10 @@ import htmlDocx from 'html-docx-js/dist/html-docx.js';
|
|||||||
import { Document, Packer, PageOrientation, Paragraph, TextRun } from 'docx'; // 引入 docx.js
|
import { Document, Packer, PageOrientation, Paragraph, TextRun } from 'docx'; // 引入 docx.js
|
||||||
import html2canvas from 'html2canvas';
|
import html2canvas from 'html2canvas';
|
||||||
|
|
||||||
const tableStyle = ` b span{
|
const tableStyle = `*{
|
||||||
|
font-family: 'Charis SIL';
|
||||||
|
}
|
||||||
|
b span{
|
||||||
font-weight: bold !important;
|
font-weight: bold !important;
|
||||||
}
|
}
|
||||||
i span{
|
i span{
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user