From 3d4f3e3f82758c7574796b8f4d86d7d64ec5415b Mon Sep 17 00:00:00 2001 From: skyle1995 Date: Fri, 24 Oct 2025 08:25:16 +0800 Subject: [PATCH] Add registration Settings --- config/validator.go | 2 +- controllers/admin/app.go | 311 ++++++++++++++++++++++++++++++++--- controllers/admin/captcha.go | 21 ++- database/database.go | 2 +- models/app.go | 22 +++ server/admin.go | 2 + web/template/admin/apps.html | 176 ++++++++++++++++++++ 7 files changed, 511 insertions(+), 25 deletions(-) diff --git a/config/validator.go b/config/validator.go index b3e29db..8a54809 100644 --- a/config/validator.go +++ b/config/validator.go @@ -136,7 +136,7 @@ func setDefaults(config *AppConfig) { config.Database.MySQL.MaxOpenConns = 100 } if config.Database.SQLite.Path == "" { - config.Database.SQLite.Path = "./recharge.db" + config.Database.SQLite.Path = "./database.db" } // Redis默认值 diff --git a/controllers/admin/app.go b/controllers/admin/app.go index 6541493..6899749 100644 --- a/controllers/admin/app.go +++ b/controllers/admin/app.go @@ -801,16 +801,18 @@ func AppGetBindConfigHandler(w http.ResponseWriter, r *http.Request) { // 返回绑定配置信息 response := map[string]interface{}{ - "machine_code_verify": app.MachineCodeVerify, - "machine_code_option": app.MachineCodeOption, - "machine_code_free_count": app.MachineCodeFreeCount, - "machine_code_rebind_count": app.MachineCodeRebindCount, - "machine_code_rebind_deduct": app.MachineCodeRebindDeduct, - "ip_verify": app.IPVerify, - "ip_option": app.IPOption, - "ip_free_count": app.IPFreeCount, - "ip_rebind_count": app.IPRebindCount, - "ip_rebind_deduct": app.IPRebindDeduct, + "machine_code_verify": app.MachineCodeVerify, + "machine_code_rebind_enabled": app.MachineCodeRebindEnabled, + "machine_code_option": app.MachineCodeOption, + "machine_code_free_count": app.MachineCodeFreeCount, + "machine_code_rebind_count": app.MachineCodeRebindCount, + "machine_code_rebind_deduct": app.MachineCodeRebindDeduct, + "ip_verify": app.IPVerify, + "ip_rebind_enabled": app.IPRebindEnabled, + "ip_option": app.IPOption, + "ip_free_count": app.IPFreeCount, + "ip_rebind_count": app.IPRebindCount, + "ip_rebind_deduct": app.IPRebindDeduct, } w.Header().Set("Content-Type", "application/json") @@ -827,11 +829,13 @@ func AppUpdateBindConfigHandler(w http.ResponseWriter, r *http.Request) { var req struct { UUID string `json:"uuid"` MachineCodeVerify int `json:"machine_code_verify"` + MachineCodeRebindEnabled int `json:"machine_code_rebind_enabled"` MachineCodeOption int `json:"machine_code_option"` MachineCodeFreeCount int `json:"machine_code_free_count"` MachineCodeRebindCount int `json:"machine_code_rebind_count"` MachineCodeRebindDeduct int `json:"machine_code_rebind_deduct"` IPVerify int `json:"ip_verify"` + IPRebindEnabled int `json:"ip_rebind_enabled"` IPOption int `json:"ip_option"` IPFreeCount int `json:"ip_free_count"` IPRebindCount int `json:"ip_rebind_count"` @@ -911,6 +915,26 @@ func AppUpdateBindConfigHandler(w http.ResponseWriter, r *http.Request) { return } + if req.MachineCodeRebindEnabled < 0 || req.MachineCodeRebindEnabled > 1 { + response := map[string]interface{}{ + "code": 1, + "msg": "机器码重绑开关参数无效", + } + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(response) + return + } + + if req.IPRebindEnabled < 0 || req.IPRebindEnabled > 1 { + response := map[string]interface{}{ + "code": 1, + "msg": "IP地址重绑开关参数无效", + } + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(response) + return + } + if req.MachineCodeFreeCount < 0 || req.MachineCodeRebindCount < 0 || req.MachineCodeRebindDeduct < 0 || req.IPFreeCount < 0 || req.IPRebindCount < 0 || req.IPRebindDeduct < 0 { response := map[string]interface{}{ @@ -949,16 +973,18 @@ func AppUpdateBindConfigHandler(w http.ResponseWriter, r *http.Request) { // 更新绑定配置 updates := map[string]interface{}{ - "machine_code_verify": req.MachineCodeVerify, - "machine_code_option": req.MachineCodeOption, - "machine_code_free_count": req.MachineCodeFreeCount, - "machine_code_rebind_count": req.MachineCodeRebindCount, - "machine_code_rebind_deduct": req.MachineCodeRebindDeduct, - "ip_verify": req.IPVerify, - "ip_option": req.IPOption, - "ip_free_count": req.IPFreeCount, - "ip_rebind_count": req.IPRebindCount, - "ip_rebind_deduct": req.IPRebindDeduct, + "machine_code_verify": req.MachineCodeVerify, + "machine_code_rebind_enabled": req.MachineCodeRebindEnabled, + "machine_code_option": req.MachineCodeOption, + "machine_code_free_count": req.MachineCodeFreeCount, + "machine_code_rebind_count": req.MachineCodeRebindCount, + "machine_code_rebind_deduct": req.MachineCodeRebindDeduct, + "ip_verify": req.IPVerify, + "ip_rebind_enabled": req.IPRebindEnabled, + "ip_option": req.IPOption, + "ip_free_count": req.IPFreeCount, + "ip_rebind_count": req.IPRebindCount, + "ip_rebind_deduct": req.IPRebindDeduct, } if err := db.Model(&app).Updates(updates).Error; err != nil { @@ -980,3 +1006,248 @@ func AppUpdateBindConfigHandler(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(response) } + +// AppGetRegisterConfigHandler 获取应用注册配置 +func AppGetRegisterConfigHandler(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodGet { + http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) + return + } + + appUUID := r.URL.Query().Get("uuid") + if appUUID == "" { + response := map[string]interface{}{ + "code": 1, + "msg": "缺少应用UUID", + } + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(response) + return + } + + // 验证UUID格式 + if _, err := uuid.Parse(appUUID); err != nil { + response := map[string]interface{}{ + "code": 1, + "msg": "无效的UUID格式", + } + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(response) + return + } + + db, err := database.GetDB() + if err != nil { + logrus.WithError(err).Error("Failed to get database connection") + response := map[string]interface{}{ + "code": 1, + "msg": "数据库连接失败", + } + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(response) + return + } + + var app models.App + if err := db.Where("uuid = ?", appUUID).First(&app).Error; err != nil { + logrus.WithError(err).Error("Failed to find app") + response := map[string]interface{}{ + "code": 1, + "msg": "应用不存在", + } + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(response) + return + } + + // 返回注册配置信息 + response := map[string]interface{}{ + "register_enabled": app.RegisterEnabled, + "register_limit_enabled": app.RegisterLimitEnabled, + "register_limit_time": app.RegisterLimitTime, + "register_count": app.RegisterCount, + "trial_enabled": app.TrialEnabled, + "trial_limit_time": app.TrialLimitTime, + "trial_duration": app.TrialDuration, + } + + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(response) +} + +// AppUpdateRegisterConfigHandler 更新应用注册配置 +func AppUpdateRegisterConfigHandler(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodPost { + http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) + return + } + + var req struct { + UUID string `json:"uuid"` + RegisterEnabled int `json:"register_enabled"` + RegisterLimitEnabled int `json:"register_limit_enabled"` + RegisterLimitTime int `json:"register_limit_time"` + RegisterCount int `json:"register_count"` + TrialEnabled int `json:"trial_enabled"` + TrialLimitTime int `json:"trial_limit_time"` + TrialDuration int `json:"trial_duration"` + } + + if err := json.NewDecoder(r.Body).Decode(&req); err != nil { + logrus.WithError(err).Error("Failed to decode JSON request") + response := map[string]interface{}{ + "code": 1, + "msg": "无效的JSON格式", + } + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(response) + return + } + + // 验证UUID + if req.UUID == "" { + response := map[string]interface{}{ + "code": 1, + "msg": "应用UUID不能为空", + } + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(response) + return + } + + if _, err := uuid.Parse(req.UUID); err != nil { + response := map[string]interface{}{ + "code": 1, + "msg": "无效的UUID格式", + } + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(response) + return + } + + // 验证参数范围 + if req.RegisterEnabled < 0 || req.RegisterEnabled > 1 { + response := map[string]interface{}{ + "code": 1, + "msg": "账号注册开关参数无效", + } + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(response) + return + } + + if req.RegisterLimitEnabled < 0 || req.RegisterLimitEnabled > 1 { + response := map[string]interface{}{ + "code": 1, + "msg": "注册限制开关参数无效", + } + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(response) + return + } + + if req.RegisterLimitTime < 0 || req.RegisterLimitTime > 1 { + response := map[string]interface{}{ + "code": 1, + "msg": "注册限制时间参数无效", + } + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(response) + return + } + + if req.RegisterCount < 1 { + response := map[string]interface{}{ + "code": 1, + "msg": "注册次数必须大于0", + } + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(response) + return + } + + if req.TrialEnabled < 0 || req.TrialEnabled > 1 { + response := map[string]interface{}{ + "code": 1, + "msg": "领取试用开关参数无效", + } + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(response) + return + } + + if req.TrialLimitTime < 0 || req.TrialLimitTime > 1 { + response := map[string]interface{}{ + "code": 1, + "msg": "试用限制时间参数无效", + } + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(response) + return + } + + if req.TrialDuration < 0 { + response := map[string]interface{}{ + "code": 1, + "msg": "试用时间不能为负数", + } + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(response) + return + } + + db, err := database.GetDB() + if err != nil { + logrus.WithError(err).Error("Failed to get database connection") + response := map[string]interface{}{ + "code": 1, + "msg": "数据库连接失败", + } + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(response) + return + } + + // 查找应用 + var app models.App + if err := db.Where("uuid = ?", req.UUID).First(&app).Error; err != nil { + logrus.WithError(err).Error("Failed to find app") + response := map[string]interface{}{ + "code": 1, + "msg": "应用不存在", + } + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(response) + return + } + + // 更新注册配置 + updates := map[string]interface{}{ + "register_enabled": req.RegisterEnabled, + "register_limit_enabled": req.RegisterLimitEnabled, + "register_limit_time": req.RegisterLimitTime, + "register_count": req.RegisterCount, + "trial_enabled": req.TrialEnabled, + "trial_limit_time": req.TrialLimitTime, + "trial_duration": req.TrialDuration, + } + + if err := db.Model(&app).Updates(updates).Error; err != nil { + logrus.WithError(err).Error("Failed to update app register config") + response := map[string]interface{}{ + "code": 1, + "msg": "更新注册配置失败", + } + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(response) + return + } + + response := map[string]interface{}{ + "code": 0, + "msg": "注册配置更新成功", + } + + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(response) +} diff --git a/controllers/admin/captcha.go b/controllers/admin/captcha.go index 189554e..dc738b0 100644 --- a/controllers/admin/captcha.go +++ b/controllers/admin/captcha.go @@ -1,9 +1,10 @@ package admin import ( + "crypto/rand" "encoding/base64" "encoding/json" - "math/rand" + "math/big" "net/http" "strings" "time" @@ -14,6 +15,15 @@ import ( // 全局验证码存储器 var store = base64Captcha.DefaultMemStore +// secureRandomInt 生成安全的随机整数,范围 [0, max) +func secureRandomInt(max int) (int, error) { + n, err := rand.Int(rand.Reader, big.NewInt(int64(max))) + if err != nil { + return 0, err + } + return int(n.Int64()), nil +} + // CaptchaHandler 生成验证码图片 // GET /admin/captcha - 返回验证码图片 func CaptchaHandler(w http.ResponseWriter, r *http.Request) { @@ -23,8 +33,13 @@ func CaptchaHandler(w http.ResponseWriter, r *http.Request) { } // 随机生成4-6位长度 - // Go 1.20+ 无需手动设置随机种子,使用默认全局随机源即可 - captchaLength := 4 + rand.Intn(3) // 4-6位随机长度 + // 使用crypto/rand生成安全的随机数 + randomNum, err := secureRandomInt(3) + if err != nil { + http.Error(w, "生成随机数失败", http.StatusInternalServerError) + return + } + captchaLength := 4 + randomNum // 4-6位随机长度 // 配置验证码参数 - 使用字母数字混合 driver := base64Captcha.DriverString{ diff --git a/database/database.go b/database/database.go index c102713..abc00a7 100644 --- a/database/database.go +++ b/database/database.go @@ -78,7 +78,7 @@ func GetDB() (*gorm.DB, error) { func initSQLite() error { path := viper.GetString("database.sqlite.path") if path == "" { - path = "./recharge.db" + path = "./database.db" } dsn := fmt.Sprintf("file:%s?cache=shared&_busy_timeout=5000&_fk=1", path) db, err := gorm.Open(sqlite.Open(dsn), &gorm.Config{}) diff --git a/models/app.go b/models/app.go index 263dbf5..a9961ec 100644 --- a/models/app.go +++ b/models/app.go @@ -56,6 +56,8 @@ type App struct { // 机器码验证相关字段 // MachineCodeVerify:机器码验证(0=关闭,1=开启) MachineCodeVerify int `gorm:"default:0;not null;comment:机器码验证,0=关闭,1=开启" json:"machine_code_verify"` + // MachineCodeRebindEnabled:机器码重绑开关(0=关闭,1=开启) + MachineCodeRebindEnabled int `gorm:"default:0;not null;comment:机器码重绑开关,0=关闭,1=开启" json:"machine_code_rebind_enabled"` // MachineCodeOption:机器码选项(0=每天,1=永久) MachineCodeOption int `gorm:"default:0;not null;comment:机器码选项,0=每天,1=永久" json:"machine_code_option"` // MachineCodeFreeCount:机器码免费次数(默认0) @@ -68,6 +70,8 @@ type App struct { // IP地址验证相关字段 // IPVerify:IP地址验证(0=关闭,1=开启,2=开启(市),3=开启(省)) IPVerify int `gorm:"default:0;not null;comment:IP地址验证,0=关闭,1=开启,2=开启(市),3=开启(省)" json:"ip_verify"` + // IPRebindEnabled:IP地址重绑开关(0=关闭,1=开启) + IPRebindEnabled int `gorm:"default:0;not null;comment:IP地址重绑开关,0=关闭,1=开启" json:"ip_rebind_enabled"` // IPOption:IP地址选项(0=每天,1=永久) IPOption int `gorm:"default:0;not null;comment:IP地址选项,0=每天,1=永久" json:"ip_option"` // IPFreeCount:IP地址免费次数(默认0) @@ -77,6 +81,24 @@ type App struct { // IPRebindDeduct:IP地址重绑扣除(默认0,单位:分钟) IPRebindDeduct int `gorm:"default:0;not null;comment:IP地址重绑扣除,单位分钟" json:"ip_rebind_deduct"` + // 账号注册相关字段 + // RegisterEnabled:账号注册开关(0=关闭,1=开启) + RegisterEnabled int `gorm:"default:1;not null;comment:账号注册开关,0=关闭,1=开启" json:"register_enabled"` + // RegisterLimitEnabled:注册限制开关(0=关闭,1=开启) + RegisterLimitEnabled int `gorm:"default:0;not null;comment:注册限制开关,0=关闭,1=开启" json:"register_limit_enabled"` + // RegisterLimitTime:限制时间(0=每天,1=永久) + RegisterLimitTime int `gorm:"default:1;not null;comment:注册限制时间,0=每天,1=永久" json:"register_limit_time"` + // RegisterCount:注册次数 + RegisterCount int `gorm:"default:1;not null;comment:注册次数" json:"register_count"` + + // 领取试用相关字段 + // TrialEnabled:领取试用开关(0=关闭,1=开启) + TrialEnabled int `gorm:"default:0;not null;comment:领取试用开关,0=关闭,1=开启" json:"trial_enabled"` + // TrialLimitTime:试用限制时间(0=每天,1=永久) + TrialLimitTime int `gorm:"default:1;not null;comment:试用限制时间,0=每天,1=永久" json:"trial_limit_time"` + // TrialDuration:试用时间(单位:分钟) + TrialDuration int `gorm:"default:0;not null;comment:试用时间,单位分钟" json:"trial_duration"` + // CreatedAt/UpdatedAt:时间字段,返回为 created_at/updated_at,便于前端展示 CreatedAt time.Time `gorm:"comment:创建时间" json:"created_at"` UpdatedAt time.Time `gorm:"comment:更新时间" json:"updated_at"` diff --git a/server/admin.go b/server/admin.go index 818c12c..f050ce8 100644 --- a/server/admin.go +++ b/server/admin.go @@ -67,6 +67,8 @@ func RegisterAdminRoutes(mux *http.ServeMux) { mux.HandleFunc("/admin/api/apps/update_multi_config", adminctl.AdminAuthRequired(adminctl.AppUpdateMultiConfigHandler)) mux.HandleFunc("/admin/api/apps/get_bind_config", adminctl.AdminAuthRequired(adminctl.AppGetBindConfigHandler)) mux.HandleFunc("/admin/api/apps/update_bind_config", adminctl.AdminAuthRequired(adminctl.AppUpdateBindConfigHandler)) + mux.HandleFunc("/admin/api/apps/get_register_config", adminctl.AdminAuthRequired(adminctl.AppGetRegisterConfigHandler)) + mux.HandleFunc("/admin/api/apps/update_register_config", adminctl.AdminAuthRequired(adminctl.AppUpdateRegisterConfigHandler)) // 系统信息API(用于仪表盘定时刷新) diff --git a/web/template/admin/apps.html b/web/template/admin/apps.html index f19ba91..0da30c6 100644 --- a/web/template/admin/apps.html +++ b/web/template/admin/apps.html @@ -330,6 +330,10 @@ title: '绑定设置', id: 'bind_settings' }, + { + title: '注册设置', + id: 'register_settings' + }, { title: '重置密钥', id: 'reset_secret' @@ -578,6 +582,13 @@ '' + '' + '
' + + '' + + '
' + + '' + + '' + + '
' + + '
' + + '
' + '' + '
' + '' + @@ -617,6 +628,13 @@ '
' + '
' + '
' + + '' + + '
' + + '' + + '' + + '
' + + '
' + + '
' + '' + '
' + '' + @@ -649,11 +667,13 @@ var formData = { uuid: obj.data.uuid, machine_code_verify: parseInt($('input[name="machine_code_verify"]:checked').val()), + machine_code_rebind_enabled: parseInt($('input[name="machine_code_rebind_enabled"]:checked').val()), machine_code_option: parseInt($('input[name="machine_code_option"]:checked').val()), machine_code_free_count: parseInt($('input[name="machine_code_free_count"]').val()) || 0, machine_code_rebind_count: parseInt($('input[name="machine_code_rebind_count"]').val()) || 0, machine_code_rebind_deduct: parseInt($('input[name="machine_code_rebind_deduct"]').val()) || 0, ip_verify: parseInt($('input[name="ip_verify"]:checked').val()), + ip_rebind_enabled: parseInt($('input[name="ip_rebind_enabled"]:checked').val()), ip_option: parseInt($('input[name="ip_option"]:checked').val()), ip_free_count: parseInt($('input[name="ip_free_count"]').val()) || 0, ip_rebind_count: parseInt($('input[name="ip_rebind_count"]').val()) || 0, @@ -665,6 +685,10 @@ layer.msg('请选择机器码验证选项', {icon: 2}); return; } + if (isNaN(formData.machine_code_rebind_enabled) || formData.machine_code_rebind_enabled < 0 || formData.machine_code_rebind_enabled > 1) { + layer.msg('请选择机器码重绑选项', {icon: 2}); + return; + } if (isNaN(formData.machine_code_option) || formData.machine_code_option < 0 || formData.machine_code_option > 1) { layer.msg('请选择机器码选项', {icon: 2}); return; @@ -673,6 +697,10 @@ layer.msg('请选择IP地址验证选项', {icon: 2}); return; } + if (isNaN(formData.ip_rebind_enabled) || formData.ip_rebind_enabled < 0 || formData.ip_rebind_enabled > 1) { + layer.msg('请选择IP地址重绑选项', {icon: 2}); + return; + } if (isNaN(formData.ip_option) || formData.ip_option < 0 || formData.ip_option > 1) { layer.msg('请选择IP地址选项', {icon: 2}); return; @@ -711,6 +739,154 @@ layer.msg('获取绑定设置失败,请稍后重试', {icon: 2}); } }); + } else if (menudata.id === 'register_settings') { + // 注册设置 + $.ajax({ + url: '/admin/api/apps/get_register_config?uuid=' + obj.data.uuid, + type: 'GET', + success: function(config) { + layer.open({ + type: 1, + title: '注册设置 - ' + obj.data.name, + area: ['550px', '500px'], + content: '
' + + '
' + + + // 账号注册设置 + '
' + + '账号注册设置' + + '
' + + '
' + + '' + + '
' + + '' + + '' + + '
' + + '
' + + '
' + + '' + + '
' + + '' + + '' + + '
' + + '
' + + '
' + + '' + + '
' + + '' + + '' + + '
' + + '
' + + '
' + + '' + + '
' + + '' + + '
' + + '
' + + + // 领取试用设置 + '
' + + '领取试用设置' + + '
' + + '
' + + '' + + '
' + + '' + + '' + + '
' + + '
' + + '
' + + '' + + '
' + + '' + + '' + + '
' + + '
' + + '
' + + '' + + '
' + + '' + + '
' + + '
' + + + '
' + + '
', + btn: ['保存', '取消'], + yes: function(index, layero) { + var formData = { + uuid: obj.data.uuid, + register_enabled: parseInt($('input[name="register_enabled"]:checked').val()), + register_limit_enabled: parseInt($('input[name="register_limit_enabled"]:checked').val()), + register_limit_time: parseInt($('input[name="register_limit_time"]:checked').val()), + register_count: parseInt($('input[name="register_count"]').val()) || 1, + trial_enabled: parseInt($('input[name="trial_enabled"]:checked').val()), + trial_limit_time: parseInt($('input[name="trial_limit_time"]:checked').val()), + trial_duration: parseInt($('input[name="trial_duration"]').val()) || 0 + }; + + // 验证数据 + if (isNaN(formData.register_enabled) || formData.register_enabled < 0 || formData.register_enabled > 1) { + layer.msg('请选择账号注册选项', {icon: 2}); + return; + } + if (isNaN(formData.register_limit_enabled) || formData.register_limit_enabled < 0 || formData.register_limit_enabled > 1) { + layer.msg('请选择注册限制选项', {icon: 2}); + return; + } + if (isNaN(formData.register_limit_time) || formData.register_limit_time < 0 || formData.register_limit_time > 1) { + layer.msg('请选择限制时间选项', {icon: 2}); + return; + } + if (isNaN(formData.register_count) || formData.register_count < 1) { + layer.msg('注册次数必须大于0', {icon: 2}); + return; + } + if (isNaN(formData.trial_enabled) || formData.trial_enabled < 0 || formData.trial_enabled > 1) { + layer.msg('请选择领取试用选项', {icon: 2}); + return; + } + if (isNaN(formData.trial_limit_time) || formData.trial_limit_time < 0 || formData.trial_limit_time > 1) { + layer.msg('请选择试用限制时间选项', {icon: 2}); + return; + } + if (isNaN(formData.trial_duration) || formData.trial_duration < 0) { + layer.msg('试用时间不能小于0', {icon: 2}); + return; + } + + // 发送更新请求 + $.ajax({ + url: '/admin/api/apps/update_register_config', + type: 'POST', + contentType: 'application/json', + data: JSON.stringify(formData), + success: function(res) { + if (res.code === 0) { + layer.msg('注册设置更新成功', {icon: 1}); + layer.close(index); + table.reload('appsTable'); + } else { + layer.msg(res.msg || '更新注册设置失败', {icon: 2}); + } + }, + error: function() { + layer.msg('网络错误,请稍后重试', {icon: 2}); + } + }); + }, + btn2: function(index) { + layer.close(index); + }, + success: function() { + // 重新渲染表单 + form.render(); + } + }); + }, + error: function() { + layer.msg('获取注册设置失败,请稍后重试', {icon: 2}); + } + }); } }, align: 'right', // 右对齐弹出