专刊
This commit is contained in:
@@ -19,8 +19,8 @@ const service = axios.create({
|
||||
// baseURL: 'https://submission.tmrjournals.com/', //正式 记得切换
|
||||
// baseURL: 'http://www.tougao.com/', //测试本地 记得切换
|
||||
// baseURL: 'http://192.168.110.110/tougao/public/index.php/',
|
||||
baseURL: '/api', //本地
|
||||
// baseURL: '/', //正式
|
||||
// baseURL: '/api', //本地
|
||||
baseURL: '/', //正式
|
||||
|
||||
});
|
||||
|
||||
|
||||
@@ -1180,86 +1180,24 @@ export default {
|
||||
callback([]);
|
||||
}
|
||||
},
|
||||
handleFileUpload(event, callback) {
|
||||
async handleFileUpload(event, callback) {
|
||||
const file = event.target.files[0];
|
||||
if (!file || file.type !== 'application/vnd.openxmlformats-officedocument.wordprocessingml.document') {
|
||||
alert('Please upload a valid Word file !');
|
||||
return;
|
||||
}
|
||||
const reader = new FileReader();
|
||||
reader.onload = (e) => {
|
||||
const arrayBuffer = e.target.result;
|
||||
const zip = new JSZip();
|
||||
zip.loadAsync(arrayBuffer).then(async (zip) => {
|
||||
const relsXml = await zip.files['word/_rels/document.xml.rels'].async('string');
|
||||
const docXml = await zip.files['word/document.xml'].async('string');
|
||||
const parser = new DOMParser();
|
||||
const relDoc = parser.parseFromString(relsXml, "text/xml");
|
||||
const docDom = parser.parseFromString(docXml, "text/xml");
|
||||
const rels = {};
|
||||
Array.from(relDoc.getElementsByTagName('Relationship')).forEach((rel) => {
|
||||
const id = rel.getAttribute('Id');
|
||||
const target = rel.getAttribute('Target');
|
||||
rels[id] = target;
|
||||
});
|
||||
const imageInfoMap = {};
|
||||
const blips = docDom.getElementsByTagName('a:blip');
|
||||
Array.from(blips).forEach((blip) => {
|
||||
const embedId = blip.getAttribute('r:embed');
|
||||
const extent = findExtentElement(blip);
|
||||
if (embedId && extent) {
|
||||
const cx = extent.getAttribute('cx');
|
||||
const cy = extent.getAttribute('cy');
|
||||
if (cx && cy) {
|
||||
const width = emuToPixels(cx);
|
||||
const height = emuToPixels(cy);
|
||||
imageInfoMap[embedId] = { width, height };
|
||||
}
|
||||
}
|
||||
});
|
||||
mammoth.convertToHtml({ arrayBuffer }, {
|
||||
convertImage: mammoth.images.inline(async function (image) {
|
||||
console.log('image at line 163:', image)
|
||||
const contentType = image.contentType.toLowerCase();
|
||||
const allowedTypes = ['image/jpeg', 'image/jpg', 'image/png'];
|
||||
if (!allowedTypes.includes(contentType)) {
|
||||
return { src: '' };
|
||||
}
|
||||
const embedId = image.relationshipId || image.refId || '';
|
||||
const imageBuffer = await image.read("base64");
|
||||
const base64Src = `data:${contentType};base64,${imageBuffer}`;
|
||||
let width = '', height = '';
|
||||
if (embedId && imageInfoMap[embedId]) {
|
||||
width = imageInfoMap[embedId].width;
|
||||
height = imageInfoMap[embedId].height;
|
||||
}
|
||||
return {
|
||||
src: base64Src,
|
||||
alt: '',
|
||||
width,
|
||||
height,
|
||||
refId: embedId,
|
||||
'content-type': contentType
|
||||
};
|
||||
})
|
||||
}).then((result) => {
|
||||
let html = result.value;
|
||||
// 提取合法表格
|
||||
const tableContent = html.match(/<table[\s\S]*?<\/table>/g);
|
||||
const validTables = tableContent
|
||||
? tableContent.filter(table => /<td[\s\S]*?>/.test(table))
|
||||
: [];
|
||||
|
||||
callback(validTables);
|
||||
}).catch(err => {
|
||||
console.error('mammoth 转换失败:', err);
|
||||
});
|
||||
}).catch(err => {
|
||||
console.error("Zip 读取失败:", err);
|
||||
});
|
||||
};
|
||||
|
||||
reader.readAsArrayBuffer(file);
|
||||
try {
|
||||
// 走 OMML→LaTeX 解析,表格单元格内公式转为 <wmath data-latex>
|
||||
const html = await parseWordDocumentWithMath(file, { forTableExtract: true });
|
||||
const tableContent = String(html || '').match(/<table[\s\S]*?<\/table>/gi);
|
||||
const validTables = tableContent
|
||||
? tableContent.filter((table) => /<t[dh][\s>]/i.test(table))
|
||||
: [];
|
||||
callback(validTables);
|
||||
} catch (err) {
|
||||
console.error('Word 表格导入失败:', err);
|
||||
callback([]);
|
||||
}
|
||||
},
|
||||
// async extractWordTablesToArrays(file, callback) {
|
||||
|
||||
|
||||
@@ -2,16 +2,16 @@
|
||||
//记得切换
|
||||
|
||||
// //正式
|
||||
// const mediaUrl = '/public/';
|
||||
// const tmrjournals = 'https://master.tmrjournals.com/public/';
|
||||
// const baseUrl = '/';
|
||||
const mediaUrl = '/public/';
|
||||
const tmrjournals = 'https://master.tmrjournals.com/public/';
|
||||
const baseUrl = '/';
|
||||
|
||||
//正式环境
|
||||
|
||||
const mediaUrl = 'https://submission.tmrjournals.com/public/';
|
||||
// const mediaUrl = 'http://192.168.110.131/tougao/public/';
|
||||
const tmrjournals = 'http://192.168.110.131/journal/public/';
|
||||
const baseUrl = '/api'
|
||||
// const mediaUrl = 'https://submission.tmrjournals.com/public/';
|
||||
// // const mediaUrl = 'http://192.168.110.131/tougao/public/';
|
||||
// const tmrjournals = 'http://192.168.110.131/journal/public/';
|
||||
// const baseUrl = '/api'
|
||||
|
||||
//测试环境
|
||||
|
||||
|
||||
@@ -1529,6 +1529,9 @@ const en = {
|
||||
tableBatchPosition: 'Batch Position',
|
||||
tableBatchPositionEmpty: 'No unpositioned tables',
|
||||
tableBatchPositionDone: 'Batch done: {ok} positioned, {skip} not found, {fail} failed',
|
||||
tableDeleteAll: 'Delete all',
|
||||
tableDeleteAllConfirm: 'Delete all tables?',
|
||||
tableDeleteAllResult: 'Deleted {ok}, failed {fail}',
|
||||
removetable: 'Are you sure you want to delete this table?',
|
||||
reContent: 'Are you sure you want to restore this content?',
|
||||
uploadImageInfo: 'Figures can only upload files in JPG, JPEG, and PNG formats!',
|
||||
|
||||
@@ -1515,6 +1515,9 @@ const zh = {
|
||||
tableBatchPosition: '批量定位',
|
||||
tableBatchPositionEmpty: '没有待定位的表格',
|
||||
tableBatchPositionDone: '批量定位完成:成功 {ok},未匹配 {skip},失败 {fail}',
|
||||
tableDeleteAll: '批量删除',
|
||||
tableDeleteAllConfirm: '确定删除全部表格吗?',
|
||||
tableDeleteAllResult: '已删除 {ok} 个,失败 {fail} 个',
|
||||
removetable: '确定要删除这个表格吗?',
|
||||
reContent: '确定要恢复这条内容吗?',
|
||||
uploadImageInfo: 'Figures 只能上传 JPG、JPEG 和 PNG 格式的文件',
|
||||
|
||||
@@ -71,6 +71,7 @@
|
||||
@edit="handleFigureAndTableEdit"
|
||||
@delete="handleFigureAndTableDelete"
|
||||
@deleteAllImages="handleDeleteAllFigures"
|
||||
@deleteAllTables="handleDeleteAllTables"
|
||||
@autoPositionImage="handleAutoPositionImage"
|
||||
@autoPositionTable="handleAutoPositionTable"
|
||||
@batchAutoPositionImages="handleBatchAutoPositionImages"
|
||||
@@ -495,7 +496,7 @@ import bus from '@/components/common/bus';
|
||||
import { del, isShallow } from 'vue';
|
||||
import Tiff from 'tiff.js';
|
||||
import { mediaUrl } from '@/common/js/commonJS.js'; // 引入通用逻辑
|
||||
import { LATEX_DATA_HTML_DATA, MATH_FORMULA_TABLE_TITLE } from '@/utils/mathFormulaModule';
|
||||
import { LATEX_DATA_HTML_DATA, MATH_FORMULA_TABLE_TITLE, isMathFormulaTableRecord } from '@/utils/mathFormulaModule';
|
||||
import Tinymce from '@/components/page/components/Tinymce';
|
||||
import bottomTinymce from '@/components/page/components/Tinymce';
|
||||
import catalogue from '@/components/page/components/table/catalogue.vue';
|
||||
@@ -1655,6 +1656,9 @@ export default {
|
||||
that.uploadWordTables = result;
|
||||
loading.close();
|
||||
that.tablesHtmlVisible = true;
|
||||
that.$nextTick(() => {
|
||||
if (window.renderMathJax) window.renderMathJax();
|
||||
});
|
||||
})
|
||||
.catch((error) => {
|
||||
loading.close();
|
||||
@@ -1966,6 +1970,82 @@ export default {
|
||||
this.$refs.commonWordHtmlTypeSetting.refresh('img');
|
||||
}
|
||||
},
|
||||
async handleDeleteAllTables(list) {
|
||||
const tables = Array.isArray(list) ? list.filter((item) => item && item.amt_id) : [];
|
||||
if (!tables.length) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
await this.$confirm(this.$t('commonTable.tableDeleteAllConfirm'), 'Prompt', {
|
||||
confirmButtonText: 'Submit',
|
||||
cancelButtonText: 'Cancel',
|
||||
type: 'warning'
|
||||
});
|
||||
} catch (e) {
|
||||
return;
|
||||
}
|
||||
const loading = this.$loading({
|
||||
lock: true,
|
||||
text: 'Loading...',
|
||||
spinner: 'el-icon-loading',
|
||||
background: 'rgba(0, 0, 0, 0.7)'
|
||||
});
|
||||
let ok = 0;
|
||||
let fail = 0;
|
||||
for (let i = 0; i < tables.length; i++) {
|
||||
const item = tables[i];
|
||||
const replaceType = isMathFormulaTableRecord(item) ? 'math' : 'table';
|
||||
try {
|
||||
// 已定位到正文:先解绑 api/Preaccept/removeTable,再删除
|
||||
const positionedRows = (this.Main_List || []).filter(
|
||||
(row) => row && row.am_id && String(row.amt_id) === String(item.amt_id)
|
||||
);
|
||||
let unboundOk = true;
|
||||
for (let j = 0; j < positionedRows.length; j++) {
|
||||
const row = positionedRows[j];
|
||||
const unbindRes = await this.$api.post(this.urlList.removePositioningTable, {
|
||||
am_id: row.am_id
|
||||
});
|
||||
if (unbindRes && unbindRes.code == 0) {
|
||||
const idx = this.Main_List.findIndex((x) => x && x.am_id == row.am_id);
|
||||
if (idx !== -1) {
|
||||
this.Main_List.splice(idx, 1);
|
||||
}
|
||||
if (this.$refs.commonWordHtmlTypeSetting) {
|
||||
this.$refs.commonWordHtmlTypeSetting.refresh('removeTable', { amt_id: item.amt_id });
|
||||
}
|
||||
} else {
|
||||
unboundOk = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!unboundOk) {
|
||||
fail += 1;
|
||||
continue;
|
||||
}
|
||||
const res = await this.$api.post(this.urlList.deleteTable, {
|
||||
amt_id: item.amt_id,
|
||||
article_id: this.articleId
|
||||
});
|
||||
if (res && res.status == 1) {
|
||||
ok += 1;
|
||||
if (this.$refs.commonWordHtmlTypeSetting) {
|
||||
this.$refs.commonWordHtmlTypeSetting.replacement(replaceType, item.amt_id);
|
||||
}
|
||||
} else {
|
||||
fail += 1;
|
||||
}
|
||||
} catch (err) {
|
||||
fail += 1;
|
||||
}
|
||||
}
|
||||
loading.close();
|
||||
this.$message.success(this.$t('commonTable.tableDeleteAllResult', { ok: ok, fail: fail }));
|
||||
if (this.$refs.commonWordHtmlTypeSetting) {
|
||||
this.$refs.commonWordHtmlTypeSetting.refresh('table');
|
||||
}
|
||||
this.$forceUpdate();
|
||||
},
|
||||
handleFigureAndTableEdit(data, type) {
|
||||
if (type == 'img') {
|
||||
var extension = data.url.split('.').pop().toLowerCase();
|
||||
|
||||
@@ -81,6 +81,7 @@
|
||||
@edit="handleImageEdit"
|
||||
@delete="handleFigureAndTableDelete"
|
||||
@deleteAllImages="handleDeleteAllFigures"
|
||||
@deleteAllTables="handleDeleteAllTables"
|
||||
@autoPositionImage="handleAutoPositionImage"
|
||||
@autoPositionTable="handleAutoPositionTable"
|
||||
@batchAutoPositionImages="handleBatchAutoPositionImages"
|
||||
@@ -470,7 +471,7 @@ import bus from '@/components/common/bus';
|
||||
import { del, isShallow } from 'vue';
|
||||
import Tiff from 'tiff.js';
|
||||
import { mediaUrl } from '@/common/js/commonJS.js'; // 引入通用逻辑
|
||||
import { LATEX_DATA_HTML_DATA, MATH_FORMULA_TABLE_TITLE } from '@/utils/mathFormulaModule';
|
||||
import { LATEX_DATA_HTML_DATA, MATH_FORMULA_TABLE_TITLE, isMathFormulaTableRecord } from '@/utils/mathFormulaModule';
|
||||
import Tinymce from '@/components/page/components/Tinymce';
|
||||
import bottomTinymce from '@/components/page/components/Tinymce';
|
||||
import catalogue from '@/components/page/components/OnlineProofreading/catalogue.vue';
|
||||
@@ -1374,6 +1375,9 @@ export default {
|
||||
that.uploadWordTables = result;
|
||||
loading.close();
|
||||
that.tablesHtmlVisible = true;
|
||||
that.$nextTick(() => {
|
||||
if (window.renderMathJax) window.renderMathJax();
|
||||
});
|
||||
})
|
||||
.catch((error) => {
|
||||
loading.close();
|
||||
@@ -1604,6 +1608,82 @@ export default {
|
||||
this.$refs.commonWordHtmlTypeSetting.refresh('img');
|
||||
}
|
||||
},
|
||||
async handleDeleteAllTables(list) {
|
||||
const tables = Array.isArray(list) ? list.filter((item) => item && item.amt_id) : [];
|
||||
if (!tables.length) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
await this.$confirm(this.$t('commonTable.tableDeleteAllConfirm'), 'Prompt', {
|
||||
confirmButtonText: 'Submit',
|
||||
cancelButtonText: 'Cancel',
|
||||
type: 'warning'
|
||||
});
|
||||
} catch (e) {
|
||||
return;
|
||||
}
|
||||
const loading = this.$loading({
|
||||
lock: true,
|
||||
text: 'Loading...',
|
||||
spinner: 'el-icon-loading',
|
||||
background: 'rgba(0, 0, 0, 0.7)'
|
||||
});
|
||||
let ok = 0;
|
||||
let fail = 0;
|
||||
for (let i = 0; i < tables.length; i++) {
|
||||
const item = tables[i];
|
||||
const replaceType = isMathFormulaTableRecord(item) ? 'math' : 'table';
|
||||
try {
|
||||
// 已定位到正文:先解绑 api/Preaccept/removeTable,再删除
|
||||
const positionedRows = (this.Main_List || []).filter(
|
||||
(row) => row && row.am_id && String(row.amt_id) === String(item.amt_id)
|
||||
);
|
||||
let unboundOk = true;
|
||||
for (let j = 0; j < positionedRows.length; j++) {
|
||||
const row = positionedRows[j];
|
||||
const unbindRes = await this.$api.post(this.urlList.removePositioningTable, {
|
||||
am_id: row.am_id
|
||||
});
|
||||
if (unbindRes && unbindRes.code == 0) {
|
||||
const idx = this.Main_List.findIndex((x) => x && x.am_id == row.am_id);
|
||||
if (idx !== -1) {
|
||||
this.Main_List.splice(idx, 1);
|
||||
}
|
||||
if (this.$refs.commonWordHtmlTypeSetting) {
|
||||
this.$refs.commonWordHtmlTypeSetting.refresh('removeTable', { amt_id: item.amt_id });
|
||||
}
|
||||
} else {
|
||||
unboundOk = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!unboundOk) {
|
||||
fail += 1;
|
||||
continue;
|
||||
}
|
||||
const res = await this.$api.post(this.urlList.deleteTable, {
|
||||
amt_id: item.amt_id,
|
||||
article_id: this.articleId
|
||||
});
|
||||
if (res && res.status == 1) {
|
||||
ok += 1;
|
||||
if (this.$refs.commonWordHtmlTypeSetting) {
|
||||
this.$refs.commonWordHtmlTypeSetting.replacement(replaceType, item.amt_id);
|
||||
}
|
||||
} else {
|
||||
fail += 1;
|
||||
}
|
||||
} catch (err) {
|
||||
fail += 1;
|
||||
}
|
||||
}
|
||||
loading.close();
|
||||
this.$message.success(this.$t('commonTable.tableDeleteAllResult', { ok: ok, fail: fail }));
|
||||
if (this.$refs.commonWordHtmlTypeSetting) {
|
||||
this.$refs.commonWordHtmlTypeSetting.refresh('table');
|
||||
}
|
||||
this.$forceUpdate();
|
||||
},
|
||||
handleTableAdd(type) {
|
||||
this.lineStyle = { note: '', table_data: '', html_data: '' };
|
||||
this.lineStyle.visiTitle = 'Add Table';
|
||||
|
||||
@@ -347,8 +347,12 @@
|
||||
</p>
|
||||
</el-tooltip> -->
|
||||
|
||||
<div class="figure-toolbar" v-if="zyModeEnabled && unpositionedTables.length">
|
||||
<div
|
||||
class="figure-toolbar"
|
||||
v-if="zyModeEnabled && (unpositionedTables.length || tablesList.length)"
|
||||
>
|
||||
<el-button
|
||||
v-if="unpositionedTables.length"
|
||||
type="text"
|
||||
size="mini"
|
||||
class="figure-batch-position-btn"
|
||||
@@ -357,6 +361,15 @@
|
||||
>
|
||||
{{ $t('commonTable.tableBatchPosition') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="tablesList.length"
|
||||
type="text"
|
||||
size="mini"
|
||||
class="figure-delete-all-btn"
|
||||
@click.stop="handleDeleteAllTables"
|
||||
>
|
||||
{{ $t('commonTable.tableDeleteAll') }}
|
||||
</el-button>
|
||||
</div>
|
||||
<div class="item_box" @click="addTable" style="width: 100%; height: auto; position: relative">
|
||||
<div class="list-center go-flex-center go-transition" style="width: 100%">
|
||||
@@ -843,6 +856,10 @@ export default {
|
||||
handleDeleteAllFigures() {
|
||||
this.$emit('deleteAllImages', [...(this.images || [])]);
|
||||
},
|
||||
handleDeleteAllTables() {
|
||||
const list = (this.tables || []).filter((item) => item && item.amt_id);
|
||||
this.$emit('deleteAllTables', list);
|
||||
},
|
||||
isMediaPositioned(item) {
|
||||
return !!(item && Number(item.has_selected) === 1);
|
||||
},
|
||||
|
||||
@@ -3567,6 +3567,10 @@ export async function importWordDocumentWithMath(file, options = {}) {
|
||||
if (options.forFigureExtract) {
|
||||
return html;
|
||||
}
|
||||
// Tables 导入:保留表格结构,单元格内 OMML 已转 wmath,再扫一遍 $...$
|
||||
if (options.forTableExtract) {
|
||||
return parseHtmlToLatex(html);
|
||||
}
|
||||
if (options.keepReferences) {
|
||||
html = annotateOrderedListItemsInHtml(html);
|
||||
html = collapseEmptyParagraphsInHtml(
|
||||
|
||||
Reference in New Issue
Block a user