唯杰地图 logo唯杰地图
VJMAP
EN

vjvp — 唯杰 AI 可视化平台二次开发

Use when working with 唯杰 AI 可视化平台 (VP / appvisual) — building dashboards in the editor, embedding screens into your own web app with the vjvpsdk runtime (createVpViewer, ctx.setData push-data, on/emit behavior events, add/remove widgets, windows, custom components, code-panel scripts), writing .vpproj.json project bodies by hand, composing multi-page control platforms with the SDK scaffold (config layer + code layer, sim engine, 3D/scada/map scene recipes), deploy/publish/iframe-embed, VP MCP/AI integration. Keywords 可视化平台 appvisual vjvpsdk 大屏 看板 驾驶舱 createVpViewer setData 组态 数字孪生 vpproj. IMPORTANT: vjvpsdk is NOT published to npm — obtain it via private registry or local package path; do not invent public npm install instructions.

vjvp/SKILL.md 9.4 KB130 行
原文
pkg: vjvpsdk@1.0.0        # 未发布到 npm:私有 registry 或本地路径安装
peer: vue@^3.5            # vue 由宿主工程提供
docsMcp: https://vjmap.com/server/vp/mcp
场景 入口
官方文档/示例 MCP https://vjmap.com/server/vp/mcp(平台自带 MCP:search_widgets / get_widget_metadata / search_documentation / get_doc / list_examples / get_example / validate_project,见 platform/mcp-and-ai.md)
SDK 类型定义(唯一权威) 包内 dist/vp-runtime.d.ts
组件 options 选项名字典(唯一权威) references/widget-schema.generated.json
手写工程 JSON 校验器 node scripts/validate-project-json.mjs <工程.json>

安装(重要:vjvpsdk 未发布到 npm)

# 方式一:本地目录(把拿到的 vjvpsdk 包放到 vendor/ 下)
npm i ./vendor/vjvpsdk
# package.json 里等价写法:"vjvpsdk": "file:./vendor/vjvpsdk"

# 方式二:私有 registry(按唯杰提供的地址配置 .npmrc 后)
npm i vjvpsdk

npm i vue@^3.5   # peer 依赖,必须装

不要 npm i vjvpsdk 指望公网 npm 能装到。包结构:ESM dist/vp-runtime.mjs + 类型 dist/vp-runtime.d.ts + 样式 dist/vp-runtime.css。

⚠️ file: 依赖 + vite 的坑:npm file: 是符号链接,vite 默认按真实路径解析 vp-runtime.mjs 里的 import "vue"——包在 vendor/ 之外(如工程目录之外的另一个磁盘目录)时会报 Failed to resolve import "vue"(HTTP 500)。修法二选一:① vite.config 加 resolve.preserveSymlinks: true(且 server.fs.allow 放行真实路径);② 把包复制进工程的 vendor/ 下(在 workspace 内即可正常解析)。

两种嵌入方式怎么选

  • 只要"把发布好的大屏放进页面" → iframe <vp平台地址>/view?project=<id>,零依赖(跨站嵌入若被拒载,检查平台响应头 X-Frame-Options / frame-ancestors,需部署侧放行)。模板见 templates/iframe-embed/。
  • 需要推数 / 事件 / 程序化改组件 → SDK createVpViewer。模板见 templates/vite-app/。

SDK 最小骨架(已按 vp-runtime.d.ts 核对)

import { createVpViewer, type VpProjectBody } from "vjvpsdk";
import "vjvpsdk/vp-runtime.css";  // exports 只放 .、./vp-runtime.css、./style.css(别名同文件)、./package.json;其余深路径会被拒

// body = 编辑器"导出工程"得到的 { project, connections, connectionData, dataRules }
const body: VpProjectBody = await (await fetch("/dashboards/sales.vpproj.json")).json();

const ctx = createVpViewer("#app", body, {
  params: { theme: "dark" },
  // ⚠️「导出工程」的 .vpproj.json 是精简形态(connectionData 省略 tableName/fields),SDK 不补齐,
  // 直挂会让柱/线/双轴图抛 TypeError(getFieldMeta 读 fields.find);挂载前补齐(完整 body 上为空操作)
  transformData(b: any) {
    for (const c of b.connections ?? []) for (const t of c.tables ?? []) {
      const d = b.connectionData?.[c.uid]?.find((x: any) => x.tableId === t.uid);
      if (d) { d.tableName ??= t.name; d.fields ??= t.fields; }
    }
  },
  onReady(ctx) {
    // 推数即重渲:ctx.setData(connectionUid, tableId, rows)
    setInterval(async () => ctx.setData("conn_sales", "tbl_sales", await fetchRows()), 5000);
    // 大屏「发送行为事件」→ 宿主;payload = 触发器 payload(itemClicked 为 {别名:值},click 为 undefined;该动作无 data 选项)
    ctx.on("open-detail", (_e, payload) => router.push(`/detail/${(payload as any)?.id}`));
  },
});
// 程序化改组件:ctx.getWidget("kpi_total")?.setOption("unit-text", "万元")
// 地图/组态句柄:ctx.getMap(uid) / ctx.getScada(uid);窗口:ctx.openWindow(uid)

