package main import ( _ "embed" "encoding/base64" "encoding/json" "fmt" "log" "os" "path/filepath" "strings" "time" ) //go:embed web/overlay.html var overlayHTML string //go:embed web/themes/aurora.html var themeAurora string //go:embed web/themes/starfield.html var themeStarfield string //go:embed web/themes/gradient.html var themeGradient string //go:embed web/themes/particles.html var themeParticles string //go:embed web/themes/fractal.html var themeFractal string //go:embed web/themes/text.html var themeText string var themeMap = map[ThemeName]string{ ThemeAurora: themeAurora, ThemeStar: themeStarfield, ThemeGradient: themeGradient, ThemeParticle: themeParticles, ThemeFractal: themeFractal, ThemeText: themeText, } func buildWallpaperHTML(cfg *Config) string { var bg string if cfg.WallpaperType == WPTheme { if t, ok := themeMap[cfg.Theme]; ok { bg = t } else { bg = themeAurora } } else { bg = buildBgHTML(cfg) } if bg == "" { bg = themeAurora } bgWrapped := fmt.Sprintf(`
%s
`, bg) if cfg.HideWallpaper { bgWrapped = `` } initialData := map[string]interface{}{ "backgroundHtml": bgWrapped, "layout": string(cfg.Layout), "showSeconds": cfg.ShowSeconds, "userZodiac": cfg.Zodiac, "wallpaperVisible": !cfg.HideWallpaper, "photoFrameMode": cfg.PhotoFrameMode && cfg.PhotoDir != "", "cardVisibility": map[string]bool{ "time": !cfg.HideTime, "weather": !cfg.HideWeather, "zodiac": !cfg.HideZodiac, "knowledge": !cfg.HideKnowledge, "ainews": !cfg.HideAINews, "photo": !cfg.HidePhoto, }, } dataJSON, _ := json.Marshal(initialData) inject := fmt.Sprintf(``, string(dataJSON)) // 注入自定义文字 if cfg.WallpaperType == WPTheme && cfg.Theme == ThemeText && cfg.WallpaperText != "" { escaped, _ := json.Marshal(cfg.WallpaperText) inject += fmt.Sprintf(``, string(escaped)) } return strings.Replace(overlayHTML, "", inject+"", 1) } func imageToDataURI(path string) string { data, err := os.ReadFile(path) if err != nil { log.Println("读取图片失败:", err) return "" } ext := strings.ToLower(filepath.Ext(path)) mime := "image/jpeg" switch ext { case ".png": mime = "image/png" case ".gif": mime = "image/gif" case ".webp": mime = "image/webp" case ".bmp": mime = "image/bmp" } return fmt.Sprintf("data:%s;base64,%s", mime, base64.StdEncoding.EncodeToString(data)) } func reloadWallpaper() { if wv == nil || wvHwnd == 0 { return } cfg := loadConfig() // 非主题壁纸切换:仅替换 #bg-layer,不销毁卡片状态 if cfg.WallpaperType != WPTheme { updateBackground(cfg) return } // 主题切换需要 SetHtml(canvas+script),之后恢复卡片数据 html := buildWallpaperHTML(cfg) select { case htmlQueue <- html: default: } procPostMessageW.Call(wvHwnd, wmSetHtml, 0, 0) go reloadAllCards() } func buildBgHTML(cfg *Config) string { switch cfg.WallpaperType { case WPImage: if cfg.ImagePath != "" { src := imageToDataURI(cfg.ImagePath) if src != "" { return buildCoverImgHTML(src) } } case WPBing: if p := getCurrentBingPath(); p != "" { if _, err := os.Stat(p); err == nil { src := imageToDataURI(p) if src != "" { return buildCoverImgHTML(src) } } } case WPColor: if cfg.ColorGradient && cfg.Color2 != "" { return fmt.Sprintf(`
`, cfg.Color1, cfg.Color2) } return fmt.Sprintf(`
`, cfg.Color1) } return "" } const coverImgTpl = `` func buildCoverImgHTML(src string) string { return fmt.Sprintf(coverImgTpl, src) } func updateBackground(cfg *Config) { bg := buildBgHTML(cfg) if bg == "" { return } display := "" if cfg.HideWallpaper { display = ` style="display:none"` } html := fmt.Sprintf(`
%s
`, display, bg) // Update Vue reactive state via bridge evalJS(fmt.Sprintf(`if(window.__updateBackgroundHtml) window.__updateBackgroundHtml(%q);`, html)) // Fallback: direct DOM update for non-Vue contexts evalJS(fmt.Sprintf(`var el=document.getElementById('bg-layer'); if(el && !window.__updateBackgroundHtml){el.outerHTML=%q;}`, html)) } func reloadAllCards() { time.Sleep(800 * time.Millisecond) evalJS(fmt.Sprintf(`window.userZodiac = %q;`, loadConfig().Zodiac)) if cached := loadHoroscopeCache(); cached != nil { pushHoroscopeInfo(cached) } if cached := loadAINewsCache(); cached != nil { pushAINews(cached) } cfg := loadConfig() if cfg.KnowledgeKeyword != "" && !cfg.HideKnowledge { if cached := getRandomKnowledgeCard(cfg.KnowledgeKeyword); cached != "" { pushKnowledgeJSON(cached, cfg.KnowledgeKeyword) } } if city := getCurrentCity(); city.ID != "" { go fetchAndPushWeather(city) } if cfg.PhotoDir != "" && !cfg.HidePhoto { go func() { time.Sleep(500 * time.Millisecond) pushCurrentPhoto(cfg.PhotoInterval) }() } } func bingReloadImage() { if wv == nil || wvHwnd == 0 { return } p := getCurrentBingPath() if p == "" { return } src := imageToDataURI(p) if src == "" { return } evalJS(fmt.Sprintf(`var bg=document.querySelector('#bg-layer img'); if(bg) bg.src=%q;`, src)) }