diff --git a/kernel/api/icon.go b/kernel/api/icon.go
new file mode 100644
index 000000000..c2d25b06b
--- /dev/null
+++ b/kernel/api/icon.go
@@ -0,0 +1,453 @@
+// SiYuan - Refactor your thinking
+// Copyright (c) 2020-present, b3log.org
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+package api
+
+import (
+ "fmt"
+ "math"
+ "net/http"
+ "regexp"
+ "strings"
+ "time"
+
+ "github.com/gin-gonic/gin"
+ "github.com/siyuan-note/siyuan/kernel/util"
+)
+
+type ColorScheme struct {
+ Primary string
+ Secondary string
+}
+
+var colorSchemes = map[string]ColorScheme{
+ "red": {"#DD2F45", "#F4BEC3"},
+ "blue": {"#2bb7ff", "#0097e6"},
+ "yellow": {"#feca57", "#ff9f43"},
+ "green": {"#55efc4", "#19b37a"},
+ "purple": {"#a55eea", "#8854d0"},
+ "pink": {"#fd79a8", "#e05b8a"},
+ "orange": {"#ff7f50", "#ff6348"},
+ "grey": {"#576574", "#222f3e"},
+}
+
+func getColorScheme(color string) ColorScheme {
+ // 检查是否是预定义的颜色
+ if scheme, ok := colorSchemes[strings.ToLower(color)]; ok {
+ return scheme
+ }
+
+ // 如果不是预定义颜色,返回默认颜色
+ return colorSchemes["red"]
+}
+
+func getDynamicIcon(c *gin.Context) {
+ iconType := c.DefaultQuery("type", "1")
+ color := c.Query("color") // 不要预设默认值,不然type6返回星期就没法自动设置周末颜色了
+ date := c.Query("date")
+ lang := c.DefaultQuery("lang", util.Lang)
+ content := c.Query("content")
+ weekdayType := c.DefaultQuery("weekdayType", "1") // 设置星期几的格式,zh_CH {1:周日,2:周天, 3:星期日,4:星期天,}, en_US {1: Mon, 2: MON,3: Monday, 4. MONDAY,}
+
+ dateInfo := getDateInfo(date, lang, weekdayType)
+ var svg string
+ switch iconType {
+ case "1":
+ // Type 1: 显示年月日星期
+ svg = generateTypeOneSVG(color, lang, dateInfo)
+ case "2":
+ // Type 2: 显示年月日
+ svg = generateTypeTwoSVG(color, lang, dateInfo)
+ case "3":
+ // Type 3: 显示年月
+ svg = generateTypeThreeSVG(color, lang, dateInfo)
+ case "4":
+ // Type 4: 仅显示年
+ svg = generateTypeFourSVG(color, lang, dateInfo)
+ case "5":
+ // Type 5: 显示周数
+ svg = generateTypeFiveSVG(color, lang, dateInfo)
+ case "6":
+ // Type 6: 仅显示星期
+ svg = generateTypeSixSVG(color, lang, weekdayType, dateInfo)
+ case "7":
+ // Type 7: 倒数日
+ svg = generateTypeSevenSVG(color, lang, dateInfo)
+ case "8":
+ // Type 8: 文字图标
+ svg = generateTypeEightSVG(color, content)
+ default:
+ // 默认为Type 1
+ svg = generateTypeOneSVG(color, lang, dateInfo)
+ }
+
+ c.Header("Content-Type", "image/svg+xml")
+ c.Header("Cache-Control", "no-cache")
+ c.Header("Pragma", "no-cache")
+ c.String(http.StatusOK, svg)
+}
+
+func getDateInfo(dateStr string, lang string, weekdayType string) map[string]interface{} {
+ // 设置默认值
+ var date time.Time
+ var err error
+ if dateStr == "" {
+ date = time.Now()
+ } else {
+ date, err = time.Parse("2006-01-02", dateStr)
+ if err != nil {
+ date = time.Now()
+ }
+ }
+ // 获取年月日星期
+ year := date.Year()
+ month := date.Format("Jan")
+ day := date.Day()
+ var weekdayStr string
+ var weekdays []string
+
+ switch lang {
+ case "zh_CN":
+ month = date.Format("1月")
+ switch weekdayType {
+ case "1":
+ weekdays = []string{"周日", "周一", "周二", "周三", "周四", "周五", "周六"}
+ case "2":
+ weekdays = []string{"周天", "周一", "周二", "周三", "周四", "周五", "周六"}
+ case "3":
+ weekdays = []string{"星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"}
+ case "4":
+ weekdays = []string{"星期天", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"}
+ default:
+ weekdays = []string{"周日", "周一", "周二", "周三", "周四", "周五", "周六"}
+ }
+ weekdayStr = weekdays[date.Weekday()]
+ case "zh_CHT":
+ month = date.Format("1月")
+ switch weekdayType {
+ case "1":
+ weekdays = []string{"週日", "週一", "週二", "週三", "週四", "週五", "週六"}
+ case "2":
+ weekdays = []string{"週天", "週一", "週二", "週三", "週四", "週五", "週六"}
+ case "3":
+ weekdays = []string{"星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"}
+ case "4":
+ weekdays = []string{"星期天", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"}
+ default:
+ weekdays = []string{"週日", "週一", "週二", "週三", "週四", "週五", "週六"}
+ }
+ weekdayStr = weekdays[date.Weekday()]
+
+
+ default:
+ // 其他语言
+ switch weekdayType {
+ case "1":
+ weekdayStr = date.Format("Mon")
+ case "2":
+ weekdayStr = date.Format("Mon")
+ weekdayStr = strings.ToUpper(weekdayStr)
+ case "3":
+ weekdayStr = date.Format("Monday")
+ case "4":
+ weekdayStr = date.Format("Monday")
+ weekdayStr = strings.ToUpper(weekdayStr)
+ default:
+ weekdayStr = date.Format("Mon")
+ }
+ }
+ // Calculate week number
+ _, weekNum := date.ISOWeek()
+ weekNumStr := fmt.Sprintf("%dW", weekNum)
+
+ switch lang {
+ case "zh_CN":
+ weekNumStr = fmt.Sprintf("%d周", weekNum)
+ case "zh_CHT":
+ weekNumStr = fmt.Sprintf("%d週", weekNum)
+ }
+ // 判断是否是周末
+ isWeekend := date.Weekday() == time.Saturday || date.Weekday() == time.Sunday
+ // Calculate days until today
+ today := time.Now()
+ today = time.Date(today.Year(), today.Month(), today.Day(), 0, 0, 0, 0, today.Location())
+ date = time.Date(date.Year(), date.Month(), date.Day(), 0, 0, 0, 0, date.Location())
+ countDown := int(math.Floor(date.Sub(today).Hours() / 24)) // 注意最大返回106751天,go的时间戳最大值
+
+ return map[string]interface{}{
+ "year": year,
+ "month": month,
+ "day": day,
+ "date": fmt.Sprintf("%02d-%02d", date.Month(), date.Day()),
+ "weekday": weekdayStr,
+ "week": weekNumStr,
+ "countDown": countDown,
+ "isWeekend": isWeekend,
+ }
+}
+
+// Type 1: 显示年月日星期
+func generateTypeOneSVG(color string, lang string, dateInfo map[string]interface{}) string {
+ colorScheme := getColorScheme(color)
+
+ return fmt.Sprintf(`
+
+ `, colorScheme.Primary, dateInfo["month"], dateInfo["day"], dateInfo["weekday"], dateInfo["year"])
+}
+
+// Type 2: 显示年月日
+func generateTypeTwoSVG(color string, lang string, dateInfo map[string]interface{}) string {
+ colorScheme := getColorScheme(color)
+
+ return fmt.Sprintf(`
+
+ `, colorScheme.Primary, dateInfo["month"], dateInfo["day"], dateInfo["year"])
+}
+
+// Type 3: 显示年月
+func generateTypeThreeSVG(color string, lang string, dateInfo map[string]interface{}) string {
+ colorScheme := getColorScheme(color)
+
+ return fmt.Sprintf(`
+
+ `, colorScheme.Primary, colorScheme.Secondary, dateInfo["year"], dateInfo["month"])
+}
+
+// Type 4: 仅显示年
+func generateTypeFourSVG(color string, lang string, dateInfo map[string]interface{}) string {
+ colorScheme := getColorScheme(color)
+
+ return fmt.Sprintf(`
+
+ `, colorScheme.Primary, colorScheme.Secondary, dateInfo["year"])
+}
+
+// Type 5:: 显示周数
+func generateTypeFiveSVG(color string, lang string, dateInfo map[string]interface{}) string {
+ colorScheme := getColorScheme(color)
+
+ return fmt.Sprintf(`
+
+ `, colorScheme.Primary, colorScheme.Secondary, dateInfo["year"], dateInfo["week"])
+}
+
+// Type 6: 仅显示星期
+func generateTypeSixSVG(color string, lang string, weekdayType string, dateInfo map[string]interface{}) string {
+
+ weekday := dateInfo["weekday"].(string)
+ isWeekend := dateInfo["isWeekend"].(bool)
+
+ // 如果不设置颜色,周末默认使用蓝色,工作日默认使用红色
+ var colorScheme ColorScheme
+ if color == "" {
+ if isWeekend {
+ colorScheme = colorSchemes["blue"]
+ } else {
+ colorScheme = colorSchemes["red"]
+ }
+ } else {
+ colorScheme = getColorScheme(color)
+ }
+ // 动态变化字体大小
+ var fontSize float64
+ switch lang{
+ case "zh_CN", "zh_CHT":
+ fontSize = 460 / float64(len([]rune(weekday)))
+ default:
+ switch weekdayType {
+ case "1":
+ fontSize = 690 / float64(len([]rune(weekday)))
+ case "2":
+ fontSize = 600 / float64(len([]rune(weekday)))
+ case "3":
+ fontSize = 720 / float64(len([]rune(weekday)))
+ case "4":
+ fontSize = 630 / float64(len([]rune(weekday)))
+ default:
+ fontSize = 750 / float64(len([]rune(weekday)))
+ }
+ }
+
+ return fmt.Sprintf(`
+ `, colorScheme.Primary, colorScheme.Secondary, colorScheme.Primary, fontSize, weekday)
+}
+
+// Type7: 倒数日
+func generateTypeSevenSVG(color string, lang string, dateInfo map[string]interface{}) string {
+ colorScheme := getColorScheme(color)
+
+ diffDays := dateInfo["countDown"].(int)
+
+ var tipText, diffDaysText string
+
+ // 设置输出字符
+ if diffDays == 0 {
+ switch lang {
+ case "zh_CN":
+ tipText = "今天"
+ case "zh_CHT":
+ tipText = "今天"
+ default:
+ tipText = "Today"
+ }
+ diffDaysText = "--"
+ } else if diffDays > 0 {
+ switch lang {
+ case "zh_CN":
+ tipText = "还有"
+ case "zh_CHT":
+ tipText = "還有"
+ default:
+ tipText = "Left"
+ }
+ diffDaysText = fmt.Sprintf("%d", diffDays)
+ } else {
+ switch lang {
+ case "zh_CN":
+ tipText = "已过"
+ case "zh_CHT":
+ tipText = "已過"
+ default:
+ tipText = "Past"
+ }
+ diffDaysText = fmt.Sprintf("%d", int(math.Abs(float64(diffDays))))
+ }
+
+ dayStr := map[string]string{
+ "zh_CN": "天",
+ "zh_CHT": "天",
+ "default": "days",
+ }[lang]
+ if dayStr == "" {
+ dayStr = "days"
+ }
+
+ fontSize := 240.0
+ if len(diffDaysText) >= 6 {
+ fontSize = 130
+ } else if len(diffDaysText) == 5 {
+ fontSize = 140
+ } else if len(diffDaysText) == 4 {
+ fontSize = 190
+ }
+ return fmt.Sprintf(`
+ `, colorScheme.Primary, dateInfo["year"], dateInfo["date"], tipText, fontSize, diffDaysText, dayStr)
+}
+
+// Type 8: 文字图标
+func generateTypeEightSVG(color, content string) string {
+ colorScheme := getColorScheme(color)
+
+ isChinese := regexp.MustCompile(`[\p{Han}]`).MatchString(content)
+
+ var fontSize float64
+ switch {
+ case len([]rune(content)) == 1:
+ fontSize = 320
+ case len([]rune(content)) == 2:
+ fontSize = 240
+ case len([]rune(content)) == 3:
+ fontSize = 160
+ case len([]rune(content)) == 4:
+ fontSize = 120
+ case len([]rune(content)) == 5:
+ fontSize = 95
+ default:
+ if isChinese {
+ fontSize = 480 / float64(len([]rune(content)))
+ } else {
+ fontSize = 750 / float64(len([]rune(content)))
+ }
+ }
+
+ return fmt.Sprintf(`
+
+ `, colorScheme.Primary, fontSize, content)
+}
diff --git a/kernel/api/router.go b/kernel/api/router.go
index a315d5293..1956e0757 100644
--- a/kernel/api/router.go
+++ b/kernel/api/router.go
@@ -33,7 +33,8 @@ func ServeAPI(ginServer *gin.Engine) {
ginServer.Handle("POST", "/api/system/loginAuth", model.LoginAuth)
ginServer.Handle("POST", "/api/system/logoutAuth", model.LogoutAuth)
ginServer.Handle("GET", "/api/system/getCaptcha", model.GetCaptcha)
-
+ ginServer.Handle("GET", "/api/icon/getDynamicIcon", getDynamicIcon) // 添加动态图标路由
+
// 需要鉴权
ginServer.Handle("POST", "/api/system/getEmojiConf", model.CheckAuth, getEmojiConf)