poem.go 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. // ============================================================================
  2. // poem.go — 随机古诗
  3. //
  4. // 主窗口首个 Tab(笔记页)footer 内水平滚动显示一首随机古诗;
  5. // 数据来自 poetry.palemoky.com 的随机接口,颜色 / 字号 / 刷新间隔可配置。
  6. // ============================================================================
  7. package main
  8. import (
  9. "encoding/json"
  10. "fmt"
  11. "net/http"
  12. "strings"
  13. "time"
  14. )
  15. const (
  16. PoemAPIURL = "https://poetry.palemoky.com/api/poems/random" // 随机古诗接口
  17. DefaultPoemColor = "#c98a3a" // 默认文字颜色(深琥珀,暗底明显可读)
  18. DefaultPoemFontSize = 16 // 默认字号(px)
  19. DefaultPoemInterval = 60 // 默认随机换诗间隔(秒),0 表示不自动换
  20. DefaultPoemSpeed = 18 // 默认滚动一轮时长(秒)
  21. )
  22. // PoemConfig 古诗显示的配置
  23. type PoemConfig struct {
  24. Enabled bool `json:"enabled"` // 是否启用古诗显示
  25. Color string `json:"color"` // 文字颜色
  26. FontSize int `json:"fontSize"` // 字号(px)
  27. TTS bool `json:"tts"` // 允许 TTS 阅读(显示朗读按钮)
  28. Interval int `json:"interval"` // 自动换诗间隔(秒),0 表示不自动换
  29. Speed int `json:"speed"` // 滚动速度(秒/轮),即滚动一个文本周期所需秒数,越小越快
  30. }
  31. // PoemData 一首古诗的完整数据(从接口解析)
  32. type PoemData struct {
  33. Title string `json:"title"` // 题目
  34. Author string `json:"author"` // 作者
  35. Dynasty string `json:"dynasty"` // 朝代
  36. Content []string `json:"content"` // 每句诗(数组,按行显示)
  37. Type string `json:"type"` // 体裁,如 五言律诗
  38. }
  39. // poemAPIResponse 接口返回的外层结构
  40. type poemAPIResponse struct {
  41. Data struct {
  42. ID int `json:"id"`
  43. Title string `json:"title"`
  44. Content []string `json:"content"`
  45. Author struct {
  46. ID int `json:"id"`
  47. Name string `json:"name"`
  48. } `json:"author"`
  49. Dynasty struct {
  50. ID int `json:"id"`
  51. Name string `json:"name"`
  52. } `json:"dynasty"`
  53. Type struct {
  54. ID int `json:"id"`
  55. Name string `json:"name"`
  56. } `json:"type"`
  57. } `json:"data"`
  58. Lang string `json:"lang"`
  59. }
  60. // fetchRandomPoem 从接口拉取一首随机古诗;失败时返回错误
  61. func fetchRandomPoem() (PoemData, error) {
  62. client := &http.Client{Timeout: 10 * time.Second}
  63. resp, err := client.Get(PoemAPIURL)
  64. if err != nil {
  65. return PoemData{}, fmt.Errorf("请求古诗接口失败: %w", err)
  66. }
  67. defer resp.Body.Close()
  68. if resp.StatusCode != http.StatusOK {
  69. return PoemData{}, fmt.Errorf("古诗接口返回状态 %d", resp.StatusCode)
  70. }
  71. var out poemAPIResponse
  72. if err := json.NewDecoder(resp.Body).Decode(&out); err != nil {
  73. return PoemData{}, fmt.Errorf("解析古诗数据失败: %w", err)
  74. }
  75. p := PoemData{
  76. Title: strings.TrimSpace(out.Data.Title),
  77. Author: strings.TrimSpace(out.Data.Author.Name),
  78. Dynasty: strings.TrimSpace(out.Data.Dynasty.Name),
  79. Content: out.Data.Content,
  80. Type: strings.TrimSpace(out.Data.Type.Name),
  81. }
  82. if p.Title == "" && len(p.Content) == 0 {
  83. return PoemData{}, fmt.Errorf("古诗接口返回空数据")
  84. }
  85. return p, nil
  86. }
  87. // GetRandomPoem 返回一首随机古诗(供主窗口前端加载 / 手动刷新调用)
  88. func (s *SettingsService) GetRandomPoem() (PoemData, error) {
  89. return fetchRandomPoem()
  90. }
  91. // normalizePoemConfig 校正古诗配置:颜色默认、字号限制、间隔限制
  92. func normalizePoemConfig(cfg PoemConfig) PoemConfig {
  93. if strings.TrimSpace(cfg.Color) == "" {
  94. cfg.Color = DefaultPoemColor
  95. }
  96. if cfg.FontSize < 12 || cfg.FontSize > 48 {
  97. cfg.FontSize = DefaultPoemFontSize
  98. }
  99. if cfg.Interval < 0 || cfg.Interval > 3600 {
  100. cfg.Interval = DefaultPoemInterval
  101. }
  102. if cfg.Speed < 5 || cfg.Speed > 120 {
  103. cfg.Speed = DefaultPoemSpeed
  104. }
  105. return cfg
  106. }