tijiao
This commit is contained in:
@@ -964,6 +964,7 @@ str = str.replace(regex, function (match, content, offset, fullString) {
|
||||
const documentFile = zip.file("word/document.xml");
|
||||
if (!documentFile) {
|
||||
console.error("❌ 找不到 word/document.xml,无法解析 Word 文件");
|
||||
callback([]);
|
||||
return;
|
||||
}
|
||||
const relsFile = zip.file("word/_rels/document.xml.rels");
|
||||
@@ -997,7 +998,8 @@ str = str.replace(regex, function (match, content, offset, fullString) {
|
||||
const allTables = [];
|
||||
if (!tables || tables.length === 0) {
|
||||
console.warn("未找到表格内容,请检查 XML 结构");
|
||||
return [];
|
||||
callback([]);
|
||||
return;
|
||||
}
|
||||
for (const table of tables) {
|
||||
const rows = table.getElementsByTagNameNS(namespace, "tr");
|
||||
|
||||
@@ -2,14 +2,14 @@
|
||||
//记得切换
|
||||
|
||||
//正式
|
||||
const mediaUrl = '/public/';
|
||||
const baseUrl = '/';
|
||||
// const mediaUrl = '/public/';
|
||||
// const baseUrl = '/';
|
||||
|
||||
//正式环境
|
||||
|
||||
// const mediaUrl = 'https://submission.tmrjournals.com/public/';
|
||||
// // const mediaUrl = 'http://zmzm.tougao.dev.com/public/';
|
||||
// const baseUrl = '/api'
|
||||
const mediaUrl = 'https://submission.tmrjournals.com/public/';
|
||||
// const mediaUrl = 'http://zmzm.tougao.dev.com/public/';
|
||||
const baseUrl = '/api'
|
||||
|
||||
//测试环境
|
||||
|
||||
|
||||
@@ -977,7 +977,7 @@ const en = {
|
||||
tableName: 'Name',
|
||||
tableNameScore: 'Name ( score )',
|
||||
tableRole: 'Role',
|
||||
tableAuthorRole: '1st auth. / Corr.',
|
||||
tableAuthorRole: 'Author role',
|
||||
tableEmail: 'Email',
|
||||
articleContextEmptyGroup: 'None',
|
||||
articleContextNoEmail: 'No email',
|
||||
@@ -991,7 +991,12 @@ const en = {
|
||||
articleContextSelectedHint: '{count} selected',
|
||||
articleContextSelectedEmpty: 'Select contacts from the left',
|
||||
articleContextRemoveSelected: 'Remove',
|
||||
articleContextTypeSwitched: 'Contact type changed; previous selection cleared',
|
||||
articleContextAddAllSelected: 'Add all selected',
|
||||
articleContextReviewerScore: 'Score {score}',
|
||||
articleContextFirstReviewLine: '1st review: {label}',
|
||||
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',
|
||||
@@ -1698,6 +1703,9 @@ const en = {
|
||||
startDetectTip:
|
||||
'Launch AI semantic consistency verification for all references against in-text citations.',
|
||||
checkComplete: 'Relevance check completed',
|
||||
auditDoneTitle: 'Reference context audit complete',
|
||||
doneNotFoundHint: '{count} reference(s) not found in text',
|
||||
doneAllClearHint: 'Review results in the table below. Re-check after editing in-text citations.',
|
||||
detectingAi: 'Proofreading',
|
||||
auditProgressTitle: 'Batch reference context audit in progress',
|
||||
queuePositionLabel: 'Queue position:',
|
||||
@@ -1722,7 +1730,19 @@ const en = {
|
||||
copyFailed: 'Copy failed',
|
||||
copyEmpty: 'Nothing to copy',
|
||||
redetect: 'Re-check',
|
||||
check: 'Check',
|
||||
redetectFailed: 'Re-check failed',
|
||||
redetectNotFound: 'Not-found references only',
|
||||
redetectAll: 'All references',
|
||||
redetectDialogTip: 'What would you like to re-check?',
|
||||
redetectNotFoundCount: '{count} reference(s) not found in text',
|
||||
redetectAllDesc:
|
||||
'Re-run the audit for every reference. Recommended if reference-related content in the manuscript HTML has changed.',
|
||||
redetectAllConfirm: 'Re-check all references?',
|
||||
redetectNotFoundConfirm: 'Re-check {count} reference(s) not found in text?',
|
||||
redetectConfirmTitle: 'Re-check references',
|
||||
redetectConfirmOk: 'Start re-check',
|
||||
redetectConfirmCancel: 'Cancel',
|
||||
noReason: '(No details)',
|
||||
aiAnalysis: 'AI analysis',
|
||||
expandReason: 'Expand',
|
||||
|
||||
@@ -962,7 +962,7 @@ const zh = {
|
||||
tableName: '姓名',
|
||||
tableNameScore: 'Name ( score )',
|
||||
tableRole: '身份',
|
||||
tableAuthorRole: '一作/通讯',
|
||||
tableAuthorRole: '作者身份',
|
||||
tableEmail: '邮箱',
|
||||
articleContextEmptyGroup: '暂无',
|
||||
articleContextNoEmail: '无邮箱',
|
||||
@@ -976,7 +976,12 @@ const zh = {
|
||||
articleContextSelectedHint: '已勾选 {count} 人',
|
||||
articleContextSelectedEmpty: '请从左侧勾选联系人',
|
||||
articleContextRemoveSelected: '移除',
|
||||
articleContextTypeSwitched: '已切换联系人类型,原选择已清空',
|
||||
articleContextAddAllSelected: '加入全部已选',
|
||||
articleContextReviewerScore: '评分 {score}',
|
||||
articleContextFirstReviewLine: '初审:{label}',
|
||||
articleContextRepeatReviewLine: '第 {n} 次复审:{label}',
|
||||
articleContextFinalReviewLine: '终审:{decision}',
|
||||
articleContextReplaceVars: '替换模板变量',
|
||||
articleContextReplaceVarsSuccess: '已替换 {{article_title}} / {{article_sn}}',
|
||||
articleContextReplaceVarsEmpty: '主题或正文不含 {{article_title}}、{{article_sn}} 等占位符',
|
||||
@@ -1677,6 +1682,9 @@ const zh = {
|
||||
startDetect: '全量引文相关性核查',
|
||||
startDetectTip: '一键启动对本篇稿件全部参考文献与正文语境的 AI 一致性核查',
|
||||
checkComplete: '相关性检测已完成',
|
||||
auditDoneTitle: '引文相关性核查已完成',
|
||||
doneNotFoundHint: '有 {count} 条参考文献未在正文中匹配,请在下方表格中核对。',
|
||||
doneAllClearHint: '请在下方表格查看核查结果;若修改了正文引文,可点击重新核查。',
|
||||
detectingAi: '校对中',
|
||||
auditProgressTitle: '全量引文相关性核查中',
|
||||
queuePositionLabel: '当前排队位置:',
|
||||
@@ -1700,8 +1708,19 @@ const zh = {
|
||||
copySuccess: '已复制',
|
||||
copyFailed: '复制失败',
|
||||
copyEmpty: '暂无可复制内容',
|
||||
redetect: '重新检测',
|
||||
redetectFailed: '重新检测失败',
|
||||
redetect: '重新核查',
|
||||
check: '核查',
|
||||
redetectFailed: '重新核查失败',
|
||||
redetectNotFound: '仅核查未匹配项',
|
||||
redetectAll: '全部参考文献',
|
||||
redetectDialogTip: '请选择要重新核查的范围',
|
||||
redetectNotFoundCount: '共 {count} 条未在正文中匹配',
|
||||
redetectAllDesc: '对全部参考文献重新核查;若 HTML 中与参考文献相关的内容有变更,建议选择此项。',
|
||||
redetectAllConfirm: '是否对全部参考文献重新核查?',
|
||||
redetectNotFoundConfirm: '是否对 {count} 条未匹配的参考文献重新核查?',
|
||||
redetectConfirmTitle: '重新核查',
|
||||
redetectConfirmOk: '开始核查',
|
||||
redetectConfirmCancel: '取消',
|
||||
noReason: '(暂无说明)',
|
||||
aiAnalysis: 'AI 分析',
|
||||
expandReason: '展开',
|
||||
|
||||
@@ -529,12 +529,14 @@ import { buildArticleAddTableListFromWordFile } from '@/utils/mathFormulaModule'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
const routeArticleId = Number(this.$route.query.id) || 0;
|
||||
return {
|
||||
journal_id:'',
|
||||
questionform:{},
|
||||
dialogFormVisible:false,
|
||||
baseUrl: this.Common.baseUrl,
|
||||
mediaUrl: this.Common.mediaUrl,
|
||||
articleId: this.$route.query.id,
|
||||
articleId: routeArticleId,
|
||||
userName: localStorage.getItem('U_name'),
|
||||
loading: false,
|
||||
Detailvisible: false,
|
||||
@@ -543,7 +545,7 @@ import { buildArticleAddTableListFromWordFile } from '@/utils/mathFormulaModule'
|
||||
activeNames: ['2'],
|
||||
authorList_name: '',
|
||||
artMes: {
|
||||
articleId: this.$route.query.id
|
||||
articleId: routeArticleId
|
||||
},
|
||||
fileMesForm: {
|
||||
manuscirpt: '',
|
||||
@@ -551,7 +553,7 @@ import { buildArticleAddTableListFromWordFile } from '@/utils/mathFormulaModule'
|
||||
picturesAndTables: '',
|
||||
responseFile: '',
|
||||
supplementary:'', //
|
||||
articleId: this.$route.query.id,
|
||||
articleId: routeArticleId,
|
||||
username: localStorage.getItem('U_name')
|
||||
},
|
||||
msgform: {
|
||||
@@ -938,7 +940,12 @@ if(this.comentDeploy.length){
|
||||
|
||||
this.loading = true;
|
||||
if (this.wordTableParsePromise) {
|
||||
await this.wordTableParsePromise;
|
||||
try {
|
||||
await this.wordTableParsePromise;
|
||||
} catch (err) {
|
||||
console.warn('parseManuscriptWordTables failed:', err);
|
||||
this.wordTablePayloadList = [];
|
||||
}
|
||||
}
|
||||
await this.$api
|
||||
.post('api/Article/RepairBack', this.fileMesForm)
|
||||
@@ -963,11 +970,13 @@ if(this.comentDeploy.length){
|
||||
},500)
|
||||
|
||||
} else {
|
||||
this.loading = false;
|
||||
this.$message.error('Failed to submit, please contact administrator!');
|
||||
console.log(res.msg);
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
this.loading = false;
|
||||
console.log(err);
|
||||
});
|
||||
},
|
||||
@@ -1031,6 +1040,11 @@ if(this.comentDeploy.length){
|
||||
this.wordTablePayloadList = list || [];
|
||||
return this.wordTablePayloadList;
|
||||
})
|
||||
.catch((err) => {
|
||||
console.warn('parseManuscriptWordTables failed:', err);
|
||||
this.wordTablePayloadList = [];
|
||||
return [];
|
||||
})
|
||||
.finally(() => {
|
||||
this.wordTableParsePromise = null;
|
||||
});
|
||||
|
||||
@@ -152,10 +152,84 @@
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
<span v-else-if="refRelevanceActionState === 'done'" class="ref-relevance-done-badge">
|
||||
<i class="el-icon-circle-check"></i>
|
||||
<span>{{ refRelevanceDoneLabel }}</span>
|
||||
</span>
|
||||
<div v-else-if="refRelevanceActionState === 'done'" class="ref-audit-done-bar">
|
||||
<div class="done-meta">
|
||||
<div class="done-status">
|
||||
<span class="status-title status-title--done">
|
||||
<i class="el-icon-circle-check"></i>
|
||||
<span>{{ $t('refRelevance.auditDoneTitle') }}</span>
|
||||
</span>
|
||||
<p class="done-subtext">{{ refRelevanceDoneSubtext }}</p>
|
||||
</div>
|
||||
<div class="done-side">
|
||||
<span v-if="refAuditProgressTotal" class="status-counter">
|
||||
<span class="count">
|
||||
{{ refAuditProgressFinished }}/{{ refAuditProgressTotal }}
|
||||
</span>
|
||||
</span>
|
||||
<el-button
|
||||
v-if="showRefRelevanceRedetectButton"
|
||||
size="small"
|
||||
type="primary"
|
||||
plain
|
||||
icon="el-icon-refresh-right"
|
||||
:disabled="refRelevanceStatusLoading || refRelevanceGlobalDetecting"
|
||||
@click="openRefRelevanceRedetectDialog"
|
||||
>
|
||||
{{ $t('refRelevance.redetect') }}
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<el-dialog
|
||||
:title="$t('refRelevance.redetectConfirmTitle')"
|
||||
:visible.sync="refRelevanceRedetectDialogVisible"
|
||||
width="440px"
|
||||
append-to-body
|
||||
:close-on-click-modal="false"
|
||||
custom-class="ref-relevance-redetect-dialog"
|
||||
@closed="resetRefRelevanceRedetectDialog"
|
||||
>
|
||||
<p class="ref-relevance-redetect-dialog-tip">
|
||||
{{ $t('refRelevance.redetectDialogTip') }}
|
||||
</p>
|
||||
<el-radio-group
|
||||
v-model="refRelevanceRedetectChoice"
|
||||
class="ref-relevance-redetect-options"
|
||||
>
|
||||
<el-radio
|
||||
label="notfound"
|
||||
:disabled="!hasRefRelevanceNotFound"
|
||||
class="ref-relevance-redetect-option"
|
||||
>
|
||||
<span class="ref-relevance-redetect-option__label">
|
||||
{{ $t('refRelevance.redetectNotFound') }}
|
||||
</span>
|
||||
<span
|
||||
v-if="hasRefRelevanceNotFound"
|
||||
class="ref-relevance-redetect-option__meta"
|
||||
>
|
||||
{{ $t('refRelevance.redetectNotFoundCount', { count: refRelevanceNotFoundRows.length }) }}
|
||||
</span>
|
||||
</el-radio>
|
||||
<el-radio label="all" class="ref-relevance-redetect-option">
|
||||
<span class="ref-relevance-redetect-option__label">
|
||||
{{ $t('refRelevance.redetectAll') }}
|
||||
</span>
|
||||
<span class="ref-relevance-redetect-option__meta">
|
||||
{{ $t('refRelevance.redetectAllDesc') }}
|
||||
</span>
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button @click="refRelevanceRedetectDialogVisible = false">
|
||||
{{ $t('refRelevance.redetectConfirmCancel') }}
|
||||
</el-button>
|
||||
<el-button type="primary" @click="submitRefRelevanceRedetectDialog">
|
||||
{{ $t('refRelevance.redetectConfirmOk') }}
|
||||
</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
</div>
|
||||
<!-- <div v-if="showB_step == 2" class="ref-ai-filter-group">
|
||||
<el-radio-group v-model="refAiFilter" size="small" @change="onRefAiFilterChange">
|
||||
@@ -987,7 +1061,11 @@ export default {
|
||||
/** 单条参考文献重新检测 loading(p_refer_id -> true) */
|
||||
refRelevanceRedetectingIds: {},
|
||||
/** 单条参考文献详情轮询 timer(p_refer_id -> timerId) */
|
||||
refRelevanceDetailsPollTimers: {}
|
||||
refRelevanceDetailsPollTimers: {},
|
||||
refRelevanceRedetectDialogVisible: false,
|
||||
refRelevanceRedetectChoice: 'all',
|
||||
/** 重新核查入口(暂隐藏) */
|
||||
showRefRelevanceRedetectButton: false
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
@@ -1044,6 +1122,20 @@ export default {
|
||||
if (status === 2 && label) return label;
|
||||
return this.$t('refRelevance.checkComplete');
|
||||
},
|
||||
refRelevanceDoneSubtext() {
|
||||
if (this.hasRefRelevanceNotFound) {
|
||||
return this.$t('refRelevance.doneNotFoundHint', {
|
||||
count: this.refRelevanceNotFoundRows.length
|
||||
});
|
||||
}
|
||||
return this.$t('refRelevance.doneAllClearHint');
|
||||
},
|
||||
refRelevanceNotFoundRows() {
|
||||
return (this.chanFerForm || []).filter((row) => this.isRefRowRelevanceNotFound(row));
|
||||
},
|
||||
hasRefRelevanceNotFound() {
|
||||
return this.refRelevanceNotFoundRows.length > 0;
|
||||
},
|
||||
refRelevanceScanSubtext() {
|
||||
const label = (this.refRelevanceArticleStatus.status_label || '').trim();
|
||||
if (label && label !== this.$t('refRelevance.detectingAi')) return label;
|
||||
@@ -2635,27 +2727,10 @@ export default {
|
||||
if (this.isRefRowRelevanceRedetecting(row)) return;
|
||||
const referId = String(row.p_refer_id);
|
||||
this.stopRefRelevancePoll();
|
||||
this.$set(this.refRelevanceRedetectingIds, referId, true);
|
||||
if (this.refRelevanceDetailsCache[referId]) {
|
||||
this.$delete(this.refRelevanceDetailsCache, referId);
|
||||
}
|
||||
this.$set(row, '_refAiItemStatus', 1);
|
||||
this.$set(row, '_refAiState', 'detecting');
|
||||
this.$set(row, 'ai_relevance_list', []);
|
||||
this.$set(row, '_refAiVisibleCount', 0);
|
||||
this.$set(row, '_refAiPendingCites', 0);
|
||||
this.prepareRefRowRelevanceRecheck(row);
|
||||
this.refreshRefAiTableLayout();
|
||||
this.$api
|
||||
.post('api/References/referenceCheckRecheckFailedAI', {
|
||||
p_article_id: this.p_article_id,
|
||||
p_refer_id: String(row.p_refer_id)
|
||||
})
|
||||
.then((res) => {
|
||||
if (res.code !== 0) {
|
||||
return Promise.reject(new Error(res.msg || this.$t('refRelevance.redetectFailed')));
|
||||
}
|
||||
return this.pollRefRelevanceOnce();
|
||||
})
|
||||
this.requestRefRowRelevanceRecheck(row)
|
||||
.then(() => this.pollRefRelevanceOnce())
|
||||
.then((finished) => {
|
||||
if (!finished && this.isRefRelevanceStatusRunning()) {
|
||||
this.continueRefRelevancePoll();
|
||||
@@ -2672,6 +2747,98 @@ export default {
|
||||
this.refreshRefAiTableLayout();
|
||||
});
|
||||
},
|
||||
prepareRefRowRelevanceRecheck(row) {
|
||||
if (!row || row.p_refer_id == null) return '';
|
||||
const referId = String(row.p_refer_id);
|
||||
if (this.refRelevanceDetailsCache[referId]) {
|
||||
this.$delete(this.refRelevanceDetailsCache, referId);
|
||||
}
|
||||
this.$set(row, '_refAiItemStatus', 1);
|
||||
this.$set(row, '_refAiState', 'detecting');
|
||||
this.$set(row, 'ai_relevance_list', []);
|
||||
this.$set(row, '_refAiVisibleCount', 0);
|
||||
this.$set(row, '_refAiPendingCites', 0);
|
||||
return referId;
|
||||
},
|
||||
requestRefRowRelevanceRecheck(row) {
|
||||
if (!row || row.p_refer_id == null || !this.p_article_id) {
|
||||
return Promise.reject(new Error(this.$t('refRelevance.noReferId')));
|
||||
}
|
||||
const referId = String(row.p_refer_id);
|
||||
this.$set(this.refRelevanceRedetectingIds, referId, true);
|
||||
return this.$api
|
||||
.post('api/References/referenceCheckRecheckFailedAI', {
|
||||
p_article_id: this.p_article_id,
|
||||
p_refer_id: referId
|
||||
})
|
||||
.then((res) => {
|
||||
if (res.code !== 0) {
|
||||
return Promise.reject(new Error(res.msg || this.$t('refRelevance.redetectFailed')));
|
||||
}
|
||||
return res;
|
||||
});
|
||||
},
|
||||
openRefRelevanceRedetectDialog() {
|
||||
if (this.refRelevanceStatusLoading || this.refRelevanceGlobalDetecting) return;
|
||||
this.refRelevanceRedetectChoice = this.hasRefRelevanceNotFound ? 'notfound' : 'all';
|
||||
this.refRelevanceRedetectDialogVisible = true;
|
||||
},
|
||||
resetRefRelevanceRedetectDialog() {
|
||||
this.refRelevanceRedetectChoice = this.hasRefRelevanceNotFound ? 'notfound' : 'all';
|
||||
},
|
||||
submitRefRelevanceRedetectDialog() {
|
||||
this.refRelevanceRedetectDialogVisible = false;
|
||||
if (this.refRelevanceRedetectChoice === 'notfound') {
|
||||
if (!this.hasRefRelevanceNotFound) return;
|
||||
this.startRefRelevanceRedetectNotFound();
|
||||
return;
|
||||
}
|
||||
this.startRefRelevanceDetect();
|
||||
},
|
||||
startRefRelevanceRedetectNotFound() {
|
||||
const rows = this.refRelevanceNotFoundRows.slice();
|
||||
if (!rows.length || !this.p_article_id) return;
|
||||
this.stopRefRelevancePoll();
|
||||
this.applyRefRelevanceArticleStatus({
|
||||
status: 1,
|
||||
status_label: this.$t('refRelevance.detectingAi'),
|
||||
progress_percent: 0,
|
||||
total: 0,
|
||||
done: 0,
|
||||
pending: 0,
|
||||
failed: 0
|
||||
});
|
||||
rows.forEach((row) => this.prepareRefRowRelevanceRecheck(row));
|
||||
this.refreshRefAiTableLayout();
|
||||
const self = this;
|
||||
rows
|
||||
.reduce(function (chain, row) {
|
||||
return chain.then(function () {
|
||||
return self.requestRefRowRelevanceRecheck(row);
|
||||
});
|
||||
}, Promise.resolve())
|
||||
.then(function () {
|
||||
return self.pollRefRelevanceOnce();
|
||||
})
|
||||
.then(function (finished) {
|
||||
if (!finished && self.isRefRelevanceStatusRunning()) {
|
||||
self.continueRefRelevancePoll();
|
||||
}
|
||||
})
|
||||
.catch(function (err) {
|
||||
const msg = err && err.message ? err.message : String(err);
|
||||
self.$message.error(msg || self.$t('refRelevance.redetectFailed'));
|
||||
return self.pollRefRelevanceOnce();
|
||||
})
|
||||
.finally(function () {
|
||||
rows.forEach(function (row) {
|
||||
if (row && row.p_refer_id != null) {
|
||||
self.$delete(self.refRelevanceRedetectingIds, String(row.p_refer_id));
|
||||
}
|
||||
});
|
||||
self.refreshRefAiTableLayout();
|
||||
});
|
||||
},
|
||||
isRefRowRelevancePending(row) {
|
||||
if (!row || this.isRefRelevanceUncited(row)) return false;
|
||||
const itemSt = this.getRefRowProgressStatus(row);
|
||||
@@ -5906,6 +6073,61 @@ export default {
|
||||
border-radius: 2px;
|
||||
transition: width 0.3s ease;
|
||||
}
|
||||
.ref-audit-done-bar {
|
||||
width: auto;
|
||||
min-width: 400px;
|
||||
max-width: 560px;
|
||||
padding: 8px 12px;
|
||||
background: #f0f9eb;
|
||||
border: 1px solid #e1f3d8;
|
||||
border-radius: 6px;
|
||||
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.05);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.ref-audit-done-bar .done-meta {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
}
|
||||
.ref-audit-done-bar .done-status {
|
||||
flex: 1 1 auto;
|
||||
min-width: 0;
|
||||
}
|
||||
.ref-audit-done-bar .status-title--done {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
color: #529b2e;
|
||||
line-height: 1.4;
|
||||
}
|
||||
.ref-audit-done-bar .status-title--done .el-icon-circle-check {
|
||||
flex-shrink: 0;
|
||||
font-size: 14px;
|
||||
color: #67c23a;
|
||||
}
|
||||
.ref-audit-done-bar .done-subtext {
|
||||
margin: 4px 0 0;
|
||||
padding: 0;
|
||||
font-size: 12px;
|
||||
line-height: 1.5;
|
||||
color: #909399;
|
||||
font-weight: normal;
|
||||
}
|
||||
.ref-audit-done-bar .done-side {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.ref-audit-done-bar .status-counter {
|
||||
font-family: 'JetBrains Mono', Consolas, monospace, sans-serif;
|
||||
font-size: 11px;
|
||||
color: #606266;
|
||||
white-space: nowrap;
|
||||
}
|
||||
@keyframes ref-relevance-spin {
|
||||
from {
|
||||
transform: rotate(0deg);
|
||||
@@ -5917,20 +6139,41 @@ export default {
|
||||
.ref-relevance-spin {
|
||||
animation: ref-relevance-spin 1s linear infinite;
|
||||
}
|
||||
.ref-relevance-done-badge {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
padding: 8px 14px;
|
||||
.ref-relevance-redetect-dialog-tip {
|
||||
margin: 0 0 16px;
|
||||
font-size: 13px;
|
||||
line-height: 1;
|
||||
color: #67c23a;
|
||||
background: #f0f9eb;
|
||||
border: 1px solid #e1f3d8;
|
||||
border-radius: 4px;
|
||||
line-height: 1.6;
|
||||
color: #606266;
|
||||
}
|
||||
.ref-relevance-done-badge .el-icon-circle-check {
|
||||
font-size: 18px;
|
||||
.ref-relevance-redetect-options {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
width: 100%;
|
||||
}
|
||||
.ref-relevance-redetect-option {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
margin-right: 0;
|
||||
padding: 12px 14px;
|
||||
border: 1px solid #dcdfe6;
|
||||
border-radius: 4px;
|
||||
white-space: normal;
|
||||
}
|
||||
.ref-relevance-redetect-option.is-checked {
|
||||
border-color: #409eff;
|
||||
background: #ecf5ff;
|
||||
}
|
||||
.ref-relevance-redetect-option__label {
|
||||
display: block;
|
||||
font-size: 14px;
|
||||
color: #303133;
|
||||
}
|
||||
.ref-relevance-redetect-option__meta {
|
||||
display: block;
|
||||
margin-top: 4px;
|
||||
font-size: 12px;
|
||||
color: #909399;
|
||||
}
|
||||
.ref-ai-cell--loading {
|
||||
display: flex;
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="crumbs">
|
||||
<el-button type="text" icon="el-icon-arrow-left" @click="goBackInbox" class="back-inbox-btn">
|
||||
{{ $t('mailboxSend.backToInbox') }}
|
||||
</el-button>
|
||||
<el-breadcrumb separator="/">
|
||||
<el-breadcrumb-item>
|
||||
<i class="el-icon-message"></i> {{ $t('mailboxSend.title') }}
|
||||
</el-breadcrumb-item>
|
||||
</el-breadcrumb>
|
||||
</div>
|
||||
|
||||
<div class="container" style="padding-top: 0px;" v-if="showSendEmail">
|
||||
<!-- 阻止回车在收件人/主题等输入框触发表单隐式提交(误点发送) -->
|
||||
<form class="mail-compose-form" @submit.prevent @keydown.enter="preventComposeEnterSubmit">
|
||||
<div v-if="articleContext.loaded && hasArticleTemplatePlaceholders" class="article-template-vars-bar mail_shuru">
|
||||
<div class="mail-compose-header">
|
||||
<div class="crumbs">
|
||||
<el-button type="text" icon="el-icon-arrow-left" @click="goBackInbox" class="back-inbox-btn">
|
||||
{{ $t('mailboxSend.backToInbox') }}
|
||||
</el-button>
|
||||
<el-breadcrumb separator="/">
|
||||
<el-breadcrumb-item>
|
||||
<i class="el-icon-message"></i> {{ $t('mailboxSend.title') }}
|
||||
</el-breadcrumb-item>
|
||||
</el-breadcrumb>
|
||||
</div>
|
||||
<div
|
||||
v-if="showSendEmail && articleContext.loaded && hasArticleTemplatePlaceholders"
|
||||
class="article-template-vars-bar"
|
||||
>
|
||||
<span class="article-loaded-sn">SN {{ articleContext.acceptSn || '—' }}</span>
|
||||
<el-button
|
||||
size="mini"
|
||||
@@ -26,7 +26,11 @@
|
||||
{{ $t('mailboxSend.articleContextReplaceVars') }}
|
||||
</el-button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="container" style="padding-top: 0px;" v-if="showSendEmail">
|
||||
<!-- 阻止回车在收件人/主题等输入框触发表单隐式提交(误点发送) -->
|
||||
<form class="mail-compose-form" @submit.prevent @keydown.enter="preventComposeEnterSubmit">
|
||||
<el-dialog
|
||||
:title="articleContextDialogTitle"
|
||||
:visible.sync="articleContextDialogVisible"
|
||||
@@ -63,9 +67,10 @@
|
||||
</div>
|
||||
|
||||
<div v-if="articleContext.loaded" class="article-context-loaded-hint">
|
||||
<span class="article-loaded-sn">SN {{ articleContext.acceptSn || '—' }}</span>
|
||||
<span class="article-loaded-divider">|</span>
|
||||
<span class="article-loaded-title" :title="articleContext.title">{{ articleContextTitleBrief }}</span>
|
||||
<div class="article-loaded-line">
|
||||
<span class="article-loaded-sn">SN {{ articleContext.acceptSn || '—' }}</span>
|
||||
</div>
|
||||
<div v-if="articleContext.title" class="article-loaded-title">{{ articleContext.title }}</div>
|
||||
</div>
|
||||
<div v-else-if="!articleContextLoading" class="article-contact-empty article-contact-empty--hint">
|
||||
{{ $t('mailboxSend.articleContextSearchHint') }}
|
||||
@@ -78,7 +83,7 @@
|
||||
:class="{ 'is-active': articleContactActiveTab === 'authors' }"
|
||||
@click="switchArticleContactTab('authors')"
|
||||
>
|
||||
{{ $t('mailboxSend.articleContextNavAuthors') }}
|
||||
{{ $t('mailboxSend.articleContextNavAuthors') }} ({{ authorContactCount }})
|
||||
</div>
|
||||
<div
|
||||
class="article-context-nav-item"
|
||||
@@ -104,22 +109,6 @@
|
||||
|
||||
<div class="article-context-main">
|
||||
<div v-show="articleContactActiveTab === 'authors'" class="article-block">
|
||||
<div class="article-block-head">
|
||||
<div class="article-block-title">{{ $t('mailboxSend.articleContextNavAuthors') }}</div>
|
||||
<div v-if="(articleContext.authors || []).length" class="article-block-actions">
|
||||
<el-button type="text" size="mini" @click="selectAllArticleContacts('authors')">{{ $t('mailboxSend.articleContextSelectAll') }}</el-button>
|
||||
<el-button type="text" size="mini" @click="clearArticleContacts('authors')">{{ $t('mailboxSend.articleContextClearAll') }}</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
size="mini"
|
||||
plain
|
||||
:disabled="!(articleContactSelected.authors || []).length"
|
||||
@click="addSelectedArticleContacts('authors')"
|
||||
>
|
||||
{{ $t('mailboxSend.articleContextAddSelected') }} ({{ (articleContactSelected.authors || []).length }})
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="!(articleContext.authors || []).length" class="article-contact-empty">{{ $t('mailboxSend.articleContextEmptyGroup') }}</div>
|
||||
<div v-else class="overflow-x-auto">
|
||||
<table class="review_table">
|
||||
@@ -135,31 +124,34 @@
|
||||
</th>
|
||||
<th class="review_table_index">No.</th>
|
||||
<th>{{ $t('mailboxSend.tableName') }}</th>
|
||||
<th>{{ $t('mailboxSend.tableAuthorRole') }}</th>
|
||||
<th>{{ $t('mailboxSend.tableEmail') }}</th>
|
||||
<th class="review_table_role">{{ $t('mailboxSend.tableAuthorRole') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="(author, idx) in articleContext.authors" :key="author.key">
|
||||
<tr
|
||||
v-for="(author, idx) in articleContext.authors"
|
||||
:key="author.key"
|
||||
:class="{ 'review_table_row--disabled': !hasContactEmail(author) }"
|
||||
>
|
||||
<td class="review_table_check">
|
||||
<el-checkbox
|
||||
v-if="hasContactEmail(author)"
|
||||
:value="isContactSelected('authors', author.key)"
|
||||
:disabled="!author.email"
|
||||
@change="toggleContactSelected('authors', author.key, $event)"
|
||||
/>
|
||||
</td>
|
||||
<td class="review_table_index">{{ idx + 1 }}</td>
|
||||
<td>{{ author.name || '—' }}</td>
|
||||
<td>{{ formatAuthorRolesShort(author.roles) || '—' }}</td>
|
||||
<td>
|
||||
<div class="reviewer-email-cell">
|
||||
<template v-if="author.email">
|
||||
<div class="author-name-email-cell">
|
||||
<div class="author-name-email-cell__name">{{ author.name || '—' }}</div>
|
||||
<div v-if="author.email" class="author-name-email-cell__email">
|
||||
<span class="is-clickable" @click="addContactToTo(author)">{{ author.email }}</span>
|
||||
<i class="el-icon-document-copy article-copy-icon" :title="$t('mailboxSend.copyText')" @click.stop="copyContactText(author.email)"></i>
|
||||
</template>
|
||||
<span v-else>{{ $t('mailboxSend.articleContextNoEmail') }}</span>
|
||||
</div>
|
||||
<div v-else class="author-name-email-cell__email reviewer-no-email">{{ $t('mailboxSend.articleContextNoEmail') }}</div>
|
||||
</div>
|
||||
</td>
|
||||
<td class="review_table_role">{{ formatAuthorRoles(author.roles) }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
@@ -167,22 +159,6 @@
|
||||
</div>
|
||||
|
||||
<div v-show="articleContactActiveTab === 'review'" class="article-block">
|
||||
<div class="article-block-head">
|
||||
<div class="article-block-title">{{ $t('mailboxSend.articleContextNavUnderReview') }}</div>
|
||||
<div v-if="hasReviewTab" class="article-block-actions">
|
||||
<el-button type="text" size="mini" @click="selectAllArticleContacts('review')">{{ $t('mailboxSend.articleContextSelectAll') }}</el-button>
|
||||
<el-button type="text" size="mini" @click="clearArticleContacts('review')">{{ $t('mailboxSend.articleContextClearAll') }}</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
size="mini"
|
||||
plain
|
||||
:disabled="!(articleContactSelected.review || []).length"
|
||||
@click="addSelectedArticleContacts('review')"
|
||||
>
|
||||
{{ $t('mailboxSend.articleContextAddSelected') }} ({{ (articleContactSelected.review || []).length }})
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="!hasReviewTab" class="article-contact-empty">{{ $t('mailboxSend.articleContextEmptyGroup') }}</div>
|
||||
<div v-else class="overflow-x-auto">
|
||||
<table class="review_table">
|
||||
@@ -245,22 +221,6 @@
|
||||
</div>
|
||||
|
||||
<div v-show="articleContactActiveTab === 'final'" class="article-block">
|
||||
<div class="article-block-head">
|
||||
<div class="article-block-title">{{ $t('mailboxSend.articleContextNavFinal') }}</div>
|
||||
<div v-if="hasFinalTab" class="article-block-actions">
|
||||
<el-button type="text" size="mini" @click="selectAllArticleContacts('final')">{{ $t('mailboxSend.articleContextSelectAll') }}</el-button>
|
||||
<el-button type="text" size="mini" @click="clearArticleContacts('final')">{{ $t('mailboxSend.articleContextClearAll') }}</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
size="mini"
|
||||
plain
|
||||
:disabled="!(articleContactSelected.final || []).length"
|
||||
@click="addSelectedArticleContacts('final')"
|
||||
>
|
||||
{{ $t('mailboxSend.articleContextAddSelected') }} ({{ (articleContactSelected.final || []).length }})
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="!hasFinalTab" class="article-contact-empty">{{ $t('mailboxSend.articleContextEmptyGroup') }}</div>
|
||||
<div v-else class="overflow-x-auto">
|
||||
<table class="review_table">
|
||||
@@ -321,7 +281,8 @@
|
||||
>
|
||||
<div class="article-context-selected-text">
|
||||
<div class="article-context-selected-name" :title="item.display">{{ item.display }}</div>
|
||||
<div v-if="item.subtitle" class="article-context-selected-sub">{{ item.subtitle }}</div>
|
||||
<div v-if="item.subtitle" class="article-context-selected-sub" :title="item.subtitle">{{ item.subtitle }}</div>
|
||||
<div v-if="item.identity" class="article-context-selected-identity">{{ item.identity }}</div>
|
||||
</div>
|
||||
<i
|
||||
class="el-icon-close article-context-selected-remove"
|
||||
@@ -345,7 +306,7 @@
|
||||
</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
<div class="mail_shuru" style="position: relative; display: flex; align-items: center;">
|
||||
<div class="mail_shuru mail_shuru--to" style="position: relative; display: flex; align-items: center;">
|
||||
<span class="mail_tit">{{ $t('mailboxSend.to') }}</span>
|
||||
|
||||
<div style="flex: 1; display: flex; flex-wrap: wrap; align-items: center;">
|
||||
@@ -694,8 +655,9 @@ import { applyReviewNotifyTemplateVariables } from '@/utils/mailTemplatePreview'
|
||||
return this.$t('mailboxSend.articleContextPickTitle');
|
||||
},
|
||||
articleSelectedTotalCount() {
|
||||
const sel = this.articleContactSelected || {};
|
||||
return (sel.authors || []).length + (sel.review || []).length + (sel.final || []).length;
|
||||
const activeModule = this.getActiveArticleContactModule();
|
||||
if (!activeModule) return 0;
|
||||
return (this.articleContactSelected[activeModule] || []).length;
|
||||
},
|
||||
hasArticleTemplatePlaceholders() {
|
||||
const text = this.getMailTextForTemplateScan();
|
||||
@@ -710,30 +672,33 @@ import { applyReviewNotifyTemplateVariables } from '@/utils/mailTemplatePreview'
|
||||
reviewContactCount() {
|
||||
return (this.articleContext.reviewRows || []).length;
|
||||
},
|
||||
authorContactCount() {
|
||||
return (this.articleContext.authors || []).length;
|
||||
},
|
||||
finalContactCount() {
|
||||
return (this.articleContext.finalReviewers || []).length;
|
||||
},
|
||||
articleSelectedContactList() {
|
||||
const self = this;
|
||||
const modules = ['authors', 'review', 'final'];
|
||||
const activeModule = this.getActiveArticleContactModule();
|
||||
if (!activeModule) return [];
|
||||
const list = [];
|
||||
modules.forEach(function (module) {
|
||||
const keys = self.articleContactSelected[module] || [];
|
||||
const map = {};
|
||||
self.getModuleContactList(module).forEach(function (item) {
|
||||
map[item.key] = item;
|
||||
});
|
||||
keys.forEach(function (key) {
|
||||
const contact = map[key];
|
||||
if (!contact || !contact.email) return;
|
||||
const name = String(contact.name || '').trim();
|
||||
const email = String(contact.email || '').trim();
|
||||
list.push({
|
||||
module: module,
|
||||
key: key,
|
||||
display: name || email,
|
||||
subtitle: name && name !== email ? email : ''
|
||||
});
|
||||
const keys = self.articleContactSelected[activeModule] || [];
|
||||
const map = {};
|
||||
self.getModuleContactList(activeModule).forEach(function (item) {
|
||||
map[item.key] = item;
|
||||
});
|
||||
keys.forEach(function (key) {
|
||||
const contact = map[key];
|
||||
if (!contact || !contact.email) return;
|
||||
const name = String(contact.name || '').trim();
|
||||
const email = String(contact.email || '').trim();
|
||||
list.push({
|
||||
module: activeModule,
|
||||
key: key,
|
||||
display: name || email,
|
||||
subtitle: email,
|
||||
identity: self.formatArticleContactIdentity(activeModule, contact)
|
||||
});
|
||||
});
|
||||
return list;
|
||||
@@ -791,19 +756,31 @@ import { applyReviewNotifyTemplateVariables } from '@/utils/mailTemplatePreview'
|
||||
this.loadArticleContext(idStr, { silent: true });
|
||||
},
|
||||
openArticleContactDialog() {
|
||||
this.articleContactActiveTab = 'authors';
|
||||
this.resetArticleContactDialog();
|
||||
this.articleContextDialogVisible = true;
|
||||
},
|
||||
resetArticleContactDialog() {
|
||||
this.articleContextInput = '';
|
||||
this.articleContextLoading = false;
|
||||
this.articleContext = {
|
||||
loaded: false,
|
||||
articleId: '',
|
||||
acceptSn: '',
|
||||
title: '',
|
||||
authors: [],
|
||||
reviewRows: [],
|
||||
finalReviewers: []
|
||||
};
|
||||
this.resetArticleContactSelection();
|
||||
this.articleContactActiveTab = 'authors';
|
||||
},
|
||||
switchArticleContactTab(tab) {
|
||||
if (tab === 'review' && !this.hasReviewTab) return;
|
||||
if (tab === 'final' && !this.hasFinalTab) return;
|
||||
this.articleContactActiveTab = tab;
|
||||
},
|
||||
handleArticleContactDialogOpen() {
|
||||
if (!this.articleContactActiveTab) {
|
||||
this.articleContactActiveTab = 'authors';
|
||||
}
|
||||
if (this.articleContextInput) return;
|
||||
this.articleContactActiveTab = 'authors';
|
||||
const qId =
|
||||
this.$route.query.article_id ||
|
||||
this.$route.query.articleId ||
|
||||
@@ -868,6 +845,48 @@ import { applyReviewNotifyTemplateVariables } from '@/utils/mailTemplatePreview'
|
||||
if ((roles || []).indexOf('correspondingAuthor') >= 0) parts.push(this.$t('mailboxSend.roleCorrespondingAuthorShort'));
|
||||
return parts.join('/');
|
||||
},
|
||||
formatArticleContactIdentity(module, contact) {
|
||||
if (!contact) return '';
|
||||
if (module === 'authors') {
|
||||
const roles = this.formatAuthorRoles(contact.roles);
|
||||
return roles && roles !== '—' ? roles : this.$t('mailboxSend.articleContextNavAuthors');
|
||||
}
|
||||
if (module === 'review') {
|
||||
const parts = [this.$t('mailboxSend.articleContextNavUnderReview')];
|
||||
if (contact.score != null && contact.score !== '') {
|
||||
parts.push(this.$t('mailboxSend.articleContextReviewerScore', { score: contact.score }));
|
||||
}
|
||||
if (this.hasFirstReviewDisplay(contact.firstReview)) {
|
||||
const label = this.formatFirstReviewLabel(contact.firstReview);
|
||||
if (label && label !== '—') {
|
||||
parts.push(this.$t('mailboxSend.articleContextFirstReviewLine', { label: label }));
|
||||
}
|
||||
}
|
||||
const repeats = contact.repeats || [];
|
||||
for (let i = repeats.length - 1; i >= 0; i--) {
|
||||
if (!this.hasRepeatReviewDisplay(repeats[i])) continue;
|
||||
const repLabel = this.formatRepeatReviewLabel(repeats[i]);
|
||||
if (repLabel && repLabel !== '—') {
|
||||
parts.push(
|
||||
this.$t('mailboxSend.articleContextRepeatReviewLine', {
|
||||
n: i + 2,
|
||||
label: repLabel
|
||||
})
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return parts.join(' · ');
|
||||
}
|
||||
if (module === 'final') {
|
||||
const decision = this.formatFinalDecisionLabel(contact.finalState);
|
||||
if (decision && decision !== '—') {
|
||||
return this.$t('mailboxSend.articleContextFinalReviewLine', { decision: decision });
|
||||
}
|
||||
return this.$t('mailboxSend.articleContextNavFinal');
|
||||
}
|
||||
return '';
|
||||
},
|
||||
formatFirstReviewLabel(review) {
|
||||
if (!review) return '—';
|
||||
if (Number(review.state) === 0) return '—';
|
||||
@@ -1115,6 +1134,23 @@ import { applyReviewNotifyTemplateVariables } from '@/utils/mailTemplatePreview'
|
||||
resetArticleContactSelection() {
|
||||
this.articleContactSelected = { authors: [], review: [], final: [] };
|
||||
},
|
||||
getActiveArticleContactModule() {
|
||||
const modules = ['authors', 'review', 'final'];
|
||||
for (let i = 0; i < modules.length; i++) {
|
||||
const module = modules[i];
|
||||
if ((this.articleContactSelected[module] || []).length) {
|
||||
return module;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
ensureSingleArticleContactModule(module) {
|
||||
const active = this.getActiveArticleContactModule();
|
||||
if (active && active !== module) {
|
||||
this.resetArticleContactSelection();
|
||||
this.$message.info(this.$t('mailboxSend.articleContextTypeSwitched'));
|
||||
}
|
||||
},
|
||||
sanitizeArticleContactSelection() {
|
||||
const self = this;
|
||||
['authors', 'review', 'final'].forEach(function (module) {
|
||||
@@ -1150,6 +1186,7 @@ import { applyReviewNotifyTemplateVariables } from '@/utils/mailTemplatePreview'
|
||||
return item.key === key;
|
||||
});
|
||||
if (!this.hasContactEmail(contact)) return;
|
||||
this.ensureSingleArticleContactModule(module);
|
||||
}
|
||||
const arr = (this.articleContactSelected[module] || []).slice();
|
||||
const idx = arr.indexOf(key);
|
||||
@@ -1184,6 +1221,7 @@ import { applyReviewNotifyTemplateVariables } from '@/utils/mailTemplatePreview'
|
||||
}
|
||||
},
|
||||
selectAllArticleContacts(module) {
|
||||
this.ensureSingleArticleContactModule(module);
|
||||
const keys = this.getModuleContacts(module).map(function (c) {
|
||||
return c.key;
|
||||
});
|
||||
@@ -1217,10 +1255,9 @@ import { applyReviewNotifyTemplateVariables } from '@/utils/mailTemplatePreview'
|
||||
return added;
|
||||
},
|
||||
addAllSelectedArticleContacts() {
|
||||
let total = 0;
|
||||
total += this.addSelectedArticleContacts('authors', true) || 0;
|
||||
total += this.addSelectedArticleContacts('review', true) || 0;
|
||||
total += this.addSelectedArticleContacts('final', true) || 0;
|
||||
const activeModule = this.getActiveArticleContactModule();
|
||||
if (!activeModule) return;
|
||||
const total = this.addSelectedArticleContacts(activeModule, true) || 0;
|
||||
if (total > 0) {
|
||||
this.$message.success(this.$t('mailboxSend.articleContextAddedTo', { count: total }));
|
||||
this.articleContextDialogVisible = false;
|
||||
@@ -1927,10 +1964,21 @@ import { applyReviewNotifyTemplateVariables } from '@/utils/mailTemplatePreview'
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.mail-compose-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 16px;
|
||||
margin-bottom: 16px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.crumbs {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 16px;
|
||||
margin-bottom: 0;
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
.back-inbox-btn {
|
||||
margin-right: 12px;
|
||||
@@ -1968,15 +2016,30 @@ import { applyReviewNotifyTemplateVariables } from '@/utils/mailTemplatePreview'
|
||||
padding-right: 10px;
|
||||
}
|
||||
|
||||
.article-context-loaded-hint,
|
||||
.article-template-vars-bar {
|
||||
.article-context-loaded-hint {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
align-items: flex-start;
|
||||
gap: 4px;
|
||||
flex-wrap: wrap;
|
||||
margin-bottom: 12px;
|
||||
font-size: 13px;
|
||||
color: #606266;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.article-template-vars-bar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
flex-shrink: 0;
|
||||
margin-left: auto;
|
||||
font-size: 13px;
|
||||
color: #606266;
|
||||
}
|
||||
|
||||
.article-loaded-line {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.article-loaded-sn {
|
||||
@@ -1984,17 +2047,12 @@ import { applyReviewNotifyTemplateVariables } from '@/utils/mailTemplatePreview'
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.article-loaded-divider {
|
||||
color: #dcdfe6;
|
||||
}
|
||||
|
||||
.article-loaded-title {
|
||||
flex: 1;
|
||||
min-width: 120px;
|
||||
max-width: 520px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
width: 100%;
|
||||
color: #606266;
|
||||
line-height: 1.5;
|
||||
word-break: break-word;
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
.article-contact-empty--hint {
|
||||
@@ -2013,7 +2071,7 @@ import { applyReviewNotifyTemplateVariables } from '@/utils/mailTemplatePreview'
|
||||
}
|
||||
|
||||
.article-context-nav {
|
||||
width: 148px;
|
||||
width: 172px;
|
||||
flex-shrink: 0;
|
||||
background: #fafafa;
|
||||
border-right: 1px solid #ebeef5;
|
||||
@@ -2021,13 +2079,14 @@ import { applyReviewNotifyTemplateVariables } from '@/utils/mailTemplatePreview'
|
||||
}
|
||||
|
||||
.article-context-nav-item {
|
||||
padding: 12px 16px;
|
||||
padding: 12px 14px;
|
||||
font-size: 13px;
|
||||
color: #606266;
|
||||
cursor: pointer;
|
||||
border-left: 3px solid transparent;
|
||||
transition: all 0.2s;
|
||||
line-height: 1.4;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.article-context-nav-item:hover:not(.is-disabled) {
|
||||
@@ -2056,7 +2115,7 @@ import { applyReviewNotifyTemplateVariables } from '@/utils/mailTemplatePreview'
|
||||
}
|
||||
|
||||
.article-context-selected {
|
||||
width: 240px;
|
||||
width: 280px;
|
||||
flex-shrink: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -2131,6 +2190,19 @@ import { applyReviewNotifyTemplateVariables } from '@/utils/mailTemplatePreview'
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.article-context-selected-identity {
|
||||
display: inline-block;
|
||||
margin-top: 4px;
|
||||
padding: 2px 6px;
|
||||
max-width: 100%;
|
||||
font-size: 11px;
|
||||
line-height: 1.4;
|
||||
color: #606266;
|
||||
background: #f4f4f5;
|
||||
border-radius: 3px;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.article-context-selected-remove {
|
||||
flex-shrink: 0;
|
||||
margin-top: 2px;
|
||||
@@ -2148,24 +2220,28 @@ import { applyReviewNotifyTemplateVariables } from '@/utils/mailTemplatePreview'
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
margin-left: 8px;
|
||||
border: 1px solid #dcdfe6;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
margin-left: 6px;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
color: #006699;
|
||||
background: transparent;
|
||||
color: #c0c4cc;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s;
|
||||
opacity: 0.55;
|
||||
transition: color 0.2s, background 0.2s, opacity 0.2s;
|
||||
}
|
||||
|
||||
.mail_shuru--to:hover .mail-to-pick-btn,
|
||||
.mail-to-pick-btn:hover {
|
||||
border-color: #006699;
|
||||
background: #f0f7fa;
|
||||
opacity: 1;
|
||||
color: #006699;
|
||||
background: #f5f7fa;
|
||||
}
|
||||
|
||||
.mail-to-pick-btn .el-icon-plus {
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
font-size: 14px;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.article-context-id-input {
|
||||
@@ -2266,31 +2342,6 @@ import { applyReviewNotifyTemplateVariables } from '@/utils/mailTemplatePreview'
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.article-block-head {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
background: #f5f7fa;
|
||||
padding: 10px;
|
||||
margin-bottom: 12px;
|
||||
border-radius: 4px;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.article-block-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.article-block-title {
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.review_table_check {
|
||||
width: 42px;
|
||||
min-width: 42px;
|
||||
@@ -2319,6 +2370,9 @@ import { applyReviewNotifyTemplateVariables } from '@/utils/mailTemplatePreview'
|
||||
border-bottom: 1px solid #ebeef5;
|
||||
text-align: left;
|
||||
font-size: 14px;
|
||||
word-break: break-word;
|
||||
white-space: normal;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.review_table th {
|
||||
@@ -2353,10 +2407,21 @@ import { applyReviewNotifyTemplateVariables } from '@/utils/mailTemplatePreview'
|
||||
}
|
||||
|
||||
.review_table_index {
|
||||
min-width: 90px;
|
||||
width: 44px;
|
||||
min-width: 44px;
|
||||
max-width: 44px;
|
||||
padding-left: 8px;
|
||||
padding-right: 8px;
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.review_table_role {
|
||||
min-width: 220px;
|
||||
white-space: nowrap;
|
||||
word-break: normal;
|
||||
}
|
||||
|
||||
.reviewer-name-cell {
|
||||
min-width: 220px;
|
||||
}
|
||||
@@ -2364,9 +2429,30 @@ import { applyReviewNotifyTemplateVariables } from '@/utils/mailTemplatePreview'
|
||||
.reviewer-name-cell--inline {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
align-items: flex-start;
|
||||
gap: 4px 8px;
|
||||
line-height: 1.4;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.author-name-email-cell {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
gap: 4px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.author-name-email-cell__name {
|
||||
font-weight: 500;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.author-name-email-cell__email {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
gap: 6px;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.reviewer-email-cell--inline {
|
||||
@@ -2709,8 +2795,4 @@ import { applyReviewNotifyTemplateVariables } from '@/utils/mailTemplatePreview'
|
||||
.article-context-dialog .el-dialog__footer {
|
||||
padding: 10px 16px 14px;
|
||||
}
|
||||
|
||||
.article-context-dialog .article-block-title {
|
||||
font-size: 14px;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user