package handler import ( "strconv" "strings" "time" ) // 内联 SVG:path 对齐 lucide-react@1.18(由 scripts/extract-lucide-paths.mjs 抽取) func ssrSVG(size int, paths ...string) string { return ssrSVGWithClass(size, "", paths...) } func ssrSVGWithClass(size int, className string, paths ...string) string { var b strings.Builder b.WriteString(``) return b.String() } func ssrIconSearch() string { return ssrSVGWithClass(16, "header-search-icon", ``, ``, ) } func ssrIconSliders() string { return ssrSVG(15, ``, ``, ``, ``, ``, ``, ``, ``, ``, ) } func ssrIconPlus() string { return ssrSVG(16, ``, ``, ) } func ssrIconMoon() string { return ssrSVG(18, ``, ) } func ssrIconSun() string { return ssrSVG(18, ``, ``, ``, ``, ``, ``, ``, ``, ``, ) } func ssrIconMail() string { return ssrSVG(18, ``, ``, ) } func ssrIconHome() string { return ssrSVG(18, ``, ``, ) } func ssrIconStar() string { return ssrSVG(18, ``, ) } func ssrIconFolderGit() string { return ssrSVG(18, ``, ``, ``, ``, ) } func ssrIconLink2() string { return ssrSVG(18, ``, ``, ``, ) } func ssrWidgetIconLink2() string { return ssrSVGWithClass(15, "widget-card-icon widget-card-icon--links", ``, ``, ``, ) } func ssrIconEarth() string { return ssrSVG(18, ``, ``, ``, ``, ) } func ssrWidgetIconEarth() string { return ssrSVGWithClass(15, "widget-card-icon widget-card-icon--showcase", ``, ``, ``, ``, ) } func ssrIconFileText() string { return ssrSVG(18, ``, ``, ``, ``, ``, ) } func ssrIconLayoutDashboard() string { return ssrSVG(18, ``, ``, ``, ``, ) } func ssrIconMessageCircle() string { return ssrSVG(16, ``, ) } func ssrWidgetIconMessageCircle() string { return ssrSVGWithClass(15, "widget-card-icon widget-card-icon--notice", ``, ) } func ssrIconClock() string { return ssrSVG(16, ``, ``, ) } func ssrIconBadgeCheck() string { return ssrSVG(16, ``, ``, ) } func ssrIconTags() string { return ssrSVG(16, ``, ``, ``, ) } func ssrWidgetIconTags() string { return ssrSVGWithClass(15, "widget-card-icon widget-card-icon--tags", ``, ``, ``, ) } func ssrIconUserPlus() string { return ssrSVG(16, ``, ``, ``, ``, ) } func ssrWidgetIconUserPlus() string { return ssrSVGWithClass(15, "widget-card-icon widget-card-icon--users", ``, ``, ``, ``, ) } func ssrIconCalendarCheck() string { return ssrSVG(18, ``, ``, ``, ``, ``, ) } func ssrIconCheck() string { return ssrSVG(18, ``, ) } func ssrIconGift() string { return ssrSVG(15, ``, ``, ``, ``, ) } func ssrIconPanelRight() string { return ssrSVG(18, ``, ``, ) } // 板块图标 path(key 对齐 BOARD_ICON_OPTIONS / AllowedBoardIcons) var ssrBoardIconInner = map[string]string{ "code-2": ``, "coffee": ``, "help-circle": ``, "message-square": ``, "lightbulb": ``, "book-open": ``, "gamepad-2": ``, "palette": ``, "music": ``, "camera": ``, "heart": ``, "zap": ``, "globe": ``, "users": ``, "briefcase": ``, "graduation-cap": ``, "shopping-bag": ``, "map-pin": ``, "megaphone": ``, "flame": ``, "star": ``, "folder": ``, "wrench": ``, "cpu": ``, } // 与前端 DEFAULT_ICONS 顺序一致(按 themeIndex 回退) var ssrBoardDefaultIcons = []string{ "code-2", "coffee", "help-circle", "message-square", "lightbulb", "book-open", "gamepad-2", "palette", } // ssrBoardIconSVG 输出板块 Lucide 图标;class 打在 svg 上(与 React BoardIconDisplay 一致) func ssrBoardIconSVG(icon string, themeIndex int, className string) string { key := strings.TrimSpace(strings.ToLower(icon)) inner, ok := ssrBoardIconInner[key] if !ok || inner == "" { if themeIndex < 0 { themeIndex = 0 } key = ssrBoardDefaultIcons[themeIndex%len(ssrBoardDefaultIcons)] inner = ssrBoardIconInner[key] } return ssrSVGWithClass(18, className, inner) } // formatSSRRelativeTime 与前端 formatTime 同规则 func formatSSRRelativeTime(t time.Time) string { if t.IsZero() { return "" } now := time.Now() diffSec := now.Sub(t).Seconds() if diffSec < 0 { diffSec = 0 } if diffSec < 60 { return "刚刚" } if diffSec < 3600 { return strconv.Itoa(int(diffSec/60)) + "分钟前" } if diffSec < 86400 { return strconv.Itoa(int(diffSec/3600)) + "小时前" } diffDay := int(diffSec / 86400) if diffDay < 30 { return strconv.Itoa(diffDay) + "天前" } if t.Year() == now.Year() { return strconv.Itoa(int(t.Month())) + "月" + strconv.Itoa(t.Day()) + "日" } return strconv.Itoa(t.Year()) + "年" + strconv.Itoa(int(t.Month())) + "月" + strconv.Itoa(t.Day()) + "日" } // formatSSRShortDateTime 与前端 formatShortDateTime 同规则(MM-DD HH:mm) func formatSSRShortDateTime(t time.Time) string { if t.IsZero() { return "" } local := t.Local() pad := func(n int) string { if n < 10 { return "0" + strconv.Itoa(n) } return strconv.Itoa(n) } return pad(int(local.Month())) + "-" + pad(local.Day()) + " " + pad(local.Hour()) + ":" + pad(local.Minute()) }