feat(frontend): artifact 文件卡片支持右键引用
This commit is contained in:
parent
4dbe930775
commit
3d5006af48
|
|
@ -10,9 +10,16 @@ import {
|
||||||
CardHeader,
|
CardHeader,
|
||||||
CardTitle,
|
CardTitle,
|
||||||
} from "@/components/ui/card";
|
} from "@/components/ui/card";
|
||||||
|
import {
|
||||||
|
ContextMenu,
|
||||||
|
ContextMenuContent,
|
||||||
|
ContextMenuItem,
|
||||||
|
ContextMenuTrigger,
|
||||||
|
} from "@/components/ui/context-menu";
|
||||||
import { urlOfArtifact } from "@/core/artifacts/utils";
|
import { urlOfArtifact } from "@/core/artifacts/utils";
|
||||||
import { useI18n } from "@/core/i18n/hooks";
|
import { useI18n } from "@/core/i18n/hooks";
|
||||||
import { installSkill } from "@/core/skills/api";
|
import { installSkill } from "@/core/skills/api";
|
||||||
|
import { dispatchMentionReference } from "@/core/threads/reference-events";
|
||||||
import {
|
import {
|
||||||
getFileExtensionDisplayName,
|
getFileExtensionDisplayName,
|
||||||
getFileIcon,
|
getFileIcon,
|
||||||
|
|
@ -78,69 +85,86 @@ export function ArtifactFileList({
|
||||||
data-testid="artifact-file-list"
|
data-testid="artifact-file-list"
|
||||||
>
|
>
|
||||||
{files.map((file) => (
|
{files.map((file) => (
|
||||||
<Card
|
<ContextMenu key={file}>
|
||||||
key={file}
|
<ContextMenuTrigger asChild>
|
||||||
className="relative cursor-pointer p-4"
|
<Card
|
||||||
data-testid="artifact-file-card"
|
className="relative cursor-pointer p-4"
|
||||||
onClick={() => handleClick(file)}
|
data-testid="artifact-file-card"
|
||||||
>
|
onClick={() => handleClick(file)}
|
||||||
<CardHeader className="pr-2 pl-1">
|
>
|
||||||
<CardTitle className="relative overflow-hidden pl-10">
|
<CardHeader className="pr-2 pl-1">
|
||||||
<div
|
<CardTitle className="relative overflow-hidden pl-10">
|
||||||
className="text-sm font-normal text-ellipsis whitespace-nowrap"
|
<div
|
||||||
title={getFileName(file)}
|
className="text-sm font-normal text-ellipsis whitespace-nowrap"
|
||||||
>
|
title={getFileName(file)}
|
||||||
{truncateMiddle(getFileName(file), 50)}
|
|
||||||
</div>
|
|
||||||
</CardTitle>
|
|
||||||
<div className="absolute top-5 left-4">
|
|
||||||
{getFileIcon(file, "size-9 stroke-[1px] stroke-[#333333]")}
|
|
||||||
</div>
|
|
||||||
<CardDescription className="pl-10 text-xs">
|
|
||||||
{getFileExtensionDisplayName(file)} file
|
|
||||||
</CardDescription>
|
|
||||||
<CardAction>
|
|
||||||
{file.endsWith(".skill") && (
|
|
||||||
<Button
|
|
||||||
variant="ghost"
|
|
||||||
disabled={!threadId || installingFile === file}
|
|
||||||
onClick={(e) => handleInstallSkill(e, file)}
|
|
||||||
>
|
|
||||||
{installingFile === file ? (
|
|
||||||
<LoaderIcon className="size-4 animate-spin" />
|
|
||||||
) : (
|
|
||||||
<PackageIcon className="size-4" />
|
|
||||||
)}
|
|
||||||
{t.common.install}
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
{threadId ? (
|
|
||||||
<a
|
|
||||||
href={urlOfArtifact({
|
|
||||||
filepath: file,
|
|
||||||
threadId,
|
|
||||||
download: true,
|
|
||||||
})}
|
|
||||||
target="_blank"
|
|
||||||
onClick={(e) => e.stopPropagation()}
|
|
||||||
>
|
|
||||||
<Button variant="ghost"
|
|
||||||
className="h-full! text-[var(--muted-foreground)]! hover:bg-transparent! hover:text-[#333333]!"
|
|
||||||
|
|
||||||
>
|
>
|
||||||
<DownloadIcon className="size-4" />
|
{truncateMiddle(getFileName(file), 50)}
|
||||||
{t.common.download}
|
</div>
|
||||||
</Button>
|
</CardTitle>
|
||||||
</a>
|
<div className="absolute top-5 left-4">
|
||||||
) : (
|
{getFileIcon(file, "size-9 stroke-[1px] stroke-[#333333]")}
|
||||||
<Button variant="ghost" disabled>
|
</div>
|
||||||
<DownloadIcon className="size-4" />
|
<CardDescription className="pl-10 text-xs">
|
||||||
{t.common.download}
|
{getFileExtensionDisplayName(file)} file
|
||||||
</Button>
|
</CardDescription>
|
||||||
)}
|
<CardAction>
|
||||||
</CardAction>
|
{file.endsWith(".skill") && (
|
||||||
</CardHeader>
|
<Button
|
||||||
</Card>
|
variant="ghost"
|
||||||
|
disabled={!threadId || installingFile === file}
|
||||||
|
onClick={(e) => handleInstallSkill(e, file)}
|
||||||
|
>
|
||||||
|
{installingFile === file ? (
|
||||||
|
<LoaderIcon className="size-4 animate-spin" />
|
||||||
|
) : (
|
||||||
|
<PackageIcon className="size-4" />
|
||||||
|
)}
|
||||||
|
{t.common.install}
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
{threadId ? (
|
||||||
|
<a
|
||||||
|
href={urlOfArtifact({
|
||||||
|
filepath: file,
|
||||||
|
threadId,
|
||||||
|
download: true,
|
||||||
|
})}
|
||||||
|
target="_blank"
|
||||||
|
onClick={(e) => e.stopPropagation()}
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
className="h-full! text-[var(--muted-foreground)]! hover:bg-transparent! hover:text-[#333333]!"
|
||||||
|
>
|
||||||
|
<DownloadIcon className="size-4" />
|
||||||
|
{t.common.download}
|
||||||
|
</Button>
|
||||||
|
</a>
|
||||||
|
) : (
|
||||||
|
<Button variant="ghost" disabled>
|
||||||
|
<DownloadIcon className="size-4" />
|
||||||
|
{t.common.download}
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</CardAction>
|
||||||
|
</CardHeader>
|
||||||
|
</Card>
|
||||||
|
</ContextMenuTrigger>
|
||||||
|
<ContextMenuContent className="min-w-[120px] p-1">
|
||||||
|
<ContextMenuItem
|
||||||
|
onSelect={() => {
|
||||||
|
dispatchMentionReference({
|
||||||
|
threadId,
|
||||||
|
filename: getFileName(file),
|
||||||
|
path: file,
|
||||||
|
ref_source: "artifact",
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
引用
|
||||||
|
</ContextMenuItem>
|
||||||
|
</ContextMenuContent>
|
||||||
|
</ContextMenu>
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue