@jzg223/design-runtime 0.0.1 → 0.1.0-rc.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/README.md +52 -0
  3. package/dist/board/api.js +57 -0
  4. package/dist/board/board-chart.vue.js +7 -0
  5. package/dist/board/board-chart2.vue.js +93 -0
  6. package/dist/board/context.js +15 -0
  7. package/dist/board/datav-map.js +66 -0
  8. package/dist/board/design-board.vue.js +172 -0
  9. package/dist/board/design-board2.vue.js +331 -0
  10. package/dist/board/echarts.js +40 -0
  11. package/dist/board/part-node.vue.js +63 -0
  12. package/dist/board/part-node2.vue.js +125 -0
  13. package/dist/board/part-renderer.vue.js +561 -0
  14. package/dist/board/part-renderer2.vue.js +884 -0
  15. package/dist/board/theme-host.js +129 -0
  16. package/dist/board-engine/asset.js +32 -0
  17. package/dist/board-engine/chart-option.js +377 -0
  18. package/dist/board-engine/data-hub.js +67 -0
  19. package/dist/board-engine/datav-meta.js +51 -0
  20. package/dist/board-engine/i18n.js +130 -0
  21. package/dist/board-engine/param-catalog.js +137 -0
  22. package/dist/board-engine/params.js +61 -0
  23. package/dist/board-engine/render-model.js +65 -0
  24. package/dist/board-engine/schema.js +856 -0
  25. package/dist/board-engine/theme-manifest.js +19 -0
  26. package/dist/board-engine/version.js +4 -0
  27. package/dist/host.js +6 -1
  28. package/dist/index.js +172 -24
  29. package/dist/style.css +1067 -0
  30. package/dist/types/board/api.d.ts +45 -0
  31. package/dist/types/board/board-chart.vue.d.ts +15 -0
  32. package/dist/types/board/context.d.ts +29 -0
  33. package/dist/types/board/datav-map.d.ts +24 -0
  34. package/dist/types/board/design-board.vue.d.ts +1409 -0
  35. package/dist/types/board/echarts.d.ts +25 -0
  36. package/dist/types/board/part-node.vue.d.ts +1237 -0
  37. package/dist/types/board/part-renderer.vue.d.ts +1205 -0
  38. package/dist/types/board/theme-host.d.ts +41 -0
  39. package/dist/types/board-engine/asset.d.ts +37 -0
  40. package/dist/types/board-engine/chart-option.d.ts +737 -0
  41. package/dist/types/board-engine/data-hub.d.ts +48 -0
  42. package/dist/types/board-engine/datav-meta.d.ts +37 -0
  43. package/dist/types/board-engine/i18n.d.ts +43 -0
  44. package/dist/types/board-engine/index.d.ts +25 -0
  45. package/dist/types/board-engine/param-catalog.d.ts +82 -0
  46. package/dist/types/board-engine/params.d.ts +37 -0
  47. package/dist/types/board-engine/render-model.d.ts +87 -0
  48. package/dist/types/board-engine/schema.d.ts +513 -0
  49. package/dist/types/board-engine/theme-manifest.d.ts +23 -0
  50. package/dist/types/board-engine/types.d.ts +147 -0
  51. package/dist/types/board-engine/version.d.ts +10 -0
  52. package/dist/types/host.d.ts +21 -0
  53. package/dist/types/index.d.ts +21 -2
  54. package/package.json +21 -4
package/CHANGELOG.md CHANGED
@@ -3,6 +3,24 @@
3
3
  版本规则:semver。**破坏性改动**(`installDesignPlatform` 的参数、公开导出、组件 props)
4
4
  必须升大版本,并在本文件写清「宿主需要改什么」。
5
5
 
