新增 OIDC/SSO、邮件验证码与 Gitea 项目同步,并强化 Feed 与管理后台。
作为 OIDC Provider 对接 Gitea;注册支持邮件验证码/验证码;侧栏同步公开仓库;Feed 分页、文章大纲、标签云与站点品牌设置。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -53,7 +53,9 @@ func IsSPARoute(path string) bool {
|
||||
strings.HasPrefix(path, "/admin") ||
|
||||
strings.HasPrefix(path, "/uploads") ||
|
||||
strings.HasPrefix(path, "/legacy") ||
|
||||
strings.HasPrefix(path, "/assets") {
|
||||
strings.HasPrefix(path, "/assets") ||
|
||||
strings.HasPrefix(path, "/oauth") ||
|
||||
strings.HasPrefix(path, "/.well-known") {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
|
||||
@@ -36,13 +36,6 @@
|
||||
<div class="label">评论总数</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="admin-stat-card admin-stat-online">
|
||||
<div class="admin-stat-icon">线</div>
|
||||
<div class="admin-stat-info">
|
||||
<div class="value">{{.OnlineCount}}</div>
|
||||
<div class="label">当前浏览</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="admin-card">
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
<div class="table-responsive">
|
||||
<table class="table admin-table mb-0">
|
||||
<thead>
|
||||
<tr><th>ID</th><th>用户名</th><th>昵称</th><th>角色</th><th>状态</th><th>注册时间</th><th width="120">操作</th></tr>
|
||||
<tr><th>ID</th><th>用户名</th><th>昵称</th><th>邮箱</th><th>角色</th><th>状态</th><th>上次登录</th><th>登录 IP</th><th>注册时间</th><th width="120">操作</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{range .Users}}
|
||||
@@ -19,6 +19,7 @@
|
||||
<td>{{.ID}}</td>
|
||||
<td>{{.Username}}</td>
|
||||
<td>{{.Nickname}}</td>
|
||||
<td>{{if .Email}}{{.Email}}{{else}}—{{end}}</td>
|
||||
<td>
|
||||
{{if eq .Role "admin"}}
|
||||
<span class="badge badge-admin">管理员</span>
|
||||
@@ -27,6 +28,8 @@
|
||||
<td>
|
||||
{{if .Banned}}<span class="badge badge-banned">已禁言</span>{{else}}<span class="text-success">正常</span>{{end}}
|
||||
</td>
|
||||
<td>{{if .LastLoginAt}}{{.LastLoginAt.Format "2006-01-02 15:04"}}{{else}}—{{end}}</td>
|
||||
<td>{{if .LastLoginIP}}{{.LastLoginIP}}{{else}}—{{end}}</td>
|
||||
<td>{{.CreatedAt.Format "2006-01-02"}}</td>
|
||||
<td>
|
||||
{{if eq .Role "admin"}}
|
||||
@@ -39,7 +42,7 @@
|
||||
</td>
|
||||
</tr>
|
||||
{{else}}
|
||||
<tr><td colspan="7" class="admin-empty">暂无用户</td></tr>
|
||||
<tr><td colspan="10" class="admin-empty">暂无用户</td></tr>
|
||||
{{end}}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
<img src="{{if .ProfileUser.Avatar}}{{.ProfileUser.Avatar}}{{else}}https://via.placeholder.com/128{{end}}" class="avatar-md mb-2" alt="avatar">
|
||||
<h4>{{.ProfileUser.Nickname}}</h4>
|
||||
<p class="text-muted">@{{.ProfileUser.Username}}</p>
|
||||
<p class="text-muted small">{{if .ProfileUser.Email}}{{.ProfileUser.Email}}{{else}}未设置邮箱{{end}}</p>
|
||||
<form id="avatarForm" enctype="multipart/form-data">
|
||||
<input type="file" name="avatar" accept="image/*" class="form-control form-control-sm mb-2">
|
||||
<button type="submit" class="btn btn-outline-primary btn-sm">更换头像</button>
|
||||
|
||||
@@ -5,20 +5,31 @@
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-body p-4">
|
||||
<h3 class="text-center mb-4">注册账号</h3>
|
||||
<p class="text-center text-muted small mb-3">本站首个注册用户将自动成为管理员</p>
|
||||
<p id="regTip" class="text-center text-muted small mb-3"></p>
|
||||
<form id="regForm">
|
||||
<div class="mb-3">
|
||||
<label class="form-label">用户名(3-32位字母数字下划线)</label>
|
||||
<label class="form-label">用户名(2-32位,支持中文)</label>
|
||||
<input type="text" name="username" class="form-control" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label">昵称</label>
|
||||
<input type="text" name="nickname" class="form-control">
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label">邮箱</label>
|
||||
<input type="email" name="email" class="form-control" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label">密码(至少6位)</label>
|
||||
<input type="password" name="password" class="form-control" required>
|
||||
</div>
|
||||
<div class="mb-3" id="emailCodeWrap" hidden>
|
||||
<label class="form-label">邮箱验证码</label>
|
||||
<div class="d-flex gap-2">
|
||||
<input type="text" name="email_code" class="form-control" autocomplete="one-time-code">
|
||||
<button type="button" class="btn btn-outline-secondary text-nowrap" id="sendCodeBtn">发送验证码</button>
|
||||
</div>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-success w-100">注册</button>
|
||||
</form>
|
||||
<p class="text-center mt-3 mb-0">已有账号?<a href="/login">去登录</a></p>
|
||||
@@ -29,6 +40,26 @@
|
||||
{{end}}
|
||||
{{define "scripts"}}
|
||||
<script>
|
||||
var regCfg = { require_email_code: false, register_open: true, is_first_user: false };
|
||||
fetch('/api/register/config').then(r=>r.json()).then(d=>{
|
||||
regCfg = d;
|
||||
var tip = document.getElementById('regTip');
|
||||
if (d.is_first_user) tip.textContent = '本站首个注册用户将自动成为管理员';
|
||||
else if (!d.register_open) tip.textContent = '注册暂未开放,请等待管理员配置邮件服务';
|
||||
document.getElementById('emailCodeWrap').hidden = !d.require_email_code;
|
||||
if (!d.register_open) document.getElementById('regForm').hidden = true;
|
||||
});
|
||||
document.getElementById('sendCodeBtn').addEventListener('click', function(){
|
||||
var email = document.querySelector('[name=email]').value;
|
||||
fetch('/api/register/email-code', {
|
||||
method:'POST',
|
||||
headers:{'Content-Type':'application/json'},
|
||||
body: JSON.stringify({email: email})
|
||||
}).then(r=>r.json()).then(d=>{
|
||||
if(d.error){ showToast(d.error,'danger'); return; }
|
||||
showToast(d.message || '已发送');
|
||||
});
|
||||
});
|
||||
document.getElementById('regForm').addEventListener('submit', function(e){
|
||||
e.preventDefault();
|
||||
apiPost('/api/register', this, true).then(d=>{
|
||||
|
||||
Reference in New Issue
Block a user