Fix learn 404, coin animation, full regions, and AI key errors.

Use numeric /learn/{num} routes, register Tailwind coin animations with方孔铜钱 UI, expand to 34 provinces, and surface missing OPENAI_API_KEY clearly.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-06-10 21:32:20 +08:00
parent 96b659fbe5
commit a487b17165
15 changed files with 931 additions and 159 deletions
@@ -6,29 +6,50 @@ import MarkdownContent from "@/components/learn/markdown-content";
import {
getGuaName,
getGuaNumber,
guaNumFromMark,
listGuaMarks,
markFromNum,
readLearnMarkdown,
stripFrontmatter,
} from "@/lib/content/zhouyi";
export async function generateStaticParams() {
async function resolveGuaMark(slug: string): Promise<string | null> {
const decoded = decodeURIComponent(slug);
if (/^\d{1,2}$/.test(decoded)) {
return markFromNum(decoded, "traditional");
}
const marks = await listGuaMarks("traditional");
return marks.map((guaMark) => ({ guaMark }));
if (marks.includes(decoded)) {
return decoded;
}
if (/^\d{2}\./.test(decoded)) {
return marks.find((m) => m === decoded || m.startsWith(decoded.split(".")[0] + ".")) ?? null;
}
return null;
}
export async function generateStaticParams() {
return Array.from({ length: 64 }, (_, i) => ({
slug: String(i + 1).padStart(2, "0"),
}));
}
export const dynamicParams = true;
export default async function GuaDetailPage({
params,
}: {
params: Promise<{ guaMark: string }>;
params: Promise<{ slug: string }>;
}) {
const { guaMark } = await params;
const marks = await listGuaMarks("traditional");
if (!marks.includes(guaMark)) {
const { slug } = await params;
const guaMark = await resolveGuaMark(slug);
if (!guaMark) {
notFound();
}
const raw = await readLearnMarkdown(guaMark, "traditional");
const content = stripFrontmatter(raw);
const num = guaNumFromMark(guaMark);
return (
<PageShell className="max-w-3xl px-4 py-8">
@@ -41,7 +62,7 @@ export default async function GuaDetailPage({
{getGuaNumber(guaMark)} · {getGuaName(guaMark)}
</div>
<MarkdownContent content={content} variant="traditional" />
<GuaFooter guaMark={guaMark} />
<GuaFooter guaMark={guaMark} guaNum={num} />
</PageShell>
);
}
@@ -6,24 +6,41 @@ import MarkdownContent from "@/components/learn/markdown-content";
import {
getGuaName,
getGuaNumber,
guaNumFromMark,
listGuaMarks,
markFromNum,
readLearnMarkdown,
stripFrontmatter,
} from "@/lib/content/zhouyi";
export async function generateStaticParams() {
async function resolveGuaMark(slug: string): Promise<string | null> {
const decoded = decodeURIComponent(slug);
if (/^\d{1,2}$/.test(decoded)) {
return markFromNum(decoded, "simplified");
}
const marks = await listGuaMarks("simplified");
return marks.map((guaMark) => ({ guaMark }));
if (marks.includes(decoded)) {
return decoded;
}
return null;
}
export async function generateStaticParams() {
return Array.from({ length: 64 }, (_, i) => ({
slug: String(i + 1).padStart(2, "0"),
}));
}
export const dynamicParams = true;
export default async function GuaOtherDetailPage({
params,
}: {
params: Promise<{ guaMark: string }>;
params: Promise<{ slug: string }>;
}) {
const { guaMark } = await params;
const marks = await listGuaMarks("simplified");
if (!marks.includes(guaMark)) {
const { slug } = await params;
const guaMark = await resolveGuaMark(slug);
if (!guaMark) {
notFound();
}
@@ -41,7 +58,7 @@ export default async function GuaOtherDetailPage({
{getGuaNumber(guaMark)} · {getGuaName(guaMark)}
</div>
<MarkdownContent content={content} variant="simplified" />
<GuaFooter guaMark={guaMark} />
<GuaFooter guaMark={guaMark} guaNum={guaNumFromMark(guaMark)} />
</PageShell>
);
}
+3 -3
View File
@@ -2,7 +2,7 @@ import Link from "next/link";
import PageShell from "@/components/page-shell";
import {
getGuaName,
getGuaNumber,
guaNumFromMark,
listGuaMarks,
} from "@/lib/content/zhouyi";
@@ -35,11 +35,11 @@ export default async function LearnOtherPage() {
{guaMarks.map((mark) => (
<tr key={mark} className="border-t">
<td className="px-4 py-2 font-mono text-muted-foreground">
{getGuaNumber(mark)}
{guaNumFromMark(mark)}
</td>
<td className="px-4 py-2">
<Link
href={`/learn/other/${encodeURIComponent(mark)}`}
href={`/learn/other/${guaNumFromMark(mark)}`}
className="text-primary underline-offset-4 hover:underline"
>
{getGuaName(mark)}
+3 -3
View File
@@ -2,7 +2,7 @@ import Link from "next/link";
import PageShell from "@/components/page-shell";
import {
getGuaName,
getGuaNumber,
guaNumFromMark,
listGuaMarks,
} from "@/lib/content/zhouyi";
@@ -35,11 +35,11 @@ export default async function LearnPage() {
{guaMarks.map((mark) => (
<tr key={mark} className="border-t">
<td className="px-4 py-2 font-mono text-muted-foreground">
{getGuaNumber(mark)}
{guaNumFromMark(mark)}
</td>
<td className="px-4 py-2">
<Link
href={`/learn/${encodeURIComponent(mark)}`}
href={`/learn/${guaNumFromMark(mark)}`}
className="text-primary underline-offset-4 hover:underline"
>
{getGuaName(mark)}