diff --git a/api/handler/admin/config_handler.go b/api/handler/admin/config_handler.go index 4a6aa690..2d87c9a1 100644 --- a/api/handler/admin/config_handler.go +++ b/api/handler/admin/config_handler.go @@ -140,3 +140,68 @@ func (h *ConfigHandler) GetLicense(c *gin.Context) { license := h.licenseService.GetLicense() resp.SUCCESS(c, license) } + +// FixData 修复数据 +func (h *ConfigHandler) FixData(c *gin.Context) { + var fixed bool + version := "data_fix_4.1.4" + err := h.levelDB.Get(version, &fixed) + if err == nil || fixed { + resp.ERROR(c, "当前版本数据修复已完成,请不要重复执行操作") + return + } + tx := h.DB.Begin() + var users []model.User + err = tx.Find(&users).Error + if err != nil { + resp.ERROR(c, err.Error()) + return + } + for _, user := range users { + if user.Email != "" || user.Mobile != "" { + continue + } + if utils.IsValidEmail(user.Username) { + user.Email = user.Username + } else if utils.IsValidMobile(user.Username) { + user.Mobile = user.Username + } + err = tx.Save(&user).Error + if err != nil { + resp.ERROR(c, err.Error()) + tx.Rollback() + return + } + } + + var orders []model.Order + err = h.DB.Find(&orders).Error + if err != nil { + resp.ERROR(c, err.Error()) + return + } + for _, order := range orders { + if order.PayWay == "支付宝" { + order.PayWay = "alipay" + order.PayType = "alipay" + } else if order.PayWay == "微信支付" { + order.PayWay = "wechat" + order.PayType = "wxpay" + } else if order.PayWay == "hupi" { + order.PayType = "wxpay" + } + err = tx.Save(&order).Error + if err != nil { + resp.ERROR(c, err.Error()) + tx.Rollback() + return + } + } + tx.Commit() + err = h.levelDB.Put(version, true) + if err != nil { + resp.ERROR(c, err.Error()) + return + } + resp.SUCCESS(c) +} diff --git a/api/main.go b/api/main.go index 76692bef..841bc75c 100644 --- a/api/main.go +++ b/api/main.go @@ -307,11 +307,12 @@ func main() { // 管理后台控制器 fx.Invoke(func(s *core.AppServer, h *admin.ConfigHandler) { - group := s.Engine.Group("/api/admin/") - group.POST("config/update", h.Update) - group.GET("config/get", h.Get) + group := s.Engine.Group("/api/admin/config") + group.POST("update", h.Update) + group.GET("get", h.Get) group.POST("active", h.Active) - group.GET("config/get/license", h.GetLicense) + group.GET("fixData", h.FixData) + group.GET("license", h.GetLicense) }), fx.Invoke(func(s *core.AppServer, h *admin.ManagerHandler) { group := s.Engine.Group("/api/admin/") diff --git a/api/utils/strings.go b/api/utils/strings.go index 12c8b107..0538163d 100644 --- a/api/utils/strings.go +++ b/api/utils/strings.go @@ -12,6 +12,7 @@ import ( "encoding/hex" "encoding/json" "fmt" + "regexp" "strings" "time" "unicode" @@ -134,3 +135,17 @@ func GenRedeemCode(codeLength int) (string, error) { } return hex.EncodeToString(bytes), nil } + +// IsValidEmail 检查给定的字符串是否是有效的电子邮件地址 +func IsValidEmail(email string) bool { + // 这个正则表达式匹配大多数常见的邮箱格式 + emailRegex := regexp.MustCompile(`^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$`) + return emailRegex.MatchString(email) +} + +// IsValidMobile 检查给定的字符串是否是有效的中国大陆手机号 +func IsValidMobile(phone string) bool { + // 支持 13x, 14x, 15x, 16x, 17x, 18x, 19x 开头的号码 + phoneRegex := regexp.MustCompile(`^1[3-9]\d{9}$`) + return phoneRegex.MatchString(phone) +} diff --git a/web/src/views/admin/SysConfig.vue b/web/src/views/admin/SysConfig.vue index 7b6d3e3a..6261021f 100644 --- a/web/src/views/admin/SysConfig.vue +++ b/web/src/views/admin/SysConfig.vue @@ -400,6 +400,18 @@ + + +
+

有些版本升级的时候更新了数据库的结构,比如字段名字改了,需要把之前的字段的值转移到其他字段,这些无法通过简单的 SQL 语句可以实现的,需要手动写程序修正数据。

+ +

当前版本 v4.1.4 需要修正用户数据,增加了 mobile 和 email 字段,需要把之前用手机号或者邮箱注册的用户的 username 字段数据初始化到 mobile 或者 email 字段。另外,需要把订单的支付渠道从名字称修正为 key。

+ + 请注意:在修复数据前,请先备份好数据库,以免数据丢失! + +

立即修复

+
+
@@ -408,7 +420,7 @@ import {onMounted, reactive, ref} from "vue"; import {httpGet, httpPost} from "@/utils/http"; import Compressor from "compressorjs"; -import {ElMessage} from "element-plus"; +import {ElMessage, ElMessageBox} from "element-plus"; import {InfoFilled, UploadFilled,Select,CloseBold} from "@element-plus/icons-vue"; import MdEditor from "md-editor-v3"; import 'md-editor-v3/lib/style.css'; @@ -463,7 +475,7 @@ onMounted(() => { }) const fetchLicense = () => { - httpGet("/api/admin/config/get/license").then(res => { + httpGet("/api/admin/config/license").then(res => { license.value = res.data }).catch(e => { ElMessage.error("获取 License 失败:" + e.message) @@ -502,7 +514,7 @@ const active = () => { if (licenseKey.value === "") { return ElMessage.error("请输入授权码") } - httpPost("/api/admin/active", {license: licenseKey.value}).then(res => { + httpPost("/api/admin/config/active", {license: licenseKey.value}).then(res => { ElMessage.success("授权成功,机器编码为:" + res.data) fetchLicense() }).catch(e => { @@ -556,6 +568,25 @@ const onUploadImg = (files, callback) => { }) }; +const fixData = () => { + + ElMessageBox.confirm( + '在修复数据前,请先备份好数据库,以免数据丢失!是否继续操作?', + '警告', + { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning', + } + ).then(() => { + httpGet("/api/admin/config/fixData").then(() => { + ElMessage.success("数据修复成功") + }).catch(e => { + ElMessage.error("数据修复失败:" + e.message) + }) + }) +} + @@ -606,6 +637,10 @@ const onUploadImg = (files, callback) => { } + .text { + font-size 14px + } + .active-info { line-height 1.5 padding 10px 0 30px 0