提交
This commit is contained in:
@@ -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'
|
||||
|
||||
//测试环境
|
||||
|
||||
|
||||
@@ -657,6 +657,15 @@ colTitle: 'Template title',
|
||||
printBtn: 'Print',
|
||||
previewNotSupported: 'This file format cannot be previewed online',
|
||||
downloadToView: 'Download to view locally',
|
||||
registerAuthorBtn: 'Create author account',
|
||||
registerAuthorConfirm:
|
||||
'Create an account via the same admin API as User Management: login name "{account}", display name "{realname}", email "{email}", initial password 123456qwe (no captcha). Continue?',
|
||||
registerAuthorSuccess: 'Author account created.',
|
||||
registerAuthorFail: 'Creation failed. Try again later or add the user manually in User Management.',
|
||||
registerAuthorExistsEmail: 'This email is already registered.',
|
||||
registerAuthorExistsAccount: 'This login name is already taken. Edit the sender display name or add the user manually.',
|
||||
registerAuthorNeedEmail: 'Sender email is missing; cannot create an account.',
|
||||
registerAuthorNoQq: 'QQ Mail is not supported for author accounts. Please add the user manually.',
|
||||
},
|
||||
crawlerKeywords: {
|
||||
pageTitle: 'Keyword Configuration',
|
||||
|
||||
@@ -646,6 +646,15 @@ const zh = {
|
||||
printBtn: '打印',
|
||||
previewNotSupported: '该文件格式无法在线预览',
|
||||
downloadToView: '下载到本地查看',
|
||||
registerAuthorBtn: '创建作者账号',
|
||||
registerAuthorConfirm:
|
||||
'将使用推广后台「添加用户」接口创建账号:登录名「{account}」,显示名「{realname}」,邮箱「{email}」,初始密码 123456qwe(无需验证码)。是否继续?',
|
||||
registerAuthorSuccess: '作者账号已创建。',
|
||||
registerAuthorFail: '创建失败,请稍后重试或到用户管理中手动添加。',
|
||||
registerAuthorExistsEmail: '该邮箱已被注册。',
|
||||
registerAuthorExistsAccount: '该登录名已被占用,请人工处理或修改发件人显示名后重试。',
|
||||
registerAuthorNeedEmail: '缺少发件人邮箱,无法创建账号。',
|
||||
registerAuthorNoQq: '本站不支持 QQ 邮箱作为作者账号,请在用户管理中手动添加。',
|
||||
},
|
||||
crawlerKeywords: {
|
||||
pageTitle: '关键词配置',
|
||||
|
||||
@@ -5,6 +5,18 @@
|
||||
<h1 class="mail-subject-top">{{ $t('mailboxCollect.subject') }}:{{ mailData.subject }}</h1>
|
||||
</div>
|
||||
<div class="toolbar-right">
|
||||
<el-button
|
||||
v-if="hasWordAttachment"
|
||||
type="primary"
|
||||
size="small"
|
||||
plain
|
||||
icon="el-icon-user-solid"
|
||||
:loading="registerAuthorLoading"
|
||||
class="register-author-btn"
|
||||
@click="registerAuthorFromMail"
|
||||
>
|
||||
{{ $t('mailboxCollect.registerAuthorBtn') }}
|
||||
</el-button>
|
||||
<!-- <i class="el-icon-star-off action-icon"></i> -->
|
||||
<i class="el-icon-close action-icon" @click="$emit('close')"></i>
|
||||
</div>
|
||||
@@ -70,6 +82,18 @@
|
||||
<el-link type="primary" :underline="false" @click="scrollToAttachments" class="jump-link">
|
||||
{{ $t('mailboxCollect.viewAttachments') }}
|
||||
</el-link>
|
||||
<el-button
|
||||
v-if="hasWordAttachment"
|
||||
type="primary"
|
||||
size="mini"
|
||||
plain
|
||||
icon="el-icon-user-solid"
|
||||
:loading="registerAuthorLoading"
|
||||
class="register-author-btn-inline"
|
||||
@click="registerAuthorFromMail"
|
||||
>
|
||||
{{ $t('mailboxCollect.registerAuthorBtn') }}
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -152,10 +176,20 @@ export default {
|
||||
mediaUrl: Common.mediaUrl,
|
||||
isDetailExpanded: false,
|
||||
downloadingIndex: -1,
|
||||
packingAll: false
|
||||
packingAll: false,
|
||||
registerAuthorLoading: false
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
/** 存在 Word 附件(.doc / .docx)时显示「创建作者账号」 */
|
||||
hasWordAttachment() {
|
||||
const att = (this.mailData && this.mailData.attachments) || [];
|
||||
if (!att.length) return false;
|
||||
return att.some((f) => {
|
||||
const n = (f && f.name) || '';
|
||||
return /\.(doc|docx)$/i.test(n);
|
||||
});
|
||||
},
|
||||
totalAttachmentSize() {
|
||||
if (!this.mailData.attachments || !this.mailData.attachments.length) return '0B';
|
||||
const total = this.mailData.attachments.reduce((sum, f) => sum + (Number(f.size) || 0), 0);
|
||||
@@ -175,6 +209,127 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
stripHtml(html) {
|
||||
if (html == null || html === '') return '';
|
||||
const s = String(html);
|
||||
const d = typeof document !== 'undefined' ? document.createElement('div') : null;
|
||||
if (d) {
|
||||
d.innerHTML = s;
|
||||
return (d.textContent || d.innerText || '').trim();
|
||||
}
|
||||
return s.replace(/<[^>]+>/g, ' ').replace(/\s+/g, ' ').trim();
|
||||
},
|
||||
/** 与 partyList 添加用户一致:从正文尝试提取手机号(国内 11 位或含 + 的国际号) */
|
||||
extractPhoneFromMailBody() {
|
||||
const m = this.mailData || {};
|
||||
let blob = '';
|
||||
['content_text', 'content', 'body', 'content_html', 'html', 'body_html'].forEach((k) => {
|
||||
const v = m[k];
|
||||
if (v != null && String(v).trim() !== '') blob += `\n${String(v)}`;
|
||||
});
|
||||
const text = this.stripHtml(blob);
|
||||
const cn = text.match(/(?:^|\D)(1[3-9]\d{9})(?:\D|$)/);
|
||||
if (cn) return cn[1];
|
||||
const intl = text.match(/\+\d{1,3}[\s\-]?\d[\d\s\-]{8,18}\d/);
|
||||
if (intl) return intl[0].replace(/\s+/g, ' ').trim().slice(0, 32);
|
||||
const labeled = text.match(/(?:Tel|Phone|Mobile|MW)[\s::]*([+()\d][\d\s\-().]{10,40})/i);
|
||||
if (labeled) return labeled[1].trim().slice(0, 32);
|
||||
return '';
|
||||
},
|
||||
buildAuthorRegisterPayload() {
|
||||
const m = this.mailData || {};
|
||||
const email = String(m.from_email || '')
|
||||
.trim()
|
||||
.toLowerCase();
|
||||
const localPart = email.split('@')[0] || 'user';
|
||||
let rawName = String(m.from_name || '').trim();
|
||||
let realname = rawName || localPart;
|
||||
if (this.$validateString && !this.$validateString(realname)) {
|
||||
realname = localPart;
|
||||
if (this.$validateString && !this.$validateString(realname)) {
|
||||
realname = 'Author';
|
||||
}
|
||||
}
|
||||
let account = rawName.replace(/[^a-zA-Z0-9_-]/g, '');
|
||||
if (!account || account.length < 2) {
|
||||
account = localPart.replace(/[^a-zA-Z0-9_-]/g, '');
|
||||
}
|
||||
if (!account || account.length < 2) {
|
||||
account = `u${email.replace(/[^a-zA-Z0-9]/g, '').slice(0, 12) || 'ser'}`;
|
||||
}
|
||||
const phone = this.extractPhoneFromMailBody() || '';
|
||||
return { email, account, realname, phone };
|
||||
},
|
||||
async registerAuthorFromMail() {
|
||||
if (!this.hasWordAttachment) return;
|
||||
const { email, account, realname, phone } = this.buildAuthorRegisterPayload();
|
||||
if (!email) {
|
||||
this.$message.warning(this.$t('mailboxCollect.registerAuthorNeedEmail'));
|
||||
return;
|
||||
}
|
||||
if (email.endsWith('@qq.com')) {
|
||||
this.$message.warning(this.$t('mailboxCollect.registerAuthorNoQq'));
|
||||
return;
|
||||
}
|
||||
const pwd = '123456qwe';
|
||||
try {
|
||||
await this.$confirm(
|
||||
this.$t('mailboxCollect.registerAuthorConfirm', { email, account, realname }),
|
||||
this.$t('mailboxCollect.registerAuthorBtn'),
|
||||
{ type: 'warning', distinguishCancelAndClose: true }
|
||||
);
|
||||
} catch (e) {
|
||||
return;
|
||||
}
|
||||
this.registerAuthorLoading = true;
|
||||
try {
|
||||
const p = this.buildAuthorRegisterPayload();
|
||||
const email2 = p.email;
|
||||
const account2 = p.account;
|
||||
const realname2 = p.realname;
|
||||
const phone2 = p.phone;
|
||||
const ef = { email: email2, account: account2 };
|
||||
const r1 = await this.$api.post('api/User/checkUserByEmail', ef);
|
||||
if (!r1 || Number(r1.code) !== 0) {
|
||||
this.$message.error((r1 && r1.msg) || this.$t('mailboxCollect.registerAuthorFail'));
|
||||
return;
|
||||
}
|
||||
const r2 = await this.$api.post('api/User/checkUserByAccount', ef);
|
||||
if (!r2 || Number(r2.code) !== 0) {
|
||||
this.$message.error((r2 && r2.msg) || this.$t('mailboxCollect.registerAuthorFail'));
|
||||
return;
|
||||
}
|
||||
const hasEmail = r1.data && Number(r1.data.has) === 1;
|
||||
const hasAccount = r2.data && Number(r2.data.has) === 1;
|
||||
if (hasEmail) {
|
||||
this.$message.warning(this.$t('mailboxCollect.registerAuthorExistsEmail'));
|
||||
return;
|
||||
}
|
||||
if (hasAccount) {
|
||||
this.$message.warning(this.$t('mailboxCollect.registerAuthorExistsAccount'));
|
||||
return;
|
||||
}
|
||||
const addForm = {
|
||||
email: email2,
|
||||
account: account2,
|
||||
password: pwd,
|
||||
repassword: pwd,
|
||||
realname: realname2,
|
||||
phone: phone2 || ''
|
||||
};
|
||||
const res = await this.$api.post('api/User/addUser', addForm);
|
||||
if (res && Number(res.code) === 0) {
|
||||
this.$message.success(this.$t('mailboxCollect.registerAuthorSuccess'));
|
||||
} else {
|
||||
this.$message.error((res && res.msg) || this.$t('mailboxCollect.registerAuthorFail'));
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
this.$message.error(this.$t('mailboxCollect.registerAuthorFail'));
|
||||
} finally {
|
||||
this.registerAuthorLoading = false;
|
||||
}
|
||||
},
|
||||
escapeHtml(text) {
|
||||
if (text == null) return '';
|
||||
return String(text)
|
||||
@@ -383,6 +538,19 @@ const res = await this.$api.post('api/email_client/getAttachment', {
|
||||
color: #606266;
|
||||
cursor: pointer;
|
||||
}
|
||||
.toolbar-right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.register-author-btn {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.register-author-btn-inline {
|
||||
margin-left: 10px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.action-icon:hover {
|
||||
color: #409eff;
|
||||
}
|
||||
@@ -665,7 +833,9 @@ const res = await this.$api.post('api/email_client/getAttachment', {
|
||||
}
|
||||
.attachment-brief-bar {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
gap: 8px 12px;
|
||||
padding: 8px 0;
|
||||
font-size: 13px;
|
||||
color: #606266;
|
||||
@@ -681,7 +851,7 @@ const res = await this.$api.post('api/email_client/getAttachment', {
|
||||
margin-left: 4px;
|
||||
}
|
||||
.jump-link {
|
||||
margin-left: 15px;
|
||||
margin-left: 0;
|
||||
font-size: 13px;
|
||||
}
|
||||
.attachment-section {
|
||||
|
||||
Reference in New Issue
Block a user