VpViewerContext 主要成员(vp-runtime.d.ts):screens/getScreen/setActiveScreen、windows/openWindow/closeWindow、getWidget/findWidgets/getWidgetsByType/addWidget/removeWidget、setData/getData/refreshData/onDataChange、getParams/setParams/onParamsChange、on/emit/startEventInbound/onScript/onRequest、reload/destroy。

按问题找文档

要做什么 去读
编辑器搭屏/绑数据/配交互/导入导出(.vpproj.json/.vpproj.zip/.vp.tsx) platform/editor-guide.md
createVpViewer 嵌入、ctx 上下文、推数、事件、自定义组件 VpWidget、代码面板 platform/sdk.md
发布快照 / /view 观看 / iframe / 二次开发工程包 / 自行托管 platform/deploy-and-integrate.md
MCP 与 AI(search_widgets / get_widget_metadata / get_doc / validate_project) platform/mcp-and-ai.md
编辑器内已打开页面的 TSX 生成/改写环路(page_export_tsx / page_apply_project) page-live-loop.md
用 SDK 做完整管控平台:配置层+代码层、目录脚手架 sdk-app/scaffold.md
实时模拟引擎、告警/工单状态机、数据建模、推数节流 sdk-app/sim-pattern.md
三维/组态/地图场景配方、跨页联动 sdk-app/scene-recipes.md
手写 .vpproj.json 工程体:envelope 结构 / 数据连接 / 交互 / 视觉风格 / 坑 project-index.md → envelope.md · data.md · interactions.md · visual-style.md · gotchas.md
各组件家族 options 速查(15 篇) widgets/index.md
VP-TSX 写法(.vp.tsx 整工程代码) vptsx.md
11 个最小示例工程(vpproj.json + vp.tsx 对照,逐对回编译等值验证;成品大屏见 catalog 里的 data/ 路径) examples/catalog.md

手写工程 JSON 校验

node vjvp/scripts/validate-project-json.mjs data/sales.vpproj.json
# ERROR 退出码 1;WARN 仅提示。不带参数时校验 examples/*.json

校验项:组件 type 合法性、position/size 必填、字段绑定三元组与 uid、connections↔connectionData 一致性、connectionData.fields 完整形态(缺了图表整块空白)、map-2d 的 map-body、dataRules 引用、动态数据项、条件样式。

VP-TSX 离线编译链(已内置于 scripts/vptsx/)

# 类型检查(值/枚举/元组)。注意 tsc -p vjvp/scripts/vptsx/tsconfig.json 只查 runtime 与 scripts/vptsx/examples,不含你的文件
pnpm exec tsc --noEmit --strict --skipLibCheck --jsx react --jsxFactory h --jsxFragmentFactory Fragment --target ES2022 --module ESNext --moduleResolution Bundler <工程.vp.tsx>
pnpm exec tsx vjvp/scripts/vptsx/compile.mts <工程.vp.tsx>   # 执行 + 选项名检查 + 校验终审

runtime.ts(defineProject/h/bind/jsonConnection/interactions/on/act)+ types.generated.ts(80 组件 + 108 piece 全量类型,由 gen-types.mts 从 schema 确定性再生)+ 示例 scripts/vptsx/examples/energy-mini.vp.tsx。外部工作区需 npm i -D tsx typescript。写法权威见 references/vptsx.md。组态场景体检:node vjvp/scripts/check-scada-scene.mjs <工程.vpproj.json>。

模板

  • templates/vite-app/ — SDK 嵌入工程(vjvpsdk 走 file: 本地依赖,README)
  • templates/iframe-embed/ — 零依赖 iframe 嵌入

红旗

  1. 把 vjvpsdk 当已发布包直接 npm i → 装不到;走私有 registry 或本地 file: 路径。
  2. iframe 能满足的场景引入 60MB SDK → 先问是否要推数/事件。
  3. 组件选项名臆造(如 background-colour)→ 一律查 widget-schema.generated.json。
  4. connectionData 写成精简形态缺 fields → 图表整块空白(SDK 直挂柱/线/双轴图抛 TypeError);校验器会 WARN。编辑器「导出工程」的 .vpproj.json 就是精简形态,SDK 挂载前用上面骨架里的 transformData 补齐。
  5. basic-graphical 不是容器——widgets 只能放 screen/group-panel/group-tabs/group-popup/layout-*(data-repeater/window-instance/scada-2d 的派生子级不走 node.widgets)。
  6. 工程 JSON / 代码里不写 token、内网地址。