package check import ( "context" "strconv" "strings" "bsm/full/module/base/initial/internal/impl" "bsm/full/module/base/initial/internal/models" pb "bsm/full/module/base/initial/pb" "git.apinb.com/bsm-sdk/core/errcode" "gorm.io/gorm" ) // 检查更新 func Updates(ctx context.Context, in *pb.CheckForUpdatesRequest) (reply *pb.CheckForUpdatesReply, err error) { // 输入验证 if in == nil || in.App == "" || in.Os == "" || in.Arch == "" || in.Version == "" { return nil, errcode.ErrInvalidArgument } var data models.InitialApps // 查询最新版本 err = impl.DBService.Where("app = ? AND os = ? AND arch = ?", in.App, in.Os, in.Arch). Order("pubdate DESC, id DESC"). First(&data).Error if err != nil { if err == gorm.ErrRecordNotFound { // 没有找到对应的应用版本 return &pb.CheckForUpdatesReply{ Identity: "0", Version: "0", }, nil } return nil, errcode.ErrDB } // 比较版本号,仅当服务端记录的版本高于客户端上报版本时才下发更新 if compareVersion(data.Version, in.Version) > 0 { // 有新版本可用 return &pb.CheckForUpdatesReply{ Identity: data.Identity, Version: data.Version, Summary: data.Summary, Files: data.Files, Pubdate: data.Pubdate.Format("2006-01-02 15:04:05"), }, nil } // 当前版本是最新的 return &pb.CheckForUpdatesReply{ Identity: data.Identity, Version: data.Version, }, nil } // compareVersion 比较两个版本号:a 高于 b 返回 1,a 低于 b 返回 -1,相同返回 0。 // 按 "." 分段转数字逐段比较,忽略前缀 "v" 与预发布后缀(如 -beta),非数字段按 0 处理。 func compareVersion(a, b string) int { segsA := versionSegments(a) segsB := versionSegments(b) length := len(segsA) if len(segsB) > length { length = len(segsB) } for i := 0; i < length; i++ { var numA, numB int if i < len(segsA) { numA = segsA[i] } if i < len(segsB) { numB = segsB[i] } if numA > numB { return 1 } if numA < numB { return -1 } } return 0 } // versionSegments 把版本号拆分为数字段 func versionSegments(version string) []int { version = strings.TrimPrefix(strings.TrimSpace(version), "v") // 去掉预发布与构建后缀,只比较主版本数字段 if idx := strings.IndexAny(version, "-+"); idx >= 0 { version = version[:idx] } parts := strings.Split(version, ".") segments := make([]int, 0, len(parts)) for _, part := range parts { num, err := strconv.Atoi(strings.TrimSpace(part)) if err != nil { num = 0 } segments = append(segments, num) } return segments }