新增: 星座运势+AI资讯+知识卡片+桌面设置窗口+秒显示开关

- 星座运势: 天聚数行API集成,5维进度条+幸运标签+今日概述
- AI资讯: 天聚数行API,图文布局5条展示,文件缓存2小时刷新
- 知识卡片: AI生成,关键字+提示词配置,30分钟刷新
- 桌面设置: 独立WebView2窗口,760x1350,含壁纸/布局/城市/颜色等配置
- 显示控制: 壁纸/时间/天气/星座/知识/AI资讯独立开关,秒显示开关
- 文件缓存: 星座运势+AI资讯缓存到本地,启动即显示上次数据
- initDone防抖: 防止设置窗口初始化触发卡片重载
This commit is contained in:
2026-05-26 04:34:00 +08:00
parent 2287e12e0d
commit 9fd3acede3
15 changed files with 2607 additions and 384 deletions

177
horoscope.go Normal file
View File

@@ -0,0 +1,177 @@
package main
import (
"encoding/json"
"fmt"
"log"
"os"
"path/filepath"
"strings"
"sync"
"time"
)
const tianapiKey = "da21ff665b09cbdcc29952a105aad97b"
const tianapiStarURL = "https://apis.tianapi.com/star/index"
var zodiacToSign = map[string]string{
"白羊座": "aries", "金牛座": "taurus", "双子座": "gemini", "巨蟹座": "cancer",
"狮子座": "leo", "处女座": "virgo", "天秤座": "libra", "天蝎座": "scorpio",
"射手座": "sagittarius", "摩羯座": "capricorn", "水瓶座": "aquarius", "双鱼座": "pisces",
}
var horoscopeMu sync.Mutex
type tianapiStarResp struct {
Code int `json:"code"`
Result struct {
List []struct {
Type string `json:"type"`
Content string `json:"content"`
} `json:"list"`
} `json:"result"`
}
type horoscopeInfo struct {
Zodiac string `json:"zodiac"`
Date string `json:"date"`
All string `json:"all"`
Love string `json:"love"`
Work string `json:"work"`
Money string `json:"money"`
Health string `json:"health"`
LuckyColor string `json:"luckyColor"`
LuckyNum string `json:"luckyNum"`
Noble string `json:"noble"`
Summary string `json:"summary"`
}
func horoscopeCachePath() string {
return filepath.Join(configDir(), "horoscope_cache.json")
}
func saveHoroscopeCache(info *horoscopeInfo) {
info.Date = time.Now().Format("2006-01-02")
data, _ := json.Marshal(info)
os.WriteFile(horoscopeCachePath(), data, 0644)
}
func loadHoroscopeCache() *horoscopeInfo {
data, err := os.ReadFile(horoscopeCachePath())
if err != nil {
return nil
}
var info horoscopeInfo
if json.Unmarshal(data, &info) != nil {
return nil
}
return &info
}
func isCacheToday(info *horoscopeInfo) bool {
return info != nil
}
func fetchHoroscope(zodiac string) *horoscopeInfo {
sign := zodiacToSign[zodiac]
if sign == "" {
sign = "sagittarius"
}
url := fmt.Sprintf("%s?key=%s&astro=%s", tianapiStarURL, tianapiKey, sign)
data, err := httpGet(url)
if err != nil {
log.Println("星座运势请求失败:", err)
return nil
}
var resp tianapiStarResp
if json.Unmarshal(data, &resp) != nil || resp.Code != 200 {
log.Println("星座运势解析失败:", string(data))
return nil
}
info := &horoscopeInfo{Zodiac: zodiac}
for _, item := range resp.Result.List {
switch item.Type {
case "综合指数":
info.All = strings.TrimSuffix(item.Content, "%")
case "爱情指数":
info.Love = strings.TrimSuffix(item.Content, "%")
case "工作指数":
info.Work = strings.TrimSuffix(item.Content, "%")
case "财运指数":
info.Money = strings.TrimSuffix(item.Content, "%")
case "健康指数":
info.Health = strings.TrimSuffix(item.Content, "%")
case "幸运颜色":
info.LuckyColor = item.Content
case "幸运数字":
info.LuckyNum = item.Content
case "贵人星座":
info.Noble = item.Content
case "今日概述":
info.Summary = strings.TrimSpace(item.Content)
}
}
log.Printf("星座运势已获取: %s", zodiac)
return info
}
func pushHoroscopeInfo(info *horoscopeInfo) {
jsonData, _ := json.Marshal(info)
log.Printf("星座运势JS: %s", string(jsonData[:min(len(jsonData), 120)]))
js := fmt.Sprintf(`if(window.updateHoroscopeFromGo) window.updateHoroscopeFromGo(%s)`, string(jsonData))
evalJS(js)
}
func pushHoroscope(zodiac string) {
info := fetchHoroscope(zodiac)
if info == nil {
log.Println("星座运势: fetchHoroscope返回nil")
return
}
saveHoroscopeCache(info)
pushHoroscopeInfo(info)
}
func horoscopeLoop() {
cfg := loadConfig()
if cfg.HideZodiac {
return
}
cached := loadHoroscopeCache()
if cached != nil {
pushHoroscopeInfo(cached)
}
time.Sleep(5 * time.Second)
cfg = loadConfig()
if cfg.HideZodiac {
return
}
today := time.Now().Format("2006-01-02")
if cached != nil && cached.Date == today && cached.Zodiac == cfg.Zodiac {
return
}
pushHoroscope(cfg.Zodiac)
ticker := time.NewTicker(24 * time.Hour)
for range ticker.C {
cfg := loadConfig()
if !cfg.HideZodiac {
pushHoroscope(cfg.Zodiac)
}
}
}
func triggerHoroscopeRefresh(zodiac string) {
go func() {
pushHoroscope(zodiac)
}()
}