// 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(` %s %d %s %d `, 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(` %s %d %d `, 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(` %d %s `, 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(` %d `, 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(` %d %s `, 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(` %s `, 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(` %d %s %s %s %s `, 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(` %s `, colorScheme.Primary, fontSize, content) }