6
+ ## 0.1.0(未发布,分支 `feat/board`)
7
+
8
+ 目标:把**数据看板运行端**迁入本库(design-ui 负责设计与预览,本库负责执行)。立项 2026-10-27。
9
+
10
+ - 组件:`DesignBoard`(+ `PartNode` / `PartRenderer` / `BoardChart`),覆盖 18 种部件、
11
+ 自由布局(1920×1080 缩放)/ 栅格 / 移动端堆叠三种布局
12
+ - 引擎单源:配置解析 / 布局样式 / 图表 option / 主题令牌 / 取数请求体抽成**零依赖**模块
13
+ (`src/board-engine/`,与 design-ui 逐字节一致,由 `test:board-fingerprint` 守住)
14
+ - 渲染契约:`partRenderModel()` 输出外层/面板/标题/边距/装饰/类名,两端模板只照它铺 DOM
15
+ - peer 新增:`echarts ^6.1.0`(**optional**,只有画图表时才动态加载)、
16
+ `@kjgl77/datav-vue3 ^1.7.4`(**optional**,边框/装饰部件,按编号懒加载)
17
+ - 宿主注入新增:`board?: { http?, assetBaseUrl?, themeBaseUrl? }`
18
+ - 多实例:参数 / 参数目录 / 取数缓存改为**每实例一份**(provide/inject),一页两个看板不串参数
19
+ - 不包含:看板设计器、看板列表/授权、数据集配置(留在 design-ui)
20
+ - 兼容性:对 0.0.1 的使用方**无破坏性改动**(只新增导出与可选注入字段);
21
+ 体积预算 1024 → 1536 KB(看板占 ~250 KB,其中 ~126 KB 是三个组件迁入后的 `.d.ts`)
22
+ - 用例:`test:board` 42 + `test:board-render` 9 + `test:board-fingerprint` 9(全套 185 条)
23
+
6
24
  ## 0.0.1(2026-10-27 首次发布)
7
25
 
8
26
  首个对外可用版本。**本版本包含**:
