1 Commits

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

BIN
dist.zip

Binary file not shown.

View File

@@ -3,14 +3,7 @@
registry: 'https://registry.npmmirror.com',
pkgs: [
{
name: 'tinymce',
version: 'latest',
type: 'tag',
alias: undefined,
arg: [Result]
},
{
name: 'tinymce-kityformula-editor',
name: 'spellchecker',
version: 'latest',
type: 'tag',
alias: undefined,
@@ -22,7 +15,7 @@
cacheDir: 'C:\\Users\\Administrator\\.npminstall_tarball',
env: {
npm_config_registry: 'https://registry.npmmirror.com',
npm_config_argv: '{"remain":[],"cooked":["--fix-bug-versions","--china","--userconfig=C:\\\\Users\\\\Administrator\\\\.cnpmrc","--disturl=https://cdn.npmmirror.com/binaries/node","--registry=https://registry.npmmirror.com","tinymce","tinymce-kityformula-editor"],"original":["--fix-bug-versions","--china","--userconfig=C:\\\\Users\\\\Administrator\\\\.cnpmrc","--disturl=https://cdn.npmmirror.com/binaries/node","--registry=https://registry.npmmirror.com","tinymce","tinymce-kityformula-editor"]}',
npm_config_argv: '{"remain":[],"cooked":["--fix-bug-versions","--china","--userconfig=C:\\\\Users\\\\Administrator\\\\.cnpmrc","--disturl=https://cdn.npmmirror.com/binaries/node","--registry=https://registry.npmmirror.com","spellchecker"],"original":["--fix-bug-versions","--china","--userconfig=C:\\\\Users\\\\Administrator\\\\.cnpmrc","--disturl=https://cdn.npmmirror.com/binaries/node","--registry=https://registry.npmmirror.com","spellchecker"]}',
npm_config_user_agent: 'npminstall/7.12.0 npm/? node/v16.14.1 win32 x64',
npm_config_cache: 'C:\\Users\\Administrator\\.npminstall_tarball',
NODE: 'C:\\Program Files\\nodejs\\node.exe',
@@ -126,10 +119,7 @@
},
fsevents: { host: 'https://cdn.npmmirror.com/binaries/fsevents' },
nodejieba: { host: 'https://cdn.npmmirror.com/binaries/nodejieba' },
canvas: {
host: 'https://cdn.npmmirror.com/binaries/canvas',
remote_path: 'v{version}'
},
canvas: { host: 'https://cdn.npmmirror.com/binaries/canvas' },
'skia-canvas': { host: 'https://cdn.npmmirror.com/binaries/skia-canvas' },
'flow-bin': {
replaceHost: 'https://github.com/facebook/flow/releases/download/v',

164
package-lock.json generated
View File

@@ -8,7 +8,6 @@
"name": "vue-manage-system",
"version": "4.2.0",
"dependencies": {
"@stripe/stripe-js": "^5.5.0",
"@tinymce/tinymce-vue": "^3.0.1",
"axios": "^0.18.0",
"babel-polyfill": "^6.26.0",
@@ -35,12 +34,10 @@
"vue": "^2.6.10",
"vue-cropperjs": "^3.0.0",
"vue-i18n": "^8.10.0",
"vue-paypal-checkout": "latest",
"vue-pdf": "^4.3.0",
"vue-quill-editor": "^3.0.6",
"vue-router": "^3.0.3",
"vue-schart": "^2.0.0",
"vue-stripe": "^0.1.52",
"vue-ueditor-wrap": "^2.5.6",
"vuedraggable": "^2.17.0",
"vxe-table": "^3.8.19"
@@ -1533,14 +1530,6 @@
"resolved": "https://registry.npmjs.org/@one-ini/wasm/-/wasm-0.1.1.tgz",
"integrity": "sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw=="
},
"node_modules/@paypal/sdk-constants": {
"version": "1.0.151",
"resolved": "https://registry.npmmirror.com/@paypal/sdk-constants/-/sdk-constants-1.0.151.tgz",
"integrity": "sha512-mmGLiMt7BYAKtoK1gxhUakvP1ua7lnbCR7LAaHsPc1KETWw9yMMARlpVEdfz9XGHrbzzNQep6U02zUtzXuncIA==",
"dependencies": {
"hi-base32": "^0.5.0"
}
},
"node_modules/@pkgjs/parseargs": {
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
@@ -1635,14 +1624,6 @@
"node": ">=8"
}
},
"node_modules/@stripe/stripe-js": {
"version": "5.5.0",
"resolved": "https://registry.npmmirror.com/@stripe/stripe-js/-/stripe-js-5.5.0.tgz",
"integrity": "sha512-lkfjyAd34aeMpTKKcEVfy8IUyEsjuAT3t9EXr5yZDtdIUncnZpedl/xLV16Dkd4z+fQwixScsCCDxSMNtBOgpQ==",
"engines": {
"node": ">=12.16"
}
},
"node_modules/@tinymce/tinymce-vue": {
"version": "3.2.8",
"resolved": "https://registry.npmmirror.com/@tinymce/tinymce-vue/-/tinymce-vue-3.2.8.tgz",
@@ -2951,11 +2932,6 @@
"node": ">=0.10.0"
}
},
"node_modules/Base64": {
"version": "1.3.0",
"resolved": "https://registry.npmmirror.com/Base64/-/Base64-1.3.0.tgz",
"integrity": "sha512-7BjEEmnnW5pm6mBXKQ8CfQFeVjSoFnB507R86mKaJqa2i8CvosDy/dj+9RpbD0A22XQ+hGb0FHO+226C0QXRGw=="
},
"node_modules/base64-arraybuffer": {
"version": "1.0.2",
"resolved": "https://registry.npmmirror.com/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz",
@@ -2998,24 +2974,6 @@
"tweetnacl": "^0.14.3"
}
},
"node_modules/beaver-logger": {
"version": "3.0.19",
"resolved": "https://registry.npmmirror.com/beaver-logger/-/beaver-logger-3.0.19.tgz",
"integrity": "sha512-hfBwPUD8PeE6mFSTtWAYd/wI8AzaoeRGNIpWGZWJGZBLyl7Fb7n6PL33JujUzWKWDsIi9V3HoppqIyM/CeeSnw==",
"dependencies": {
"zalgo-promise": "^1.0.26"
}
},
"node_modules/belter": {
"version": "1.0.173",
"resolved": "https://registry.npmmirror.com/belter/-/belter-1.0.173.tgz",
"integrity": "sha512-wmUVEQR0igzKKO1yHT6ouGLCwzoeXFf1OsHeAk8DcCOgYtdBU8NiUlV94qx8NLFnahuwbpDqLBETfHUGXQOL8Q==",
"dependencies": {
"cross-domain-safe-weakmap": "^1",
"cross-domain-utils": "^2",
"zalgo-promise": "^1"
}
},
"node_modules/bfj": {
"version": "6.1.2",
"resolved": "https://registry.npmjs.org/bfj/-/bfj-6.1.2.tgz",
@@ -3155,11 +3113,6 @@
"integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==",
"dev": true
},
"node_modules/bowser": {
"version": "1.9.4",
"resolved": "https://registry.npmmirror.com/bowser/-/bowser-1.9.4.tgz",
"integrity": "sha512-9IdMmj2KjigRq6oWhmwv1W36pDuA4STQZ8q6YO9um+x07xgYNCD3Oou+WP/3L1HNz7iqythGet3/p4wvc8AAwQ=="
},
"node_modules/brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
@@ -12650,22 +12603,6 @@
"resolved": "https://registry.npmjs.org/cropperjs/-/cropperjs-1.6.2.tgz",
"integrity": "sha512-nhymn9GdnV3CqiEHJVai54TULFAE3VshJTXSqSJKa8yXAKyBKDWdhHarnlIPrshJ0WMFTGuFvG02YjLXfPiuOA=="
},
"node_modules/cross-domain-safe-weakmap": {
"version": "1.0.29",
"resolved": "https://registry.npmmirror.com/cross-domain-safe-weakmap/-/cross-domain-safe-weakmap-1.0.29.tgz",
"integrity": "sha512-VLoUgf2SXnf3+na8NfeUFV59TRZkIJqCIATaMdbhccgtnTlSnHXkyTRwokngEGYdQXx8JbHT9GDYitgR2sdjuA==",
"dependencies": {
"cross-domain-utils": "^2.0.0"
}
},
"node_modules/cross-domain-utils": {
"version": "2.0.38",
"resolved": "https://registry.npmmirror.com/cross-domain-utils/-/cross-domain-utils-2.0.38.tgz",
"integrity": "sha512-zZfi3+2EIR9l4chrEiXI2xFleyacsJf8YMLR1eJ0Veb5FTMXeJ3DpxDjZkto2FhL/g717WSELqbptNSo85UJDw==",
"dependencies": {
"zalgo-promise": "^1.0.11"
}
},
"node_modules/cross-spawn": {
"version": "6.0.5",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
@@ -14105,11 +14042,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/es6-promise": {
"version": "4.2.8",
"resolved": "https://registry.npmmirror.com/es6-promise/-/es6-promise-4.2.8.tgz",
"integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w=="
},
"node_modules/escalade": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz",
@@ -14915,11 +14847,6 @@
"node": ">= 0.12"
}
},
"node_modules/form-serialize": {
"version": "0.7.2",
"resolved": "https://registry.npmmirror.com/form-serialize/-/form-serialize-0.7.2.tgz",
"integrity": "sha512-ohEA4Crzd/+hSREjGf4kSsy73WhAtQ7H+blGEz2DVd+JCi0TV5nZBSn9PaPlvrl9m29fa6xclAfpRkqZ57b1bw=="
},
"node_modules/forwarded": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
@@ -15464,11 +15391,6 @@
"integrity": "sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ==",
"dev": true
},
"node_modules/hi-base32": {
"version": "0.5.1",
"resolved": "https://registry.npmmirror.com/hi-base32/-/hi-base32-0.5.1.tgz",
"integrity": "sha512-EmBBpvdYh/4XxsnUybsPag6VikPYnN30td+vQk+GI3qpahVEG9+gTkG0aXVxTjBqQ5T6ijbWIu77O+C5WFWsnA=="
},
"node_modules/highlight.js": {
"version": "10.7.3",
"resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz",
@@ -17442,11 +17364,6 @@
"readable-stream": "^2.0.1"
}
},
"node_modules/merge": {
"version": "1.2.1",
"resolved": "https://registry.npmmirror.com/merge/-/merge-1.2.1.tgz",
"integrity": "sha512-VjFo4P5Whtj4vsLzsYBu5ayHhoHJ0UqNm7ibvShmbmoz7tGi0vXaoJbGdB+GmDMLUdg8DpQXEIeVDAe8MaABvQ=="
},
"node_modules/merge-descriptors": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
@@ -18674,24 +18591,6 @@
"node": ">=4"
}
},
"node_modules/paypal-checkout": {
"version": "4.0.344",
"resolved": "https://registry.npmmirror.com/paypal-checkout/-/paypal-checkout-4.0.344.tgz",
"integrity": "sha512-CDdkbfsk2Fcc8VQX+4UIlJcA+ylnumSnIFupScYvvGuJHrC1Yr6CwnSBPqo4e2fxCfeeoMxOrWzSFetw6RF+vQ==",
"dependencies": {
"@paypal/sdk-constants": "^1.0.64",
"Base64": "^1.0.0",
"beaver-logger": "^3.0.6",
"belter": "1.0.173",
"bowser": "^1.7.1",
"cross-domain-utils": "^2.0.1",
"form-serialize": "^0.7.2",
"hi-base32": "^0.5.0",
"post-robot": "^8.0.0",
"zalgo-promise": "^1.0.10",
"zoid": "6.0.84"
}
},
"node_modules/pbkdf2": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz",
@@ -18878,16 +18777,6 @@
"node": ">= 0.4"
}
},
"node_modules/post-robot": {
"version": "8.0.32",
"resolved": "https://registry.npmmirror.com/post-robot/-/post-robot-8.0.32.tgz",
"integrity": "sha512-PMOdDAt3pyuKUxZcTzdcXXFxLqkdeLpRlcCQl7QAJpI+e7J1YHH+PfC7KAbcL8hRVQ1LknQYGoirbA1/eO/a1g==",
"dependencies": {
"cross-domain-safe-weakmap": "^1.0.1",
"cross-domain-utils": "^2.0.0",
"zalgo-promise": "^1.0.3"
}
},
"node_modules/postcss": {
"version": "7.0.39",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz",
@@ -22816,20 +22705,6 @@
"node": ">=4.0.0"
}
},
"node_modules/vue-paypal-checkout": {
"version": "3.2.0",
"resolved": "https://registry.npmmirror.com/vue-paypal-checkout/-/vue-paypal-checkout-3.2.0.tgz",
"integrity": "sha512-y7Fz60ePTr6rMHGVu5S+6kDZTl5x3+Wh2DV0E4V1ibc3z4YJ8gw18PxMOt34FexYs5621F5C/9MF30TiSoDXBg==",
"dependencies": {
"babel-runtime": "^6.26.0",
"paypal-checkout": "^4.0.228",
"vue": "^2.5.17"
},
"engines": {
"node": ">= 4.0.0",
"npm": ">= 3.0.0"
}
},
"node_modules/vue-pdf": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/vue-pdf/-/vue-pdf-4.3.0.tgz",
@@ -22958,16 +22833,6 @@
"schart.js": "^3.0.0"
}
},
"node_modules/vue-stripe": {
"version": "0.1.52",
"resolved": "https://registry.npmmirror.com/vue-stripe/-/vue-stripe-0.1.52.tgz",
"integrity": "sha512-gNM49Tp+17L1HXgaSz/mZskYGO5Exqj6NQ0YyB74ji3QDsO7T21mWvY5FO5sA26OIKvH6JQDmpSbY0/VQzjyVA==",
"dependencies": {
"es6-promise": "^4.0.5",
"merge": "^1.2.0",
"vue": "^2"
}
},
"node_modules/vue-style-loader": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/vue-style-loader/-/vue-style-loader-4.1.3.tgz",
@@ -24155,35 +24020,6 @@
"node": ">=10"
}
},
"node_modules/zalgo-promise": {
"version": "1.0.48",
"resolved": "https://registry.npmmirror.com/zalgo-promise/-/zalgo-promise-1.0.48.tgz",
"integrity": "sha512-LLHANmdm53+MucY9aOFIggzYtUdkSBFxUsy4glTTQYNyK6B3uCPWTbfiGvSrEvLojw0mSzyFJ1/RRLv+QMNdzQ=="
},
"node_modules/zoid": {
"version": "6.0.84",
"resolved": "https://registry.npmmirror.com/zoid/-/zoid-6.0.84.tgz",
"integrity": "sha512-hFz75WxribvnWDIq8QA9iw1Csxa2BdjOsSmItnVSe+SKS75FZDp6hnxgoKkI0SM+7OTWNJ9Gwx/lywAImjk6Cg==",
"dependencies": {
"beaver-logger": "^3.0.17",
"belter": "1.0.123",
"cross-domain-safe-weakmap": "^1.0.22",
"cross-domain-utils": "^2.0.16",
"hi-base32": "^0.5.0",
"post-robot": "^8.0.29",
"zalgo-promise": "^1.0.34"
}
},
"node_modules/zoid/node_modules/belter": {
"version": "1.0.123",
"resolved": "https://registry.npmmirror.com/belter/-/belter-1.0.123.tgz",
"integrity": "sha512-SV1wtG+HHygUmFOBcPbKBix5aWfxdeUZ/+h2d7yGuIuQTu6x65zzUYGQg9CrUsd63DtzqCj09S1CBSHxDjhYmQ==",
"dependencies": {
"cross-domain-safe-weakmap": "^1.0.20",
"cross-domain-utils": "^2.0.10",
"zalgo-promise": "^1.0.28"
}
},
"node_modules/zrender": {
"version": "5.6.0",
"resolved": "https://registry.npmjs.org/zrender/-/zrender-5.6.0.tgz",

View File

@@ -8,9 +8,7 @@
"build": "vue-cli-service build"
},
"dependencies": {
"@stripe/stripe-js": "^5.5.0",
"@tinymce/tinymce-vue": "^3.0.1",
"@vue/reactivity": "^3.5.13",
"axios": "^0.18.0",
"babel-polyfill": "^6.26.0",
"clipboard": "^2.0.11",
@@ -25,9 +23,7 @@
"html2canvas": "^1.4.1",
"install": "^0.13.0",
"jszip": "^3.10.1",
"katex": "^0.16.21",
"mammoth": "^1.5.1",
"mathlive": "^0.104.0",
"mavon-editor": "^2.6.17",
"multi-items-input": "^0.2.0",
"pizzip": "^3.1.7",
@@ -43,7 +39,6 @@
"vue-quill-editor": "^3.0.6",
"vue-router": "^3.0.3",
"vue-schart": "^2.0.0",
"vue-stripe": "^0.1.52",
"vue-ueditor-wrap": "^2.5.6",
"vuedraggable": "^2.17.0",
"vxe-table": "^3.8.19"

View File

@@ -15,8 +15,7 @@
<div id="app"></div>
<!-- built files will be auto injected -->
</body><script src="<%=BASE_URL %>/tinymce/tinymce.min.js"></script>
<script async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
<script src="/js/global-math.js"></script>
<script src="https://www.paypal.com/sdk/js?client-id=ATqBigrhcNdqR8J83aDjTOoJHsAVz0U45JRY4H0stcEcv0mQrMDHQmyrydQInYd1w4lJ1ee3Wsblm2WP"></script>
</html>

View File

@@ -1,108 +0,0 @@
// 确保 MathJax 配置正确
window.MathJax = window.MathJax || {
loader: {
load: ['[tex]/ams', '[tex]/newcommand']
},
tex: {
inlineMath: [['$', '$'], ['\\(', '\\)']],
displayMath: [['$$', '$$'], ['\\[', '\\]']]
},
a11y: {
// 启用 MathJax 可访问性功能,确保使用 aria-label
texHints: true,
screenReader: true,
mathml: {
enable: true,
},
label: {
// 公式的 aria-label 配置
enable: true,
texClass: 'MathJax-Label',
form: 'LaTeX'
}
},
svg: { fontCache: 'global' }
};
// **定义全局渲染方法**
window.renderMathJax = function (tinymceId) {
if (window.MathJax && typeof window.MathJax.typesetPromise === "function") {
console.log("正在渲染 MathJax 公式...");
// 如果提供了 TinyMCE 编辑器 ID
if (tinymceId) {
const editorInstance = window.tinymce.get(tinymceId); // 根据 ID 获取 TinyMCE 实例
if (!editorInstance) return;
const editorBody = editorInstance.getBody();
// 获取所有 <wmath> 元素
const wmathElements = editorBody.querySelectorAll('wmath');
if (wmathElements.length > 0) {
wmathElements.forEach((element) => {
const latexContent = element.getAttribute('data-latex');
if (latexContent) {
// 将公式内容填入标签内部
element.innerHTML = latexContent;
// 使用 MathJax 渲染该元素
window.MathJax.typesetPromise([element]).catch((err) => {
console.warn("TinyMCE MathJax 渲染失败:", err);
});
}
});
}
// 渲染 <math>MathML标签如果有的话
const mathElements = editorBody.querySelectorAll('math');
if (mathElements.length > 0) {
window.MathJax.typesetPromise(Array.from(mathElements)).catch((err) => {
console.warn("MathML 渲染失败:", err);
});
}
}
else {
// 处理全局文档中的 <wmath> 标签
const wmathElements = document.querySelectorAll('wmath');
wmathElements.forEach((element) => {
// 检查 <wmath> 标签是否包含有效的 data-latex 属性值
const latexContent = element.getAttribute('data-latex');
if (latexContent) {
// 将元素的内部内容替换为 data-latex 的值
element.innerHTML = latexContent;
// 渲染 MathJax 公式
window.MathJax.typesetPromise([element]).catch((err) => {
console.warn("MathJax 渲染失败:", err);
});
}
});
// 处理全局文档中的 <math> 标签MathML 内容)
const mathElements = document.querySelectorAll('math');
mathElements.forEach((element) => {
// 渲染 MathJax 公式
window.MathJax.typesetPromise([element]).catch((err) => {
console.warn("MathJax 渲染失败:", err);
});
});
}
} else {
console.warn("MathJax 未正确加载!");
}
}

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

@@ -1106,7 +1106,6 @@ a {
.wordTableHtml table {
border: 0px !important;
border-bottom: 1px solid #000 !important;
border-collapse: collapse;
/* 去除单元格间隙 */
width: auto;
@@ -1115,10 +1114,10 @@ a {
/* 自动调整列宽 */
text-align: left;
font-family: 'Charis SIL' !important;
font-size: 12px !important;
font-size: 7.5pt !important;
mso-font-kerning: 1pt !important;
line-height: 20px !important;
mos-line-height: 20px !important;
line-height: 10pt !important;
mos-line-height: 10pt !important;
}
.wordTableHtml table td,
@@ -1126,15 +1125,14 @@ a {
padding: 5px;
text-align: left !important;
word-wrap: normal;
word-wrap: break-word;
/* 长单词自动换行 */
word-break: normal;
word-break: break-word;
font-family: 'Charis SIL' !important;
font-size: 12px !important;
font-size: 7.5pt !important;
mso-font-kerning: 1pt !important;
line-height: 20px !important;
mos-line-height: 20px !important;
line-height: 10pt !important;
mos-line-height: 10pt !important;
}
.wordTableHtml table tbody tr td {
@@ -1160,38 +1158,38 @@ a {
align-items: center;
margin: 0;
font-family: 'Charis SIL' !important;
font-size: 12px !important;
font-size: 7.5pt !important;
mso-font-kerning: 1pt !important;
line-height: 20px !important;
mos-line-height: 20px !important;
line-height: 10pt !important;
mos-line-height: 10pt !important;
}
.wordTableHtml table span {
color: #000000;
text-align: left !important;
font-family: 'Charis SIL' !important;
font-size: 12px !important;
line-height: 20px !important;
font-size: 7.5pt !important;
mso-font-kerning: 1pt !important;
line-height: 10pt !important;
mos-line-height: 10pt !important;
}
.wordTableHtml table .color-highlight {
color: rgb(0, 130, 170) !important;
font-family: 'Charis SIL' !important;
font-size: 12px !important;
font-size: 7.5pt !important;
mso-font-kerning: 1pt !important;
line-height: 20px !important;
mos-line-height: 20px !important;
line-height: 10pt !important;
mos-line-height: 10pt !important;
}
.wordTableHtml table blue {
color: rgb(0, 130, 170) !important;
font-family: 'Charis SIL' !important;
font-size: 12px !important;
font-size: 7.5pt !important;
mso-font-kerning: 1pt !important;
line-height: 20px !important;
mos-line-height: 20px !important;
line-height: 10pt !important;
mos-line-height: 10pt !important;
}
.wordTableHtml table tr:first-child td {
@@ -1201,20 +1199,11 @@ a {
}
/* 给表格中最后一行表头添加红色下边框 */
/* 给最后一个 table-header-row 添加红色下边框 */
.wordTableHtml table tr:last-of-type td {
border-bottom: 1px solid #000 !important;
}
/* 给最后一个 table-header-row第二行加样式 */
.wordTableHtml table tr.table-header-row:nth-of-type(2) td {
border-bottom: 1px solid #000 !important;
}
.word-container b span {
font-weight: bold !important;
@@ -1258,10 +1247,10 @@ a {
/* 自动调整列宽 */
text-align: left;
font-family: 'Charis SIL' !important;
font-size: 14px !important;
font-size: 7.5pt !important;
mso-font-kerning: 1pt !important;
line-height: 20px !important;
mos-line-height: 20px !important;
line-height: 10pt !important;
mos-line-height: 10pt !important;
}
.word-container table td,
@@ -1270,14 +1259,14 @@ a {
text-align: left !important;
white-space: pre-wrap;
/* 保留换行符并换行 */
word-wrap: normal;
word-wrap: break-word;
/* 长单词自动换行 */
word-break: normal;
word-break: break-word;
font-family: 'Charis SIL' !important;
font-size: 14px !important;
font-size: 7.5pt !important;
mso-font-kerning: 1pt !important;
line-height: 20px !important;
mos-line-height: 20px !important;
line-height: 10pt !important;
mos-line-height: 10pt !important;
}
.word-container table tbody tr td {
@@ -1294,8 +1283,7 @@ a {
border-left: 1px dashed #dcdfe6 !important;
border-right: 1px dashed #dcdfe6 !important;
word-break: keep-all !important;
white-space: pre-wrap !important;
/* text-align: justify !important; */
text-align: justify !important;
}
.word-container table tr td p {
@@ -1303,36 +1291,36 @@ a {
margin: 0;
font-family: 'Charis SIL' !important;
font-size: 14px !important;
font-size: 7.5pt !important;
mso-font-kerning: 1pt !important;
line-height: 20px !important;
mos-line-height: 20px !important;
line-height: 10pt !important;
mos-line-height: 10pt !important;
}
.word-container table span {
color: #000000;
text-align: left !important;
font-family: 'Charis SIL' !important;
font-size: 14px !important;
font-size: 7.5pt !important;
mso-font-kerning: 1pt !important;
line-height: 20px !important;
mos-line-height: 20px !important;
line-height: 10pt !important;
mos-line-height: 10pt !important;
}
.word-container table .color-highlight {
color: rgb(0, 130, 170) !important;
font-family: 'Charis SIL' !important;
font-size: 14px !important;
font-size: 7.5pt !important;
mso-font-kerning: 1pt !important;
line-height: 20px !important;
mos-line-height: 20px !important;
line-height: 10pt !important;
mos-line-height: 10pt !important;
}
.word-container table tr:first-child td {
/* border-top: 1pt solid #000 !important;
border-top: 1pt solid #000 !important;
mso-border-top-alt: 0.5pt solid #000 !important;
border-bottom: 1pt solid #000 !important;
mso-border-bottom-alt: 0.5pt solid #000 !important; */
mso-border-bottom-alt: 0.5pt solid #000 !important;
}
.word-container table tr:last-of-type {
@@ -1409,7 +1397,6 @@ a {
/* font-size:16px!important; */
/* 设置字体颜色 */
}
.tinymce-custom-button-addrow {
font-weight: bold !important;
background-color: #cbccd1 !important;
@@ -1434,19 +1421,3 @@ a {
text-decoration: line-through !important;
/* 设置字体颜色 */
}
mjx-container {
font-size: 14px !important;
}
wmath {
width: 100%;
display: block;
display: flex;
}
/* 强制 MathLive 虚拟键盘浮在最顶层 */
.ML__keyboard {
z-index: 99999 !important;
position: fixed !important;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 99 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 882 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

View File

@@ -1,5 +1,4 @@
import Vue from 'vue';
import katex from 'katex';
import JSZip from 'jszip';
import Common from '@/components/common/common'
import Tiff from 'tiff.js';
@@ -19,107 +18,11 @@ const capitalizeFirstLetter = function (text) {
});
};
export default {
extractLatexFromMathJax() {
// 获取所有 MathJax 渲染的公式容器
const mathContainers = document.querySelectorAll('mjx-container');
mathContainers.forEach(container => {
// 查找每个渲染公式对应的 MathML 部分
const mathElement = container.querySelector('mjx-math');
console.log('mathElement at line 28:', mathElement)
if (mathElement) {
// 获取 MathJax 渲染的公式对象
const jax = window.MathJax.getJaxFor(mathElement);
console.log('jax at line 32:', jax)
if (jax) {
// 使用 MathJax API 获取公式的 LaTeX 代码
const latex = jax.getLiteral(); // 获取 LaTeX 表达式
console.log('提取到的 LaTeX 公式:', latex); // 输出 LaTeX 代码
} else {
console.warn('MathJax 对象未找到');
}
}
});
},
replaceWMathContent(inputHtml, callback) {
// 使用正则表达式查找所有 <wmath> 标签,并提取 data-latex 的内容
var str = inputHtml.replace(/<wmath data-latex="([^"]+)">[^<]*<\/wmath>/g, function (match, latexContent) {
// 返回 <wmath> 标签,内容替换为 data-latex 的值
return `<wmath data-latex="${latexContent}">${latexContent}</wmath>`;
});
// 调用回调函数并传递处理后的结果
callback(str);
// 输出结果到控制台
console.log('Processed HTML:', str);
}
,
// **解析 MathJax 公式,获取 LaTeX**
async extractMathJaxLatex(cell, callback) {
console.log('cell at line 67:', cell)
return new Promise((resolve, reject) => {
// Step 1: First, process the math content and extract LaTeX from <wmath> tags
let updatedContent = cell.innerHTML; // Start with the cell's inner HTML
console.log('cell content at the start:', updatedContent);
// Find all <wmath> elements
const wmathElements = cell.querySelectorAll('wmath');
wmathElements.forEach((element) => {
// Get the LaTeX content from the data-latex attribute
const latexContent = element.getAttribute('data-latex');
console.log('LaTeX content from data-latex:', latexContent);
// Replace the <wmath> tag with its LaTeX content wrapped in $$...$$
updatedContent = updatedContent.replace(element.outerHTML, `<wmath data-latex="${latexContent}">${latexContent}</wmath>`);
});
console.log('updatedContent after processing wmath tags:', updatedContent);
// Step 2: Now extract content without the outer <span> tags
updatedContent = this.extractContentWithoutOuterSpan(updatedContent);
console.log('updatedContent after extractContentWithoutOuterSpan:', updatedContent);
// Step 3: Call the callback function with the final updated content
// callback(updatedContent);
// Resolve the promise with the final content
resolve(updatedContent);
});
}
,
renderLatex(latexString) {
return katex.renderToString(latexString, {
throwOnError: false
});
},
decodeHtml(html) {
var txt = document.createElement('textarea');
txt.innerHTML = html;
return txt.value;
},
//去掉最外层自定义的span标签
extractContentWithoutOuterSpan(cell) {
console.log('cell at line 90:', cell)
var str = ''
if (!cell) {
return ''
}
// 获取单元格的 HTML 内容
let htmlContent = cell.trim();
console.log('htmlContent at line 94:', htmlContent)
let htmlContent = cell.innerHTML.trim();
str = this.transformHtmlString(htmlContent)
// 创建一个临时的 DOM 元素来解析 HTML
@@ -140,29 +43,12 @@ export default {
str = capitalizeFirstLetter(str);
// 添加蓝色标签
const regex = /\[(\d+(?:\d+)?(?:, ?\d+(?:\d+)?)*)\]/g;
str = str.replace(/<blue>/g, '').replace(/<\/blue>/g, ''); // 先去掉所有的 <blue> 标签
const regex = /\[(\d+(?:\d+)?(?:,\d+(?:\d+)?)*)\]/g;;
if (regex.test(str)) {
str = str.replace(regex, function (match) {
// 提取出方括号中的内容,并进行匹配
const content = match.slice(1, match.length - 1); // 去掉方括号
// 判断是否符合条件,纯数字、逗号后有空格、连字符
if (/^\d+$/.test(content) || /, ?/.test(content) || //.test(content)) {
return `<blue>${match}</blue>`; // 如果符合条件则加上蓝色标签
str = `<blue>${str}</blue>`;
}
return match; // 如果不符合条件,则保持原样
});
}
console.log('str at line 141:', str)
// 如果没有 <span> 标签,直接返回原始 HTML 内容
return str;
},
async extractPastedWordTablesToArrays(pastedHtml, callback) {
try {
@@ -253,140 +139,90 @@ export default {
callback([]);
}
},
async extractWordTablesToArrays(file, callback) {
const namespace = "http://schemas.openxmlformats.org/wordprocessingml/2006/main";
try {
const Zip = new JSZip();
try {
// 解压 Word 文档
const zip = await Zip.loadAsync(file);
const documentXml = await zip.file("word/document.xml").async("string");
console.log("解压后的文件:", Object.keys(zip.files));
const documentFile = zip.file("word/document.xml");
if (!documentFile) {
console.error("❌ 找不到 word/document.xml无法解析 Word 文件");
return;
}
const documentXml = await documentFile.async("string");
// 解析 XML
const parser = new DOMParser();
const documentDoc = parser.parseFromString(documentXml, "application/xml");
console.log("解析的 XML 结构:", new XMLSerializer().serializeToString(documentDoc));
const numberingFile = zip.file("word/numbering.xml");
let numberingMap = {};
if (numberingFile) {
const numberingXml = await numberingFile.async("string");
const numberingDoc = parser.parseFromString(numberingXml, "application/xml");
numberingMap = this.parseNumbering(numberingDoc);
} else {
console.warn("⚠️ word/numbering.xml 不存在,跳过编号解析");
// 获取命名空间
const namespace = "http://schemas.openxmlformats.org/wordprocessingml/2006/main";
const numberingXml = await zip.file("word/numbering.xml").async("string");
let numberingDoc = null;
if (numberingXml) {
numberingDoc = parser.parseFromString(numberingXml, "application/xml");
}
// 获取编号定义
const numberingMap = this.parseNumbering(numberingDoc);
// 获取所有表格
const tables = documentDoc.getElementsByTagNameNS(namespace, "tbl");
const allTables = [];
const allTables = []; // 存储所有表格的二维数组
if (!tables || tables.length === 0) {
console.warn("未找到表格内容,请检查 XML 结构");
return [];
}
for (const table of tables) {
const rows = table.getElementsByTagNameNS(namespace, "tr");
const tableArray = [];
let rowSpanMap = [];
for (let rowIndex = 0; rowIndex < rows.length; rowIndex++) {
const row = rows[rowIndex];
const cells = row.getElementsByTagNameNS(namespace, "tc");
const rowArray = [];
if (!rowSpanMap[rowIndex]) {
rowSpanMap[rowIndex] = [];
const prevParagraph = table.previousElementSibling;
if (prevParagraph) {
console.log(`表格前的段落: ${prevParagraph.textContent}`);
}
const rows = table.getElementsByTagNameNS(namespace, "tr");
const tableArray = []; // 当前表格的二维数组
let cellIndex = 0;
for (const row of rows) {
const cells = row.getElementsByTagNameNS(namespace, "tc");
const rowArray = []; // 当前行的数据
// 存储已合并的单元格
let colSpanInfo = [];
for (let i = 0; i < cells.length; i++) {
while (rowSpanMap[rowIndex][cellIndex]) {
rowArray.push(null);
cellIndex++;
}
const cell = cells[i];
let cellText = "";
// const paragraphs = cell.getElementsByTagNameNS(namespace, "p");
const paragraphs = cell.getElementsByTagName("w:p");
// 检查合并单元格属性
const gridSpan = cell.getElementsByTagNameNS(namespace, "gridSpan")[0];
const vMerge = cell.getElementsByTagNameNS(namespace, "vMerge")[0];
var colspan = gridSpan ? parseInt(gridSpan.getAttribute("w:val"), 10) : 1;
var rowspan = 1;
if (vMerge) {
if (vMerge.getAttribute("w:val") === "restart") {
rowspan = 1; // 初始化 rowspan
let nextRowIdx = rowIndex + 1;
let maxRowspan = rows.length - rowIndex; // 确保 rowspan 不会超过剩余行数
// 获取合并信息
let colspan = gridSpan ? parseInt(gridSpan.getAttribute("w:val"), 10) : 1;
let rowspan = 1;
while (nextRowIdx < rows.length) {
const nextRowCells = rows[nextRowIdx].getElementsByTagNameNS(namespace, "tc");
// console.log(`🔍 检查下一行单元格 at row ${nextRowIdx}, col ${cellIndex}:`, nextRowCells);
if (nextRowCells.length > cellIndex) {
const nextCell = nextRowCells[cellIndex];
if (!nextCell) {
// console.warn(`⚠️ nextCell 未定义 at row ${nextRowIdx}, col ${cellIndex}`);
break;
if (vMerge && vMerge.getAttribute("w:val") === "restart") {
rowspan = 2; // 假设合并两行
} else if (vMerge && !vMerge.getAttribute("w:val")) {
continue; // 如果是合并单元格的继续部分,则跳过
}
const nextVMerge = nextCell.getElementsByTagNameNS(namespace, "vMerge")[0];
// console.log(`🔍 检查 nextVMerge at row ${nextRowIdx}, col ${cellIndex}:`, nextVMerge);
// 处理单元格内容
// let cellText = "";
// **如果 nextVMerge 为空,则不应继续增长 rowspan**
if (!nextVMerge) {
// console.log(`⚠️ nextVMerge 为空 at row ${nextRowIdx}, col ${cellIndex} - 停止扩展`);
break;
}
// **解析 nextVMerge 的值**
const vMergeVal = nextVMerge.getAttribute("w:val");
if (!vMergeVal || vMergeVal === "continue") {
if (rowspan < maxRowspan) { // 限制 rowspan 最大值
rowspan++;
// console.log(`✅ rowspan 扩展到: ${rowspan} (row: ${nextRowIdx}, col: ${cellIndex})`);
nextRowIdx++;
} else {
// console.log(`⛔ 最大 rowspan 限制 ${rowspan},在 row ${nextRowIdx} 停止`);
break;
}
} else if (vMergeVal === "restart") {
// console.log(`⛔ 停止 rowspan 扩展 at row ${nextRowIdx}, 因为 w:val="restart"`);
break;
} else {
// console.log(`⚠️ 未知 w:val="${vMergeVal}" at row ${nextRowIdx},停止合并`);
break;
}
} else {
// console.warn(`⚠️ Row ${nextRowIdx} 没有足够的列 cellIndex ${cellIndex}`);
break;
}
}
} else {
continue;
}
}
console.log('rowspan at line 265:', rowspan)
// 为当前单元格初始化计数器
const currentLevelNumbers = {};
for (const paragraph of paragraphs) {
// 提取段落编号
let listPrefix = "";
const numPr = paragraph.getElementsByTagName("w:numPr")[0];
if (numPr) {
console.log('numPr at line 54:', numPr)
const numIdElement = numPr.getElementsByTagName("w:numId")[0];
console.log('numIdElement at line 56:', numIdElement)
const ilvlElement = numPr.getElementsByTagName("w:ilvl")[0];
console.log('ilvlElement at line 58:', ilvlElement)
if (numIdElement && ilvlElement) {
const numId = numIdElement.getAttribute("w:val");
const ilvl = ilvlElement.getAttribute("w:val");
@@ -394,6 +230,7 @@ export default {
}
}
// 初始化当前段落文本
let paragraphText = listPrefix ? `${listPrefix} ` : "";
const runs = paragraph.getElementsByTagName("w:r");
@@ -404,6 +241,7 @@ export default {
textContent += text.textContent;
}
// 检查格式
const rPr = run.getElementsByTagName("w:rPr")[0];
let formattedText = textContent;
@@ -428,308 +266,70 @@ export default {
}
}
// 替换负号
formattedText = replaceNegativeSign(formattedText);
// 首字母大写
formattedText = capitalizeFirstLetter(formattedText);
const regex = /\[(\d+(?:\d+)?(?:, ?\d+(?:\d+)?)*)\]/g;
formattedText = formattedText.replace(/<blue>/g, '').replace(/<\/blue>/g, '');
// 添加蓝色标签
const regex = /\[\d+(?:,\d+)*\]/g;
if (regex.test(formattedText)) {
formattedText = formattedText.replace(regex, function (match) {
const content = match.slice(1, match.length - 1);
if (/^\d+$/.test(content) || /, ?/.test(content) || //.test(content)) {
return `<blue>${match}</blue>`;
formattedText = `<blue>${formattedText}</blue>`;
}
return match;
});
}
console.log("After replacement:", formattedText);
paragraphText += formattedText;
}
// 处理换行符
const breaks = paragraph.getElementsByTagName("w:br");
for (const br of breaks) {
paragraphText += "<br/>";
paragraphText += "<br>";
}
cellText += paragraphText;
console.log('cellText at line 366:', cellText)
cellText += paragraphText; // 将段落文本添加到单元格文本
}
// 更新合并单元格的信息
if (colSpanInfo[i]) {
colspan = colSpanInfo[i].colspan;
}
// 保存当前单元格信息
rowArray.push({
text: cellText,
colspan: colspan,
rowspan: rowspan
});
if (rowspan > 1) {
for (let j = 1; j < rowspan; j++) {
if (!rowSpanMap[rowIndex + j]) {
rowSpanMap[rowIndex + j] = [];
// 记录跨列合并
if (colspan > 1) {
for (let j = 1; j < colspan; j++) {
colSpanInfo[i + j] = { colspan: 0 }; // 用 0 填充后续的列合并
}
rowSpanMap[rowIndex + j][cellIndex] = true;
}
}
cellIndex++;
tableArray.push(rowArray); // 添加当前行到表格数组
}
tableArray.push(rowArray.filter(item => item !== null));
}
allTables.push(tableArray);
allTables.push(tableArray); // 添加当前表格到所有表格数组
}
console.log("解析后的二维数组:", allTables);
callback(allTables);
callback(allTables); // 返回处理后的 HTML
} catch (error) {
console.error("解析 Word 文件失败:", error);
callback([]);
return [];
}
},
// async extractWordTablesToArrays(file, callback) {
// const namespace = "http://schemas.openxmlformats.org/wordprocessingml/2006/main";
// try {
// const Zip = new JSZip();
// // 解压 ZIP
// const zip = await Zip.loadAsync(file);
// // **检查解压的文件列表**
// console.log("解压后的文件:", Object.keys(zip.files));
// const documentFile = zip.file("word/document.xml");
// if (!documentFile) {
// console.error("❌ 找不到 word/document.xml无法解析 Word 文件");
// return;
// }
// const documentXml = await documentFile.async("string");
// const parser = new DOMParser();
// const documentDoc = parser.parseFromString(documentXml, "application/xml");
// // **打印 XML 结构以检查表格**
// console.log("解析的 XML 结构:", new XMLSerializer().serializeToString(documentDoc));
// // **检查 word/numbering.xml 是否存在**
// const numberingFile = zip.file("word/numbering.xml");
// let numberingMap = {};
// if (numberingFile) {
// const numberingXml = await numberingFile.async("string");
// const numberingDoc = parser.parseFromString(numberingXml, "application/xml");
// numberingMap = parseNumbering(numberingDoc); // 解析编号信息
// } else {
// console.warn("⚠️ word/numbering.xml 不存在,跳过编号解析");
// }
// const tables = documentDoc.getElementsByTagNameNS(namespace, "tbl");
// const allTables = []; // 存储所有表格的二维数组
// if (!tables || tables.length === 0) {
// console.warn("未找到表格内容,请检查 XML 结构");
// return [];
// }
// for (const table of tables) {
// const prevParagraph = table.previousElementSibling;
// if (prevParagraph) {
// console.log(`表格前的段落: ${prevParagraph.textContent}`);
// }
// const rows = table.getElementsByTagNameNS(namespace, "tr");
// const tableArray = []; // 当前表格的二维数组
// for (const row of rows) {
// const cells = row.getElementsByTagNameNS(namespace, "tc");
// const rowArray = []; // 当前行的数据
// // 存储已合并的单元格
// let colSpanInfo = [];
// for (let i = 0; i < cells.length; i++) {
// const cell = cells[i];
// let cellText = "";
// // const paragraphs = cell.getElementsByTagNameNS(namespace, "p");
// const paragraphs = cell.getElementsByTagName("w:p");
// // 检查合并单元格属性
// const gridSpan = cell.getElementsByTagNameNS(namespace, "gridSpan")[0];
// const vMerge = cell.getElementsByTagNameNS(namespace, "vMerge")[0];
// // 获取合并信息
// let colspan = gridSpan ? parseInt(gridSpan.getAttribute("w:val"), 10) : 1;
// let rowspan = 1;
// if (vMerge && vMerge.getAttribute("w:val") === "restart") {
// rowspan = 4; // 假设合并两行
// } else if (vMerge && !vMerge.getAttribute("w:val")) {
// continue; // 如果是合并单元格的继续部分,则跳过
// }
// // 处理单元格内容
// // let cellText = "";
// // 为当前单元格初始化计数器
// const currentLevelNumbers = {};
// for (const paragraph of paragraphs) {
// // 提取段落编号
// let listPrefix = "";
// const numPr = paragraph.getElementsByTagName("w:numPr")[0];
// if (numPr) {
// console.log('numPr at line 54:', numPr)
// const numIdElement = numPr.getElementsByTagName("w:numId")[0];
// console.log('numIdElement at line 56:', numIdElement)
// const ilvlElement = numPr.getElementsByTagName("w:ilvl")[0];
// console.log('ilvlElement at line 58:', ilvlElement)
// if (numIdElement && ilvlElement) {
// const numId = numIdElement.getAttribute("w:val");
// const ilvl = ilvlElement.getAttribute("w:val");
// listPrefix = this.getListNumber(numId, ilvl, numberingMap, currentLevelNumbers);
// }
// }
// // 初始化当前段落文本
// let paragraphText = listPrefix ? `${listPrefix} ` : "";
// const runs = paragraph.getElementsByTagName("w:r");
// for (const run of runs) {
// let textContent = "";
// const texts = run.getElementsByTagName("w:t");
// for (const text of texts) {
// textContent += text.textContent;
// }
// // 检查格式
// const rPr = run.getElementsByTagName("w:rPr")[0];
// let formattedText = textContent;
// if (rPr) {
// const bold = rPr.getElementsByTagName("w:b").length > 0;
// const italic = rPr.getElementsByTagName("w:i").length > 0;
// const vertAlignElement = rPr.getElementsByTagName("w:vertAlign")[0];
// if (bold) {
// formattedText = `<b>${formattedText}</b>`;
// }
// if (italic) {
// formattedText = `<i>${formattedText}</i>`;
// }
// if (vertAlignElement) {
// const vertAlign = vertAlignElement.getAttribute("w:val");
// if (vertAlign === "superscript") {
// formattedText = `<sup>${formattedText}</sup>`;
// } else if (vertAlign === "subscript") {
// formattedText = `<sub>${formattedText}</sub>`;
// }
// }
// }
// // 替换负号
// formattedText = replaceNegativeSign(formattedText);
// // 首字母大写
// formattedText = capitalizeFirstLetter(formattedText);
// // 添加蓝色标签
// const regex = /\[(\d+(?:\d+)?(?:, ?\d+(?:\d+)?)*)\]/g;
// formattedText = formattedText.replace(/<blue>/g, '').replace(/<\/blue>/g, ''); // 先去掉所有的 <blue> 标签
// if (regex.test(formattedText)) {
// formattedText = formattedText.replace(regex, function (match) {
// // 提取出方括号中的内容,并进行匹配
// const content = match.slice(1, match.length - 1); // 去掉方括号
// // 判断是否符合条件,纯数字、逗号后有空格、连字符
// if (/^\d+$/.test(content) || /, ?/.test(content) || //.test(content)) {
// return `<blue>${match}</blue>`; // 如果符合条件则加上蓝色标签
// }
// return match; // 如果不符合条件,则保持原样
// });
// }
// console.log("After replacement:", formattedText); // 调试:查看替换后的文本
// paragraphText += formattedText;
// }
// // 处理换行符
// const breaks = paragraph.getElementsByTagName("w:br");
// for (const br of breaks) {
// paragraphText += "<br>";
// }
// cellText += paragraphText; // 将段落文本添加到单元格文本
// }
// // 更新合并单元格的信息
// if (colSpanInfo[i]) {
// colspan = colSpanInfo[i].colspan;
// }
// // 保存当前单元格信息
// rowArray.push({
// text: cellText,
// colspan: colspan,
// rowspan: rowspan
// });
// // 记录跨列合并
// if (colspan > 1) {
// for (let j = 1; j < colspan; j++) {
// colSpanInfo[i + j] = { colspan: 0 }; // 用 0 填充后续的列合并
// }
// }
// }
// tableArray.push(rowArray); // 添加当前行到表格数组
// }
// allTables.push(tableArray); // 添加当前表格到所有表格数组
// }
// console.log("解析后的二维数组:", allTables);
// callback(allTables); // 返回处理后的 HTML
// } catch (error) {
// console.error("解析 Word 文件失败:", error);
// return [];
// }
// },
transformHtmlString(inputHtml) {
inputHtml = inputHtml.replace(/(<[^>]+) style="[^"]*"/g, '$1'); // 移除style属性
inputHtml = inputHtml.replace(/(<[^>]+) class="[^"]*"/g, '$1'); // 移除class属性
// inputHtml = inputHtml.replace(/(<[^>]+) style="[^"]*"/g, '$1'); // 移除style属性
// inputHtml = inputHtml.replace(/(<[^>]+) class="[^"]*"/g, '$1'); // 移除class属性
// inputHtml = inputHtml.replace(/<([a-zA-Z0-9]+)[^>]*>/g, '<$1>'); // 删除标签上的所有属性
inputHtml = inputHtml.replace(/<([a-zA-Z0-9]+)([^>]*)>/g, function (match, tag, attributes) {
// 使用正则表达式删除属性(保留 data-latex
let updatedAttributes = attributes.replace(/\s([a-zA-Z0-9-]+)(="[^"]*")?/g, function (attrMatch, attrName) {
// 只保留 data-latex 属性,其他属性删除
if (attrName === "data-latex") {
return attrMatch;
}
return ''; // 删除其他属性
});
// 返回标签,保留 data-latex 属性
return `<${tag}${updatedAttributes}>`;
});
// 2. 删除所有不需要的标签 (除 `strong`, `em`, `sub`, `sup`, `b`, `i` 外的所有标签)
inputHtml = inputHtml.replace(/<(?!\/?(strong|em|sub|sup|b|i|blue|wmath))[^>]+>/g, ''); // 删除不需要的标签
inputHtml = inputHtml.replace(/<(?!\/?(strong|em|sub|sup|b|i))[^>]+>/g, ''); // 删除不需要的标签
// 3. 如果有 `<strong>` 和 `<em>` 标签,去掉内部样式并保留内容
inputHtml = inputHtml.replace(/<span[^>]*>/g, '').replace(/<\/span>/g, ''); // 去除span标签
@@ -744,79 +344,26 @@ export default {
},
cleanAndParseWordContent(content) {
// 1⃣ 解析成 <p> 段落数组
let tempDiv = document.createElement('div');
tempDiv.innerHTML = content; // 解析 HTML 内容
let paragraphs = tempDiv.querySelectorAll("p"); // 选取所有 <p> 作为数据项
// 2⃣ 将 <p> 内容转换为数组,并处理内容
let parsedData = Array.from(paragraphs).map(p => {
let text = p.innerHTML.trim(); // 获取内容,去除两端空格
text = this.transformHtmlString(text)
// 3⃣ **正确移除 <o:p>Word 复制的无效标签)**
text = text.replace(/<\/?o:p[^>]*>/g, "");
// 4⃣ **移除所有 style="..."**
text = text.replace(/\s*style="[^"]*"/gi, "");
// 5⃣ **修正标签替换**
text = text.replace(/<strong>/gi, "<b>").replace(/<\/strong>/gi, "</b>");
text = text.replace(/<em>/gi, "<i>").replace(/<\/em>/gi, "</i>");
// 6⃣ **移除空的 span、b、i 标签**
text = text.replace(/<span>\s*<\/span>/gi, "");
text = text.replace(/<b>\s*<\/b>/gi, "");
text = text.replace(/<i>\s*<\/i>/gi, "");
// 7⃣ **确保不移除半个标签(修复匹配规则)**
text = text.replace(/<[^\/>]+>\s*<\/[^>]+>/gi, match => {
return match.trim() === "" ? "" : match;
});
// 8⃣ **返回最终内容**
return text.trim() === "" ? "" : text;
});
console.log(parsedData); // 输出数组,方便调试
return parsedData;
}
,
async parseTableToArray(tableString, callback) {
parseTableToArray(tableString, callback) {
const parser = new DOMParser();
const doc = parser.parseFromString(tableString, 'text/html');
const rows = doc.querySelectorAll('table tr'); // 获取所有的行(<tr>
// 使用 Promise 来处理异步的 MathJax 解析
const result = await Promise.all(
Array.from(rows).map(async (row) => {
callback(Array.from(rows).map(row => {
const cells = row.querySelectorAll('th, td'); // 获取每个行中的单元格(包括 <th> 和 <td>
return await Promise.all(
Array.from(cells).map(async (cell) => {
const text = await this.extractMathJaxLatex(cell);
return {
text,
return Array.from(cells).map(cell => ({
text: this.extractContentWithoutOuterSpan(cell),
colspan: cell.getAttribute('colspan') ? parseInt(cell.getAttribute('colspan')) : 1, // 提取 colspan默认值为 1
rowspan: cell.getAttribute('rowspan') ? parseInt(cell.getAttribute('rowspan')) : 1 // 提取 rowspan默认值为 1
};
})
);
})
);
console.log('result at line 78611:', result)
callback(result)
// 返回处理后的数组
}));
}));
},
parseNumbering(numberingDoc) {
const numberingMap = new Map();
if (!numberingDoc) return numberingMap;
@@ -1605,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) {
@@ -1651,7 +1242,7 @@ export default {
}
});
ed.ui.registry.addButton('addRow', {
icon: 'duplicate-row',
icon:'duplicate-row',
text: 'Add Row', // 下拉框标题
onAction: function () {
var edSelection = ed.selection;
@@ -1711,7 +1302,7 @@ export default {
emTags[i].parentNode.replaceChild(iTag, emTags[i]);
}
content = div.innerHTML;
console.log('content at line 486:', content);
vueInstance.$emit('saveContent', content, dataId);
}
}
@@ -1801,8 +1392,6 @@ export default {
}
}
});
ed.ui.registry.addButton('commentAdd', {
icon: 'comment-add',
text: 'Comment Add',
@@ -1931,7 +1520,6 @@ export default {
}
});
ed.ui.registry.addButton('customBlue', {
text: 'Blue', // 按钮文本
className: 'custom-button-blue', // 添加自定义类
@@ -1948,112 +1536,6 @@ export default {
}
}
});
let latexEditorBookmark = null; // 用于记录插入点
let activeEditorId = null; // 当前激活的编辑器 ID
// 在编辑器工具栏中添加 "LateX" 按钮
ed.ui.registry.addButton('LateX', {
text: 'LateX', // 按钮文本
onAction: function () {
// 1. 获取当前光标位置
const latexEditorBookmark = ed.selection.getBookmark(2); // 获取光标位置
const editorId = ed.id; // 保存当前编辑器 ID
console.log('activeEditorId:', editorId);
// 2. 生成一个随机的 ID用于 wmath 标签
const uid = 'wmath-' + Math.random().toString(36).substr(2, 9);
// 3. 创建一个 <wmath> 标签并插入到光标处
const wmathHtml = `<wmath contenteditable="false" data-id="${uid}" data-latex=""></wmath>`;
ed.insertContent(wmathHtml); // 在光标位置插入 wmath 标签
// 4. 打开公式编辑器窗口,并传递光标位置、编辑器 ID 和 wmathId
const url = `/LateX?editorId=${editorId}&wmathId=${uid}`;
// vueInstance.openLatexEditor({
// editorId:editorId,
// wmathId:uid,
// });
window.open(url, '_blank', 'width=1000,height=800,scrollbars=no,resizable=no');
}
});
ed.ui.registry.addButton('myuppercase', {
text: 'A', // 按钮文本
onAction: function () {
// 在选中的文本周围包裹 <blue> 标签
var selectedText = ed.selection.getContent({ format: 'html' });
// 确保选中的文本是单个单词,包括空格
if (selectedText.trim() && /^[\s\w]+$/.test(selectedText)) {
// 使用正则将选中的文本中的第一个字母大写
var capitalizedText = selectedText.replace(/(^|\s)([a-zA-Z])/g, function (match, p1, p2) {
return p1 + p2.toUpperCase();
});
// 替换选中的文本,保持空格和其他内容
ed.selection.setContent(capitalizedText);
} else {
vueInstance.$message.error(vueInstance.$t('commonTable.selectWord'));
}
}
});
ed.ui.registry.addButton('myuppercase', {
text: 'A', // 按钮文本
onAction: function () {
// 在选中的文本周围包裹 <blue> 标签
var selectedText = ed.selection.getContent({ format: 'html' });
// 确保选中的文本是单个单词,包括空格
if (selectedText.trim() && /^[\s\w]+$/.test(selectedText)) {
// 使用正则将选中的文本中的第一个字母大写
var capitalizedText = selectedText.replace(/(^|\s)([a-zA-Z])/g, function (match, p1, p2) {
return p1 + p2.toUpperCase();
});
// 替换选中的文本,保持空格和其他内容
ed.selection.setContent(capitalizedText);
} else {
vueInstance.$message.error(vueInstance.$t('commonTable.selectWord'));
}
}
});
ed.ui.registry.addButton('myuppercasea', {
text: 'a', // 按钮文本(小写字母)
onAction: function () {
// 获取选中的文本,保留 HTML 格式
var selectedText = ed.selection.getContent({ format: 'html' });
// 确保选中的文本是单个有效的单词,包括空格
if (selectedText.trim() && /^[\s\w]+$/.test(selectedText)) {
// 使用正则将选中的文本中的第一个字母转换为小写
var lowercasedText = selectedText.replace(/(^|\s)([a-zA-Z])/g, function (match, p1, p2) {
return p1 + p2.toLowerCase();
});
// 替换选中的文本,保持空格和其他内容
ed.selection.setContent(lowercasedText);
} else {
vueInstance.$message.error(vueInstance.$t('commonTable.selectWord'));
}
}
});
ed.ui.registry.addButton('Line', {
text: '', // 按钮文本
onAction: function () {
// 插入 `` 符号到当前光标位置
ed.insertContent('');
}
});
ed.ui.registry.addButton('removeBlue', {
text: 'Blue', // 按钮文本
onAction: function () {

View File

@@ -1,7 +1,6 @@
<template>
<div class="wrapper">
<template v-if="!this.$route.meta.hideTitle"
><template v-if="!this.$route.meta.hideSidebar">
<template v-if="!this.$route.meta.hideSidebar">
<v-head></v-head>
<v-sidebar></v-sidebar>
@@ -19,24 +18,14 @@
</template>
<template v-else>
<v-head2 :home="true"></v-head2>
<div style="width: 100%; height: calc(100% - 62px); overflow: hidden">
<div class="content" style="padding: 0; overflow: hidden">
<div style="width: 100%;height: calc(100% - 62px);overflow: hidden;">
<div class="content" style="padding: 0;overflow: hidden;">
<!-- <transition name="move" mode="out-in"> -->
<!-- <keep-alive :include="tagsList"> -->
<router-view></router-view>
<!-- </keep-alive> -->
<!-- </transition> -->
<el-backtop target=".content"></el-backtop>
</div>
</div>
</template>
</template>
<template v-else>
<div style="width: 100%; ">
<div class="content" style="padding: 0; overflow: hidden">
<router-view></router-view>
<el-backtop target=".content"></el-backtop>
</div>
</div>

View File

@@ -380,7 +380,6 @@ const en = {
reContent:'Are you sure you want to restore this content?',
uploadImageInfo:'Figures can only upload files in JPG, JPEG, and PNG formats!',
selectComment:'Please select the text to add annotations to!',
selectWord:'Please select only a single word',
alreadyCommented:'There are already annotations in the text, please select again!'
},
pendingPayment:{
@@ -412,16 +411,6 @@ Information:'Fill in information',
},
Formula:{
FormulaTemplate:'Formula Template'
},
AI: {
AISummaryAnalysis: 'AI analysis',
AIKeywords: 'Keywords',
AIAbstract: 'Abstract',
AIAbstractInfo: 'Analysis Result',
}
}

View File

@@ -373,7 +373,6 @@ const zh = {
reContent: '确定要恢复这条内容吗?',
uploadImageInfo: 'Figures 只能上传 JPG、JPEG 和 PNG 格式的文件',
selectComment: '请选择要添加批注的文本',
selectWord:'请只选中单个单词!',
alreadyCommented:'文本中已有批注内容请重新选择',
},
pendingPayment: {
@@ -405,15 +404,6 @@ const zh = {
},
Formula:{
FormulaTemplate:'公式模版'
},
AI:{
AISummaryAnalysis:'AI分析',
AIKeywords:'关键词',
AIAbstract:'摘要',
AIAbstractInfo:'分析结果',
},
}

File diff suppressed because it is too large Load Diff

View File

@@ -73,7 +73,7 @@
</common-word-html-type-setting>
</div>
</div>
<div style="width: 100%; width: calc(100% - 285px); float: right; height: calc(100% - 0px); background-color: #e4e9ed">
<div style="width: 100%; width: calc(100% - 285px); float: right; height: calc(100%); background-color: #e4e9ed">
<!-- <div class="toolbar">
<div class="toolbar_item" @click="handleImageAdd('img')">
<img src="@/assets/img/upload.png" style="object-fit: contain" />
@@ -94,14 +94,12 @@
:comments="comments"
:wordStyle="wordStyle"
@onDrop="onDrop"
@onSort="onSort"
@saveContent="saveContent"
@editComment="editComment"
@loaded="loadedWord"
@onEdit="onEdit"
@addContent="onAddContent"
@changeSort="changeSort"
@onDelete="onDelete"
@onDeletes="onDeletes"
@refresh="onRefresh"
@onComment="onComment"
@onAddComment="onAddComment"
@@ -151,7 +149,6 @@
:isAutomaticUpdate="true"
:value="picStyle.note"
@getContent="getContent"
@openLatexEditor="openLatexEditor"
v-if="pictVisible"
@updateChange="(res) => updateChange(res, 'imgNote')"
:height="120"
@@ -171,27 +168,22 @@
</el-dialog>
<!-- 添加表格 -->
<el-drawer
title="我嵌套了表格!"
<el-dialog
class="editTableDialog"
destroy-on-close
v-if="threeVisible"
:title="lineStyle.visiTitle"
:visible.sync="threeVisible"
:wrapperClosable="false"
width="1200px"
:close-on-click-modal="false"
direction="rtl"
size="70%"
>
<el-form ref="editMes" :model="lineStyle" label-width="80px">
<!-- <common-late-x></common-late-x> -->
<el-form-item label="Title:">
<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"
@openLatexEditor="openLatexEditor"
v-if="threeVisible"
@updateChange="(res) => updateChange(res, 'title')"
:height="120"
@@ -202,42 +194,35 @@
<el-form-item label="Word">
<span slot="label">
<font style="color: #f56c6c; margin-right: 5px">*</font>
Table:
Table :
</span>
<common-table
@getContent="getContent"
v-if="threeVisible"
ref="commonTable"
@openLatexEditor="openLatexEditor"
style="margin-left: -115px"
:lineStyle="lineStyle"
></common-table>
</el-form-item>
<el-form-item label="Note:">
<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"
@openLatexEditor="openLatexEditor"
v-if="threeVisible"
@updateChange="(res) => updateChange(res, 'note')"
:height="120"
ref="tinymceChildNote"
style="margin-left: -115px"
></common-content>
</el-form-item>
</el-form>
<p style="margin-top: 20px; text-align: right">
<p style="margin: 20px 0; text-align: right">
<el-button @click="threeVisible = false"> Cancel </el-button>
<el-button
type="primary"
plain
@click="handleSaveTable"
style="background-color: #006699 !important; background: #006699 !important; margin-right: 20px; color: #fff !important"
>
save Table
</el-button>
<el-button type="primary" plain @click="handleSaveTable"> save Table </el-button>
</p>
</el-drawer>
</el-dialog>
<el-dialog
destroy-on-close
v-if="commentVisible"
@@ -248,10 +233,9 @@
>
<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"
v-html="commentForm.content"
></p>
<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">
<span slot="label">
@@ -295,7 +279,6 @@
<common-content
:value="currentContent.content"
@getContent="getContent"
@openLatexEditor="openLatexEditor"
v-if="editVisible"
ref="commonContent"
style="margin-left: -115px"
@@ -311,40 +294,6 @@
</el-button>
</span>
</el-dialog>
<el-dialog
destroy-on-close
v-if="addContentVisible"
title="Add Content"
:visible.sync="addContentVisible"
width="1200px"
:close-on-click-modal="false"
>
<el-form ref="editMes" :model="addContent" label-width="115px">
<el-form-item label="Word">
<span slot="label">
<font style="color: #f56c6c; margin-right: 5px">*</font>
Content :
</span>
<common-content
:value="addContent.content"
@getContent="getContent"
@openLatexEditor="openLatexEditor"
v-if="addContentVisible"
ref="addContent"
style="margin-left: -115px"
></common-content>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="editVisible = false"> Cancel </el-button>
<el-button type="primary" @click="handleSaveAddContent">
<!-- <i class="el-icon-finished" style="margin-right: 5px"></i> -->
Save
</el-button>
</span>
</el-dialog>
<common-late-x v-if="showLateX" @close="showLateX = false" @save="saveLateX" :LateXInfo="LateXInfo"></common-late-x>
</div>
</template>
@@ -358,9 +307,7 @@ import bottomTinymce from '@/components/page/components/Tinymce';
export default {
data() {
return {
LateXInfo: {},
isEditComment: false,
showLateX: false,
comments: [],
remarkImageUrl: 'https://submission.tmrjournals.com/public/usericon/20241222/4e77ba3f29ce3cf798b36f24dc411b76.png',
isFirstComponentLoaded: false,
@@ -454,8 +401,6 @@ export default {
ChGtpTxt: ''
},
txtVisible: false,
addContentVisible: false,
addContent: {},
lineStyle: {},
contentStyle: {},
lineTable: [],
@@ -515,11 +460,6 @@ export default {
},
methods: {
openLatexEditor(data) {
console.log('data at line 563:', data);
this.showLateX = true;
this.LateXInfo=data
},
isShowEditComment() {
if (localStorage.getItem('U_role')) {
var identity = localStorage.getItem('U_role');
@@ -555,17 +495,21 @@ export default {
handleSaveContent() {
this.$refs.commonContent.getTinymceContent('content');
},
handleSaveAddContent() {
this.$refs.addContent.getTinymceContent('addcontent');
},
async getContent(type, content) {
console.log('content at line 539:', content);
if (type == 'content') {
content = this.$commonJS.transformHtmlString(content);
console.log('content at line 604:', content);
// 使用正则表达式移除所有不允许的标签
// 1. 移除不允许的标签
content = content.replace(/<(?!\/?(img|b|i|sub|sup|span|strong|em |blue)\b)[^>]+>/g, '');
// 2. 移除所有 style 属性
content = content.replace(/\s*style="[^"]*"/g, '');
// 3. 将 <strong> 转换为 <b><em> 转换为 <i>
var div = document.createElement('div');
div.innerHTML = content; // 将 HTML 字符串加载到 div 中
// 替换所有 <strong> 为 <b>
var strongTags = div.getElementsByTagName('strong');
for (var i = 0; i < strongTags.length; i++) {
@@ -573,6 +517,7 @@ export default {
bTag.innerHTML = strongTags[i].innerHTML; // 保留内容
strongTags[i].parentNode.replaceChild(bTag, strongTags[i]);
}
// 替换所有 <em> 为 <i>
var emTags = div.getElementsByTagName('em');
for (var i = 0; i < emTags.length; i++) {
@@ -583,76 +528,24 @@ export default {
// 获取最终修改后的 HTML
content = div.innerHTML;
console.log('content at line 486:', content);
// // 4. 去除多余的空格:替换连续的空格、换行符、制表符等
// content = content.replace(/\s+/g, ' ').trim(); // 将多个空白字符替换为一个空格,并去除前后空白
// // 5. 去除标签之间的空格
// content = content.replace(/>\s+</g, '><'); // 去除标签之间的空格
// 6. 如果需要,还可以去除 <span> 标签内部的空格
// content = content.replace(/<span[^>]*>\s*([^<]+)\s*<\/span>/g, '<span>$1</span>'); // 清理 <span> 标签内部的空格
this.saveContent(content, this.currentContent.am_id);
} else if (type == 'addcontent') {
var hasTable = /<table[\s\S]*?>[\s\S]*?<\/table>/i.test(content);
if (hasTable) {
this.$message({
type: 'warning',
message: 'Table content is not supported!'
});
return false;
}
var list = this.$commonJS.cleanAndParseWordContent(content);
console.log('list at line 569:', list);
this.saveContentList(list, this.currentId);
} else if (type == 'table') {
this.saveTable(content);
} else if (type == 'comment') {
this.addComment(content);
}
},
async saveContent(content, am_id) {
var that = this;
var str = content.replace(/^<p>\s*(.*?)\s*<\/p>$/, '$1').trim();
// var str = content.replace(/^<p>(.*?)<\/p>$/, '$1') ? content.replace(/^<p>(.*?)<\/p>$/, '$1') : '';
console.log('str at line 580:', JSON.stringify(str));
// if (str == '') {
// this.$message({
// type: 'warning',
// message: 'Please enter the content!'
// });
// }
str = await that.$commonJS.decodeHtml(str);
await that.$api
.post(that.urlList.editContent, {
am_id: am_id,
content: str
})
.then(async (res) => {
if (res.code == 0) {
this.editVisible = false;
this.getDate();
this.getCommentList();
}
});
},
async saveContentList(content, am_id) {
if (content.length == 0) {
this.$message({
type: 'warning',
message: 'Please enter the content!'
});
}
await this.$api
.post('api/Preaccept/addMoreRow', {
article_id: this.articleId,
am_id: am_id,
rows: content
})
.then(async (res) => {
if (res.code == 0) {
this.addContentVisible = false;
this.getDate();
this.getCommentList();
}
});
},
deleteComment(comment, index) {
console.log('comment at line 480:', comment);
if (this.isEditComment) {
@@ -679,30 +572,27 @@ export default {
.catch(() => {});
}
},
saveLateX(data) {
console.log('data at line 735:', data)
const { editorId, wmathId, latex } = data;
const newLatex = latex ? latex.trim() : '';
if (!editorId || !wmathId) return;
const targetEditor = tinymce.get(editorId);
if (!targetEditor) return;
const targetWmath = targetEditor.dom.select(`wmath[data-id="${wmathId}"]`, targetEditor.getBody())[0];
if (targetWmath) {
if (!newLatex) {
// ❌ 删除公式
targetEditor.dom.remove(targetWmath);
} else {
// ✅ 更新公式
targetWmath.setAttribute('data-latex', newLatex);
targetWmath.innerHTML = newLatex;
setTimeout(() => {
if (typeof renderMathJax === 'function') {
this.window.renderMathJax(editorId);
}
}, 10);
async saveContent(content, am_id) {
var that = this;
var str = content.replace(/^<p>(.*?)<\/p>$/, '$1') ? content.replace(/^<p>(.*?)<\/p>$/, '$1') : '';
if (str == '') {
this.$message({
type: 'warning',
message: 'Please enter the content!'
});
}
await that.$api
.post(that.urlList.editContent, {
am_id: am_id,
content: str
})
.then(async (res) => {
if (res.code == 0) {
this.editVisible = false;
this.getDate();
this.getCommentList();
}
});
},
async huifu(id) {
var that = this;
@@ -740,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;
},
@@ -833,56 +738,6 @@ export default {
console.log('err at line 466:', err);
});
},
async onDeletes(dataId) {
await this.$confirm(this.$t('commonTable.removeContent'), 'Prompt', {
confirmButtonText: 'Submit',
cancelButtonText: 'Cancel',
type: 'warning'
})
.then(async () => {
var that = this;
await that.$api
.post('/api/Preaccept/delMoreArticleMains', {
ids: dataId
})
.then(async (res) => {
if (res.code == 0) {
setTimeout(() => {
that.getDate();
that.getCommentList();
that.$refs.commonWordHtmlTypeSetting.refresh('img');
that.$refs.commonWordHtmlTypeSetting.refresh('table');
that.$forceUpdate();
});
}
});
// this.Main_List.splice(
// this.Main_List.findIndex((item) => item.p_main_id == dataId),
// 1
// );
})
.catch((err) => {
console.log('err at line 466:', err);
});
},
async changeSort(type, id) {
var that = this;
await that.$api
.post(type == 'up' ? '/api/Preaccept/upArticleMain' : '/api/Preaccept/downArticleMain', {
am_id: id
})
.then(async (res) => {
if (res.code == 0) {
setTimeout(() => {
that.getDate();
that.getCommentList();
that.$forceUpdate();
});
}
});
},
async addCommentSetting(content) {
console.log('content at line 602:', content);
await this.$api
@@ -1021,9 +876,6 @@ export default {
async onEditTitle(data) {
var url;
switch (data.value) {
case 0:
url = 'api/Preaccept/changeNormal';
break;
case 1:
url = 'api/Preaccept/changeH1';
break;
@@ -1136,8 +988,6 @@ export default {
}
},
updateChange(content, type) {
console.log('content at line 1154:', content);
// console.log('content at line 976:', content);
var str = this.$commonJS.transformHtmlString(content);
if (type == 'imgNote') {
this.picStyle.note = str;
@@ -1180,19 +1030,11 @@ export default {
this.lineStyle.visiTitle = 'Edit Table';
this.threeVisible = true;
} else {
data.content = data.content.replace(/<span[^>]*>/g, '').replace(/<\/span>/g, ''); // 去除span标签
this.currentContent = data;
this.editVisible = true;
this.currentId = dataId;
}
},
onAddContent(dataId) {
this.addContentVisible = true;
this.addContent = {};
this.currentId = dataId;
},
async onDrop(event, dataId) {
if (event.dataTransfer.getData('image')) {
const draggedImage = JSON.parse(event.dataTransfer.getData('image'));
@@ -1511,16 +1353,15 @@ export default {
},
// 确定保存图片
async savePic() {
savePic() {
this.picStyle.picUrl;
var str = this.picStyle.note;
str = await this.$commonJS.decodeHtml(str);
if (this.picStyle.visiTitle == 'Edit Figure') {
this.$api
.post(this.urlList.editImage, {
ami_id: this.picStyle.ami_id,
url: this.picStyle.picUrl,
note: str
note: this.picStyle.note
})
.then((res) => {
if (res.code == 0) {
@@ -1572,31 +1413,18 @@ export default {
this.$refs.tinymceChildComment.getContent('comment');
});
},
async saveTable(content) {
saveTable(content) {
console.log('content at line 998:', content);
var strTitle = this.lineStyle.title;
strTitle = await this.$commonJS.decodeHtml(strTitle);
var strNote = this.lineStyle.note;
if (strNote != '') {
strNote = await this.$commonJS.decodeHtml(strNote);
}
if (content && content.table && content.table.length > 0) {
if (this.lineStyle.visiTitle == 'Edit Table') {
const loading = this.$loading({
lock: true,
text: 'Loading...',
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)'
});
this.$api
.post(this.urlList.editTable, {
amt_id: this.lineStyle.amt_id,
table_data: JSON.stringify(content.table),
html_data: content.html_data,
note: strNote,
title: strTitle
note: this.lineStyle.note,
title: this.lineStyle.title
})
.then((res) => {
if (res.code == 0) {

View File

@@ -286,8 +286,7 @@ export default {
// username: this.query.username
})
.then(async (res) => {
this.jourList = res.data.journals;
console.log('this.jourList at line 289:', this.jourList)
this.jourList = res;
// this.currentJournal = this.jourList[0];
await this.getDate();
})
@@ -486,7 +485,7 @@ export default {
var that = this;
// this.currentJournalStage = data;
this.detailForm = {
issn: this.journal.issn,
issn: this.currentJournal.issn,
// stage_icon: '11.jpg',
// stage_icon: data.stage_icon,
@@ -497,14 +496,12 @@ export default {
// issue_date: data.issue_date,
// stage_icon: data.stage_icon
};
console.log('this.detailForm at line 487:', this.detailForm)
this.editDialogVisible1 = true;
// this.$nextTick(() => {
// that.$refs.commonClassRef.init();
// });
},
openJournalAgreement(data) {
console.log('data at line 505:', data)
var that = this;
this.currentJournal = data;
this.drawerAgreement = true;

View File

@@ -215,7 +215,7 @@
localStorage.setItem('U_role', 'superadmin');
localStorage.setItem('U_name', res.userinfo.account);
localStorage.setItem('U_id', res.userinfo.user_id);
// localStorage.setItem('U_id', res.userinfo.admin_id);
this.$router.push('/');
} else if (res.data.roles.includes('editor')) {
localStorage.setItem('U_status', '1'); //编辑

View File

@@ -1,6 +1,6 @@
<template>
<div>
<div class="tab_post" >
<div class="tab_post">
@@ -97,7 +97,7 @@
<!-- 文章正文 -->
<!-- 参考文献 -->
<div :ref="tabsList[0].refName" class="scroll-item" >
<div :ref="tabsList[0].refName" class="scroll-item">
<div class="bor_style_onli">
<h4>{{ tabsList[0].name }}</h4>
<div class="liter_ture" v-if="0 == 2">
@@ -404,7 +404,6 @@ import { quillEditor } from 'vue-quill-editor';
import { Loading } from 'element-ui';
import timetalk from './time_talk';
export default {
props:['type'],
data() {
return {
feeStatus: null,

File diff suppressed because it is too large Load Diff

View File

@@ -92,10 +92,6 @@
<li>
<p>- If you want to discard all references and import a new batch of reference information, please click <el-button type="text" @click="removeAll">Delete and re-import</el-button>.</p>
</li>
<li >
<p style="display: flex;align-items: center">- Please note that if this status exists, <span > <img src="../../assets/img/repeat.png" alt="" style="width: 24px;height: 24px;margin-left: 5px;margin-right: 5px">
</span> it indicates that the current reference is duplicated .</p>
</li>
<li>
<p>- Please do not forget to recheck all references in the <span class="status ok float" ><i class="el-icon-circle-check"></i></span> status,especially abbreviated journal title.</p>
</li>
@@ -104,15 +100,10 @@
<div class="refenceCentent mt20">
<el-table :data="tableData" ref="multipleTable"
empty-text="New messages (0)" :show-header="false" :stripe="false" :highlight-current-row="false">
<el-table-column type="index" label="No." width="60" align="center">
<template slot-scope="scope" >
<img src="../../assets/img/repeat.png" v-if="scope.row.is_repeat==1" alt="" style="width: 24px;height: 24px;float: left;">
<span>{{scope.$index+1}}</span>
</template>
</el-table-column>
<el-table-column type="index" label="No." width="55" align="center"></el-table-column>
<el-table-column label="state" width="55" align="center">
<template slot-scope="scope">
<span class="status ok" v-if="scope.row.refer_type == 'journal' && scope.row.doilink != '' || scope.row.refer_type == 'book' && scope.row.isbn != '' " >
<span class="status ok" v-if="scope.row.refer_type == 'journal' && scope.row.doilink != '' || scope.row.refer_type == 'book' && scope.row.isbn != '' || scope.row.refer_type == 'other' && scope.row.refer_frag != '' && scope.row.refer_frag.length > 15" >
<i class="el-icon-circle-check"></i>
</span>
<span class="status warn" v-else >

File diff suppressed because it is too large Load Diff

View File

@@ -20,7 +20,7 @@
</div>
<div class="manu_add" style="width: 960px" v-loading="loading">
<el-form ref="articleform" :model="form" :rules="rules" label-width="120px">
<el-form ref="articleform" :model="form" :rules="rules" label-width="160px">
<div class="bag_color" v-if="show_step == 1">
<div>
<h3>Manuscript Information</h3>
@@ -56,9 +56,8 @@
></el-option>
</el-select>
</el-form-item>
<el-form-item label="Research areas :" prop="major" label-width="160px">
<common-major-list :list="majorValueList" @load="(e) => (this.majorValueList = e)"></common-major-list>
<!-- <el-select
<el-form-item label="Major :" :required="true" prop="major_a">
<el-select
v-model="form.major_a"
placeholder="Please select major"
@change="majorChange(1)"
@@ -100,9 +99,9 @@
:label="item.major_title"
:value="item.major_id"
></el-option>
</el-select> -->
</el-select>
</el-form-item>
<el-form-item label="Manuscript Title :" prop="title" label-width="160px">
<el-form-item label="Manuscript Title :" prop="title">
<el-input v-model="form.title" placeholder="Please enter title"></el-input>
</el-form-item>
<el-form-item label="Whether ethical approval was obtained ?" prop="approval" label-width="300px">
@@ -189,19 +188,17 @@
>
</el-input>
</el-form-item>
<el-form-item label="Article Processing Charge :" v-if="form.journal != 0" label-width="180px">
<el-form-item label="Article Processing Charge :" v-if="ms_alias == null" label-width="180px">
$ {{ getFee(form.journal) }}
<div style="color: #8c8d8f" v-if="getFee(form.journal) && getFee(form.journal) != '0.00'">
<i class="el-icon-warning" style="color: #517fd5; margin-right: 4px"></i>The article processing fee
applies to papers submitted and ultimately accepted for publication after January 1, 2025. For
authors seeking to apply for fee discounts, please
<a
<div style="color: #8c8d8f"v-if=" getFee(form.journal)&&getFee(form.journal)!='0.00'">
<i class="el-icon-warning" style="color: #517fd5; margin-right: 4px"></i>The article processing fee applies to papers submitted and ultimately accepted for publication after January 1, 2025. For authors seeking to apply for fee discounts, please <a
style="color: rgb(81, 127, 213); cursor: pointer; text-decoration: underline"
href="https://www.tmrjournals.com/apc/"
target="_blank"
>click here</a
>
to view detailed policies.
> to view detailed policies.
</div>
</el-form-item>
<div style="text-align: center; margin: 40px 0 0 0">
@@ -969,7 +966,6 @@
export default {
data() {
return {
majorValueList: [],
baseUrl: this.Common.baseUrl,
usercap: localStorage.getItem('U_role'),
ms_alias: localStorage.getItem('ms_journal_alias'),
@@ -1010,7 +1006,7 @@ export default {
],
form: {
article_id: 0,
journal: localStorage.getItem('ms_journal_alias') ? parseInt(localStorage.getItem('ms_journal_alias')) : '',
journal: localStorage.getItem('ms_journal_alias') ? parseInt(localStorage.getItem('ms_journal_alias')) : 1,
username: localStorage.getItem('U_name'),
user_id: localStorage.getItem('U_id'),
title: '',
@@ -1200,17 +1196,8 @@ export default {
major: [
{
required: true,
validator: (rule, value, callback) => {
console.log('value at line 1202:', this.form);
var major = this.majorValueList.map((item) => item.selectedValue[item.selectedValue.length - 1]).toString(',');
if (major == '') {
callback(new Error('Please select the Research areas'));
} else {
callback();
}
// 如果你需要在此处使用 this 访问 Vue 实例的数据,使用箭头函数保持上下文
// 其他逻辑
}
message: 'Please select major',
trigger: 'blur'
}
],
abstrart: [
@@ -1462,17 +1449,12 @@ export default {
return false;
}
this.$refs.articleform.validate((valid) => {
if (this.isAbstractTooShort(this.form.abstrart)) {
this.$message.error('The abstract should not be less than 200 Chinese characters or English words!');
return false;
}
//验证文档
if (this.form.manuscirpt == '') {
this.$message.error('Manuscirpt is required');
// console.log('file up error');
return false;
}
//验证作者
let authorlist = this.form.authorList;
let Firsta = 0;
@@ -1513,11 +1495,9 @@ export default {
this.$message.error('First author and corresponding author must be exist');
return false;
}
console.log('this.form.major at line 1512:', this.form.major);
//验证文章领域
this.form.major = this.majorValueList.map((item) => item.selectedValue[item.selectedValue.length - 1]).toString(',');
if (this.form.major == '') {
this.$message.error('Please select the Research areas');
this.$message.error('Major is required');
return false;
}
//验证选择转投但没选期刊项的情况
@@ -1620,17 +1600,7 @@ export default {
},
Submission_of_manuscripts() {
// 提交稿件AI检索
this.$api
// api/Article/addArticle
.post('api/Aireview/review', {
article_id: this.form.article_id,
abstrart: this.form.abstrart,
keywords: this.form.keyWords,
api_model: 'gpt-4o'
})
.then((res) => {});
// 提交稿件
this.$api
// api/Article/addArticle
.post('api/Article/addArticlePart4', this.form)
@@ -2527,27 +2497,10 @@ export default {
this.form.checkedjours = [];
this.form.istransfer = false;
this.form.becomeRev = false;
if (this.$route.query.id) {
this.saveArticle();
}
this.initMajor();
// this.getTopics()
},
saveArticle() {
// api/Article/changeJournal
this.$api
.post('api/Article/changeJournal', {
article_id: this.$route.query.id,
journal_id: this.form.journal
})
.then((res) => {
if (res.code == 0) {
} else {
// this.$message.error(res.msg);
}
});
},
// 点击tab变化
StepCode(e) {
console.log('🚀 ~ StepCode ~ e111:', e);
@@ -2646,20 +2599,9 @@ export default {
// 点击进行下一步
onStep(e) {
console.log('this.majorValueList at line 2604:', this.majorValueList);
console.log('this.form at line 2622:', this.form.abstrart);
this.$refs.articleform.validate((valid) => {
if (valid) {
if (this.isAbstractTooShort(this.form.abstrart)) {
this.$message.error('The abstract should not be less than 200 Chinese characters or English words!');
return false;
}
if (e == 1) {
if (this.form.journal == 0 || !this.form.journal) {
this.$message.error('Please select the Journal');
return false;
}
// this.onStaging(1)
// setTimeout(() => {
// console.log('456')
@@ -2675,14 +2617,6 @@ export default {
}
}
this.form.keyWords = fstr == '' ? '' : fstr.substring(0, fstr.length - 1);
this.form.major = this.majorValueList
.map((item) => item.selectedValue[item.selectedValue.length - 1])
.toString(',');
if (this.form.major == '') {
this.$message.error('Please select the Research areas');
return false;
}
this.$api.post('api/Article/addArticlePart1', this.form).then((res) => {
if (res.code == 0) {
this.stagingID = res.data.article_id;
@@ -2760,12 +2694,7 @@ export default {
onStaging(e) {
var that = this;
console.log('e at line 2584:', e);
console.log('this.form at line 2622:', this.form);
if (e == 1) {
if (this.form.journal == 0 || !this.form.journal) {
this.$message.error('Please select the Journal');
return false;
}
var flist = this.keywordsList;
var fstr = '';
for (var fu in flist) {
@@ -2773,17 +2702,7 @@ export default {
fstr += flist[fu].ke.trim() + ',';
}
}
console.log('this.form at line 2707:', this.form.abstrart);
this.form.keyWords = fstr == '' ? '' : fstr.substring(0, fstr.length - 1);
this.form.major = this.majorValueList.map((item) => item.selectedValue[item.selectedValue.length - 1]).toString(',');
if (this.form.major == '') {
this.$message.error('Please select the Research areas');
return false;
}
if (this.isAbstractTooShort(this.form.abstrart)) {
this.$message.error('The abstract should not be less than 200 Chinese characters or English words!');
return false;
}
this.$api.post('api/Article/addArticlePart1', this.form).then((res) => {
if (res.code == 0) {
this.stagingID = res.data.article_id;
@@ -2900,14 +2819,7 @@ export default {
});
}
},
isAbstractTooShort(text) {
let chineseCount = (text.match(/[\u4e00-\u9fa5]/g) || []).length;
let englishCount = (text.match(/[A-Za-z0-9]/g) || []).length;
const total = chineseCount + englishCount;
return total < 200; // 不足 200说明太短
},
// 读取
Temporary() {
this.$api
@@ -2928,52 +2840,44 @@ export default {
console.log(res.data.base);
// this.form.topics = res.data.base.topics
// 领域
this.majorValueList = res.data.majors.map((item) => ({
selectedValue: Array.isArray(item.major)
? item.major
: typeof item.major === 'string'
? item.major.split(',').map(Number)
: [item.major]
}));
console.log('this.majorValueList at line 2853:', this.majorValueList);
// this.$api
// .post('api/Major/getMajorForAddArticle', {
// journal_id: this.form.journal,
// major_id: 1
// })
// .then((res) => {
// this.majors_a = res.data.majors;
// });
// this.form.major_a = res.data.major.major_id;
// this.$api
// .post('api/Major/getMajorForAddArticle', {
// journal_id: this.form.journal,
// major_id: this.form.major_a
// })
// .then((ref) => {
// this.majors_b = ref.data.majors;
// this.majors_c = [];
// this.form.major_b = '';
// this.form.major_c = '';
// this.majorChange_panduan();
// if (res.data.major.child != undefined) {
// this.form.major_b = res.data.major.child.major_id;
// this.$api
// .post('api/Major/getMajorForAddArticle', {
// journal_id: this.form.journal,
// major_id: this.form.major_b
// })
// .then((ref) => {
// this.majors_c = ref.data.majors;
// this.form.major_c = '';
// this.majorChange_panduan();
// if (res.data.major.child.child != undefined) {
// this.form.major_c = res.data.major.child.child.major_id;
// this.majorChange_panduan();
// }
// });
// }
// });
this.$api
.post('api/Major/getMajorForAddArticle', {
journal_id: this.form.journal,
major_id: 1
})
.then((res) => {
this.majors_a = res.data.majors;
});
this.form.major_a = res.data.major.major_id;
this.$api
.post('api/Major/getMajorForAddArticle', {
journal_id: this.form.journal,
major_id: this.form.major_a
})
.then((ref) => {
this.majors_b = ref.data.majors;
this.majors_c = [];
this.form.major_b = '';
this.form.major_c = '';
this.majorChange_panduan();
if (res.data.major.child != undefined) {
this.form.major_b = res.data.major.child.major_id;
this.$api
.post('api/Major/getMajorForAddArticle', {
journal_id: this.form.journal,
major_id: this.form.major_b
})
.then((ref) => {
this.majors_c = ref.data.majors;
this.form.major_c = '';
this.majorChange_panduan();
if (res.data.major.child.child != undefined) {
this.form.major_c = res.data.major.child.child.major_id;
this.majorChange_panduan();
}
});
}
});
// 关键词
let keyList = res.data.base.keywords.split(',');
this.keywordsList = [];
@@ -3373,30 +3277,26 @@ export default {
}
.jour_ku_all {
font-size: 14px;
font-size: 12px;
float: left;
width: 48%;
width: 265px;
padding-left: 10px;
cursor: pointer;
color: #666;
line-height: 26px;
}
/* .jour_ku_all:nth-child(3n + 1) {
.jour_ku_all:nth-child(3n + 1) {
width: 230px;
}
.jour_ku_all:nth-child(3n + 2) {
width: 220px;
} */
}
.jour_ku_all.B_style {
color: #1161ea;
color: #006699;
font-weight: bold;
font-size: 16px;
background: #ebf5ff;
border-radius: 4px;
/* border: 1px solid #b3d8ff ; */
}
.tally_jour {

View File

@@ -5,12 +5,7 @@
<el-breadcrumb-item> <i class="el-icon-lx-calendar"></i> Manuscript detail </el-breadcrumb-item>
</el-breadcrumb>
</div>
<div class="container_state" v-loading="loading" style="margin: 10px 0 0 0">
<div style="margin-bottom: 10px; margin-top: 0px;overflow: hidden;" v-if="AIcontent!=''">
<img src="@/assets/img/ai.png" style="width: 30px; height: 30px; margin-right: 4px;float: left;margin-top: 10px;" />
<p class="beautiful-gradient"style="float: right;width: calc(100% - 40px);font-size: 13px;line-height: 16px;color: #1d45f2;" >{{ AIcontent }}</p>
</div>
<div class="container_state" v-loading="loading" style="margin: 20px 0 0 0">
<el-row :gutter="30">
<el-col :span="16">
<div class="art_state_">
@@ -113,7 +108,6 @@
</div>
</el-collapse-item>
</el-collapse>
<el-collapse class="auth_colla auth_collna_ew" style="margin-top: -15px">
<el-collapse-item name="2">
<template slot="title">
@@ -132,38 +126,6 @@
</p>
</el-collapse-item>
</el-collapse>
<el-collapse class="auth_colla auth_collna_ew" style="margin-top: -15px">
<el-collapse-item title="Research areas" name="1">
<div style="position: relative; height: 30px">
<common-major
:articleId="editform.articleId"
@load="initMajor()"
style="position: absolute; top: 10px; right: 10px"
></common-major>
</div>
<div style="margin: 12px 20px 30px 0px; line-height: 24px; font-size: 14px; position: relative">
<div>
<!-- 统计数据 -->
<div class="join_link">
<!-- 如果你想投稿 请点击 -->
<p style="" v-for="(v, i) in majorsList">
<span style="color: #006699; font-weight: bold; margin-right: 10px"
>Field {{ i + 1 }}:</span
>{{ v.str
}}<i
class="el-icon-delete-solid"
style="color: #f56c6c !important; margin-left: 10px"
@click="handleDeleteMajor(v)"
></i>
</p>
<!-- 查看已投稿件列表 -->
</div>
</div>
</div>
</el-collapse-item>
</el-collapse>
</div>
<div class="art_file_">
@@ -231,7 +193,7 @@
<i class="el-icon-download download"></i>
</a>
</a> -->
<a v-for="item in manuscirptFileList" :href="mediaUrl + item.file_url">
<a v-for="item in manuscirptFileList" :href="mediaUrl + item.file_url" >
<img src="../../assets/img/icon_0.png" />
<span>
<font>Uploader : </font>{{ form.username }}
@@ -279,8 +241,12 @@
</el-col>
</el-row>
</div>
<common-word-html
:articleId="$route.query.id"
style=" box-sizing: border-box"
<common-word-html :articleId="$route.query.id" style="box-sizing: border-box"></common-word-html>
></common-word-html>
</div>
<!-- 被拒稿件操作 --->
<div class="art_caozuo_" v-if="opname == 'rejectArticles'">
@@ -553,7 +519,6 @@ export default {
},
data() {
return {
AIcontent:'',
previewData: {},
baseUrl: this.Common.baseUrl,
mediaUrl: this.Common.mediaUrl,
@@ -625,10 +590,10 @@ export default {
state: 6,
title: this.$t('artstate.state6')
},
// {
// state: 5,
// title: this.$t('artstate.state5')
// }
{
state: 5,
title: this.$t('artstate.state5')
}
],
form: {
articleId: this.$route.query.id,
@@ -661,7 +626,6 @@ export default {
ad_content: ''
},
talkMsgs: [],
majorsList: [],
opname: '', // 稿件详细类型
editorJournalList: [], // 编辑期刊列表
resubmitJournal: {
@@ -674,7 +638,6 @@ export default {
};
},
created: function () {
this.getAi();
this.initarticle();
this.initFileList();
@@ -810,18 +773,6 @@ export default {
}
},
methods: {
async getAi(){
var that = this;
await this.$api
.post('api/Aireview/get', {
article_id: this.$route.query.id
})
.then(async (res) => {
console.log('res at line 819:', res)
this.AIcontent = res.data.content?res.data.content:'';
});
},
async getWordimgList() {
var that = this;
await this.$api
@@ -854,7 +805,7 @@ export default {
});
},
openDrawer(data, url) {
console.log('url at line 799:', data, url);
console.log('url at line 799:',data, url)
this.previewData = {
...data,
previewUrl: url,
@@ -948,29 +899,7 @@ export default {
return { status: status, msg: msg };
},
handleDeleteMajor(v) {
console.log('v at line 925:', v);
this.$confirm('Are you sure you want to delete this Field ?', 'Tip', {
type: 'warning'
})
.then(() => {
this.$api
.post('api/Major/delMajorByArticleIdForEditor', {
mta_id: v.mta_id
})
.then((res) => {
if (res.code == 0) {
this.initMajor();
} else {
this.$message.error(res.msg);
}
})
.catch((err) => {
this.$message.error(err);
});
})
.catch(() => {});
},
//修改文章状态
async saveEdit() {
if (this.form.state == 0) {
@@ -1019,16 +948,7 @@ export default {
this.$router.go(0);
});
},
initMajor() {
this.$api
.post('api/Major/getMajorByArticleId', {
article_id: this.editform.articleId
})
.then((res) => {
console.log('res at line 978:', res);
this.majorsList = res.data.majors;
});
},
//初始化期刊信息
initarticle() {
this.now_year = new Date().getFullYear();
@@ -1037,9 +957,7 @@ export default {
articleId: this.editform.articleId,
human: 'editor'
})
.then((res) => {
this.initMajor();
this.form.username = res.article.account;
this.form.title = res.article.title;
this.form.journal = res.article.journal_id;
@@ -1488,21 +1406,4 @@ export default {
::v-deep .el-drawer__wrapper .WACContainer {
z-index: 10000 !important;
}
.beautiful-gradient {
background: linear-gradient(135deg, #f0f9fe, #dce6ff, #d7e9fd);
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.01);
border-radius: 16px;
padding: 10px;
box-sizing: border-box;
color: #333;
font-family: "Segoe UI", sans-serif;
transition: transform 0.3s ease, box-shadow 0.3s ease;
}
.beautiful-gradient:hover {
transform: translateY(-4px);
box-shadow: 0 12px 30px rgba(0, 0, 0, 0.15);
}
</style>

View File

@@ -52,19 +52,7 @@
<el-button type="primary" icon="el-icon-search" @click="handleSearch" style="margin: 0 0 10px 0">Search </el-button>
</div>
<div v-if="!PreAcpVisible">
<div v-for="(item, ikgn) in tableData" class="mangu_list" style="position: relative">
<img
v-if="item.ai_review != '' && item.ai_review"
src="@/assets/img/ai.png"
@click="openAI(item)"
style="cursor: pointer; width: 30px; height: 30px; position: absolute; right: 6px; top: 6px"
/>
<img
v-else
src="@/assets/img/ai.png"
@click="creatAI(item,ikgn)"
style="opacity: 0.5; cursor: pointer; width: 30px; height: 30px; position: absolute; right: 6px; top: 6px"
/>
<div v-for="(item, ikgn) in tableData" class="mangu_list">
<div>
<font style="color: #666b7a">ID : </font>
<span
@@ -265,7 +253,7 @@
<div v-if="item.reportList.length > 0" style="text-align: left">
<div v-for="(v, i) in item.reportList" style="margin-top: 10px; overflow: hidden">
<div style="display: flex; align-items: center; justify-content: space-between">
<div style="display: flex; align-items: center">
<div style="display: flex; align-items: center;">
<span
style="
float: left;
@@ -280,20 +268,14 @@
"
><i class="el-icon-s-custom"></i
></span>
<span
style="
max-width: 80%;
white-space: nowrap;
display: inline-block;
<span style="max-width:80%;white-space: nowrap;display: inline-block;
overflow: hidden;
text-overflow: ellipsis;
"
>{{ v.author_account.realname }}</span
>
text-overflow: ellipsis;">{{ v.author_account.realname }}</span>
</div>
<div style="max-width: 260px; width: auto">
<div style="max-width:260px;width:auto;">
<span style="margin-left: 6px" v-if="v.author_account.wos_time">
<span style="font-size: 12px; font-weight: bold">WOS</span> :
<span v-html="colorIndex1(v.author_account.wos_index)"></span>
@@ -979,7 +961,7 @@
"
>
<el-button type="primary" @click="saveUserIndex(userIndexForm)" style="float: right">{{ $t('citeList.save') }}</el-button>
<el-button style="float: right; margin-right: 20px" @click="aiSorbox = false">{{ $t('citeList.cancel') }}</el-button>
<el-button style="float: right; margin-right: 20px">{{ $t('citeList.cancel') }}</el-button>
</div>
</el-drawer>
@@ -1130,34 +1112,6 @@
</div>
</div>
</el-dialog>
<el-dialog :title="$t('AI.AISummaryAnalysis')" :visible.sync="isShowAI" width="50%" class="AIDialog">
<div class="AISummaryAnalysis">
<el-collapse class="auth_colla auth_collna_ew" style="margin-bottom: 0">
<el-collapse-item name="1">
<template slot="title">
Abstract
<font v-if="currentArticleData.keywords" style="margin-left: 3px">, Keywords</font>
</template>
<p>
<font>Abstract :</font><b>{{ currentArticleData.abstrart }}</b>
</p>
<p v-if="currentArticleData.keywords">
<font>Keywords :</font><b>{{ currentArticleData.keywords }}</b>
</p>
</el-collapse-item>
</el-collapse>
<p style="line-height: 20px">
<span>{{ $t('AI.AIAbstractInfo') }} :</span>
{{ currentArticleData.ai_review }}
</p>
</div>
<span slot="footer" class="dialog-footer">
<!-- <el-button @click="isShowAI = false">取 消</el-button> -->
<el-button type="primary" @click="isShowAI = false">Close</el-button>
</span>
</el-dialog>
</div>
</template>
@@ -1170,8 +1124,6 @@ export default {
},
data() {
return {
isShowAI: false,
currentArticleData: {},
rules: {},
userloading: false,
curState: null,
@@ -1327,37 +1279,6 @@ export default {
}
},
methods: {
openAI(data) {
this.isShowAI = true;
this.currentArticleData = { ...data };
console.log('this.currentArticleData at line 1312:', this.currentArticleData);
},
creatAI(data,i){
const loading = this.$loading({
lock: true,
text: 'Loading...',
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)'
});
console.log('data at line 1336:', data)
this.$api
// api/Article/addArticle
.post('api/Aireview/review', {
article_id: data.article_id,
})
.then((res) => {
if(res.data.content){
this.tableData[i].ai_review=res.data.content
loading.close()
this.openAI({...data,ai_review:res.data.content});
}
}).catch((err) => {
loading.close()
this.$message.error('AI analysis failed')
})
},
// 保存个人信息
saveUserIndex() {
let link_geo = '';
@@ -1881,9 +1802,7 @@ export default {
typeName = 'Google';
index = this.userMessage.google_time != 0 ? this.userMessage.google_index : '';
date = this.userMessage.google_time;
website = this.userMessage.g_author
? `https://scholar.google.com/citations?hl=en&user=${this.userMessage.g_author}`
: '';
website =this.userMessage.g_author?`https://scholar.google.com/citations?hl=en&user=${this.userMessage.g_author}`:'';
editor = this.userMessage.google_editor;
g_author = this.userMessage.g_author;
this.bankVisible = false;
@@ -2785,42 +2704,4 @@ export default {
.userIndexBox .s_rol > div.rol_mess > font {
width: auto;
}
.AISummaryAnalysis p {
margin-top: 10px;
font-size: 14px;
padding-left: 10px;
box-sizing: border-box;
}
.AISummaryAnalysis p span {
display: inline-block;
width: auto;
color: #6157fd;
font-weight: bold;
}
::v-deep .AIDialog .el-dialog__body {
padding: 20px !important;
}
::v-deep .AIDialog .el-dialog__body .auth_collna_ew .el-collapse-item__arrow {
padding-left: 0px !important;
}
::v-deep .AIDialog .el-dialog__body .auth_collna_ew .el-collapse-item__header {
padding-left: 30px !important;
}
::v-deep .AIDialog .el-dialog {
/* background: linear-gradient(135deg, #f0f9fe, #dce6ff, #d7e9fd) !important;
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.01) !important;
border-radius: 16px !important;
padding: 10px !important;
box-sizing: border-box !important;
color: #333 !important;
font-family: "Segoe UI", sans-serif !important;
transition: transform 0.3s ease, box-shadow 0.3s ease !important; */
}
.beautiful-gradient {
}
.beautiful-gradient:hover {
transform: translateY(-4px);
box-shadow: 0 12px 30px rgba(0, 0, 0, 0.15);
}
</style>

View File

@@ -420,13 +420,11 @@
<!-- 参考文献 -->
<div :ref="tabsList[3].refName" class="scroll-item">
<div class="bor_style_onli">
<h4>{{tabsList[3].name}}</h4>
<PreIngestedEditorProduce type="produce" v-if="detailMes.article_id&&p_article_id" :article_id="detailMes.article_id" :p_article_id="p_article_id"></PreIngestedEditorProduce>
<!--<div class="liter_ture">
<div class="liter_ture">
<div class="chanSelLef">
<!-- 1 -->
<div :class="showB_step ==1?'C_style':''">
<h3><span>1</span>Check References and Doi</h3>
<div v-if="showB_step ==1">
@@ -456,7 +454,7 @@
</div>
</div>
<!-- 2 -->
<div :class="showB_step ==2?'C_style':''">
<h3><span>2</span>Check Standard</h3>
<div v-if="showB_step ==2">
@@ -534,7 +532,8 @@
</div>
</div>
<br clear="both">
<!-- <p v-if="this.chanFerForm==''" style="text-align: center;color: #999;margin-top: 50px;">No references</p> -->
<!-- 进度条 -->
<div v-if="refProcess==1" class="RefProBar">
<div>
<el-progress :text-inside="true" :stroke-width="24" :percentage="refReal"
@@ -545,7 +544,7 @@
</p>
</div>
</div>
</div> -->
</div>
</div>
</div>
@@ -829,15 +828,12 @@
import 'quill/dist/quill.core.css';
import 'quill/dist/quill.snow.css';
import 'quill/dist/quill.bubble.css';
import {
quillEditor
} from 'vue-quill-editor';
import {
Loading
} from 'element-ui';
import PreIngestedEditorProduce from './PreIngestedEditorProduce.vue'
export default {
data() {
return {
@@ -2742,7 +2738,7 @@
},
},
components: {
quillEditor,PreIngestedEditorProduce
quillEditor
},
}
</script>

View File

@@ -390,12 +390,10 @@
</div>
<div class="titHtml titHtml1" v-if="htmlContent && html_type == 2">
<common-word
:isPreview="true"
:readonly="true"
v-if="htmlContent"
ref="commonWord"
:value="htmlContent"
:contentList="mains"
:wordStyle="wordStyle"
style="width: calc(100%); height: 50vh"
:style="`100%`"
@@ -1026,70 +1024,70 @@ export default {
});
},
getWord() {
// var htmlContent = ``;
// htmlContent += this.mains
// .map((item) => {
// //批注
// let contentHtml = '';
// var isRemark = ``;
var htmlContent = ``;
htmlContent += this.mains
.map((item) => {
//批注
let contentHtml = '';
var isRemark = ``;
// // 判断是否是图片
// if (item.type == 1) {
// contentHtml = `
// <p contenteditable="false" main-state="${item.state}" class="MaxPicture pMain" data-id="${
// item.ami_id
// }" main-id="${item.am_id}">
// ${isRemark}
// <img src="${this.mediaUrl +'articleImage/'+ item.image.url}" style="width: ${
// item.width ? `${item.width}px` : '100%'
// }" />
// <font class="font" style="width: ${item.width ? `${item.width}px` : '100%'}" >${
// item.image.note ? item.image.note : ''
// }</font>
// </p>
// `;
// } else if (item.type == 2) {
// var tableList = JSON.parse(item.table.table_data);
// 判断是否是图片
if (item.type == 1) {
contentHtml = `
<p contenteditable="false" main-state="${item.state}" class="MaxPicture pMain" data-id="${
item.ami_id
}" main-id="${item.am_id}">
${isRemark}
<img src="${this.mediaUrl +'articleImage/'+ item.image.url}" style="width: ${
item.width ? `${item.width}px` : '100%'
}" />
<font class="font" style="width: ${item.width ? `${item.width}px` : '100%'}" >${
item.image.note ? item.image.note : ''
}</font>
</p>
`;
} else if (item.type == 2) {
var tableList = JSON.parse(item.table.table_data);
// contentHtml = `
// <div contenteditable="false" data-id="${item.amt_id}" main-state="${item.state}" main-id="${
// item.am_id
// }" class="thumbnailTableBox wordTableHtml table_Box pMain" style="width: 100%; padding: 8px 15px; box-sizing: border-box; border-radius: 4px; position: relative;">
// ${isRemark}
// <font class="font tableTitle" style="width:100%" >${item.table.title ? item.table.title : ''}</font>
// <table border="1" style="width: auto; border-collapse: collapse; text-align: center; ">
// ${tableList
// .map((row) => {
// return `
// <tr>
// ${row
// .map((cell) => {
// return `
// <td colspan="${cell.colspan || 1}" rowspan="${cell.rowspan || 1}">
// <span>${cell.text || ''}</span>
// </td>
// `;
// })
// .join('')} <!-- join the cells in the row -->
// </tr>
// `;
// })
// .join('')} <!-- join the rows -->
// </table>
// <font class="font" style="width:100%" >${item.table.note ? item.table.note : ''}</font>
// </div>
// `;
// } else {
contentHtml = `
<div contenteditable="false" data-id="${item.amt_id}" main-state="${item.state}" main-id="${
item.am_id
}" class="thumbnailTableBox wordTableHtml table_Box pMain" style="width: 100%; padding: 8px 15px; box-sizing: border-box; border-radius: 4px; position: relative;">
${isRemark}
<font class="font tableTitle" style="width:100%" >${item.table.title ? item.table.title : ''}</font>
<table border="1" style="width: auto; border-collapse: collapse; text-align: center; ">
${tableList
.map((row) => {
return `
<tr>
${row
.map((cell) => {
return `
<td colspan="${cell.colspan || 1}" rowspan="${cell.rowspan || 1}">
<span>${cell.text || ''}</span>
</td>
`;
})
.join('')} <!-- join the cells in the row -->
</tr>
`;
})
.join('')} <!-- join the rows -->
</table>
<font class="font" style="width:100%" >${item.table.note ? item.table.note : ''}</font>
</div>
`;
} else {
// contentHtml = `<p class="pMain" main-state="${item.state}" contenteditable="false" data-id="${item.am_id}" main-id="${item.am_id}">${isRemark}${item.content}</p>`;
// }
contentHtml = `<p class="pMain" main-state="${item.state}" contenteditable="false" data-id="${item.am_id}" main-id="${item.am_id}">${isRemark}${item.content}</p>`;
}
// // 判断是否是表格类型
// 判断是否是表格类型
// return contentHtml;
// })
// .join('');
this.htmlContent = 'true';
return contentHtml;
})
.join('');
this.htmlContent = htmlContent;
},
getMainsInfo2(e) {
@@ -1101,12 +1099,11 @@ export default {
.then((res) => {
this.loadHtml = false;
if (res.code == 0) {
console.log(res,'res')
// console.log(res,'res')
this.mains = '';
if (res.data.list.length > 0) {
this.mains = res.data.list;
console.log('this.mains at line 1108:', this.mains)
this.getWord();
} else {
this.mains = '';
@@ -1149,7 +1146,6 @@ export default {
},
// 文章html弹出层
async htmlContet(e) {
console.log('e at line 1151:', e)
this.htmlContent=''
this.articleId = e.article_id;
this.tg_article_id = e.tg_article_id;

View File

@@ -4,7 +4,7 @@
<el-breadcrumb separator="/">
<el-breadcrumb-item>
<i class="el-icon-lx-calendar"></i>
<router-link :to="{ path: '/articleList' }">
<router-link :to="{path:'/articleList'}">
<span class="top_dao"> Manuscript list</span>
</router-link>
>> Manuscript process
@@ -12,86 +12,68 @@
</el-breadcrumb>
</div>
<div class="container_state">
<p style="color: #888; margin: 10px 0 5px 0">ID : {{ artMes.accept_sn }}</p>
<p style="font-size: 16px; font-weight: bolder; letter-spacing: -0.5px">
<p style="color: #888;margin: 10px 0 5px 0;">ID : {{artMes.accept_sn}}</p>
<p style="font-size: 16px;font-weight: bolder;letter-spacing: -0.5px;">
<!-- <span class="art_type">{{ellType(artMes.type)}}</span> -->
{{ artMes.title }}
{{artMes.title}}
</p>
<!-- <p style="color: #7f8790;margin: 10px 0 0 0;">Follow the progress of your submission.</p> -->
<div class="tit_head">
Status : <b style="margin: 0 50px 0 0">{{ statetostr(artMes.laststate) }}</b> Journal : <b>{{ artMes.journalname }}</b>
</div>
<div class="tit_head" v-if="artMes.majors&&artMes.majors.length>0">
<b style="margin: 0 50px 0 0;font-size: 20px;">Research areas</b>
<div style="margin-top: 10px;">
<p style="" v-for="(v, i) in artMes.majors">
<span style="color: #333; margin-right: 10px">Field {{ i + 1 }}:</span>{{ v.str
}}
</p>
</div>
Status : <b style="margin: 0 50px 0 0;">{{statetostr(artMes.laststate)}}</b>
Journal : <b>{{artMes.journalname}}</b>
</div>
<el-row :gutter="30">
<el-col :span="15">
<div class="process_new">
<!-- <p style="width: 100%;height: 1px;background-color: #eee;margin: 35px 0 30px 0;"></p> -->
<h2 style="font-size: 18px; margin: 0 0 10px 0; float: left; letter-spacing: -0.8px">Manuscript Tracking</h2>
<h2 style="font-size: 18px;margin: 0 0 10px 0;float: left;letter-spacing: -0.8px;">Manuscript
Tracking</h2>
<!-- <div class="radio" style="float: right;">
<el-radio-group v-model="reverse">
<el-radio-button :label="false">Ascending</el-radio-button>
<el-radio-button :label="true">Descending</el-radio-button>
</el-radio-group>
</div> -->
<br clear="both" />
<br clear="both">
<el-timeline :reverse="reverse" class="author_tree">
<el-timeline-item
v-for="(item, index) in prossMsgs"
:icon="item.icon"
:color="item.color"
size="large"
:key="index"
:timestamp="formatDate(item.ctime)"
placement="top"
v-if="item.ftype == 0"
>
<el-timeline-item v-for="(item, index) in prossMsgs" :icon="item.icon" :color="item.color"
size="large" :key="index" :timestamp="formatDate(item.ctime)" placement="top" v-if="item.ftype == 0">
<el-card>
<p>
<font>{{ statetostr(item.state_to) }}</font>
<!-- 提交 -->
<font v-if="item.state_to == -1">
<font v-if="item.state_to==-1">
<!-- : <font style="margin-left: 5px;">First submitted to <b>{{artMes.journalname}}</b></font> -->
</font>
<!-- 给编辑 -->
<font v-if="item.state_to == 1">
<font v-if="item.state_to==1">
<!-- : <b style="margin-left: 5px;"> Submission checks complete</b> -->
</font>
<!-- 审查中 -->
<font v-if="item.state_to == 2">
<font v-if="item.state_to==2">
<!-- : <b style="margin-left: 5px;"> Editor assigned</b> -->
</font>
<!-- 拒绝 -->
<font v-if="item.state_to == 3">
<font v-if="item.state_to==3">
<!-- : <b> Reject manuscript</b> -->
</font>
<!-- 修改 -->
<font v-if="item.state_to == 4">
<font v-if="item.state_to==4">
:
<router-link
:to="{ path: '/articleProcessRevision', query: { id: artMes.article_id } }"
v-if="item.back == 1"
>
<b style="margin-left: 5px; color: #006699; text-decoration: underline"
>Upload Major Revision</b
>
:to="{path:'/articleProcessRevision',query:{id:artMes.article_id}}"
v-if="item.back==1">
<b style="margin-left: 5px;color: #006699;text-decoration: underline;">Upload
Major Revision</b>
</router-link>
<b style="margin-left: 5px; color: #888; text-decoration: underline" v-if="item.back == 0">
<b style="margin-left: 5px;color: #888;text-decoration: underline;"
v-if="item.back==0">
Upload Major Revision (Completed)
</b>
</font>
<!-- 接收 -->
<font v-if="item.state_to == 5">
<font v-if="item.state_to==5">
<!-- : <b style="margin-left: 5px;"> Successfully received manuscript</b> -->
</font>
</p>
@@ -120,76 +102,88 @@
<!-- 对话列表 -->
<div class="kuang_communtion">
<h2>Communication</h2>
<h2>
Communication
</h2>
<div v-for="item in talkMsgs" class="kuang_communtion_conmt">
<div v-if="item.user_id != artMes.user_id" class="talk_aued">
<p>Editor :</p>
<p>
Editor :
</p>
<el-card>
<p style="white-space: pre-wrap">{{ item.ad_content }}</p>
<p style="white-space: pre-wrap;">{{ item.ad_content }}</p>
</el-card>
<b>{{ formatDate(item.ad_ctime) }}</b>
<b>{{formatDate(item.ad_ctime)}}</b>
</div>
<div v-if="item.user_id == artMes.user_id" class="talk_aued talk_edit">
<p>Author :</p>
<p>
Author :
</p>
<el-card>
<p style="white-space: pre-wrap">{{ item.ad_content }}</p>
<p style="white-space: pre-wrap;">{{ item.ad_content }}</p>
</el-card>
<b>{{ formatDate(item.ad_ctime) }}</b>
<b>{{formatDate(item.ad_ctime)}}</b>
</div>
</div>
<div class="kuang_communtion_input">
<p v-if="talkMsgs"></p>
<span class="text_bor_ghu">
<el-input
type="textarea"
rows="3"
v-model="msgform.ad_content"
placeholder="You can initiate short conversations with the editor."
resize="none"
>
<el-input type="textarea" rows="3" v-model="msgform.ad_content"
placeholder="You can initiate short conversations with the editor." resize="none">
</el-input>
<el-button type="primary" @click="saveMsg">Send</el-button>
</span>
<font style="font-size: 12px; color: #999; padding: 12px 5px 0 5px; display: block">
This column is served as an instant correspondence between the editor and authors, aiming to acquire a
faster way of communication than E-Mail. If you have any questions, please start the instant corresponding,
and the editors will reply to you in 24 hours.
<br />
<font style="color: #006699">Please Attention</font>
<br />
<font style="color: #006699">1.</font> If you need to send files as attachments, please send them to
<font style="font-size: 12px;color: #999;padding:12px 5px 0 5px;display: block;">
This column is served as an instant correspondence between the editor and authors,
aiming to acquire a faster
way of communication than E-Mail. If you have any questions, please start the instant
corresponding, and the
editors will reply to you in 24 hours.
<br>
<font style="color: #006699;">Please Attention</font>
<br>
<font style="color: #006699;">1.</font> If you need to send files as attachments, please
send them to
tmr@tmrjournals.com
<br />
<font style="color: #006699">2.</font> Please do not upload the primary documents like the cover letter, the
reply to the reviewer comments, etc.
<br>
<font style="color: #006699;">2.</font> Please do not upload the primary documents like
the cover letter, the
reply to the reviewer comments,
etc.
</font>
</div>
</div>
<p style="line-height: 20px; color: #999; padding: 0 15px 0 15px">
We encourage authors to upload a Cover Letter file and make sure the Highlights part in the main manuscript is after
the abstract and keywords. That will help authors let editors quickly obtain information and evaluate the scientific
value of their research correctly.
<br />Please remind our editor in the cover letter if you want your manuscript processed quickly. <br />Please note
that manuscripts with at least one of the following characteristics will be included in the journal's manuscript
fast track:
<br />
<font style="color: #006699">1.Interest:</font> This manuscript has a novel perspective.
<br />
<font style="color: #006699">2.Importance:</font> This manuscript belongs to the focus area.
<br />
<font style="color: #006699">3.Value:</font> This manuscript belongs to the advanced topic and can attract wide
<p style="line-height: 20px;color: #999;padding: 0 15px 0 15px;">
We encourage authors to upload a Cover Letter file and make sure the Highlights part in the main
manuscript is
after the abstract and keywords. That will help authors let editors quickly obtain information
and evaluate the
scientific value of their research correctly.
<br>Please remind our editor in the cover letter if you want your manuscript processed quickly.
<br>Please note that manuscripts with at least one of the following characteristics will be
included in the
journal's manuscript fast track:
<br>
<font style="color: #006699;">1.Interest:</font> This manuscript has a novel perspective.
<br>
<font style="color: #006699;">2.Importance:</font> This manuscript belongs to the focus area.
<br>
<font style="color: #006699;">3.Value:</font> This manuscript belongs to the advanced topic and
can attract wide
attention.
</p>
</el-col>
</el-row>
</div>
<el-dialog title="Message" :visible.sync="editVisible" width="40%">
<el-form ref="msgform" :model="msgform" label-width="80px">
<el-form-item label="Message">
<el-input type="textarea" rows="5" v-model="msgform.content" placeholder="Author messages"> </el-input>
<el-input type="textarea" rows="5" v-model="msgform.content" placeholder="Author messages">
</el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
@@ -200,7 +194,7 @@
</template>
<script>
export default {
export default {
data() {
return {
baseUrl: this.Common.baseUrl,
@@ -230,10 +224,12 @@ export default {
saveloading: false
};
},
created: function () {
created: function() {
this.initarticle();
},
computed: {},
computed: {
},
methods: {
//初始化文章信息
initarticle() {
@@ -243,45 +239,45 @@ export default {
human: 'author'
})
.then((res) => {
let back_num = 0;
let back_num = 0
// 添加投递稿件条目
res.msg.unshift({
state_to: -1,
ctime: res.article.ctime,
color: '#B5C334',
icon: 'el-icon-collection-tag',
ftype: 0
ftype: 0,
});
for (let i = res.msg.length - 1; i >= 0; i--) {
if (res.msg[i].state_to == 4 && res.msg[i + 1] == undefined && back_num == 0) {
res.msg[i].back = 1;
back_num = 1;
back_num = 1
} else {
res.msg[i].back = 0;
}
if (res.msg[i].state_to == 1) {
res.msg[i].color = '#f75822';
res.msg[i].icon = 'el-icon-document-checked';
res.msg[i].color = '#f75822'
res.msg[i].icon = 'el-icon-document-checked'
}
if (res.msg[i].state_to == 2) {
res.msg[i].color = '#0ebee1';
res.msg[i].icon = 'el-icon-document';
res.msg[i].color = '#0ebee1'
res.msg[i].icon = 'el-icon-document'
}
if (res.msg[i].state_to == 3) {
res.msg[i].color = '#888';
res.msg[i].icon = 'el-icon-close';
res.msg[i].color = '#888'
res.msg[i].icon = 'el-icon-close'
}
if (res.msg[i].state_to == 4) {
res.msg[i].color = '#5a90e1';
res.msg[i].icon = 'el-icon-edit-outline';
res.msg[i].color = '#5a90e1'
res.msg[i].icon = 'el-icon-edit-outline'
}
if (res.msg[i].state_to == 5) {
res.msg[i].color = '#91cc75';
res.msg[i].icon = 'el-icon-check';
res.msg[i].color = '#91cc75'
res.msg[i].icon = 'el-icon-check'
}
if (res.msg[i].state_to == 6) {
res.msg[i].color = '#27727B';
res.msg[i].icon = 'el-icon-star-off';
res.msg[i].color = '#27727B'
res.msg[i].icon = 'el-icon-star-off'
}
}
this.artMes = res.article;
@@ -339,10 +335,11 @@ export default {
return false;
}
this.loading = true;
this.$api.post('api/Article/pushArticleDialog', this.msgform).then((res) => {
this.$api.post('api/Article/pushArticleDialog', this.msgform)
.then((res) => {
this.loading = false;
this.$message.success('Sent successfully');
this.initarticle();
this.initarticle()
});
},
@@ -382,7 +379,7 @@ export default {
ellType(e) {
let frag = '';
switch (e) {
case 'A':
case "A":
frag = 'Article';
break;
case 'B':
@@ -449,117 +446,121 @@ export default {
frag = 'Others';
}
return frag;
}
},
filters: {}
};
},
filters: {
}
};
</script>
<style>
.top_dao:hover {
.top_dao:hover {
text-decoration: underline;
cursor: pointer;
}
}
.process_new {
.process_new {
border: 1px solid #dcdfe6;
padding: 20px;
background-color: #fff;
border-radius: 5px;
}
}
.art_type {
.art_type {
/* background-color: #ddeef7; */
color: #006699;
padding: 2px 5px;
border-radius: 5px;
font-size: 12px;
margin: 0 10px 0 0;
}
}
.tit_head {
.tit_head {
border-radius: 5px;
border: 1px solid #ebeef5;
border: 1px solid #EBEEF5;
padding: 20px;
font-size: 15px;
margin: 20px 0 30px 0;
background-color: #fff;
/* background-color: #fcfcfc; */
}
}
.tit_head b {
.tit_head b {
color: #006699;
/* text-decoration: underline; */
}
}
.el-radio-button__orig-radio:checked + .el-radio-button__inner {
.el-radio-button__orig-radio:checked+.el-radio-button__inner {
background-color: #006699;
border-color: #006699;
}
}
.author_tree {
.author_tree {
margin: 40px 0 0 10px;
}
}
.author_tree .el-timeline-item {
.author_tree .el-timeline-item {
padding-bottom: 1px;
}
}
.author_tree .el-timeline-item__node--large {
.author_tree .el-timeline-item__node--large {
left: 155px;
width: 30px;
height: 30px;
}
}
.author_tree .el-timeline-item__wrapper {
.author_tree .el-timeline-item__wrapper {
padding-left: 0;
margin: 0 0 50px 0;
}
}
.author_tree .el-timeline-item__timestamp.is-top {
.author_tree .el-timeline-item__timestamp.is-top {
padding-top: 10px;
margin-bottom: 13px;
font-size: 14px;
}
}
.author_tree .el-timeline-item__content {
.author_tree .el-timeline-item__content {
margin: -50px 0 0 210px;
}
}
.author_tree .el-timeline-item__tail {
.author_tree .el-timeline-item__tail {
height: auto;
bottom: 15px;
top: 45px;
border-left: 3px solid #e4e7ed;
border-left: 3px solid #E4E7ED;
/* border-left: 2px solid #66a3c2; */
left: 168px;
}
}
.art_process_ {
.art_process_ {
margin-bottom: 30px;
border: 1px solid #dcdfe6;
padding: 20px;
background-color: #fff;
border-radius: 5px;
}
}
.art_process_ > h2 {
.art_process_>h2 {
font-size: 18px;
margin: 0 0 2px 0;
letter-spacing: -0.8px;
}
}
.art_process_list {
.art_process_list {
border-bottom: 1px solid #dcdfe6;
padding: 15px 0 25px 10px;
}
}
.art_process_ .art_process_list:last-child {
.art_process_ .art_process_list:last-child {
border-bottom: 0;
padding-bottom: 5px;
}
}
.art_process_list b {
.art_process_list b {
background-color: #006699;
color: #fff;
display: inline-block;
@@ -568,14 +569,15 @@ export default {
line-height: 18px;
text-align: center;
margin: 0 10px 0 0;
}
.art_process_list span {
}
.art_process_list span {
color: #888;
margin: 0 0 0 15px;
}
}
.art_process_list p {
.art_process_list p {
margin: 10px 0 0 28px;
}
}
</style>

View File

@@ -200,7 +200,6 @@ export default {
},
methods: {
goEdit() {
window.open(this.$router.resolve({ path: '/GenerateCharts',
query: {

View File

@@ -0,0 +1,533 @@
<template>
<div class="tinymce-container editor-container">
<textarea class="tinymce-textarea" :id="tinymceId"></textarea>
</div>
</template>
<script>
import { string } from 'html-docx-js/dist/html-docx';
import htmlDocx from 'html-docx-js/dist/html-docx.js';
import { Document, Packer, PageOrientation, Paragraph, TextRun } from 'docx'; // 引入 docx.js
import html2canvas from 'html2canvas';
const tableStyle = ` b span{
font-weight: bold !important;
}
i span{
font-style: italic !important; ;
}
sub span{
vertical-align: sub;
}
sup span{
vertical-align: sup;
}
sub {
vertical-align: sub!important;
}
sup {
vertical-align: sup !important;
}
span[style*="vertical-align: super"] {
vertical-align: super !important;
}
span[style*="vertical-align: sub"] {
vertical-align: sub !important;
}
table {
border:0px !important;
border-collapse: collapse; /* 去除单元格间隙 */
width: auto;
margin : 0 auto !important;
table-layout: auto; /* 自动调整列宽 */
text-align:left;
font-family:'Charis SIL' !important;
font-size: 7.5000pt !important;
mso-font-kerning: 1.0000pt !important;
line-height: 10pt !important;
mos-line-height: 10pt !important;
}
table td, table th {
padding: 5px;
text-align:left !important;
white-space: pre-wrap; /* 保留换行符并换行 */
word-wrap: break-word; /* 长单词自动换行 */
word-break: break-word;
font-family:'Charis SIL' !important;
font-size: 7.5000pt !important;
mso-font-kerning: 1.0000pt !important;
line-height: 10pt !important;
mos-line-height: 10pt !important;
}
table tbody tr td{
text-align:left !important;
border-left:none !important;
mso-border-left-alt:none !important;
border-right:none !important;
mso-border-right-alt:none !important;
border-top:none;mso-border-top-alt:none !important;
border-bottom:none !important;
mso-border-bottom-alt:none !important;
border:1px dashed #dcdfe6 !important;
border-left:1px dashed #dcdfe6 !important;
border-right:1px dashed #dcdfe6 !important;
word-break: keep-all !important;
text-align: justify !important; // 设置两端对齐
}
table tr td p{
text-align:left !important;
margin:0;
font-family:'Charis SIL' !important;
font-size: 7.5000pt !important;
mso-font-kerning: 1.0000pt !important;
line-height: 10pt !important;
mos-line-height: 10pt !important;
}
table span{
color:#000000;text-align:left !important;
font-family:'Charis SIL' !important;
font-size: 7.5000pt !important;
mso-font-kerning: 1.0000pt !important;
line-height: 10pt !important;
mos-line-height: 10pt !important;
}
table .color-highlight{
color:rgb(0,130,170) !important;
font-family:'Charis SIL' !important;
font-size: 7.5000pt !important;
mso-font-kerning: 1.0000pt !important;
line-height: 10pt !important;
mos-line-height: 10pt !important;
}
table tr:first-child td {
border-top:1.0000pt solid #000 !important;mso-border-top-alt:0.5000pt solid #000 !important;border-bottom:1.0000pt solid #000 !important;mso-border-bottom-alt:0.5000pt solid #000 !important;
}
table tr:last-of-type td {
border-bottom:1.0000pt solid #000 !important;mso-border-bottom-alt:0.5000pt solid #000 !important;;
}
`;
export default {
name: 'tinymce',
components: {},
props: {
id: {
type: String
},
value: {
type: String,
default: ''
},
isEdit: {},
toolbar: {
type: Array,
required: false,
default() {
return [];
}
},
menubar: {
default: 'file edit insert view format table '
},
height: {
type: Number,
required: false,
default: 360
},
width: {
type: String,
required: false,
default: '100%'
},
isShowArtWorkButton: {
default: false
}
},
data() {
return {
typesettingType: 1,
typesettingTypeOptions: [
{
label: this.$t('commonTable.typesettingType1'),
value: 1,
orientation: 'portrait',
pageSize: {
width: 11906,
height: 16976
},
pageMargins: {
top: 1440,
bottom: 1440,
left: 1084,
right: 1084
}
},
// 1 cm = 144 Twip 上边距2.54 cm = 2.54 × 144 = 365.76 Twip
{
label: this.$t('commonTable.typesettingType2'),
value: 2,
orientation: 'landscape',
pageSize: {
width: 16976,
height: 11906
},
pageMargins: {
top: 1440,
bottom: 1440,
left: 1084,
right: 1084
}
}
],
uploadReset: false,
dialogVisible: false,
form: {
name: '',
region: '',
date1: '',
date2: '',
delivery: false,
type: [],
resource: '',
desc: ''
},
formLabelWidth: '120px',
hasChange: false,
hasInit: false,
tinymceId: this.id || 'vue-tinymce-' + +new Date()
};
},
watch: {
value(val) {
if (!this.hasChange && this.hasInit) {
this.$nextTick(() => window.tinymce.get(this.tinymceId).setContent(val));
}
}
},
mounted() {
this.typesettingType = 1;
this.initTinymce();
},
activated() {
this.typesettingType = 1;
this.initTinymce();
},
deactivated() {
this.destroyTinymce();
},
methods: {
handleSubmit() {
this.$refs.uploadImage.handleSubmit();
},
getDetail(val) {
if (this.hasInit == true) {
this.$nextTick(() => window.tinymce.get(this.tinymceId).setContent(val));
}
},
//将字符串添加到富文本编辑器中
addArtWork(str) {
window.tinymce.get(this.tinymceId).insertContent(str);
},
onClick(e) {
this.$emit('onClick', e, tinymce);
},
changeTable() {
// 获取所有表格
const tables = window.tinymce.get(this.tinymceId).getBody().querySelectorAll('table');
console.log('tables at line 110:', tables);
// 遍历并设置样式
tables.forEach((table) => {
const editor = window.tinymce.get(this.tinymceId);
editor.dom.setStyles(table, {
width: this.typesettingType == 1 ? '17.18cm' : '25.88cm'
});
});
this.$forceUpdate();
},
initTinymce() {
const _this = this;
window.tinymce.init({
selector: `#${this.tinymceId}`,
content_css: false, // 禁用默认样式
table_resize_bars: true, // 启用拖动调整功能
valid_elements: '*[*]', // 允许所有 HTML 标签
paste_preprocess: function (plugin, args) {
let content = args.content;
const container = document.createElement('div');
container.innerHTML = content;
_this.updateTableStyles(container);
args.content = container.innerHTML; // 更新内容
},
content_style: `${tableStyle}`,
formats: {
bold: { inline: 'b' },
italic: { inline: 'i' }
},
body_class: 'panel-body ',
object_resizing: false,
toolbar: this.toolbar.length > 0 ? this.toolbar : toolbar,
menubar: false, // 启用菜单栏并保持必要的项目
statusbar: false, // 关闭底部状态栏
custom_colors: false,
color_map: ['000000', 'Black', '0082AA', 'TMR Blue'],
plugins: 'forecolor code paste table image', // 启用 forecolor 和 code 插件
end_container_on_empty_block: true,
content_css: 'default', // 加载 TinyMCE 默认样式表
//设置自定义按钮 myCustomToolbarButton
setup(ed) {
ed.ui.registry.addButton('uploadWord', {
text: 'Word',
icon: 'import-word', // 使用自定义图标
onAction: function () {
const input = document.createElement('input');
input.type = 'file';
input.accept = '.docx'; // 限制为 Word 文件
input.addEventListener('change', function () {
const file = input.files[0];
if (file) {
const reader = new FileReader();
reader.onload = function (e) {
const arrayBuffer = e.target.result;
_this.$commonJS.extractTablesFromWord(arrayBuffer, function (tablesHtml) {
console.log('tablesHtml at line 279:', tablesHtml);
ed.setContent(tablesHtml);
});
};
reader.readAsArrayBuffer(file);
}
});
input.click();
}
});
ed.ui.registry.addMenuButton('customDropdown', {
text: _this.$t('commonTable.PaperRotation'), // 下拉框标题
fetch: function (callback) {
// 定义下拉框的内容
const items = [..._this.typesettingTypeOptions];
const menuItems = items.map((item) => ({
type: 'menuitem',
text: item.label,
onAction: function () {
_this.typesettingType = item.value;
_this.changeTable();
// ed.execCommand(item.value); // 执行命令
}
}));
callback(menuItems);
}
});
ed.on('init', function () {
const editorBody = ed.getBody();
// 创建 MutationObserver 监听内容变化
const observer = new MutationObserver(() => {
console.log('editorBody at line 313:', editorBody);
// _this.updateTableStyles(editorBody, _this.typesettingType);
// const hasHorizontalScrollbar = editorBody.scrollWidth > editorBody.clientWidth;
// if (hasHorizontalScrollbar) {
// console.log('TinyMCE 出现横向滚动条');
// } else {
// console.log('没有横向滚动条');
// }
});
// 监听子节点和内容的变化
observer.observe(editorBody, { childList: true, subtree: true, characterData: true });
});
// 定义自定义按钮
ed.ui.registry.addButton('clearButton', {
text: 'Empty',
onAction: () => {
// 插入自定义表格到编辑器中
ed.setContent('');
}
});
// 定义自定义按钮
ed.ui.registry.addButton('customButtonExportWord', {
text: _this.$t('commonTable.exportWord'),
onAction: () => {
// 插入自定义表格到编辑器中
let content = ed.getContent(); // 获取内容
content = content.replace(/<strong>/g, '<b>').replace(/<\/strong>/g, '</b>');
content = content.replace(/<em>/g, '<i>').replace(/<\/strong>/g, '</i>');
const container = document.createElement('div');
container.innerHTML = content;
_this.export('table', _this.$commonJS.updateTableStyles(container, _this.typesettingType, 1));
}
});
// 定义自定义按钮
ed.ui.registry.addButton('customButtonExportImg', {
text: _this.$t('commonTable.exportImg'),
onAction: () => {
// 插入自定义表格到编辑器中
_this.export('image', ed.getContent());
}
});
ed.ui.registry.addContextToolbar('spacer', {
predicate: () => false, // 保持静态
items: '',
scope: 'node'
});
ed.on('paste', (event) => {});
ed.on('SetContent', function (e) {
e.content = e.content.replace(/<strong>/g, '<b>').replace(/<\/strong>/g, '</b>');
e.content = e.content.replace(/<em>/g, '<i>').replace(/<\/em>/g, '</i>');
});
ed.on('GetContent', function (e) {
e.content = e.content.replace(/<b>/g, '<strong>').replace(/<\/b>/g, '</strong>');
e.content = e.content.replace(/<i>/g, '<em>').replace(/<\/i>/g, '</em>');
});
},
init_instance_callback: (editor) => {
if (_this.value) {
editor.setContent(_this.value);
}
_this.hasInit = true;
editor.on('NodeChange Change KeyUp SetContent', () => {
this.hasChange = true;
this.$emit('input', editor.getContent());
});
}
});
},
// 提取 Word 文件中的表格
updateTableStyles(container) {
var html = this.$commonJS.updateTableStyles(container, this.typesettingType);
var editor = window.tinymce.activeEditor; // 将外部 DOM 内容更新到编辑器
const container1 = document.createElement('div');
container1.innerHTML = html; // html 是更新后的 HTML 内容
editor.setContent(container1.innerHTML); // 更新编辑器内容
editor.focus(); // 聚焦到编辑器// 触发编辑器内容变化后,如果需要,可能还要设置编辑器的样式
},
//销毁富文本
destroyTinymce() {
if (window.tinymce.get(this.tinymceId)) {
window.tinymce.get(this.tinymceId).destroy();
}
},
//设置内容
setContent(value) {
window.tinymce.get(this.tinymceId).setContent(value);
},
//获取内容
getContent(type) {
this.$emit('getContent', type, window.tinymce.get(this.tinymceId).getContent());
console.log('window.tinymce.get(this.tinymceId).getContent() at line 431:', window.tinymce.get(this.tinymceId).getContent());
},
async export(type, data) {
if (type == 'table') {
var tableHtml = `<html xmlns:w="urn:schemas-microsoft-com:office:word">
<head>
<style>
${tableStyle}
</style>
</head>
<body>
${data}
</body>
</html>`;
const converted = htmlDocx.asBlob(tableHtml, {
orientation: this.typesettingTypeOptions[this.typesettingType - 1].orientation,
pageSize: {
...this.typesettingTypeOptions[this.typesettingType - 1].pageSize
},
pageMargins: {
...this.typesettingTypeOptions[this.typesettingType - 1].pageMargins
}
});
// const converted = htmlDocx.asBlob(tableHtml); // 将 HTML 转换为 Word Blob
// 触发文件下载
const link = document.createElement('a');
link.href = URL.createObjectURL(converted);
link.download = 'table.docx';
link.click();
} else if (type == 'image') {
const hiddenContainer = document.createElement('div');
hiddenContainer.style.position = 'absolute';
hiddenContainer.style.left = '-9999ppx';
hiddenContainer.style.top = '0';
hiddenContainer.innerHTML = data;
const style = document.createElement('style');
style.innerHTML = `${tableStyle}`;
document.head.appendChild(style);
document.body.appendChild(hiddenContainer);
// 使用 html2canvas 捕获表格内容
const table = hiddenContainer.querySelector('table'); // 找到表格
table.style.border = 'none';
// 使用 html2canvas 将内容转为图片
html2canvas(hiddenContainer, {
scale: 2, // 提高图片的分辨率默认为1设置为2可以使图片更清晰
logging: false, // 禁用日志输出
useCORS: true, // 允许跨域图像
allowTaint: true // 允许污染 canvas解决图片链接不可用问题
})
// 清空现有内容,显示图片
.then((canvas) => {
const imgData = canvas.toDataURL('image/png'); // 创建一个图片对象
const link = document.createElement('a'); // 创建一个链接并下载图片
link.href = imgData;
link.download = 'image.png';
link.click();
});
}
},
inlineStyles(element) {
const styles = window.getComputedStyle(element);
for (let style in styles) {
if (styles.hasOwnProperty(style)) {
element.style[style] = styles[style];
}
}
},
//获取上传图片后的地址,并设置图片样式
tableSuccessCBK(arr) {
console.log(arr, '222');
const _this = this;
window.tinymce.get(_this.tinymceId).insertContent(arr);
}
},
destroyed() {
this.destroyTinymce();
}
};
</script>
<style scoped>
::v-deep .tox-tinymce-aux {
z-index: 9999 !important;
}
::v-deep .tox .tox-menu {
z-index: 9999 !important;
}
/* 自定义按钮样式 */
.custom-btn {
background-color: #28a745 !important;
color: #fff !important;
border-radius: 4px;
padding: 5px 10px;
font-weight: bold;
}
.custom-btn:hover {
background-color: #218838 !important;
}
</style>

View File

@@ -1,5 +1,6 @@
<template>
<div class="tinymce-container editor-container">
<textarea class="tinymce-textarea" :id="tinymceId"></textarea>
</div>
</template>
@@ -41,10 +42,10 @@ const tableStyle = ` b span{
table-layout: auto; /* 自动调整列宽 */
text-align:left;
font-family:'Charis SIL' !important;
font-size: 14px !important;
font-size: 7.5000pt !important;
mso-font-kerning: 1.0000pt !important;
line-height: 20px !important;
mos-line-height: 20px !important;
line-height: 10pt !important;
mos-line-height: 10pt !important;
}
table td, table th {
padding: 5px;
@@ -53,10 +54,10 @@ const tableStyle = ` b span{
word-wrap: break-word; /* 长单词自动换行 */
word-break: break-word;
font-family:'Charis SIL' !important;
font-size: 14px !important;
font-size: 7.5000pt !important;
mso-font-kerning: 1.0000pt !important;
line-height: 20px !important;
mos-line-height: 20px !important;
line-height: 10pt !important;
mos-line-height: 10pt !important;
}
table tbody tr td{
@@ -72,7 +73,7 @@ const tableStyle = ` b span{
border-left:1px dashed #dcdfe6 !important;
border-right:1px dashed #dcdfe6 !important;
word-break: keep-all !important;
// text-align: justify !important; // 设置两端对齐
text-align: justify !important; // 设置两端对齐
}
@@ -82,27 +83,27 @@ const tableStyle = ` b span{
margin:0;
font-family:'Charis SIL' !important;
font-size: 14px !important;
font-size: 7.5000pt !important;
mso-font-kerning: 1.0000pt !important;
line-height: 20px !important;
mos-line-height: 20px !important;
line-height: 10pt !important;
mos-line-height: 10pt !important;
}
table span{
color:#000000;text-align:left !important;
font-family:'Charis SIL' !important;
font-size: 14px !important;
font-size: 7.5000pt !important;
mso-font-kerning: 1.0000pt !important;
line-height: 20px !important;
mos-line-height: 20px !important;
line-height: 10pt !important;
mos-line-height: 10pt !important;
}
table .color-highlight{
color:rgb(0,130,170) !important;
font-family:'Charis SIL' !important;
font-size: 14px !important;
font-size: 7.5000pt !important;
mso-font-kerning: 1.0000pt !important;
line-height: 20px !important;
mos-line-height: 20px !important;
line-height: 10pt !important;
mos-line-height: 10pt !important;
}
table tr:first-child td {
border-top:1.0000pt solid #000 !important;mso-border-top-alt:0.5000pt solid #000 !important;border-bottom:1.0000pt solid #000 !important;mso-border-bottom-alt:0.5000pt solid #000 !important;
@@ -115,21 +116,7 @@ const tableStyle = ` b span{
}blue {
color: rgb(0, 130, 170) !important;
}
.wordTableHtml table tr.table-header-row:nth-of-type(2) td {
border-bottom: 1px solid #000 !important;
}
mjx-container {
font-size: 14px !important;
;
}
wmath{
width: 100%;
display: block;
display: flex;
}
Info{
color:#ff8f25;
}
`;
export default {
name: 'tinymce',
@@ -151,7 +138,9 @@ export default {
},
isEdit: {},
toolbar: {
required: false
required: false,
},
menubar: {
default: 'file edit insert view format table '
@@ -159,7 +148,7 @@ export default {
height: {
type: Number,
required: false,
default: 400
default: 360
},
width: {
type: String,
@@ -231,12 +220,9 @@ export default {
},
watch: {
value(val) {
// console.log('val at line 208:', val);
console.log('val at line 208:', val);
if (!this.hasChange && this.hasInit) {
this.$nextTick(() => {
window.tinymce.get(this.tinymceId).setContent(val);
// window.renderMathJax(); // 主动触发 MathJax 渲染
});
this.$nextTick(() => window.tinymce.get(this.tinymceId).setContent(val));
}
}
},
@@ -252,10 +238,6 @@ export default {
this.destroyTinymce();
},
methods: {
openLatexEditor(data) {
this.$emit('openLatexEditor', data);
console.log('at line 254:', '打开数字公式');
},
handleSubmit() {
this.$refs.uploadImage.handleSubmit();
},
@@ -287,25 +269,25 @@ export default {
this.$forceUpdate();
},
generateUniqueId() {
return 'wmath-' + Math.random().toString(36).substr(2, 9);
},
initTinymce() {
var _this = this;
window.tinymce.init({
inline: false, // 使用 iframe 模式
selector: `#${this.tinymceId}`,
// noneditable_regexp: "/<wmath>.*?<\/wmath>/g",
content_css: false, // 禁用默认样式
table_resize_bars: true, // 启用拖动调整功能
valid_elements: this.type == 'table' ? '*[*]' : 'img[src|alt|width|height],strong,em,sub,sup,blue,table,b,i,wmath', // 允许的标签和属性
valid_elements: this.type == 'table' ? '*[*]' : 'img[src|alt|width|height],strong,em,sub,sup,blue,table,b,i', // 允许的标签和属性
// valid_elements: '*[*]', // 允许所有 HTML 标签
noneditable_editable_class: 'MathJax',
height: this.height,
paste_preprocess: function (plugin, args) {
let content = args.content; // 获取粘贴的内容
let content = args.content;
// 创建一个临时 div 元素来解析粘贴的 HTML
let tempDiv = document.createElement('div');
tempDiv.innerHTML = content;
// 检查粘贴的内容是否包含 <table> 元素
if (tempDiv.querySelector('table')) {
console.log('粘贴的内容包含表格');
if (_this.type == 'table') {
@@ -341,40 +323,18 @@ export default {
// _this.updateTableStyles(container); // 根据需要应用额外的样式
args.content = container.innerHTML; // 更新处理后的内容
});
} else {
}
} else {
console.log('Original content:', content); // 输出原始粘贴内容
// 改进的正则表达式,匹配 $$...$$ 格式的 LaTeX 公式
const mathRegex = /\$\$([^$]+)\$\$/g;
// 如果粘贴的内容包含 $$...$$ 格式的公式,进行处理
content = content.replace(mathRegex, function (match, formula) {
console.log('Matched formula:', formula); // 输出每个匹配的公式
// 将公式包裹在 <wmath> 标签中,保留 $$...$$ 结构
return `<wmath data-latex="${match}">${match}</wmath>`;
});
console.log('Processed content:', content); // 输出处理后的内容
}
// 更新 args.content 为处理后的内容
// 阻止默认的粘贴行为,确保自定义处理优先执行
if (args.event) {
args.event.preventDefault();
args.event.stopPropagation();
}
if (_this.isAutomaticUpdate) {
args.content = _this.$commonJS.transformHtmlString(content); // 更新处理后的内容
} else {
args.content = content;
args.content = _this.$commonJS.transformHtmlString(args.content); // 更新处理后的内容
}
console.log('粘贴的内容不包含表格');
}
// 阻止默认的粘贴行为
if (args.event) {
args.event.preventDefault(); // 阻止默认的粘贴处理
args.event.stopPropagation(); // 阻止事件冒泡,确保自定义处理优先执行
}
setTimeout(() => {
window.renderMathJax(_this.tinymceId);
}, 10);
},
content_style: `
@@ -397,9 +357,7 @@ export default {
statusbar: false, // 关闭底部状态栏
custom_colors: false,
color_map: ['0082AA', 'TMR Blue'],
plugins: 'texttransform kityformula-editor noneditable', // 启用 forecolor 和 code 插件
// plugins: 'forecolor code paste table image mathType searchreplace raw', // 启用 forecolor 和 code 插件
plugins: 'forecolor code paste table image mathType', // 启用 forecolor 和 code 插件
end_container_on_empty_block: true,
content_css: 'default', // 加载 TinyMCE 默认样式表
mathjax: {
@@ -411,43 +369,6 @@ export default {
setup(ed) {
_this.$commonJS.initEditorButton(_this, ed);
var currentWmathElement = null;
ed.on('click', function (e) {
const wmathElement = e.target.closest('wmath');
if (wmathElement) {
currentWmathElement = wmathElement; // 👈 保存当前点击的元素
const latexContentRaw = wmathElement.getAttribute('data-latex') || '';
console.log('at line 488: raw =', latexContentRaw);
// 去除所有 $ 符号
const latexContent = latexContentRaw.replace(/\$/g, '').trim();
console.log('at line 489: cleaned =', latexContent);
// 编码后用于传递到弹窗
const encoded = encodeURIComponent(latexContent);
// 给 wmath 添加唯一 data-id方便后续精准替换
let wmathId = wmathElement.getAttribute('data-id');
if (!wmathId) {
wmathId = 'wmath-' + Math.random().toString(36).substr(2, 9);
wmathElement.setAttribute('data-id', wmathId);
}
// 当前编辑器 ID 也保存下来(如果你有多个编辑器)
const editorId = ed.id;
// 打开编辑窗口并传参(传递 data-id + 内容)
window.open(
`/LateX?id=${encoded}&wmathId=${wmathId}&editorId=${editorId}`,
'_blank',
'width=1000,height=800,scrollbars=no,resizable=no'
);
}
});
ed.ui.registry.addButton('uploadWord', {
text: 'Word',
icon: 'import-word', // 使用自定义图标
@@ -473,23 +394,35 @@ export default {
}
});
// ed.ui.registry.addMenuButton('customDropdown', {
// text: _this.$t('commonTable.PaperRotation'), // 下拉框标题
// fetch: function (callback) {
// // 定义下拉框的内容
// const items = [..._this.typesettingTypeOptions];
// const menuItems = items.map((item) => ({
// type: 'menuitem',
// text: item.label,
// onAction: function () {
// _this.typesettingType = item.value;
// _this.changeTable();
// // ed.execCommand(item.value); // 执行命令
// }
// }));
// callback(menuItems);
// }
// });
ed.on('init', function () {
_this.$commonJS.inTinymceButtonClass();
const editorBody = ed.getBody();
// 监听点击事件来确保用户可以删除<wmath>元素
// 创建 MutationObserver 监听内容变化
const observer = new MutationObserver(() => {
const currentContent = ed.getContent();
// console.log('currentContent at line 447:', currentContent);
if (_this.isAutomaticUpdate) {
// _this.$emit('updateChange', _this.$commonJS.decodeHtml(currentContent));
_this.$commonJS.replaceWMathContent(currentContent, (res) => {
console.log('res at line 451:', res);
_this.$emit('updateChange', res);
});
_this.$emit('updateChange', ed.getContent());
}
});
@@ -535,11 +468,6 @@ export default {
});
ed.on('SetContent', function (e) {
const editorBody = ed.getBody();
ed.dom.select('wmath', editorBody).forEach(function (wmathElement) {
ed.dom.setAttrib(wmathElement, 'contenteditable', 'false');
// ed.dom.addClass(wmathElement, 'non-editable-wmath');
});
e.content = e.content.replace(/<strong>/g, '<b>').replace(/<\/strong>/g, '</b>');
e.content = e.content.replace(/<em>/g, '<i>').replace(/<\/em>/g, '</i>');
});
@@ -551,72 +479,14 @@ export default {
init_instance_callback: (editor) => {
if (_this.value) {
editor.setContent(_this.value);
console.log('at line 489:', ' 页面');
setTimeout(() => {
window.renderMathJax(_this.tinymceId); // 初始化时渲染 MathJax
}, 10);
}
_this.hasInit = true;
editor.on('NodeChange Change KeyUp SetContent', () => {
this.hasChange = true;
this.$emit('input', editor.getContent());
console.log('at line 518:', '改变');
// setTimeout(() => {
// window.renderMathJax(); // 初始化时渲染 MathJax
// }, 50);
});
}
});
if (!window._wmath_listener_registered) {
// 💾 新增公式插入点记录
let latexEditorBookmark = null;
let activeEditorId = null;
// 👂 message 监听器:处理编辑 + 新增两种情况
window.addEventListener('message', function (event) {
const data = event.data;
console.log('data at line 648:', data);
// ✅ 编辑现有公式:替换或删除
if (data && data.type === 'update-wmath') {
const { editorId, wmathId, latex } = data;
const newLatex = latex ? latex.trim() : '';
if (!editorId || !wmathId) return;
const targetEditor = tinymce.get(editorId);
if (!targetEditor) return;
const targetWmath = targetEditor.dom.select(`wmath[data-id="${wmathId}"]`, targetEditor.getBody())[0];
if (targetWmath) {
if (!newLatex) {
// ❌ 删除公式
targetEditor.dom.remove(targetWmath);
} else {
// ✅ 更新公式
targetWmath.setAttribute('data-latex', newLatex);
targetWmath.innerHTML = newLatex;
setTimeout(() => {
if (typeof renderMathJax === 'function') {
this.window.renderMathJax(editorId);
}
}, 10);
}
}
}
});
// 🚩 标记为已注册,防止重复
window._wmath_listener_registered = true;
// 🧠 导出保存位置函数(你可以在按钮点击时调用它)
window._recordLatexInsertContext = function (editorInstance) {
latexEditorBookmark = editorInstance.selection.getBookmark(2);
activeEditorId = editorInstance.id;
};
}
},
// 提取 Word 文件中的表格
@@ -639,16 +509,13 @@ export default {
window.tinymce.get(this.tinymceId).setContent(value);
},
//获取内容
async getContent(type) {
getContent(type) {
var content = window.tinymce.get(this.tinymceId).getContent();
console.log('content at line 627:', content);
content = content.replace(/<span[^>]*>/g, '').replace(/<\/span>/g, ''); // 去除span标签
content = content.replace(/<strong>/g, '<b>').replace(/<\/strong>/g, '</b>');
content = content.replace(/<em>/g, '<i>').replace(/<\/em>/g, '</i>');
content = content.replace(/&nbsp;/g, ' '); // 将所有 &nbsp; 替换为空格
console.log('content at line 632:', content);
this.$emit('getContent', type, content);
console.log('window.tinymce.get(this.tinymceId).getContent() at line 431:', content);
},
async export(type, data) {

View File

@@ -131,12 +131,10 @@
</div>
<div class="titHtml titHtml1" v-if="htmlContent && html_type == 2">
<common-word
:isPreview="true"
:readonly="true"
v-if="htmlContent"
ref="commonWord"
:value="htmlContent"
:contentList="mains"
:wordStyle="wordStyle"
style="width: calc(100%); height: 50vh"
:style="`100%`"
@@ -757,69 +755,69 @@ export default {
});
},
getWord() {
// var htmlContent = ``;
// htmlContent += this.mains
// .map((item) => {
// //批注
// let contentHtml = '';
// var isRemark = ``;
var htmlContent = ``;
htmlContent += this.mains
.map((item) => {
//批注
let contentHtml = '';
var isRemark = ``;
// // 判断是否是图片
// if (item.type == 1) {
// contentHtml = `
// <p contenteditable="false" main-state="${item.state}" class="MaxPicture pMain" data-id="${
// item.ami_id
// }" main-id="${item.am_id}">
// ${isRemark}
// <img src="${this.mediaUrl +'articleImage/'+ item.image.url}" style="width: ${
// item.width ? `${item.width}px` : '100%'
// }" />
// <font class="font" style="width: ${item.width ? `${item.width}px` : '100%'}" >${
// item.image.note ? item.image.note : ''
// }</font>
// </p>
// `;
// } else if (item.type == 2) {
// var tableList = JSON.parse(item.table.table_data);
// 判断是否是图片
if (item.type == 1) {
contentHtml = `
<p contenteditable="false" main-state="${item.state}" class="MaxPicture pMain" data-id="${
item.ami_id
}" main-id="${item.am_id}">
${isRemark}
<img src="${this.mediaUrl +'articleImage/'+ item.image.url}" style="width: ${
item.width ? `${item.width}px` : '100%'
}" />
<font class="font" style="width: ${item.width ? `${item.width}px` : '100%'}" >${
item.image.note ? item.image.note : ''
}</font>
</p>
`;
} else if (item.type == 2) {
var tableList = JSON.parse(item.table.table_data);
// contentHtml = `
// <div contenteditable="false" data-id="${item.amt_id}" main-state="${item.state}" main-id="${
// item.am_id
// }" class="thumbnailTableBox wordTableHtml table_Box pMain" style="width: 100%; padding: 8px 15px; box-sizing: border-box; border-radius: 4px; position: relative;">
// ${isRemark}
// <font class="font tableTitle" style="width:100%" >${item.table.title ? item.table.title : ''}</font>
// <table border="1" style="width: auto; border-collapse: collapse; text-align: center; ">
// ${tableList
// .map((row) => {
// return `
// <tr>
// ${row
// .map((cell) => {
// return `
// <td colspan="${cell.colspan || 1}" rowspan="${cell.rowspan || 1}">
// <span>${cell.text || ''}</span>
// </td>
// `;
// })
// .join('')} <!-- join the cells in the row -->
// </tr>
// `;
// })
// .join('')} <!-- join the rows -->
// </table>
// <font class="font" style="width:100%" >${item.table.note ? item.table.note : ''}</font>
// </div>
// `;
// } else {
// contentHtml = `<p class="pMain" main-state="${item.state}" contenteditable="false" data-id="${item.am_id}" main-id="${item.am_id}">${isRemark}${item.content}</p>`;
// }
contentHtml = `
<div contenteditable="false" data-id="${item.amt_id}" main-state="${item.state}" main-id="${
item.am_id
}" class="thumbnailTableBox wordTableHtml table_Box pMain" style="width: 100%; padding: 8px 15px; box-sizing: border-box; border-radius: 4px; position: relative;">
${isRemark}
<font class="font tableTitle" style="width:100%" >${item.table.title ? item.table.title : ''}</font>
<table border="1" style="width: auto; border-collapse: collapse; text-align: center; ">
${tableList
.map((row) => {
return `
<tr>
${row
.map((cell) => {
return `
<td colspan="${cell.colspan || 1}" rowspan="${cell.rowspan || 1}">
<span>${cell.text || ''}</span>
</td>
`;
})
.join('')} <!-- join the cells in the row -->
</tr>
`;
})
.join('')} <!-- join the rows -->
</table>
<font class="font" style="width:100%" >${item.table.note ? item.table.note : ''}</font>
</div>
`;
} else {
contentHtml = `<p class="pMain" main-state="${item.state}" contenteditable="false" data-id="${item.am_id}" main-id="${item.am_id}">${isRemark}${item.content}</p>`;
}
// // 判断是否是表格类型
// 判断是否是表格类型
// return contentHtml;
// })
// .join('');
this.htmlContent = 'true';
return contentHtml;
})
.join('');
this.htmlContent = htmlContent;
console.log('this.htmlContent at line 820:', this.htmlContent)
},
getMainsInfo2(e) {

View File

@@ -1,201 +0,0 @@
<template>
<div class="block commonMajor" style="width: 100%">
<el-button type="primary" plain size="mini" @click="handleAdd" style="float:right"><i class="el-icon-plus" ></i>Add Field </el-button>
<el-dialog title="Add Field " :visible.sync="coreVisible1" width="780px" :close-on-click-modal="false">
<el-form :model="coreForm1" :rules="rules1" ref="core_Form1" label-width="140px" >
<el-form-item prop="major">
<span slot="label">
<i style="color: #f56c6c; margin-right: 4px">*</i>
Field
</span>
<div
v-for="(field, index) in fields"
:key="index"
class="cascader-container"
style="margin-bottom: 10px; display: flex; align-items: center; justify-content: space-between"
>
<!-- <span style="margin-right: 10px; font-size: 12px; color: #006699; font-weight: bold">Field {{ Number(index+1) }} :</span> -->
<el-cascader
:ref="`cascader${index}`"
@change="handleChange(index)"
v-model="field.selectedValue"
:placeholder="'Please select Field '"
:options="options"
:props="getProps()"
style="width: calc(100%)"
></el-cascader>
<!-- Delete button -->
<!-- <el-button size="mini" type="danger" style="margin-left: 10px;" @click="handleDelete(index)"><i class="el-icon-delete"></i></el-button> -->
</div>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="coreVisible1 = false">Cancel</el-button>
<el-button type="primary" @click="onSubmit_core1(coreForm1)">Save</el-button>
</span>
</el-dialog>
<!-- 渲染多个 el-cascader 组件 -->
</div>
</template>
<script>
export default {
props: {
userId: {
type: String,
default: ''
},
articleId: {
type: String,
default: ''
}
},
data() {
return {
rules1:{},
coreVisible1: false,
coreForm1: {
majorList: []
},
fields: [{}], // 用于存储多个领域的选项数据
options: [] // 用于存储级联选择的选项数据
};
},
created() {
this.loadFields(); // 初始化时加载数据
},
methods: {
handleChange(i) {
console.log('.blur at line 45:');
console.log('i at line 40:', i);
this.$nextTick(() => {
this.$refs[`cascader${i}`][0].dropDownVisible = false;
this.coreForm1.majorList = this.fields[i].selectedValue;
this.$forceUpdate();
});
},
onSubmit_core1(coreForm) {
console.log('coreForm at line 1963:', coreForm);
if(!this.fields[0].selectedValue||this.fields[0].selectedValue.length == 0){
this.$message.error('Please select Field !');
return false;
}
this.$refs.core_Form1.validate((valid) => {
if (valid) {
var data={
major_id: this.coreForm1.majorList[this.coreForm1.majorList.length - 1]
}
if(this.userId){
data.user_id = this.userId;
}else{
data.article_id = this.articleId;
}
this.$api
.post(this.userId?'api/User/addUserMajor':'api/Major/addMajorByArticleIdForEditor', {
...data
})
.then((res) => {
if (res.code == 0) {
this.$message.success('Personal information modified successfully!');
this.coreVisible1 = false;
// this.tipVisible = false;
this.$emit('load')
} else {
this.$message.error(res.msg);
}
})
.catch((err) => {
this.$message.error(err);
});
} else {
this.$message.error('error submit!!');
return false;
}
});
},
// 动态添加一个新的 Cascader
handleAdd() {
this.$nextTick(() => {
this.fields=[]
this.fields.push({ selectedValue: [] }); // 添加一个新的字段
this.coreVisible1 = true;
});
},
// 删除指定的 Cascader
handleDelete(index) {
this.fields.splice(index, 1); // 删除指定索引的字段
},
// 获取 Cascader 配置
getProps() {
return {
value: 'value',
label: 'label',
children: 'children',
checkStrictly: true, // 允许任意选择一级
expandTrigger: 'hover' // 使用 hover 触发展开
};
},
// API 调用,获取子节点数据
getMajor(majorId) {
return this.$api
.post('api/Ucenter/getMajor', { major_id: majorId })
.then((response) => response.data)
.catch((error) => {
console.error('API Error:', error);
return [];
});
},
// 加载多个领域数据
loadFields() {
this.$api.post('api/Major/getMajorList', {}).then((res) => {
const transformData = (data) => {
return data.map((item) => {
const transformedItem = {
...item,
value: item.major_id,
label: `${item.major_title}`
};
// 如果存在 children递归处理
if (item.children && item.children.length > 0) {
transformedItem.children = transformData(item.children);
}
return transformedItem;
});
};
// 执行递归,获取选项数据
const data = transformData(res.data.majors.find((item) => item.major_id == 1).children);
this.options = [...data]; // 将选项数据赋给 options
});
}
}
};
</script>
<style scoped>
/* 你可以根据需要自定义样式 */
.cascader-container {
display: flex;
align-items: center;
justify-content: space-between;
}
::v-deep input[aria-hidden='true'] {
display: none !important;
}
</style>

View File

@@ -1,208 +0,0 @@
<template>
<div class="block commonMajor" style="width: 100%;overflow: hidden;">
<el-button type="primary" plain size="mini" @click="handleAdd" style="float:right;margin-bottom: 20px;"><i class="el-icon-plus" ></i>Add Field </el-button>
<div
v-for="(field, index) in fields"
:key="index"
class="cascader-container"
style="margin-bottom: 10px; display: flex; align-items: center; justify-content: space-between"
>
<span style="margin-right: 10px; font-size: 12px; color: #006699; font-weight: bold">Field {{ Number(index+1) }} :</span>
<el-cascader
:ref="`cascader${index}`"
@change="handleChange(index)"
v-model="field.selectedValue"
:placeholder="'Please select Field '"
:options="options"
:props="getProps()"
style="width: calc(100% - 120px)"
></el-cascader>
<!-- Delete button -->
<el-button size="mini" type="danger" style="margin-left: 10px;" @click="handleDelete(index)"><i class="el-icon-delete"></i></el-button>
</div>
<!-- <el-dialog title="Add Field " :visible.sync="coreVisible1" width="780px" :close-on-click-modal="false">
<el-form :model="coreForm1" :rules="rules1" ref="core_Form1" label-width="140px" >
<el-form-item prop="major">
<span slot="label">
<i style="color: #f56c6c; margin-right: 4px">*</i>
Field
</span>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="coreVisible1 = false">Cancel</el-button>
<el-button type="primary" @click="onSubmit_core1(coreForm1)">Save</el-button>
</span>
</el-dialog> -->
<!-- 渲染多个 el-cascader 组件 -->
</div>
</template>
<script>
export default {
props: {
userId: {
type: String,
default: ''
},
list: {
type: Array,
default: []
}
},
watch: {
list: {
handler(e) {
this.fields=this.list.length>0?[...this.list]:[{}]
},
immediate: true
},
},
data() {
return {
rules1:{},
coreVisible1: false,
coreForm1: {
majorList: []
},
fields: [], // 用于存储多个领域的选项数据
options: [] // 用于存储级联选择的选项数据
};
},
created() {
this.loadFields(); // 初始化时加载数据
},
methods: {
handleChange(i) {
console.log('.blur at line 45:');
console.log('i at line 40:', i);
this.$nextTick(() => {
this.$refs[`cascader${i}`][0].dropDownVisible = false;
this.coreForm1.majorList = this.fields[i].selectedValue;
this.$emit('load',this.fields)
this.$forceUpdate();
});
},
onSubmit_core1(coreForm) {
console.log('coreForm at line 1963:', coreForm);
if(!this.fields[0].selectedValue||this.fields[0].selectedValue.length == 0){
this.$message.error('Please select Field !');
return false;
}
this.$refs.core_Form1.validate((valid) => {
if (valid) {
this.$api
.post('api/User/addUserMajor', {
user_id: this.userId,
major_id: this.coreForm1.majorList[this.coreForm1.majorList.length - 1]
})
.then((res) => {
if (res.code == 0) {
this.$message.success('Personal information modified successfully!');
this.coreVisible1 = false;
// this.tipVisible = false;
this.$emit('load')
} else {
this.$message.error(res.msg);
}
})
.catch((err) => {
this.$message.error(err);
});
} else {
this.$message.error('error submit!!');
return false;
}
});
},
// 动态添加一个新的 Cascader
handleAdd() {
this.$nextTick(() => {
// this.fields=[]
this.fields.push({ selectedValue: [] }); // 添加一个新的字段
this.$emit('load',this.fields)
// this.coreVisible1 = true;
});
},
// 删除指定的 Cascader
handleDelete(index) {
this.fields.splice(index, 1); // 删除指定索引的字段
this.$emit('load',this.fields)
},
// 获取 Cascader 配置
getProps() {
return {
value: 'value',
label: 'label',
children: 'children',
checkStrictly: true, // 允许任意选择一级
expandTrigger: 'hover' // 使用 hover 触发展开
};
},
// API 调用,获取子节点数据
getMajor(majorId) {
return this.$api
.post('api/Ucenter/getMajor', { major_id: majorId })
.then((response) => response.data)
.catch((error) => {
console.error('API Error:', error);
return [];
});
},
// 加载多个领域数据
loadFields() {
this.$api.post('api/Major/getMajorList', {}).then((res) => {
const transformData = (data) => {
return data.map((item) => {
const transformedItem = {
...item,
value: item.major_id,
label: `${item.major_title}`
};
// 如果存在 children递归处理
if (item.children && item.children.length > 0) {
transformedItem.children = transformData(item.children);
}
return transformedItem;
});
};
// 执行递归,获取选项数据
const data = transformData(res.data.majors.find((item) => item.major_id == 1).children);
this.options = [...data]; // 将选项数据赋给 options
});
}
}
};
</script>
<style scoped>
/* 你可以根据需要自定义样式 */
.cascader-container {
width: 100%;
/* margin-top: 40px; */
display: flex;
align-items: center;
justify-content: space-between;
}
::v-deep input[aria-hidden='true'] {
display: none !important;
}
</style>

View File

@@ -66,7 +66,7 @@
</div>
<div class="SettlementInstallmentOptionArea">
<div class="optionArea">
<!-- <div
<div
class="installmentOption"
:class="selectedPaymentMethod == 'PayPal' ? 'isSelect' : ''"
@click="selectPaymentMethod('PayPal')"
@@ -92,36 +92,6 @@
</div>
<div v-if="selectedPaymentMethod === 'PayPal'" class="checkmark"></div>
</div>
</div> -->
<div
class="installmentOption"
:class="selectedPaymentMethod == 'Paystation' ? 'isSelect' : ''"
@click="selectPaymentMethod('Paystation')"
>
<div
class="ant-row trade-layout-row"
style="height: 100%; align-items: center; justify-content: flex-start"
>
<div class="trade-layout-leaf">
<div class="iconWrapper">
<img src="@/assets/img/paystation.png" class="icon" />
</div>
</div>
<div
class="ant-col trade-layout-col"
style="width: 74%; align-items: flex-start; justify-content: flex-start"
>
<div class="trade-layout-leaf" style="width: 100%">
<div
class="clamp-wrap clamp-ellipsis mainTitle"
style="-webkit-line-clamp: unset; color: #a2a91b"
>
Paystation
</div>
</div>
</div>
<div v-if="selectedPaymentMethod === 'Paystation'" class="checkmark"></div>
</div>
</div>
<!-- <div
class="installmentOption"
@@ -184,8 +154,7 @@ export default {
articleInfo: {},
journalInfo: {},
total: '',
// selectedPaymentMethod: 'PayPal', // 默认选中 PayPal
selectedPaymentMethod: 'Paystation', // 默认选中 PayPal
selectedPaymentMethod: 'PayPal', // 默认选中 PayPal
articleId: this.$route.query.id,
urlList: {
detail: 'api/Order/preOrderDetail',
@@ -220,35 +189,8 @@ export default {
if (this.selectedPaymentMethod == 'PayPal') {
this.getPayPal();
}else if (this.selectedPaymentMethod == 'Paystation') {
this.getPaystation();
}
},
getPaystation() {
const loading = this.$loading({
lock: true,
text: 'Loading',
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)'
});
var that = this;
this.$api
.post(this.urlList.createdOrder, {
article_id: this.articleId,
type: 2
})
.then((res) => {
console.log('res at line 222:', res);
if (res.code == 0) {
window.location.href = res.data.detail.paystation_url;
loading.close();
} else {
this.$message.error(res.data.msg);
loading.close()
}
});
},
getPayPal(id) {
var that = this;
window.paypal

View File

@@ -1,5 +1,5 @@
<template>
<div class="success-box" v-if="articleInfo.order_sn">
<div class="success-box" v-if="articleInfo.accept_sn">
<div class="payment-success">
<div style="display: flex; align-items: center; margin-bottom: 10px">
<h2 style="margin: 0 auto; display: flex; align-items: center">
@@ -10,11 +10,11 @@
<p>
Article ID:
<span style="color: #333; font-weight: 600"> {{ articleInfo.order_sn }}</span>
<span style="color: #333; font-weight: 600"> {{ articleInfo.accept_sn }}</span>
</p>
<p>
Total Amount: <span style="color: #ff5000"></span
><span style="color: #ff5000; font-size: 24px; line-height: 24px">{{ formatAmount(total) }} <span class="" style="font-size: 20px;">{{ articleInfo.paystation.currency }}</span></span>
Total Amount: <span style="color: #ff5000"><span class="currency">$</span></span
><span style="color: #ff5000; font-size: 24px; line-height: 24px">{{ formatAmount(total) }}</span>
</p>
<!-- <p>Payment Method: {{ paymentMethod }}</p> -->
<p>You will receive an email confirmation shortly.</p>
@@ -30,7 +30,7 @@ export default {
return {
alertShow: true,
urlList: {
detail: 'api/Preaccept/getPreacceptPayment',
detail: 'api/Order/preOrderDetail',
createdOrder: 'api/Order/creatArticleOrder'
},
articleInfo: {},
@@ -68,10 +68,10 @@ export default {
.then((res) => {
console.log('res at line 191:', res);
if (res.code == 0) {
this.articleInfo = res.data.order;
// this.journalInfo = res.data.journal_detail;
this.articleInfo = res.data.article_detail;
this.journalInfo = res.data.journal_detail;
this.total = Number(res.data.order.paystation.amount / 100);
this.total = this.journalInfo.fee;
}
});
},

View File

@@ -1,151 +0,0 @@
<template>
<div style="position: fixed;top: 0;left: 0;background-color: #f8f8f8; width: 100%; height: 100%; overflow: hidden; background: linear-gradient(to top, #fbfffe, #ebf9ff);">
<div class="navbar-default">
<div class="nav commonWidth" style="height: 100%">
<div class="title">Digital Formula Editor</div>
</div>
</div>
<div class="commonWidth" style="padding:40px 20px; box-sizing: border-box;">
<!-- <div style="margin-bottom: 20px;font-size: 20px;">Numerical formula:</div> -->
<div style="display: flex;align-items: center;justify-content: space-between;">
<div ref="mathField" class="math-container" style="width: calc(100% - 100px);"></div>
<span @click="copyLatex" style="font-size: 20px;width: 80px;cursor: pointer;">📋 Copy </span>
</div>
<!-- 公式显示框 -->
<div class="formula-box" :style="{ opacity: showLatex ? 1 : 0 }">
<p>LaTeX 代码:</p>
<textarea ref="latexBox" class="latex-text" readonly>$${{ latex }}$$</textarea>
</div>
</div>
</div>
</template>
<script>
import { MathfieldElement } from 'mathlive';
export default {
data() {
return {
latex: '', // 默认公式
// latex: '\\frac{a}{b} + \\sqrt{x^2 + y^2} + e^{i\\pi}', // 默认公式
mathFieldInstance: null,
showLatex: false, // 控制 LaTeX 代码框的显示与隐藏
};
},
mounted() {
if (this.$refs.mathField) {
// 创建 MathfieldElement 组件
const mf = new MathfieldElement();
mf.style.width = '100%';
mf.virtualKeyboardMode = 'manual'; // 显示虚拟键盘
mf.value = this.latex; // 设置默认值
// 监听输入变化,更新 LaTeX 代码
mf.addEventListener('input', (event) => {
this.latex = event.target.value;
});
// 挂载到 DOM
this.$refs.mathField.appendChild(mf);
this.mathFieldInstance = mf;
// 强制显示虚拟键盘并保持显示
mf.executeCommand('showVirtualKeyboard');
// 保证虚拟键盘持续显示
this.keepKeyboardVisible(mf);
} else {
console.error('MathLive 未正确加载');
}
},
methods: {
keepKeyboardVisible(mf) {
// 每秒确保虚拟键盘显示
setInterval(() => {
mf.executeCommand('showVirtualKeyboard');
}, 20); // 每秒确保键盘显示
},
copyLatex() {
if (this.$refs.latexBox) {
this.$refs.latexBox.select(); // 选中文本
document.execCommand('copy'); // 复制到剪贴板
setTimeout(( )=>{
window.close();
},100)
}
},
},
beforeDestroy() {
this.mathFieldInstance = null; // 组件销毁时清除实例
}
};
</script>
<style scoped>
.commonWidth {
width: 100%;
margin: 0 auto;
}
.title {
font-size: 32px;
font-weight: bold;
line-height: 80px;
background-color: #0f4eb6;
color: #fff;
}
.navbar-default {
width: 100%;
height: 80px;
background-color: #0f4eb6;
border-color: #e7e7e7;
}
.math-container {
min-height: 40px;
border: 1px solid #ccc;
padding: 5px;
font-size: 18px;
/* margin-bottom: 20px; */
}
/* 公式弹出框样式 */
.formula-box {
margin-top: 10px;
padding: 10px;
border: 1px solid #ccc;
background-color: #f9f9f9;
display: flex;
flex-direction: column;
align-items: flex-start;
}
/* LaTeX 代码框 */
.latex-text {
width: 100%;
height: 50px;
font-size: 16px;
border: 1px solid #ccc;
padding: 5px;
margin-bottom: 10px;
resize: none;
}
/* 复制按钮 */
button {
padding: 5px 10px;
background-color: #007bff;
color: white;
border: none;
cursor: pointer;
}
button:hover {
background-color: #0056b3;
}
/* 防止虚拟键盘覆盖 */
::v-deep .ML__virtual-keyboard-toggle {
opacity: 1 !important; /* 确保虚拟键盘的按钮可见 */
}
</style>

View File

@@ -1,335 +0,0 @@
<template>
<div
style="
background-color: #f8f8f8;
height: 100vh;
overflow: hidden;
background: linear-gradient(to top, #fbfffe, #ebf9ff);
z-index: 9999;
border-radius: 10px 10px 0 0;
box-shadow: 0 0 20px rgba(0, 0, 0, 0.1);
"
>
<div class="navbar-default" style="padding: 10px">
<div class="nav commonWidth" style="height: 100%">
<div class="title" style="padding: 0 0px; box-sizing: border-box">
<img src="@/assets/img/logo.png" style="width: 30px; height: 20px; margin-right: 10px" />
Digital Formula Editor
</div>
</div>
</div>
<div style="height: calc(100vh - 50px); overflow: hidden; padding-top: 20px; box-sizing: border-box">
<div
class="commonWidth"
style="width: calc(100% - 380px); height: 100%; padding-left: 20px; box-sizing: border-box; float: left"
>
<p style="padding: 10px 0; color: rgb(51, 51, 51); box-sizing: border-box">Numerical formula:</p>
<div ref="mathField" class="math-container" style="width: calc(100%)"></div>
<!-- 公式显示框 -->
<div class="formula-box" style="position: relative; margin-top: 20px">
<p style="padding: 10px 0; color: rgb(51, 51, 51); box-sizing: border-box">LaTeX Code:</p>
<div style="position: absolute; right: 10px; top: 45px">
<span @click="copyLatex" style="font-size: 16px; cursor: pointer; opacity: 0.6" disabled v-if="!this.latex"
>📋 Copy
</span>
<span @click="copyLatex" style="font-size: 16px; cursor: pointer; opacity: 1" v-else>📋 Copy </span>
<span style="margin: 0 10px; cursor: pointer">|</span>
<span style="color: red; cursor: pointer" @click="handleClear"
><i class="el-icon-delete-solid" style="color: red; margin-right: 4px"></i>Clear</span
>
</div>
<textarea ref="latexBox1" class="latexBox1" v-model="latex" @input="changeLatex"></textarea>
<textarea ref="latexBox" class="latex-text" readonly :style="{ opacity: showLatex ? 1 : 0 }" style="height: 0">
$${{ latex }}$$</textarea
>
</div>
<div style="margin-top: 10px; overflow: hidden">
<el-button type="primary" @click="SaveyLatex" style="background-color: #1654f7 !important; float: right"
>Submit</el-button
>
<el-button @click="handleCancel" style="float: right; margin-right: 10px">Cancel</el-button>
</div>
</div>
<div class="panel-default">
<p style="padding: 10px; color: #333; box-sizing: border-box">Formula Template</p>
<div class="panel-heading">
<div v-for="(item, index) in list" @click="changeSelectLateX(item, index)">
<p :class="currentSelect == index ? 'isSelect' : ''">
<span style="font-size: 12px; display: block; font-weight: bold">{{ item.titleEn }}</span>
<span style="font-size: 13px; display: block; font-weight: bold">{{ item.title }}</span>
</p>
</div>
</div>
<div
class="math-only"
v-for="(item, index) in list"
v-show="currentSelect == index"
style="height: calc(100% - 200px); overflow-y: auto"
>
<div
style="overflow-x: auto; overflow-y: hidden"
v-for="(v, i) in item.data"
:key="i"
class="math-block"
v-html="`$$${v}$$`"
@click="handleClick(v)"
></div>
</div>
</div>
</div>
</div>
</template>
<script>
import { MathfieldElement } from 'mathlive';
import formulaTemplates from './formulas.js';
export default {
props: ['LateXInfo'],
data() {
return {
currentSelect: 0,
list: formulaTemplates,
latex: '', // 默认公式
mathFieldInstance: null,
showLatex: false // 控制 LaTeX 代码框的显示与隐藏
};
},
mounted() {
// 获取并初始化公式
if (this.$route.query.id) {
this.latex = this.$route.query.id;
}
if (this.$refs.mathField) {
const mf = new MathfieldElement();
mf.style.width = '100%';
mf.style.height = '100%';
mf.virtualKeyboardMode = 'manual'; // 显示虚拟键盘
mf.value = this.latex;
// 监听输入变化,更新 LaTeX 代码
mf.addEventListener('input', (event) => {
this.latex = event.target.value;
});
this.$refs.mathField.appendChild(mf);
this.mathFieldInstance = mf;
// mf.executeCommand('showVirtualKeyboard');
// this.keepKeyboardVisible(mf);
} else {
console.error('MathLive 未正确加载');
}
this.renderMathInScope(); // 首次挂载后也渲染
},
methods: {
handleClick(value) {
console.log('value at line 115:', this.mathFieldInstance);
if (this.$refs.mathField) {
this.mathFieldInstance.value = value;
}
this.latex = value;
this.$forceUpdate();
},
changeLatex() {
if (this.$refs.mathField) {
this.mathFieldInstance.value = this.latex;
}
},
changeSelectLateX(item, index) {
this.currentSelect = index;
this.renderMathInScope();
// this.mathFieldInstance.value = this.latex;
},
escapeLaTeX(input) {
// 将所有单斜线 \ 替换为双斜线 \\
return input.replace(/\\/g, '\\\\');
},
renderMathInScope() {
this.$nextTick(() => {
setTimeout(() => {
const el = document.querySelector('.math-only');
console.log('el at line 121:', el);
if (window.MathJax && el) {
// MathJax.typesetClear([el]); // 清除旧渲染
window.MathJax.typesetPromise([el]).catch((err) => {
console.warn('MathJax 渲染失败:', err);
});
}
}, 500);
});
},
// keepKeyboardVisible(mf) {
// setInterval(() => {
// mf.executeCommand('showVirtualKeyboard');
// }, 50); // 每秒确保键盘显示
// },
copyLatex() {
if (this.latex == '') {
return;
}
if (this.$refs.latexBox) {
this.$refs.latexBox.select(); // 选中文本
document.execCommand('copy'); // 复制到剪贴板
this.$message({
message: 'Replicating Success',
type: 'success'
});
}
},
handleClear() {
this.latex = '';
this.mathFieldInstance.value = '';
this.$forceUpdate();
},
handleCancel() {
this.$emit('close');
},
SaveyLatex() {
const wmathId = this.$route.query.wmathId;
const editorId = this.$route.query.editorId;
// this.$emit('save', {
// latex: this.latex && this.latex != '' ? `$$${this.latex}$$` : '',
// editorId: this.LateXInfo.editorId,
// wmathId: this.LateXInfo.wmathId
// });
window.opener.postMessage(
{
type: 'update-wmath',
latex: this.latex && this.latex != '' ? `$$${this.latex}$$` : '',
editorId: editorId,
wmathId: wmathId
},
'*'
);
setTimeout(() => {
window.close();
// this.$emit('close');
}, 100);
}
},
beforeDestroy() {
this.mathFieldInstance = null; // 组件销毁时清除实例
}
};
</script>
<style scoped>
.commonWidth {
width: 100%;
margin: 0 auto;
}
.title {
font-size: 20px;
font-weight: bold;
line-height: 30px;
background-color: #0f4eb6;
color: #fff;
display: flex;
align-items: center;
}
.navbar-default {
width: 100%;
height: 30px;
background-color: #0f4eb6;
border-color: #e7e7e7;
}
.math-container {
height: 200px;
/* padding: 5px; */
font-size: 18px;
width: 100%;
}
.formula-box {
/* margin-top: 10px;
padding: 10px;
border: 1px solid #ccc;
background-color: #f9f9f9;
display: flex;
flex-direction: column;
align-items: flex-start; */
}
.latex-text {
width: 100%;
height: 50px;
font-size: 16px;
padding: 5px;
margin-bottom: 10px;
resize: none;
}
::v-deep .ML__virtual-keyboard-toggle {
opacity: 1 !important;
}
li {
line-height: none;
}
.panel-default {
width: 360px;
height: 100%;
float: right;
border: 1px solid #ddd;
background-color: #fff;
}
.panel-heading {
color: #333;
font-weight: bold;
background-color: #f5f5f5;
border-color: #ddd;
display: flex;
align-items: center;
justify-content: space-between;
flex-wrap: wrap;
}
.panel-heading div {
width: 25%;
padding: 5px 0px;
line-height: 20px;
border-radius: 4px;
text-align: center;
box-sizing: border-box;
}
.isSelect {
color: white !important;
background: #333;
border-radius: 4px;
}
.math-block {
background-color: #fff;
cursor: pointer;
background: #f0f0f0;
color: #000;
display: block;
margin: 10px;
padding: 6px;
/* min-height: 40px !important; */
border: 1px solid #ddd;
}
::v-deep .math-block mjx-container {
font-size: 18px !important;
margin: 0 !important;
text-align: left !important;
}
.latexBox1 {
width: 100%;
padding: 10px 140px 10px 10px;
box-sizing: border-box;
border: 1px solid #ccc;
background-color: #f9f9f9;
font-size: 18px;
resize: none;
height: 200px;
}
</style>

View File

@@ -6,24 +6,22 @@
<tinymce
type="table"
:height="height"
:id="id"
ref="tinymceChild1"
:wordStyle="wordStyle"
:isAutomaticUpdate="isAutomaticUpdate"
@getContent="getContent"
@openLatexEditor="openLatexEditor"
@updateChange="updateChange"
:value="value"
:typesettingType="typesettingType"
class="paste-area text-container"
:toolbar="`['bold italic|customBlue removeBlue|${!isAutomaticUpdate?'LateX|':''} myuppercase myuppercasea Line|subscript superscript|clearButton|searchreplace']`"
:toolbar="['bold italic|customBlue removeBlue|subscript superscript|clearButton']"
style="
/* white-space: pre-line; */
line-height: 12px;
max-height: 60vh;
overflow: auto;
font-size: 12px;
font-size: 14px; /* 字体大小 */
font-size: 7.5pt; /* 字体大小 */
margin-top: 0pt; /* 段前间距 */
margin-bottom: 0pt; /* 段后间距 */
@@ -36,7 +34,7 @@
<script>
import Tinymce from '@/components/page/components/Tinymce';
export default {
props: ['value','isAutomaticUpdate','height','id'],
props: ['value','isAutomaticUpdate','height'],
components: {
Tinymce
},
@@ -74,10 +72,6 @@ export default {
}
},
methods: {
openLatexEditor(data) {
this.$emit('openLatexEditor',data)
console.log('at line 254:', '打开数字公式');
},
updateChange(content){
this.$emit('updateChange',content)
},
@@ -85,7 +79,7 @@ export default {
this.$refs.tinymceChild1.getContent(type);
},
getContent(type, content) {
console.log('content at line 75:', content)
this.$emit('getContent', type, content);
}
}

View File

@@ -92,22 +92,22 @@ b span{
table-layout: auto; /* 自动调整列宽 */
text-align:left;
font-family:'Charis SIL' !important;
font-size: 14px !important;
font-size: 7.5000pt !important;
mso-font-kerning: 1.0000pt !important;
line-height: 20px !important;
mos-line-height: 20px !important;
line-height: 10pt !important;
mos-line-height: 10pt !important;
}
table td, table th {
padding: 5px;
text-align:left !important;
white-space: pre-wrap; /* 保留换行符并换行 */
word-wrap: nomarl; /* 长单词自动换行 */
word-break: nomarl;
word-wrap: break-word; /* 长单词自动换行 */
word-break: break-word;
font-family:'Charis SIL' !important;
font-size: 14px !important;
font-size: 7.5000pt !important;
mso-font-kerning: 1.0000pt !important;
line-height: 20px !important;
mos-line-height: 20px !important;
line-height: 10pt !important;
mos-line-height: 10pt !important;
}
table tbody tr td{
@@ -123,7 +123,7 @@ b span{
border-left:1px dashed #dcdfe6 !important;
border-right:1px dashed #dcdfe6 !important;
word-break: keep-all !important;
// text-align: justify !important; // 设置两端对齐
text-align: justify !important; // 设置两端对齐
}
@@ -134,27 +134,27 @@ b span{
margin:0;
font-family:'Charis SIL' !important;
font-size: 14px !important;
font-size: 7.5000pt !important;
mso-font-kerning: 1.0000pt !important;
line-height: 20px !important;
mos-line-height: 20px !important;
line-height: 10pt !important;
mos-line-height: 10pt !important;
}
table span{
color:#000000;text-align:left !important;
font-family:'Charis SIL' !important;
font-size: 14px !important;
font-size: 7.5000pt !important;
mso-font-kerning: 1.0000pt !important;
line-height: 20px !important;
mos-line-height: 20px !important;
line-height: 10pt !important;
mos-line-height: 10pt !important;
}
table .color-highlight{
color:rgb(0,130,170) !important;
font-family:'Charis SIL' !important;
font-size: 14px !important;
font-size: 7.5000pt !important;
mso-font-kerning: 1.0000pt !important;
line-height: 20px !important;
mos-line-height: 20px !important;
line-height: 10pt !important;
mos-line-height: 10pt !important;
}
table tr:first-child td {
border-top:1.0000pt solid #000 !important;mso-border-top-alt:0.5000pt solid #000 !important;border-bottom:1.0000pt solid #000 !important;mso-border-bottom-alt:0.5000pt solid #000 !important;

View File

@@ -1,168 +0,0 @@
const algebraFormulas = [
'\\left(x - 1\\right)\\left(x + 3\\right)', '\\sqrt{a^2 + b^2}',
'\\frac{a}{b}',
'x = \\frac{-b \\pm \\sqrt{b^2 - 4ac}}{2a}',
'(a + b)^2 = a^2 + 2ab + b^2',
'a^n \\cdot a^m = a^{n + m}',
'a^0 = 1',
'\\left(a + b + c\\right)^2',
'\\left ( \\frac{a}{b}\\right )^{n}=\\frac{a^{n}}{b^{n}}',
'\\frac{a}{b}\\pm \\frac{c}{d}=\\frac{ad \\pm bc}{bd}',
'\\frac{1}{\\sqrt{a}}=\\frac{\\sqrt{a}}{a},a\\ge 0\\frac{1}{\\sqrt{a}}=\\frac{\\sqrt{a}}{a},a\\ge 0',
'\\sqrt[n]{a^{n}}=\\left ( \\sqrt[n]{a}\\right )^{n}',
'a\\geqslant 0,b\\geqslant 0 \\sqrt[n]{\\frac{a}{b}}=\\frac{\\sqrt[n]{a}}{\\sqrt[n]{a}}',
'x=a_0+\\frac{1}{\\displaystyle a_1+\\frac{1}{ \\displaystyle a_2+\\frac{ 1}{ \\displaystyle a_3+ a_4}}}',
];
//数列
const sequenceFormulas = [
'a_{n}=a_{1}q^{n-1}',
'S_{n}=\\frac{n \\left( a_{1}+a\\_{n}\\right)}{2}',
'S_{n}=na_{1}+\\frac{n \\left( n-1 \\right)}{{2}}d',
'a_{n}=a_{1}+\\left( n-1 \\left) d\\right. \\right.',
];
//矩阵
const matrixFormulas = [
`A=A^{T}\\
A=-A^{T}`
];
const otherFormulas = [
'\\bigcup_{i=1}^{n}{X_i}',
'\\bigcap_{i=1}^{n}{X_i}',
];
const geometryFormulas = [
'\\overrightarrow{AB}',
'\\overleftrightarrow{AB}',
'\\widehat{AB}',
'\\Delta A B C',
'l \\perp \\beta,l \\subset \\alpha \\Rightarrow \\alpha \\perp \\beta',
'P \\in \\alpha,P \\in \\beta,\\alpha \\cap \\beta=l \\Rightarrow P \\in l',
'\\alpha \\perp \\beta,\\alpha \\cap \\beta=l,a \\subset \\alpha,a \\perp l \\Rightarrow a \\perp \\beta',
'A \\in l,B \\in l,A \\in \\alpha,B \\in \\alpha \\Rightarrow l \\subset \\alpha',
'\\alpha \\parallel \\beta,\\gamma \\cap \\alpha=a,\\gamma \\cap \\beta=b \\Rightarrow a \\parallel b',
'A \\in l,B \\in l,A \\in \\alpha,B \\in \\alpha \\Rightarrow l \\subset \\alpha',
'A = \\pi r^2',
'C = 2\\pi r',
'a^2 + b^2 = c^2',
'\\angle ABC = 90^\\circ',
'\\triangle ABC \\cong \\triangle DEF',
'V = \\frac{4}{3}\\pi r^3',
'P = 4a',
'S = \\frac{1}{2}ab\\sin C'
];
const inequalityFormulas = [
'a > b',
'x \\leq y',
'|x| < 1',
'\\left|x + y\\right| \\leq \\left|x\\right| + \\left|y\\right|',
'\\forall x > 0,\\; x^2 > 0',
'\\exists x \\in \\mathbb{R},\\; x < 0',
'a^2 + b^2 \\geq 2ab'
];
const equationFormulas = [
'y = mx + b',
'x^2 - 4 = 0',
'x^2 + y^2 = 1',
'e^x = \\sum_{n=0}^{\\infty} \\frac{x^n}{n!}',
'\\log_b xy = \\log_b x + \\log_b y',
'x = \\frac{-b \\pm \\sqrt{b^2 - 4ac}}{2a}',
'a_n = a_1 + (n-1)d',
`a\\mathop{{x}}\\nolimits^{{2}}+bx+c=0\\
\\Delta=\\mathop{{b}}\\nolimits^{{2}}-4ac\\
\\mathop{{x}}\\nolimits_{{1,2}}=\\frac{{-b \\pm \\sqrt{{\\mathop{{b}}\\nolimits^{{2}}-4ac}}}}{{2a}}\\
\\mathop{{x}}\\nolimits_{{1}}+\\mathop{{x}}\\nolimits_{{2}}=-\\frac{{b}}{{a}}\\
\\mathop{{x}}\\nolimits_{{1}}\\mathop{{x}}\\nolimits_{{2}}=\\frac{{c}}{{a}}`,
`\\frac{x^{2}}{a^{2}}-\\frac{y^{2}}{b^{2}}=1`,
`y=kx+b`,
`y-y_{1}=k \\left( x-x_{1}\\right)`,
];
const trigonometryFormulas = [
'\\cos^{-1}\\theta',
'\\sin^{-1}\\theta',
'e^{i \\theta}',
'\\text{sin}^{2}\\frac{\\alpha}{2}=\\frac{1- \\text{cos}\\alpha}{2}',
'\\text{sin}^{2}\\frac{\\alpha}{2}=\\frac{1- \\text{cos}\\alpha}{2}',
'\\text{cos}^{2}\\frac{\\alpha}{2}=\\frac{1+\\text{cos}\\alpha}{2}',
'\\text{tan}\\frac{\\alpha}{2}=\\frac{\\text{sin}\\alpha}{1+\\text{cos}\\alpha}',
'\\sin^2\\theta + \\cos^2\\theta = 1',
'\\tan\\theta = \\frac{\\sin\\theta}{\\cos\\theta}',
'\\sin(2\\theta) = 2\\sin\\theta\\cos\\theta',
'\\cos(2\\theta) = \\cos^2\\theta - \\sin^2\\theta',
'\\cot\\theta = \\frac{1}{\\tan\\theta}',
'\\sec\\theta = \\frac{1}{\\cos\\theta}'
];
const calculusFormulas = [
'\\frac{dy}{dx}',
'\\int x^2 \\, dx',
'\\int_a^b f(x) \\, dx',
'\\lim_{x \\to 0} \\frac{\\sin x}{x} = 1',
'\\sum_{n=1}^{\\infty} \\frac{1}{n^2} = \\frac{\\pi^2}{6}',
'f\'(x) = \\lim_{h \\to 0} \\frac{f(x+h)-f(x)}{h}',
'e^x = \\sum_{n=0}^{\\infty} \\frac{x^n}{n!}'
];
const statisticsFormulas = [
'\\mu = \\frac{1}{n} \\sum_{i=1}^{n} x_i',
'\\sigma = \\sqrt{\\frac{1}{n} \\sum_{i=1}^{n} (x_i - \\mu)^2}',
'E(X) = \\sum x \\cdot P(x)',
'P(A \\cap B) = P(A)P(B \\mid A)',
'\\binom{n}{r} = \\frac{n!}{r!(n-r)!}',
'P(A \\cup B) = P(A) + P(B) - P(A \\cap B)'
];
const physicsFormulas = [
'\\vec{F}=m\\vec{a}',
'e=m c^2',
'\\vec{F}=m \\frac{d \\vec{v}}{dt}+\\vec{v}\\frac{dm}{dt}',
'\\oint \\vec{F}\\cdot d\\vec{s}=0',
'\\vec{F}_g=-F\\frac{m_1 m_2}{r^2}\\vec{e}_r',
'\\psi (t)=\\hat{\\psi}e^{i(\\omega t\\,\\pm\,\\theta)}',
'\\sum_i \\hat{\\psi_i}cos(\\alpha_i \\pm \\omega t)',
'E = mc^2',
'F = ma',
'v = u + at',
's = ut + \\frac{1}{2}at^2',
'V = IR',
'P = \\frac{W}{t}'
];
const chemistryFormulas = [
'_{10}^{5}C^{16}',
'2H_2+O_2 \\xrightarrow{n,m}2H_2O',
'A\\underset{b}{\\overset{a}{\\longleftrightarrow}}B',
'A\\underset{0}{\\overset{a}{\\rightleftarrows}}B',
'A\\underset{0^{\\circ}C}{\\overset{100^{\\circ}C}{\\rightleftarrows}}B',
'\\ce{H2 + O2 -> H2O}',
'\\ce{CO2 + H2O <=> H2CO3}',
'\\ce{Na+ + Cl- -> NaCl}',
'PV = nRT'
];
const formulaTemplates = [
{ title: '代数', data: algebraFormulas, titleEn: 'Algebra' },
{ title: '几何', data: geometryFormulas, titleEn: 'Geometry' },
{ title: '不等式', data: inequalityFormulas, titleEn: 'Inequalities' },
{ title: '方程', data: equationFormulas, titleEn: 'Equations' },
{ title: '数列', data: sequenceFormulas, titleEn: 'Sequences' },
{ title: '矩阵', data: matrixFormulas, titleEn: 'Matrices' },
{ title: '统计学', data: statisticsFormulas, titleEn: 'Statistics' },
{ title: '三角', data: trigonometryFormulas, titleEn: 'Trigonometry' },
{ title: '物理', data: physicsFormulas, titleEn: 'Physics' },
{ title: '化学', data: chemistryFormulas, titleEn: 'Chemistry' },
{ title: '微积分', data: calculusFormulas, titleEn: 'Calculus' },
{ title: '其他', data: otherFormulas, titleEn: 'Others' },
];
export default formulaTemplates;

View File

@@ -1,6 +1,6 @@
<template>
<div>
<div>
<!--uploadWord |customButtonExportWord |customButtonExportImg -->
<tinymce
@@ -8,25 +8,23 @@
ref="tinymceChild1"
:wordStyle="wordStyle"
@getContent="getContent"
@openLatexEditor="openLatexEditor"
:height="calcDynamicWidth()"
:value="updatedHtml"
:typesettingType="typesettingType"
class="paste-area text-container"
:toolbar="['bold italic|customBlue removeBlue|kityformula-editor|LateX |myuppercase myuppercasea Line|subscript superscript|table tabledelete| searchreplace |clearButton']"
:toolbar="['bold italic|customBlue removeBlue|subscript superscript|table tabledelete| mathType |clearButton']"
style="
/* white-space: pre-line; */
line-height: 12px;
/* max-height: 60vh; */
max-height: 60vh;
overflow: auto;
font-size: 12px;
font-size: 14px; /* 字体大小 */
font-size: 7.5pt; /* 字体大小 */
margin-top: 0pt; /* 段前间距 */
margin-bottom: 0pt; /* 段后间距 */
"
></tinymce>
</div>
</div>
</template>
@@ -78,8 +76,8 @@ export default {
text-align: center;
table-layout: auto;"
>`;
this.tableData.forEach((row,i) => {
modalContent += `<tr class="${this.isHeaderRow(i,this.tableData)?'table-header-row':''}">`;
this.tableData.forEach((row) => {
modalContent += `<tr>`;
row.forEach((cell) => {
modalContent += `
<td
@@ -102,34 +100,16 @@ export default {
}
},
methods: {
openLatexEditor(data) {
this.$emit('openLatexEditor',data)
console.log('at line 254:', '打开数字公式');
},
calcDynamicWidth() {
const parentWidth = window.innerHeight; // 获取窗口宽度
const result = parentWidth - 420; // 计算 `100% - 200px`
return result ;
},
isHeaderRow(rowIndex,table) {
var head=table[0]
return rowIndex < head[0].rowspan; // 假设前两行是表头
},
getTableContent(type) {
this.$refs.tinymceChild1.getContent(type);
},
getContent(type, content) {
if (content) {
console.log('content at line 121:', content)
const container = document.createElement('div');
container.innerHTML = content;
this.$commonJS.parseTableToArray(content, (table) => {
console.log('res at line 104:', table);
// return false
this.$emit('getContent', type, { html_data: content, table: table });
});
} else {

File diff suppressed because it is too large Load Diff

View File

@@ -1,113 +1,18 @@
<template>
<div
class="tinymce-container editor-container word-container"
:style="!isPreview ? 'padding:10px 20px 10px 30px;' : 'padding:0px;'"
ref="scrollDiv"
>
<div class="tinymce-container editor-container word-container" :style="!isPreview ? 'padding:20px;' : 'padding:0px;'" ref="scrollDiv">
<div
style="
box-shadow: 0 2px 2px -2px rgba(34, 47, 62, 0.1), 0 8px 8px -4px rgba(34, 47, 62, 0.07);
margin: 0px 0;
margin: 10px 0;
box-sizing: border-box;
display: flex;
"
>
<div
v-if="!isPreview"
style="
border-bottom: 2px solid #c7cdcf;
background-color: #fff;
position: fixed;
top: 60px;
left: 285px;
z-index: 10;
right: 330px;
height: 60px;
display: flex;
align-items: center;
justify-content: space-between;
padding: 10px;
box-sizing: border-box;
overflow: hidden;
width: calc(100% - 285px - 330px);
"
>
<div style="width: auto; display: flex; align-items: center">
<!-- <el-checkbox v-model="checked" style="border-right: 1px solid #d8d8d8; padding: 0 20px 0 0;z-index: 10;" size="medium">Select All</el-checkbox> -->
<div
style="border-right: 1px solid #d8d8d8; padding: 0 20px"
:style="currentData.type == 0 ? 'Opacity:1' : 'Opacity:0.6'"
>
<ul class="HTitleBox">
<li
:style="currentData.is_h1 == 1 ? 'color:#4d99f1' : 'color:#333'"
@click="currentData.is_h1 == 0 ? changeTitle(1) : changeTitle(0)"
>
H1
</li>
<li
:style="currentData.is_h2 == 1 ? 'color:#4d99f1' : 'color:#333'"
@click="currentData.is_h2 == 0 ? changeTitle(2) : changeTitle(0)"
>
H2
</li>
<li
:style="currentData.is_h3 == 1 ? 'color:#4d99f1' : 'color:#333'"
@click="currentData.is_h3 == 0 ? changeTitle(3) : changeTitle(0)"
>
H3
</li>
</ul>
</div>
<div style="border-right: 1px solid #d8d8d8; padding: 0 20px">
<ul class="HTitleBox" style="border: none">
<li @click="addContent" style="font-size: 14px; padding: 0">
<i class="el-icon-document"> </i>
Batch Add content
</li>
</ul>
</div>
</div>
<div style="border-left: 1px solid #d8d8d8; padding: 0 20px; float: right">
<ul class="operateBox">
<li
v-if="isEditComment"
style="height: 40px; background-color: #fff !important; color: #f56c6c; border: 1px solid #f56c6c"
@mousedown="cacheSelection"
@click="handleSelection"
>
<i class="el-icon-document-add" style="margin-top: 2px"></i>
Comment
</li>
<li
style="height: 40px; background-color: #cbccd1 !important; color: #333; border: 1px solid #cbccd1"
@click="onAddRow"
>
<i class="el-icon-document-add" style="margin-top: 2px"></i>
Row
</li>
<li style="height: 40px" @click="onEdit">
<i class="el-icon-edit" style="margin-top: 2px"></i>
Edit
</li>
<li style="height: 40px; background-color: red !important" @click="onDelete">
<i class="el-icon-delete" style="margin-top: 2px"></i>
Delete
</li>
</ul>
</div>
</div>
<div
class=""
:style="isPreview ? 'width: 100%;padding: 20px;' : 'width: calc(100% - 300px);padding: 60px 20px 20px 34px;'"
:style="isPreview ? 'width: 100%' : 'width: calc(100% - 300px)'"
style="
padding: 20px;
box-sizing: border-box;
width: calc(100% - 300px);
float: left;
@@ -116,16 +21,8 @@
position: relative;
"
>
<!-- <common-late-x></common-late-x> -->
<template v-for="(item, index) in wordList">
<el-checkbox
@change="updateUniqueIds"
v-if="!isPreview"
v-model="item.checked"
style="position: absolute; left: -20px; width: 8px; height: 8px; margin-top: 8px"
></el-checkbox>
<span class="isRemark" :remark-main-id="item.am_id" v-if="item.checks && item.checks.length > 0 && !isPreview">
<span class="isRemark" :remark-main-id="item.am_id" v-if="item.checks.length > 0 && !isPreview">
><img
class="isRemark"
src="@/assets/img/isRemark.png"
@@ -135,58 +32,22 @@
<span>{{ item.am_id }}</span>
</span>
<div
:class="!isPreview ? (item.is_h1 ? 'isTitleH1' : item.is_h2 ? 'isTitleH2' : item.is_h3 ? 'isTitleH3' : '') : ''"
style="line-height: 24px"
>
<template v-if="!isPreview">
<span class="Htitle Htitle1" v-if="item.is_h1 == 1">H1</span>
<span class="Htitle Htitle2" v-else-if="item.is_h2 == 1">H2</span>
<span class="Htitle Htitle3" v-else-if="item.is_h3 == 1">H3</span></template
>
<div :class="currentId == item.am_id ? 'glowing-border' : ''" style="position: relative">
<div
v-if="currentId == item.am_id"
style="background-color: #fff; z-index: 100; position: absolute; right: 0px; top: -40px"
>
<el-button
v-if="currentId == item.am_id"
style="background-color: #006699d1; font-weight: bold; color: #fff; font-size: 16px !important"
:style="index == 0 ? ' opacity: 0.2;' : ' opacity: 1;'"
size="mini"
plain
:disabled="index != 0 ? false : true"
@click="changeSort('up')"
></el-button
>
<el-button
v-if="currentId == item.am_id"
style="background-color: #006699d1; font-weight: bold; color: #fff; font-size: 16px !important"
size="mini"
:style="index == wordList.length - 1 ? ' opacity: 0.2;' : ' opacity: 1;'"
plain
:disabled="index == wordList.length - 1 ? true : false"
@click="changeSort('down')"
></el-button
>
</div>
<div
@dblclick="dblclickEdit(item.am_id, 'img', item, index)"
:key="item.am_id"
id="drop-target"
:class="highlightImg(item.ami_id, item.checks ? item.checks : [])"
:comment-Id="highlightImgCommentId(item.ami_id, item.checks ? item.checks : [])"
:class="highlightImg(item.ami_id, item.checks)"
:comment-Id="highlightImgCommentId(item.ami_id, item.checks)"
@dragover="handleDragOver"
@dragenter="handleDragEnter"
@dragleave="handleDragLeave"
@drop="handleDrop"
class="MaxPicture pMain myeditabledivImage drop-target"
@click="initializeEditor(item.am_id, 'img', item, index)"
@click="initializeEditor(item.am_id, 'img', item)"
v-if="item.type == 1"
:main-state="item.state"
:remark="item.checks && item.checks.length > 0 ? 1 : 0"
:remark="item.checks.length > 0 ? 1 : 0"
:contenteditable="!readonly && !isPreview"
:data-id="item.ami_id"
:type="item.type"
:main-id="item.am_id"
@@ -195,78 +56,70 @@
<img :src="`${mediaUrl + item.image.url}`" />
<font class="font" :style="`width: ${item.width ? `${item.width}px` : '100%'}`">
<span
v-html="item.image.note ? highlightText(item.image.note, item.checks ? item.checks : []) : ''"
></span>
<span v-html="item.image.note ? highlightText(item.image.note, item.checks) : ''"></span>
</font>
</div>
<div
@dblclick="dblclickEdit(item.am_id, 'table', item, index)"
id="drop-target"
@dragover="handleDragOver"
@dragenter="handleDragEnter"
@dragleave="handleDragLeave"
@drop="handleDrop"
@click="initializeEditor(item.am_id, 'table', item, index)"
@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 && item.checks.length > 0 ? 1 : 0"
: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%'}`" style="text-align: center">
<span v-html="highlightText(item.table.title || '', item.checks ? item.checks : [])"></span>
<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: 100%; border-collapse: collapse; text-align: center">
<tr
v-for="(row, i) in JSON.parse(item.table.table_data)"
:key="i"
:class="{ 'table-header-row': isHeaderRow(i, item.table.table_data) }"
>
<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 ? item.checks : [])"></span>
: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 ? item.checks : [])"></span>
<span v-html="highlightText(item.table.note || '', item.checks)"></span>
</font>
</div>
</div>
<div
@dblclick="dblclickEdit(item.am_id, 'text', item, index)"
v-else
id="drop-target"
@dragover="handleDragOver"
@dragenter="handleDragEnter"
@dragleave="handleDragLeave"
@drop="handleDrop"
@click="initializeEditor(item.am_id, 'text', item, index)"
@click="initializeEditor(item.am_id)"
class="pMain myeditablediv drop-target"
v-else
@blur="clearEditor(item.am_id)"
:main-state="item.state"
:remark="item.checks && item.checks.length > 0 ? 1 : 0"
:remark="item.checks.length > 0 ? 1 : 0"
:contenteditable="!readonly && !isPreview"
:data-id="item.am_id"
:main-id="item.am_id"
:type="item.type"
:id="'editor' + item.am_id"
v-html="highlightText(item.content, item.checks ? item.checks : [], item.type)"
v-html="highlightText(item.content, item.checks)"
></div>
</div>
</div>
</template>
</div>
@@ -275,7 +128,7 @@
style="
width: 310px;
position: fixed;
top: 70px;
top: 60px;
box-sizing: border-box;
right: 10px;
bottom: 0;
@@ -285,10 +138,11 @@
class="commentList"
>
<li
v-for="(item, index) in commentList"
class="comment-item annotation"
:data-target="`main-${item.am_id}`"
style="width: 100%; margin: 0 0 10px; background: #fafafa; box-sizing: border-box"
style="width: 100%; margin: 10px 0; background: #fafafa; box-sizing: border-box"
>
<div>
<div style="display: flex; align-items: center; justify-content: space-between; background-color: #f3d5d5c2">
@@ -304,21 +158,22 @@
</el-link>
</div>
<div
style="padding: 6px 6px; box-sizing: border-box; border-bottom: 1px solid rgba(243, 213, 213)"
:style="commont.estate == 1 ? 'background:#13bc200f;' : ''"
style="
margin-bottom: 10px;
padding: 10px 10px;
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)"
>
<div style="width: 100%; display: flex; align-items: center; justify-content: space-between">
<div style="display: flex; align-items: center; line-height: 20px">
<span
:style="commont.estate == 1 ? 'opacity:0.6;color:rgb(19, 188, 32);' : ''"
style="color: #e61a12; font-weight: bold; font-size: 12px"
<div style="display: flex; align-items: center">
<span :style="commont.estate == 1 ? 'opacity:0.6;color:rgb(19, 188, 32);' : ''" style="color: #e61a12; font-weight: bold"
>{{ commentIndex + 1 }}</span
>
<span
style="color: rgb(230, 26, 18); font-size: 12px"
:style="commont.estate == 1 ? 'opacity:0.6;color:rgb(19, 188, 32);' : ''"
<span style="color: rgb(230, 26, 18); font-size: 12px" :style="commont.estate == 1 ? 'opacity:0.6;color:rgb(19, 188, 32);' : ''"
>Comment</span
>
<!-- <img
@@ -328,11 +183,9 @@
style="width: 30px; height: 14px"
/> -->
<span v-if="commont.estate == 1" class="Resolved" :style="commont.estate == 1 ? 'opacity:0.6;' : ''">{{
$t('commonTable.Resolved')
}}</span>
<span v-if="commont.estate == 1" class="Resolved" :style="commont.estate == 1 ? 'opacity:0.6;' : ''">{{ $t('commonTable.Resolved') }}</span>
</div>
<div style="display: flex; align-items: center; justify-content: center; line-height: 20px">
<div style="display: flex; align-items: center; justify-content: center">
<span style="color: #b8b7b7; font-size: 12px">{{ getTime(commont.ctime) }}</span
><span
style="color: #aaa; font-size: 13px; margin: 0 4px"
@@ -439,10 +292,7 @@
"
>
<i class="el-icon-user-solid" style="color: #333; padding: 0 4px"></i>
<div
v-html="commont.author_remark"
style="width: calc(100% - 20px); font-size: 13px; line-height: 14px"
></div>
<div v-html="commont.author_remark" style="width: calc(100% - 20px); font-size: 14px"></div>
</div>
<i
class="el-icon-edit"
@@ -513,22 +363,22 @@ b span{
table-layout: auto; /* 自动调整列宽 */
text-align:left;
font-family:'Charis SIL' !important;
font-size: 14px !important;
font-size: 7.5000pt !important;
mso-font-kerning: 1.0000pt !important;
line-height: 20px !important;
mos-line-height: 20px !important;
line-height: 10pt !important;
mos-line-height: 10pt !important;
}
table td, table th {
padding: 5px;
text-align: !important;
text-align:left !important;
white-space: pre-wrap; /* 保留换行符并换行 */
word-wrap: nomarl; /* 长单词自动换行 */
word-break: nomarl;
word-wrap: break-word; /* 长单词自动换行 */
word-break: break-word;
font-family:'Charis SIL' !important;
font-size: 14px !important;
font-size: 7.5000pt !important;
mso-font-kerning: 1.0000pt !important;
line-height: 20px !important;
mos-line-height: 20px !important;
line-height: 10pt !important;
mos-line-height: 10pt !important;
}
table tbody tr td{
@@ -540,9 +390,11 @@ b span{
border-top:none;mso-border-top-alt:none !important;
border-bottom:none !important;
mso-border-bottom-alt:none !important;
border:1px dashed #dcdfe6 !important;
border-left:1px dashed #dcdfe6 !important;
border-right:1px dashed #dcdfe6 !important;
word-break: keep-all !important;
// text-align: justify !important; // 设置两端对齐
text-align: justify !important; // 设置两端对齐
}
@@ -553,27 +405,27 @@ b span{
margin:0;
font-family:'Charis SIL' !important;
font-size: 14px !important;
font-size: 7.5000pt !important;
mso-font-kerning: 1.0000pt !important;
line-height: 20px !important;
mos-line-height: 20px !important;
line-height: 10pt !important;
mos-line-height: 10pt !important;
}
table span{
color:#000000;text-align:left !important;
font-family:'Charis SIL' !important;
font-size: 14px !important;
font-size: 7.5000pt !important;
mso-font-kerning: 1.0000pt !important;
line-height: 20px !important;
mos-line-height: 20px !important;
line-height: 10pt !important;
mos-line-height: 10pt !important;
}
table .color-highlight{
color:rgb(0,130,170) !important;
font-family:'Charis SIL' !important;
font-size: 14px !important;
font-size: 7.5000pt !important;
mso-font-kerning: 1.0000pt !important;
line-height: 20px !important;
mos-line-height: 20px !important;
line-height: 10pt !important;
mos-line-height: 10pt !important;
}
table tr:first-child td {
border-top:1.0000pt solid #000 !important;mso-border-top-alt:0.5000pt solid #000 !important;border-bottom:1.0000pt solid #000 !important;mso-border-bottom-alt:0.5000pt solid #000 !important;
@@ -650,15 +502,6 @@ export default {
},
data() {
return {
cachedHtml: '', // 缓存选中的 HTML
cachedText: '', // 缓存选中的纯文本
cachedMainId: null, // 选中的 main-id
cachedType: null, // 选中的 type
currentId: null,
currentIndex: null,
checked: false,
currentData: {},
imagePath: require('@/assets/img/carriageReturn.png'), // 或者你可以设置其他路径
scrollPosition: 0,
wordList: [],
commentList: [],
@@ -704,7 +547,6 @@ export default {
}
],
uploadReset: false,
uniqueIds: [],
dialogVisible: false,
form: {
name: '',
@@ -731,7 +573,6 @@ export default {
if (val) {
this.wordList = [...this.contentList];
this.$nextTick(() => {
window.renderMathJax(); // 主动触发 MathJax 渲染
this.getCommentsData();
});
}
@@ -739,18 +580,12 @@ export default {
deep: true // 启用深度监听
}
},
computed: {
selectedIds() {
return this.wordList.filter((item) => item.checked).map((item) => item.am_id);
}
},
updated() {
// 恢复子组件的滚动位置
// this.$refs.scrollDiv.scrollTop = this.scrollPosition;
},
mounted() {
this.$nextTick(() => {
window.renderMathJax(); // 主动触发 MathJax 渲染
this.getCommentsData();
if (!this.isPreview && localStorage.getItem('scrollPosition')) {
this.$refs.scrollDiv.scrollTop = localStorage.getItem('scrollPosition'); // 滚动到 500px 位置
@@ -767,7 +602,6 @@ export default {
this.$refs.scrollDiv.addEventListener('scroll', this.divOnScroll, { passive: true });
},
activated() {
window.renderMathJax(); // 主动触发 MathJax 渲染
this.isShowEditComment();
this.typesettingType = 1;
this.editors = {};
@@ -780,6 +614,8 @@ export default {
this.editors = {};
},
beforeDestroy() {
console.log('at line 523:', '是否走了销毁');
for (const key in this.editors) {
if (this.editors[key]) {
// 确保销毁所有编辑器实例
@@ -794,142 +630,6 @@ export default {
this.editors = {};
},
methods: {
changeSort(type) {
console.log('type at line 782:', type);
if (this.currentId) {
this.$emit('changeSort', type, this.currentId);
}
},
addContent() {
if (this.currentId) {
this.$emit('addContent', this.currentId);
} else {
this.$message.warning('Please select content');
}
},
cacheSelection() {
const selection = window.getSelection();
if (!selection.rangeCount) {
this.clearCache();
return;
}
const range = selection.getRangeAt(0);
let selectedNode = range.commonAncestorContainer;
// **向上查找包含 main-id 的最近 div**
let outerDiv = selectedNode;
while (outerDiv && outerDiv.tagName !== 'DIV') {
outerDiv = outerDiv.parentNode;
}
if (!outerDiv) {
this.clearCache();
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())) {
return node.outerHTML; // 仅保留允许的标签
}
return '';
}
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'));
return;
}
// **发送批注**
this.$emit('onAddComment', {
mainId: this.cachedMainId,
label: this.cachedHtml
});
// **清空缓存**
this.clearCache();
},
// **清空缓存**
clearCache() {
this.cachedHtml = '';
this.cachedText = '';
this.cachedMainId = null;
this.cachedType = null;
},
updateUniqueIds() {
this.currentId = null;
this.currentData = {};
// this.uniqueIds = [...new Set(this.wordList.filter((item) => item.checked).map((item) => item.am_id))];
// console.log('this.uniqueIds at line 839:', this.selectedIds);
this.$forceUpdate();
},
onEdit() {
this.currentData = this.currentData;
this.$emit('onEdit', this.currentId);
},
onAddRow() {
this.currentData = this.currentData;
this.$emit('onAddRow', this.currentId);
},
onDelete() {
// console.log('this.uniqueIds.length at line 866:', this.selectedIds.length);
if (this.selectedIds.length > 0) {
this.$emit('onDeletes', this.selectedIds.toString());
this.$forceUpdate();
}
if (this.currentId) {
this.$emit('onDelete', this.currentId);
}
},
changeTitle(value) {
if (this.currentData.type == 0) {
this.$emit('onEditTitle', {
mainId: this.currentId,
value: value
});
}
},
// 右侧批注列点击时,触发高亮左侧对应的批注
// 右侧批注列点击时,触发高亮左侧对应的批注
highlightLeftComment(commentId) {
@@ -980,14 +680,6 @@ export default {
if (outerDiv) {
}
},
// 判断是否是表头行
isHeaderRow(rowIndex, table) {
var table = JSON.parse(table);
var head = table[0];
return rowIndex < head[0].rowspan; // 假设前两行是表头
},
handleDragLeave(e) {
e.preventDefault();
e.stopPropagation();
@@ -1031,11 +723,11 @@ export default {
table_resize_bars: true,
image_advtab: false, // 禁用图片高级选项卡(防止自动调整大小)
valid_elements: '*[*]',
entity_encoding: 'raw', // 不编码 > 等字符
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}
@@ -1180,7 +872,6 @@ export default {
content_style: `${tableStyle + this.wordStyle}
`,
entity_encoding: 'raw', // 不编码 > 等字符
menubar: false,
toolbar: _this.isEditComment ? ['commentAdd |delete| addRow|Edit'] : ['delete| addRow|Edit'],
end_container_on_empty_block: true,
@@ -1248,52 +939,29 @@ export default {
}
});
},
initializeEditor(id, type, data, index) {
this.clearHighlight();
this.selectedIds = [];
this.wordList.forEach((item, index) => {
item.checked = false;
});
initializeEditor(index, type, data) {
if (!this.isPreview) {
this.currentId = id;
this.currentIndex = index;
this.currentData = data;
// const editorId = `editor${index}`;
// // 检查当前编辑器是否已经初始化
// if (this.editors[editorId]) return;
// // 销毁所有已初始化的编辑器实例
// for (const key in this.editors) {
// if (this.editors[key]) {
// // 确保销毁所有编辑器实例
// tinymce.remove(this.editors[key]);
// this.editors[key] = null; // 清除引用
// }
// }
// if (type == 'img') {
// this.initTinymceImg(editorId);
// } else if (type == 'table') {
// this.initTinymceTable(editorId);
// } else {
// this.initTinymceContent(editorId);
// }
// this.$set(this.editors, editorId, tinymce.get(`editor${index}`));
const editorId = `editor${index}`;
// 检查当前编辑器是否已经初始化
if (this.editors[editorId]) return;
// 销毁所有已初始化的编辑器实例
for (const key in this.editors) {
if (this.editors[key]) {
// 确保销毁所有编辑器实例
tinymce.remove(this.editors[key]);
this.editors[key] = null; // 清除引用
}
},
dblclickEdit(id, type, data, index) {
if (!this.isPreview) {
this.currentId = id;
this.currentIndex = index;
this.currentData = data;
this.onEdit();
}
this.clearHighlight();
this.selectedIds = [];
this.wordList.forEach((item, index) => {
item.checked = false;
});
if (type == 'img') {
this.initTinymceImg(editorId);
} else if (type == 'table') {
this.initTinymceTable(editorId);
} else {
this.initTinymceContent(editorId);
}
this.$set(this.editors, editorId, tinymce.get(`editor${index}`));
}
},
deleteComment(data) {
this.$emit('deleteComment', data);
@@ -1332,13 +1000,12 @@ export default {
return formattedDate;
},
goToListComment(data) {
console.log('data at line 993:', data);
this.goToComment(data.am_id);
console.log('data at line 993:', data)
this.goToComment(data.am_id)
},
divOnScroll() {
if (!this.isPreview) {
this.currentId = null;
this.currentData = {};
// const scrollTop = scrollDiv.scrollTop; // 获取垂直滚动距离
this.scrollPosition = this.$refs.scrollDiv.scrollTop;
localStorage.setItem('scrollPosition', this.scrollPosition);
@@ -1389,12 +1056,13 @@ export default {
.map((annotation, index) => (annotation.content === '' ? annotation.amc_id : -1)) // 找到内容为空的批注项的索引,其他项返回 -1
.filter((index) => index !== -1) // 过滤掉值为 -1 的项
.join(','); // 以逗号连接索引
return emptyContentIndexes;
},
escapeRegExp(string) {
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
},
highlightText(text, annotations, type) {
},
highlightText(text, annotations) {
if (!this.isPreview) {
let tempText = text;
@@ -1427,7 +1095,7 @@ export default {
style="background-color: ${randomColor};
position: relative;
display: inline-block;
// white-space: nowrap;
white-space: nowrap;
overflow-wrap: anywhere;
border-left: 2px solid #cd5454;
border-right: 2px solid #cd5454;"
@@ -1442,17 +1110,14 @@ export default {
`;
});
});
if (type == 0 && tempText == '') {
tempText =
tempText +
`<img contenteditable="${false}" src="${this.imagePath}" alt="" style="width: 20px;height: 20px;opacity:0.6;">`;
}
// 3. 返回处理后的文本
return tempText;
} else {
return text;
}
},
},
getCommentsData() {
if (!this.isPreview) {
@@ -2159,7 +1824,6 @@ export default {
.pMain {
margin-top: 5px;
margin-bottom: 5px;
min-height: 30px;
}
::v-deep .tox.tox-tinymce-inline {
z-index: 9999 !important;
@@ -2234,11 +1898,10 @@ export default {
/* color: #000; */
color: #fff;
box-sizing: border-box;
padding: 1px 2px;
padding: 2px 4px;
border-radius: 2px;
font-size: 11px;
font-size: 12px;
font-weight: 400;
line-height: 14px;
}
.MaxPicture img {
width: 580px !important;
@@ -2264,105 +1927,4 @@ export default {
border: 2px solid #cd5454; /* 高亮边框 */
box-shadow: 0 0 10px #f77b7b; /* 高亮阴影 */
}
.isTitleH1 {
position: relative;
/* border: 1px solid #94c2f7; */
background-color: #dbebfc54;
}
.Htitle {
color: #4d99f1;
background-color: #dbebfca6;
/* border: 1px solid #4d99f1; */
border-radius: 50%;
font-weight: bold;
position: absolute;
line-height: 24px;
padding: 2px;
font-size: 16px;
left: -30px;
top: 0px;
text-align: center;
}
.Htitle1 {
width: 24px;
height: 24px;
/* font-size: 14px; */
}
.Htitle2 {
width: 24px;
height: 24px;
/* font-size: 16px; */
}
.Htitle3 {
width: 24px;
height: 24px;
/* font-size: 12px; */
}
.isTitleH2 {
position: relative;
background-color: #dbebfc54;
}
.isTitleH3 {
position: relative;
background-color: #dbebfc54;
}
.glowing-border {
border: 3px solid #006699d1;
border-radius: 5px;
padding: 4px;
animation: glow 1.5s infinite alternate;
}
@keyframes glow {
0% {
box-shadow: 0 0 5px #006699d1;
}
50% {
box-shadow: 0 0 20px #006699d1;
}
100% {
box-shadow: 0 0 5px #006699d1;
}
}
.HTitleBox {
height: 100%;
border: 1px solid #c5c5c5;
width: auto;
display: flex;
align-items: center;
justify-content: space-between;
border-radius: 6px;
}
.HTitleBox li {
list-style: none;
padding: 0 10px;
color: #333;
font-weight: bold;
font-size: 20px;
}
.operateBox {
width: auto;
display: flex;
}
.operateBox li {
width: 55px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
list-style: none;
padding: 2px 10px;
margin: 0 10px;
color: #8a8a8b;
/* font-weight: bold; */
font-size: 16px;
background-color: rgb(43, 129, 239) !important;
color: #fff;
border-radius: 4px;
}
::v-deep .el-checkbox__inner {
width: 18px;
height: 18px;
}
</style>

View File

@@ -202,8 +202,7 @@
text-align: center;
"
>
<tr v-for="(row, rowIndex) in table.table" :key="rowIndex" >
<tr v-for="(row, rowIndex) in table.table" :key="rowIndex">
<td
v-for="(cell, cellIndex) in row"
:key="cellIndex"
@@ -325,7 +324,7 @@ export default {
this.filterData();
},
filterData(type) {
console.log('type at line 374:', type);
if (type) {
if (type == 'img') {
this.imagesList = [...this.images];
@@ -542,7 +541,7 @@ export default {
this.$commonJS.createImageModal(index, modalContent, 'table', '');
});
}
console.log('this.tables at line 533:', this.tables);
});
}
},
@@ -582,7 +581,6 @@ export default {
::v-deep .wordTableHtml table {
cursor: pointer;
background-color: #fff !important;
border-bottom: 1px solid #000 !important;
}
.el-menu-vertical-demo {
width: 85px;

View File

@@ -631,7 +631,7 @@ export default {
})
.then((res) => {
this.comments = res.data.list;
console.log('this.comments at line 537:', this.comments);
});
},
addImage() {
@@ -663,7 +663,7 @@ export default {
this.filterData();
},
filterData(type) {
console.log('type at line 374:', type);
if (type) {
if (type == 'img') {
this.imagesList = [...this.images];
@@ -866,7 +866,7 @@ export default {
this.$commonJS.createImageModal(index, modalContent, 'table', '');
});
}
console.log('this.tables at line 533:', this.tables);
});
}
},
@@ -908,7 +908,6 @@ export default {
::v-deep .wordTableHtml table {
cursor: pointer;
background-color: #fff !important;
border-bottom: 1px solid #000 !important;
}
.el-menu-vertical-demo {
width: 85px;

View File

@@ -313,6 +313,5 @@ export default {
::v-deep .wordTableHtml table {
cursor: pointer;
background-color: #fff !important;
border-bottom: 1px solid #000 !important;
}
</style>

View File

@@ -78,13 +78,12 @@
<el-table-column type="index" label="No." width="55" align="center">
<template slot-scope="scope">
<i v-if="scope.row.is_change == 1" class="itemChanged"></i>
<img src="../../assets/img/repeat.png" v-if="scope.row.is_repeat==1" alt="" style="width: 24px;height: 24px;float: left;">
<span>{{scope.$index + 1}}</span>
</template>
</el-table-column>
<el-table-column label="state" width="55" align="center">
<template slot-scope="scope">
<span class="status ok" v-if="scope.row.refer_type == 'journal' && scope.row.doilink != '' || scope.row.refer_type == 'book' && scope.row.isbn != '' " >
<span class="status ok" v-if="scope.row.refer_type == 'journal' && scope.row.doilink != '' || scope.row.refer_type == 'book' && scope.row.isbn != '' || scope.row.refer_type == 'other' && scope.row.refer_frag != '' && scope.row.refer_frag.length > 15" >
<i class="el-icon-circle-check"></i>
</span>
<span class="status warn" v-else >

View File

@@ -13,26 +13,8 @@ import 'babel-polyfill';
import api from './api/index.js';
import Common from './components/common/common'
Vue.prototype.$validateString = function (str) {
return /^[a-zA-Z\s\u00C0-\u00FF\u0100-\u017F-]+$/.test(str);
return /^[a-zA-Z\s-]+$/.test(str);
}
window.MathJax = {
tex: {
inlineMath: [['$', '$'], ['\\(', '\\)']], // 行内公式
displayMath: [['$$', '$$'], ['\\[', '\\]']], // 块级公式
},
svg: { fontCache: 'global' }
};
// 监听 DOM 变化,并自动渲染公式
Vue.prototype.$renderMath = function () {
if (window.MathJax && window.MathJax.typeset) {
setTimeout(() => {
window.MathJax.typeset();
}, 100); // 延迟防止 Vue 还未完全渲染
} else {
console.warn('MathJax 未正确加载');
}
};
import VXETable from 'vxe-table'
import 'vxe-table/lib/style.css'
@@ -49,7 +31,7 @@ Vue.use(VueQuillEditor)
// 时间过滤器
// 定义时间过滤器(不含时分秒)
Vue.filter('formatDate', function (originVal) {
Vue.filter('formatDate', function(originVal) {
const dt = new Date(originVal * 1000)
const y = dt.getFullYear()
const m = (dt.getMonth() + 1 + '').padStart(2, '0')
@@ -58,9 +40,9 @@ Vue.filter('formatDate', function (originVal) {
const mm = (dt.getMinutes() + '').padStart(2, '0')
const ss = (dt.getSeconds() + '').padStart(2, '0')
return `${y}-${m}-${d}`
})
// 含时分秒
Vue.filter('formatDatehms', function (originVal) {
})
// 含时分秒
Vue.filter('formatDatehms', function(originVal) {
const dt = new Date(originVal * 1000)
const y = dt.getFullYear()
const m = (dt.getMonth() + 1 + '').padStart(2, '0')
@@ -69,7 +51,7 @@ Vue.filter('formatDatehms', function (originVal) {
const mm = (dt.getMinutes() + '').padStart(2, '0')
const ss = (dt.getSeconds() + '').padStart(2, '0')
return `${y}-${m}-${d} ${hh}:${mm}:${ss}`
})
})
// 引入wps文档编辑
import mammoth from "mammoth";
import commonJS from '@/common/js/commonJS.js'
@@ -91,12 +73,6 @@ Vue.component("Editor", Editor);
import commonTable from '@/components/page/components/table/table.vue'
Vue.component('common-table', commonTable);
import commonLateX from '@/components/page/components/table/LateX.vue'
Vue.component('common-late-x', commonLateX);
import commonMajor from '@/components/page/components/major/index.vue'
Vue.component('common-major', commonMajor);
import commonMajorList from '@/components/page/components/major/list.vue'
Vue.component('common-major-list', commonMajorList);
import commonPayPalButton from '@/components/page/components/pendingPayment/PayPalButton.vue'
Vue.component('common-paypal-button', commonPayPalButton);
import commonTiff from '@/components/page/components/table/tiff.vue'
@@ -125,7 +101,7 @@ Vue.use(ElementUI, {
locale
});
const i18n = new VueI18n({
locale: localStorage.getItem('langs') || 'en',
locale: localStorage.getItem('langs')||'en',
messages
});
//使用钩子函数对路由进行权限跳转
@@ -133,7 +109,7 @@ router.beforeEach((to, from, next) => {
document.title = `${to.meta.title} | Traditional Medicine Research`;
const role = localStorage.getItem('U_name');
const userrole = localStorage.getItem('U_status');
if (!role && to.path != '/register' && to.path !== '/submission' && to.path !== '/verification' && to.path !== '/orcidLink' && to.path !== '/img' && to.path !== '/reviewer' && to.path !== '/thanks' && to.path !== '/login' && to.path !== '/refuse' && to.path !== '/managing' && to.path.search(/retrieve/i) < 0) {
if (!role && to.path!='/register'&&to.path!=='/submission'&&to.path!=='/verification'&&to.path!=='/orcidLink'&&to.path!=='/img'&& to.path !=='/reviewer'&&to.path !=='/thanks' &&to.path !== '/login' &&to.path !== '/refuse' &&to.path !== '/managing'&&to.path.search(/retrieve/i)<0 ) {
next('/login');
// } else if (to.meta.permission) {
// // 如果是管理员权限则可进入,这里只是简单的模拟管理员权限而已
@@ -163,8 +139,5 @@ router.beforeEach((to, from, next) => {
new Vue({
router,
i18n,
render: h => h(App),
mounted() {
this.$renderMath(); // 页面加载后自动渲染
}
render: h => h(App)
}).$mount('#app');

View File

@@ -992,15 +992,6 @@ export default new Router({
hideSidebar: true
}
},
{
path: '/LateX', //用户端预收录-引用编辑
component: () => import('../components/page/components/table/LateX.vue'),
meta: {
title: 'LateX',
hideSidebar: true,
hideTitle: true,
}
},
{
name: 'PreIngestedEditor',
path: '/PreIngestedEditor', // 编辑端 - 预收录编辑页面