mcpField
I
integrate-file-viewer

integrate-file-viewer

github.com/cognitedata开发337 次安装
代码仓库

关于 integrate-file-viewer

用于在 Dune 应用中集成 CogniteFileViewer 以预览 CDF 文件的技能,涵盖依赖和 Vite 配置、PDF.js worker 设置、支持格式及交互。

主要功能

  1. 01安装查看器依赖
  2. 02配置 PDF.js worker
  3. 03设置 Vite 不预打包 pdfjs-dist
  4. 04预览 PDF、Office、图像和文本
  5. 05支持缩放、平移和注释

适用场景

  1. 01为 Dune 应用添加文件预览
  2. 02通过 CDF Document Preview API 呈现 Office 文档
  3. 03从注释跳转到关联文件

MCP 相关

查看器使用 Dune SDK 访问 CDF 文件。Office 文档通过 CDF Document Preview API 转换。

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/cognitedata/dune-skills --skill integrate-file-viewer

安装后在 Claude Code 中输入/integrate-file-viewer确认已加载。

详细介绍

集成 CogniteFileViewer

将 CogniteFileViewer 添加到此 Dune 应用,以预览 CDF 文件(PDF、图像、文本)。

你的任务

按顺序完成以下步骤。修改文件前,先阅读每个文件。


步骤 1 — 了解应用

开始操作前,先阅读以下文件:

  • package.json — 检查包管理器(packageManager 字段或锁文件)和现有依赖项
  • vite.config.ts — 了解当前的 Vite 配置
  • 要添加文件查看器的组件

步骤 2 — 安装依赖项

  • pnpm → pnpm add "github:cognitedata/dune-industrial-components#semver:*" react-pdf
  • npm → npm install "github:cognitedata/dune-industrial-components#semver:*" react-pdf
  • yarn → yarn add "github:cognitedata/dune-industrial-components#semver:*" react-pdf

pdfjs-dist 会以正确版本作为 react-pdf 的依赖项安装,无需单独安装。


步骤 3 — 配置 PDF.js worker

使用方应用必须配置 PDF.js worker,以确保 worker 版本与 react-pdf 安装包中包含的 pdfjs-dist 版本一致。

在使用 CogniteFileViewer 的同一文件中添加此设置(模块执行顺序很重要):

import { pdfjs } from 'react-pdf';

pdfjs.GlobalWorkerOptions.workerSrc = new URL(
  'pdfjs-dist/build/pdf.worker.min.mjs',
  import.meta.url,
).toString();

pnpm 用户: pnpm 的严格链接可能会导致浏览器无法解析 pdfjs-dist。可以将 pdfjs-dist 添加为直接依赖项(pnpm add pdfjs-dist),也可以将 public-hoist-pattern[]=pdfjs-dist 添加到 .npmrc。


步骤 4 — 配置 Vite

在 vite.config.ts 中添加 optimizeDeps.exclude: ['pdfjs-dist'],以防止 Vite 预打包 pdfjs-dist(这会导致 worker 无法正常工作):

export default defineConfig({
  // ... existing config ...
  optimizeDeps: {
    exclude: ['pdfjs-dist'],
  },
});

步骤 5 — 使用组件

在需要预览文件的位置导入并渲染 CogniteFileViewer。

import { CogniteFileViewer } from '@cognite/dune-industrial-components/file-viewer';

通过 useDune() 钩子获取 sdk(每个 Dune 应用中均已提供):

import { useDune } from '@cognite/dune';
const { sdk } = useDune();
支持的文件类型
类型格式
PDF.pdf — 页面导航、缩放、平移、图表注释叠加层
Office 文档Word、PowerPoint、Excel、ODS、ODP、ODT、RTF、TSV — 通过 CDF Document Preview API 转换为 PDF,然后以与 PDF 相同的方式渲染
图像JPEG、PNG、WebP、SVG、TIFF — 缩放、平移、旋转
文本.txt、.csv、.json — 以预格式化文本的形式渲染
其他回退到 renderUnsupported
最简用法

只需这些即可 — 缩放、平移和触控手势均由组件内部处理:

<CogniteFileViewer
  source={{ type: 'internalId', id: file.id }}
  client={sdk}
  style={{ width: '100%', height: '600px' }}
/>

组件必须设置明确的高度。 如果父元素没有明确的高度,文件查看器将收缩至零高度。请始终通过 style、className 或父容器设置 height。

文件来源

传入以下三种来源类型之一:

// By instance ID (data-modelled file — enables annotations)
<CogniteFileViewer
  source={{ type: 'instanceId', space: 'my-space', externalId: 'my-file' }}
  client={sdk}
/>

// By CDF internal ID
<CogniteFileViewer
  source={{ type: 'internalId', id: 12345 }}
  client={sdk}
/>

// By direct URL
<CogniteFileViewer
  source={{ type: 'url', url: 'https://...', mimeType: 'application/pdf' }}
/>

如果有 instanceId,优先使用它 — 这是唯一能启用图表注释叠加层的来源类型。通过 sdk.files.list() 列出文件时,请先检查 file.instanceId:

