From 7d944cfa3513f40f080fbdf917431287e252a672 Mon Sep 17 00:00:00 2001 From: Victor_Jay Date: Tue, 2 Jun 2026 22:09:41 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E6=9B=B4=E5=90=8D?= =?UTF-8?q?=E9=80=80=E6=AC=BE=E9=80=BB=E8=BE=91=E3=80=81=E5=AE=A1=E6=A0=B8?= =?UTF-8?q?=E5=88=97=E8=A1=A8=E6=98=BE=E7=A4=BA=E5=8F=8A=E6=9B=B4=E5=90=8D?= =?UTF-8?q?=E6=B6=88=E8=80=97=E7=A1=AE=E8=AE=A4=E6=8F=90=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 首次更名审核被拒不再退款,首次免费未扣费不产生退款 - 审核列表提交者列改用 UID,当前用户名列显示当前用户名 - 更名消耗提示改为确认弹窗,首次/非首次动态显示不同文案 --- internal/controller/admin/audit_controller.go | 6 ++--- internal/controller/settings_controller.go | 24 ++++++++++++------- internal/service/audit_review.go | 22 ++++++++++++----- internal/service/audit_service.go | 1 + .../MetaLab-2026/html/settings/index.html | 20 ++++++++++++++-- templates/admin/static/js/audit.js | 10 ++++---- 6 files changed, 59 insertions(+), 24 deletions(-) diff --git a/internal/controller/admin/audit_controller.go b/internal/controller/admin/audit_controller.go index d3bad63..c837258 100644 --- a/internal/controller/admin/audit_controller.go +++ b/internal/controller/admin/audit_controller.go @@ -50,17 +50,17 @@ func (ac *AuditController) ListAudits(c *gin.Context) { return } - // 为每个审核记录附加提交者的用户名 + // 为每个审核记录附加提交者的当前用户名 type auditItem struct { model.AuditSubmission - SubmitterUsername string `json:"submitter_username"` + CurrentUsername string `json:"current_username"` } items := make([]auditItem, 0, len(result.Items)) for _, a := range result.Items { item := auditItem{AuditSubmission: a} if user, err := ac.userRepo.FindByID(a.UserID); err == nil { - item.SubmitterUsername = user.Username + item.CurrentUsername = user.Username } items = append(items, item) } diff --git a/internal/controller/settings_controller.go b/internal/controller/settings_controller.go index 59f78cb..3484906 100644 --- a/internal/controller/settings_controller.go +++ b/internal/controller/settings_controller.go @@ -58,15 +58,23 @@ func (sc *SettingsController) SettingsPage(c *gin.Context) { // 查询待审核类型(用于前端显示审核提示) pendingTypes, _ := sc.auditService.GetPendingTypes(uid) + // 是否已完成首次改名(用于前端确认弹窗显示消耗提示) + hasCompletedRename := false + if sc.levelSvc != nil { + completed, _ := sc.levelSvc.HasCompletedTask(uid, "username") + hasCompletedRename = completed + } + data := gin.H{ - "Title": "个人设置", - "ExtraCSS": "/static/css/settings.css", - "ActiveTab": tab, - "User": user, - "RoleName": model.RoleDisplayNames[user.Role], - "StatusName": model.StatusDisplayNames[user.Status], - "PendingTypes": pendingTypes, - "AuditTypes": model.AuditTypeNames, + "Title": "个人设置", + "ExtraCSS": "/static/css/settings.css", + "ActiveTab": tab, + "User": user, + "RoleName": model.RoleDisplayNames[user.Role], + "StatusName": model.StatusDisplayNames[user.Status], + "PendingTypes": pendingTypes, + "AuditTypes": model.AuditTypeNames, + "HasCompletedRename": hasCompletedRename, } // 登录管理 tab 需要额外数据 diff --git a/internal/service/audit_review.go b/internal/service/audit_review.go index 66bef82..2fe3564 100644 --- a/internal/service/audit_review.go +++ b/internal/service/audit_review.go @@ -45,18 +45,28 @@ func (s *AuditService) review(reviewerID uint, submissionID uint, approved bool, } else { submission.Status = model.AuditStatusRejected submission.RejectReason = &reason - // 通知用户审核被拒(改名审核追加域能返还提示) + + // 改名审核被拒 → 仅非首次改名(已扣费)才退还域能 + // 首次改名免费,被拒不退还 + shouldRefund := false + if submission.AuditType == model.AuditTypeUsername && s.energyRefundSvc != nil { + if s.levelSvc != nil { + hasCompleted, _ := s.levelSvc.HasCompletedTask(submission.UserID, "username") + shouldRefund = hasCompleted + } + if shouldRefund { + _ = s.energyRefundSvc.RefundOnRenameReject(submission.UserID) + } + } + + // 通知用户审核被拒(仅实际退款时追加域能返还提示) if s.notifier != nil { reasonMsg := reason - if submission.AuditType == model.AuditTypeUsername { + if shouldRefund { reasonMsg += "。扣除的域能已被返还" } s.notifier.NotifyAuditRejected(submission.UserID, submission.AuditType, reasonMsg, submission.ID) } - // 改名审核被拒 → 返还域能 - if submission.AuditType == model.AuditTypeUsername && s.energyRefundSvc != nil { - _ = s.energyRefundSvc.RefundOnRenameReject(submission.UserID) - } } return s.auditRepo.Update(submission) } diff --git a/internal/service/audit_service.go b/internal/service/audit_service.go index 7d5e226..c49d4c0 100644 --- a/internal/service/audit_service.go +++ b/internal/service/audit_service.go @@ -40,6 +40,7 @@ type auditNotifier interface { // auditTaskCompleter 审核通过时触发首次任务奖励的接口 type auditTaskCompleter interface { CompleteTask(userID uint, taskType string) (newExp int, levelUp bool, err error) + HasCompletedTask(userID uint, taskType string) (bool, error) } // energyRenameRefunder 改名审核被拒时返还域能的接口(ISP) diff --git a/templates/MetaLab-2026/html/settings/index.html b/templates/MetaLab-2026/html/settings/index.html index c61193a..a366ac9 100644 --- a/templates/MetaLab-2026/html/settings/index.html +++ b/templates/MetaLab-2026/html/settings/index.html @@ -79,7 +79,7 @@
用户名 - +
@@ -375,6 +375,7 @@ // ---- 原始值(用于判断是否变更) ---- var origUsername = usernameInput.value.trim(); var origBio = bioInput.value; + var hasCompletedRename = usernameInput.getAttribute('data-has-completed-rename') === 'true'; // 与后端一致的合法字符集:中文、英文大小写、数字、下划线、连字符 var usernameRe = /^[\u4e00-\u9fffa-zA-Z0-9_-]+$/; @@ -409,6 +410,21 @@ return; } + // 用户名有变更时弹出消耗确认 + if (username !== origUsername) { + var confirmMsg = hasCompletedRename + ? '确认修改用户名?\n\n本次将消耗 6 域能,是否继续?' + : '确认修改用户名?\n\n首次更名无需消耗域能。'; + showConfirm('修改用户名', confirmMsg).then(function(ok) { + if (ok) doSave(username, bio); + }); + return; + } + + doSave(username, bio); + }); + + function doSave(username, bio) { btn.disabled = true; btn.textContent = '保存中...'; @@ -434,7 +450,7 @@ } }; xhr.send(JSON.stringify({ username: username, bio: bio })); - }); + } // ---- 头像裁切上传 ---- var avatarWrap = document.getElementById('avatarWrap'); diff --git a/templates/admin/static/js/audit.js b/templates/admin/static/js/audit.js index 297e2cd..33f6f3c 100644 --- a/templates/admin/static/js/audit.js +++ b/templates/admin/static/js/audit.js @@ -149,8 +149,8 @@ function renderTable(items, bodyId) { function renderUsernameRow(item) { return ` - ${escapeHtml(item.submitter_username || '—')} - — + ${item.user_id || '—'} + ${escapeHtml(item.current_username || '—')} ${escapeHtml(item.new_value)} ${formatTime(item.created_at)} @@ -165,7 +165,7 @@ function renderBioRow(item) { const display = text.length > 40 ? text.substring(0, 40) + '...' : text; return ` - ${escapeHtml(item.submitter_username || '—')} + ${item.user_id || '—'} ${escapeHtml(display)} ${formatTime(item.created_at)} @@ -188,7 +188,7 @@ function renderAvatarCards(items) { grid.innerHTML = items.map(item => `
- 提交者: ${escapeHtml(item.submitter_username || '—')} + 提交者: ${item.user_id || '—'} ${formatTime(item.created_at)}
@@ -224,7 +224,7 @@ function renderHistoryTable(items) { return ` ${typeLabel} - ${escapeHtml(item.submitter_username || '—')} + ${item.user_id || '—'} ${escapeHtml(content)} ${statusLabel} ${escapeHtml(reviewer)}