package controller import ( "encoding/json" "fmt" "io/ioutil" "net/http" "os" "os/exec" "path" "path/filepath" "sort" "strconv" "strings" "time" "vamicro/extend/code" "vamicro/extend/util" "vamicro/version-control/models" "vamicro/version-control/routers" "vamicro/version-control/service" "basic.com/valib/bhomeclient.git" "basic.com/valib/c_bhomebus.git/proto/source/bhome_msg" "basic.com/valib/licence.git" "basic.com/valib/logger.git" "github.com/gin-gonic/gin" ) type ( VersionRouter struct { routers.Router } ) const ( basePath = "/version" manifest = "dist/bin/manifest.ini" zipDir = "dist/bin" ) var ( CheckVersion *VersionRouter Upgrade *VersionRouter UploadDist *VersionRouter SettingFetch *VersionRouter SettingPush *VersionRouter UpdateNotice *VersionRouter DelayNotice *VersionRouter PreUpLoad *VersionRouter UpgradePreUpLoad *VersionRouter RollBack *VersionRouter Authorization *VersionRouter GetSn *VersionRouter Qrcode *VersionRouter AuthorizationUpload *VersionRouter CancelAuthorization *VersionRouter CancelAuthorizationUpload *VersionRouter ShopMakeSmsCod *VersionRouter ShopCenterLogin *VersionRouter ShopCenterGetOrderList *VersionRouter AuthActiveByOrder *VersionRouter AutoBakShow *VersionRouter AutoBakConfSet *VersionRouter AutoBakRightNow *VersionRouter BackupListShow *VersionRouter BackupRecov *VersionRouter Ms *bhomeclient.MicroNode ) func init() { CheckVersion = &VersionRouter{ routers.Router{ Methods: []string{http.MethodGet, http.MethodPost}, Path: "check", Handles: []gin.HandlerFunc{versionCheckHandle}, }, } UploadDist = &VersionRouter{ routers.Router{ Methods: []string{http.MethodPost}, Path: "upload", Handles: []gin.HandlerFunc{uploadDistHandle}, }, } Upgrade = &VersionRouter{ routers.Router{ Methods: []string{http.MethodGet, http.MethodPost}, Path: "upgrade", Handles: []gin.HandlerFunc{upgradeHandle}, }, } SettingFetch = &VersionRouter{ routers.Router{ Methods: []string{http.MethodGet}, Path: "settings", Handles: []gin.HandlerFunc{settingFetchHandle}, }, } SettingPush = &VersionRouter{ routers.Router{ Methods: []string{http.MethodPost}, Path: "setting/update", Handles: []gin.HandlerFunc{settingPushHandle}, }, } UpdateNotice = &VersionRouter{ routers.Router{ Methods: []string{http.MethodGet}, Path: "notice", Handles: []gin.HandlerFunc{updateNoticeHandle}, }, } DelayNotice = &VersionRouter{ routers.Router{ Methods: []string{http.MethodPost}, Path: "notice/delay", Handles: []gin.HandlerFunc{delayNoticeHandle}, }, } PreUpLoad = &VersionRouter{ routers.Router{ Methods: []string{http.MethodPost}, Path: "upload/zip", Handles: []gin.HandlerFunc{preUploadDistHandle}, }, } UpgradePreUpLoad = &VersionRouter{ routers.Router{ Methods: []string{http.MethodGet, http.MethodPost}, Path: "upgrade/zip", Handles: []gin.HandlerFunc{upgradePreUploadHandle}, }, } RollBack = &VersionRouter{ routers.Router{ Methods: []string{http.MethodGet, http.MethodPost}, Path: "rollback", Handles: []gin.HandlerFunc{RollBackHandle}, }, } Authorization = &VersionRouter{ routers.Router{ Methods: []string{http.MethodGet, http.MethodPost}, Path: "authorization", Handles: []gin.HandlerFunc{AuthorizationHandle}, }, } AuthorizationUpload = &VersionRouter{ routers.Router{ Methods: []string{http.MethodGet, http.MethodPost}, Path: "authorization/upload", Handles: []gin.HandlerFunc{AuthorizationUploadHandle}, }, } GetSn = &VersionRouter{ routers.Router{ Methods: []string{http.MethodGet, http.MethodPost}, Path: "sn", Handles: []gin.HandlerFunc{GetSnHandle}, }, } Qrcode = &VersionRouter{ routers.Router{ Methods: []string{http.MethodGet, http.MethodPost}, Path: "offline/qrcode", Handles: []gin.HandlerFunc{QrcodeHandle}, }, } CancelAuthorization = &VersionRouter{ routers.Router{ Methods: []string{http.MethodGet, http.MethodPost}, Path: "cancelAuthorization", Handles: []gin.HandlerFunc{CancelAuthorizationHandle}, }, } CancelAuthorizationUpload = &VersionRouter{ routers.Router{ Methods: []string{http.MethodGet, http.MethodPost}, Path: "cancelAuthorization/upload", Handles: []gin.HandlerFunc{CancelAuthorizationUploadHandle}, }, } ShopMakeSmsCod = &VersionRouter{ routers.Router{ Methods: []string{http.MethodGet}, Path: "auth/shop/smsCode", Handles: []gin.HandlerFunc{shopMakSmsHandle}, }, } ShopCenterLogin = &VersionRouter{ routers.Router{ Methods: []string{http.MethodPost}, Path: "auth/shop/login", Handles: []gin.HandlerFunc{shopCenterLoginHandle}, }, } ShopCenterGetOrderList = &VersionRouter{ routers.Router{ Methods: []string{http.MethodPost}, Path: "auth/shop/getOrderList", Handles: []gin.HandlerFunc{shopCenterGetOrderListHandle}, }, } AuthActiveByOrder = &VersionRouter{ routers.Router{ Methods: []string{http.MethodPost}, Path: "auth/shop/activeByOrder", Handles: []gin.HandlerFunc{authActiveByOrderHandle}, }, } AutoBakShow = &VersionRouter{ routers.Router{ Methods: []string{http.MethodGet}, Path: "autoBak/config", Handles: []gin.HandlerFunc{ShowAutoBakConf}, }, } AutoBakConfSet = &VersionRouter{ routers.Router{ Methods: []string{http.MethodPost}, Path: "autoBak/saveConf", Handles: []gin.HandlerFunc{SaveAutoBakConf}, }, } AutoBakRightNow = &VersionRouter{ routers.Router{ Methods: []string{http.MethodPost}, Path: "autoBak/backupRN", Handles: []gin.HandlerFunc{BackupRN}, }, } BackupListShow = &VersionRouter{ routers.Router{ Methods: []string{http.MethodGet}, Path: "autoBak/list", Handles: []gin.HandlerFunc{BackupList}, }, } BackupRecov = &VersionRouter{ routers.Router{ Methods: []string{http.MethodPost}, Path: "autoBak/recover", Handles: []gin.HandlerFunc{BackupRecover}, }, } } func (r *VersionRouter) GetPath() string { return path.Join(basePath, r.Path) } //在系统配置app中,给页面调用,判断提醒有没有程序是否需要升级 func versionCheckHandle(c *gin.Context) { _, version, intro := service.CheckVersion() curVersion := service.GetCurVersion() //curEnv, _ := service.GetRunVersionEnv() //hasNewVersion := len(programs) > 0 hasNewVersion := version != curVersion if version == "" { hasNewVersion = false version = curVersion } c.JSON(http.StatusOK, gin.H{ "code": 200, "msg": "ok", "data": map[string]interface{}{ "hasNewVersion": hasNewVersion, "newVersion": version, "newVersionInfo": intro, "curVersion": curVersion, "curVersionPath": curVersion, }, }) } func preUploadDistHandle(c *gin.Context) { file, err := c.FormFile("archive") if nil != err { c.JSON(http.StatusBadRequest, gin.H{ "code": http.StatusBadRequest, "msg": err.Error(), "data": []*models.Program{}, }) logger.Error("uploadDistHandle upload field is not filled with a file, err:", err.Error()) return } UpgradePath := service.GetPreUploadPath() err = os.RemoveAll(UpgradePath) if nil == err { _ = os.MkdirAll(UpgradePath, 0777) } else { c.JSON(http.StatusInternalServerError, gin.H{ "code": http.StatusInternalServerError, "msg": err.Error(), "data": []*models.Program{}, }) logger.Error("uploadDistHandle remove pre upload path failed, err:", err.Error()) return } fileMd5 := service.GetMd5(file.Filename) + ".tgz" if err = c.SaveUploadedFile(file, path.Join(UpgradePath, fileMd5)); err != nil { c.JSON(http.StatusInternalServerError, gin.H{ "code": http.StatusInternalServerError, "msg": err.Error(), "data": []*models.Program{}, }) logger.Error("uploadDistHandle save file failed, err:", err.Error()) return } logger.Info("uploadDistHandle saved to temp file ok:", fileMd5) c.JSON(http.StatusOK, gin.H{ "code": http.StatusOK, "msg": "ok", "data": map[string]string{"id": fileMd5}, }) } func upgradePreUploadHandle(c *gin.Context) { upid := c.Query("id") if upid == "" { util.ResponseFormat(c, code.RequestParamError, "id不能为空") return } UpgradePath := service.GetPreUploadPath() upZip := path.Join(UpgradePath, upid) if !util.FileExists(upZip) { c.JSON(http.StatusInternalServerError, gin.H{ "code": http.StatusInternalServerError, "msg": "升级包未找到!", "data": []*models.Program{}, }) logger.Error("upgradePreUploadHandle upload file not found:", upZip) return } logger.Info("开始升级!") apps, err := service.UpgradeViaZip(upZip) logger.Info("系统升级完成!!") if nil != err { c.JSON(http.StatusOK, gin.H{ "code": http.StatusOK, "msg": err.Error(), "data": apps, }) } else { c.JSON(http.StatusOK, gin.H{ "code": http.StatusOK, "msg": "ok", "data": apps, }) killApp(apps) } } //在离线的情况,使用tgz包直接在内网上传离线安装包 func uploadDistHandle(c *gin.Context) { file, err := c.FormFile("archive") if nil != err { c.JSON(http.StatusBadRequest, gin.H{ "code": http.StatusBadRequest, "msg": err.Error(), "data": []*models.Program{}, }) logger.Error("uploadDistHandle upload field is not filled with a file, err:", err.Error()) return } UpgradePath := service.GetPreUploadPath() tmpFile, err := ioutil.TempFile(UpgradePath, "dist-*.tgz") if nil != err { c.JSON(http.StatusInternalServerError, gin.H{ "code": http.StatusInternalServerError, "msg": err.Error(), "data": []*models.Program{}, }) logger.Error("uploadDistHandle create temp file failed, err:", err.Error()) return } defer func() { tmpFile.Close() os.Remove(tmpFile.Name()) }() if err = c.SaveUploadedFile(file, tmpFile.Name()); err != nil { c.JSON(http.StatusInternalServerError, gin.H{ "code": http.StatusInternalServerError, "msg": err.Error(), "data": []*models.Program{}, }) logger.Error("uploadDistHandle save file failed, err:", err.Error()) return } logger.Info("uploadDistHandle saved to temp file ok:", tmpFile.Name()) apps, err := service.UpgradeViaZip(tmpFile.Name()) if nil != err { c.JSON(http.StatusOK, gin.H{ "code": http.StatusOK, "msg": err.Error(), "data": apps, }) } else { c.JSON(http.StatusOK, gin.H{ "code": http.StatusOK, "msg": "ok", "data": apps, }) } } func upgradeHandle(c *gin.Context) { apps, err := service.OnlineUpgrade() if nil != err { c.JSON(http.StatusOK, gin.H{ "code": http.StatusOK, "msg": err.Error(), "data": apps, }) } else { c.JSON(http.StatusOK, gin.H{ "code": http.StatusOK, "msg": "ok", "data": apps, }) //_ = syscall.Kill(syscall.Getpid(), syscall.SIGINT) killApp(apps) } } func killApp(apps []*models.Program) { //循环杀死升级应用进程 versionControl := "" for _, app := range apps { if app.Name == "version-control" { versionControl = app.Name continue } if app.Type == "sys" || app.Type == "app" { command := "pkill " + app.Name result, err := execCommand(command) logger.Info("执行命令【", command, "】") logger.Info("执行结果【", result, "err:,", err, "】") } } if versionControl != "" { command := "pkill " + versionControl result, err := execCommand(command) logger.Info("执行命令【", command, "】") logger.Info("执行结果【", result, "\n err:,", err, "】") } } //执行命令 func execCommand(cmd string) ([]byte, error) { return exec.Command("/bin/bash", "-c", cmd).Output() } //获取配置 func settingFetchHandle(c *gin.Context) { var model models.SysSetting settings, err := model.GetAllSetting() if nil != err { c.JSON(http.StatusOK, gin.H{ "code": http.StatusOK, "msg": err.Error(), "data": settings, }) } else { c.JSON(http.StatusOK, gin.H{ "code": http.StatusOK, "msg": "ok", "data": settings, }) } } //更新配置 func settingPushHandle(c *gin.Context) { name := c.PostForm("name") value := c.PostForm("value") setting := models.SysSetting{Name: name, Value: value} err := setting.SaveSetting(true) if nil != err { c.JSON(http.StatusOK, gin.H{ "code": http.StatusOK, "msg": err.Error(), "data": []interface{}{}, }) } else { data, _ := json.Marshal(setting) var nodes []bhome_msg.BHAddress nodes = append(nodes, bhome_msg.BHAddress{}) go Ms.PublishNetTimeout(nodes, service.SysUpdateConfigTopic, data, 10) c.JSON(http.StatusOK, gin.H{ "code": http.StatusOK, "msg": "ok", "data": []interface{}{}, }) } } func updateNoticeHandle(c *gin.Context) { notice := service.GetUpdateNotice() uid, ok := c.Get("uid") if ok { LastNoticeTime, ok := notice.NoticeUser[uid.(string)] if ok { notice.LastNoticeTime = int64(LastNoticeTime) } } c.JSON(http.StatusOK, gin.H{ "code": http.StatusOK, "msg": "ok", "data": notice, }) } func delayNoticeHandle(c *gin.Context) { delaySecond := c.PostForm("delaySecond") second, err := strconv.Atoi(delaySecond) if nil == err { uid, ok := c.Get("uid") if ok { notice := service.DelayNotice(uid.(string), second) c.JSON(http.StatusOK, gin.H{ "code": http.StatusOK, "msg": "ok", "data": notice, }) } else { c.JSON(http.StatusOK, gin.H{ "code": http.StatusOK, "msg": "未找到用户", "data": []interface{}{}, }) } } else { c.JSON(http.StatusOK, gin.H{ "code": http.StatusOK, "msg": "参数错误", "data": []interface{}{}, }) } } func RollBackHandle(c *gin.Context) { version := c.PostForm("version") err := service.Rollback(version) if nil == err { c.JSON(http.StatusOK, gin.H{ "code": http.StatusOK, "msg": "ok", "data": []interface{}{}, }) } else { c.JSON(http.StatusOK, gin.H{ "code": http.StatusOK, "msg": "回滚失败," + err.Error(), "data": []interface{}{}, }) } } func sn() map[string]interface{} { data := make(map[string]interface{}, 0) sn := util.GetSn() data["sn"] = sn auth := util.GetAuthorization() data["expireTime"] = "" authInfo, err := util.GetAuthorizationInfo(auth) //logger.Debug("授权信息:", authInfo, err, licence.GetMachineCode()) if err == nil && authInfo.MachineCode == licence.GetMachineCode() { expireUt := time.Unix(authInfo.ExpirationTime, 0) expireTimeStr := expireUt.Format("2006-01-02 15:04:05") data["expireTime"] = expireTimeStr data["expire"] = false if authInfo.ActivateCode != "" { data["sn"] = authInfo.ActivateCode } if authInfo.DevCount == -1 { //试用版 data["sn"] = "" } if time.Now().Sub(expireUt) > 0 { data["expire"] = true data["sn"] = "" } if data["sn"] != "" { data["authorization"] = auth } data["edition"] = authInfo.Edition data["installTime"] = authInfo.InstallTime if authInfo.Edition == "" || authInfo.InstallTime == "" { if eii, err := util.GetEdtionSetFromIns(); err == nil { if authInfo.Edition == "" { data["edition"] = eii.Edition } if authInfo.InstallTime == "" { data["installTime"] = eii.InstallTime } } } } else { //测试版 eii, err := util.GetEdtionSetFromIns() if err == nil { insT, _ := time.ParseInLocation("2006-01-02 15:04:05", eii.InstallTime, time.Local) if eii.OrderAuth != nil && eii.OrderAuth.ProductId != "" && eii.OrderAuth.OrderId != "" { data["sn"] = "" expireT := insT.AddDate(eii.OrderAuth.ServeYear, 0, 0) data["expireTime"] = expireT.Format("2006-01-02 15:04:05") if time.Now().Sub(expireT) > 0 { data["expire"] = true } else { data["expire"] = false } } else { data["sn"] = "" expireT := insT.AddDate(0, 0, eii.Setting.TrialDays) data["expireTime"] = expireT.Format("2006-01-02 15:04:05") if time.Now().Sub(expireT) > 0 { data["expire"] = true } else { data["expire"] = false } } data["edition"] = eii.Edition data["installTime"] = eii.InstallTime } else { logger.Error("Install info missing") data["sn"] = "" data["authorization"] = "" data["expire"] = true data["edition"] = "trial" data["installTime"] = "" } } data["q"] = service.GetQ() return data } func GetSnHandle(c *gin.Context) { data := sn() /* set := logc.RuleServerPushLog{} set.TaskName = "Test" set.Type = 0 set.Info = "111222111" uuid, _ := uuid.GenerateUUID() set.ID = uuid data2, _ := json.Marshal(set) var nodes []bhome_msg.BHAddress nodes = append(nodes, bhome_msg.BHAddress{}) go Ms.PublishNetTimeout(nodes, "ruleServerLogSaveTopic", data2, 10)*/ c.JSON(http.StatusOK, gin.H{ "code": http.StatusOK, "msg": "ok", "data": data, }) } func QrcodeHandle(c *gin.Context) { png, url, err := service.GenQRCode() if nil == err { c.Header("content-disposition", `attachment; filename=qrcode.png`) c.Header("qrcode-url", url) c.Data(200, "image/png", png) return } logger.Error("QrcodeHandle err!!!") c.JSON(http.StatusInternalServerError, gin.H{ "code": http.StatusBadRequest, "msg": "生成二维码失败", "data": "", }) } func AuthorizationUploadHandle(c *gin.Context) { codeF, err := c.FormFile("code") //就是商城中生成的产品密钥订单下载的文件 if nil != err { c.JSON(http.StatusBadRequest, gin.H{ "code": http.StatusBadRequest, "msg": err.Error(), "data": []*models.Program{}, }) logger.Error("AuthorizationUploadHandle upload field is not filled with a file, err:", err.Error()) return } F, err := codeF.Open() if nil != err { c.JSON(http.StatusBadRequest, gin.H{ "code": http.StatusBadRequest, "msg": err.Error(), "data": []*models.Program{}, }) logger.Error("AuthorizationUploadHandle upload field is not filled with a file, err:", err.Error()) return } buffer := make([]byte, codeF.Size) _, err = F.Read(buffer) if nil != err { c.JSON(http.StatusBadRequest, gin.H{ "code": http.StatusBadRequest, "msg": err.Error(), "data": []*models.Program{}, }) logger.Error("AuthorizationUploadHandle upload field is not filled with a file, err:", err.Error()) return } code := string(buffer) if "" == code { c.JSON(http.StatusOK, gin.H{ "code": http.StatusBadRequest, "msg": "产品密钥不能为空", "data": []interface{}{}, }) return } _, err = service.Authorization(code, true) if nil == err || strings.Contains(err.Error(), "成功") { c.JSON(http.StatusOK, gin.H{ "code": http.StatusOK, "msg": "ok", "data": string(code), }) } else { c.JSON(http.StatusOK, gin.H{ "code": http.StatusBadRequest, "msg": "激活失败," + err.Error(), "data": []interface{}{}, }) } } func AuthorizationHandle(c *gin.Context) { code := c.PostForm("code") //产品密钥的内容,就是商城中生成的产品密钥订单下载的文件内容 if "" == code { c.JSON(http.StatusOK, gin.H{ "code": http.StatusBadRequest, "msg": "产品密钥不能为空", "data": []interface{}{}, }) return } _, err := service.Authorization(code, true) if nil == err || strings.Contains(err.Error(), "成功") { c.JSON(http.StatusOK, gin.H{ "code": http.StatusOK, "msg": "ok", "data": []interface{}{}, }) } else { c.JSON(http.StatusBadRequest, gin.H{ "code": http.StatusBadRequest, "msg": "激活失败," + err.Error(), "data": []interface{}{}, }) } } func CancelAuthorizationHandle(c *gin.Context) { q := c.PostForm("q") supperPasswd := c.PostForm("passwd") down := c.PostForm("down") err, authCode := service.CancelAuthorization(supperPasswd, q) if err != nil && !strings.Contains(err.Error(), "成功") { c.JSON(http.StatusOK, gin.H{ "code": http.StatusBadRequest, "msg": err.Error(), "data": []interface{}{}, }) } else { if "1" == down { c.Header("content-disposition", `attachment; filename=authorization.txt`) ///c.Header("qrcode-url", url) c.Data(200, "text/plain", []byte(authCode)) } else { c.JSON(http.StatusOK, gin.H{ "code": http.StatusOK, "msg": "ok", "data": authCode, }) } } } func CancelAuthorizationUploadHandle(c *gin.Context) { q, err := c.FormFile("q") supperPasswd := c.PostForm("passwd") down := c.PostForm("down") if nil != err { c.JSON(http.StatusBadRequest, gin.H{ "code": http.StatusBadRequest, "msg": err.Error(), "data": []*models.Program{}, }) logger.Error("AuthorizationUploadHandle upload field is not filled with a file, err:", err.Error()) return } F, err := q.Open() if nil != err { c.JSON(http.StatusBadRequest, gin.H{ "code": http.StatusBadRequest, "msg": err.Error(), "data": []*models.Program{}, }) logger.Error("AuthorizationUploadHandle upload field is not filled with a file, err:", err.Error()) return } buffer := make([]byte, q.Size) _, err = F.Read(buffer) if nil != err { c.JSON(http.StatusBadRequest, gin.H{ "code": http.StatusBadRequest, "msg": err.Error(), "data": []*models.Program{}, }) logger.Error("AuthorizationUploadHandle upload field is not filled with a file, err:", err.Error()) return } err, authinfo := service.CancelAuthorization(supperPasswd, string(buffer)) if nil == err { if "1" == down { c.Header("content-disposition", `attachment; filename=authorization.txt`) ///c.Header("qrcode-url", url) c.Data(200, "text/plain", []byte(authinfo)) } else { c.JSON(http.StatusOK, gin.H{ "code": http.StatusOK, "msg": "ok", "data": authinfo, }) } } else { c.JSON(http.StatusBadRequest, gin.H{ "code": http.StatusBadRequest, "msg": err.Error(), "data": []interface{}{}, }) } } func ShowAutoBakConf(c *gin.Context) { var ab models.AutoBackupConf i, e := ab.Select() if e == nil && i > 0 { c.JSON(http.StatusOK, gin.H{ "code": http.StatusOK, "msg": "查询成功", "data": ab, }) return } c.JSON(http.StatusOK, gin.H{ "code": http.StatusOK, "msg": "查询成功", "data": models.AutoBackupConf{ Dir: util.GetVamicroPath() + "/backup_auto", }, }) } func SaveAutoBakConf(c *gin.Context) { var reqBody models.AutoBackupConf err := c.BindJSON(&reqBody) if err != nil { c.JSON(http.StatusBadRequest, gin.H{ "code": http.StatusBadRequest, "msg": err.Error(), "data": []models.AutoBackupConf{}, }) return } fmt.Println("go here 1 ", reqBody) reqBody.Dir = util.GetVamicroPath() + "/backup_auto" var ab models.AutoBackupConf i, _ := ab.Select() if i > 0 { fmt.Println("go here 2 ", reqBody) if reqBody.Update() { c.JSON(http.StatusOK, gin.H{ "code": http.StatusOK, "msg": "更新成功", "data": reqBody, }) } else { c.JSON(http.StatusInternalServerError, gin.H{ "code": http.StatusInternalServerError, "msg": "更新失败", "data": nil, }) } } else { fmt.Println("go here 3 ") if reqBody.Insert() { fmt.Println("go here 4 ") c.JSON(http.StatusOK, gin.H{ "code": http.StatusOK, "msg": "保存成功", "data": reqBody, }) } else { c.JSON(http.StatusInternalServerError, gin.H{ "code": http.StatusInternalServerError, "msg": "保存失败", "data": nil, }) } } } //立即备份操作 func BackupRN(c *gin.Context) { var ab models.AutoBackupConf i, e := ab.Select() if i == 0 || e != nil { ab.Dir = util.GetVamicroPath() + "/backup_auto" } err := service.DoAutoBackup(&ab) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{ "code": http.StatusInternalServerError, "msg": "立即备份失败:" + err.Error(), "data": nil, }) return } c.JSON(http.StatusOK, gin.H{ "code": http.StatusOK, "msg": "立即备份成功", "data": nil, }) } //显示备份列表 func BackupList(c *gin.Context) { var ab models.AutoBackupConf i, e := ab.Select() if i == 0 || e != nil { ab.Dir = util.GetVamicroPath() + "/backup_auto/" } else { if !strings.HasSuffix(ab.Dir, "/") { ab.Dir = ab.Dir + "/" } } backList := make([]string, 0) err := filepath.Walk(ab.Dir, func(src string, f os.FileInfo, err error) error { if src == ab.Dir { return nil } if f.IsDir() { depth := strings.Count(src, "/") - strings.Count(ab.Dir, "/") if depth != 0 { return filepath.SkipDir } _, e := time.ParseInLocation("2006-01-02-15-04-05", f.Name(), time.Local) if e != nil { return e } backList = append(backList, f.Name()) } return nil }) if err != nil { logger.Error("filepath.Walk ab.dir err:", err) } sort.Sort(sort.Reverse(sort.StringSlice(backList))) //降序排序 c.JSON(http.StatusOK, gin.H{ "code": http.StatusOK, "msg": "查询成功", "data": backList, }) } //根据指定的还原节点进行还原操作 func BackupRecover(c *gin.Context) { bakDir := c.PostForm("bakDir") if bakDir == "" { c.JSON(http.StatusBadRequest, gin.H{ "code": http.StatusBadRequest, "msg": "参数有误,bakDir不能为空", "data": nil, }) return } var ab models.AutoBackupConf i, e := ab.Select() if i == 0 || e != nil { c.JSON(http.StatusInternalServerError, gin.H{ "code": http.StatusInternalServerError, "msg": "备份设置为空", "data": nil, }) return } fd := ab.Dir + "/" + bakDir if !util.DirExists(fd) { c.JSON(http.StatusInternalServerError, gin.H{ "code": http.StatusInternalServerError, "msg": "当前备份文件夹已不存在,请检查", "data": nil, }) return } //执行还原操作 err := service.DoBackupRecover(fd) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{ "code": http.StatusInternalServerError, "msg": "还原失败:" + err.Error(), "data": nil, }) } else { c.JSON(http.StatusOK, gin.H{ "code": http.StatusOK, "msg": "还原成功", "data": nil, }) } }