feat(ui): add fixed image completion summary and remove upgrade usage table
This commit is contained in:
parent
8d4a54de4a
commit
28847b5705
@ -240,6 +240,7 @@ function formatMessageDateLabel(timestamp: number): string {
|
||||
}
|
||||
|
||||
const CANVAS_IMAGE_ANALYSIS_TITLE = "图片分析";
|
||||
const CANVAS_IMAGE_DONE_SUMMARY = "已完成本次生成,如需微调可继续告诉我。";
|
||||
const CANVAS_AGENT_SECTION_TITLES = new Set([
|
||||
"需求理解",
|
||||
CANVAS_IMAGE_ANALYSIS_TITLE,
|
||||
@ -5106,30 +5107,37 @@ export function CanvasChatPanel({ chatId, initialMessages = [], onClose, onOpenF
|
||||
</span>
|
||||
) : null}
|
||||
{imageUrls.length > 0 && (
|
||||
<div className={cn("flex flex-wrap gap-2", textWithoutImages ? "mt-3" : "mt-0")}>
|
||||
{imageUrls.map((url, idx) => (
|
||||
<div
|
||||
key={idx}
|
||||
className={cn(
|
||||
"relative group overflow-hidden border transition-all",
|
||||
"rounded-2xl border-black/5 dark:border-white/10 bg-white/70 dark:bg-zinc-900/50",
|
||||
"shadow-[0_8px_24px_-16px_rgba(15,23,42,0.45)] hover:shadow-[0_12px_28px_-14px_rgba(15,23,42,0.5)]"
|
||||
)}
|
||||
>
|
||||
<img
|
||||
src={url}
|
||||
alt=""
|
||||
className="block max-w-full h-auto cursor-zoom-in transition-transform duration-300 group-hover:scale-[1.02]"
|
||||
style={{ maxHeight: "260px" }}
|
||||
onClick={() => setFullscreenPreview({ url })}
|
||||
onDoubleClick={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
setFullscreenPreview({ url });
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
<div className={cn("space-y-2", textWithoutImages ? "mt-3" : "mt-0")}>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{imageUrls.map((url, idx) => (
|
||||
<div
|
||||
key={idx}
|
||||
className={cn(
|
||||
"relative group overflow-hidden border transition-all",
|
||||
"rounded-2xl border-black/5 dark:border-white/10 bg-white/70 dark:bg-zinc-900/50",
|
||||
"shadow-[0_8px_24px_-16px_rgba(15,23,42,0.45)] hover:shadow-[0_12px_28px_-14px_rgba(15,23,42,0.5)]"
|
||||
)}
|
||||
>
|
||||
<img
|
||||
src={url}
|
||||
alt=""
|
||||
className="block max-w-full h-auto cursor-zoom-in transition-transform duration-300 group-hover:scale-[1.02]"
|
||||
style={{ maxHeight: "260px" }}
|
||||
onClick={() => setFullscreenPreview({ url })}
|
||||
onDoubleClick={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
setFullscreenPreview({ url });
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
{!isDetailGenerationMode ? (
|
||||
<p className="text-[14px] font-medium leading-6 text-[#2f3640]">
|
||||
{CANVAS_IMAGE_DONE_SUMMARY}
|
||||
</p>
|
||||
) : null}
|
||||
</div>
|
||||
)}
|
||||
{videoUrls.length > 0 && (
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { Fragment, useEffect, useMemo, useRef, useState } from "react";
|
||||
import { useEffect, useMemo, useRef, useState } from "react";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { signIn, signOut } from "next-auth/react";
|
||||
import useSWR from "swr";
|
||||
@ -455,17 +455,6 @@ export function LovartHome({
|
||||
const membershipPlans = membershipConfig?.plans || [];
|
||||
const currentPlan = membershipData?.currentPlan;
|
||||
|
||||
const groupedModelRows = useMemo(() => {
|
||||
const rows = membershipConfig?.modelRows || [];
|
||||
return rows.reduce<Record<string, typeof rows>>((acc, row) => {
|
||||
if (!acc[row.category]) {
|
||||
acc[row.category] = [];
|
||||
}
|
||||
acc[row.category].push(row);
|
||||
return acc;
|
||||
}, {});
|
||||
}, [membershipConfig?.modelRows]);
|
||||
|
||||
const imageModels = useMemo(
|
||||
() => (modelsData?.models || []).filter((model) => model.supportsImageGen),
|
||||
[modelsData?.models]
|
||||
@ -2422,53 +2411,6 @@ export function LovartHome({
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="mt-7">
|
||||
<h4 className="mb-2 text-center text-2xl font-semibold text-black">
|
||||
模型积分消耗 & 每月生成数量
|
||||
</h4>
|
||||
<p className="mb-3 text-center text-[11px] text-black/45">
|
||||
以下表格基于系统设置中的会员配置,可直接在后台调整。
|
||||
</p>
|
||||
<div className="overflow-x-auto rounded-xl border border-black/10 bg-white">
|
||||
<table className="w-full min-w-[820px] text-xs">
|
||||
<thead>
|
||||
<tr className="bg-black/[0.03]">
|
||||
<th className="px-2.5 py-2.5 text-left font-semibold text-black/75">模型</th>
|
||||
{membershipPlans.map((plan) => (
|
||||
<th key={plan.id} className="px-2.5 py-2.5 text-left font-semibold text-black/75">
|
||||
{plan.name}
|
||||
</th>
|
||||
))}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{Object.entries(groupedModelRows).map(([category, rows]) => (
|
||||
<Fragment key={category}>
|
||||
<tr className="bg-black/[0.045]">
|
||||
<td
|
||||
colSpan={membershipPlans.length + 1}
|
||||
className="px-2.5 py-2 text-[11px] font-semibold text-black/60"
|
||||
>
|
||||
{category}
|
||||
</td>
|
||||
</tr>
|
||||
{rows.map((row) => (
|
||||
<tr key={`${category}-${row.model}`} className="border-t border-black/[0.06]">
|
||||
<td className="px-2.5 py-2 text-black/70">{row.model}</td>
|
||||
{membershipPlans.map((plan) => (
|
||||
<td key={`${row.model}-${plan.id}`} className="px-2.5 py-2 text-black/60">
|
||||
{row.values[plan.id] ?? "-"}
|
||||
{row.values[plan.id] && row.values[plan.id] !== "-" ? row.unit : ""}
|
||||
</td>
|
||||
))}
|
||||
</tr>
|
||||
))}
|
||||
</Fragment>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</DialogContent>
|
||||
|
||||
@ -5,6 +5,7 @@ import { memo, useState } from "react";
|
||||
import type { Vote } from "@/lib/db/schema";
|
||||
import type { ChatMessage } from "@/lib/types";
|
||||
import { cn, sanitizeText } from "@/lib/utils";
|
||||
import { extractImageUrlsFromText } from "@/lib/image-url";
|
||||
import { useDataStream } from "./data-stream-provider";
|
||||
import { DocumentToolResult } from "./document";
|
||||
import { DocumentPreview } from "./document-preview";
|
||||
@ -172,6 +173,17 @@ function filterAgentRoutingNoise(text: string): string {
|
||||
return filtered;
|
||||
}
|
||||
|
||||
const IMAGE_DONE_SUMMARY = "已完成本次生成,如需微调可继续告诉我。";
|
||||
|
||||
function appendImageDoneSummary(text: string): string {
|
||||
if (!text) return text;
|
||||
const normalized = String(text || "").trim();
|
||||
if (!normalized) return normalized;
|
||||
if (extractImageUrlsFromText(normalized).length === 0) return normalized;
|
||||
if (normalized.includes(IMAGE_DONE_SUMMARY)) return normalized;
|
||||
return `${normalized}\n\n${IMAGE_DONE_SUMMARY}`;
|
||||
}
|
||||
|
||||
const PurePreviewMessage = ({
|
||||
chatId,
|
||||
message,
|
||||
@ -315,7 +327,7 @@ const PurePreviewMessage = ({
|
||||
// 应用视频内容过滤
|
||||
const filteredText =
|
||||
message.role === "assistant"
|
||||
? filterAgentRoutingNoise(filterVideoContent(part.text))
|
||||
? appendImageDoneSummary(filterAgentRoutingNoise(filterVideoContent(part.text)))
|
||||
: part.text;
|
||||
const textParts = parseAnnotations(filteredText);
|
||||
|
||||
@ -567,7 +579,7 @@ export const ThinkingMessage = () => {
|
||||
<div className="flex w-full flex-col gap-2">
|
||||
{/* 简洁明了的文本 + 动态点 */}
|
||||
<div className="flex items-center gap-1.5">
|
||||
<span className="text-base font-medium text-foreground">AI 正在思考中</span>
|
||||
<span className="text-base font-medium text-foreground">AI 正在分析中</span>
|
||||
<span className="flex gap-1">
|
||||
<span className="h-2 w-2 rounded-full bg-foreground animate-bounce" style={{ animationDelay: '0ms' }} />
|
||||
<span className="h-2 w-2 rounded-full bg-foreground animate-bounce" style={{ animationDelay: '150ms' }} />
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user