邮件模版
This commit is contained in:
360
src/components/page/mailboxMouldDetail.vue
Normal file
360
src/components/page/mailboxMouldDetail.vue
Normal file
@@ -0,0 +1,360 @@
|
||||
<template>
|
||||
<div class="detail-container">
|
||||
<header class="action-bar">
|
||||
<div class="left">
|
||||
<el-button type="text" icon="el-icon-back" @click="goBack" class="back-btn">{{ $t('mailboxMouldDetail.back') }}</el-button>
|
||||
<el-divider direction="vertical"></el-divider>
|
||||
<span class="page-title">{{ isEditMode ? $t('mailboxMouldDetail.editTemplate') : $t('mailboxMouldDetail.createTemplate') }}</span>
|
||||
|
||||
</div>
|
||||
<div class="right">
|
||||
<el-button size="mini" @click="goBack">{{ $t('mailboxMouldDetail.cancel') }}</el-button>
|
||||
<el-button type="primary" size="mini" icon="el-icon-document-checked" @click="handleSave">{{ $t('mailboxMouldDetail.save') }}</el-button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main class="editor-layout" v-loading="journalLoading" :element-loading-text="$t('mailboxMouldDetail.loading')">
|
||||
<aside class="config-aside scroll-panel" v-show="!journalLoading">
|
||||
<el-form ref="detailForm" label-position="top" :model="form" :rules="rules" size="mini" class="compact-form">
|
||||
<div class="section-title"><i class="el-icon-setting"></i> {{ $t('mailboxMouldDetail.basicInfo') }}</div>
|
||||
|
||||
<el-form-item prop="title" :label="$t('mailboxMouldDetail.templateTitle')">
|
||||
<el-input v-model="form.title" :placeholder="$t('mailboxMouldDetail.templateTitlePlaceholder')"></el-input>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item prop="journalId" :label="$t('mailboxMouldDetail.journal')">
|
||||
<el-select v-model="form.journalId" filterable style="width: 100%">
|
||||
<el-option v-for="j in journalList" :key="j.journal_id" :label="j.title" :value="String(j.journal_id)" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item prop="scene" :label="$t('mailboxMouldDetail.templateType')">
|
||||
<el-select v-model="form.scene" style="width: 100%">
|
||||
<el-option :label="$t('mailboxMouldDetail.sceneInviteSubmission')" value="invite_submission"></el-option>
|
||||
<el-option :label="$t('mailboxMouldDetail.scenePromoteCitation')" value="promote_citation"></el-option>
|
||||
<el-option :label="$t('mailboxMouldDetail.sceneGeneralThanks')" value="general_thanks"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-row :gutter="8">
|
||||
<el-col :span="14">
|
||||
<el-form-item prop="lang" :label="$t('mailboxMouldDetail.languageConfig')">
|
||||
<el-radio-group v-model="form.lang" class="full-width-radio">
|
||||
<el-radio-button label="en">EN</el-radio-button>
|
||||
<el-radio-button label="zh">ZH</el-radio-button>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="10">
|
||||
<el-form-item prop="version" :label="$t('mailboxMouldDetail.version')">
|
||||
<el-input v-model="form.version" :placeholder="$t('mailboxMouldDetail.versionPlaceholder')"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-divider></el-divider>
|
||||
|
||||
<div class="section-title"><i class="el-icon-cpu"></i> {{ $t('mailboxMouldDetail.variablesJson') }}</div>
|
||||
<el-form-item class="no-m-b">
|
||||
<el-input
|
||||
type="textarea"
|
||||
:rows="6"
|
||||
v-model="form.variables"
|
||||
class="dark-json-input"
|
||||
:placeholder="$t('mailboxMouldDetail.variablesPlaceholder')"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
|
||||
<div class="status-box">
|
||||
<span>{{ $t('mailboxMouldDetail.activeStatus') }}</span>
|
||||
<el-switch v-model="form.is_active" :active-value="1" :inactive-value="0"></el-switch>
|
||||
</div>
|
||||
</el-form>
|
||||
</aside>
|
||||
|
||||
<section class="main-editor" v-show="!journalLoading">
|
||||
<el-card shadow="never" class="editor-card">
|
||||
<div class="subject-input-wrapper">
|
||||
<div class="subject-label">{{ $t('mailboxMouldDetail.emailSubject') }}:</div>
|
||||
<el-input
|
||||
v-model="form.subject"
|
||||
size="small"
|
||||
:placeholder="$t('mailboxMouldDetail.emailSubjectPlaceholder')"
|
||||
class="subject-inner-input"
|
||||
></el-input>
|
||||
</div>
|
||||
|
||||
<div class="body-editor-container">
|
||||
<div class="subject-label" style="margin-bottom: 10px;">{{ $t('mailboxMouldDetail.emailBody') }}:</div>
|
||||
<CkeditorMail v-model="form.body" />
|
||||
</div>
|
||||
</el-card>
|
||||
</section>
|
||||
</main>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import CkeditorMail from '@/components/page/components/email/CkeditorMail.vue';
|
||||
|
||||
const API = {
|
||||
getAllJournal: 'api/Journal/getAllJournal',
|
||||
getTemplate: 'api/mail_template/getTemplate',
|
||||
saveTemplate: 'api/mail_template/saveTemplate'
|
||||
};
|
||||
|
||||
export default {
|
||||
name: 'mailboxMouldDetail',
|
||||
components: { CkeditorMail },
|
||||
data() {
|
||||
return {
|
||||
journalLoading: true,
|
||||
journalList: [],
|
||||
rules: {
|
||||
journalId: [{ required: true, message: this.$t('mailboxMouldDetail.rulesJournal'), trigger: 'change' }],
|
||||
scene: [{ required: true, message: this.$t('mailboxMouldDetail.rulesScene'), trigger: 'change' }],
|
||||
lang: [{ required: true, message: this.$t('mailboxMouldDetail.rulesLanguage'), trigger: 'change' }],
|
||||
title: [{ required: true, message: this.$t('mailboxMouldDetail.rulesTitle'), trigger: 'blur' }],
|
||||
version: [{ required: true, message: this.$t('mailboxMouldDetail.rulesVersion'), trigger: 'blur' }]
|
||||
},
|
||||
form: {
|
||||
journalId: '',
|
||||
scene: 'invite_submission',
|
||||
lang: 'en',
|
||||
version: '1.0.0',
|
||||
title: '',
|
||||
subject: '',
|
||||
body: '',
|
||||
variables: '',
|
||||
is_active: 1
|
||||
}
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
isEditMode() {
|
||||
const q = this.$route && this.$route.query ? this.$route.query : {};
|
||||
return !!(q.template_id || q.id);
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.loadJournals();
|
||||
},
|
||||
methods: {
|
||||
loadJournals() {
|
||||
this.journalLoading = true;
|
||||
this.$api
|
||||
.post(API.getAllJournal, {})
|
||||
.then(res => {
|
||||
const list = (res && res.data && res.data.journals) || res.data || [];
|
||||
const mapped = (Array.isArray(list) ? list : []).map(j => ({
|
||||
journal_id: j.journal_id || j.id,
|
||||
title: j.title || j.name || ''
|
||||
}));
|
||||
this.journalList = mapped;
|
||||
if (!this.form.journalId && mapped.length > 0) {
|
||||
this.form.journalId = String(mapped[0].journal_id);
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
this.journalList = [];
|
||||
})
|
||||
.then(() => {
|
||||
const q = this.$route && this.$route.query ? this.$route.query : {};
|
||||
const templateId = q.template_id || q.id || '';
|
||||
if (templateId) {
|
||||
return this.loadTemplate(String(templateId));
|
||||
}
|
||||
return null;
|
||||
})
|
||||
.finally(() => {
|
||||
this.journalLoading = false;
|
||||
});
|
||||
},
|
||||
loadTemplate(templateId) {
|
||||
return this.$api.post(API.getTemplate, { template_id: String(templateId) }).then(res => {
|
||||
if (!res || res.code !== 0) return;
|
||||
const data = (res && res.data) || {};
|
||||
const t = data.template || data.detail || data || {};
|
||||
if (t.journal_id != null) this.form.journalId = String(t.journal_id);
|
||||
if (t.scene != null) this.form.scene = String(t.scene);
|
||||
if (t.language != null) this.form.lang = String(t.language).toLowerCase();
|
||||
if (t.title != null) this.form.title = String(t.title);
|
||||
if (t.subject != null) this.form.subject = String(t.subject);
|
||||
if (t.variables_json != null) this.form.variables = String(t.variables_json);
|
||||
if (t.version != null) this.form.version = String(t.version);
|
||||
if (t.is_active != null) this.form.is_active = Number(t.is_active) === 1 ? 1 : 0;
|
||||
const bodyHtml = t.body_html != null ? t.body_html : (t.body != null ? t.body : '');
|
||||
this.form.body = String(bodyHtml || '');
|
||||
});
|
||||
},
|
||||
goBack() {
|
||||
this.$router.push({ path: '/mailboxMould' });
|
||||
},
|
||||
handleSave() {
|
||||
const formRef = this.$refs.detailForm;
|
||||
const validatePromise = formRef && formRef.validate ? new Promise(resolve => formRef.validate(ok => resolve(ok))) : Promise.resolve(true);
|
||||
validatePromise.then(ok => {
|
||||
if (!ok) return;
|
||||
if (!this.form.subject) {
|
||||
this.$message.warning(this.$t('mailboxMouldDetail.rulesSubject'));
|
||||
return;
|
||||
}
|
||||
if (!this.form.body) {
|
||||
this.$message.warning(this.$t('mailboxMouldDetail.rulesBody'));
|
||||
return;
|
||||
}
|
||||
|
||||
const q = this.$route.query;
|
||||
const templateId = q.template_id || q.id || '';
|
||||
const bodyHtml = this.form.body || '';
|
||||
const bodyText = bodyHtml.replace(/<[^>]+>/g, ' ').replace(/\s+/g, ' ').trim();
|
||||
const params = {
|
||||
journal_id: String(this.form.journalId || ''),
|
||||
scene: String(this.form.scene || 'invite_submission'),
|
||||
language: String(this.form.lang || 'en'),
|
||||
title: String(this.form.title || ''),
|
||||
subject: String(this.form.subject || ''),
|
||||
body_html: bodyHtml,
|
||||
body_text: bodyText || '',
|
||||
variables_json: String(this.form.variables || ''),
|
||||
version: String(this.form.version || '1.0.0'),
|
||||
is_active: this.form.is_active === 1 ? '1' : '0'
|
||||
};
|
||||
if (templateId) params.template_id = String(templateId);
|
||||
this.$api.post(API.saveTemplate, params).then(res => {
|
||||
if (res && res.code === 0) {
|
||||
this.$message.success(this.$t('mailboxMouldDetail.saveSuccess'));
|
||||
this.goBack();
|
||||
} else {
|
||||
this.$message.error((res && res.msg) || this.$t('mailboxMouldDetail.saveFail'));
|
||||
}
|
||||
}).catch(() => {
|
||||
this.$message.error(this.$t('mailboxMouldDetail.saveFail'));
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* 容器锁定 */
|
||||
.detail-container { height: 100vh; display: flex; flex-direction: column; background: #f0f2f5; overflow: hidden; }
|
||||
|
||||
/* 顶部栏高度压缩 */
|
||||
.action-bar {
|
||||
height: 40px;
|
||||
background: #fff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0 15px;
|
||||
border-bottom: 1px solid #dcdfe6;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.action-bar .left { display: flex; align-items: center; min-width: 0; }
|
||||
.page-title { font-size: 13px; font-weight: bold; color: #333; }
|
||||
.page-subject {
|
||||
margin-left: 10px;
|
||||
font-size: 12px;
|
||||
color: #666;
|
||||
max-width: 520px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.editor-layout { flex: 1; display: flex; overflow: hidden; background: #f0f2f5; }
|
||||
|
||||
/* 左侧边栏 - 占比 2 (约 20%-25%) */
|
||||
.config-aside {
|
||||
width: 280px;
|
||||
background: #fff;
|
||||
border-right: 1px solid #dcdfe6;
|
||||
padding: 15px;
|
||||
flex-shrink: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.section-title { font-size: 12px; font-weight: bold; color: #409EFF; margin-bottom: 12px; display: flex; align-items: center; gap: 5px; }
|
||||
.el-divider--horizontal { margin: 15px 0; }
|
||||
|
||||
/* 右侧编辑区 - 占比 8 */
|
||||
.main-editor {
|
||||
flex: 1;
|
||||
padding: 12px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.editor-card {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border: none;
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,0.05);
|
||||
}
|
||||
.editor-card /deep/ .el-card__body {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 0 !important;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* 邮件主题行优化 */
|
||||
.subject-input-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 10px 15px;
|
||||
background: #fafafa;
|
||||
border-bottom: 1px solid #eee;
|
||||
gap: 10px;
|
||||
}
|
||||
.subject-label { font-size: 12px; font-weight: bold; color: #666; white-space: nowrap; }
|
||||
.subject-inner-input{
|
||||
border: 1px solid #dcdfe6;
|
||||
border-radius: 4px;
|
||||
|
||||
}
|
||||
.subject-inner-input /deep/ .el-input__inner { border: transparent; background: transparent; font-weight: 500; font-size: 14px; }
|
||||
.subject-inner-input /deep/ .el-input__inner:focus { background: #fff; border-color: #dcdfe6; }
|
||||
|
||||
/* 编辑器容器撑满 */
|
||||
.body-editor-container { flex: 1; overflow: hidden; padding: 10px 15px; }
|
||||
.body-editor-container /deep/ .ck-editor { height: 100%; display: flex; flex-direction: column; }
|
||||
.body-editor-container /deep/ .ck-editor__main { flex: 1; overflow: auto; }
|
||||
|
||||
/* 状态切换栏 */
|
||||
.status-box {
|
||||
margin-top: auto;
|
||||
padding-top: 15px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
font-size: 12px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
/* 黑色背景 JSON 输入框 */
|
||||
.dark-json-input /deep/ .el-textarea__inner {
|
||||
background: #1e1e1e;
|
||||
color: #9cdcfe;
|
||||
font-family: 'Consolas', 'Monaco', monospace;
|
||||
font-size: 12px;
|
||||
line-height: 1.5;
|
||||
border: 1px solid #333;
|
||||
}
|
||||
|
||||
/* 滚动条 */
|
||||
.scroll-panel { overflow-y: auto; }
|
||||
.scroll-panel::-webkit-scrollbar { width: 4px; }
|
||||
.scroll-panel::-webkit-scrollbar-thumb { background: #ccc; border-radius: 2px; }
|
||||
|
||||
/* 表单紧凑微调 */
|
||||
.detail-container /deep/ .el-form-item--mini.el-form-item { margin-bottom: 12px; }
|
||||
.detail-container /deep/ .el-form--label-top .el-form-item__label { padding: 0 0 4px; font-size: 12px; color: #999; }
|
||||
</style>
|
||||
Reference in New Issue
Block a user