From 82ec4edba98c68382785649d53bd065eaae07222 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=A7=8B=E4=BA=8E=E5=88=9D=E8=A7=81?= <752204717@qq.com>
Date: Mon, 3 Aug 2026 11:05:44 +0800
Subject: [PATCH] =?UTF-8?q?=E4=B8=93=E5=88=8A?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/api/index.js | 4 +-
src/common/js/commonJS.js | 88 +++----------------
src/components/common/common.vue | 14 +--
src/components/common/langs/en.js | 3 +
src/components/common/langs/zh.js | 3 +
src/components/page/GenerateCharts.vue | 82 ++++++++++++++++-
src/components/page/OnlineProofreading.vue | 82 ++++++++++++++++-
.../components/table/wordHtmlTypesetting.vue | 19 +++-
src/utils/wordMathImport.js | 4 +
9 files changed, 212 insertions(+), 87 deletions(-)
diff --git a/src/api/index.js b/src/api/index.js
index 487fb66..525753d 100644
--- a/src/api/index.js
+++ b/src/api/index.js
@@ -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: '/', //正式
});
diff --git a/src/common/js/commonJS.js b/src/common/js/commonJS.js
index 36c93a9..0b68ae7 100644
--- a/src/common/js/commonJS.js
+++ b/src/common/js/commonJS.js
@@ -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(/
/g);
- const validTables = tableContent
- ? tableContent.filter(table => //.test(table))
- : [];
-
- callback(validTables);
- }).catch(err => {
- console.error('mammoth 转换失败:', err);
- });
- }).catch(err => {
- console.error("Zip 读取失败:", err);
- });
- };
-
- reader.readAsArrayBuffer(file);
+ try {
+ // 走 OMML→LaTeX 解析,表格单元格内公式转为
+ const html = await parseWordDocumentWithMath(file, { forTableExtract: true });
+ const tableContent = String(html || '').match(//gi);
+ const validTables = tableContent
+ ? tableContent.filter((table) => /]/i.test(table))
+ : [];
+ callback(validTables);
+ } catch (err) {
+ console.error('Word 表格导入失败:', err);
+ callback([]);
+ }
},
// async extractWordTablesToArrays(file, callback) {
diff --git a/src/components/common/common.vue b/src/components/common/common.vue
index e0f6d02..0e04e69 100644
--- a/src/components/common/common.vue
+++ b/src/components/common/common.vue
@@ -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'
//测试环境
diff --git a/src/components/common/langs/en.js b/src/components/common/langs/en.js
index e390a86..db90620 100644
--- a/src/components/common/langs/en.js
+++ b/src/components/common/langs/en.js
@@ -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!',
diff --git a/src/components/common/langs/zh.js b/src/components/common/langs/zh.js
index 0c210a9..2f1998b 100644
--- a/src/components/common/langs/zh.js
+++ b/src/components/common/langs/zh.js
@@ -1515,6 +1515,9 @@ const zh = {
tableBatchPosition: '批量定位',
tableBatchPositionEmpty: '没有待定位的表格',
tableBatchPositionDone: '批量定位完成:成功 {ok},未匹配 {skip},失败 {fail}',
+ tableDeleteAll: '批量删除',
+ tableDeleteAllConfirm: '确定删除全部表格吗?',
+ tableDeleteAllResult: '已删除 {ok} 个,失败 {fail} 个',
removetable: '确定要删除这个表格吗?',
reContent: '确定要恢复这条内容吗?',
uploadImageInfo: 'Figures 只能上传 JPG、JPEG 和 PNG 格式的文件',
diff --git a/src/components/page/GenerateCharts.vue b/src/components/page/GenerateCharts.vue
index aef55d0..702dad9 100644
--- a/src/components/page/GenerateCharts.vue
+++ b/src/components/page/GenerateCharts.vue
@@ -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();
diff --git a/src/components/page/OnlineProofreading.vue b/src/components/page/OnlineProofreading.vue
index 5a96784..b774180 100644
--- a/src/components/page/OnlineProofreading.vue
+++ b/src/components/page/OnlineProofreading.vue
@@ -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';
diff --git a/src/components/page/components/table/wordHtmlTypesetting.vue b/src/components/page/components/table/wordHtmlTypesetting.vue
index 1cdc9b7..8cdb982 100644
--- a/src/components/page/components/table/wordHtmlTypesetting.vue
+++ b/src/components/page/components/table/wordHtmlTypesetting.vue
@@ -347,8 +347,12 @@
-->
- |