Support ultrawide layout with equal columns and taiji branding.
Use 50/50 mode workspace columns, widen content to 1920px on fish screens, replace header logo with taiji icon, and add full-page taiji backdrop. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,9 +1,12 @@
|
||||
import React from "react";
|
||||
import { VERSION } from "@/lib/constant";
|
||||
import { APP_CONTAINER } from "@/lib/layout";
|
||||
|
||||
function Footer() {
|
||||
return (
|
||||
<footer className="mx-auto flex items-center gap-1 text-xs text-muted-foreground/80">
|
||||
<footer
|
||||
className={`${APP_CONTAINER} relative z-10 flex items-center justify-center gap-1 py-4 text-xs text-muted-foreground/80`}
|
||||
>
|
||||
<span className="italic">心诚则灵</span>
|
||||
<span className="text-muted-foreground/60">·</span>
|
||||
<span>知命阁 v{VERSION}</span>
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
"use client";
|
||||
import Link from "next/link";
|
||||
import { usePathname } from "next/navigation";
|
||||
import { ChatGPT } from "@/components/svg";
|
||||
import { TaijiIcon } from "@/components/svg/taiji";
|
||||
import { ModeToggle } from "@/components/mode-toggle";
|
||||
import { APP_CONTAINER } from "@/lib/layout";
|
||||
|
||||
const NAV_ITEMS = [
|
||||
{ href: "/learn", label: "易经学习" },
|
||||
@@ -34,11 +35,11 @@ function NavLink({ href, label }: { href: string; label: string }) {
|
||||
|
||||
export default function Header() {
|
||||
return (
|
||||
<header className="border-b border-border/40 bg-card/60 py-3 shadow-sm backdrop-blur-md">
|
||||
<div className="mx-auto flex w-full max-w-6xl flex-col gap-2 px-4 sm:flex-row sm:items-center sm:justify-between">
|
||||
<header className="relative z-10 border-b border-border/40 bg-card/70 py-3 shadow-sm backdrop-blur-md">
|
||||
<div className={`${APP_CONTAINER} flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between`}>
|
||||
<Link href="/" className="flex items-center justify-center gap-2 sm:justify-start">
|
||||
<ChatGPT />
|
||||
<span className="font-medium">知命阁</span>
|
||||
<TaijiIcon />
|
||||
<span className="font-medium tracking-wide">知命阁</span>
|
||||
</Link>
|
||||
<nav className="flex flex-wrap items-center justify-center gap-x-4 gap-y-1">
|
||||
{NAV_ITEMS.map((item) => (
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import { Sparkles } from "lucide-react";
|
||||
import { APP_CONTAINER } from "@/lib/layout";
|
||||
|
||||
export function ModeWorkspace({
|
||||
children,
|
||||
@@ -12,18 +13,20 @@ export function ModeWorkspace({
|
||||
aiTitle?: string;
|
||||
}) {
|
||||
return (
|
||||
<div className="mx-auto w-full max-w-6xl px-4 py-6 lg:py-8">
|
||||
<div className="grid gap-6 lg:grid-cols-[minmax(0,1fr)_minmax(280px,380px)] lg:items-start lg:gap-8">
|
||||
<div className="space-y-5">{children}</div>
|
||||
<aside className="lg:sticky lg:top-6">
|
||||
<div className="zen-card flex min-h-[320px] flex-col rounded-2xl border border-border/60 bg-card/90 shadow-md backdrop-blur-sm lg:min-h-[calc(100vh-8rem)]">
|
||||
<div className={`${APP_CONTAINER} py-6 lg:py-8`}>
|
||||
<div className="grid gap-6 lg:grid-cols-2 lg:items-stretch lg:gap-8 xl:gap-10">
|
||||
<div className="grid h-full min-h-0 auto-rows-fr gap-5 lg:min-h-[calc(100vh-9rem)]">
|
||||
{children}
|
||||
</div>
|
||||
<aside className="flex min-h-[320px] flex-col lg:min-h-[calc(100vh-9rem)]">
|
||||
<div className="zen-card flex min-h-0 flex-1 flex-col rounded-2xl border border-border/60 bg-card/90 shadow-md backdrop-blur-sm">
|
||||
<div className="flex items-center gap-2 border-b border-border/50 px-5 py-4">
|
||||
<Sparkles size={18} className="text-primary/80" />
|
||||
<h2 className="text-sm font-medium tracking-widest text-muted-foreground">
|
||||
{aiTitle}
|
||||
</h2>
|
||||
</div>
|
||||
<div className="flex flex-1 flex-col p-4 sm:p-5">{aiPanel}</div>
|
||||
<div className="flex min-h-0 flex-1 flex-col p-4 sm:p-5">{aiPanel}</div>
|
||||
</div>
|
||||
</aside>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
import { TaijiWatermark } from "@/components/svg/taiji";
|
||||
|
||||
/** 全页太极背景水印 */
|
||||
export default function TaijiBackdrop() {
|
||||
return (
|
||||
<div
|
||||
aria-hidden
|
||||
className="pointer-events-none fixed inset-0 -z-10 overflow-hidden bg-background/80"
|
||||
>
|
||||
<TaijiWatermark className="absolute left-1/2 top-1/2 h-[min(95vmin,1200px)] w-[min(95vmin,1200px)] -translate-x-1/2 -translate-y-1/2 opacity-90" />
|
||||
<TaijiWatermark className="absolute -right-[8%] top-[6%] h-[min(42vmin,520px)] w-[min(42vmin,520px)] opacity-45" />
|
||||
<TaijiWatermark className="absolute -left-[10%] bottom-[4%] h-[min(38vmin,460px)] w-[min(38vmin,460px)] opacity-40" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -109,7 +109,7 @@ export default function BaziForm() {
|
||||
/>
|
||||
}
|
||||
>
|
||||
<ZenCard title="出生 · 命局" subtitle="四柱排盘所需信息">
|
||||
<ZenCard title="出生 · 命局" subtitle="四柱排盘所需信息" className="flex h-full min-h-0 flex-col">
|
||||
<DateTimePicker
|
||||
label="出生日期 / 时间"
|
||||
date={date}
|
||||
@@ -148,7 +148,7 @@ export default function BaziForm() {
|
||||
/>
|
||||
</ZenCard>
|
||||
|
||||
<ZenCard title="问事 · 排盘" subtitle="所求与命盘结果">
|
||||
<ZenCard title="问事 · 排盘" subtitle="所求与命盘结果" className="flex h-full min-h-0 flex-col">
|
||||
<Textarea
|
||||
placeholder="事业、婚姻、健康等..."
|
||||
value={question}
|
||||
|
||||
@@ -156,7 +156,7 @@ export default function CombinedForm() {
|
||||
/>
|
||||
}
|
||||
>
|
||||
<ZenCard title="人和 · 生辰" subtitle="出生时空与地域">
|
||||
<ZenCard title="人和 · 生辰" subtitle="出生时空与地域" className="flex h-full min-h-0 flex-col">
|
||||
<DateTimePicker
|
||||
label="出生日期 / 时间"
|
||||
date={birthDate}
|
||||
@@ -195,7 +195,7 @@ export default function CombinedForm() {
|
||||
/>
|
||||
</ZenCard>
|
||||
|
||||
<ZenCard title="天时地利 · 问事" subtitle="当前时空与所求">
|
||||
<ZenCard title="天时地利 · 问事" subtitle="当前时空与所求" className="flex h-full min-h-0 flex-col">
|
||||
<RegionSelect
|
||||
label="当前所在地域"
|
||||
provinceCode={currentProvince}
|
||||
|
||||
@@ -117,7 +117,7 @@ export default function LiuyaoForm() {
|
||||
/>
|
||||
}
|
||||
>
|
||||
<ZenCard title="问事 · 心意" subtitle="所求何事,心诚则灵">
|
||||
<ZenCard title="问事 · 心意" subtitle="所求何事,心诚则灵" className="flex h-full min-h-0 flex-col">
|
||||
<Textarea
|
||||
placeholder="您想算点什么?"
|
||||
value={question}
|
||||
@@ -139,7 +139,7 @@ export default function LiuyaoForm() {
|
||||
</div>
|
||||
</ZenCard>
|
||||
|
||||
<ZenCard title="起卦 · 时空" subtitle="地域、时辰与六爻">
|
||||
<ZenCard title="起卦 · 时空" subtitle="地域、时辰与六爻" className="flex h-full min-h-0 flex-col">
|
||||
<RegionSelect
|
||||
label="起卦地域"
|
||||
provinceCode={provinceCode}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import Header from "@/components/header";
|
||||
import Footer from "@/components/footer";
|
||||
import TaijiBackdrop from "@/components/layout/taiji-backdrop";
|
||||
|
||||
export default function PageShell({
|
||||
children,
|
||||
@@ -9,11 +10,10 @@ export default function PageShell({
|
||||
className?: string;
|
||||
}) {
|
||||
return (
|
||||
<div className="flex min-h-screen flex-col">
|
||||
<div className="relative flex min-h-screen flex-col">
|
||||
<TaijiBackdrop />
|
||||
<Header />
|
||||
<div className={`mx-auto flex w-full flex-1 flex-col ${className}`}>
|
||||
{children}
|
||||
</div>
|
||||
<div className={`flex w-full flex-1 flex-col ${className}`}>{children}</div>
|
||||
<Footer />
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -2,6 +2,7 @@ import React, { useEffect, useRef, useState } from "react";
|
||||
import { RotateCw } from "lucide-react";
|
||||
import Markdown from "react-markdown";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { TaijiIcon } from "@/components/svg/taiji";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
function ResultAI({
|
||||
@@ -85,8 +86,8 @@ function ResultAI({
|
||||
<p className="text-sm text-muted-foreground">正在等待 AI 响应...</p>
|
||||
) : (
|
||||
<div className="flex h-full min-h-[200px] flex-col items-center justify-center text-center text-muted-foreground">
|
||||
<p className="text-4xl opacity-20">☯</p>
|
||||
<p className="mt-3 max-w-[200px] text-sm leading-relaxed">
|
||||
<TaijiIcon className="h-16 w-16 opacity-25" />
|
||||
<p className="mt-3 max-w-[220px] text-sm leading-relaxed">
|
||||
{emptyHint}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
import React from "react";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
const YANG = "fill-stone-100 dark:fill-stone-200";
|
||||
const YIN = "fill-stone-800 dark:fill-stone-900";
|
||||
|
||||
/** 太极阴阳鱼图标(页眉 Logo) */
|
||||
export const TaijiIcon = React.memo(function TaijiIcon({
|
||||
className,
|
||||
}: {
|
||||
className?: string;
|
||||
}) {
|
||||
return (
|
||||
<svg
|
||||
viewBox="0 0 64 64"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
className={cn("h-7 w-7 shrink-0 drop-shadow-sm", className)}
|
||||
aria-hidden
|
||||
>
|
||||
<circle cx="32" cy="32" r="30" className={YANG} />
|
||||
<path
|
||||
d="M32 2a30 30 0 0 1 0 60 15 15 0 0 1 0-30 15 15 0 0 0 0-30z"
|
||||
className={YIN}
|
||||
/>
|
||||
<circle cx="32" cy="17" r="5" className={YANG} />
|
||||
<circle cx="32" cy="47" r="5" className={YIN} />
|
||||
</svg>
|
||||
);
|
||||
});
|
||||
|
||||
/** 背景用水印版太极 */
|
||||
export function TaijiWatermark({
|
||||
className,
|
||||
}: {
|
||||
className?: string;
|
||||
}) {
|
||||
return (
|
||||
<svg
|
||||
viewBox="0 0 200 200"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
className={className}
|
||||
aria-hidden
|
||||
>
|
||||
<circle cx="100" cy="100" r="98" className={`${YANG} opacity-[0.35]`} />
|
||||
<path
|
||||
d="M100 2a98 98 0 0 1 0 196 49 49 0 0 1 0-98 49 49 0 0 0 0-98z"
|
||||
className={`${YIN} opacity-[0.08] dark:opacity-[0.12]`}
|
||||
/>
|
||||
<circle cx="100" cy="51" r="10" className={`${YANG} opacity-50`} />
|
||||
<circle cx="100" cy="149" r="10" className={`${YIN} opacity-20 dark:opacity-30`} />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user