chore: sync local updates
This commit is contained in:
136
mengyaping-backend/cmd/importjson/main.go
Normal file
136
mengyaping-backend/cmd/importjson/main.go
Normal file
@@ -0,0 +1,136 @@
|
||||
// 将 data/*.json(站点与分组)导入 MySQL。建议空库首次使用,或加 -wipe 清空业务表后再导。
|
||||
//
|
||||
// go run ./cmd/importjson -data ./data -wipe
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"gorm.io/datatypes"
|
||||
"gorm.io/driver/mysql"
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/logger"
|
||||
|
||||
"mengyaping-backend/config"
|
||||
"mengyaping-backend/models"
|
||||
"mengyaping-backend/storage"
|
||||
)
|
||||
|
||||
func main() {
|
||||
dataDir := flag.String("data", "./data", "JSON 目录(websites.json、groups.json)")
|
||||
wipe := flag.Bool("wipe", false, "导入前 TRUNCATE 所有 monitor_* 表(慎用)")
|
||||
flag.Parse()
|
||||
|
||||
cfg := config.GetConfig()
|
||||
// 大批量 INSERT 时单条超过 200ms 会触发 GORM 默认「SLOW SQL」提示,易被误认为报错;导入工具改为静默 SQL 日志
|
||||
db, err := gorm.Open(mysql.Open(cfg.DatabaseDSN()), &gorm.Config{
|
||||
Logger: logger.Default.LogMode(logger.Silent),
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
if err := db.AutoMigrate(
|
||||
&storage.MonitorGroup{},
|
||||
&storage.MonitorWebsite{},
|
||||
&storage.MonitorWebsiteURL{},
|
||||
&storage.MonitorWebsiteGroup{},
|
||||
&storage.MonitorProbeLatest{},
|
||||
&storage.MonitorProbeHour{},
|
||||
&storage.MonitorProbeDay{},
|
||||
&storage.MonitorKV{},
|
||||
); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
if *wipe {
|
||||
_ = db.Exec("SET FOREIGN_KEY_CHECKS = 0").Error
|
||||
for _, tbl := range []string{
|
||||
"monitor_probe_latest",
|
||||
"monitor_probe_hour",
|
||||
"monitor_probe_day",
|
||||
"monitor_kv",
|
||||
"monitor_checks",
|
||||
"monitor_website_urls",
|
||||
"monitor_website_groups",
|
||||
"monitor_websites",
|
||||
"monitor_groups",
|
||||
} {
|
||||
_ = db.Exec("TRUNCATE TABLE " + tbl).Error
|
||||
}
|
||||
_ = db.Exec("SET FOREIGN_KEY_CHECKS = 1").Error
|
||||
log.Println("已清空 monitor_* 表")
|
||||
}
|
||||
|
||||
websitesPath := filepath.Join(*dataDir, "websites.json")
|
||||
raw, err := os.ReadFile(websitesPath)
|
||||
if err != nil {
|
||||
log.Fatalf("读取 websites.json: %v", err)
|
||||
}
|
||||
var websites []models.Website
|
||||
if err := json.Unmarshal(raw, &websites); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
groupsPath := filepath.Join(*dataDir, "groups.json")
|
||||
var fileGroups []models.Group
|
||||
if g, err := os.ReadFile(groupsPath); err == nil {
|
||||
_ = json.Unmarshal(g, &fileGroups)
|
||||
}
|
||||
if len(fileGroups) == 0 {
|
||||
fileGroups = models.DefaultGroups
|
||||
}
|
||||
for i, g := range fileGroups {
|
||||
if err := db.Create(&storage.MonitorGroup{
|
||||
ID: g.ID, Name: g.Name, SortOrder: i + 1,
|
||||
}).Error; err != nil {
|
||||
log.Printf("导入分组 %s: %v", g.ID, err)
|
||||
}
|
||||
}
|
||||
|
||||
for _, w := range websites {
|
||||
if len(w.Groups) == 0 && w.Group != "" {
|
||||
w.Groups = []string{w.Group}
|
||||
}
|
||||
row := &storage.MonitorWebsite{
|
||||
ID: w.ID,
|
||||
Name: w.Name,
|
||||
LegacyGroup: "",
|
||||
Favicon: w.Favicon,
|
||||
Title: w.Title,
|
||||
IPAddresses: datatypes.JSON(mustJSON(w.IPAddresses)),
|
||||
CreatedAt: w.CreatedAt,
|
||||
UpdatedAt: w.UpdatedAt,
|
||||
}
|
||||
if err := db.Create(row).Error; err != nil {
|
||||
log.Printf("网站 %s: %v", w.ID, err)
|
||||
continue
|
||||
}
|
||||
for i, u := range w.URLs {
|
||||
_ = db.Create(&storage.MonitorWebsiteURL{
|
||||
WebsiteID: w.ID, URLID: u.ID, URL: u.URL, Remark: u.Remark, SortOrder: i,
|
||||
})
|
||||
}
|
||||
for _, gid := range w.Groups {
|
||||
_ = db.Create(&storage.MonitorWebsiteGroup{WebsiteID: w.ID, GroupID: gid})
|
||||
}
|
||||
}
|
||||
fmt.Printf("已导入 %d 个网站\n", len(websites))
|
||||
log.Println("探测历史由运行时写入 monitor_probe_* 汇总表,不再从 records.json 导入")
|
||||
}
|
||||
|
||||
func mustJSON(v []string) []byte {
|
||||
if v == nil {
|
||||
return []byte("[]")
|
||||
}
|
||||
b, err := json.Marshal(v)
|
||||
if err != nil {
|
||||
return []byte("[]")
|
||||
}
|
||||
return b
|
||||
}
|
||||
Reference in New Issue
Block a user