78 lines
3.2 KiB
TypeScript
78 lines
3.2 KiB
TypeScript
"use client";
|
|
|
|
import { AppResource } from "@/lib/types";
|
|
import { useTrack } from "@/hooks/use-track";
|
|
import { buildChannelUrl } from "@/lib/marketing";
|
|
import { TRACKING_EVENTS } from "@/lib/tracking-events";
|
|
|
|
export function AppMetaInfo({ app }: { app: AppResource }) {
|
|
return (
|
|
<div className="grid grid-cols-2 gap-3 text-sm md:grid-cols-4">
|
|
<div className="panel-strong"><p className="text-xs text-slate-400">版本</p><p className="mt-1 font-semibold">{app.version}</p></div>
|
|
<div className="panel-strong"><p className="text-xs text-slate-400">大小</p><p className="mt-1 font-semibold">{app.size}</p></div>
|
|
<div className="panel-strong"><p className="text-xs text-slate-400">更新</p><p className="mt-1 font-semibold">{app.updatedAt}</p></div>
|
|
<div className="panel-strong"><p className="text-xs text-slate-400">上传</p><p className="mt-1 font-semibold">{app.uploadedAt}</p></div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export function DownloadButtons({ app }: { app: AppResource }) {
|
|
const { track } = useTrack();
|
|
return (
|
|
<div className="grid grid-cols-1 gap-2 sm:grid-cols-2 xl:grid-cols-4">
|
|
{app.channels.map((c) => (
|
|
<a
|
|
key={c.id}
|
|
href={buildChannelUrl(c.href, c.name, app.slug)}
|
|
onClick={() => track(TRACKING_EVENTS.downloadClick, { slug: app.slug, channel: c.name, sourceType: c.type, location: "detail" })}
|
|
className="panel-strong text-center text-sm transition hover:border-cyan-300/40 hover:bg-cyan-400/10"
|
|
>
|
|
<p className="font-medium">{c.name}</p>
|
|
{c.hint && <p className="mt-1 text-xs text-slate-400">{c.hint}</p>}
|
|
</a>
|
|
))}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export function VersionHistory({ app }: { app: AppResource }) {
|
|
return (
|
|
<div className="panel space-y-3">
|
|
<h3 className="text-base font-semibold">历史版本</h3>
|
|
{app.versionHistory.map((v) => (
|
|
<div key={v.version} className="flex items-center justify-between rounded-xl border border-white/10 bg-slate-950/20 p-3 text-sm">
|
|
<div><p>{v.version}</p><p className="text-xs text-slate-400">{v.updatedAt} · {v.size}</p></div>
|
|
<a href={v.downloadHref} className="pill pill-active">下载此版本</a>
|
|
</div>
|
|
))}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export function ChangelogTimeline({ app }: { app: AppResource }) {
|
|
return (
|
|
<div className="panel space-y-4">
|
|
<h3 className="text-base font-semibold">更新日志</h3>
|
|
{app.changelog.map((item) => (
|
|
<div key={item.date + item.title} className="relative border-l border-cyan-300/40 pl-4">
|
|
<span className="absolute -left-[5px] top-1 h-2.5 w-2.5 rounded-full bg-cyan-300" />
|
|
<p className="text-xs text-cyan-300">{item.date}</p>
|
|
<p className="font-medium">{item.title}</p>
|
|
<p className="text-sm text-slate-300">{item.description}</p>
|
|
</div>
|
|
))}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export function QRCodeSection() {
|
|
return (
|
|
<div className="panel text-center">
|
|
<div className="mx-auto grid h-40 w-40 place-items-center rounded-2xl border border-dashed border-cyan-300/40 bg-slate-900/60 text-xs text-slate-400">
|
|
二维码区域
|
|
</div>
|
|
<p className="mt-3 text-sm text-slate-300">关注公众号并发送关键词“下载”获取解锁码。</p>
|
|
</div>
|
|
);
|
|
}
|