source={
  file.instanceId
    ? { type: 'instanceId', space: file.instanceId.space, externalId: file.instanceId.externalId }
    : { type: 'internalId', id: file.id }
}
完整属性参考
<CogniteFileViewer
  // Required
  source={source}
  client={sdk}              // required for instanceId and internalId sources

  // PDF pagination
  page={page}               // controlled current page (1-indexed)
  onPageChange={setPage}
  onDocumentLoad={({ numPages }) => setNumPages(numPages)}

  // Zoom & pan (works on PDF and images)
  zoom={zoom}               // 1 = 100%; Ctrl/Cmd+wheel, pinch-to-zoom, and middle-click drag built in
  onZoomChange={setZoom}
  minZoom={0.25}            // default
  maxZoom={5}               // default
  panOffset={pan}           // controlled pan offset; resets on page change
  onPanChange={setPan}

  // Fit mode
  fitMode="width"           // 'width' fits to container width; 'page' fits entire page in container

  // Rotation (PDFs and images)
  rotation={rotation}       // 0 | 90 | 180 | 270

  // Diagram annotations (instanceId sources only)
  showAnnotations={true}    // default
  onAnnotationClick={(annotation) => { /* annotation.linkedResource has space + externalId */ }}
  onAnnotationHover={(annotation) => {}}

  // Custom annotation tooltip (replaces native <title> tooltip)
  renderAnnotationTooltip={(annotation, rect) => (
    <div style={{
      position: 'absolute',
      left: rect.x + rect.width,
      top: rect.y,
      zIndex: 11,
    }}>
      {annotation.text}
    </div>
  )}

  // Custom overlay (SVG paths, highlights, drawings — works on PDF and images)
  renderOverlay={({ width, height, originalWidth, originalHeight, pageNumber, rotation }) => (
    <svg
      width={width}
      height={height}
      viewBox={`0 0 ${originalWidth} ${originalHeight}`}
      preserveAspectRatio="none"
      style={{ position: 'absolute', top: 0, left: 0, pointerEvents: 'all' }}
    >
      <path d="..." stroke="cyan" fill="none" />
    </svg>
  )}

  // Custom renderers (all optional)
  renderLoading={() => <MySpinner />}
  renderError={(error) => <MyError message={error.message} />}
  renderUnsupported={(mimeType) => <div>Cannot preview {mimeType}</div>}

  // Layout
  className="..."
  style={{ width: '100%', height: '100%' }}
/>

提示与技巧

源文件更改时重置页面、缩放和旋转。 切换文件时,组件不会自动重置这些设置 — 请自行处理:

const navigateToFile = (file: FileInfo) => {
  setSelectedFile(file);
  setPage(1);
  setZoom(1);
  setRotation(0);
};

仅当 numPages > 0 时显示分页 UI。 onDocumentLoad 只会对 PDF 触发。确定存在可分页的页面后,再渲染分页控件:

{numPages > 0 && (
  <>
    <button disabled={page <= 1} onClick={() => setPage(p => p - 1)}>‹</button>
    <span>{page} / {numPages}</span>
    <button disabled={page >= numPages} onClick={() => setPage(p => p + 1)}>›</button>
  </>
)}

点击注释 → 导航到关联文件。 annotation.linkedResource 包含关联 CDF 实例的 space 和 externalId。将其与 file.instanceId 匹配即可导航:

onAnnotationClick={(annotation) => {
  if (!annotation.linkedResource) return;
  const { space, externalId } = annotation.linkedResource;
  const linked = files.find(
    f => f.instanceId?.space === space && f.instanceId?.externalId === externalId
  );
  if (linked) navigateToFile(linked);
}}

内置触控支持。 在触控设备上,双指捏合缩放和双指拖动平移会自动生效。无需配置。

在桌面设备上,按住鼠标中键拖动即可平移(放大时)。鼠标左键仍可用于点击注释和选择文本。

按住 Ctrl/Cmd 并滚动滚轮可朝光标方向缩放 — 此功能也已内置。如果需要以编程方式添加缩放按钮或持久化缩放状态,请接入 zoom/onZoomChange;否则无需额外设置即可使用。

renderOverlay 接收页面的原始尺寸(originalWidth、originalHeight),因此你可以在原始坐标空间中设置 SVG viewBox。以 PDF 点或图像像素坐标绘制的路径,在任何缩放级别下都能正确映射到渲染后的页面。


常见问题

问题原因解决方法
Failed to resolve module specifier 'pdf.worker.mjs'未配置 Worker在使用 CogniteFileViewer 的同一个文件中,添加步骤 3 中的 Worker 设置
API version does not match Worker version应用与 react-pdf 之间的 pdfjs-dist 版本不匹配不要单独安装 pdfjs-dist — 由 react-pdf 提供即可。如果已安装,请将其移除
注释始终不显示instanceId 为 undefined — 未提供时会禁用注释叠加层使用 instanceId 源,或回退并接受经典文件不显示注释
注释显示但内容为空文件在 CDF 中没有 CogniteDiagramAnnotation 边这是预期行为 — 只有同步到数据模型的 P&ID/图纸文件才有注释
查看器高度变为零父级未设置明确的高度通过 style、className 或父级 CSS 设置 height

评论

支持 Markdown