init
@ -0,0 +1,40 @@
|
|||||||
|
{
|
||||||
|
"name": "scrin-visual-editor",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"type": "module",
|
||||||
|
"license": "MIT",
|
||||||
|
"main": "dist/scrin-visual-editor.umd.js",
|
||||||
|
"module": "dist/scrin-visual-editor.es.js",
|
||||||
|
"style": "dist/style.css",
|
||||||
|
"types": "dist/index.d.ts",
|
||||||
|
"files": [
|
||||||
|
"dist"
|
||||||
|
],
|
||||||
|
"exports": {
|
||||||
|
".": {
|
||||||
|
"import": "./dist/scrin-visual-editor.es.js",
|
||||||
|
"require": "./dist/scrin-visual-editor.umd.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"build": "vite build",
|
||||||
|
"dev": "vite build --watch"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@vue-flow/background": "^1.3.2",
|
||||||
|
"@vue-flow/core": "^1.48.2",
|
||||||
|
"@vue-flow/node-resizer": "^1.5.1",
|
||||||
|
"uuid": "^11.0.5"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@vitejs/plugin-vue": "^6.0.4",
|
||||||
|
"element-plus": "^2.13.3",
|
||||||
|
"less": "^4.5.1",
|
||||||
|
"vite": "^7.3.1",
|
||||||
|
"vue": "^3.5.29"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"element-plus": "^2.13.3",
|
||||||
|
"vue": "^3.3.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 7.0 KiB |
|
After Width: | Height: | Size: 6.2 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 5.0 KiB |
|
After Width: | Height: | Size: 8.0 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 4.3 KiB |
|
After Width: | Height: | Size: 8.4 KiB |
|
After Width: | Height: | Size: 9.0 KiB |
|
After Width: | Height: | Size: 8.2 KiB |
|
After Width: | Height: | Size: 9.4 KiB |
|
After Width: | Height: | Size: 8.1 KiB |
|
After Width: | Height: | Size: 6.9 KiB |
|
After Width: | Height: | Size: 37 KiB |
|
After Width: | Height: | Size: 1011 B |
|
After Width: | Height: | Size: 44 KiB |
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 1000 B |
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 955 B |
|
After Width: | Height: | Size: 527 B |
|
After Width: | Height: | Size: 527 B |
|
After Width: | Height: | Size: 527 B |
|
After Width: | Height: | Size: 632 B |
|
After Width: | Height: | Size: 632 B |
|
After Width: | Height: | Size: 456 B |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 635 B |
|
After Width: | Height: | Size: 532 B |
@ -0,0 +1,470 @@
|
|||||||
|
<template>
|
||||||
|
<div class="hw-root">
|
||||||
|
<div class="visual-editor">
|
||||||
|
<div class="visual-editor-top">
|
||||||
|
<div style="display: inline-block;">
|
||||||
|
<el-popover
|
||||||
|
:width="880"
|
||||||
|
trigger="click"
|
||||||
|
placement="bottom-start">
|
||||||
|
<template #reference>
|
||||||
|
<div style="margin-left: 20px;display: inline-block">
|
||||||
|
<svg viewBox="0 0 1024 1024" width="20" height="20" style="margin-top: 15px;">
|
||||||
|
<path
|
||||||
|
d="M629.333333 160v768h-213.333333v-768h213.333333z m-277.333333 192v576h-213.333333v-576h213.333333z m554.666667 213.333333v362.666667h-213.333334v-362.666667h213.333334z m-341.333334-341.333333h-85.333333v640h85.333333v-640z m-277.333333 192h-85.333333v448h85.333333v-448z m554.666667 213.333333h-85.333334v234.666667h85.333334v-234.666667z"
|
||||||
|
fill="#ddd" p-id="10516"></path>
|
||||||
|
</svg>
|
||||||
|
<el-icon color="#eee" :size="10" style="margin-top: 20px;margin-left: 8px;;vertical-align: top">
|
||||||
|
<component :is="icon.ArrowDown"/>
|
||||||
|
</el-icon>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<div style="max-height: 60vh;overflow:auto;">
|
||||||
|
<BoardNodes/>
|
||||||
|
</div>
|
||||||
|
</el-popover>
|
||||||
|
<el-popover
|
||||||
|
:width="620"
|
||||||
|
trigger="click"
|
||||||
|
placement="bottom-start">
|
||||||
|
<template #reference>
|
||||||
|
<div style="margin-left: 30px;display: inline-block">
|
||||||
|
<svg viewBox="0 0 1024 1024" width="20" height="20" style="margin-top: 15px;">
|
||||||
|
<path
|
||||||
|
d="M108.8 224v576C108.8 902.4 313.6 960 512 960s403.2-57.6 403.2-160v-576C915.2 12.8 108.8 12.8 108.8 224z m742.4 390.4c0 32-121.6 96-339.2 96s-339.2-64-339.2-96V518.4C249.6 563.2 384 588.8 512 588.8s262.4-25.6 339.2-70.4v96z m0-300.8v108.8c0 32-121.6 96-339.2 96s-339.2-64-339.2-96V313.6h6.4c6.4 6.4 12.8 12.8 19.2 12.8h6.4c12.8 6.4 19.2 6.4 32 12.8 19.2 12.8 32 12.8 44.8 19.2 70.4 19.2 147.2 25.6 230.4 25.6s160-6.4 230.4-25.6c12.8-6.4 25.6-6.4 38.4-12.8 12.8-6.4 25.6-6.4 32-12.8h6.4c12.8-6.4 19.2-12.8 32-19.2-6.4 0 0 0 0 0zM512 128c217.6 0 339.2 64 339.2 96S729.6 320 512 320 172.8 256 172.8 224 294.4 128 512 128z m0 768c-217.6 0-339.2-64-339.2-96V704c76.8 44.8 211.2 70.4 339.2 70.4s262.4-25.6 339.2-70.4v89.6c0 38.4-121.6 102.4-339.2 102.4z"
|
||||||
|
fill="#ddd" p-id="22021"></path>
|
||||||
|
</svg>
|
||||||
|
<el-icon color="#eee" :size="10" style="margin-top: 20px;margin-left: 8px;;vertical-align: top">
|
||||||
|
<component :is="icon.ArrowDown"/>
|
||||||
|
</el-icon>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<div style="max-height: 60vh;overflow:auto;">
|
||||||
|
<CustomData/>
|
||||||
|
</div>
|
||||||
|
</el-popover>
|
||||||
|
<el-popover
|
||||||
|
:width="620"
|
||||||
|
trigger="click"
|
||||||
|
placement="bottom-start"
|
||||||
|
>
|
||||||
|
<template #reference>
|
||||||
|
<div style="margin-left: 30px;display: inline-block">
|
||||||
|
<svg viewBox="0 0 1024 1024" width="20" height="20" style="margin-top: 15px;">
|
||||||
|
<path
|
||||||
|
d="M959.825022 384.002258V191.939717C959.825022 121.2479 902.517291 63.940169 831.825474 63.940169H191.939717C121.2479 63.940169 63.940169 121.2479 63.940169 191.939717v639.885757C63.940169 902.517291 121.2479 959.825022 191.939717 959.825022h639.885757c70.691817 0 127.999548-57.307731 127.999548-127.999548V384.002258zM146.66502 146.66502a63.737872 63.737872 0 0 1 45.336109-18.784682h639.997742A63.961844 63.961844 0 0 1 895.884854 192.001129V320.062089H127.880338V192.001129A63.737872 63.737872 0 0 1 146.66502 146.66502z m269.1267 461.308451v-223.971213h192.181751v223.971213h-192.181751z m192.181751 63.940169v223.971214h-192.181751v-223.971214h192.181751z m-256.12192-63.940169H127.880338v-223.971213h223.971213v223.971213z m-205.186531 269.235073a63.466939 63.466939 0 0 1-18.784682-45.209673V671.91364h223.971213v223.971214H192.001129a63.625887 63.625887 0 0 1-45.336109-18.67631z m749.219834-45.209673A63.763159 63.763159 0 0 1 831.998871 895.884854H671.91364v-223.971214h223.971214v160.085231z m0-224.0254h-223.971214v-223.971213h223.971214v223.971213z"
|
||||||
|
fill="#ddd" p-id="23072"></path>
|
||||||
|
</svg>
|
||||||
|
<el-icon color="#eee" :size="10" style="margin-top: 20px;margin-left: 8px;;vertical-align: top">
|
||||||
|
<component :is="icon.ArrowDown"/>
|
||||||
|
</el-icon>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<div style="max-height: 60vh;overflow:auto;">
|
||||||
|
<FormNodes/>
|
||||||
|
</div>
|
||||||
|
</el-popover>
|
||||||
|
<el-popover
|
||||||
|
:width="620"
|
||||||
|
trigger="click"
|
||||||
|
placement="bottom-start"
|
||||||
|
>
|
||||||
|
<template #reference>
|
||||||
|
<div style="margin-left: 30px;display: inline-block;vertical-align: top">
|
||||||
|
<el-icon color="#fff" style="margin-top: 15px;">
|
||||||
|
<component :is="icon.Opportunity"/>
|
||||||
|
</el-icon>
|
||||||
|
<el-icon color="#eee" :size="10" style="margin-top: 20px;margin-left: 8px;;vertical-align: top">
|
||||||
|
<component :is="icon.ArrowDown"/>
|
||||||
|
</el-icon>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<div style="max-height: 60vh;overflow:auto;">
|
||||||
|
<OtherNodes :icons="icon"/>
|
||||||
|
</div>
|
||||||
|
</el-popover>
|
||||||
|
</div>
|
||||||
|
<div class="options-menu">
|
||||||
|
<el-icon color="#ddd" :size="20" style="margin-top: 15px;margin-left: 20px;vertical-align: top"
|
||||||
|
@click="pageSetting">
|
||||||
|
<component :is="icon.Setting"/>
|
||||||
|
</el-icon>
|
||||||
|
<el-icon color="#ddd" :size="20" style="margin-top: 15px;margin-left: 20px;vertical-align: top" @click="save">
|
||||||
|
<component :is="icon.DocumentChecked"/>
|
||||||
|
</el-icon>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="visual-editor-left">
|
||||||
|
<div class="title">
|
||||||
|
图层
|
||||||
|
</div>
|
||||||
|
<div class="levels">
|
||||||
|
<el-dropdown
|
||||||
|
style="min-width: 100%;display: inline-block"
|
||||||
|
v-for="i in nodes.filter(e => e.type !== 'area').reverse()"
|
||||||
|
:key="i.id"
|
||||||
|
trigger="contextmenu"
|
||||||
|
@command="nodeOperate">
|
||||||
|
<div class="level" :class="{isSelect: i.selected}" @contextmenu.prevent @click="pitchOnNode(i)">
|
||||||
|
<div class="isLock">
|
||||||
|
<el-icon style="cursor: pointer" color="#fff" :size="16" @click="i.draggable = !i.draggable">
|
||||||
|
<Unlock v-if="i.draggable"/>
|
||||||
|
<Lock v-if="!i.draggable"/>
|
||||||
|
</el-icon>
|
||||||
|
</div>
|
||||||
|
<div class="icon">
|
||||||
|
<svg viewBox="0 0 1024 1024" width="16" height="16" style="margin-left: 10px;">
|
||||||
|
<path
|
||||||
|
d="M629.333333 160v768h-213.333333v-768h213.333333z m-277.333333 192v576h-213.333333v-576h213.333333z m554.666667 213.333333v362.666667h-213.333334v-362.666667h213.333334z m-341.333334-341.333333h-85.333333v640h85.333333v-640z m-277.333333 192h-85.333333v448h85.333333v-448z m554.666667 213.333333h-85.333334v234.666667h85.333334v-234.666667z"
|
||||||
|
fill="#ddd"
|
||||||
|
></path>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<div class="boardName">
|
||||||
|
<span style="display: inline-block;">{{ i.name }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<template #dropdown>
|
||||||
|
<el-dropdown-menu>
|
||||||
|
<el-dropdown-item :command="{ type: 'toTop', node: i }">置顶</el-dropdown-item>
|
||||||
|
<el-dropdown-item :command="{ type: 'toBottom', node: i }">置底</el-dropdown-item>
|
||||||
|
<el-dropdown-item :command="{ type: 'moveUp', node: i }">上移一层</el-dropdown-item>
|
||||||
|
<el-dropdown-item :command="{ type: 'moveDown', node: i }">下移一层</el-dropdown-item>
|
||||||
|
<el-dropdown-item :command="{ type: 'copy', node: i }">复制</el-dropdown-item>
|
||||||
|
<el-dropdown-item :command="{ type: 'del', node: i }">删除</el-dropdown-item>
|
||||||
|
</el-dropdown-menu>
|
||||||
|
</template>
|
||||||
|
</el-dropdown>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="visual-editor-center" @drop="onDrop" v-loading="loading">
|
||||||
|
<FlowRuler>
|
||||||
|
<VueFlow
|
||||||
|
id="flowA"
|
||||||
|
:min-zoom="0.01"
|
||||||
|
ref="flowRef"
|
||||||
|
:snapToGrid="isSnapToGrid"
|
||||||
|
:snapGrid="[10, 10]"
|
||||||
|
v-model:nodes="nodes"
|
||||||
|
v-model:edges="edges"
|
||||||
|
fit-view-on-init
|
||||||
|
default-marker-color="#409EFF"
|
||||||
|
@connect="logEvent('connect', $event)"
|
||||||
|
@node-click="logEvent('click', $event)"
|
||||||
|
@pane-click="logEvent('paneClick', $event)"
|
||||||
|
@node-drag-start="logEvent('nodeDrag', $event)"
|
||||||
|
@node-contextMenu="logEvent('contextmenu', $event)"
|
||||||
|
@dragover="onDragOver"
|
||||||
|
>
|
||||||
|
<Background :size="1" :gap="20" pattern-color="#BDBDBD" style="background-color: #000"/>
|
||||||
|
|
||||||
|
<template #node-area="props">
|
||||||
|
<AreaNode v-bind="props" :pageData="pageData" @resize="(e) => handleResizeStop(e, props)"/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #node-customBoard="props">
|
||||||
|
<CustomBoardNode v-bind="props" :inputData="getInputData(props.id)"
|
||||||
|
@resize="(e) => handleResizeStop(e, props)"/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #node-customData="props">
|
||||||
|
<CustomDataNode v-bind="props" :inputData="getInputData(props.id)"
|
||||||
|
@resize="(e) => handleResizeStop(e, props)"/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #node-line="props">
|
||||||
|
<LineNode :colors="pageSettingForm.colors" v-bind="props" :inputData="getInputData(props.id)"
|
||||||
|
@resize="(e) => handleResizeStop(e, props)"/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #node-multiLines="props">
|
||||||
|
<MultiLinesNode :colors="pageSettingForm.colors" v-bind="props" :inputData="getInputData(props.id)"
|
||||||
|
@resize="(e) => handleResizeStop(e, props)"/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #node-curve="props">
|
||||||
|
<CurveNode :colors="pageSettingForm.colors" v-bind="props" :inputData="getInputData(props.id)"
|
||||||
|
@resize="(e) => handleResizeStop(e, props)"/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #node-multiCurves="props">
|
||||||
|
<MultiCurvesNode :colors="pageSettingForm.colors" v-bind="props" :inputData="getInputData(props.id)"
|
||||||
|
@resize="(e) => handleResizeStop(e, props)"/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #node-lineBar="props">
|
||||||
|
<LineBarNode :colors="pageSettingForm.colors" v-bind="props" :inputData="getInputData(props.id)"
|
||||||
|
@resize="(e) => handleResizeStop(e, props)"/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #node-bar="props">
|
||||||
|
<BarNode :colors="pageSettingForm.colors" v-bind="props" :inputData="getInputData(props.id)"
|
||||||
|
@resize="(e) => handleResizeStop(e, props)"/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #node-backgroundBar="props">
|
||||||
|
<BackgroundBarNode :colors="pageSettingForm.colors" v-bind="props" :inputData="getInputData(props.id)"
|
||||||
|
@resize="(e) => handleResizeStop(e, props)"/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #node-multiBars="props">
|
||||||
|
<MultiBarsNode :colors="pageSettingForm.colors" v-bind="props" :inputData="getInputData(props.id)"
|
||||||
|
@resize="(e) => handleResizeStop(e, props)"/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #node-pie="props">
|
||||||
|
<PieNode :colors="pageSettingForm.colors" v-bind="props" :inputData="getInputData(props.id)"
|
||||||
|
@resize="(e) => handleResizeStop(e, props)"/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #node-annular="props">
|
||||||
|
<AnnularNode :colors="pageSettingForm.colors" v-bind="props" :inputData="getInputData(props.id)"
|
||||||
|
@resize="(e) => handleResizeStop(e, props)"/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #node-radar="props">
|
||||||
|
<RadarNode :colors="pageSettingForm.colors" v-bind="props" :inputData="getInputData(props.id)"
|
||||||
|
@resize="(e) => handleResizeStop(e, props)"/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #node-dashboard="props">
|
||||||
|
<DashboardNode :colors="pageSettingForm.colors" v-bind="props" :inputData="getInputData(props.id)"
|
||||||
|
@resize="(e) => handleResizeStop(e, props)"/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #node-props="props">
|
||||||
|
<NightingaleRoseDiagramNode :colors="pageSettingForm.colors" v-bind="props"
|
||||||
|
:inputData="getInputData(props.id)"
|
||||||
|
@resize="(e) => handleResizeStop(e, props)"/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #node-carousel="props">
|
||||||
|
<CarouselNode :colors="pageSettingForm.colors" v-bind="props" :inputData="getInputData(props.id)"
|
||||||
|
@resize="(e) => handleResizeStop(e, props)"/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #node-data="props">
|
||||||
|
<DataNode :colors="pageSettingForm.colors" v-bind="props" :inputData="getInputData(props.id)"
|
||||||
|
@resize="(e) => handleResizeStop(e, props)"/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #node-text="props">
|
||||||
|
<TextNode :colors="pageSettingForm.colors" v-bind="props" :inputData="getInputData(props.id)"
|
||||||
|
@resize="(e) => handleResizeStop(e, props)"/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #node-img="imgNodeProps">
|
||||||
|
<ImgNode :colors="pageSettingForm.colors" v-bind="imgNodeProps" :inputData="getInputData(imgNodeProps.id)"
|
||||||
|
@resize="(e) => handleResizeStop(e, imgNodeProps)"/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #node-icon="iconNodeProps">
|
||||||
|
<IconNode :colors="pageSettingForm.colors" v-bind="iconNodeProps"
|
||||||
|
:inputData="getInputData(iconNodeProps.id)"
|
||||||
|
@resize="(e) => handleResizeStop(e, iconNodeProps)"/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #node-video="videoNodeProps">
|
||||||
|
<VideoNode :colors="pageSettingForm.colors" v-bind="videoNodeProps"
|
||||||
|
:inputData="getInputData(videoNodeProps.id)"
|
||||||
|
@resize="(e) => handleResizeStop(e, videoNodeProps)"/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #node-timeline="timelineNodeProps">
|
||||||
|
<TimelineNode :colors="pageSettingForm.colors" v-bind="timelineNodeProps"
|
||||||
|
:inputData="getInputData(timelineNodeProps.id)"
|
||||||
|
@resize="(e) => handleResizeStop(e, timelineNodeProps)"/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #node-digitalFlop="digitalFlopNodeProps">
|
||||||
|
<DigitalFlopNode :colors="pageSettingForm.colors" v-bind="digitalFlopNodeProps"
|
||||||
|
:inputData="getInputData(digitalFlopNodeProps.id)"
|
||||||
|
@resize="(e) => handleResizeStop(e, digitalFlopNodeProps)"/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #node-inputNode="inputNodeProps">
|
||||||
|
<InputNode :colors="pageSettingForm.colors" v-bind="inputNodeProps"
|
||||||
|
:inputData="getInputData(inputNodeProps.id)"
|
||||||
|
@resize="(e) => handleResizeStop(e, inputNodeProps)"/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #node-buttonNode="buttonNodeProps">
|
||||||
|
<ButtonNode :colors="pageSettingForm.colors" v-bind="buttonNodeProps"
|
||||||
|
:inputData="getInputData(buttonNodeProps.id)"
|
||||||
|
@resize="(e) => handleResizeStop(e, buttonNodeProps)"/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #node-selectNode="selectNodeProps">
|
||||||
|
<SelectNode :colors="pageSettingForm.colors" v-bind="selectNodeProps"
|
||||||
|
:inputData="getInputData(selectNodeProps.id)"
|
||||||
|
@resize="(e) => handleResizeStop(e, selectNodeProps)"/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #node-time="props">
|
||||||
|
<TimeNode :colors="pageSettingForm.colors" v-bind="props" :inputData="getInputData(props.id)"
|
||||||
|
@resize="(e) => handleResizeStop(e, props)"/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #node-map="mapNodeProps">
|
||||||
|
<MapNode :colors="pageSettingForm.colors" v-bind="mapNodeProps" :inputData="getInputData(mapNodeProps.id)"
|
||||||
|
@resize="(e) => handleResizeStop(e, mapNodeProps)"/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #node-staticData="staticDataNodeProps">
|
||||||
|
<StaticDataNode :colors="pageSettingForm.colors" v-bind="staticDataNodeProps"
|
||||||
|
:inputData="getInputData(staticDataNodeProps.id)"
|
||||||
|
@resize="(e) => handleResizeStop(e, staticDataNodeProps)"/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #node-table="tableNodeProps">
|
||||||
|
<TableNode :colors="pageSettingForm.colors" v-bind="tableNodeProps"
|
||||||
|
:inputData="getInputData(tableNodeProps.id)"
|
||||||
|
@resize="(e) => handleResizeStop(e, tableNodeProps)"/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #node-scrollTable="scrollTableNodeProps">
|
||||||
|
<ScrollTableNode :colors="pageSettingForm.colors" v-bind="scrollTableNodeProps"
|
||||||
|
:inputData="getInputData(scrollTableNodeProps.id)"
|
||||||
|
@resize="(e) => handleResizeStop(e, scrollTableNodeProps)"/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #node-background="backgroundNodeProps">
|
||||||
|
<BackgroundNode :colors="pageSettingForm.colors" v-bind="backgroundNodeProps"
|
||||||
|
:inputData="getInputData(backgroundNodeProps.id)"
|
||||||
|
@resize="(e) => handleResizeStop(e, backgroundNodeProps)"/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #node-pagination="paginationNodeProps">
|
||||||
|
<PaginationNode :colors="pageSettingForm.colors" v-bind="paginationNodeProps"
|
||||||
|
:inputData="getInputData(paginationNodeProps.id)"
|
||||||
|
@resize="(e) => handleResizeStop(e, paginationNodeProps)"/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #node-menu="props">
|
||||||
|
<MenuNode :colors="pageSettingForm.colors" v-bind="props" :inputData="getInputData(props.id)"
|
||||||
|
@resize="(e) => handleResizeStop(e, props)"/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #node-tree="props">
|
||||||
|
<TreeNode :colors="pageSettingForm.colors" v-bind="props" :inputData="getInputData(props.id)"
|
||||||
|
@resize="(e) => handleResizeStop(e, props)"/>
|
||||||
|
</template>
|
||||||
|
</VueFlow>
|
||||||
|
</FlowRuler>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup>
|
||||||
|
import {MarkerType, useVueFlow, VueFlow} from '@vue-flow/core';
|
||||||
|
import tool from '../../util/tool.js';
|
||||||
|
import {Background} from '@vue-flow/background';
|
||||||
|
import * as icon from '@element-plus/icons-vue';
|
||||||
|
import BoardNodes from '../inside/boardNodes/index.vue'
|
||||||
|
import CustomData from '../inside/customData/index.vue'
|
||||||
|
import FormNodes from '../inside/formNodes/index.vue'
|
||||||
|
import OtherNodes from '../inside/otherNodes/index.vue'
|
||||||
|
import FlowRuler from '../inside/FlowRuler.vue'
|
||||||
|
|
||||||
|
const nodes = ref([])
|
||||||
|
const {onDragStart, onDrop, onDragOver} = tool();
|
||||||
|
|
||||||
|
</script>
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.hw-root {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
min-height: 80vh;
|
||||||
|
--visual-editor-top-height: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.visual-editor {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
.visual-editor-top {
|
||||||
|
width: 100%;
|
||||||
|
height: var(--visual-editor-top-height);
|
||||||
|
background-color: #1C1F20;
|
||||||
|
border-bottom: 1px solid #000;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.options-menu {
|
||||||
|
vertical-align: top;
|
||||||
|
display: inline-block;
|
||||||
|
position: absolute;
|
||||||
|
right: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.visual-editor-left {
|
||||||
|
width: 200px;
|
||||||
|
height: calc(100% - var(--visual-editor-top-height));
|
||||||
|
display: inline-block;
|
||||||
|
overflow: auto;
|
||||||
|
background-color: #1C1F20;
|
||||||
|
border-right: 1px solid #000;
|
||||||
|
|
||||||
|
.title {
|
||||||
|
width: 100%;
|
||||||
|
height: 50px;
|
||||||
|
line-height: 50px;
|
||||||
|
text-align: center;
|
||||||
|
color: #FFF;
|
||||||
|
background-color: #293133;
|
||||||
|
border-bottom: 1px solid #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.levels {
|
||||||
|
width: 100%;
|
||||||
|
height: calc(100% - 50px);
|
||||||
|
overflow: auto;
|
||||||
|
background-color: #1C1F20;
|
||||||
|
|
||||||
|
&::-webkit-scrollbar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.level {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
height: 50px;
|
||||||
|
padding-left: 20px;
|
||||||
|
border-bottom: 1px solid #000;
|
||||||
|
|
||||||
|
.icon, .boardName {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
width: 40px;
|
||||||
|
min-width: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.boardName {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.isSelect {
|
||||||
|
background-color: #494949;
|
||||||
|
|
||||||
|
.isShow {
|
||||||
|
border-right: 1px solid #373737;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.visual-editor-center {
|
||||||
|
width: calc(100% - 500px);
|
||||||
|
display: inline-block;
|
||||||
|
background-color: #1C1F20;
|
||||||
|
height: calc(100vh - var(--visual-editor-top-height));
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,158 @@
|
|||||||
|
<template>
|
||||||
|
<div class="hw-flow-ruler-container">
|
||||||
|
<div class="hw-flow-ruler-x">
|
||||||
|
<canvas ref="rulerXCanvas" class="hw-flow-ruler-canvas"></canvas>
|
||||||
|
</div>
|
||||||
|
<div class="hw-flow-ruler-main-content">
|
||||||
|
<div class="hw-flow-ruler-y">
|
||||||
|
<canvas ref="rulerYCanvas" class="hw-flow-ruler-canvas"></canvas>
|
||||||
|
</div>
|
||||||
|
<slot/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import {ref, onMounted} from 'vue';
|
||||||
|
import {useVueFlow} from '@vue-flow/core';
|
||||||
|
|
||||||
|
const rulerXCanvas = ref(null);
|
||||||
|
const rulerYCanvas = ref(null);
|
||||||
|
const {viewport} = useVueFlow();
|
||||||
|
|
||||||
|
let animationFrameId = null;
|
||||||
|
let lastRenderTime = 0;
|
||||||
|
const FRAME_INTERVAL = 1000 / 60;
|
||||||
|
|
||||||
|
const getNiceStep = (target) => {
|
||||||
|
const steps = [1, 2, 5, 10, 20, 25, 50, 100, 200, 500, 1000];
|
||||||
|
return steps.find(s => s * viewport.value.zoom >= target) || 1000;
|
||||||
|
};
|
||||||
|
|
||||||
|
const drawRulers = () => {
|
||||||
|
const scale = viewport.value.zoom;
|
||||||
|
const offsetX = viewport.value.x;
|
||||||
|
const offsetY = viewport.value.y;
|
||||||
|
|
||||||
|
const step = getNiceStep(10);
|
||||||
|
const bigStep = step * 10;
|
||||||
|
const leftOffset = 30;
|
||||||
|
const rulerSize = 30;
|
||||||
|
|
||||||
|
const xCanvas = rulerXCanvas.value;
|
||||||
|
const xCtx = xCanvas.getContext('2d');
|
||||||
|
xCanvas.width = xCanvas.offsetWidth * window.devicePixelRatio;
|
||||||
|
xCanvas.height = xCanvas.offsetHeight * window.devicePixelRatio;
|
||||||
|
xCtx.scale(window.devicePixelRatio, window.devicePixelRatio);
|
||||||
|
xCtx.clearRect(0, 0, xCanvas.offsetWidth, xCanvas.offsetHeight);
|
||||||
|
|
||||||
|
xCtx.fillStyle = '#999';
|
||||||
|
xCtx.font = '10px sans-serif';
|
||||||
|
|
||||||
|
const canvasWidth = xCanvas.offsetWidth;
|
||||||
|
const startWorldX = Math.floor((-offsetX - leftOffset) / scale / step) * step;
|
||||||
|
const endWorldX = (-offsetX + canvasWidth) / scale;
|
||||||
|
|
||||||
|
for (let worldX = startWorldX; worldX < endWorldX; worldX += step) {
|
||||||
|
const screenX = worldX * scale + offsetX + leftOffset;
|
||||||
|
xCtx.beginPath();
|
||||||
|
if (Math.round(worldX) % bigStep === 0) {
|
||||||
|
xCtx.strokeStyle = '#fff';
|
||||||
|
xCtx.moveTo(screenX, rulerSize - 20);
|
||||||
|
xCtx.lineTo(screenX, rulerSize);
|
||||||
|
xCtx.stroke();
|
||||||
|
xCtx.fillStyle = '#ccc';
|
||||||
|
xCtx.fillText(Math.round(worldX).toString(), screenX + 2, 10);
|
||||||
|
} else {
|
||||||
|
xCtx.strokeStyle = '#666';
|
||||||
|
xCtx.moveTo(screenX, rulerSize - 10);
|
||||||
|
xCtx.lineTo(screenX, rulerSize);
|
||||||
|
xCtx.stroke();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const yCanvas = rulerYCanvas.value;
|
||||||
|
const yCtx = yCanvas.getContext('2d');
|
||||||
|
yCanvas.width = yCanvas.offsetWidth * window.devicePixelRatio;
|
||||||
|
yCanvas.height = yCanvas.offsetHeight * window.devicePixelRatio;
|
||||||
|
yCtx.scale(window.devicePixelRatio, window.devicePixelRatio);
|
||||||
|
yCtx.clearRect(0, 0, yCanvas.offsetWidth, yCanvas.offsetHeight);
|
||||||
|
|
||||||
|
yCtx.fillStyle = '#999';
|
||||||
|
yCtx.font = '10px sans-serif';
|
||||||
|
|
||||||
|
const canvasHeight = yCanvas.offsetHeight;
|
||||||
|
const startWorldY = Math.floor((-offsetY) / scale / step) * step;
|
||||||
|
const endWorldY = (-offsetY + canvasHeight) / scale;
|
||||||
|
|
||||||
|
for (let worldY = startWorldY; worldY < endWorldY; worldY += step) {
|
||||||
|
const screenY = worldY * scale + offsetY;
|
||||||
|
yCtx.beginPath();
|
||||||
|
if (Math.round(worldY) % bigStep === 0) {
|
||||||
|
yCtx.strokeStyle = '#fff';
|
||||||
|
yCtx.save();
|
||||||
|
yCtx.translate(rulerSize - 2, screenY + 5);
|
||||||
|
yCtx.rotate(-Math.PI / 2);
|
||||||
|
yCtx.fillStyle = '#ccc';
|
||||||
|
yCtx.fillText(Math.round(worldY).toString(), 0, 0);
|
||||||
|
yCtx.restore();
|
||||||
|
|
||||||
|
yCtx.moveTo(rulerSize - 20, screenY);
|
||||||
|
yCtx.lineTo(rulerSize, screenY);
|
||||||
|
yCtx.stroke();
|
||||||
|
} else {
|
||||||
|
yCtx.strokeStyle = '#666';
|
||||||
|
yCtx.moveTo(rulerSize - 10, screenY);
|
||||||
|
yCtx.lineTo(rulerSize, screenY);
|
||||||
|
yCtx.stroke();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const renderLoop = (time) => {
|
||||||
|
if (time - lastRenderTime >= FRAME_INTERVAL) {
|
||||||
|
drawRulers();
|
||||||
|
lastRenderTime = time;
|
||||||
|
}
|
||||||
|
animationFrameId = requestAnimationFrame(renderLoop);
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
animationFrameId = requestAnimationFrame(renderLoop);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.hw-flow-ruler-container {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hw-flow-ruler-x {
|
||||||
|
height: 30px;
|
||||||
|
background: #1F2122;
|
||||||
|
border-bottom: 1px solid #444;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hw-flow-ruler-y {
|
||||||
|
width: 30px;
|
||||||
|
background: #1F2122;
|
||||||
|
border-right: 1px solid #444;
|
||||||
|
height: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hw-flow-ruler-main-content {
|
||||||
|
display: flex;
|
||||||
|
height: calc(100% - 30px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.hw-flow-ruler-canvas {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,177 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<el-card class="moduleCard" shadow="never" :draggable="true"
|
||||||
|
@dragstart="onDragStart($event, 'line')" :style="{display:'inline-block',margin:'0 4px 4px 0'}"
|
||||||
|
:body-style="{padding:'4px 0'}">
|
||||||
|
<template #header>
|
||||||
|
<el-image style="width: 100%; height: 100%" :src="lineImg" fit="contain"/>
|
||||||
|
</template>
|
||||||
|
<div class="moduleText">折线</div>
|
||||||
|
</el-card>
|
||||||
|
<el-card class="moduleCard" shadow="never" :draggable="true"
|
||||||
|
@dragstart="onDragStart($event, 'multiLines')"
|
||||||
|
:style="{display:'inline-block',margin:'0 4px 4px 0'}"
|
||||||
|
:body-style="{padding:'4px 0'}">
|
||||||
|
<template #header>
|
||||||
|
<el-image style="width: 100%; height: 100%" :src="multiLinesImg" fit="contain"/>
|
||||||
|
</template>
|
||||||
|
<div class="moduleText">多折线</div>
|
||||||
|
</el-card>
|
||||||
|
<el-card class="moduleCard" shadow="never" :draggable="true"
|
||||||
|
@dragstart="onDragStart($event, 'curve')" :style="{display:'inline-block',margin:'0 4px 4px 0'}"
|
||||||
|
:body-style="{padding:'4px 0'}">
|
||||||
|
<template #header>
|
||||||
|
<el-image style="width: 100%; height: 100%" :src="curveImg" fit="contain"/>
|
||||||
|
</template>
|
||||||
|
<div class="moduleText">曲线</div>
|
||||||
|
</el-card>
|
||||||
|
<el-card class="moduleCard" shadow="never" :draggable="true"
|
||||||
|
@dragstart="onDragStart($event, 'multiCurves')"
|
||||||
|
:style="{display:'inline-block',margin:'0 4px 4px 0'}"
|
||||||
|
:body-style="{padding:'4px 0'}">
|
||||||
|
<template #header>
|
||||||
|
<el-image style="width: 100%; height: 100%" :src="multiCurvesImg" fit="contain"/>
|
||||||
|
</template>
|
||||||
|
<div class="moduleText">多曲线
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
<el-card class="moduleCard" shadow="never" :draggable="true"
|
||||||
|
@dragstart="onDragStart($event, 'lineBar')"
|
||||||
|
:style="{display:'inline-block',margin:'0 4px 4px 0'}"
|
||||||
|
:body-style="{padding:'4px 0'}">
|
||||||
|
<template #header>
|
||||||
|
<el-image style="width: 100%; height: 100%" :src="lineBarImg" fit="contain"/>
|
||||||
|
</template>
|
||||||
|
<div class="moduleText">双轴图
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
<el-card class="moduleCard" shadow="never" :draggable="true"
|
||||||
|
@dragstart="onDragStart($event, 'bar')" :style="{display:'inline-block',margin:'0 4px 4px 0'}"
|
||||||
|
:body-style="{padding:'4px 0'}">
|
||||||
|
<template #header>
|
||||||
|
<el-image style="width: 100%; height: 100%" :src="barImg" fit="contain"/>
|
||||||
|
</template>
|
||||||
|
<div class="moduleText">柱状图</div>
|
||||||
|
</el-card>
|
||||||
|
<el-card class="moduleCard" shadow="never" :draggable="true"
|
||||||
|
@dragstart="onDragStart($event, 'backgroundBar')"
|
||||||
|
:style="{display:'inline-block',margin:'0 4px 4px 0'}"
|
||||||
|
:body-style="{padding:'4px 0'}">
|
||||||
|
<template #header>
|
||||||
|
<el-image style="width: 100%; height: 100%" :src="backgroundBarImg" fit="contain"/>
|
||||||
|
</template>
|
||||||
|
<div class="moduleText">背景柱状图</div>
|
||||||
|
</el-card>
|
||||||
|
<el-card class="moduleCard" shadow="never" :draggable="true"
|
||||||
|
@dragstart="onDragStart($event, 'multiBars')"
|
||||||
|
:style="{display:'inline-block',margin:'0 4px 4px 0'}"
|
||||||
|
:body-style="{padding:'4px 0'}">
|
||||||
|
<template #header>
|
||||||
|
<el-image style="width: 100%; height: 100%" :src="multiBarsImg" fit="contain"/>
|
||||||
|
</template>
|
||||||
|
<div class="moduleText">多柱状图
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
<el-card class="moduleCard" shadow="never" :draggable="true"
|
||||||
|
@dragstart="onDragStart($event, 'pie')" :style="{display:'inline-block',margin:'0 4px 4px 0'}"
|
||||||
|
:body-style="{padding:'4px 0'}">
|
||||||
|
<template #header>
|
||||||
|
<el-image style="width: 100%; height: 100%" :src="pieImg" fit="contain"/>
|
||||||
|
</template>
|
||||||
|
<div class="moduleText">饼图</div>
|
||||||
|
</el-card>
|
||||||
|
<el-card class="moduleCard" shadow="never" :draggable="true"
|
||||||
|
@dragstart="onDragStart($event, 'annular')"
|
||||||
|
:style="{display:'inline-block',margin:'0 4px 4px 0'}"
|
||||||
|
:body-style="{padding:'4px 0'}">
|
||||||
|
<template #header>
|
||||||
|
<el-image style="width: 100%; height: 100%" :src="annularImg" fit="contain"/>
|
||||||
|
</template>
|
||||||
|
<div class="moduleText">中空饼图</div>
|
||||||
|
</el-card>
|
||||||
|
<el-card class="moduleCard" shadow="never" :draggable="true"
|
||||||
|
@dragstart="onDragStart($event, 'dashboard')"
|
||||||
|
:style="{display:'inline-block',margin:'0 4px 4px 0'}"
|
||||||
|
:body-style="{padding:'4px 0'}">
|
||||||
|
<template #header>
|
||||||
|
<el-image style="width: 100%; height: 100%" :src="dashboardImg" fit="contain"/>
|
||||||
|
</template>
|
||||||
|
<div class="moduleText">仪表盘</div>
|
||||||
|
</el-card>
|
||||||
|
<el-card class="moduleCard" shadow="never" :draggable="true"
|
||||||
|
@dragstart="onDragStart($event, 'radar')"
|
||||||
|
:style="{display:'inline-block',margin:'0 4px 4px 0'}"
|
||||||
|
:body-style="{padding:'4px 0'}">
|
||||||
|
<template #header>
|
||||||
|
<el-image style="width: 100%; height: 100%" :src="radarImg" fit="contain"/>
|
||||||
|
</template>
|
||||||
|
<div class="moduleText">雷达图</div>
|
||||||
|
</el-card>
|
||||||
|
<el-card class="moduleCard" shadow="never" :draggable="true"
|
||||||
|
@dragstart="onDragStart($event, 'nightingaleRoseDiagram')"
|
||||||
|
:style="{display:'inline-block',margin:'0 4px 4px 0'}"
|
||||||
|
:body-style="{padding:'4px 0'}">
|
||||||
|
<template #header>
|
||||||
|
<el-image style="width: 100%; height: 100%" :src="nightingaleRoseDiagramImg" fit="contain"/>
|
||||||
|
</template>
|
||||||
|
<div class="moduleText">南丁格尔玫瑰图</div>
|
||||||
|
</el-card>
|
||||||
|
<el-card class="moduleCard" shadow="never" :draggable="true"
|
||||||
|
@dragstart="onDragStart($event, 'carousel')"
|
||||||
|
:style="{display:'inline-block',margin:'0 4px 4px 0'}"
|
||||||
|
:body-style="{padding:'4px 0'}">
|
||||||
|
<template #header>
|
||||||
|
<el-image style="width: 100%; height: 100%" :src="carouselImg" fit="contain"/>
|
||||||
|
</template>
|
||||||
|
<div class="moduleText">轮播图</div>
|
||||||
|
</el-card>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup>
|
||||||
|
import backgroundBarImg from '../../../assets/images/boardNodes/backgroundBarImg.png';
|
||||||
|
import pieImg from '../../../assets/images/boardNodes/pieImg.png';
|
||||||
|
import multiCurvesImg from '../../../assets/images/boardNodes/multiCurvesImg.png';
|
||||||
|
import lineBarImg from '../../../assets/images/boardNodes/lineBarImg.png';
|
||||||
|
import multiLinesImg from '../../../assets/images/boardNodes/multiLinesImg.png';
|
||||||
|
import multiBarsImg from '../../../assets/images/boardNodes/multiBarsImg.png';
|
||||||
|
import annularImg from '../../../assets/images/boardNodes/annularImg.png';
|
||||||
|
import radarImg from '../../../assets/images/boardNodes/radarImg.png';
|
||||||
|
import carouselImg from '../../../assets/images/boardNodes/carouselImg.png';
|
||||||
|
import nightingaleRoseDiagramImg from '../../../assets/images/boardNodes/nightingaleRoseDiagramImg.png';
|
||||||
|
import curveImg from '../../../assets/images/boardNodes/curveImg.png';
|
||||||
|
import dashboardImg from '../../../assets/images/boardNodes/dashboardImg.png';
|
||||||
|
import lineImg from '../../../assets/images/boardNodes/lineImg.png';
|
||||||
|
import barImg from '../../../assets/images/boardNodes/barImg.png';
|
||||||
|
|
||||||
|
defineProps({
|
||||||
|
onDragStart: Function
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
<style scoped lang="less">
|
||||||
|
.moduleCard {
|
||||||
|
width: 100px;
|
||||||
|
vertical-align: top;
|
||||||
|
|
||||||
|
:deep(.el-card__body) {
|
||||||
|
height: 40px;
|
||||||
|
padding: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-card__header) {
|
||||||
|
padding: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.moduleText {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 12px;
|
||||||
|
-webkit-line-clamp: 2;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,73 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<el-card class="moduleCard" shadow="never" :draggable="true"
|
||||||
|
@dragstart="onDragStart($event, 'map')" :style="{display:'inline-block',margin:'0 4px 4px 0'}"
|
||||||
|
:body-style="{padding:'4px 0'}">
|
||||||
|
<template #header>
|
||||||
|
<div style="width: 100%;height: 100px;text-align: center">
|
||||||
|
|
||||||
|
<el-image style="width:80px;height: 80px;margin-top: 10px;" :src="mapImg" fit="contain"/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<div class="moduleText">映射</div>
|
||||||
|
</el-card>
|
||||||
|
<el-card class="moduleCard" shadow="never" :draggable="true"
|
||||||
|
@dragstart="onDragStart($event, 'staticData')"
|
||||||
|
:style="{display:'inline-block',margin:'0 4px 4px 0'}"
|
||||||
|
:body-style="{padding:'4px 0'}">
|
||||||
|
<template #header>
|
||||||
|
<el-image style="width: 100%; height: 100%" :src="customizationRequestImg" fit="contain"/>
|
||||||
|
</template>
|
||||||
|
<div class="moduleText">静态数据</div>
|
||||||
|
</el-card>
|
||||||
|
<template v-for="i in customData">
|
||||||
|
<el-card class="moduleCard" shadow="never" :draggable="true"
|
||||||
|
@dragstart="onDragStart($event, 'customData',i)"
|
||||||
|
:style="{display:'inline-block',margin:'0 4px 4px 0'}"
|
||||||
|
:body-style="{padding:'4px 0'}">
|
||||||
|
<template #header>
|
||||||
|
<el-image style="width: 100%; height: 100%" :src="network" fit="contain"/>
|
||||||
|
</template>
|
||||||
|
<div class="moduleText">{{ i.name }}</div>
|
||||||
|
</el-card>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup>
|
||||||
|
import customizationRequestImg from '@/assets/images/customData/customizationRequestImg.png';
|
||||||
|
import mapImg from '@/assets/images/customData/mapImg.png';
|
||||||
|
import network from '@/assets/images/customData/network.png';
|
||||||
|
|
||||||
|
defineProps({
|
||||||
|
onDragStart: Function
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
<style lang="less" scoped>
|
||||||
|
|
||||||
|
.moduleCard {
|
||||||
|
width: 100px;
|
||||||
|
vertical-align: top;
|
||||||
|
|
||||||
|
:deep(.el-card__body) {
|
||||||
|
height: 40px;
|
||||||
|
padding: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-card__header) {
|
||||||
|
padding: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.moduleText {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 12px;
|
||||||
|
-webkit-line-clamp: 2;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,213 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<el-card class="moduleCard" shadow="never" :draggable="true"
|
||||||
|
@dragstart="onDragStart($event, 'text')" :style="{display:'inline-block',margin:'0 4px 4px 0'}"
|
||||||
|
:body-style="{padding:'4px 0'}">
|
||||||
|
<template #header>
|
||||||
|
<div style="width: 100%;height: 100%;text-align: center">
|
||||||
|
|
||||||
|
<el-image style="width:50px;height: 50px;text-align: center" :src="textImg" fit="contain"/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<div class="moduleText">文字</div>
|
||||||
|
</el-card>
|
||||||
|
<el-card class="moduleCard" shadow="never" :draggable="true"
|
||||||
|
@dragstart="onDragStart($event, 'buttonNode')"
|
||||||
|
:style="{display:'inline-block',margin:'0 4px 4px 0'}"
|
||||||
|
:body-style="{padding:'4px 0'}">
|
||||||
|
<template #header>
|
||||||
|
<div style="width: 100%;height: 100%;text-align: center">
|
||||||
|
|
||||||
|
<el-image style="width:50px;height: 50px;text-align: center" :src="inputNodeImg" fit="contain"/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<div class="moduleText">按钮</div>
|
||||||
|
</el-card>
|
||||||
|
<el-card class="moduleCard" shadow="never" :draggable="true"
|
||||||
|
@dragstart="onDragStart($event, 'inputNode')"
|
||||||
|
:style="{display:'inline-block',margin:'0 4px 4px 0'}"
|
||||||
|
:body-style="{padding:'4px 0'}">
|
||||||
|
<template #header>
|
||||||
|
<div style="width: 100%;height: 100%;text-align: center">
|
||||||
|
|
||||||
|
<el-image style="width:50px;height: 50px;text-align: center" :src="inputNodeImg2" fit="contain"/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<div class="moduleText">输入框</div>
|
||||||
|
</el-card>
|
||||||
|
<el-card class="moduleCard" shadow="never" :draggable="true"
|
||||||
|
@dragstart="onDragStart($event, 'selectNode')"
|
||||||
|
:style="{display:'inline-block',margin:'0 4px 4px 0'}"
|
||||||
|
:body-style="{padding:'4px 0'}">
|
||||||
|
<template #header>
|
||||||
|
<div style="width: 100%;height: 100%;text-align: center">
|
||||||
|
|
||||||
|
<el-image style="width:50px;height: 50px;text-align: center" :src="inputNodeImg3" fit="contain"/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<div class="moduleText">选择框</div>
|
||||||
|
</el-card>
|
||||||
|
<el-card class="moduleCard" shadow="never" :draggable="true"
|
||||||
|
@dragstart="onDragStart($event, 'time')" :style="{display:'inline-block',margin:'0 4px 4px 0'}"
|
||||||
|
:body-style="{padding:'4px 0'}">
|
||||||
|
<template #header>
|
||||||
|
<div style="width: 100%;height: 100%;text-align: center">
|
||||||
|
|
||||||
|
<el-image style="width:50px;height: 50px;text-align: center" :src="timeImg" fit="contain"/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<div class="moduleText">时间</div>
|
||||||
|
</el-card>
|
||||||
|
<el-card class="moduleCard" shadow="never" :draggable="true"
|
||||||
|
@dragstart="onDragStart($event, 'img')" :style="{display:'inline-block',margin:'0 4px 4px 0'}"
|
||||||
|
:body-style="{padding:'4px 0'}">
|
||||||
|
<template #header>
|
||||||
|
<div style="width: 100%;height: 100%;text-align: center">
|
||||||
|
|
||||||
|
<el-image style="width:50px;height: 50px;text-align: center" :src="imgImg" fit="contain"/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<div class="moduleText">图片</div>
|
||||||
|
</el-card>
|
||||||
|
<el-card class="moduleCard" shadow="never" :draggable="true"
|
||||||
|
@dragstart="onDragStart($event, 'icon')" :style="{display:'inline-block',margin:'0 4px 4px 0'}"
|
||||||
|
:body-style="{padding:'4px 0'}">
|
||||||
|
<template #header>
|
||||||
|
<div style="width: 100%;height: 100%;text-align: center">
|
||||||
|
|
||||||
|
<el-image style="width:50px;height: 50px;text-align: center" :src="iconImg" fit="contain"/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<div class="moduleText">图标</div>
|
||||||
|
</el-card>
|
||||||
|
<el-card class="moduleCard" shadow="never" :draggable="true"
|
||||||
|
@dragstart="onDragStart($event, 'video')" :style="{display:'inline-block',margin:'0 4px 4px 0'}"
|
||||||
|
:body-style="{padding:'4px 0'}">
|
||||||
|
<template #header>
|
||||||
|
<div style="width: 100%;height: 100%;text-align: center">
|
||||||
|
|
||||||
|
<el-image style="width:50px;height: 50px;text-align: center" :src="videoImg" fit="contain"/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<div class="moduleText">视频</div>
|
||||||
|
</el-card>
|
||||||
|
<el-card class="moduleCard" shadow="never" :draggable="true"
|
||||||
|
@dragstart="onDragStart($event, 'timeline')" :style="{display:'inline-block',margin:'0 4px 4px 0'}"
|
||||||
|
:body-style="{padding:'4px 0'}">
|
||||||
|
<template #header>
|
||||||
|
<div style="width: 100%;height: 100%;text-align: center">
|
||||||
|
|
||||||
|
<el-image style="width:50px;height: 50px;text-align: center" :src="timelineImg" fit="contain"/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<div class="moduleText">时间线</div>
|
||||||
|
</el-card>
|
||||||
|
<el-card class="moduleCard" shadow="never" :draggable="true"
|
||||||
|
@dragstart="onDragStart($event, 'digitalFlop')"
|
||||||
|
:style="{display:'inline-block',margin:'0 4px 4px 0'}"
|
||||||
|
:body-style="{padding:'4px 0'}">
|
||||||
|
<template #header>
|
||||||
|
<div style="width: 100%;height: 100%;text-align: center">
|
||||||
|
|
||||||
|
<el-image style="width:50px;height: 50px;text-align: center" :src="digitalFlopImg" fit="contain"/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<div class="moduleText">数字翻牌器</div>
|
||||||
|
</el-card>
|
||||||
|
<el-card class="moduleCard" shadow="never" :draggable="true"
|
||||||
|
@dragstart="onDragStart($event, 'table')"
|
||||||
|
:style="{display:'inline-block',margin:'0 4px 4px 0'}"
|
||||||
|
:body-style="{padding:'4px 0'}">
|
||||||
|
<template #header>
|
||||||
|
<div style="width: 100%;height: 100%;text-align: center">
|
||||||
|
<el-image style="width:50px;height: 50px;text-align: center" :src="scrollTableImg" fit="contain"/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<div class="moduleText">普通表格</div>
|
||||||
|
</el-card>
|
||||||
|
<el-card class="moduleCard" shadow="never" :draggable="true"
|
||||||
|
@dragstart="onDragStart($event, 'scrollTable')"
|
||||||
|
:style="{display:'inline-block',margin:'0 4px 4px 0'}"
|
||||||
|
:body-style="{padding:'4px 0'}">
|
||||||
|
<template #header>
|
||||||
|
<div style="width: 100%;height: 100%;text-align: center">
|
||||||
|
<el-image style="width:50px;height: 50px;text-align: center" :src="scrollTableImg2" fit="contain"/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<div class="moduleText">滚动表格</div>
|
||||||
|
</el-card>
|
||||||
|
<el-card class="moduleCard" shadow="never" :draggable="true"
|
||||||
|
@dragstart="onDragStart($event, 'background')"
|
||||||
|
:style="{display:'inline-block',margin:'0 4px 4px 0'}"
|
||||||
|
:body-style="{padding:'4px 0'}">
|
||||||
|
<template #header>
|
||||||
|
<div style="width: 100%;height: 100%;text-align: center">
|
||||||
|
|
||||||
|
<el-image style="width:50px;height: 50px;text-align: center" :src="backgroundImg" fit="contain"/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<div class="moduleText">背景</div>
|
||||||
|
</el-card>
|
||||||
|
<el-card class="moduleCard" shadow="never" :draggable="true"
|
||||||
|
@dragstart="onDragStart($event, 'pagination')"
|
||||||
|
:style="{display:'inline-block',margin:'0 4px 4px 0'}"
|
||||||
|
:body-style="{padding:'4px 0'}">
|
||||||
|
<template #header>
|
||||||
|
<div style="width: 100%;height: 100%;text-align: center">
|
||||||
|
|
||||||
|
<el-image style="width:50px;height: 50px;text-align: center" :src="backgroundImg" fit="contain"/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<div class="moduleText">分页</div>
|
||||||
|
</el-card>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup>
|
||||||
|
import backgroundImg from '@/assets/images/formNodes/backgroundImg.png';
|
||||||
|
import digitalFlopImg from '@/assets/images/formNodes/digitalFlopImg.png';
|
||||||
|
import iconImg from '@/assets/images/formNodes/iconImg.png';
|
||||||
|
import imgImg from '@/assets/images/formNodes/imgImg.png';
|
||||||
|
import inputNodeImg from '@/assets/images/formNodes/inputNodeImg.png';
|
||||||
|
import inputNodeImg2 from '@/assets/images/formNodes/inputNodeImg2.png';
|
||||||
|
import inputNodeImg3 from '@/assets/images/formNodes/inputNodeImg3.png';
|
||||||
|
import scrollTableImg from '@/assets/images/formNodes/scrollTableImg.png';
|
||||||
|
import scrollTableImg2 from '@/assets/images/formNodes/scrollTableImg2.png';
|
||||||
|
import textImg from '@/assets/images/formNodes/textImg.png';
|
||||||
|
import timeImg from '@/assets/images/formNodes/timeImg.png';
|
||||||
|
import timelineImg from '@/assets/images/formNodes/timelineImg.png';
|
||||||
|
import videoImg from '@/assets/images/formNodes/videoImg.png';
|
||||||
|
|
||||||
|
|
||||||
|
defineProps({
|
||||||
|
onDragStart: Function
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
<style lang="less" scoped>
|
||||||
|
|
||||||
|
.moduleCard {
|
||||||
|
width: 100px;
|
||||||
|
vertical-align: top;
|
||||||
|
|
||||||
|
:deep(.el-card__body) {
|
||||||
|
height: 40px;
|
||||||
|
padding: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-card__header) {
|
||||||
|
padding: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.moduleText {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 12px;
|
||||||
|
-webkit-line-clamp: 2;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,68 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<el-card class="moduleCard" shadow="never" :draggable="true"
|
||||||
|
@dragstart="onDragStart($event, 'menu')" :style="{display:'inline-block',margin:'0 4px 4px 0'}"
|
||||||
|
:body-style="{padding:'4px 0'}">
|
||||||
|
<template #header>
|
||||||
|
<div style="width: 100%;height: 50px;line-height:50px;text-align: center">
|
||||||
|
<el-icon>
|
||||||
|
<component :is="icons.Menu"/>
|
||||||
|
</el-icon>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<div class="moduleText">菜单</div>
|
||||||
|
</el-card>
|
||||||
|
<el-card class="moduleCard" shadow="never" :draggable="true"
|
||||||
|
@dragstart="onDragStart($event, 'tree')" :style="{display:'inline-block',margin:'0 4px 4px 0'}"
|
||||||
|
:body-style="{padding:'4px 0'}">
|
||||||
|
<template #header>
|
||||||
|
<div style="width: 100%;height: 50px;display: flex; justify-content: center; align-items: center;">
|
||||||
|
<svg t="1768964556223" viewBox="0 0 1024 1024" version="1.1"
|
||||||
|
xmlns="http://www.w3.org/2000/svg" p-id="4878" width="30" height="30">
|
||||||
|
<path
|
||||||
|
d="M554.666667 682.666667h85.333333v128h-213.333333v-128h85.333333v-128H256v128h85.333333v128H128v-128h85.333333v-170.666667h298.666667V384h-85.333333V256h213.333333v128h-85.333333v128h298.666666v170.666667h85.333334v128h-213.333334v-128h85.333334v-128h-256v128z m42.666666-384h-128v42.666666h128V298.666667zM298.666667 725.333333H170.666667v42.666667h128v-42.666667z m597.333333 0h-128v42.666667h128v-42.666667z m-298.666667 0h-128v42.666667h128v-42.666667z"
|
||||||
|
fill="#444444" p-id="4879"></path>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<div class="moduleText">树状图</div>
|
||||||
|
</el-card>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup>
|
||||||
|
|
||||||
|
defineProps({
|
||||||
|
icons: Object,
|
||||||
|
onDragStart: Function
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
<style lang="less" scoped>
|
||||||
|
|
||||||
|
|
||||||
|
.moduleCard {
|
||||||
|
width: 100px;
|
||||||
|
vertical-align: top;
|
||||||
|
|
||||||
|
:deep(.el-card__body) {
|
||||||
|
height: 40px;
|
||||||
|
padding: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-card__header) {
|
||||||
|
padding: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.moduleText {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 12px;
|
||||||
|
-webkit-line-clamp: 2;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
import VisualEditor from './components/external/VisualEditor.vue'
|
||||||
|
|
||||||
|
export { VisualEditor }
|
||||||
|
|
||||||
|
export default {
|
||||||
|
install(app) {
|
||||||
|
app.component('VisualEditor', VisualEditor)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,515 @@
|
|||||||
|
import {useVueFlow} from '@vue-flow/core';
|
||||||
|
import {ref,} from 'vue';
|
||||||
|
import {v4 as uuidv4} from 'uuid';
|
||||||
|
|
||||||
|
|
||||||
|
const getId = (type) => {
|
||||||
|
return `${type}_${uuidv4().replaceAll('-', '_')}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
const optionList = (e) => {
|
||||||
|
const normalOption = {
|
||||||
|
title: '', boundaryGap: true,
|
||||||
|
}
|
||||||
|
const chartOption = {
|
||||||
|
gridTop: 30,
|
||||||
|
gridLeft: 5,
|
||||||
|
gridBottom: 10,
|
||||||
|
gridRight: 10,
|
||||||
|
xName: '',
|
||||||
|
xNameLocation: 'end',
|
||||||
|
xAxisLineShow: true,
|
||||||
|
xAxisLineColor: '#DCE2E8',
|
||||||
|
xAxisTickShow: true,
|
||||||
|
xAxisTickInside: false,
|
||||||
|
xAxisTickColor: '#DCE2E8',
|
||||||
|
xAxisLabelShow: true,
|
||||||
|
xAxisLabelInterval: true,
|
||||||
|
xAxisLabelInside: false,
|
||||||
|
xAxisLabelRotate: 0,
|
||||||
|
xAxisLabelFormatter: '',
|
||||||
|
xAxisLabelColor: '#fff',
|
||||||
|
xAxisLabelFontSize: 12,
|
||||||
|
xAxisLabelMargin: 3,
|
||||||
|
xAxisSplitLineShow: false,
|
||||||
|
xAxisSplitLineColor: '#DCE2E8',
|
||||||
|
xAxisSplitLineType: 'solid',
|
||||||
|
yName: '',
|
||||||
|
yNames: [],
|
||||||
|
yNameLocation: 'end',
|
||||||
|
yAxisLineShow: true,
|
||||||
|
yAxisLineColor: '#DCE2E8',
|
||||||
|
yAxisTickShow: true,
|
||||||
|
yAxisTickInside: false,
|
||||||
|
yAxisTickColor: '#DCE2E8',
|
||||||
|
yAxisLabelShow: true,
|
||||||
|
yAxisLabelInterval: true,
|
||||||
|
yAxisLabelInside: false,
|
||||||
|
yAxisLabelRotate: 0,
|
||||||
|
yAxisLabelFormatter: '',
|
||||||
|
yAxisLabelColor: '#fff',
|
||||||
|
yAxisLabelFontSize: 12,
|
||||||
|
yAxisLabelMargin: 3,
|
||||||
|
yAxisSplitLineShow: false,
|
||||||
|
yAxisSplitLineColor: '#DCE2E8',
|
||||||
|
yAxisSplitLineType: 'solid',
|
||||||
|
lineSymbolShow: false,
|
||||||
|
lineSymbolSize: 5,
|
||||||
|
lineSymbolType: 'circle',
|
||||||
|
seriesColor: '#9E87FF',
|
||||||
|
tooltip: true,
|
||||||
|
legend: true,
|
||||||
|
}
|
||||||
|
const options = {
|
||||||
|
...normalOption, ...chartOption,
|
||||||
|
}
|
||||||
|
return e.map(v => {
|
||||||
|
return {[v]: options[v]};
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const getOption = (e) => {
|
||||||
|
let res = {}
|
||||||
|
if (e === 'line' || e === 'multiLines') {
|
||||||
|
return optionList(['title', 'boundaryGap', 'gridTop', 'gridLeft', 'gridBottom', 'gridRight', 'xName', 'xNameLocation', 'xAxisLineShow', 'xAxisLineColor', 'xAxisTickShow', 'xAxisTickInside', 'xAxisTickColor', 'xAxisLabelShow', 'xAxisLabelInterval', 'xAxisLabelInside', 'xAxisLabelRotate', 'xAxisLabelFormatter', 'xAxisLabelColor', 'xAxisLabelFontSize', 'xAxisLabelMargin', 'xAxisSplitLineShow', 'xAxisSplitLineColor', 'xAxisSplitLineType', 'yName', 'yNames', 'yNameLocation', 'yAxisLineShow', 'yAxisLineColor', 'yAxisTickShow', 'yAxisTickInside', 'yAxisTickColor', 'yAxisLabelShow', 'yAxisLabelInterval', 'yAxisLabelInside', 'yAxisLabelRotate', 'yAxisLabelFormatter', 'yAxisLabelColor', 'yAxisLabelFontSize', 'yAxisLabelMargin', 'yAxisSplitLineShow', 'yAxisSplitLineColor', 'yAxisSplitLineType', 'lineSymbolShow', 'lineSymbolSize', 'lineSymbolType', 'seriesColor', 'tooltip', 'legend'])
|
||||||
|
} else if (e === 'bar' || e === 'multiBars') {
|
||||||
|
return {
|
||||||
|
title: '',
|
||||||
|
yNames: [],
|
||||||
|
gridTop: 30,
|
||||||
|
gridLeft: 5,
|
||||||
|
gridBottom: 10,
|
||||||
|
gridRight: 10,
|
||||||
|
xName: '',
|
||||||
|
xNameLocation: 'end',
|
||||||
|
xAxisLineShow: true,
|
||||||
|
xAxisLineColor: '#DCE2E8',
|
||||||
|
xAxisTickShow: true,
|
||||||
|
xAxisTickInside: false,
|
||||||
|
xAxisTickColor: '#DCE2E8',
|
||||||
|
xAxisLabelShow: true,
|
||||||
|
xAxisLabelInterval: true,
|
||||||
|
xAxisLabelInside: false,
|
||||||
|
xAxisLabelRotate: 0,
|
||||||
|
xAxisLabelFormatter: '',
|
||||||
|
xAxisLabelColor: '#fff',
|
||||||
|
xAxisLabelFontSize: 12,
|
||||||
|
xAxisLabelMargin: 3,
|
||||||
|
xAxisSplitLineShow: false,
|
||||||
|
xAxisSplitLineColor: '#DCE2E8',
|
||||||
|
xAxisSplitLineType: 'solid',
|
||||||
|
yName: '',
|
||||||
|
yNameLocation: 'end',
|
||||||
|
yAxisLineShow: true,
|
||||||
|
yAxisLineColor: '#DCE2E8',
|
||||||
|
yAxisTickShow: true,
|
||||||
|
yAxisTickInside: false,
|
||||||
|
yAxisTickColor: '#DCE2E8',
|
||||||
|
yAxisLabelShow: true,
|
||||||
|
yAxisLabelInterval: true,
|
||||||
|
yAxisLabelInside: false,
|
||||||
|
yAxisLabelRotate: 0,
|
||||||
|
yAxisLabelFormatter: '',
|
||||||
|
yAxisLabelColor: '#fff',
|
||||||
|
yAxisLabelFontSize: 12,
|
||||||
|
yAxisLabelMargin: 3,
|
||||||
|
yAxisSplitLineShow: false,
|
||||||
|
yAxisSplitLineColor: '#DCE2E8',
|
||||||
|
yAxisSplitLineType: 'solid',
|
||||||
|
seriesColor: '#9E87FF',
|
||||||
|
tooltip: true,
|
||||||
|
legend: true,
|
||||||
|
isHorizontal: false,
|
||||||
|
};
|
||||||
|
} else if (e === 'backgroundBar') {
|
||||||
|
return {
|
||||||
|
title: '',
|
||||||
|
yNames: [],
|
||||||
|
gridTop: 30,
|
||||||
|
gridLeft: 5,
|
||||||
|
gridBottom: 10,
|
||||||
|
gridRight: 10,
|
||||||
|
xName: '',
|
||||||
|
xNameLocation: 'end',
|
||||||
|
xAxisLineShow: true,
|
||||||
|
xAxisLineColor: '#DCE2E8',
|
||||||
|
xAxisTickShow: true,
|
||||||
|
xAxisTickInside: false,
|
||||||
|
xAxisTickColor: '#DCE2E8',
|
||||||
|
xAxisLabelShow: true,
|
||||||
|
xAxisLabelInterval: true,
|
||||||
|
xAxisLabelInside: false,
|
||||||
|
xAxisLabelRotate: 0,
|
||||||
|
xAxisLabelFormatter: '',
|
||||||
|
xAxisLabelColor: '#fff',
|
||||||
|
xAxisLabelFontSize: 12,
|
||||||
|
xAxisLabelMargin: 3,
|
||||||
|
xAxisSplitLineShow: false,
|
||||||
|
xAxisSplitLineColor: '#DCE2E8',
|
||||||
|
xAxisSplitLineType: 'solid',
|
||||||
|
yName: '',
|
||||||
|
yNameLocation: 'end',
|
||||||
|
yAxisLineShow: true,
|
||||||
|
yAxisLineColor: '#DCE2E8',
|
||||||
|
yAxisTickShow: true,
|
||||||
|
yAxisTickInside: false,
|
||||||
|
yAxisTickColor: '#DCE2E8',
|
||||||
|
yAxisLabelShow: true,
|
||||||
|
yAxisLabelInterval: true,
|
||||||
|
yAxisLabelInside: false,
|
||||||
|
yAxisLabelRotate: 0,
|
||||||
|
yAxisLabelFormatter: '',
|
||||||
|
yAxisLabelColor: '#fff',
|
||||||
|
yAxisLabelFontSize: 12,
|
||||||
|
yAxisLabelMargin: 3,
|
||||||
|
yAxisSplitLineShow: false,
|
||||||
|
yAxisSplitLineColor: '#DCE2E8',
|
||||||
|
yAxisSplitLineType: 'solid',
|
||||||
|
tooltip: true,
|
||||||
|
legend: true,
|
||||||
|
seriesColor: '#9E87FF',
|
||||||
|
backgroundColor: 'rgba(180, 180, 180, 0.2)',
|
||||||
|
isHorizontal: false,
|
||||||
|
};
|
||||||
|
} else if (e === 'curve' || e === 'multiCurves') {
|
||||||
|
return {
|
||||||
|
title: '',
|
||||||
|
yNames: [],
|
||||||
|
gridTop: 30,
|
||||||
|
gridLeft: 5,
|
||||||
|
gridBottom: 10,
|
||||||
|
gridRight: 10,
|
||||||
|
boundaryGap: true,
|
||||||
|
xName: '',
|
||||||
|
xNameLocation: 'end',
|
||||||
|
xAxisLineShow: true,
|
||||||
|
xAxisLineColor: '#DCE2E8',
|
||||||
|
xAxisTickShow: true,
|
||||||
|
xAxisTickInside: false,
|
||||||
|
xAxisTickColor: '#DCE2E8',
|
||||||
|
xAxisLabelShow: true,
|
||||||
|
xAxisLabelInterval: true,
|
||||||
|
xAxisLabelInside: false,
|
||||||
|
xAxisLabelRotate: 0,
|
||||||
|
xAxisLabelFormatter: '',
|
||||||
|
xAxisLabelColor: '#fff',
|
||||||
|
xAxisLabelFontSize: 12,
|
||||||
|
xAxisLabelMargin: 3,
|
||||||
|
xAxisSplitLineShow: false,
|
||||||
|
xAxisSplitLineColor: '#DCE2E8',
|
||||||
|
xAxisSplitLineType: 'solid',
|
||||||
|
yName: '',
|
||||||
|
yNameLocation: 'end',
|
||||||
|
yAxisLineShow: true,
|
||||||
|
yAxisLineColor: '#DCE2E8',
|
||||||
|
yAxisTickShow: true,
|
||||||
|
yAxisTickInside: false,
|
||||||
|
yAxisTickColor: '#DCE2E8',
|
||||||
|
yAxisLabelShow: true,
|
||||||
|
yAxisLabelInterval: true,
|
||||||
|
yAxisLabelInside: false,
|
||||||
|
yAxisLabelRotate: 0,
|
||||||
|
yAxisLabelFormatter: '',
|
||||||
|
yAxisLabelColor: '#fff',
|
||||||
|
yAxisLabelFontSize: 12,
|
||||||
|
yAxisLabelMargin: 3,
|
||||||
|
yAxisSplitLineShow: false,
|
||||||
|
yAxisSplitLineColor: '#DCE2E8',
|
||||||
|
yAxisSplitLineType: 'solid',
|
||||||
|
lineSymbolShow: false,
|
||||||
|
lineSymbolSize: 5,
|
||||||
|
lineSymbolType: 'circle',
|
||||||
|
seriesColor: '#9E87FF',
|
||||||
|
tooltip: true,
|
||||||
|
legend: true
|
||||||
|
};
|
||||||
|
} else if (e === 'lineBar') {
|
||||||
|
return {
|
||||||
|
title: '',
|
||||||
|
yNames: [],
|
||||||
|
gridTop: 30,
|
||||||
|
gridLeft: 5,
|
||||||
|
gridBottom: 10,
|
||||||
|
gridRight: 10,
|
||||||
|
xName: '',
|
||||||
|
xNameLocation: 'end',
|
||||||
|
xAxisLineShow: true,
|
||||||
|
xAxisLineColor: '#DCE2E8',
|
||||||
|
xAxisTickShow: true,
|
||||||
|
xAxisTickInside: false,
|
||||||
|
xAxisTickColor: '#DCE2E8',
|
||||||
|
xAxisLabelShow: true,
|
||||||
|
xAxisLabelInterval: true,
|
||||||
|
xAxisLabelInside: false,
|
||||||
|
xAxisLabelRotate: 0,
|
||||||
|
xAxisLabelFormatter: '',
|
||||||
|
xAxisLabelColor: '#fff',
|
||||||
|
xAxisLabelFontSize: 12,
|
||||||
|
xAxisLabelMargin: 3,
|
||||||
|
xAxisSplitLineShow: false,
|
||||||
|
xAxisSplitLineColor: '#DCE2E8',
|
||||||
|
xAxisSplitLineType: 'solid',
|
||||||
|
yName: '',
|
||||||
|
yNameLocation: 'end',
|
||||||
|
yAxisLineShow: true,
|
||||||
|
yAxisLineColor: '#DCE2E8',
|
||||||
|
yAxisTickShow: true,
|
||||||
|
yAxisTickInside: false,
|
||||||
|
yAxisTickColor: '#DCE2E8',
|
||||||
|
yAxisLabelShow: true,
|
||||||
|
yAxisLabelInterval: true,
|
||||||
|
yAxisLabelInside: false,
|
||||||
|
yAxisLabelRotate: 0,
|
||||||
|
yAxisLabelFormatter: '',
|
||||||
|
yAxisLabelColor: '#fff',
|
||||||
|
yAxisLabelFontSize: 12,
|
||||||
|
yAxisLabelMargin: 3,
|
||||||
|
yAxisSplitLineShow: false,
|
||||||
|
yAxisSplitLineColor: '#DCE2E8',
|
||||||
|
yAxisSplitLineType: 'solid',
|
||||||
|
lineSymbolShow: false,
|
||||||
|
lineSymbolSize: 5,
|
||||||
|
lineSymbolType: 'circle',
|
||||||
|
tooltip: true,
|
||||||
|
legend: true,
|
||||||
|
seriesColor: '#9E87FF'
|
||||||
|
};
|
||||||
|
} else if (e === 'radar') {
|
||||||
|
return {
|
||||||
|
title: '',
|
||||||
|
seriesColor: '#9E87FF',
|
||||||
|
yNames: [],
|
||||||
|
tooltip: true,
|
||||||
|
legend: true,
|
||||||
|
radarCenter: [30, 50],
|
||||||
|
radarRadius: 40,
|
||||||
|
radarShape: 'polygon',
|
||||||
|
radarSplitNumber: 5,
|
||||||
|
splitLineColor: '#9E87FF'
|
||||||
|
};
|
||||||
|
} else if (e === 'pie' || e === 'nightingaleRoseDiagram') {
|
||||||
|
return {
|
||||||
|
title: '',
|
||||||
|
yNames: [],
|
||||||
|
tooltip: true,
|
||||||
|
legend: true,
|
||||||
|
label: true,
|
||||||
|
pieCenter: 50,
|
||||||
|
pieLabelFormatter: '',
|
||||||
|
legendColor: '#fff'
|
||||||
|
};
|
||||||
|
} else if (e === 'annular') {
|
||||||
|
return {
|
||||||
|
title: '',
|
||||||
|
yNames: [],
|
||||||
|
tooltip: true,
|
||||||
|
legend: true,
|
||||||
|
label: true,
|
||||||
|
pieCenter: 50,
|
||||||
|
pieRadius: [30, 70],
|
||||||
|
colorList: ['#D6F4FF', '#D6F4FF', '#D6F4FF', '#D6F4FF'],
|
||||||
|
};
|
||||||
|
} else if (e === 'dashboard') {
|
||||||
|
return {title: '', yNames: [], tooltip: true, legend: true, label: true};
|
||||||
|
} else if (e === 'customBoard') {
|
||||||
|
return {title: '', yNames: []};
|
||||||
|
} else if (e === 'data') {
|
||||||
|
return {timeout: 5};
|
||||||
|
} else if (e === 'staticData') {
|
||||||
|
return {defaultInputArea: '', field: 'input', defaultDataType: ''};
|
||||||
|
} else if (e === 'customData') {
|
||||||
|
return {timeout: 5};
|
||||||
|
} else if (e === 'map') {
|
||||||
|
return {dataMap: []};
|
||||||
|
} else if (e === 'inputNode') {
|
||||||
|
return {field: 'input', defaultInput: ''};
|
||||||
|
} else if (e === 'buttonNode') {
|
||||||
|
return {backgroundColor: '#409EFF', color: '#fff', text: '按钮', sendType: ['ok']};
|
||||||
|
} else if (e === 'selectNode') {
|
||||||
|
return {field: 'select', defaultInput: '', labelField: 'label', valueField: 'value'};
|
||||||
|
} else if (e === 'time') {
|
||||||
|
return {startTimeId: 'startTime', endTimeId: 'endTime', defaultTime: [], format: ''};
|
||||||
|
} else if (e === 'text') {
|
||||||
|
return {text: '文字', align: '', color: '#fff', whiteSpace: 'nowrap'};
|
||||||
|
} else if (e === 'img') {
|
||||||
|
return {imgSrc: ''};
|
||||||
|
} else if (e === 'icon') {
|
||||||
|
return {icon: 'Tools', iconSrc: ''};
|
||||||
|
} else if (e === 'video') {
|
||||||
|
return {videoSrc: ''};
|
||||||
|
} else if (e === 'timeline') {
|
||||||
|
return {
|
||||||
|
color: '#fff', timestampColor: '#fff', field: 'content', timestampField: 'timestamp', isTimestamp: true
|
||||||
|
};
|
||||||
|
} else if (e === 'scrollTable' || e === 'table') {
|
||||||
|
return {
|
||||||
|
tableOptions: [],
|
||||||
|
tableCellOptions: [],
|
||||||
|
tableClassOption: {},
|
||||||
|
isThShow: true,
|
||||||
|
thHeight: '32px',
|
||||||
|
tdHeight: '28px',
|
||||||
|
thColor: '#D6F4FF',
|
||||||
|
tdColor: ['#D6F4FF', '#D6F4FF', '#D6F4FF', '#D6F4FF'],
|
||||||
|
thBgColor: '#1E90FF',
|
||||||
|
tdBgColor: ['#0D2B3D', '#103B4C', '#14576B', '#187E99']
|
||||||
|
};
|
||||||
|
} else if (e === 'customTable') {
|
||||||
|
return {
|
||||||
|
tableOptions: [],
|
||||||
|
tableCellOptions: [],
|
||||||
|
cellNum: 2,
|
||||||
|
dataNum: 2,
|
||||||
|
tdHeight: '28px',
|
||||||
|
tdColor: ['#D6F4FF', '#D6F4FF', '#D6F4FF', '#D6F4FF'],
|
||||||
|
tdBgColor: ['#0D2B3D', '#103B4C', '#14576B', '#187E99']
|
||||||
|
};
|
||||||
|
} else if (e === 'carousel') {
|
||||||
|
return {swiperOptions: {}, imageFit: 'contain', carouselImages: []};
|
||||||
|
} else if (e === 'background') {
|
||||||
|
return {backgroundColor: '#fff', isBorder: true, borderColor: '#fff', backgroundImage: ''};
|
||||||
|
} else if (e === 'pagination') {
|
||||||
|
return {pageSizeField: 'pageSize', currentPageField: 'pageNum'};
|
||||||
|
} else if (e === 'digitalFlop') {
|
||||||
|
return {
|
||||||
|
field: '',
|
||||||
|
color: '#fff',
|
||||||
|
fontSize: 22,
|
||||||
|
number: 123,
|
||||||
|
numQuantity: 3,
|
||||||
|
backgroundColor: 'rgba(180, 180, 180, 0.2)',
|
||||||
|
isBorder: true,
|
||||||
|
borderColor: '#fff'
|
||||||
|
};
|
||||||
|
} else if (e === 'menu') {
|
||||||
|
return {menuField: '', activeField: '', field: '', color: '#fff', activeColor: '#ffd04b'};
|
||||||
|
} else if (e === 'tree') {
|
||||||
|
return {level: 2, treeOptions: []};
|
||||||
|
} else {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const getNodeSize = (e) => {
|
||||||
|
if (e === 'line' || e === 'multiLines' || e === 'bar' || e === 'multiBars' || e === 'curve' || e === 'multiCurves' || e === 'customBoard' || e === 'pie' || e === 'annular' || e === 'dashboard' || e === 'radar') {
|
||||||
|
return {width: 300, height: 150};
|
||||||
|
} else if (e === 'data' || e === 'customData') {
|
||||||
|
return {width: 150, height: 50};
|
||||||
|
} else if (e === 'inputNode') {
|
||||||
|
return {width: 100, height: 30};
|
||||||
|
} else if (e === 'buttonNode') {
|
||||||
|
return {width: 100, height: 30};
|
||||||
|
} else if (e === 'staticData') {
|
||||||
|
return {width: 100, height: 60};
|
||||||
|
} else if (e === 'text') {
|
||||||
|
return {width: 100, height: 30};
|
||||||
|
} else if (e === 'time') {
|
||||||
|
return {width: 200, height: 30};
|
||||||
|
} else if (e === 'img') {
|
||||||
|
return {width: 300, height: 300};
|
||||||
|
} else if (e === 'map') {
|
||||||
|
return {width: 100, height: 30};
|
||||||
|
} else if (e === 'menu') {
|
||||||
|
return {width: 200, height: 800};
|
||||||
|
} else if (e === 'scrollTable' || e === 'table') {
|
||||||
|
return {width: 500, height: 300};
|
||||||
|
} else if (e === 'tree') {
|
||||||
|
return {width: 800, height: 800};
|
||||||
|
} else {
|
||||||
|
return {width: 100, height: 100};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const nameEnum = {
|
||||||
|
line: '折线',
|
||||||
|
multiLines: '多折线',
|
||||||
|
curve: '曲线',
|
||||||
|
multiCurves: '多曲线',
|
||||||
|
lineBar: '双轴图',
|
||||||
|
bar: '柱状图',
|
||||||
|
backgroundBar: '背景柱状图',
|
||||||
|
multiBars: '多柱状图',
|
||||||
|
pie: '饼图',
|
||||||
|
annular: '中空饼图',
|
||||||
|
dashboard: '仪表盘',
|
||||||
|
radar: '雷达图',
|
||||||
|
nightingaleRoseDiagram: '南丁格尔玫瑰图',
|
||||||
|
carousel: '轮播图',
|
||||||
|
map: '映射',
|
||||||
|
staticData: '静态数据',
|
||||||
|
customData: '自定义数据',
|
||||||
|
text: '文字',
|
||||||
|
inputNode: '输入框',
|
||||||
|
time: '时间',
|
||||||
|
img: '图片',
|
||||||
|
icon: '图标',
|
||||||
|
video: '视频',
|
||||||
|
timeline: '时间线',
|
||||||
|
digitalFlop: '数字翻牌器',
|
||||||
|
scrollTable: '滚动表格',
|
||||||
|
background: '背景',
|
||||||
|
tree: '树状图'
|
||||||
|
};
|
||||||
|
const tool = () => {
|
||||||
|
const nodeType = ref('');
|
||||||
|
const customData = ref({script: ''});
|
||||||
|
const {addNodes, screenToFlowCoordinate, onNodesInitialized, updateNode} = useVueFlow({id: 'flowA'});
|
||||||
|
const onDragStart = (event, type, data) => {
|
||||||
|
if (event.dataTransfer) {
|
||||||
|
event.dataTransfer.setData('application/vueflow', type);
|
||||||
|
event.dataTransfer.effectAllowed = 'move';
|
||||||
|
}
|
||||||
|
|
||||||
|
nodeType.value = type;
|
||||||
|
customData.value = {...customData.value, ...(data || {})};
|
||||||
|
document.addEventListener('drop', onDragEnd);
|
||||||
|
};
|
||||||
|
const onDragEnd = () => {
|
||||||
|
nodeType.value = null;
|
||||||
|
document.removeEventListener('drop', onDragEnd);
|
||||||
|
};
|
||||||
|
const onDrop = (event) => {
|
||||||
|
const dimensions = getNodeSize(nodeType.value);
|
||||||
|
|
||||||
|
const position = screenToFlowCoordinate({
|
||||||
|
x: event.clientX, y: event.clientY
|
||||||
|
});
|
||||||
|
|
||||||
|
const nodeId = getId(nodeType.value);
|
||||||
|
const newNode = {
|
||||||
|
id: nodeId,
|
||||||
|
name: nameEnum[nodeType.value],
|
||||||
|
draggable: true,
|
||||||
|
type: nodeType.value,
|
||||||
|
dimensions,
|
||||||
|
position,
|
||||||
|
data: {options: getOption(nodeType.value), outputData: {}, customData: customData.value}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const {off} = onNodesInitialized(() => {
|
||||||
|
updateNode(nodeId, (node) => ({
|
||||||
|
position: {
|
||||||
|
x: node.position.x - node.dimensions.width / 2, y: node.position.y - node.dimensions.height / 2
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
off();
|
||||||
|
});
|
||||||
|
|
||||||
|
addNodes(newNode);
|
||||||
|
|
||||||
|
};
|
||||||
|
const onDragOver = (event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
if (nodeType.value) {
|
||||||
|
|
||||||
|
if (event.dataTransfer) {
|
||||||
|
event.dataTransfer.dropEffect = 'move';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return {
|
||||||
|
onDragStart, onDragEnd, onDrop, onDragOver
|
||||||
|
};
|
||||||
|
};
|
||||||
|
export default tool;
|
||||||
@ -0,0 +1,38 @@
|
|||||||
|
import {defineConfig} from 'vite'
|
||||||
|
import vue from '@vitejs/plugin-vue'
|
||||||
|
import path from 'path'
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
plugins: [vue()],
|
||||||
|
resolve: {
|
||||||
|
alias: {
|
||||||
|
// @ 指向 src 目录
|
||||||
|
'@': path.resolve(__dirname, 'src')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
build: {
|
||||||
|
lib: {
|
||||||
|
entry: path.resolve(__dirname, 'src/index.js'),
|
||||||
|
name: 'ScrinVisualEditor',
|
||||||
|
fileName: (format) => {
|
||||||
|
if (format === 'es') return 'scrin-visual-editor.es.js'
|
||||||
|
if (format === 'umd') return 'scrin-visual-editor.umd.js'
|
||||||
|
return `scrin-visual-editor.${format}.js`
|
||||||
|
},
|
||||||
|
cssFileName: 'style'
|
||||||
|
},
|
||||||
|
preserveModules: false,
|
||||||
|
assetsInlineLimit: 0,
|
||||||
|
output: {
|
||||||
|
preserveModulesRoot: 'src',
|
||||||
|
},
|
||||||
|
rollupOptions: {
|
||||||
|
external: ['vue'],
|
||||||
|
output: {
|
||||||
|
globals: {
|
||||||
|
vue: 'Vue'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||