package/README.md CHANGED
@@ -198,6 +198,58 @@ transformTableConfig(config, '100%', {
198
198
 
199
199
  回归用例:`npm run test:table`(32 条,零依赖,跑的是 `dist` 产物,离线可跑)。
200
200
 
201
+ ## 数据看板(0.1.0)
202
+
203
+ 把 design-ui 里**设计好的看板**在业务宿主里渲染出来(设计/预览留在 design-ui,本库只负责执行)。
204
+
205
+ ### 1. 装依赖(两个 **optional** peer,用不到就不用装)
206
+
207
+ ```bash
208
+ pnpm add @jzg223/design-runtime
209
+ pnpm add echarts # 看板里有「图表」部件才需要(^6)
210
+ pnpm add @kjgl77/datav-vue3 # 看板里有「边框/装饰」部件才需要(^1.7)
211
+ ```
212
+
213
+ 两者都是**动态 import**:不进本库产物,也不会进不用看板的宿主首屏。
214
+
215
+ ### 2. 注入看板能力(都可缺省)
216
+
217
+ ```ts
218
+ installDesignPlatform({
219
+ http, // 主 http(看板默认也用它)
220
+ board: {
221
+ http: boardHttp, // 可选:看板接口在别的服务时单独指
222
+ assetBaseUrl: '/server', // 可选:素材直链前缀(asset: 引用),缺省同源
223
+ themeBaseUrl: '/board/theme/', // 可选:主题 CSS 目录,缺省这个值
224
+ },
225
+ })
226
+ ```
227
+
228
+ ### 3. 用
229
+
230
+ ```vue
231
+ <DesignBoard code="EMP_BIGSCREEN" lang="zh-CHS" />
232
+ ```
233
+
234
+ - 配置来源:`GET /design/board/info/queryByCode?code=`;
235
+ - 部件取数:`POST /design/board/data/query`(同查询自动合并 + 1.5s 合并窗口,刷新用工具栏按钮);
236
+ - 参数目录:`GET /design/board/dataset/paramsBySets?ids=`(筛选控件的类型/可选值以数据集声明为准);
237
+ - 素材:`GET /design/board/asset/file?path=`(**不经 http**,拼成 `<img src>`);
238
+ - 主题:外部 CSS(`<themeBaseUrl>/<code>.css`,按需 `<link>`),库内只有 `:root` 级兜底 + 3 套内置。
239
+ 47 套主题(651 KB)**不随包发**——它要能在部署后替换/新增。
240
+
241
+ ### 4. 三件要知道的事
242
+
243
+ 1. **必须先保存再看**:运行端只认 `code`,未保存的草稿没有 code(设计端的"预览"同理)。
244
+ 2. **多实例安全**:参数/取数缓存是 `provide/inject` 的**每实例一份**(不是模块级单例),
245
+ 一页放两个看板不会串参数。
246
+ 3. **DataV 边框/装饰是懒加载的**:整包里 25 个组件按编号 `defineAsyncComponent` 映射,
247
+ 配置里没用到就不会下载(`@kjgl77/datav-vue3` 解包 720 KB,是单入口整包,没有子路径导出)。
248
+
249
+ 回归用例:`npm run test:board`(引擎 42 条)+ `test:board-render`(组件 SSR 冒烟 9 条)+ `test:board-fingerprint`(双端指纹 9 条)。
250
+ `test:board-fingerprint` 会去读同工作区的 `design-ui` 引擎做**逐字节对比**——两边任一被改却没同步就红;
251
+ 单独 clone 本库时找不到 `design-ui`,它会打印 SKIP 并成功退出。
252
+
201
253
  ## 开发
202
254
 
203
255
  ```bash
@@ -0,0 +1,57 @@
1
+ import { getHostBoard, requireHttp } from "../host.js";
2
+ import { assetUrl } from "../board-engine/asset.js";
3
+ function boardHttp() {
4
+ return getHostBoard().http ?? requireHttp();
5
+ }
6
+ function boardAssetBaseUrl() {
7
+ return String(getHostBoard().assetBaseUrl ?? "");
8
+ }
9
+ function unwrap(res) {
10
+ if (res && typeof res === "object" && "code" in res && "data" in res) {
11
+ return res.data;
12
+ }
13
+ return res;
14
+ }
15
+ async function fetchBoardInfo(code) {
16
+ if (!code) return null;
17
+ const res = await boardHttp().get("/design/board/info/queryByCode", {
18
+ params: { code },
19
+ silent: true
20
+ });
21
+ const data = unwrap(res);
22
+ return data && data.boardCode ? data : null;
23
+ }
24
+ async function fetchBoardData(body) {
25
+ try {
26
+ const res = await boardHttp().post("/design/board/data/query", body, { silent: true });
27
+ return unwrap(res) ?? null;
28
+ } catch (error) {
29
+ console.warn("[design-board] 部件取数失败:", error);
30
+ return null;
31
+ }
32
+ }
33
+ async function fetchBoardParams(ids) {
34
+ if (!ids) return [];
35
+ try {
36
+ const res = await boardHttp().get("/design/board/dataset/paramsBySets", {
37
+ params: { ids },
38
+ silent: true
39
+ });
40
+ const list = unwrap(res);
41
+ return Array.isArray(list) ? list : [];
42
+ } catch (error) {
43
+ console.warn("[design-board] 参数目录取数失败(筛选控件退化为手填):", error);
44
+ return [];
45
+ }
46
+ }
47
+ function boardAssetUrl(value) {
48
+ return assetUrl(value, boardAssetBaseUrl());
49
+ }
50
+ export {
51
+ boardAssetBaseUrl,
52
+ boardAssetUrl,
53
+ boardHttp,
54
+ fetchBoardData,
55
+ fetchBoardInfo,
56
+ fetchBoardParams
57
+ };
@@ -0,0 +1,7 @@
1
+ import _sfc_main from "./board-chart2.vue.js";
2
+ /* empty css */
3
+ import _export_sfc from "../_virtual/_plugin-vue_export-helper.js";
4
+ const BoardChart = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-ab9edc2c"]]);
5
+ export {
6
+ BoardChart as default
7
+ };
@@ -0,0 +1,93 @@
1
+ import { defineComponent, ref, onMounted, onBeforeUnmount, watch, openBlock, createElementBlock, toDisplayString, createCommentVNode } from "vue";
2
+ const _hoisted_1 = {
3
+ key: 0,
4
+ class: "drb-chart__error"
5
+ };
6
+ const _sfc_main = /* @__PURE__ */ defineComponent({
7
+ __name: "board-chart",
8
+ props: {
9
+ option: { default: null }
10
+ },
11
+ emits: ["chart-click"],
12
+ setup(__props, { expose: __expose, emit: __emit }) {
13
+ const props = __props;
14
+ const emit = __emit;
15
+ const hostEl = ref(null);
16
+ const errorText = ref("");
17
+ let chart = null;
18
+ let observer = null;
19
+ let disposed = false;
20
+ async function loadEcharts() {
21
+ return import("./echarts.js");
22
+ }
23
+ function render() {
24
+ if (!chart) return;
25
+ const option = props.option;
26
+ if (!option || !Object.keys(option).length) {
27
+ chart.clear();
28
+ return;
29
+ }
30
+ chart.setOption(option, true);
31
+ chart.off("click");
32
+ chart.on("click", (payload) => emit("chart-click", payload));
33
+ resize();
34
+ }
35
+ function resize() {
36
+ if (!chart) return;
37
+ try {
38
+ chart.resize();
39
+ } catch {
40
+ }
41
+ }
42
+ onMounted(async () => {
43
+ if (!hostEl.value) return;
44
+ try {
45
+ const mod = await loadEcharts();
46
+ if (disposed || !hostEl.value) return;
47
+ const echarts = (mod == null ? void 0 : mod.default) ?? mod;
48
+ chart = echarts.init(hostEl.value);
49
+ render();
50
+ if (typeof ResizeObserver !== "undefined") {
51
+ observer = new ResizeObserver(() => resize());
52
+ observer.observe(hostEl.value);
53
+ }
54
+ window.addEventListener("resize", resize);
55
+ } catch (error) {
56
+ errorText.value = "图表不可用:宿主未安装 echarts(optional peer)";
57
+ console.error(
58
+ "[design-board] 加载 echarts 失败:请宿主执行 `pnpm add echarts`(^6;与 @vben/plugins 里那份同版本)。",
59
+ error
60
+ );
61
+ }
62
+ });
63
+ onBeforeUnmount(() => {
64
+ disposed = true;
65
+ window.removeEventListener("resize", resize);
66
+ if (observer) {
67
+ try {
68
+ observer.disconnect();
69
+ } catch {
70
+ }
71
+ observer = null;
72
+ }
73
+ if (chart) {
74
+ chart.dispose();
75
+ chart = null;
76
+ }
77
+ });
78
+ watch(() => props.option, () => render(), { deep: true });
79
+ __expose({ resize });
80
+ return (_ctx, _cache) => {
81
+ return openBlock(), createElementBlock("div", {
82
+ ref_key: "hostEl",
83
+ ref: hostEl,
84
+ class: "drb-chart"
85
+ }, [
86
+ errorText.value ? (openBlock(), createElementBlock("div", _hoisted_1, toDisplayString(errorText.value), 1)) : createCommentVNode("", true)
87
+ ], 512);
88
+ };
89
+ }
90
+ });
91
+ export {
92
+ _sfc_main as default
93
+ };
@@ -0,0 +1,15 @@
1
+ import { inject } from "vue";
2
+ const DESIGN_BOARD_CTX = Symbol("design-board-ctx");
3
+ function useBoardContext() {
4
+ const ctx = inject(DESIGN_BOARD_CTX, null);
5
+ if (!ctx) {
6
+ throw new Error(
7
+ "[design-board] 缺少看板上下文:part-node / part-renderer 必须放在 <DesignBoard> 内部使用"
8
+ );
9
+ }
10
+ return ctx;
11
+ }
12
+ export {
13
+ DESIGN_BOARD_CTX,
14
+ useBoardContext
15
+ };
@@ -0,0 +1,66 @@
1
+ import { defineAsyncComponent } from "vue";
2
+ const componentCache = /* @__PURE__ */ new Map();
3
+ let datavModulePromise = null;
4
+ let stylePromise = null;
5
+ function loadDatavModule() {
6
+ if (!datavModulePromise) {
7
+ datavModulePromise = import("@kjgl77/datav-vue3").then((mod) => {
8
+ const exports = mod && mod.default && typeof mod.default === "object" && !mod.BorderBox1 ? mod.default : mod;
9
+ return exports;
10
+ }).catch((error) => {
11
+ datavModulePromise = null;
12
+ throw error;
13
+ });
14
+ }
15
+ return datavModulePromise;
16
+ }
17
+ function ensureDatavStyle() {
18
+ if (!stylePromise) {
19
+ stylePromise = import("@kjgl77/datav-vue3/dist/style.css").catch((error) => {
20
+ stylePromise = null;
21
+ console.warn("[design-board] datav 样式加载失败(边框/装饰会缺描边):", error);
22
+ return null;
23
+ });
24
+ }
25
+ return stylePromise;
26
+ }
27
+ function lazyDatavComponent(name) {
28
+ const cached = componentCache.get(name);
29
+ if (cached) return cached;
30
+ const component = defineAsyncComponent(async () => {
31
+ await ensureDatavStyle();
32
+ const module = await loadDatavModule();
33
+ const resolved = module[name];
34
+ if (!resolved) {
35
+ console.warn(`[design-board] datav 组件 ${name} 不存在(@kjgl77/datav-vue3 版本不匹配?)`);
36
+ return { name: `Missing${name}`, render: () => null };
37
+ }
38
+ return resolved;
39
+ });
40
+ componentCache.set(name, component);
41
+ return component;
42
+ }
43
+ function datavBorderComponent(n, fallback = 8) {
44
+ const index = Number(n);
45
+ const safe = Number.isInteger(index) && index >= 1 && index <= 13 ? index : fallback;
46
+ return lazyDatavComponent(`BorderBox${safe}`);
47
+ }
48
+ function datavDecorationComponent(n, fallback = 5) {
49
+ const index = Number(n);
50
+ const safe = Number.isInteger(index) && index >= 1 && index <= 12 ? index : fallback;
51
+ return lazyDatavComponent(`Decoration${safe}`);
52
+ }
53
+ function preloadDatav() {
54
+ return ensureDatavStyle().then(() => loadDatavModule());
55
+ }
56
+ function resetDatavCache() {
57
+ componentCache.clear();
58
+ datavModulePromise = null;
59
+ stylePromise = null;
60
+ }
61
+ export {
62
+ datavBorderComponent,
63
+ datavDecorationComponent,
64
+ preloadDatav,
65
+ resetDatavCache
66
+ };
@@ -0,0 +1,172 @@
1
+ import _sfc_main from "./design-board2.vue.js";
2
+ import { resolveComponent, openBlock, createElementBlock, normalizeStyle, createElementVNode, normalizeClass, toDisplayString, Fragment, renderList, createTextVNode, createCommentVNode, createBlock } from "vue";
3
+ /* empty css */
4
+ /* empty css */
5
+ import _export_sfc from "../_virtual/_plugin-vue_export-helper.js";
6
+ const _hoisted_1 = ["data-board-theme"];
7
+ const _hoisted_2 = { class: "tb-title" };
8
+ const _hoisted_3 = {
9
+ key: 0,
10
+ class: "tb-params"
11
+ };
12
+ const _hoisted_4 = ["onClick"];
13
+ const _hoisted_5 = { class: "tb-ops" };
14
+ const _hoisted_6 = ["value"];
15
+ const _hoisted_7 = ["value"];
16
+ const _hoisted_8 = {
17
+ key: 0,
18
+ class: "watermark"
19
+ };
20
+ const _hoisted_9 = {
21
+ key: 1,
22
+ class: "board-empty"
23
+ };
24
+ function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
25
+ const _component_part_node = resolveComponent("part-node");
26
+ return openBlock(), createElementBlock("div", {
27
+ ref: "stage",
28
+ class: "board-view",
29
+ "data-board-theme": $options.themeCode,
30
+ style: normalizeStyle($options.stageStyle)
31
+ }, [
32
+ createElementVNode("div", {
33
+ class: normalizeClass(["board-toolbar", { "is-hidden": $data.toolbarHidden, "is-mobile": $options.isMobile }])
34
+ }, [
35
+ createElementVNode("span", _hoisted_2, toDisplayString($data.board.boardName || "看板"), 1),
36
+ $options.activeParams.length ? (openBlock(), createElementBlock("span", _hoisted_3, [
37
+ (openBlock(true), createElementBlock(Fragment, null, renderList($options.activeParams, (p) => {
38
+ return openBlock(), createElementBlock("span", {
39
+ key: p.code,
40
+ class: "tb-param"
41
+ }, [
42
+ createTextVNode(toDisplayString(p.code) + " = " + toDisplayString(p.value), 1),
43
+ createElementVNode("i", {
44
+ class: "tb-param__x",
45
+ title: "清除该参数",
46
+ onClick: ($event) => $options.clearParam(p.code)
47
+ }, "×", 8, _hoisted_4)
48
+ ]);
49
+ }), 128)),
50
+ createElementVNode("a", {
51
+ class: "tb-clear",
52
+ onClick: _cache[0] || (_cache[0] = (...args) => $options.clearAllParams && $options.clearAllParams(...args))
53
+ }, "清空")
54
+ ])) : createCommentVNode("", true),
55
+ createElementVNode("span", _hoisted_5, [
56
+ createElementVNode("select", {
57
+ class: "tb-lang",
58
+ value: $data.locale,
59
+ onChange: _cache[1] || (_cache[1] = ($event) => $options.onLocaleChange($event.target.value))
60
+ }, [
61
+ (openBlock(true), createElementBlock(Fragment, null, renderList($data.locales, (l) => {
62
+ return openBlock(), createElementBlock("option", {
63
+ key: l.code,
64
+ value: l.code
65
+ }, toDisplayString(l.label), 9, _hoisted_7);
66
+ }), 128))
67
+ ], 40, _hoisted_6),
68
+ createElementVNode("button", {
69
+ type: "button",
70
+ class: "tb-btn",
71
+ title: "刷新数据",
72
+ onClick: _cache[2] || (_cache[2] = (...args) => $options.refresh && $options.refresh(...args))
73
+ }, [..._cache[6] || (_cache[6] = [
74
+ createElementVNode("svg", {
75
+ viewBox: "0 0 16 16",
76
+ width: "14",
77
+ height: "14",
78
+ "aria-hidden": "true"
79
+ }, [
80
+ createElementVNode("path", {
81
+ fill: "currentColor",
82
+ d: "M13.5 8a5.5 5.5 0 1 1-1.6-3.9l-1.7 1.7h4.6V1.2l-1.5 1.5A7 7 0 1 0 15 8h-1.5z"
83
+ })
84
+ ], -1)
85
+ ])]),
86
+ createElementVNode("button", {
87
+ type: "button",
88
+ class: "tb-btn",
89
+ title: "全屏",
90
+ onClick: _cache[3] || (_cache[3] = (...args) => $options.toggleFullscreen && $options.toggleFullscreen(...args))
91
+ }, [..._cache[7] || (_cache[7] = [
92
+ createElementVNode("svg", {
93
+ viewBox: "0 0 16 16",
94
+ width: "14",
95
+ height: "14",
96
+ "aria-hidden": "true"
97
+ }, [
98
+ createElementVNode("path", {
99
+ fill: "currentColor",
100
+ d: "M1 1h5v1.5H3.06L6.5 5.94 5.44 7 2.5 4.06V6.5H1V1zm14 14h-5v-1.5h2.94L9.5 10.06 10.56 9l2.94 2.94V9.5H15V15z"
101
+ })
102
+ ], -1)
103
+ ])]),
104
+ createElementVNode("button", {
105
+ type: "button",
106
+ class: "tb-btn",
107
+ title: "隐藏工具栏",
108
+ onClick: _cache[4] || (_cache[4] = ($event) => $data.toolbarHidden = true)
109
+ }, [..._cache[8] || (_cache[8] = [
110
+ createElementVNode("svg", {
111
+ viewBox: "0 0 16 16",
112
+ width: "14",
113
+ height: "14",
114
+ "aria-hidden": "true"
115
+ }, [
116
+ createElementVNode("path", {
117
+ fill: "currentColor",
118
+ d: "M8 3c3 0 5.6 1.7 7 5-1.4 3.3-4 5-7 5S2.4 11.3 1 8c1.4-3.3 4-5 7-5zm0 1.5C5.9 4.5 4 5.7 2.7 8c1.3 2.3 3.2 3.5 5.3 3.5s4-1.2 5.3-3.5C12 5.7 10.1 4.5 8 4.5zm0 1.2a2.3 2.3 0 1 1 0 4.6 2.3 2.3 0 0 1 0-4.6z"
119
+ })
120
+ ], -1)
121
+ ])])
122
+ ])
123
+ ], 2),
124
+ $data.toolbarHidden ? (openBlock(), createElementBlock("div", {
125
+ key: 0,
126
+ class: "show-toolbar",
127
+ title: "显示工具栏",
128
+ onClick: _cache[5] || (_cache[5] = ($event) => $data.toolbarHidden = false)
129
+ }, "⚙")) : createCommentVNode("", true),
130
+ createElementVNode("div", {
131
+ class: "board-scroll",
132
+ style: normalizeStyle($options.scrollStyle)
133
+ }, [
134
+ createElementVNode("div", {
135
+ class: "canvas-holder",
136
+ style: normalizeStyle($options.holderStyle)
137
+ }, [
138
+ createElementVNode("div", {
139
+ class: "board-canvas",
140
+ style: normalizeStyle($options.canvasStyle)
141
+ }, [
142
+ (openBlock(true), createElementBlock(Fragment, null, renderList($options.topParts, (p) => {
143
+ return openBlock(), createBlock(_component_part_node, {
144
+ key: p.id,
145
+ "extra-class": "view-part",
146
+ part: p,
147
+ page: $data.config.page,
148
+ "all-parts": $options.visibleParts,
149
+ "theme-code": $data.config.page.chartTheme,
150
+ "refresh-key": $data.refreshKey,
151
+ "params-version": $data.paramsVersion,
152
+ narrow: $options.narrow || $options.stacked,
153
+ stacked: $options.stacked
154
+ }, null, 8, ["part", "page", "all-parts", "theme-code", "refresh-key", "params-version", "narrow", "stacked"]);
155
+ }), 128)),
156
+ $data.config.page.watermark ? (openBlock(), createElementBlock("div", _hoisted_8, toDisplayString($data.config.page.watermark), 1)) : createCommentVNode("", true)
157
+ ], 4)
158
+ ], 4)
159
+ ], 4),
160
+ !$data.board.id && !$data.loading ? (openBlock(), createElementBlock("div", _hoisted_9, [
161
+ _cache[9] || (_cache[9] = createElementVNode("span", {
162
+ class: "board-empty__icon",
163
+ "aria-hidden": "true"
164
+ }, "!", -1)),
165
+ createElementVNode("p", null, toDisplayString($data.errorMessage || "看板不存在或没有访问权限"), 1)
166
+ ])) : createCommentVNode("", true)
167
+ ], 12, _hoisted_1);
168
+ }
169
+ const designBoard = /* @__PURE__ */ _export_sfc(_sfc_main, [["render", _sfc_render], ["__scopeId", "data-v-16c3c220"]]);
170
+ export {
171
+ designBoard as default
172
+ };