终审编委信息

This commit is contained in:
2026-07-06 09:11:20 +08:00
parent 5260ca8ea5
commit 262e634f85
24 changed files with 5529 additions and 519 deletions

View File

@@ -976,6 +976,13 @@ const en = {
sendProgressRunning: 'Sending… {done}/{total} completed',
sendProgressAllSuccess: 'All sent successfully ({count})',
sendProgressDone: 'Done: {ok} sent, {fail} failed',
sendPreviewTitle: 'Send preview',
sendPreviewSub: 'Review the email each recipient will receive',
sendPreviewCount: '{count} email(s)',
sendPreviewRecipient: 'To',
sendPreviewSubject: 'Subject',
sendPreviewConfirm: 'Confirm send',
sendPreviewRealHint: 'Each recipient will receive a separate email matching the preview above',
backToInbox: 'Back to email list',
articleContextId: 'Article ID:',
articleContextIdPlaceholder: 'Enter article ID',
@@ -1018,8 +1025,26 @@ const en = {
articleContextRepeatReviewLine: '{n}nd review: {label}',
articleContextFinalReviewLine: 'Final decision: {decision}',
articleContextReplaceVars: 'Replace template vars',
articleContextReplaceVarsSuccess: 'Replaced {{article_title}} / {{article_sn}}',
articleContextReplaceVarsEmpty: 'Subject or body has no {{article_title}} / {{article_sn}} placeholders',
articleContextReplaceVarsSuccess: 'Replaced template variables (title, SN, name, article_id, final_r_id, etc.)',
articleContextReplaceVarsEmpty: 'Subject or body has no replaceable placeholders (e.g. {{article_title}}, [[name]], {{final_r_id}})',
recipientVarsSendHint: 'Keep placeholders in the body; each recipient gets a separate email with values from the table',
recipientVarsPanelTitle: 'Recipient variables',
recipientVarsPanelSub: 'One email per recipient; placeholders are replaced using the values below when sending',
recipientVarsSharedTitle: 'Shared (same for all recipients on this article)',
recipientVarsPerRecipientTitle: 'Per recipient',
recipientVarsColEmail: 'Recipient',
recipientVarsMissingWarn: '{count} recipient(s) missing name or final_r_id — load article and add from Final tab',
templateVar_name: 'Name [[name]]',
templateVar_article_id: 'Article ID',
templateVar_final_r_id: 'final_r_id',
templateVar_article_title: 'Article title',
templateVar_title: 'Title',
templateVar_manuscript_title: 'Manuscript title',
templateVar_accept_sn: 'SN',
templateVar_article_sn: 'SN',
templateVar_sn: 'SN',
templateVar_journal_name: 'Journal name',
templateVar_journal_url: 'Journal URL',
roleFirstAuthor: 'First author',
roleCorrespondingAuthor: 'Corresponding author',
roleFirstAuthorShort: '1st auth.',

View File

@@ -961,6 +961,13 @@ const zh = {
sendProgressRunning: '正在发送,已完成 {done}/{total}',
sendProgressAllSuccess: '全部发送成功,共 {count} 封',
sendProgressDone: '发送完成:成功 {ok} 封,失败 {fail} 封',
sendPreviewTitle: '发送预览',
sendPreviewSub: '请确认每位收件人将收到的邮件内容',
sendPreviewCount: '共 {count} 封',
sendPreviewRecipient: '收件人',
sendPreviewSubject: '主题',
sendPreviewConfirm: '确认发送',
sendPreviewRealHint: '确认后将按上方预览内容,为每位收件人逐封发送',
backToInbox: '返回收件箱',
articleContextId: '文章 ID',
articleContextIdPlaceholder: '请输入文章 ID',
@@ -1003,8 +1010,26 @@ const zh = {
articleContextRepeatReviewLine: '第 {n} 次复审:{label}',
articleContextFinalReviewLine: '终审:{decision}',
articleContextReplaceVars: '替换模板变量',
articleContextReplaceVarsSuccess: '已替换 {{article_title}} / {{article_sn}}',
articleContextReplaceVarsEmpty: '主题或正文不含 {{article_title}}、{{article_sn}} 等占位符',
articleContextReplaceVarsSuccess: '已替换模板变量标题、SN、name、article_id、final_r_id 等)',
articleContextReplaceVarsEmpty: '主题或正文不含可替换占位符(如 {{article_title}}、[[name]]、{{final_r_id}}',
recipientVarsSendHint: '正文保留占位符,发送时按左侧表格为每人单独替换并发送',
recipientVarsPanelTitle: '收件人变量',
recipientVarsPanelSub: '每人一封邮件,发送时按下列值替换模板中的占位符',
recipientVarsSharedTitle: '公共变量(本稿所有人相同)',
recipientVarsPerRecipientTitle: '每人不同',
recipientVarsColEmail: '收件人',
recipientVarsMissingWarn: '有 {count} 位收件人缺少 name 或 final_r_id请从终审列表添加或先加载稿件',
templateVar_name: '姓名 [[name]]',
templateVar_article_id: '文章 ID',
templateVar_final_r_id: 'final_r_id',
templateVar_article_title: '稿件标题',
templateVar_title: '标题',
templateVar_manuscript_title: '稿件标题',
templateVar_accept_sn: 'SN',
templateVar_article_sn: 'SN',
templateVar_sn: 'SN',
templateVar_journal_name: '期刊名',
templateVar_journal_url: '期刊网址',
roleFirstAuthor: '第一作者',
roleCorrespondingAuthor: '通讯作者',
roleFirstAuthorShort: '一作',

View File

@@ -79,8 +79,10 @@
v-if="Main_List.length > 0"
:content="Main_List"
:articleId="articleId"
:strippingHeadingNumbers="strippingHeadingNumbers"
ref="catalogue"
@goToListComment="goToListComment"
@stripHeadingNumbers="stripHeadingNumbersFromOutline"
style="width: 100%; height: 100%; padding: 0 0px; box-sizing: border-box; background-color: #fff"
>
</catalogue>
@@ -425,6 +427,22 @@
</el-form>
<span slot="footer" class="dialog-footer">
<el-button
v-if="zyModeEnabled"
type="warning"
plain
@click="handleConvertAddContentSupToBlue"
>
上标转引用
</el-button>
<el-button
v-if="zyModeEnabled"
type="warning"
plain
@click="handleMoveAddContentCitationBeforePeriod"
>
引用挪到句号前
</el-button>
<el-button @click="addContentVisible = false"> Cancel </el-button>
<el-button type="primary" @click="handleSaveAddContent">
<!-- <i class="el-icon-finished" style="margin-right: 5px"></i> -->
@@ -447,6 +465,7 @@ import Tinymce from '@/components/page/components/Tinymce';
import bottomTinymce from '@/components/page/components/Tinymce';
import catalogue from '@/components/page/components/table/catalogue.vue';
import { isZyModeEnabled } from '@/utils/zyMode';
import { collectHeadingNumberStripUpdates } from '@/utils/stripHeadingNumber';
export default {
data() {
return {
@@ -466,6 +485,7 @@ export default {
currentId: null,
ManuscirptContent: [],
mathFormulasList: [],
strippingHeadingNumbers: false,
articleId: this.$route.query.id,
pArticleId: this.$route.query.p_article_id || '',
isShowComment: false,
@@ -701,6 +721,34 @@ export default {
handleSaveAddContent() {
this.$refs.addContent.getTinymceContent('addcontent');
},
/** 临时Add Content 内数字上标 → blue 引用标签 */
handleConvertAddContentSupToBlue() {
const ref = this.$refs.addContent;
if (!ref || typeof ref.convertNumericSuperscriptsToBlue !== 'function') {
this.$message.warning('编辑器未就绪');
return;
}
const count = ref.convertNumericSuperscriptsToBlue();
if (count > 0) {
this.$message.success('已转换 ' + count + ' 处数字上标为 blue 引用');
} else {
this.$message.info('未找到可转换的数字上标(需为上标且内容仅为数字、逗号或连字符)');
}
},
/** 临时Add Content 内 blue 引用挪到句号前 */
handleMoveAddContentCitationBeforePeriod() {
const ref = this.$refs.addContent;
if (!ref || typeof ref.moveBlueCitationsBeforePeriod !== 'function') {
this.$message.warning('编辑器未就绪');
return;
}
const count = ref.moveBlueCitationsBeforePeriod();
if (count > 0) {
this.$message.success('已调整 ' + count + ' 处参考文献位置');
} else {
this.$message.info('未找到需要调整的 blue 参考文献(句号已在引用之后则不会重复处理)');
}
},
handleSaveEditProofreadingContent() {
this.$refs.addContent.getTinymceContent('addcontent');
},
@@ -991,6 +1039,65 @@ export default {
this.$refs.commonWord.goToComment(mainId);
});
},
async stripHeadingNumbersFromOutline(updates) {
const list = updates && updates.length ? updates : collectHeadingNumberStripUpdates(this.Main_List);
if (!list.length) {
this.$message.info('No heading numbers found to remove.');
return;
}
try {
await this.$confirm(
'Remove numbering from ' + list.length + ' heading(s)? (e.g. "1 Introduction" → "Introduction")',
'Remove Heading Numbers',
{
confirmButtonText: 'Remove',
cancelButtonText: 'Cancel',
type: 'warning'
}
);
} catch (e) {
return;
}
this.strippingHeadingNumbers = true;
const loading = this.$loading({
lock: true,
text: 'Removing heading numbers...',
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)'
});
let successCount = 0;
try {
for (let i = 0; i < list.length; i++) {
const item = list[i];
let str = String(item.content || '')
.replace(/^<p>\s*(.*?)\s*<\/p>$/, '$1')
.trim();
str = str.replace(/<br\s*\/?>/gi, '');
str = await this.$commonJS.decodeHtml(str);
const res = await this.$api.post(this.urlList.editContent, {
am_id: item.am_id,
content: str
});
if (res && res.code == 0) {
successCount++;
await this.refreshCurrentContent('content', item.am_id, res.data);
} else {
throw new Error((res && res.msg) || 'Save failed');
}
}
this.$message.success('Removed numbering from ' + successCount + ' heading(s).');
} catch (err) {
console.error(err);
this.$message.error((err && err.message) || 'Failed to remove heading numbers.');
} finally {
loading.close();
this.strippingHeadingNumbers = false;
}
},
getTables(tables, html) {
this.tables = data.map((e, i) => ({ ...e, p_main_table_id: 2141 + i, p_article_id: 2141 }));
this.tablesHtml = html;

View File

@@ -74,29 +74,46 @@
</el-select>
</el-form-item>
<el-form-item label="Manuscript :" prop="manuscirpt" label-width="120px">
<el-upload
:on-progress="handleProgress"
ref="uploadFileManuscirpt"
class="upload-demo up_newstyle"
:action="upload_manuscirpt"
accept=".docx"
name="manuscirpt"
:before-upload="beforeupload_manuscirpt"
:on-error="uperr_coverLetter"
:on-success="upSuccess_manuscirpt"
:limit="1"
:on-exceed="alertlimit"
:on-remove="removefilemanuscirpt"
:file-list="fileL_manuscirpt"
:on-preview="dowloadFile"
>
<div class="el-upload__text" @click="removefilemanuscirpt">
<em>Upload</em>
<div class="manuscript-upload-wrap">
<el-upload
:on-progress="handleProgress"
ref="uploadFileManuscirpt"
class="upload-demo up_newstyle"
:action="upload_manuscirpt"
accept=".docx"
name="manuscirpt"
:before-upload="beforeupload_manuscirpt"
:on-error="uperr_coverLetter"
:on-success="upSuccess_manuscirpt"
:limit="1"
:on-exceed="alertlimit"
:on-remove="removefilemanuscirpt"
:file-list="fileL_manuscirpt"
:on-preview="dowloadFile"
>
<div class="el-upload__text" @click="removefilemanuscirpt">
<em>Upload</em>
</div>
<div class="el-upload__tip" slot="tip">
Only Word and compressed files can be uploaded (file format: .docx).
</div>
</el-upload>
<div class="manuscript-template-notice">
<i class="el-icon-info manuscript-template-notice__icon"></i>
<p>
Kindly prepare and submit your manuscript in DOCX format using our
<a
href="javascript:void(0)"
class="template-download-link"
@click.prevent="dowloadFileTemplate"
>
<i class="el-icon-download"></i> official template
</a>.
Compliance with the template requirements allows us to process your submission more
efficiently and refine the articles final typesetting to a higher standard.
</p>
</div>
<div class="el-upload__tip" slot="tip">
Only Word and compressed files can be uploaded (file format: .docx).
</div>
</el-upload>
</div>
</el-form-item>
<el-form-item label="Manuscript Title :" prop="title" label-width="160px">
<el-input v-model="form.title" type="textarea" rows="2"></el-input>
@@ -4365,6 +4382,55 @@ export default {
font-size: 13px;
}
.manuscript-upload-wrap {
position: relative;
min-height: 32px;
}
.manuscript-template-notice {
display: flex;
align-items: flex-start;
gap: 8px;
margin-top: 12px;
padding: 10px 12px;
background: #f5f9fb;
border: 1px solid #e3eef3;
border-left: 3px solid #006699;
border-radius: 4px;
}
.manuscript-template-notice__icon {
flex-shrink: 0;
margin-top: 2px;
color: #006699;
font-size: 16px;
}
.manuscript-template-notice p {
margin: 0;
font-size: 13px;
line-height: 1.65;
color: #555;
}
.template-download-link {
color: #006699;
font-weight: 600;
text-decoration: none;
cursor: pointer;
white-space: nowrap;
}
.template-download-link:hover {
text-decoration: underline;
}
.template-download-link .el-icon-download {
font-weight: bold;
margin-right: 2px;
}
.el-collapse-item__content {
padding-bottom: 8px !important;
}

View File

@@ -154,23 +154,40 @@
>
<el-table-column type="index" label="No." align="center" width="50"></el-table-column>
<el-table-column prop="User Message" label="Realname" width="340">
<el-table-column prop="User Message" label="Realname" width="320">
<template slot-scope="scope">
<p style="font-size: 14px; font-weight: bold; margin-top: 2px">{{ scope.row.realname }}</p>
<p style="margin: 2px 0 0px 0">
<span style="color: #999">Email :</span>
{{ scope.row.email }}
</p>
<p style="margin: 0 0 5px 0" v-if="scope.row.title != ''">
<p style="margin: 2px 0 0" v-if="scope.row.type != null && scope.row.type !== ''">
<span style="color: #999">Identity : </span>
<span v-if="scope.row.type == 0" style="color: #409eff">Editor-in-Chief</span>
<span v-if="scope.row.type == 1" style="color: #409eff">Vice Editor-in-Chief</span>
<span v-if="scope.row.type == 2" style="color: #409eff">Editorial Board Members</span>
</p>
<p class="tab_tie_col tab_tie_col--invite tab_tie_col--dialog">
<span>Latest invitation: </span>{{ formatInviteTime(scope.row) }}
</p>
</template>
</el-table-column>
<el-table-column prop="research_areas" label="Research Areas">
<el-table-column label="Other Information" min-width="280">
<template slot-scope="scope">
<p class="tab_tie_col">
<span>Research areas: </span>{{ getBoardResearchAreas(scope.row) }}
</p>
<p class="tab_tie_col">
<span>Field: </span>{{ getBoardField(scope.row) }}
</p>
<p class="tab_tie_col">
<span>AI Field: </span>{{ getBoardFieldAi(scope.row) }}
</p>
</template>
</el-table-column>
<el-table-column label="Research Areas" width="260">
<template slot-scope="scope">
<commonMajorTableList
:user_id="scope.row.user_id"
@@ -363,6 +380,52 @@ export default {
}
},
methods: {
formatBoardText(value) {
const text = value != null ? String(value).trim() : '';
return text || '—';
},
getBoardField(row) {
return this.formatBoardText(row && row.field);
},
getBoardFieldAi(row) {
return this.formatBoardText(row && row.field_ai);
},
getBoardResearchAreas(row) {
return this.formatBoardText(row && row.research_areas);
},
formatInviteTime(row) {
const raw =
row &&
(row.last_time != null
? row.last_time
: row.last_invite_time != null
? row.last_invite_time
: row.latest_invite_time);
if (raw == null || raw === '') {
return '—';
}
if (typeof raw === 'string' && /[-/]/.test(raw) && isNaN(Number(raw))) {
return raw;
}
let ts = Number(raw);
if (!ts) {
return '—';
}
if (ts < 1e12) {
ts *= 1000;
}
const date = new Date(ts);
if (isNaN(date.getTime())) {
return String(raw);
}
const Y = date.getFullYear() + '-';
const M = (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1) + '-';
const D = date.getDate() < 10 ? '0' + date.getDate() : date.getDate();
const h = date.getHours() < 10 ? '0' + date.getHours() : date.getHours();
const m = date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes();
const s = date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds();
return Y + M + D + ' ' + h + ':' + m + ':' + s;
},
selectEditorialBoardType(type) {
console.log('type at line 525:', type);
this.editorialBoardForm.board_type = type;
@@ -745,6 +808,20 @@ export default {
margin: 0 5px 0 0;
font-size: 13px;
}
.tab_tie_col--invite {
display: block;
margin-top: 4px;
font-size: 12px;
color: #aaa;
}
.tab_tie_col--dialog {
margin: 4px 0 0;
}
.tab_tie_col--multiline {
white-space: pre-wrap;
word-break: break-word;
line-height: 1.5;
}
::v-deep .editorialBoardDialog .el-dialog__body {
padding-top: 10px !important;
padding-bottom: 0px !important;

View File

@@ -1,7 +1,12 @@
<template>
<div class="ManuscirptList">
<div class="arrlist">
<ul class="catalogue-ul">
<span v-if="zyModeEnabled" class="outline-format-icon" @click.stop="handleStripHeadingNumbers">
<el-tooltip effect="dark" content="Remove heading numbers (e.g. 1, 1.1)" placement="left">
<i :class="strippingHeadingNumbers ? 'el-icon-loading' : 'el-icon-brush'"></i>
</el-tooltip>
</span>
<ul class="catalogue-ul" :class="{ 'catalogue-ul--with-toolbar': zyModeEnabled }">
<li class="catalogue-li">
<div
@click="goToListComment(item.am_id, 'content')"
@@ -21,8 +26,15 @@
<script>
import { mediaUrl } from '@/common/js/commonJS.js'; // 引入通用逻辑
import { collectHeadingNumberStripUpdates } from '@/utils/stripHeadingNumber';
import { isZyModeEnabled } from '@/utils/zyMode';
export default {
props: ['articleId', 'imgWidth', 'imgHeight', 'scale', 'isEdit', 'isShowEdit', 'urlList', 'content'],
props: ['articleId', 'imgWidth', 'imgHeight', 'scale', 'isEdit', 'isShowEdit', 'urlList', 'content', 'strippingHeadingNumbers'],
computed: {
zyModeEnabled() {
return isZyModeEnabled(this.$route);
}
},
watch: {
content: {
handler(newVal, oldVal) {
@@ -102,6 +114,17 @@ export default {
goToListComment(id, type) {
this.$emit('goToListComment', id, type);
},
handleStripHeadingNumbers() {
if (this.strippingHeadingNumbers) {
return;
}
const updates = collectHeadingNumberStripUpdates(this.content);
if (!updates.length) {
this.$message.info('No heading numbers found to remove.');
return;
}
this.$emit('stripHeadingNumbers', updates);
}
},
async created() {},
@@ -159,9 +182,25 @@ export default {
.arrlist {
flex: 1;
overflow-y: auto;
position: relative;
/* padding-top: 8px; */
}
.outline-format-icon {
position: absolute;
top: 0px;
right: 2px;
z-index: 2;
color: #909399;
font-size: 16px;
line-height: 1;
cursor: pointer;
}
.outline-format-icon:hover {
color: #409eff;
}
.catalogue-ul {
width: 100%;
list-style: none;
@@ -169,6 +208,10 @@ export default {
margin: 0;
}
.catalogue-ul--with-toolbar {
padding-top: 0px;
}
/* 基础条目样式 - 模拟 Word 悬浮效果 */
.catalogue-item {
position: relative;

View File

@@ -37,6 +37,8 @@
<script>
import Tinymce from '@/components/page/components/Tinymce';
import { convertNumericSuperscriptsToBlueCitationsHtml } from '@/utils/convertNumericSuperscriptsToBlue';
import { moveBlueCitationsBeforePeriodHtml } from '@/utils/moveBlueCitationsBeforePeriod';
export default {
props: {
value: {},
@@ -128,6 +130,42 @@ export default {
getContent(type, content) {
this.$emit('getContent', type, content);
},
/** 临时:数字上标 → blue 参考文献标签 */
convertNumericSuperscriptsToBlue() {
const tinymceRef = this.$refs.tinymceChild1;
if (!tinymceRef || !tinymceRef.tinymceId || typeof window.tinymce === 'undefined') {
return 0;
}
const editor = window.tinymce.get(tinymceRef.tinymceId);
if (!editor) {
return 0;
}
const raw = editor.getContent({ format: 'raw' });
const result = convertNumericSuperscriptsToBlueCitationsHtml(raw);
if (result.count > 0) {
editor.setContent(result.html);
editor.fire('change');
}
return result.count;
},
/** 临时blue 引用挪到句号前,重复句号合并为一个 */
moveBlueCitationsBeforePeriod() {
const tinymceRef = this.$refs.tinymceChild1;
if (!tinymceRef || !tinymceRef.tinymceId || typeof window.tinymce === 'undefined') {
return 0;
}
const editor = window.tinymce.get(tinymceRef.tinymceId);
if (!editor) {
return 0;
}
const raw = editor.getContent({ format: 'raw' });
const result = moveBlueCitationsBeforePeriodHtml(raw);
if (result.count > 0) {
editor.setContent(result.html);
editor.fire('change');
}
return result.count;
}
}
};

View File

@@ -1179,7 +1179,7 @@ import { TableUtils } from '@/common/js/TableUtils';
import { debounce, throttle } from '@/common/js/debounce';
import { tableStyle, commonWordStyle } from '@/utils/tinymceStyles';
import LatexDataPanel from './LatexDataPanel.vue';
import { downloadManuscriptWord, fetchManuscriptReferenceList } from '@/utils/exportManuscriptWord';
import { downloadManuscriptWord, fetchManuscriptReferenceList, summarizeManuscriptExportItems } from '@/utils/exportManuscriptWord';
import {
buildReferencesCopyText,
buildReferencesHtmlLabels,
@@ -1768,6 +1768,11 @@ export default {
return;
}
this.exportingManuscriptWord = true;
console.info('[Word export] 用户点击导出按钮', {
articleId: this.articleId,
pArticleId: this.pArticleId,
summary: summarizeManuscriptExportItems(this.wordList)
});
try {
const hasUploaded =
this.uploadedReferenceHtmlItems && this.uploadedReferenceHtmlItems.length;
@@ -1786,7 +1791,12 @@ export default {
: this.$t('commonTable.exportManuscriptSuccess') || 'Word downloaded.'
);
} catch (err) {
console.error(err);
console.error('[Word export] 导出失败', {
articleId: this.articleId,
pArticleId: this.pArticleId,
summary: summarizeManuscriptExportItems(this.wordList),
error: err
});
if (err && err.message === 'NO_CONTENT') {
this.$message.warning(this.$t('commonTable.exportManuscriptEmpty') || 'No content to export.');
} else {

View File

@@ -502,6 +502,40 @@
ref="myTableModal"
/>
<el-dialog
title="导出全部图片 Word"
:visible.sync="figureExportDialogVisible"
width="420px"
append-to-body
:close-on-click-modal="false"
>
<div class="figure-export-dialog">
<p class="figure-export-dialog__hint">高只需填一项即可另一项按原图比例自动计算两项都填则固定尺寸图与图之间仅空 1 </p>
<el-form label-width="88px" size="small" @submit.native.prevent>
<el-form-item label="宽度 (cm)">
<el-input
v-model="figureExportWidthCm"
placeholder="如 8只填宽度时锁定纵横比"
clearable
/>
</el-form-item>
<el-form-item label="高度 (cm)">
<el-input
v-model="figureExportHeightCm"
placeholder="如 6只填高度时锁定纵横比"
clearable
/>
</el-form-item>
</el-form>
</div>
<span slot="footer">
<el-button @click="figureExportDialogVisible = false">取消</el-button>
<el-button type="primary" :loading="exportingAllFiguresWord" @click="confirmDownloadAllFiguresWord">
导出
</el-button>
</span>
</el-dialog>
</div>
</template>
@@ -550,7 +584,10 @@ export default {
exportingAllWord: false,
exportingTableId: null,
exportingAllFiguresWord: false,
exportingFigureId: null
exportingFigureId: null,
figureExportDialogVisible: false,
figureExportWidthCm: '',
figureExportHeightCm: ''
};
},
components: {
@@ -1034,10 +1071,43 @@ if(newData.ami_id) {
this.$message.warning('No figures to export.');
return;
}
this.figureExportWidthCm = '';
this.figureExportHeightCm = '';
this.figureExportDialogVisible = true;
},
parseFigureExportSizeCm(value) {
if (value === undefined || value === null || value === '') {
return null;
}
const num = Number(String(value).trim());
if (!Number.isFinite(num) || num <= 0) {
return null;
}
return num;
},
async confirmDownloadAllFiguresWord() {
const widthCm = this.parseFigureExportSizeCm(this.figureExportWidthCm);
const heightCm = this.parseFigureExportSizeCm(this.figureExportHeightCm);
if (
(this.figureExportWidthCm && widthCm == null) ||
(this.figureExportHeightCm && heightCm == null)
) {
this.$message.warning('请输入有效的厘米数值(大于 0。');
return;
}
this.exportingAllFiguresWord = true;
try {
await exportAllFiguresWordFile(this.images, this.mediaUrl, 'figures');
const exportOptions = {};
if (widthCm != null || heightCm != null) {
exportOptions.figureSize = {
widthCm: widthCm,
heightCm: heightCm
};
}
await exportAllFiguresWordFile(this.images, this.mediaUrl, 'figures', exportOptions);
this.$message.success('Word downloaded.');
this.figureExportDialogVisible = false;
} catch (err) {
console.error(err);
if (err && err.message === 'NO_FIGURES') {
@@ -1370,4 +1440,11 @@ li {
}
.single {
}
.figure-export-dialog__hint {
margin: 0 0 14px;
color: #606266;
font-size: 13px;
line-height: 1.5;
}
</style>

File diff suppressed because it is too large Load Diff

View File

@@ -93,8 +93,15 @@
</div>
<!-- 同意弹出框 -->
<el-dialog title="Agree User" :visible.sync="agreeVisible" width="700px" :close-on-click-modal="false" class="agree_form_box">
<el-form ref="agree_Form" :model="agreeForm" :rules="rules" label-width="140px">
<el-dialog
title="Agree User"
:visible.sync="agreeVisible"
width="700px"
:close-on-click-modal="false"
class="agree_form_box"
@opened="handleAgreeDialogOpened"
>
<el-form ref="agree_Form" :model="agreeForm" :rules="agreeFormRules" label-width="140px">
<el-form-item label="Account :" style="margin-bottom: 2px !important">
<span>{{ agreeForm.account }}</span>
</el-form-item>
@@ -188,6 +195,10 @@
<script>
import commonCv from '../common/cv.vue';
import bus from '../common/bus';
import { isZyModeEnabled } from '@/utils/zyMode';
const AGREE_DETAIL_FIELDS = ['realname', 'phone', 'technical', 'country', 'website', 'field', 'introduction', 'company'];
export default {
components: {
commonCv
@@ -336,6 +347,33 @@ export default {
}
};
},
computed: {
zyModeEnabled() {
return isZyModeEnabled(this.$route);
},
agreeFormRules() {
const rules = JSON.parse(JSON.stringify(this.rules));
if (this.zyModeEnabled) {
rules.phone = [
{
validator: function (rule, value, callback) {
if (!value || String(value).trim() === '') {
callback();
return;
}
if (/^1[34578]\d{9}$/.test(value) == false) {
callback(new Error('Please enter the correct phone format'));
} else {
callback();
}
},
trigger: 'blur'
}
];
}
return rules;
}
},
created() {
this.getDate();
this.getCountry();
@@ -406,16 +444,81 @@ export default {
// 同意
agreeApply(e) {
this.agreeForm = {};
console.log('e at line 405:', e);
this.agreeForm = Object.assign({}, e);
this.applyZyDefaultYear();
this.agreeVisible = true;
this.agreeForm = e;
this.$refs.agree_Form.clearValidate();
this.$nextTick(() => {
this.applyZyDefaultYear();
if (this.$refs.agree_Form) {
this.$refs.agree_Form.clearValidate();
}
});
if (this.zyModeEnabled && e.user_id) {
this.supplementAgreeFormByUserDetail(e.user_id);
}
},
// 提交同意
saveAgreee() {
applyZyDefaultYear() {
if (!this.zyModeEnabled) {
return;
}
this.$set(this.agreeForm, 'year', 1);
},
handleAgreeDialogOpened() {
this.applyZyDefaultYear();
},
isAgreeFieldEmpty(value) {
return value === undefined || value === null || String(value).trim() === '';
},
mergeAgreeFormFromUserDetail(user) {
if (!user) {
return;
}
AGREE_DETAIL_FIELDS.forEach((key) => {
if (this.isAgreeFieldEmpty(this.agreeForm[key]) && !this.isAgreeFieldEmpty(user[key])) {
this.$set(this.agreeForm, key, user[key]);
}
});
this.applyZyDefaultYear();
},
supplementAgreeFormByUserDetail(userId) {
this.$api
.post('api/User/getUserDetail', {
user_id: userId
})
.then((res) => {
if (res.code != 0 || !res.data || !res.data.user) {
if (res.msg) {
this.$message.error(res.msg);
}
return;
}
this.mergeAgreeFormFromUserDetail(res.data.user);
this.$nextTick(() => {
this.tryZyModeAutoAgree();
});
})
.catch((err) => {
console.log(err);
});
},
tryZyModeAutoAgree() {
if (!this.zyModeEnabled || !this.$refs.agree_Form) {
return;
}
this.$refs.agree_Form.validate((valid) => {
if (valid) {
this.submitAgreeForm();
}
});
},
submitAgreeForm() {
var data = {
ap_yboard_id: this.agreeForm.ap_yboard_id,
year: this.agreeForm.year,
@@ -428,27 +531,30 @@ export default {
introduction: this.agreeForm.introduction,
company: this.agreeForm.company
};
console.log('data at line 419:', data);
this.$api
.post('api/User/agreeYboardApplyNew', {
...data
})
.then((res) => {
if (res.code == 0) {
this.$message.success('Add succeeded!');
this.agreeVisible = false;
this.getDate();
} else {
this.$message.error(res.msg);
}
})
.catch((err) => {
console.log(err);
});
},
// 提交同意
saveAgreee() {
this.$refs.agree_Form.validate((valid) => {
if (valid) {
this.$api
.post('api/User/agreeYboardApplyNew', {
...data
})
.then((res) => {
if (res.code == 0) {
this.$message.success('Add succeeded!');
this.agreeVisible = false;
this.getDate();
} else {
this.$message.error(res.msg);
}
})
.catch((err) => {
console.log(err);
});
this.submitAgreeForm();
} else {
this.$message.error('Please complete the information!!');
}