Redesign UI with zen cards, split AI panel, and PWA install support.
Learn uses 64-gua card grid; liuyao/bazi/combined use two input cards plus sticky right AI panel; add manifest, service worker, and install prompt. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,18 +1,23 @@
|
||||
import React, { useEffect, useRef, useState } from "react";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { RotateCw } from "lucide-react";
|
||||
import Markdown from "react-markdown";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
function ResultAI({
|
||||
completion,
|
||||
isLoading,
|
||||
onCompletion,
|
||||
error,
|
||||
panel = false,
|
||||
emptyHint = "完成左侧填写并起卦/排盘后,点击「AI 解读」",
|
||||
}: {
|
||||
completion: string;
|
||||
isLoading: boolean;
|
||||
onCompletion: () => void;
|
||||
error: string;
|
||||
panel?: boolean;
|
||||
emptyHint?: string;
|
||||
}) {
|
||||
const scrollRef = useRef<HTMLDivElement>(null);
|
||||
const [autoScroll, setAutoScroll] = useState(false);
|
||||
@@ -39,8 +44,13 @@ function ResultAI({
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex w-full flex-col gap-2">
|
||||
{isLoading && (
|
||||
<div
|
||||
className={cn(
|
||||
"flex w-full flex-col",
|
||||
panel ? "min-h-0 flex-1" : "gap-2",
|
||||
)}
|
||||
>
|
||||
{isLoading && !panel && (
|
||||
<div className="flex items-center text-sm text-muted-foreground">
|
||||
<RotateCw size={16} className="animate-spin" />
|
||||
<span className="ml-1">AI 分析中...</span>
|
||||
@@ -49,25 +59,41 @@ function ResultAI({
|
||||
<div
|
||||
ref={scrollRef}
|
||||
onScroll={(e) => onScroll(e.currentTarget)}
|
||||
className="min-h-[240px] max-h-[420px] overflow-y-auto rounded-md border bg-background p-3 shadow sm:p-5 dark:border-0 dark:bg-secondary/90 dark:shadow-none"
|
||||
className={cn(
|
||||
"overflow-y-auto",
|
||||
panel
|
||||
? "min-h-0 flex-1"
|
||||
: "min-h-[240px] max-h-[420px] rounded-md border bg-background p-3 shadow sm:p-5 dark:border-0 dark:bg-secondary/90",
|
||||
)}
|
||||
>
|
||||
{isLoading && panel && (
|
||||
<div className="mb-3 flex items-center text-sm text-muted-foreground">
|
||||
<RotateCw size={16} className="animate-spin" />
|
||||
<span className="ml-1">AI 分析中...</span>
|
||||
</div>
|
||||
)}
|
||||
{error ? (
|
||||
<div className="text-sm text-destructive">
|
||||
<p className="font-medium">请求出错了</p>
|
||||
<p className="mt-1 whitespace-pre-wrap">{error}</p>
|
||||
</div>
|
||||
) : completion ? (
|
||||
<Markdown className="prose max-w-none dark:prose-invert">
|
||||
<Markdown className="prose max-w-none text-sm dark:prose-invert prose-p:leading-relaxed">
|
||||
{completion}
|
||||
</Markdown>
|
||||
) : isLoading ? (
|
||||
<p className="text-sm text-muted-foreground">正在等待 AI 响应...</p>
|
||||
) : (
|
||||
<p className="text-sm text-muted-foreground">暂无解读内容</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">
|
||||
{emptyHint}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
{!isLoading && (
|
||||
<Button onClick={onCompletion} size="sm" className="mt-3">
|
||||
<RotateCw size={18} className="mr-1" />
|
||||
{!isLoading && (completion || error) && (
|
||||
<Button onClick={onCompletion} size="sm" variant="outline" className="mt-4">
|
||||
<RotateCw size={16} className="mr-1" />
|
||||
重新生成
|
||||
</Button>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user