后台可注入全站 CSS/JS(SSR 生效,CSS 可热换);发帖/编辑改为锁一屏工作室;经济看板增加存量健康度;主题令牌与弹层误关一并收紧。 Co-authored-by: Cursor <cursoragent@cursor.com>
94 lines
3.1 KiB
TypeScript
94 lines
3.1 KiB
TypeScript
/** 帖子类型 / 可见性 / 展示文案(前后端共用约定) */
|
||
|
||
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}`;
|
||
}
|