Files
2026-05-16 19:03:32 +08:00

137 lines
3.5 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 将 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
}