From 79669376aa127335c84c283a6b3ceaf4e14807ec Mon Sep 17 00:00:00 2001 From: skyle1995 Date: Thu, 19 Mar 2026 05:11:44 +0800 Subject: [PATCH] Fix a large number of bugs --- cmd/root.go | 10 +- config/config.go | 24 +- controllers/admin/app.go | 29 + .../admin/{handlers.go => dashboard.go} | 16 +- controllers/admin/function.go | 58 ++ controllers/admin/login_log.go | 3 - controllers/admin/operation_log.go | 8 - controllers/admin/profile.go | 36 +- controllers/admin/variable.go | 58 ++ database/database.go | 9 +- models/operation_log.go | 15 +- services/operation_log.go | 5 +- utils/database.go | 31 +- web/template/admin/operation_logs.html | 10 - web/template/admin/profile.html | 547 +++++++++++------- 15 files changed, 570 insertions(+), 289 deletions(-) rename controllers/admin/{handlers.go => dashboard.go} (93%) diff --git a/cmd/root.go b/cmd/root.go index 2f49fe8..2923677 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -75,8 +75,14 @@ func setupLogrusForNonHTTP() { // 初始化HTTP日志处理器 logger.InitLogger() - // 记录配置加载完成 - logrus.WithField("file", viper.ConfigFileUsed()).Info("配置文件加载完成") + // 记录配置加载完成,使用相对路径或文件名保持一致性 + configFile := viper.ConfigFileUsed() + if configFile != "" { + fileName := filepath.Base(configFile) + logrus.WithField("file", fileName).Info("配置文件加载完成") + } else { + logrus.Info("配置加载完成(内存默认配置)") + } } // initConfig 读取配置文件和环境变量 diff --git a/config/config.go b/config/config.go index c7f6065..511fc7a 100644 --- a/config/config.go +++ b/config/config.go @@ -170,20 +170,18 @@ func Init(cfgFilePath string) { }, ).Fatal("配置文件解析错误") } - } - - // 只显示配置文件名,不显示完整路径 - configFile := viper.ConfigFileUsed() - if configFile != "" { - // 提取文件名 - fileName := filepath.Base(configFile) - log.WithFields( - log.Fields{ - "file": fileName, - }, - ).Info("使用配置文件") } else { - log.Info("使用默认配置") + // 只显示配置文件名,不显示完整路径 + configFile := viper.ConfigFileUsed() + if configFile != "" { + // 统一使用 filepath.Clean 和 filepath.Base 处理路径展示 + cleanPath := filepath.Clean(configFile) + log.WithFields( + log.Fields{ + "file": cleanPath, + }, + ).Info("使用配置文件") + } } // 验证配置 diff --git a/controllers/admin/app.go b/controllers/admin/app.go index 2010d4f..ca915d4 100644 --- a/controllers/admin/app.go +++ b/controllers/admin/app.go @@ -3,6 +3,7 @@ package admin import ( "NetworkAuth/controllers" "NetworkAuth/models" + "NetworkAuth/services" "crypto/rand" "encoding/base64" "encoding/hex" @@ -385,6 +386,20 @@ func AppCreateHandler(c *gin.Context) { return } + // 记录操作日志 + operator := c.GetString("admin_username") + if operator == "" { + operator = "unknown" + } + operatorUUID := c.GetString("admin_uuid") + + services.RecordOperationLog( + "创建应用", + operator, + operatorUUID, + "创建了应用: "+app.Name, + ) + logrus.WithField("app_uuid", app.UUID).Debug("Successfully created app with default APIs") c.JSON(http.StatusOK, gin.H{ @@ -555,6 +570,20 @@ func AppDeleteHandler(c *gin.Context) { return } + // 记录操作日志 + operator := c.GetString("admin_username") + if operator == "" { + operator = "unknown" + } + operatorUUID := c.GetString("admin_uuid") + + services.RecordOperationLog( + "删除应用", + operator, + operatorUUID, + "删除了应用: "+app.Name, + ) + logrus.WithFields(logrus.Fields{ "app_id": app.ID, "app_uuid": app.UUID, diff --git a/controllers/admin/handlers.go b/controllers/admin/dashboard.go similarity index 93% rename from controllers/admin/handlers.go rename to controllers/admin/dashboard.go index c09f584..e9bf60d 100644 --- a/controllers/admin/handlers.go +++ b/controllers/admin/dashboard.go @@ -211,9 +211,20 @@ func DashboardLoginLogsHandler(c *gin.Context) { } offset := (page - 1) * limit + // 获取当前管理员信息(可能是 username 或 admin_username,具体取决于认证中间件设置的 key) + username := c.GetString("admin_username") + if username == "" { + // 尝试获取其他可能的键名 + username = c.GetString("username") + } + var total int64 - // 当前模型的 LoginLog 本身就是专用于 admin 的登录日志模型(没有 type 字段),所以直接查询全部即可 - query := db.Model(&models.LoginLog{}) + query := db.Model(&models.LoginLog{}).Where("type = ?", "admin") + + // 如果有用户名,则仅过滤该用户的日志 + if username != "" { + query = query.Where("username = ?", username) + } if err := query.Count(&total).Error; err != nil { handlersBaseController.HandleInternalError(c, "获取登录日志总数失败", err) @@ -232,3 +243,4 @@ func DashboardLoginLogsHandler(c *gin.Context) { } handlersBaseController.HandleSuccess(c, "获取登录日志成功", data) } + diff --git a/controllers/admin/function.go b/controllers/admin/function.go index 8246db8..a5db9f6 100644 --- a/controllers/admin/function.go +++ b/controllers/admin/function.go @@ -3,6 +3,7 @@ package admin import ( "NetworkAuth/controllers" "NetworkAuth/models" + "NetworkAuth/services" "net/http" "regexp" "strconv" @@ -203,6 +204,20 @@ func FunctionCreateHandler(c *gin.Context) { return } + // 记录操作日志 + operator := c.GetString("admin_username") + if operator == "" { + operator = "unknown" + } + operatorUUID := c.GetString("admin_uuid") + + services.RecordOperationLog( + "创建函数", + operator, + operatorUUID, + "创建了函数: "+function.Alias, + ) + functionBaseController.HandleSuccess(c, "创建成功", function) } @@ -292,6 +307,10 @@ func FunctionDeleteHandler(c *gin.Context) { return } + // 查找函数以记录日志 + var function models.Function + db.First(&function, req.ID) + // 删除函数 if err := db.Delete(&models.Function{}, req.ID).Error; err != nil { logrus.WithError(err).Error("Failed to delete function") @@ -299,6 +318,25 @@ func FunctionDeleteHandler(c *gin.Context) { return } + // 记录操作日志 + operator := c.GetString("admin_username") + if operator == "" { + operator = "unknown" + } + operatorUUID := c.GetString("admin_uuid") + + details := "删除了函数ID: " + strconv.Itoa(int(req.ID)) + if function.ID != 0 { + details = "删除了函数: " + function.Alias + } + + services.RecordOperationLog( + "删除函数", + operator, + operatorUUID, + details, + ) + logrus.WithField("function_id", req.ID).Debug("Successfully deleted function") functionBaseController.HandleSuccess(c, "删除成功", nil) @@ -331,6 +369,26 @@ func FunctionsBatchDeleteHandler(c *gin.Context) { return } + // 记录操作日志 + operator := c.GetString("admin_username") + if operator == "" { + operator = "unknown" + } + operatorUUID := c.GetString("admin_uuid") + + var idStrs []string + for _, id := range req.IDs { + idStrs = append(idStrs, strconv.Itoa(int(id))) + } + details := "批量删除了函数ID: " + strings.Join(idStrs, ",") + + services.RecordOperationLog( + "删除函数", + operator, + operatorUUID, + details, + ) + logrus.WithField("function_ids", req.IDs).Debug("Successfully batch deleted functions") functionBaseController.HandleSuccess(c, "批量删除成功", nil) diff --git a/controllers/admin/login_log.go b/controllers/admin/login_log.go index 13d3f71..36b8f60 100644 --- a/controllers/admin/login_log.go +++ b/controllers/admin/login_log.go @@ -162,9 +162,6 @@ func LoginLogsClearHandler(c *gin.Context) { OperationType: "清空登录日志", Operator: operator, OperatorUUID: "", // NetworkAuth 中暂时无法获取 UUID - AppName: "-", - ProductName: "-", - TransactionID: "-", Details: "管理员清空了所有登录日志", CreatedAt: time.Now(), } diff --git a/controllers/admin/operation_log.go b/controllers/admin/operation_log.go index 2a89b3e..9b8917b 100644 --- a/controllers/admin/operation_log.go +++ b/controllers/admin/operation_log.go @@ -51,7 +51,6 @@ func LogsListHandler(c *gin.Context) { endTimeStr := strings.TrimSpace(c.Query("end_time")) operationType := strings.TrimSpace(c.Query("operation_type")) operator := strings.TrimSpace(c.Query("operator")) - transactionID := strings.TrimSpace(c.Query("transaction_id")) // 构建查询 db, ok := logBaseController.GetDB(c) @@ -72,10 +71,6 @@ func LogsListHandler(c *gin.Context) { // 支持按 UUID 或 用户名 筛选 query = query.Where("operator_uuid = ? OR operator = ?", operator, operator) } - if transactionID != "" { - // 优化:使用精确匹配提升查询性能 - query = query.Where("transaction_id = ?", transactionID) - } if startTimeStr != "" { if t, err := time.ParseInLocation("2006-01-02", startTimeStr, time.Local); err == nil { query = query.Where("created_at >= ?", t) @@ -140,9 +135,6 @@ func LogsClearHandler(c *gin.Context) { OperationType: "清空日志", Operator: operator, OperatorUUID: "", - AppName: "-", - ProductName: "-", - TransactionID: "-", Details: "管理员清空了所有操作日志", CreatedAt: time.Now(), } diff --git a/controllers/admin/profile.go b/controllers/admin/profile.go index a308b81..6cdd611 100644 --- a/controllers/admin/profile.go +++ b/controllers/admin/profile.go @@ -144,6 +144,20 @@ func ProfilePasswordUpdateHandler(c *gin.Context) { cookie := utils.CreateSecureCookie("admin_session", token, maxAge, domain, secure, sameSite) c.SetCookie(cookie.Name, cookie.Value, cookie.MaxAge, cookie.Path, cookie.Domain, cookie.Secure, cookie.HttpOnly) + // 记录操作日志 + operator := c.GetString("admin_username") + if operator == "" { + operator = "unknown" + } + operatorUUID := c.GetString("admin_uuid") + + services.RecordOperationLog( + "修改密码", + operator, + operatorUUID, + "管理员修改了登录密码", + ) + authBaseController.HandleSuccess(c, "密码修改成功", nil) } @@ -217,6 +231,24 @@ func ProfileUpdateHandler(c *gin.Context) { return } + // 刷新缓存 + settingsService.RefreshCache() + _ = utils.RedisDel(c.Request.Context(), "setting:admin_username") + + // 记录操作日志 + operator := c.GetString("admin_username") + if operator == "" { + operator = "unknown" + } + operatorUUID := c.GetString("admin_uuid") + + services.RecordOperationLog( + "修改账号", + operator, + operatorUUID, + "管理员修改了用户名为: "+username, + ) + // 重新签发JWT并写入Cookie token, err := generateJWTTokenForAdmin(username, currentHash) if err != nil { @@ -228,10 +260,6 @@ func ProfileUpdateHandler(c *gin.Context) { cookie := utils.CreateSecureCookie("admin_session", token, maxAge, domain, secure, sameSite) c.SetCookie(cookie.Name, cookie.Value, cookie.MaxAge, cookie.Path, cookie.Domain, cookie.Secure, cookie.HttpOnly) - // 刷新缓存 - settingsService.RefreshCache() - _ = utils.RedisDel(c.Request.Context(), "setting:admin_username") - authBaseController.HandleSuccess(c, "用户名修改成功", map[string]interface{}{ "username": username, }) diff --git a/controllers/admin/variable.go b/controllers/admin/variable.go index 983cfd5..f0d99af 100644 --- a/controllers/admin/variable.go +++ b/controllers/admin/variable.go @@ -3,6 +3,7 @@ package admin import ( "NetworkAuth/controllers" "NetworkAuth/models" + "NetworkAuth/services" "net/http" "regexp" "strconv" @@ -223,6 +224,20 @@ func VariableCreateHandler(c *gin.Context) { return } + // 记录操作日志 + operator := c.GetString("admin_username") + if operator == "" { + operator = "unknown" + } + operatorUUID := c.GetString("admin_uuid") + + services.RecordOperationLog( + "创建变量", + operator, + operatorUUID, + "创建了变量: "+variable.Alias, + ) + variableBaseController.HandleSuccess(c, "创建成功", variable) } @@ -312,6 +327,10 @@ func VariableDeleteHandler(c *gin.Context) { return } + // 查找变量以记录日志 + var variable models.Variable + db.First(&variable, req.ID) + // 删除变量 if err := db.Delete(&models.Variable{}, req.ID).Error; err != nil { logrus.WithError(err).Error("Failed to delete variable") @@ -319,6 +338,25 @@ func VariableDeleteHandler(c *gin.Context) { return } + // 记录操作日志 + operator := c.GetString("admin_username") + if operator == "" { + operator = "unknown" + } + operatorUUID := c.GetString("admin_uuid") + + details := "删除了变量ID: " + strconv.Itoa(int(req.ID)) + if variable.ID != 0 { + details = "删除了变量: " + variable.Alias + } + + services.RecordOperationLog( + "删除变量", + operator, + operatorUUID, + details, + ) + logrus.WithField("variable_id", req.ID).Debug("Successfully deleted variable") variableBaseController.HandleSuccess(c, "删除成功", nil) @@ -351,6 +389,26 @@ func VariablesBatchDeleteHandler(c *gin.Context) { return } + // 记录操作日志 + operator := c.GetString("admin_username") + if operator == "" { + operator = "unknown" + } + operatorUUID := c.GetString("admin_uuid") + + var idStrs []string + for _, id := range req.IDs { + idStrs = append(idStrs, strconv.Itoa(int(id))) + } + details := "批量删除了变量ID: " + strings.Join(idStrs, ",") + + services.RecordOperationLog( + "删除变量", + operator, + operatorUUID, + details, + ) + logrus.WithField("variable_ids", req.IDs).Debug("Successfully batch deleted variables") variableBaseController.HandleSuccess(c, "批量删除成功", nil) diff --git a/database/database.go b/database/database.go index 8989503..4aeb45a 100644 --- a/database/database.go +++ b/database/database.go @@ -2,6 +2,7 @@ package database import ( "NetworkAuth/utils" + "context" "fmt" "log" "os" @@ -23,6 +24,8 @@ import ( var ( // dbInstance 全局 *gorm.DB 实例,使用单例确保全局复用 dbInstance *gorm.DB + // healthCheckCancel 数据库健康检查取消函数 + healthCheckCancel context.CancelFunc // once 确保初始化只执行一次 once sync.Once ) @@ -56,6 +59,10 @@ func GetDB() (*gorm.DB, error) { func ReInit() (*gorm.DB, error) { // 如果已有连接,尝试关闭它 if dbInstance != nil { + if healthCheckCancel != nil { + healthCheckCancel() + healthCheckCancel = nil + } if sqlDB, err := dbInstance.DB(); err == nil { sqlDB.Close() } @@ -124,7 +131,7 @@ func performInit() error { } // 启动健康检查 - utils.StartHealthCheck(dbInstance, dbConfig) + healthCheckCancel = utils.StartHealthCheck(dbInstance, dbConfig) } return initErr } diff --git a/models/operation_log.go b/models/operation_log.go index b8241d3..c6dd46b 100644 --- a/models/operation_log.go +++ b/models/operation_log.go @@ -6,19 +6,16 @@ import ( // OperationLog 操作日志模型 type OperationLog struct { - ID uint `gorm:"primarykey" json:"id"` - CreatedAt time.Time `gorm:"index;comment:创建时间" json:"created_at"` + ID uint `gorm:"primarykey" json:"id"` // 操作信息 - OperationType string `gorm:"type:varchar(50);index;comment:操作方式" json:"operation_type"` // 如:入库成功、凭证分配等 + OperationType string `gorm:"type:varchar(50);index;comment:操作方式" json:"operation_type"` // 操作人信息 Operator string `gorm:"type:varchar(100);index;comment:操作账号" json:"operator"` OperatorUUID string `gorm:"type:varchar(36);index;comment:操作账号UUID" json:"operator_uuid"` - // 关联对象信息 (快照,防止关联对象被删除后无法查询) - TransactionID string `gorm:"type:varchar(100);index;comment:交易ID" json:"transaction_id"` - AppName string `gorm:"type:varchar(100);comment:应用名称" json:"app_name"` - ProductName string `gorm:"type:varchar(100);comment:商品名称" json:"product_name"` - Details string `gorm:"type:text;comment:操作详情" json:"details"` -} \ No newline at end of file + Details string `gorm:"type:text;comment:操作详情" json:"details"` + + CreatedAt time.Time `gorm:"index;comment:创建时间" json:"created_at"` +} diff --git a/services/operation_log.go b/services/operation_log.go index 34f4c02..d5dd9ec 100644 --- a/services/operation_log.go +++ b/services/operation_log.go @@ -9,7 +9,7 @@ import ( ) // RecordOperationLog 记录操作日志 -func RecordOperationLog(operationType, operator, operatorUUID, transactionID, appName, productName, details string) { +func RecordOperationLog(operationType, operator, operatorUUID, details string) { db, err := database.GetDB() if err != nil { logrus.WithError(err).Error("获取数据库连接失败,无法记录操作日志") @@ -20,9 +20,6 @@ func RecordOperationLog(operationType, operator, operatorUUID, transactionID, ap OperationType: operationType, Operator: operator, OperatorUUID: operatorUUID, - TransactionID: transactionID, - AppName: appName, - ProductName: productName, Details: details, CreatedAt: time.Now(), } diff --git a/utils/database.go b/utils/database.go index cc605f8..859e8dc 100644 --- a/utils/database.go +++ b/utils/database.go @@ -301,22 +301,29 @@ func LogConnectionStats(db *gorm.DB) { // StartHealthCheck 启动数据库健康检查 // 启动一个后台goroutine定期检查数据库连接健康状态 // 只在健康检查失败时输出错误日志,正常情况下不输出日志 -func StartHealthCheck(db *gorm.DB, config *DatabaseConfig) { +// 返回一个 CancelFunc 用于停止健康检查 +func StartHealthCheck(db *gorm.DB, config *DatabaseConfig) context.CancelFunc { + ctx, cancel := context.WithCancel(context.Background()) go func() { ticker := time.NewTicker(config.HealthCheckInterval) defer ticker.Stop() - for range ticker.C { - if err := PingDatabase(db, config.PingTimeout); err != nil { - // 只在健康检查失败时输出错误日志 - LogError("数据库健康检查失败", err, map[string]interface{}{ - "ping_timeout": config.PingTimeout, - }) - } + for { + select { + case <-ctx.Done(): + return + case <-ticker.C: + if err := PingDatabase(db, config.PingTimeout); err != nil { + // 只在健康检查失败时输出错误日志 + LogError("数据库健康检查失败", err, map[string]interface{}{ + "ping_timeout": config.PingTimeout, + }) + } - // 记录连接池统计信息(仅在调试模式下) - if logrus.GetLevel() == logrus.DebugLevel { - LogConnectionStats(db) + // 记录连接池统计信息(仅在调试模式下) + if logrus.GetLevel() == logrus.DebugLevel { + LogConnectionStats(db) + } } } }() @@ -325,6 +332,8 @@ func StartHealthCheck(db *gorm.DB, config *DatabaseConfig) { // "check_interval": config.HealthCheckInterval, // "ping_timeout": config.PingTimeout, // }) + + return cancel } // ValidateDatabaseConfig 验证数据库配置参数 diff --git a/web/template/admin/operation_logs.html b/web/template/admin/operation_logs.html index c060292..7943d9f 100644 --- a/web/template/admin/operation_logs.html +++ b/web/template/admin/operation_logs.html @@ -26,12 +26,6 @@ -
- -
- -
-
@@ -91,9 +85,6 @@ layui.use(['table', 'form', 'laydate', 'util', 'jquery'], function(){ limit: 20, limits: [10, 20, 50, 100, 200, 500, 1000], cols: [[ - {field: 'app_name', title: '应用名称', minWidth: 150}, - {field: 'product_name', title: '商品名称', minWidth: 150}, - {field: 'transaction_id', title: '交易ID', width: 280}, {field: 'operator', title: '操作账号', minWidth: 150}, {field: 'operation_type', title: '操作方式', minWidth: 150}, {field: 'details', title: '日志内容', minWidth: 200}, @@ -125,7 +116,6 @@ layui.use(['table', 'form', 'laydate', 'util', 'jquery'], function(){ where: { operation_type: formData.operation_type, operator: formData.operator, - transaction_id: formData.transaction_id, start_time: $('#operation_start_time').val(), end_time: $('#operation_end_time').val() }, diff --git a/web/template/admin/profile.html b/web/template/admin/profile.html index efa026b..0162473 100644 --- a/web/template/admin/profile.html +++ b/web/template/admin/profile.html @@ -1,237 +1,340 @@ {{ define "profile.html" }} -
-
个人资料
-
-
- -
- -
- +
+

账户管理

+
+
    +
  • 修改密码
  • +
  • 修改用户名
  • +
+
+ +
+
+

修改密码

+
+ +
+ +
+
+ +
+
+
+
+ +
+
+ +
+
+
+
+ +
+
+ +
+
+
+
+
+ + +
+
+ +
-
- -
- - + +
+
+

修改用户名

+
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+
+ +
+
+
+
+
+ + +
+
+
+
- -
- -
- - -
-
- -
- -
- - -
-
- -
-
- - - -
-
- +
-
- -{{ end }} + // 全局变量 + let currentUsername = null + + // 获取当前用户名 + const getCurrentUsername = async () => { + try { + const res = await fetch('/admin/api/profile/info') + let data + try { + const text = await res.text() + data = JSON.parse(text) + } catch (e) { + throw new Error('服务器响应格式错误') + } + + const ok = (data.success === true) || (data.code === 0) + if (!ok) throw new Error(data.message || data.msg || '获取用户信息失败') + + currentUsername = data.data.username + // 填充用户名修改表单的当前用户名 + form.val('usernameForm', { current_username: currentUsername }) + + } catch (e) { + layer.msg(e.message || '获取用户信息失败', { icon: 2 }) + } + } + + // 修改密码模块 + const PasswordModule = { + validate: (fields) => { + const { old_password, new_password, confirm_password } = fields + + if (!old_password || !new_password || !confirm_password) { + return { ok: false, msg: '请填写完整的密码信息' } + } + + if (new_password.length < 6) { + return { ok: false, msg: '新密码长度不能少于6位' } + } + + if (new_password !== confirm_password) { + return { ok: false, msg: '两次输入的新密码不一致' } + } + + if (old_password === new_password) { + return { ok: false, msg: '新密码不能与当前密码相同' } + } + + return { ok: true } + }, + + submit: async (fields) => { + const validation = PasswordModule.validate(fields) + if (!validation.ok) { + layer.msg(validation.msg, { icon: 2 }) + return false + } + + try { + const res = await fetch('/admin/api/profile/password', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + old_password: fields.old_password, + new_password: fields.new_password, + confirm_password: fields.confirm_password + }) + }) + + let data + try { + const text = await res.text() + data = JSON.parse(text) + } catch (e) { + throw new Error('服务器响应格式错误') + } + + const ok = (data.success === true) || (data.code === 0) + if (!ok) throw new Error(data.message || data.msg || '修改密码失败') + + // 检查是否需要跳转 + if (data.data?.redirect) { + layer.msg('密码修改成功,即将跳转到登录页', { icon: 1, time: 1500 }, () => { + window.location.href = data.data.redirect + }) + } else { + // 密码修改成功,不跳转,重置表单 + layer.msg('密码修改成功', { icon: 1 }) + document.getElementById('passwordForm').reset() + } + + } catch (e) { + layer.msg(e.message || '修改密码失败', { icon: 2 }) + } + + return false + }, + + reset: () => { + document.getElementById('passwordForm').reset() + layer.msg('表单已重置', { icon: 1 }) + } + } + + // 修改用户名模块 + const UsernameModule = { + validate: (fields) => { + const { new_username, password } = fields + + if (!new_username || !password) { + return { ok: false, msg: '请填写新用户名和当前密码' } + } + + if (new_username === currentUsername) { + return { ok: false, msg: '新用户名不能与当前用户名相同' } + } + + if (new_username.length < 3) { + return { ok: false, msg: '用户名长度不能少于3位' } + } + + return { ok: true } + }, + + submit: async (fields) => { + const validation = UsernameModule.validate(fields) + if (!validation.ok) { + layer.msg(validation.msg, { icon: 2 }) + return false + } + + try { + const res = await fetch('/admin/api/profile/update', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + username: fields.new_username, + old_password: fields.password + }) + }) + + let data + try { + const text = await res.text() + data = JSON.parse(text) + } catch (e) { + throw new Error('服务器响应格式错误') + } + + const ok = (data.success === true) || (data.code === 0) + if (!ok) throw new Error(data.message || data.msg || '修改用户名失败') + + layer.msg('用户名修改成功', { icon: 1 }) + + // 重新获取当前用户名 + await getCurrentUsername() + + // 清空表单(不显示重置提示) + form.val('usernameForm', { + new_username: '', + password: '', + current_username: currentUsername || '' + }) + + } catch (e) { + layer.msg(e.message || '修改用户名失败', { icon: 2 }) + } + + return false + }, + + reset: () => { + form.val('usernameForm', { + new_username: '', + password: '', + current_username: currentUsername || '' + }) + layer.msg('表单已重置', { icon: 1 }) + } + } + + // 绑定表单提交事件 + form.on('submit(submitPassword)', (obj) => { + return PasswordModule.submit(obj.field) + }) + + form.on('submit(submitUsername)', (obj) => { + return UsernameModule.submit(obj.field) + }) + + // 绑定重置按钮 + document.getElementById('resetPasswordBtn')?.addEventListener('click', PasswordModule.reset) + document.getElementById('resetUsernameBtn')?.addEventListener('click', UsernameModule.reset) + + // 初始化加载 + getCurrentUsername() + }) + }) + })() + +
+{{ end }} \ No newline at end of file