资源卡文档分区:Markdown/纯文本显示前几行,代码文件改画代码图标
- index.tsx:卡面据 projectResourceCardPreviewVariant 分流,代码卡分支只渲染 lucide 代码图标 + 扩展名标签,不再显示文件内容 - index.tsx:文档卡改用 projectResourceDocumentPreviewText 取前 3 行,并带上 data-document-preview-variant 便于排障与验收 - index.tsx:引入 FileCode2 图标 - ResourcePreviewMedia.tsx:弹窗宿主里代码文件同样改画代码图标,避免看起来像"读不出来的图片" - styles.css:文档卡预览保留换行并限制 3 行(white-space: pre-line + -webkit-line-clamp: 3) - styles.css:新增 .game-resource-card-code-visual / .game-resource-card-code-label,复用现有卡片色板与居中排布口径
This commit is contained in:
@@ -7209,9 +7209,38 @@ iframe.preview-frame {
|
||||
font-size: 11px;
|
||||
line-height: 1.55;
|
||||
text-align: left;
|
||||
white-space: normal;
|
||||
/* 文档卡预览改为"前几行"(最多 3 行),必须保留换行:折成一行就看不出结构了。 */
|
||||
white-space: pre-line;
|
||||
word-break: break-word;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 5;
|
||||
-webkit-line-clamp: 3;
|
||||
}
|
||||
|
||||
/*
|
||||
* 代码文件卡:不显示文件内容,只给代码图标 + 扩展名标签。
|
||||
* 与 `.game-resource-card-version-visual` 共用同一套居中排布口径,视觉上仍是同一族卡片。
|
||||
*/
|
||||
.game-resource-card-code-visual {
|
||||
display: grid;
|
||||
gap: 8px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: linear-gradient(145deg, #fff8f1, #f2ded2);
|
||||
color: #8b5b45;
|
||||
/* 图标与标签作为一组整体垂直居中,与 `.game-resource-card-version-visual` 同口径。 */
|
||||
align-content: center;
|
||||
place-items: center;
|
||||
}
|
||||
|
||||
.game-resource-card-code-label {
|
||||
padding: 1px 7px;
|
||||
border: 1px solid rgb(139 91 69 / 28%);
|
||||
border-radius: 999px;
|
||||
background: rgb(255 255 255 / 72%);
|
||||
color: #8b5b45;
|
||||
font-size: 9px;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.04em;
|
||||
}
|
||||
|
||||
.game-resource-card-version-visual {
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { Image as ImageIcon, Music2, Video } from 'lucide-react';
|
||||
import { FileCode2, Image as ImageIcon, Music2, Video } from 'lucide-react';
|
||||
import { useEffect, useRef } from 'react';
|
||||
|
||||
import {
|
||||
projectResourceCardPreviewKind,
|
||||
type ProjectResourceCardPreviewState,
|
||||
projectResourceCardPreviewVariant,
|
||||
} from './resourceCardPreviewModel';
|
||||
import type { ProjectResource } from './resourceProjectionModel';
|
||||
|
||||
@@ -79,6 +80,13 @@ export function ResourcePreviewMedia({
|
||||
}, [onObservePreview, previewIdentity, resource]);
|
||||
|
||||
const kind = resource ? projectResourceCardPreviewKind(resource) : null;
|
||||
/**
|
||||
* 代码文件走与资源卡一致的分流:不画内容(本组件本来也只画缩略图 / 占位),
|
||||
* 占位图标换成代码图标,免得弹窗里代码文件看起来像"读不出来的图片"。
|
||||
*/
|
||||
const previewVariant = resource
|
||||
? projectResourceCardPreviewVariant(resource)
|
||||
: null;
|
||||
const sourceUrl =
|
||||
preview.status === 'loaded' ? (preview.preview.sourceUrl ?? null) : null;
|
||||
const visual = (() => {
|
||||
@@ -111,6 +119,9 @@ export function ResourcePreviewMedia({
|
||||
/>
|
||||
);
|
||||
}
|
||||
if (previewVariant === 'code') {
|
||||
return <FileCode2 className="h-5 w-5" aria-hidden="true" />;
|
||||
}
|
||||
return resourcePreviewPlaceholderIcon(
|
||||
kind === 'video'
|
||||
? 'video'
|
||||
|
||||
@@ -18,6 +18,7 @@ import { save as saveNativeFileDialog } from '@tauri-apps/plugin-dialog';
|
||||
import {
|
||||
AtSign,
|
||||
Crosshair,
|
||||
FileCode2,
|
||||
FileText,
|
||||
FolderTree,
|
||||
Gamepad2,
|
||||
@@ -275,7 +276,9 @@ import {
|
||||
import {
|
||||
projectResourceCardPreviewKind,
|
||||
type ProjectResourceCardPreviewState,
|
||||
summarizeProjectResourceDocument,
|
||||
projectResourceCardPreviewVariant,
|
||||
projectResourceCodeTypeLabel,
|
||||
projectResourceDocumentPreviewText,
|
||||
} from './resourceCardPreviewModel';
|
||||
import { ResourceClassificationPanel } from './ResourceClassificationPanel';
|
||||
import {
|
||||
@@ -757,9 +760,24 @@ const ResourceCard = memo(function ResourceCard({
|
||||
const mediaActive = activeMediaIdentity === previewIdentity;
|
||||
const sourceUrl =
|
||||
preview.status === 'loaded' ? preview.preview.sourceUrl : null;
|
||||
const documentSummary =
|
||||
preview.status === 'loaded' && preview.preview.content !== undefined
|
||||
? summarizeProjectResourceDocument(preview.preview.content)
|
||||
/**
|
||||
* 文档类卡片的卡面分流结论(`markdown` / `code` / `plain-text` / `null`)。
|
||||
*
|
||||
* 判据只看路径扩展名与 subtype,**不依赖是否读到内容** —— 代码卡的卡面本就不该有内容,
|
||||
* 等读完再决定画什么只会把"丑预览"和多余 IO 一起留在链路上。
|
||||
*/
|
||||
const previewVariant = projectResourceCardPreviewVariant(resource);
|
||||
/** 代码卡的类型标签(`.tsx` → `TSX`);不是代码卡时为 `null`。 */
|
||||
const codeTypeLabel = projectResourceCodeTypeLabel(resource.path);
|
||||
const documentPreview =
|
||||
preview.status === 'loaded' &&
|
||||
preview.preview.content !== undefined &&
|
||||
previewVariant !== null &&
|
||||
previewVariant !== 'code'
|
||||
? projectResourceDocumentPreviewText(
|
||||
preview.preview.content,
|
||||
previewVariant === 'markdown',
|
||||
)
|
||||
: '';
|
||||
|
||||
useEffect(() => {
|
||||
@@ -908,10 +926,31 @@ const ResourceCard = memo(function ResourceCard({
|
||||
</span>
|
||||
);
|
||||
}
|
||||
if ((kind === 'document' || kind === 'code') && documentSummary) {
|
||||
/**
|
||||
* 代码文件卡:**不显示内容**,只给代码图标 + 类型标签。
|
||||
*
|
||||
* 这里的判据是路径分流(`previewVariant === 'code'`),与是否读到内容无关 ——
|
||||
* 代码卡压根不发起读取(见 `useProjectResourceCardPreviews` 的入队门禁)。
|
||||
*/
|
||||
if (previewVariant === 'code') {
|
||||
return (
|
||||
<span className="game-resource-card-document-summary">
|
||||
{documentSummary}
|
||||
<span className="game-resource-card-code-visual">
|
||||
<FileCode2 size={30} aria-hidden="true" />
|
||||
{codeTypeLabel ? (
|
||||
<span className="game-resource-card-code-label">
|
||||
{codeTypeLabel}
|
||||
</span>
|
||||
) : null}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
if (previewVariant !== null && documentPreview) {
|
||||
return (
|
||||
<span
|
||||
className="game-resource-card-document-summary"
|
||||
data-document-preview-variant={previewVariant}
|
||||
>
|
||||
{documentPreview}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user