/** 帖子类型 / 可见性 / 展示文案(前后端共用约定) */ export const POST_TYPES = [ { value: "discussion", label: "讨论", hint: "日常交流" }, { value: "question", label: "问答", hint: "提问求解" }, { value: "poll", label: "投票", hint: "收集选项意见" }, { value: "bounty", label: "悬赏", hint: "积分托管求解" }, { value: "lottery", label: "抽奖", hint: "评论参与开奖" }, ] as const; export type PostTypeValue = (typeof POST_TYPES)[number]["value"]; export const CONTENT_ACCESS = [ { value: "public", label: "公开" }, { value: "login", label: "登录可见" }, { value: "reply", label: "回复可见" }, { value: "points", label: "积分可见" }, { value: "password", label: "密码可见" }, { value: "mixed", label: "含隐藏内容" }, ] as const; export type ContentAccessValue = (typeof CONTENT_ACCESS)[number]["value"]; export const BOUNTY_EXPIRE_DAYS = [3, 7, 14, 30] as const; export const LOTTERY_EXPIRE_DAYS = [1, 3, 7, 14] as const; export const POLL_EXPIRE_DAYS = [1, 3, 7, 14] as const; export function normalizePostType(t?: string): PostTypeValue { if (!t) return "discussion"; if (POST_TYPES.some((x) => x.value === t)) return t as PostTypeValue; return "discussion"; } export function postTypeLabel(t?: string): string { const n = normalizePostType(t); return POST_TYPES.find((x) => x.value === n)?.label || "讨论"; } export function contentAccessLabel(a?: string): string { const hit = CONTENT_ACCESS.find((x) => x.value === a); return hit?.label || "公开"; } /** 列表 type_status → 徽章文案 */ export function typeStatusLabel(postType?: string, typeStatus?: string): string { const pt = normalizePostType(postType); const s = (typeStatus || "").toLowerCase(); switch (pt) { case "question": return s === "solved" ? "已解决" : "未解决"; case "poll": return s === "closed" ? "已结束" : "进行中"; case "bounty": if (s === "solved") return "已采纳"; if (s === "expired") return "已过期"; return "进行中"; case "lottery": if (s === "drawn") return "已开奖"; if (s === "closed") return "已截止"; return "进行中"; default: return ""; } } /** 状态徽章 CSS class(浅色区分) */ export function typeStatusClass(postType?: string, typeStatus?: string): string { const pt = normalizePostType(postType); const s = (typeStatus || "").toLowerCase(); let kind = "open"; switch (pt) { case "question": kind = s === "solved" ? "solved" : "unsolved"; break; case "poll": kind = s === "closed" ? "closed" : "open"; break; case "bounty": if (s === "solved") kind = "solved"; // 已过期:与投票「已结束」同色(灰胶囊,标识已到期) else if (s === "expired") kind = "closed"; else kind = "open"; break; case "lottery": // 已开奖 / 已截止:与投票「已结束」同色(灰胶囊) if (s === "drawn" || s === "closed") kind = "closed"; else kind = "open"; break; default: return ""; } return `badge-status badge-status-${kind}`; }