Show compressed previews in vision lab
这个提交包含在:
@@ -47,6 +47,67 @@ type VisionRun = {
|
||||
updatedAt: Date;
|
||||
};
|
||||
|
||||
const COMMONS_SPECIAL_FILE_PATH = "/wiki/Special:FilePath/";
|
||||
const COMMONS_FILE_PAGE_PATH = "/wiki/File:";
|
||||
|
||||
function getCompressedVisionImageUrl(imageUrl: string, width = 960) {
|
||||
try {
|
||||
const url = new URL(imageUrl);
|
||||
if (url.hostname !== "commons.wikimedia.org") {
|
||||
return imageUrl;
|
||||
}
|
||||
|
||||
let fileName: string | null = null;
|
||||
if (url.pathname.startsWith(COMMONS_SPECIAL_FILE_PATH)) {
|
||||
fileName = url.pathname.slice(COMMONS_SPECIAL_FILE_PATH.length);
|
||||
} else if (url.pathname.startsWith(COMMONS_FILE_PAGE_PATH)) {
|
||||
fileName = url.pathname.slice(COMMONS_FILE_PAGE_PATH.length);
|
||||
}
|
||||
|
||||
if (!fileName) {
|
||||
return imageUrl;
|
||||
}
|
||||
|
||||
const decodedFileName = decodeURIComponent(fileName);
|
||||
return `https://commons.wikimedia.org/wiki/Special:Redirect/file/${encodeURIComponent(decodedFileName)}?width=${width}`;
|
||||
} catch {
|
||||
return imageUrl;
|
||||
}
|
||||
}
|
||||
|
||||
function VisionPreviewImage({
|
||||
src,
|
||||
alt,
|
||||
className,
|
||||
width = 960,
|
||||
}: {
|
||||
src: string;
|
||||
alt: string;
|
||||
className: string;
|
||||
width?: number;
|
||||
}) {
|
||||
const [displaySrc, setDisplaySrc] = useState(() => getCompressedVisionImageUrl(src, width));
|
||||
|
||||
useEffect(() => {
|
||||
setDisplaySrc(getCompressedVisionImageUrl(src, width));
|
||||
}, [src, width]);
|
||||
|
||||
return (
|
||||
<img
|
||||
src={displaySrc}
|
||||
alt={alt}
|
||||
className={className}
|
||||
loading="lazy"
|
||||
referrerPolicy="no-referrer"
|
||||
onError={() => {
|
||||
if (displaySrc !== src) {
|
||||
setDisplaySrc(src);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function statusBadge(run: VisionRun) {
|
||||
if (run.status === "failed" || run.visionStatus === "failed") {
|
||||
return <Badge variant="destructive">失败</Badge>;
|
||||
@@ -212,12 +273,11 @@ export default function VisionLab() {
|
||||
{references.map((reference) => (
|
||||
<Card key={reference.id} className="overflow-hidden border-0 shadow-sm">
|
||||
<div className="aspect-[4/3] overflow-hidden bg-muted">
|
||||
<img
|
||||
<VisionPreviewImage
|
||||
src={reference.imageUrl}
|
||||
alt={reference.title}
|
||||
className="h-full w-full object-cover"
|
||||
loading="lazy"
|
||||
referrerPolicy="no-referrer"
|
||||
width={960}
|
||||
/>
|
||||
</div>
|
||||
<CardHeader className="pb-3">
|
||||
@@ -272,6 +332,24 @@ export default function VisionLab() {
|
||||
{runs.map((run) => (
|
||||
<Card key={run.id} className="border-0 shadow-sm">
|
||||
<CardContent className="pt-5 space-y-3">
|
||||
<div className="flex flex-col gap-4 lg:flex-row">
|
||||
<a
|
||||
href={run.imageUrl}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
className="block overflow-hidden rounded-xl bg-muted lg:w-72 lg:flex-none"
|
||||
>
|
||||
<div className="aspect-[4/3]">
|
||||
<VisionPreviewImage
|
||||
src={run.imageUrl}
|
||||
alt={run.title}
|
||||
className="h-full w-full object-cover"
|
||||
width={720}
|
||||
/>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<div className="min-w-0 flex-1 space-y-3">
|
||||
<div className="flex flex-col gap-3 lg:flex-row lg:items-start lg:justify-between">
|
||||
<div className="space-y-1">
|
||||
<div className="flex flex-wrap items-center gap-2">
|
||||
@@ -325,6 +403,8 @@ export default function VisionLab() {
|
||||
{run.corrections}
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
))}
|
||||
|
||||
在新工单中引用
屏蔽一个用户