|
|
@@ -2,8 +2,18 @@
|
|
|
|
|
|
const BRAND = 'RunForge'
|
|
|
|
|
|
-/** 所有经 renderEmail 输出的邮件页脚均附带此说明 */
|
|
|
-const AUTO_REPLY_NOTICE = '本邮件由系统自动发送,请勿直接回复'
|
|
|
+/** 页脚固定说明(分段展示,避免单行过长) */
|
|
|
+const FOOTER_DISCLAIMER = {
|
|
|
+ label: '本邮件由系统自动发送,请勿直接回复本邮件。',
|
|
|
+ helpPrefix: '如需帮助,请访问 RunForge 网站提交工单,或发送邮件至',
|
|
|
+ helpEmail: 'service@xxoo365.top'
|
|
|
+}
|
|
|
+
|
|
|
+/** 合并后的纯文本说明(供外部引用) */
|
|
|
+const AUTO_REPLY_NOTICE = [
|
|
|
+ FOOTER_DISCLAIMER.label,
|
|
|
+ `${FOOTER_DISCLAIMER.helpPrefix} ${FOOTER_DISCLAIMER.helpEmail}`
|
|
|
+].join(' ')
|
|
|
|
|
|
/**
|
|
|
* Escape text for safe insertion into HTML email bodies.
|
|
|
@@ -36,6 +46,24 @@ const ACCENTS = {
|
|
|
danger: '#b91c1c'
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * 页脚:可选补充说明 + 固定分段提示(左对齐,避免长句居中拥挤)
|
|
|
+ * @param {string} footerExtra
|
|
|
+ */
|
|
|
+function buildFooterHtml(footerExtra) {
|
|
|
+ const ctx = footerExtra
|
|
|
+ ? `<div class="footer-context">${escapeHtml(footerExtra)}</div>`
|
|
|
+ : ''
|
|
|
+
|
|
|
+ const mail = escapeHtml(FOOTER_DISCLAIMER.helpEmail)
|
|
|
+
|
|
|
+ return `${ctx}
|
|
|
+ <span class="footer-meta-label">${escapeHtml(FOOTER_DISCLAIMER.label)}</span>
|
|
|
+ <ul class="footer-meta">
|
|
|
+ <li>${escapeHtml(FOOTER_DISCLAIMER.helpPrefix)} <a href="mailto:${mail}">${mail}</a></li>
|
|
|
+ </ul>`
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* Wrap transactional email body in shared layout (single stylesheet + structure).
|
|
|
* @param {object} opts
|
|
|
@@ -59,11 +87,7 @@ function renderEmail(opts) {
|
|
|
const accent = ACCENTS[variant] || ACCENTS.default
|
|
|
const year = new Date().getFullYear()
|
|
|
|
|
|
- const footerNote = footerExtra
|
|
|
- ? `<p class="fineprint">${escapeHtml(footerExtra)}</p>`
|
|
|
- : ''
|
|
|
-
|
|
|
- const autoReplyLine = `<p class="fineprint">${escapeHtml(AUTO_REPLY_NOTICE)}</p>`
|
|
|
+ const footerHtml = buildFooterHtml(footerExtra)
|
|
|
|
|
|
return `<!DOCTYPE html>
|
|
|
<html lang="zh-CN">
|
|
|
@@ -126,14 +150,58 @@ function renderEmail(opts) {
|
|
|
font-family:Consolas,'Courier New',monospace;
|
|
|
}
|
|
|
.footer {
|
|
|
- padding:16px 28px 22px;
|
|
|
- border-top:1px solid #f1f5f9;
|
|
|
- text-align:center;
|
|
|
+ padding:0;
|
|
|
+ border-top:1px solid #e2e8f0;
|
|
|
+ background:#f8fafc;
|
|
|
+ }
|
|
|
+ .footer-inner {
|
|
|
+ max-width:504px;
|
|
|
+ margin:0 auto;
|
|
|
+ padding:18px 28px 20px;
|
|
|
+ text-align:left;
|
|
|
+ }
|
|
|
+ .footer-context {
|
|
|
+ margin:0 0 14px;
|
|
|
+ padding:10px 12px;
|
|
|
+ font-size:13px;
|
|
|
+ line-height:1.55;
|
|
|
+ color:#475569;
|
|
|
+ background:#ffffff;
|
|
|
+ border:1px solid #e2e8f0;
|
|
|
+ border-radius:6px;
|
|
|
+ }
|
|
|
+ .footer-meta {
|
|
|
+ margin:0;
|
|
|
+ padding:0;
|
|
|
+ list-style:none;
|
|
|
font-size:12px;
|
|
|
- line-height:1.5;
|
|
|
+ line-height:1.65;
|
|
|
+ color:#64748b;
|
|
|
+ }
|
|
|
+ .footer-meta li { margin:0; padding:0; }
|
|
|
+ .footer-meta li + li { margin-top:8px; }
|
|
|
+ .footer-meta-label {
|
|
|
+ display:block;
|
|
|
+ font-size:11px;
|
|
|
+ font-weight:600;
|
|
|
+ letter-spacing:0.04em;
|
|
|
+ color:#94a3b8;
|
|
|
+ margin-bottom:8px;
|
|
|
+ }
|
|
|
+ .footer-meta a {
|
|
|
+ color:#1e40af;
|
|
|
+ text-decoration:none;
|
|
|
+ word-break:break-all;
|
|
|
+ }
|
|
|
+ .footer-copyright {
|
|
|
+ margin:14px 0 0;
|
|
|
+ padding-top:14px;
|
|
|
+ border-top:1px solid #e2e8f0;
|
|
|
+ text-align:center;
|
|
|
+ font-size:11px;
|
|
|
+ line-height:1.4;
|
|
|
color:#94a3b8;
|
|
|
}
|
|
|
- .fineprint { margin:0 0 8px; font-size:12px; color:#64748b; }
|
|
|
.tag {
|
|
|
display:inline-block;
|
|
|
margin-left:10px;
|
|
|
@@ -157,9 +225,10 @@ function renderEmail(opts) {
|
|
|
${bodyHtml}
|
|
|
</div>
|
|
|
<div class="footer">
|
|
|
- ${footerNote}
|
|
|
- ${autoReplyLine}
|
|
|
- <p style="margin:0;">© ${year} ${escapeHtml(BRAND)}</p>
|
|
|
+ <div class="footer-inner">
|
|
|
+ ${footerHtml}
|
|
|
+ <p class="footer-copyright">© ${year} ${escapeHtml(BRAND)}</p>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|