// 一次性工具:把某个应用业务库 goods 表导出的 JSON 同步进 console 主库的 app_goods 表。 // 用法: go run ./cmd/syncgoods -dsn -file goods.json -app Voitrans-Test [-apply] package main import ( "encoding/json" "flag" "fmt" "os" "sort" "time" "yunyan/comm" "gorm.io/driver/postgres" "gorm.io/gorm" "gorm.io/gorm/logger" ) type srcGoods struct { Id string `json:"id"` Enable int `json:"enable"` Name string `json:"name"` Localname string `json:"localname"` Price int32 `json:"price"` Usagetype int32 `json:"usagetype"` Ainum int64 `json:"ainum"` Meetnum int64 `json:"meetnum"` Tradenum int64 `json:"tradenum"` Viptime int32 `json:"viptime"` } func main() { dsn := flag.String("dsn", "", "console 主库 postgres dsn") file := flag.String("file", "", "源 goods JSON 文件") app := flag.String("app", "", "目标应用名 app_goods.app_name") remark := flag.String("remark", "", "备注") apply := flag.Bool("apply", false, "真正写入(默认只做 dry-run 打印)") flag.Parse() if *dsn == "" || *file == "" || *app == "" { fmt.Println("缺少参数 -dsn/-file/-app") os.Exit(1) } buf, err := os.ReadFile(*file) if err != nil { panic(err) } var src []*srcGoods if err = json.Unmarshal(buf, &src); err != nil { panic(err) } sort.Slice(src, func(i, j int) bool { return src[i].Id < src[j].Id }) db, err := gorm.Open(postgres.Open(*dsn), &gorm.Config{Logger: logger.Default.LogMode(logger.Error)}) if err != nil { panic(err) } if err = db.Table(comm.TableAppGoods).AutoMigrate(&comm.AppGoods{}); err != nil { panic(err) } fmt.Printf("表 %s 就绪,源记录 %d 条,目标应用 %s,apply=%v\n", comm.TableAppGoods, len(src), *app, *apply) now := time.Now().Unix() var ins, upd int for i, g := range src { row := &comm.AppGoods{ AppName: *app, GoodsId: g.Id, Enable: g.Enable != 0, Name: g.Name, Price: g.Price, Usagetype: g.Usagetype, Ainum: g.Ainum, Meetnum: g.Meetnum, Tradenum: g.Tradenum, Viptime: g.Viptime, Localname: g.Localname, Sort: int32((i + 1) * 10), Remark: *remark, Createtime: now, Updatetime: now, } old := &comm.AppGoods{} err := db.Table(comm.TableAppGoods).Where("app_name=? AND goods_id=?", *app, g.Id).Take(old).Error switch { case err == gorm.ErrRecordNotFound: ins++ fmt.Printf(" + %-22s %-16s price=%d type=%d enable=%v\n", g.Id, g.Name, g.Price, g.Usagetype, row.Enable) if *apply { if err = db.Table(comm.TableAppGoods).Create(row).Error; err != nil { panic(err) } } case err != nil: panic(err) default: upd++ row.Id = old.Id row.Createtime = old.Createtime fmt.Printf(" ~ %-22s %-16s (覆盖已有 id=%d)\n", g.Id, g.Name, old.Id) if *apply { if err = db.Table(comm.TableAppGoods).Where("id=?", old.Id).Updates(row).Error; err != nil { panic(err) } } } } fmt.Printf("完成:新增 %d,更新 %d%s\n", ins, upd, map[bool]string{false: "(dry-run,未写库)", true: ""}[*apply]) }