This commit is contained in:
2026-01-30 15:15:31 +08:00
parent 1ad05f016a
commit beee2ec54b
11 changed files with 255 additions and 193 deletions

View File

@@ -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: '/', //正式
});

View File

@@ -150,49 +150,49 @@ export default {
replaceWMathContent(inputHtml, callback) {
// 正则逻辑:匹配整个 wmath 标签,并捕获内部所有的属性字符串
var str = inputHtml.replace(/<wmath ([^>]+)>[^<]*<\/wmath>/g, function (match, allProps) {
// 1. 从所有属性中提取 data-latex 的值
const latexMatch = allProps.match(/data-latex="([^"]+)"/);
const latexContent = latexMatch ? latexMatch[1] : '';
// 2. 从所有属性中提取 data-wrap 的值
const wrapMatch = allProps.match(/data-wrap="([^"]+)"/);
const wrapAttr = wrapMatch ? ` data-wrap="${wrapMatch[1]}"` : '';
// 3. 重新组装:只保留 data-latex 和 data-wrap
// 注意:这里去掉了多余的 prefix/suffix确保标签“干净”
return `<wmath${wrapAttr} data-latex="${latexContent}">${latexContent}</wmath>`;
});
callback(str);
} ,
},
// **解析 MathJax 公式,获取 LaTeX**
async extractMathJaxLatex(cell, callback) {
return new Promise((resolve, reject) => {
// Step 1: 获取初始 HTML
let updatedContent = cell.innerHTML;
// 查找所有 <wmath> 元素
const wmathElements = cell.querySelectorAll('wmath');
wmathElements.forEach((element) => {
// 1. 提取 latex 内容
const latexContent = element.getAttribute('data-latex') || '';
// 2. 提取 wrap 模式 (只提取,不包裹)
const wrapMode = element.getAttribute('data-wrap') || 'block';
// 3. 重新组装标签:只保留属性,标签内部只放原始 latex 文本
// 这里不加 $ 或 $$,保持数据的原始性
const newWmathTag = `<wmath data-wrap="${wrapMode}" data-latex="${latexContent}">${latexContent}</wmath>`;
// 4. 执行替换
updatedContent = updatedContent.replace(element.outerHTML, newWmathTag);
});
// Step 2: 提取去掉外层 span 的内容
updatedContent = this.extractContentWithoutOuterSpan(updatedContent);
// Step 3: Resolve 结果
resolve(updatedContent);
});
@@ -350,6 +350,21 @@ export default {
console.error("❌ 找不到 word/document.xml无法解析 Word 文件");
return;
}
const relsFile = zip.file("word/_rels/document.xml.rels");
let imageRelMap = {};
if (relsFile) {
const relsXml = await relsFile.async("string");
const relDoc = new DOMParser().parseFromString(relsXml, "application/xml");
const rels = relDoc.getElementsByTagName("Relationship");
for (let r = 0; r < rels.length; r++) {
const id = rels[r].getAttribute("Id");
const target = rels[r].getAttribute("Target");
if (target && target.includes("media/")) {
// 补全路径,通常 rels 里的路径是相对 word 文件夹的
imageRelMap[id] = `word/${target}`;
}
}
}
const documentXml = await documentFile.async("string");
const parser = new DOMParser();
const documentDoc = parser.parseFromString(documentXml, "application/xml");
@@ -458,14 +473,44 @@ export default {
const drawings = run.getElementsByTagName("w:drawing");
for (let d = 0; d < drawings.length; d++) {
const drawing = drawings[d];
// 使用命名空间提取 a:blip
// --- 1. 提取宽高 (EMUs 转 PX) ---
// Word 存储尺寸的地方通常在 wp:extent
const extent = drawing.getElementsByTagName("wp:extent")[0];
let styleStr = "";
if (extent) {
const cx = parseInt(extent.getAttribute("cx"));
const cy = parseInt(extent.getAttribute("cy"));
// 9525 是 EMU 到像素的换算比例
const widthPx = Math.round(cx / 9525);
const heightPx = Math.round(cy / 9525);
styleStr = `width="${widthPx}" height="${heightPx}"`;
}
const blips = drawing.getElementsByTagNameNS("http://schemas.openxmlformats.org/drawingml/2006/main", "blip");
for (let b = 0; b < blips.length; b++) {
const blip = blips[b];
const embedId = blip.getAttribute("r:embed");
if (embedId) {
textContent += `<img data-embed="${embedId}"/>`;
if (embedId && imageRelMap[embedId]) {
// const imagePath = imageRelMap[embedId];
// const imgFile = zip.file(imagePath);
// if (imgFile) {
// const fileSize = imgFile._data.uncompressedSize;
// // 依然保留 1MB 限制,保护浏览器不卡死
// if (fileSize <= 1048576) {
// const base64 = await imgFile.async("base64");
// const ext = imagePath.split('.').pop().toLowerCase();
// // <img src="data:image/${ext};base64,${base64}" ${styleStr} />
// // --- 2. 直接拼接带宽高的 img 标签 ---
// textContent += ``;
// } else {
// // console.warn(`跳过大图片: ${imagePath}, 大小: ${(fileSize / 1024 / 1024).toFixed(2)}MB`);
// textContent += ``;
// }
// }
}
}
}
@@ -2062,12 +2107,12 @@ export default {
// 插入自定义表格到编辑器中
ed.setContent('');
const customCallback = ed.getParam('clear_custom_action');
if (typeof customCallback === 'function') {
customCallback(ed, vueInstance);
} else {
// 3. 如果没有自定义逻辑,执行默认逻辑
vueInstance.$emit('onClear');
}
if (typeof customCallback === 'function') {
customCallback(ed, vueInstance);
} else {
// 3. 如果没有自定义逻辑,执行默认逻辑
vueInstance.$emit('onClear');
}
}
});
@@ -2079,11 +2124,11 @@ export default {
onAction: function () {
// 必须获取带 HTML 的内容,否则里面的 em/i 标签在拼接前就丢了
var selectedText = ed.selection.getContent({ format: 'html' });
if (selectedText) {
// 这就是你想要的:直接外层套一个 blue
var wrappedText = `<blue>${selectedText}</blue>`;
// 使用 setContent 强行回写
ed.selection.setContent(wrappedText);
}
@@ -2166,29 +2211,29 @@ export default {
ed.ui.registry.addMenuButton('MoreSymbols', {
text: '···', // 按钮显示的三个点
tooltip: 'More Special Characters',
onAction: () => {}, // 菜单主按钮点击通常不执行操作,由子菜单执行
onAction: () => { }, // 菜单主按钮点击通常不执行操作,由子菜单执行
fetch: (callback) => {
const items = [
{
type: 'menuitem',
text: 'en-dash (短划线)',//短划线
onAction: () => ed.insertContent('')
},
{
type: 'menuitem',
text: 'minus sign (减号)',//减号
onAction: () => ed.insertContent('')
},
{
type: 'menuitem',
text: 'hyphen (连接符)',
onAction: () => ed.insertContent('-')
},
];
callback(items);
const items = [
{
type: 'menuitem',
text: 'en-dash (短划线)',//短划线
onAction: () => ed.insertContent('')
},
{
type: 'menuitem',
text: 'minus sign (减号)',//减号
onAction: () => ed.insertContent('')
},
{
type: 'menuitem',
text: 'hyphen (连接符)',
onAction: () => ed.insertContent('-')
},
];
callback(items);
}
});
});
ed.ui.registry.addButton('removeBlue', {
text: 'Blue', // 按钮文本

View File

@@ -2,8 +2,8 @@
//记得切换
//正式
// const mediaUrl = '/public/';
// const baseUrl = '/';
const mediaUrl = '/public/';
const baseUrl = '/';
//正式环境
@@ -18,8 +18,8 @@
// const baseUrl = '/api';
////新正式环境
const mediaUrl = 'http://mytest.tmrjournals.com/public/';
const baseUrl = '/api';
// const mediaUrl = 'http://mytest.tmrjournals.com/public/';
// const baseUrl = '/api';
//本地(正式环境 )
// const mediaUrl = 'https://submission.tmrjournals.com/public/';

View File

@@ -2804,7 +2804,7 @@ export default {
that.$commonJS.extractWordTablesToArrays(File.raw, function (wordTables) {
that.addWordTablesList(wordTables);
loading.close();
});
},that.form.article_id);
};
reader.readAsArrayBuffer(File.raw);
}

View File

@@ -1298,7 +1298,7 @@
<span slot="label" class="title" :style="v.color ? `color:${v.color}` : ''">
{{ `${i + 1}. ${v.topic} : ` }}
</span>
<div style="">
<div style="" v-if="v.value!='hotspot'">
<div
style="color: #333; width: calc(100% - 180px); margin-left: 180px"
v-if="v.parameter && v.parameter.length > 0"
@@ -1349,6 +1349,58 @@
</template>
</div>
<div style="color: #888; line-height: 22px" v-if="v.explanationValue">
<p
:class="{ 'short-content': !v.showFullContent }"
@click="toggleContent1(i)"
style="margin-top: 0; cursor: pointer; color: #888"
>
<span>{{ $t('aiReview.Explain') }} : </span> {{ currentArticleData.ai_review[v.explanationValue] }}
</p>
</div>
</div>
<div style="" v-else>
<div
style="color: #333; width: calc(100% - 180px); margin-left: 180px"
v-if=" currentArticleData.ai_review[v.value] && currentArticleData.ai_review[v.value].length > 0"
>
<div label="``" v-for="(item, index) in currentArticleData.ai_review[v.value]">
<span class="title" style="" :style="item.color ? `color:${item.color}` : ''">
{{ `(${index + 1}) 领域 : ${item['领域']} ` }}
</span>
<div style="">
<div style="color: #333">
是否热点 : 【{{item['是否热点'] }}】
<div v-if="item['解释说明']">
<div>
<p
:class="{ 'short-content': !item.showFullContent }"
@click="toggleContent2(i, index)"
style="margin-top: 0; cursor: pointer; color: #888; line-height: 22px"
>
<span>{{ $t('aiReview.Explain') }} : </span>
{{ item['解释说明'] }}
</p>
</div>
</div>
</div>
</div>
</div>
</div>
<div style="color: #333" v-else>
<template v-if="v.isShowSign == 1"> 【{{ currentArticleData.ai_review[v.value] }}】 </template>
<template v-else>
{{ currentArticleData.ai_review[v.value] }}
</template>
</div>
<div style="color: #888; line-height: 22px" v-if="v.explanationValue">
<p
:class="{ 'short-content': !v.showFullContent }"
@@ -2076,7 +2128,7 @@ export default {
ai_review: ''
};
if (res.data) {
this.currentArticleData.ai_review = res.data;
this.currentArticleData.ai_review = {...res.data, hotspot: res.data.hotspot?JSON.parse(res.data.hotspot):''};
var aiReview = {};
if (this.currentArticleData.ai_review.journal_scope_assessment == '') {
aiReview = {
@@ -2108,6 +2160,8 @@ export default {
};
}
this.aiReview[0] = aiReview;
}
})
.catch((err) => {

View File

@@ -2981,7 +2981,7 @@ export default {
this.preactive = 1;
// 获取文章信息
this.$api
.post('api/Production/getProductionMains', {
.post('api/Preaccept/getArticleMains', {
p_article_id: this.p_article_id
})
.then((res) => {

View File

@@ -347,44 +347,46 @@ export default {
}
},
// 按照你要求的 XMLHttpRequest 格式编写
uploadSingleImage(base64Data, index) {
const _this = this;
//转为 Blob
const blob = _this.dataURLtoBlob(base64Data);
const xhr = new XMLHttpRequest();
const formData = new FormData();
// 按照你截图中的参数名,这里假设是 'file'
formData.append('file_name', blob, `word_img_${index}.png`);
formData.append('article_id', this.articleId);
xhr.withCredentials = false;
xhr.open('POST', _this.baseUrl + 'api/Articlemain/uploadTableImage');
xhr.onload = function () {
if (xhr.status !== 200) {
console.error('HTTP Error: ' + xhr.status);
return;
}
try {
const json = JSON.parse(xhr.responseText);
if (json.status == 1) {
// 2. 拼接服务器返回的 URL
const finalUrl = _this.mediaUrl + 'articleTableImage/' + json.data;
// 3. 找到对应的加载中占位图并替换
const doc = tinymce.activeEditor.getDoc();
const placeholder = doc.querySelector(`img[data-idx="${index}"]`);
if (placeholder) {
placeholder.src = finalUrl;
placeholder.removeAttribute('data-idx'); // 任务完成,移除标记
}
} else {
_this.removePlaceholder(index);
}
} catch (e) {
console.error('解析响应失败', e);
}
};
// 直接接收已经转好的 blob
uploadSingleImage(blob, index) {
const _this = this;
const xhr = new XMLHttpRequest();
const formData = new FormData();
// 直接把传进来的 blob 丢进表单
formData.append('file_name', blob, `word_img_${index}.png`);
formData.append('article_id', this.articleId);
xhr.send(formData);
},
xhr.withCredentials = false;
xhr.open('POST', _this.baseUrl + 'api/Articlemain/uploadTableImage');
xhr.onload = function () {
if (xhr.status !== 200) {
_this.removePlaceholder(index); // 失败清理
return;
}
try {
const json = JSON.parse(xhr.responseText);
if (json.status == 1) {
const finalUrl = _this.mediaUrl + 'articleTableImage/' + json.data;
const doc = tinymce.activeEditor.getDoc();
const placeholder = doc.querySelector(`img[data-idx="${index}"]`);
if (placeholder) {
placeholder.src = finalUrl;
placeholder.removeAttribute('data-idx');
}
} else {
_this.removePlaceholder(index);
}
} catch (e) {
console.error('解析响应失败', e);
_this.removePlaceholder(index);
}
};
xhr.onerror = () => _this.removePlaceholder(index);
xhr.send(formData);
},
removePlaceholder(idx) {
const doc = tinymce.activeEditor.getDoc();
@@ -591,13 +593,18 @@ myfigure *,
_this.updateUploadProgressNotification(i, 'tooLarge');
return; // 跳过此图片
}
try {
const base64 = _this.hexToBase64Sync(img.hex, img.mimeType);
_this.updateUploadProgressNotification(i, 'uploading'); // 更新为上传中
await _this.uploadSingleImage(base64, i);
_this.updateUploadProgressNotification(i, 'success'); // 上传成功
} catch (err) {
const imageBlob = _this.hexToBlob(img.hex, img.mimeType);
_this.updateUploadProgressNotification(i, 'uploading');
// 2. 【核心优化】直接上传这个 Blob 文件
// uploadSingleImage 内部需要改用 FormData 发送
await _this.uploadSingleImage(imageBlob, i);
_this.updateUploadProgressNotification(i, 'success');
} catch (err) {
console.error('Upload failed:', err);
_this.updateUploadProgressNotification(i, 'fail', err.message || 'Network error'); // 上传失败
}
@@ -895,8 +902,15 @@ console.log('Processed content:', content); // 输出处理后的内容
};
}
},
// 提取 Word 文件中的表格
hexToBlob(hex, mimeType) {
const len = hex.length / 2;
const bytes = new Uint8Array(len);
for (let i = 0; i < len; i++) {
bytes[i] = parseInt(hex.substr(i * 2, 2), 16);
}
return new Blob([bytes], { type: mimeType });
},
updateTableStyles(container) {
var html = this.$commonJS.updateTableStyles(container, this.typesettingType);
var editor = window.tinymce.activeEditor; // 将外部 DOM 内容更新到编辑器

View File

@@ -39,7 +39,7 @@
<div class="img-wrapper">
<img :src="mediaUrl + processedItem.url" class="full-screen-img" @click="close" title="点击图片关闭">
<img :src="mediaUrl + (processedItem.url||processedItem.image)" class="full-screen-img" @click="close" title="点击图片关闭">
</div>
<div class="imageTitle font" style="margin-top: 0px;">
<span v-html="processedItem.title"></span>
@@ -71,7 +71,7 @@ export default {
};
},
methods: {
async open(type, item) {
async open(type, item,isNoBg) {
this.visible = true;
this.type = type;
@@ -86,7 +86,7 @@ export default {
...item.table,
tableHeader: processed.tableHeader,
tableContent: processed.tableContent,
oddRowIds: processed.oddRowIds
oddRowIds: isNoBg ? [] : processed.oddRowIds
}
});
} catch (err) {

View File

@@ -1796,19 +1796,17 @@ export default {
this.$refs.proofreadingContent.getTinymceContent('proofreadingContent');
}, 2000),
convertSpacesToNbsp(html) {
// 把字符串转成 DOM 结构
const parser = new DOMParser();
const doc = parser.parseFromString(`<div>${html}</div>`, 'text/html'); // 包一层防止body空
// 遍历所有文本节点
const walker = doc.createTreeWalker(doc.body, NodeFilter.SHOW_TEXT);
let node;
while ((node = walker.nextNode())) {
const text = node.nodeValue;
// 转换逻辑:
// 1. 保留开头和结尾空格
// 2. 保留中间连续空格
const replaced = text
.replace(/(^ +)|( +$)/g, (m) => '\u00A0'.repeat(m.length)) // 首尾空格
.replace(/ {2,}/g, (m) => '\u00A0'.repeat(m.length)); // 中间多个空格
@@ -1828,14 +1826,14 @@ export default {
};
this.editProofreadingContentVisible = true;
// this.currentId = data.am_id;
},
async handleClickProofreading(data, index) {
await this.goToListComment(data);
},
// 让右侧相同 id 的项闪一下边框,并可选滚动到可视区域
flashRightPanel(proofreadingId, { scroll = true, offset = 80 } = {}) {
// 1⃣ 清除所有其他元素的闪烁样式
const oldFlashEls = document.querySelectorAll('.flash-border');
oldFlashEls.forEach((el) => {
el.classList.remove('flash-border');
@@ -1849,18 +1847,18 @@ export default {
}
});
// 2⃣ 获取当前匹配元素
const items = document.querySelectorAll(`[data-proofreading-id="${proofreadingId}"]`);
if (!items.length) return;
items.forEach((el) => {
// 3⃣ 确保能重新触发动画
el.classList.remove('flash-border');
// 强制重排
void el.offsetWidth;
el.classList.add('flash-border');
// 4⃣ 动画结束时自动清除
el.__flashHandler = (evt) => {
if (evt.animationName === 'flashFade') {
el.classList.remove('flash-border');
@@ -1870,7 +1868,6 @@ export default {
};
el.addEventListener('animationend', el.__flashHandler);
// 5⃣ 兜底 2 秒后清除
el.__flashTimer = setTimeout(() => {
el.classList.remove('flash-border');
if (el.__flashHandler) {
@@ -1880,8 +1877,7 @@ export default {
el.__flashTimer = null;
}, 1000);
// 6⃣ 自动滚动
// if (scroll) this.scrollContainerTo(el, offset);
});
},
scrollContainerTo(targetEl, offset = 80) {
@@ -1930,7 +1926,7 @@ export default {
});
},
openMenu(event, type, currentId) {
console.log('event at line 860:', event);
// 获取鼠标点击位置
this.menuPosition.x = event.clientX + 30;
this.menuPosition.y = event.clientY + 40;
@@ -2036,7 +2032,7 @@ export default {
const range = selection.getRangeAt(0);
let selectedNode = range.commonAncestorContainer;
// **向上查找包含 main-id 的最近 div**
let outerDiv = selectedNode;
while (outerDiv && outerDiv.tagName !== 'DIV') {
outerDiv = outerDiv.parentNode;
@@ -2047,27 +2043,24 @@ export default {
return;
}
// **缓存 main-id 和 type**
this.cachedMainId = outerDiv.getAttribute('main-id');
this.cachedType = outerDiv.getAttribute('type');
// **创建临时 div 存放选中的 HTML**
const tempDiv = document.createElement('div');
tempDiv.appendChild(range.cloneContents());
// **检查是否包含 <img> 标签**
if (tempDiv.querySelector('img')) {
this.clearCache();
this.$message.error(this.$t('commonTable.selectComment'));
return;
}
// **获取纯文本**
let selectedText = tempDiv.innerText.trim().replace(/\s+/g, ' ');
// **允许保留的 HTML 标签**
const allowedTags = ['sup', 'sub', 'strong', 'em', 'b', 'i', 'blue', 'tr', 'td'];
function preserveTags(node) {
if (node.nodeType === 3) return node.nodeValue; // 文本节点
if (node.nodeType === 1 && allowedTags.includes(node.nodeName.toLowerCase())) {
@@ -2078,19 +2071,19 @@ export default {
let preservedContent = Array.from(tempDiv.childNodes).map(preserveTags).join('');
// **检查是否已有批注**
if (tempDiv.querySelector('.positionRemarkIndex')) {
this.clearCache();
this.$message.error(this.$t('commonTable.alreadyCommented'));
return;
}
// **缓存选区内容**
this.cachedHtml = preservedContent;
this.cachedText = selectedText;
},
// **点击“添加批注”按钮**
handleSelection() {
if (!this.cachedText) {
this.$message.error(this.$t('commonTable.selectComment'));

View File

@@ -35,7 +35,7 @@
<span
>Figure {{ index + 1 }}
<span
@click="openPreview(index, 'img')"
@click="openPreview(index, 'img',img)"
>
<!-- <el-tooltip class="item" effect="dark" :content="$t('commonTable.preview')" placement="top"> -->
@@ -149,7 +149,7 @@
<div class="title">
<span
>Table {{ index + 1 }}
<span @click="openPreview(index, 'table')">
<span @click="openPreview(index, 'table',table)">
<el-tooltip class="item" effect="dark" :content="$t('commonTable.preview')" placement="top">
<i class="el-icon-view" style="font-size: 16px"></i>
</el-tooltip> </span
@@ -252,11 +252,17 @@
</ul>
</div>
<DynamicTable
ref="myTableModal"
/>
</div>
</template>
<script>
import { mediaUrl } from '@/common/js/commonJS.js'; // 引入通用逻辑
import DynamicTable from './DynamicTable.vue';
export default {
props: ['articleId', 'imgWidth', 'imgHeight', 'scale', 'isEdit', 'isShowEdit', 'urlList', 'content'],
data() {
@@ -298,6 +304,9 @@ export default {
}
}
},
components: {
DynamicTable
},
methods: {
@@ -423,10 +432,10 @@ export default {
});
}
},
openPreview(index, type) {
this.$nextTick(() => {
document.getElementById(type + '-modal-' + index).style.display = 'flex';
});
openPreview(index, type,data) {
console.log("🚀 ~ data:", data);
this.$refs.myTableModal.open(type,data,'no');
},
async getWordimgList() {
await this.$api
@@ -453,31 +462,7 @@ export default {
}
if (list.length > 0) {
list.forEach((img, index) => {
// var extension = img.image.split('.').pop().toLowerCase();
// if (extension === 'tif' || extension === 'jpg' || extension === 'jpeg' || extension === 'png') {
const modalContent = `<img src="${this.mediaUrl + img.image}" alt="Image ${index}" style="width:100%;background:#FFF;" >`;
this.$commonJS.createImageModal(index, modalContent, 'img');
// }
// if (extension === 'tif') {
// this.$nextTick(() => {
// this.$commonJS.renderTiffImage(
// this.mediaUrl + img.image,
// `tiff-canvas-modal-${index}`,
// function (url) {
// list[index].dataUrl = url;
// },
// index,
// true
// );
// });
// }
});
}
this.images = list;
// this.$emit('loaded');
});
@@ -512,36 +497,7 @@ export default {
: [];
}
await this.filterData('table');
if (this.tables.length > 0) {
this.tables.forEach((table, index) => {
var modalContent = `
<div class="wordTableHtml" style="background:#FFF;padding:20px">
<table
border="1"
style="
border-collapse: collapse;
width: 100%;
text-align: center;
table-layout: auto;"
>`;
table.table.forEach((row) => {
modalContent += `<tr>`;
row.forEach((cell) => {
modalContent += `
<td
colspan="${cell.colspan || 1}"
rowspan="${cell.rowspan || 1}"
style=""
>
<span>${cell.text}</span>
</td>`;
});
modalContent += `</tr>`;
});
modalContent += `</table></div>`;
this.$commonJS.createImageModal(index, modalContent, 'table', '');
});
}
});
}

View File

@@ -71,9 +71,9 @@ module.exports = {
proxy: {
'/api': {
// target: 'http://zmzm.tougao.dev.com/',//晓玲本地
// target: 'https://submission.tmrjournals.com/',//正式
target: 'https://submission.tmrjournals.com/',//正式
// target: 'http://tougaotest.tmrjournals.com/public/index.php/',//测试环境
target: 'http://mytest.tmrjournals.com/public/index.php/',//新正式环境
// target: 'http://mytest.tmrjournals.com/public/index.php/',//新正式环境
changeOrigin: true,
pathRewrite: {
'^/api': ''