- 新增 internal/i18n 包:以原始中文字符串为 key 的翻译目录(zh 恒等, en 兜底,ja 缺译回退 en),t/tf 模板函数与 Accept-Language 解析 (按 q 值排序,兜底英语) - User 模型新增 language 字段(auto|en|zh|ja,默认 auto), AutoMigrate 自动加列;UserStore 新增 UpdateLanguage - 语言解析:登录用户按偏好(auto 时取浏览器 Accept-Language), 登录/封禁页按浏览器语言;所有 c.HTML 渲染注入 Lang 模板数据 - 全部页面模板(用户页 + 管理后台 12 页)接入翻译:导航、文件夹、 邮件列表/阅读/写信、设置、登录、封禁页、表单、表格、JS 确认框等; html lang 属性随语言切换;日期函数(shortDate/time12/time12m) 与 folderLabel 改为语言感知(上午/下午 vs AM/PM vs 午前/午後) - 设置页新增「界面语言」选择(自动/English/中文/日本語), /settings 表单支持单独提交语言偏好;管理后台用户表单可预设语言 - 封禁原因等入库中文文案在展示时经 t 翻译(未知 key 原样回退) - 测试:i18n 单测(解析/回退/译文)、render 测试补 Lang 数据、 时间格式化测试适配新签名;全量 go test 通过
78 lines
3.6 KiB
HTML
78 lines
3.6 KiB
HTML
{{define "banned"}}
|
|
<!DOCTYPE html>
|
|
<html lang="{{htmlLang .Lang}}">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
|
|
<title>{{t .Lang "访问被禁止"}} - MailGo</title>
|
|
<style>
|
|
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
body {
|
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC",
|
|
"Hiragino Sans GB", "Microsoft YaHei", sans-serif;
|
|
background: linear-gradient(165deg, #fdecec 0%, #f6f8fc 55%, #eaf2ff 100%);
|
|
color: #1f2329; display: flex; justify-content: center; align-items: center; min-height: 100vh;
|
|
}
|
|
.banned-card {
|
|
background: #fff; border-radius: 14px;
|
|
box-shadow: 0 10px 40px rgba(227, 77, 89, 0.10);
|
|
padding: 48px; text-align: center; max-width: 480px; width: 100%;
|
|
}
|
|
.banned-icon {
|
|
width: 72px; height: 72px; margin: 0 auto 18px; border-radius: 50%;
|
|
background: #fde8e8; display: flex; align-items: center; justify-content: center;
|
|
font-size: 34px;
|
|
}
|
|
h1 { font-size: 22px; color: #e34d59; margin-bottom: 12px; }
|
|
p { color: #646a73; line-height: 1.7; margin-bottom: 8px; font-size: 14px; }
|
|
.detail {
|
|
background: #f8f9fb; border-radius: 10px; padding: 16px 18px;
|
|
margin: 18px 0; text-align: left;
|
|
}
|
|
.detail-row { display: flex; justify-content: space-between; padding: 7px 0; border-bottom: 1px solid #f0f1f3; }
|
|
.detail-row:last-child { border-bottom: none; }
|
|
.detail-label { color: #8f959e; font-size: 13px; }
|
|
.detail-value { color: #1f2329; font-weight: 600; font-size: 13px; }
|
|
.back-link {
|
|
display: inline-block; margin-top: 22px; color: #1677ff;
|
|
text-decoration: none; font-size: 14px;
|
|
}
|
|
.back-link:hover { text-decoration: underline; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="banned-card">
|
|
<div class="banned-icon">🚫</div>
|
|
<h1>{{t .Lang "您的 IP 已被暂时禁止访问"}}</h1>
|
|
<p>{{t .Lang "由于登录失败次数过多,您的 IP 地址已被暂时封禁。"}}</p>
|
|
{{if .entry}}
|
|
<div class="detail">
|
|
<div class="detail-row">
|
|
<span class="detail-label">{{t .Lang "IP 地址"}}</span>
|
|
<span class="detail-value">{{.entry.IPAddress}}</span>
|
|
</div>
|
|
<div class="detail-row">
|
|
<span class="detail-label">{{t .Lang "封禁档位"}}</span>
|
|
<span class="detail-value">{{if gt .entry.BanCount 3}}{{tf .Lang "第 %d 次封禁" (sub .entry.BanCount 3)}}{{else}}—{{end}}</span>
|
|
</div>
|
|
<div class="detail-row">
|
|
<span class="detail-label">{{t .Lang "原因"}}</span>
|
|
<span class="detail-value">{{t .Lang .entry.Reason}}</span>
|
|
</div>
|
|
<div class="detail-row">
|
|
<span class="detail-label">{{t .Lang "失败次数"}}</span>
|
|
<span class="detail-value">{{tf .Lang "%d 次" .entry.FailCount}}</span>
|
|
</div>
|
|
<div class="detail-row">
|
|
<span class="detail-label">{{t .Lang "解封时间"}}</span>
|
|
<span class="detail-value">{{time12 .Lang .entry.ExpiresAt}}</span>
|
|
</div>
|
|
</div>
|
|
{{end}}
|
|
<p style="font-size:13px;">{{t .Lang "请在解封时间后重试,或联系管理员。"}}</p>
|
|
<a href="/login" class="back-link">{{t .Lang "返回登录页"}}</a>
|
|
</div>
|
|
</body>
|
|
</html>
|
|
{{end}}
|