74 lines
2.8 KiB
TypeScript
74 lines
2.8 KiB
TypeScript
import type { BadgeTone } from "@/components/home/data";
|
|
|
|
/**
|
|
* 黄果黑料卡片 / 详情页公用视觉:琥珀色强调(区别于其它导航站的品红主题)。
|
|
* 卡片不做整块底色,封面 + 正文排版;hover 只给封面描边、标题变色。
|
|
*/
|
|
export const HL_ACCENT = "#FFB020";
|
|
|
|
export const HL_COVER =
|
|
"relative block overflow-hidden rounded-md bg-[#17161D] outline outline-1 -outline-offset-1 outline-white/5 transition-[outline-color] duration-300 group-hover:outline-[#FFB020]/80";
|
|
|
|
export const HL_COVER_IMG =
|
|
"absolute inset-0 h-full w-full object-cover transition-transform duration-500 ease-out group-hover:scale-[1.04]";
|
|
|
|
export const HL_TITLE_LINK = "transition-colors duration-200 hover:text-[#FFB020] group-hover:text-[#FFB020]";
|
|
|
|
const badgeText: Record<BadgeTone, string> = {
|
|
hot: "热播",
|
|
fresh: "新上架",
|
|
original: "独家",
|
|
};
|
|
|
|
/** 封面左上角琥珀角标(文字,不用图片角标) */
|
|
export function HlBadge({ tone, small = false }: { tone?: BadgeTone | null; small?: boolean }) {
|
|
if (!tone) return null;
|
|
return (
|
|
<span
|
|
className={`absolute top-0 left-0 z-[1] rounded-br-md bg-[#FFB020] font-semibold text-[#1A1206] ${
|
|
small ? "px-1.5 py-0.5 text-[10px] leading-[14px]" : "px-2 py-0.5 text-xs leading-[18px]"
|
|
}`}
|
|
>
|
|
{badgeText[tone]}
|
|
</span>
|
|
);
|
|
}
|
|
|
|
/** 接口时间 → YYYY-MM-DD;无效返回空串。优先直接截取,避免服务端 / 浏览器时区不同导致水合不一致 */
|
|
export function formatDay(raw?: string | null) {
|
|
const text = raw?.trim();
|
|
if (!text) return "";
|
|
const head = /^\d{4}-\d{2}-\d{2}/.exec(text);
|
|
if (head) return head[0];
|
|
const date = new Date(/^\d+$/.test(text) ? Number(text) : text);
|
|
if (Number.isNaN(date.getTime())) return "";
|
|
const pad = (value: number) => String(value).padStart(2, "0");
|
|
return `${date.getUTCFullYear()}-${pad(date.getUTCMonth() + 1)}-${pad(date.getUTCDate())}`;
|
|
}
|
|
|
|
/** 秒 → m:ss / h:mm:ss;无效返回空串 */
|
|
export function formatDuration(seconds?: number | null) {
|
|
const total = Math.floor(Number(seconds) || 0);
|
|
if (total <= 0) return "";
|
|
const h = Math.floor(total / 3600);
|
|
const m = Math.floor((total % 3600) / 60);
|
|
const s = total % 60;
|
|
const pad = (value: number) => String(value).padStart(2, "0");
|
|
return h ? `${h}:${pad(m)}:${pad(s)}` : `${m}:${pad(s)}`;
|
|
}
|
|
|
|
/** 卡片元信息里的小眼睛图标 */
|
|
export function EyeIcon({ className = "size-3.5" }: { className?: string }) {
|
|
return (
|
|
<svg viewBox="0 0 16 16" fill="none" className={className} aria-hidden="true">
|
|
<path
|
|
d="M1.5 8S4 3.5 8 3.5 14.5 8 14.5 8 12 12.5 8 12.5 1.5 8 1.5 8Z"
|
|
stroke="currentColor"
|
|
strokeWidth="1.3"
|
|
strokeLinejoin="round"
|
|
/>
|
|
<circle cx="8" cy="8" r="2" stroke="currentColor" strokeWidth="1.3" />
|
|
</svg>
|
|
);
|
|
}
|