修改看板和首页

master
suixy 3 months ago
parent 23f49449aa
commit eae37c7f7d

@ -0,0 +1,155 @@
<template>
<div class="card">
<div class="head">{{title}}</div>
<div class="content">
<div class="left">
<div class="inner">
<div>
<div class="value" :class="items.color">{{ items[0].value }}</div>
<div class="label">{{ items[0].label }}</div>
</div>
</div>
</div>
<div class="right">
<div class="inner">
<div class="item"></div>
<div
v-for="(item, index) in items.slice(1)"
:key="index"
class="item"
>
<div class="value" :class="item.color">
<span>
{{ item.label }}
</span>
<span style="font-weight: bold;font-size: 22px;margin-left: 12px;">
{{ item.value }}
</span>
</div>
</div>
<div class="item"></div>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { computed } from 'vue';
const props = defineProps({
title: {
type: String,
required: true
},
items: {
type: Array,
default: () => []
}
});
</script>
<style scoped lang="less">
.red {
color: #f56c6c;
}
.green {
color: #67c23a;
}
.blue {
color: #409eff;
}
.card {
height: 100%;
background-color: #fff;
border: 1px solid #ddd;
border-radius: 8px;
position: relative;
margin-right: 16px;
&:last-child{
margin-right: 0;
}
}
.head{
position: absolute;
top: 0;
left: 0;
background-color: #5085FD;
color: #fff;
font-size: 0.8vw;
width: 4vw;
height: 1.5vw;
text-align: center;
line-height: 1.5vw;
border-bottom-right-radius: 1.5vw;
}
.content {
height: 100%;
}
.item {
text-align: center;
}
.left {
height: calc(100% - 2vw);
margin: 1vw 0;
width: 50%;
display: inline-block;
text-align: center;
border-right: 1px solid #ddd;
.inner {
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.value {
font-size: 22px;
font-weight: 600;
line-height: 1.2;
}
.label {
font-size: 13px;
color: #909399;
margin-top: 4px;
}
}
.right {
height: calc(100% - 2vw);
margin: 1vw 0;
width: 50%;
display: inline-block;
vertical-align: top;
.inner {
height: 100%;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.value {
font-size: 14px;
line-height: 1.2;
padding: 0.2vw 0;
}
}
</style>

@ -1,6 +1,9 @@
<template>
<div class="boardGenerate">
<div class="top">
<span style="color: #fff">
{{pageSettingForm}}
</span>
<!-- <el-button @click="nodes.forEach(e=>e.draggable =true)">11</el-button>-->
<div class="componentMenu">
<el-popover
@ -1211,6 +1214,22 @@
<el-form-item label="饼图半径" v-if="Object.keys(nodeAttrForm).includes('pieRadius')">
<el-slider v-model="nodeAttrForm.pieRadius" :min="0" :max="100" range />
</el-form-item>
<el-form-item label="饼图颜色" v-if="Object.keys(nodeAttrForm).includes('colorList')">
<el-badge value="99" class="item" :offset="[-8,0]"
v-for="(i,k) in nodeAttrForm.colorList">
<el-color-picker style="margin-right: 8px;"
v-model="nodeAttrForm.colorList[k]" show-alpha />
<template #content>
<div class="custom-content" @click="nodeAttrForm.colorList.splice(k, 1)">
<el-icon>
<Close />
</el-icon>
</div>
</template>
</el-badge>
<el-button :icon="Plus" @click="nodeAttrForm.colorList.push('#fff')" />
</el-form-item>
<el-form-item label="发送脉冲类型" v-if="Object.keys(nodeAttrForm).includes('sendType')">
<el-select
multiple
@ -2104,7 +2123,7 @@ const setText = (value, row, formula) => {
}
};
</script>
<style scoped lang="less">

@ -16,22 +16,6 @@ import { NodeResizer } from '@vue-flow/node-resizer';
import { Handle, Position } from '@vue-flow/core';
import * as echarts from 'echarts';
let json = {
'tableData': [{
'value1': '测试数据1-1',
'value2': '测试数据1-2',
'value3': '测试数据1-3'
}, { 'value1': '测试数据2-1', 'value2': '测试数据2-2', 'value3': '测试数据2-3' }, {
'value1': '测试数据3-1',
'value2': '测试数据3-2',
'value3': '测试数据3-3'
}, { 'value1': '测试数据4-1', 'value2': '测试数据4-2', 'value3': '测试数据4-3' }, {
'value1': '测试数据5-1',
'value2': '测试数据5-2',
'value3': '测试数据5-3'
}, { 'value1': '测试数据6-1', 'value2': '测试数据6-2', 'value3': '测试数据6-3' }],
'total': 10
};
const props = defineProps({
@ -130,6 +114,15 @@ const getOption = () => {
series: [
{
type: 'pie',
itemStyle: {
color: (a) => {
if(props.data?.options?.colorList?.length){
return props.data?.options?.colorList?.[a.dataIndex % props.data?.options?.colorList?.length];
}else{
return colorList[a.dataIndex %colorList.length]
}
}
},
center: [`${props.data?.options?.pieCenter || 50}%`, '50%'],
radius: [`${props.data?.options?.pieRadius?.[0] || 50}%`, `${props.data?.options?.pieRadius?.[1] || 50}%`],
label: {

@ -1,7 +1,8 @@
<template>
<div
:style="{width:props.dimensions.width*props.ratioWidth+'px',height:props.dimensions.height*props.ratioHeight+'px'}">
<NodeResizer @resizeEnd="(e) => $emit('resize', e)" color="#fff" v-if="!props.isView && !props.isHideHandle && props.selected" @resize="resize" />
<NodeResizer @resizeEnd="(e) => $emit('resize', e)" color="#fff"
v-if="!props.isView && !props.isHideHandle && props.selected" @resize="resize" />
<div class="custom-node"
:style="{width:props.dimensions.width*props.ratioWidth+'px',height:props.dimensions.height*props.ratioHeight+'px',pointerEvents:props.isView?'auto': 'none'}">
@ -72,18 +73,18 @@ const getOption = () => {
top: '5%'
},
legend: {
show:props.data?.options?.legend||false,
show: props.data?.options?.legend || false,
icon: 'circle',
top: '5%',
right: '5%',
itemWidth: 6,
itemGap: 20,
textStyle: {
color: props.data?.options?.legendColor ||'#fff'
color: props.data?.options?.legendColor || '#fff'
}
},
tooltip: {
show:props.data?.options?.tooltip||false,
show: props.data?.options?.tooltip || false,
trigger: 'axis',
axisPointer: {
label: {
@ -115,19 +116,26 @@ const getOption = () => {
radius: '50%',
center: [`${props.data?.options?.pieCenter || 50}%`, '50%'],
label: {
show:props.data?.options?.label||false,
show: props.data?.options?.label || false,
formatter: props.data?.options?.pieLabelFormatter || '{b}: {d}%'
},
itemStyle:{
color:(a,b,c,d) =>{
console.log(a);
console.log(b);
console.log(c);
console.log(d);
}
},
labelLine: {
length: 2, // 线
length2: 3 // 线
length: 2,
length2: 3
}
}
]
};
let xData = [props.inputData?.x1 || []];
let yData = [props.inputData?.y1 || []];
console.log(chartOption);
let length = Math.min(...xData.map(e => e.length), ...yData.map(e => e.length));
let source = [['product', ...[props.data.options?.yNames?.[0] || '数量']]];
Array(length).fill(0).forEach((_, i) => {
@ -140,7 +148,6 @@ const getOption = () => {
});
source.push(item);
});
console.log(source);
return {
...chartOption,
dataset: {

@ -288,7 +288,8 @@ const getOption = (e) => {
};
} else if (e === 'annular') {
return {
title: '', yNames: [], tooltip: true, legend: true, label: true, pieCenter: 50, pieRadius: [30, 70]
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 };

@ -1,165 +1,349 @@
<template>
<div class="app-container home">
<el-row :gutter="20">
<el-col :sm="24" :lg="12" style="padding-left: 20px">
<h2>{{ $t('login.momSystem') }}</h2>
<!-- <p>-->
<!-- RuoYi-Vue-Plus 是基于 RuoYi-Vue 针对 分布式集群 场景升级(不兼容原框架)-->
<!-- <br />-->
<!-- * 前端开发框架 Vue3TSElement Plus<br />-->
<!-- * 后端开发框架 Spring Boot<br />-->
<!-- * 容器框架 Undertow 基于 Netty 的高性能容器<br />-->
<!-- * 权限认证框架 Sa-Token 支持多终端认证系统<br />-->
<!-- * 关系数据库 MySQL 适配 8.X 最低 5.7<br />-->
<!-- * 缓存数据库 Redis 适配 6.X 最低 4.X<br />-->
<!-- * 数据库框架 Mybatis-Plus 快速 CRUD 增加开发效率<br />-->
<!-- * 数据库框架 p6spy 更强劲的 SQL 分析<br />-->
<!-- * 多数据源框架 dynamic-datasource 支持主从与多种类数据库异构<br />-->
<!-- * 序列化框架 Jackson 统一使用 jackson 高效可靠<br />-->
<!-- * Redis客户端 Redisson 性能强劲API丰富<br />-->
<!-- * 分布式限流 Redisson 全局请求IP集群ID 多种限流<br />-->
<!-- * 分布式锁 Lock4j 注解锁工具锁 多种多样<br />-->
<!-- * 分布式幂等 Lock4j 基于分布式锁实现<br />-->
<!-- * 分布式链路追踪 SkyWalking 支持链路追踪网格分析度量聚合可视化<br />-->
<!-- * 分布式任务调度 SnailJob 高性能 高可靠 易扩展<br />-->
<!-- * 文件存储 Minio 本地存储<br />-->
<!-- * 文件存储 七牛阿里腾讯 云存储<br />-->
<!-- * 监控框架 SpringBoot-Admin 全方位服务监控<br />-->
<!-- * 校验框架 Validation 增强接口安全性 严谨性<br />-->
<!-- * Excel框架 Alibaba EasyExcel 性能优异 扩展性强<br />-->
<!-- * 文档框架 SpringDocjavadoc 无注解零入侵基于java注释<br />-->
<!-- * 工具类框架 HutoolLombok 减少代码冗余 增加安全性<br />-->
<!-- * 代码生成器 适配MPSpringDoc规范化代码 一键生成前后端代码<br />-->
<!-- * 部署方式 Docker 容器编排 一键部署业务集群<br />-->
<!-- * 国际化 SpringMessage Spring标准国际化方案<br />-->
<!-- </p>-->
<!-- <p><b>当前版本:</b> <span>v5.2.3</span></p>-->
<!-- <p>-->
<!-- <el-tag type="danger">&yen;免费开源</el-tag>-->
<!-- </p>-->
<!-- <p>-->
<!-- <el-button type="primary" icon="Cloudy" plain @click="goTarget('https://gitee.com/dromara/RuoYi-Vue-Plus')">访</el-button>-->
<!-- <el-button type="primary" icon="Cloudy" plain @click="goTarget('https://github.com/dromara/RuoYi-Vue-Plus')">访GitHub</el-button>-->
<!-- <el-button type="primary" icon="Cloudy" plain @click="goTarget('https://plus-doc.dromara.org/#/ruoyi-vue-plus/changlog')"-->
<!-- >更新日志</el-button-->
<!-- >-->
<!-- </p>-->
<!-- </el-col>-->
<div class="dashboard">
<!-- Top Cards -->
<div class="card-row">
<StatCard title="订单" :items="[
{ label: '销售总量', value: 1000 },
{ label: '未出库量', value: 100, color: 'red' },
{ label: '已出库量', value: 100, color: 'green' }
]" />
<StatCard title="工单" :items="[
{ label: '工单总数', value: 10 },
{ label: '未投产', value: 10, color: 'red' },
{ label: '已投产', value: 10, color: 'blue' },
{ label: '已完工', value: 10, color: 'green' }
]" />
<StatCard title="任务" :items="[
{ label: '任务总数', value: 10 },
{ label: '未开工', value: 10, color: 'red' },
{ label: '执行中', value: 10, color: 'blue' },
{ label: '已完工', value: 10, color: 'green' }
]" />
<StatCard title="产量" :items="[
{ label: '产量总量', value: 10 },
{ label: '完成率', value: '10%' },
{ label: '良品率', value: '90%', color: 'green' }
]" />
</div>
<!-- <el-col :sm="24" :lg="12" style="padding-left: 20px">-->
<!-- <h2>RuoYi-Cloud-Plus多租户微服务管理系统</h2>-->
<!-- <p>-->
<!-- RuoYi-Cloud-Plus 微服务通用权限管理系统 重写 RuoYi-Cloud 全方位升级(不兼容原框架)-->
<!-- <br />-->
<!-- * 前端开发框架 Vue3TSElement UI<br />-->
<!-- * 后端开发框架 Spring Boot<br />-->
<!-- * 微服务开发框架 Spring CloudSpring Cloud Alibaba<br />-->
<!-- * 容器框架 Undertow 基于 XNIO 的高性能容器<br />-->
<!-- * 权限认证框架 Sa-TokenJwt 支持多终端认证系统<br />-->
<!-- * 关系数据库 MySQL 适配 8.X 最低 5.7<br />-->
<!-- * 关系数据库 Oracle 适配 11g 12c<br />-->
<!-- * 关系数据库 PostgreSQL 适配 13 14<br />-->
<!-- * 关系数据库 SQLServer 适配 2017 2019<br />-->
<!-- * 缓存数据库 Redis 适配 6.X 最低 5.X<br />-->
<!-- * 分布式注册中心 Alibaba Nacos 采用2.X 基于GRPC通信高性能<br />-->
<!-- * 分布式配置中心 Alibaba Nacos 采用2.X 基于GRPC通信高性能<br />-->
<!-- * 服务网关 Spring Cloud Gateway 响应式高性能网关<br />-->
<!-- * 负载均衡 Spring Cloud Loadbalancer 负载均衡处理<br />-->
<!-- * RPC远程调用 Apache Dubbo 原生态使用体验高性能<br />-->
<!-- * 分布式限流熔断 Alibaba Sentinel 无侵入高扩展<br />-->
<!-- * 分布式事务 Alibaba Seata 无侵入高扩展 支持 四种模式<br />-->
<!-- * 分布式消息队列 Apache Kafka 高性能高速度<br />-->
<!-- * 分布式消息队列 Apache RocketMQ 高可用功能多样<br />-->
<!-- * 分布式消息队列 RabbitMQ 支持各种扩展插件功能多样性<br />-->
<!-- * 分布式搜索引擎 ElasticSearch 业界知名<br />-->
<!-- * 分布式链路追踪 Apache SkyWalking 链路追踪网格分析度量聚合可视化<br />-->
<!-- * 分布式日志中心 ELK 业界成熟解决方案<br />-->
<!-- * 分布式监控 PrometheusGrafana 全方位性能监控<br />-->
<!-- * 其余与 Vue 版本一致<br />-->
<!-- </p>-->
<!-- <p><b>当前版本:</b> <span>v2.2.2</span></p>-->
<!-- <p>-->
<!-- <el-tag type="danger">&yen;免费开源</el-tag>-->
<!-- </p>-->
<!-- <p>-->
<!-- <el-button type="primary" icon="Cloudy" plain @click="goTarget('https://gitee.com/dromara/RuoYi-Cloud-Plus')">访</el-button>-->
<!-- <el-button type="primary" icon="Cloudy" plain @click="goTarget('https://github.com/dromara/RuoYi-Cloud-Plus')">访GitHub</el-button>-->
<!-- <el-button type="primary" icon="Cloudy" plain @click="goTarget('https://plus-doc.dromara.org/#/ruoyi-cloud-plus/changlog')"-->
<!-- >更新日志</el-button-->
<!-- >-->
<!-- </p>-->
</el-col>
</el-row>
<el-divider />
<!-- Middle -->
<div class="middle-row">
<div class="panel">
<div class="head">
<div>实时报工</div>
</div>
<el-timeline style="max-width: 600px">
<el-timeline-item :timestamp="item.time" placement="top" v-for="item in timeline ">
<div class="content">
<div style="color: #9EBDFE;font-size: 0.8vw;margin-bottom: 0.4vw;">{{ item.user }} {{ item.action }}</div>
<div>工单号{{ item.order }}</div>
<div>物料{{ item.material }}</div>
<div>良品 {{ item.good }} / 不良 {{ item.bad }}</div>
</div>
</el-timeline-item>
</el-timeline>
</div>
<div class="panel">
<div class="head">
<div>生产预警</div>
</div>
<div class="th">
<div class="td">工单计划截止日</div>
<div class="td" style="text-align: right">计划数</div>
</div>
<div v-for="(d,i) in warning" :key="d.day" class="progress-item">
<div class="td" style="width: 50px">{{ d.day }}</div>
<div class="td" style="width: calc(100% - 130px); ">
<el-progress
:text-inside="true"
:stroke-width="6"
:percentage="(d.value / d.max)*100"
:status="i > 0 ? 'exception':''"
>
<div></div>
</el-progress>
<div :style="{left:((d.value / d.max)*100)+'%'}" class="progressNum" :class="i > 0 ? 'exception':''">
{{ d.value }}
</div>
</div>
<div class="td" style="width: 80px;padding-right: 12px;text-align: right">{{ d.max }}</div>
</div>
</div>
<div style="margin-right: 0" class="panel">
<div class="head">
<div>物料库存</div>
</div>
<div class="stock-summary">
<div class="stockCard">
<div class="num">100</div>
<div class="text">物料数</div>
</div>
<div class="stockCard">
<div class="num">1000.1234</div>
<div class="text">库存总量</div>
</div>
<div class="stockCard">
<div class="num">20</div>
<div class="text">超库存上限</div>
</div>
<div class="stockCard">
<div class="num">10</div>
<div class="text">超库存下限</div>
</div>
</div>
<div ref="pieRef" class="chart"></div>
</div>
</div>
<!-- Bottom Chart -->
<div style="margin-right: 0" class="panel">
<div class="head">
<div>物料库存趋势</div>
</div>
<div ref="lineRef" class="chart"></div>
</div>
</div>
</template>
<script setup name="Index" lang="ts">
const goTarget = (url: string) => {
window.open(url, '__blank');
};
<script setup>
import { onMounted, ref } from 'vue';
import * as echarts from 'echarts';
import StatCard from '@/components/StatCard.vue';
const timeline = [
{ time: '10:00', user: '张三', action: '印刷', order: 'GD2033322222', material: '电子标签001', good: 100, bad: 10 },
{ time: '09:00', user: '张三', action: '印刷', order: 'GD2033322222', material: '电子标签001', good: 100, bad: 10 }
];
const warning = [
{ day: '1天内', value: 1000, max: 2000 },
{ day: '2天内', value: 1000, max: 3000 },
{ day: '3天内', value: 1000, max: 3000 },
{ day: '4天内', value: 1000, max: 3000 },
{ day: '5天内', value: 1000, max: 3000 }
];
const pieRef = ref(null);
const lineRef = ref(null);
onMounted(() => {
const pie = echarts.init(pieRef.value);
pie.setOption({
tooltip: {},
series: [{
type: 'pie',
radius: '70%',
label: {
formatter: '{b}\n{c}'
},
itemStyle: {
borderRadius: 5 //
},
data: [
{
name: '原料',
value: 100,
itemStyle: {
color: '#4A63EA'
}
},
{
name: '成品',
value: 150,
itemStyle: {
color: '#86AAF4'
}
},
{
name: '半成品',
value: 208,
itemStyle: {
color: '#698CF1'
}
},
{
name: '原辅料',
value: 149,
itemStyle: {
color: '#CDDFF9'
}
}
]
}]
});
const line = echarts.init(lineRef.value);
line.setOption({
tooltip: {},
grid:{
top:40,
left:80,
right:20,
bottom:30,
},
legend: { data: ['入库', '出库'] },
xAxis: { type: 'category', data: ['2022-01-01', '2022-01-02', '2022-01-03', '2022-01-04', '2022-01-05'] },
yAxis: { type: 'value' },
series: [
{
name: '入库',
type: 'bar',
data: [100, 140, 230, 100, 130],
itemStyle: {
color: '#4A63EA'
}
},
{
name: '出库',
type: 'bar',
data: [150, 100, 200, 150, 100],
itemStyle: {
color: '#85ABF4'
}
},
{
name: '库存',
type: 'line',
data: [100, 140, 230, 100, 130],
itemStyle: {
color: '#4B64EA'
},
label: {
show: true,
color: '#3D59E9'
}
}
]
});
});
</script>
<style scoped lang="scss">
.home {
blockquote {
padding: 10px 20px;
margin: 0 0 20px;
font-size: 17.5px;
border-left: 5px solid #eee;
<style scoped>
.dashboard {
padding: 16px;
background: #f5f7fa;
}
.card-row {
display: grid;
grid-template-columns: repeat(4, 1fr);
}
.middle-row {
display: grid;
grid-template-columns: 1fr 1fr 2fr;
margin-top: 16px;
}
.panel {
background: #fff;
padding: 16px;
border-radius: 8px;
margin-right: 16px;
.head {
color: #5291FD;
font-weight: bold;
border-bottom: 1px solid #ddd;
margin-bottom: 0.5vw;
padding-bottom: 0.5vw;
}
hr {
margin-top: 20px;
margin-bottom: 20px;
border: 0;
border-top: 1px solid #eee;
}
.col-item {
margin-bottom: 20px;
}
.timeline {
list-style: none;
padding: 0;
}
.timeline li {
display: flex;
margin-bottom: 12px;
}
.time {
width: 60px;
color: #409eff;
}
.content {
background: #f0f4ff;
padding: 8px;
border-radius: 6px;
flex: 1;
}
.progress-item {
width: 100%;
margin-bottom: 1.6vw;
.td {
display: inline-block;
font-size: 14px;
color: #666;
position: relative;
}
ul {
padding: 0;
margin: 0;
.progressNum {
position: absolute;
top: 50%;
transform: translate(-50%, -50%);
text-align: center;
width: 2vw;
height: 1vw;
color: #fff;
line-height: 1vw;
background-color: #419EFF;
border-radius: 1vw;
}
font-family: 'open sans', 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-size: 13px;
color: #676a6c;
overflow-x: hidden;
ul {
list-style-type: none;
.exception {
background-color: #F56C6C;
}
}
h4 {
margin-top: 0px;
}
.chart {
width: 100%;
height: 260px;
}
h2 {
margin-top: 10px;
font-size: 26px;
font-weight: 100;
}
.stock-summary {
width: 100%;
height: 5vw;
p {
margin-top: 10px;
.stockCard {
display: inline-block;
width: 25%;
height: 100%;
text-align: center;
b {
font-weight: 700;
.num {
height: 60%;
line-height: 3vw;
font-size: 1.4vw;
font-weight: bold;
}
}
.update-log {
ol {
display: block;
list-style-type: decimal;
margin-block-start: 1em;
margin-block-end: 1em;
margin-inline-start: 0;
margin-inline-end: 0;
padding-inline-start: 40px;
.text {
height: 40%;
color: #666;
}
}
}
.th {
width: 100%;
margin-bottom: 1vw;
.td {
width: 50%;
display: inline-block;
padding-right: 12px;
font-size: 14px;
color: #666;
}
}
</style>

@ -16,7 +16,7 @@
<div id="printInfo" ref="printRef">
<div
class="content"
v-for="pageData in pageDatas"
v-for="(pageData,k) in pageDatas"
:style="{ pageBreakAfter: 'always', width: cmToPx(pageWidth) + 'px', height: cmToPx(pageHeight) + 'px', marginBottom: '4px' ,transform: `scale(${zoom})`}"
>
<div v-for="i in nodes" class="node" :style="{ left: i.position?.x + 'px', top: i.position?.y + 'px' }">
@ -70,6 +70,7 @@
:isView="true"
:isPrint="isPrint"
:pageData="pageData"
@update="setValue($event,i.data.options.field,k)"
:pageSize="{ width: cmToPx(pageWidth), height: cmToPx(pageHeight) }"
v-bind="i"
></SelectNode>
@ -79,6 +80,7 @@
:isView="true"
:isPrint="isPrint"
:pageData="pageData"
@update="setValue($event,i.data.options.field,k)"
:pageSize="{ width: cmToPx(pageWidth), height: cmToPx(pageHeight) }"
v-bind="i"
></InputNode>
@ -151,31 +153,29 @@ const printRef = ref();
const pageWidth = ref(21);
const pageHeight = ref(29.7);
const pageDatas = ref([]);
const zoom = ref(1)
const zoom = ref(1);
const { cmToPx } = options;
const nodes = ref([]);
const messageFun = (event) => {
console.log(event);
// if (isJSON(event.data)) {
// let data = JSON.parse(event.data);
let data = event.data;
if (data.type === 'print') {
printFun();
}
if (data.type === 'print') {
window.chrome?.webview?.postMessage(JSON.stringify({ value: pageDatas.value, type: 'print' }));
printFun();
}
if (data.type === 'JSONDATA') {
if (typeof data.message === 'object' && data.message !== null && !Array.isArray(data.message)) {
pageDatas.value = [data.message];
// window.chrome?.webview?.postMessage('setDataFinally');
} else if (Array.isArray(data.message)) {
pageDatas.value = data.message;
// window.chrome?.webview?.postMessage('setDataFinally');
} else {
// window.chrome?.webview?.postMessage('setDataFail');
}
console.log('message', data.message);
if (typeof data.message === 'object' && data.message !== null && !Array.isArray(data.message)) {
pageDatas.value = [data.message];
// window.chrome?.webview?.postMessage('setDataFinally');
} else if (Array.isArray(data.message)) {
pageDatas.value = data.message;
// window.chrome?.webview?.postMessage('setDataFinally');
} else {
// window.chrome?.webview?.postMessage('setDataFail');
}
}
// }
console.log(event);
};
const setNodes = (data) => {
@ -203,11 +203,14 @@ const setNodes = (data) => {
};
});
nextTick(() => {
zoom.value = ((printRef.value.offsetWidth - 20) / 793)
zoom.value = ((printRef.value.offsetWidth - 20) / 793);
});
});
});
};
const setValue = (value, field, index) => {
pageDatas.value[index][field] = value;
};
onMounted(() => {
window.chrome?.webview?.addEventListener('message', messageFun);
window.chrome?.webview?.postMessage('onMounted');
@ -224,32 +227,11 @@ onMounted(() => {
}
}
listPrintTemplateList().then(data => {
console.log(data);
printTemplateList.value = data.rows;
});
});
const printInfoObj = {
id: 'printInfo',
preview: false, //
beforeOpenCallback(vue) {
console.log('触发打印工具打开前回调');
},
openCallback(vue) {
console.log('触发打印工具打开的回调');
},
closeCallback() {
console.log('触发关闭打印工具回调');
},
previewBeforeOpenCallback() {
console.log('触发预览前回调');
},
previewOpenCallback() {
console.log('触发预览的回调');
}
};
const switchPrinter = (e) => {
console.log(e);
printType.value = e;
};
const printFun = (e) => {
@ -315,7 +297,6 @@ const openPrint = (pages, templateId) => {
if (typeof pages !== 'object' || pages === null) {
pageData = [pages];
}
console.log(pageData);
pageDatas.value = pageData || [];
});
};

@ -1,718 +0,0 @@
<template>
<div style="width: 100%;height: 100vh;overflow: hidden">
<div class="left">
<div id="printInfo" ref="printRef">
<div class="content" v-for=" pageData in pageDatas"
:style="{pageBreakAfter: 'always',width: cmToPx(pageWidth)+'px',height: cmToPx(pageHeight)+'px',marginBottom:'4px'}">
<div v-for="i in nodes" class="node" :style="{left:i.position?.x+'px',top: i.position?.y+'px'}">
<template v-if="i.type === 'text'">
<TextNode v-bind="i" :isView="true" :isPrint="isPrint" :pageData="pageData"
:pageSize="{width: cmToPx(pageWidth) ,height: cmToPx(pageHeight) }"></TextNode>
</template>
<template v-if="i.type === 'image'">
<ImageNode v-bind="i" :isView="true" :isPrint="isPrint" :pageData="pageData"
:pageSize="{width: cmToPx(pageWidth) ,height: cmToPx(pageHeight) }"></ImageNode>
</template>
<template v-if="i.type === 'barCode'">
<BarCodeNode v-bind="i" :isView="true" :isPrint="isPrint" :pageData="pageData"
:pageSize="{width: cmToPx(pageWidth) ,height: cmToPx(pageHeight) }"></BarCodeNode>
</template>
<template v-if="i.type === 'QRCode'">
<QRCodeNode v-bind="i" :isView="true" :isPrint="isPrint" :pageData="pageData"
:pageSize="{width: cmToPx(pageWidth) ,height: cmToPx(pageHeight) }"></QRCodeNode>
</template>
<template v-if="i.type === 'dateTime'">
<TimeNode v-bind="i" :isView="true" :isPrint="isPrint" :pageData="pageData"
:pageSize="{width: cmToPx(pageWidth) ,height: cmToPx(pageHeight) }"></TimeNode>
</template>
<template v-if="i.type === 'select'">
<SelectNode :isView="true" :isPrint="isPrint" :pageData="pageData"
:pageSize="{width: cmToPx(pageWidth) ,height: cmToPx(pageHeight) }"
v-bind="i"></SelectNode>
</template>
</div>
</div>
</div>
</div>
<div class="right">
<el-dropdown split-button type="primary" @click="printFun" @command="switchPrinter" style="margin-right: 8px;">
{{ printName() }}
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item :command="-1">导出PDF</el-dropdown-item>
<el-dropdown-item divided :command="0">本地打印</el-dropdown-item>
<el-dropdown-item :divided="k===0" :command="i.id" v-for=" (i,k) in printers">{{ i.name }}
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</div>
</div>
<div id="printArea" v-if="printPngList.length>0">
<div
v-for="(url, index) in printPngList"
:key="index"
class="print-page"
>
<img :src="url" class="print-image" />
</div>
</div>
</template>
<script setup>
import html2canvas from 'html2canvas';
import jsPDF from 'jspdf';
import { options } from '@/views/print/tool.js';
import TextNode from '@/views/print/nodes/textNode.vue';
import ImageNode from '@/views/print/nodes/image.vue';
import BarCodeNode from './nodes/barCodeNode.vue';
import QRCodeNode from './nodes/QRCodeNode.vue';
import TimeNode from './nodes/timeNode.vue';
import SelectNode from './nodes/selectNode.vue';
import { useRoute } from 'vue-router';
import { isJSON } from '@/utils/scrin.js';
const route = useRoute();
const printType = ref(0);
const printers = ref([
{
id: 1,
name: '网络打印机1'
},
{
id: 2,
name: '网络打印机2'
},
{
id: 3,
name: '网络打印机3'
}
]);
const printPngList = ref([]);
const isView = ref(true);
const isPrint = ref(false);
const printRef = ref();
const pageWidth = ref(21);
const pageHeight = ref(29.7);
const pageDatas = ref([{}, {}]);
const { cmToPx } = options;
const nodes = ref([]);
let printNode = `[
{
"id": "area_d14a13ad_1a78_4171_b54f_93d18abd528d",
"type": "area",
"dimensions": {
"width": 794,
"height": 1123
},
"computedPosition": {
"x": 0,
"y": 0,
"z": 0
},
"handleBounds": {
"source": null,
"target": null
},
"selected": false,
"dragging": false,
"resizing": false,
"initialized": false,
"isParent": true,
"position": {
"x": 0,
"y": 0
},
"data": {},
"events": {},
"name": "area"
},
{
"id": "text_1902a5ff_d7fc_4750_b634_8a88868f3ddb",
"type": "text",
"dimensions": {
"width": 94,
"height": 19
},
"computedPosition": {
"x": 151.1811023622047,
"y": 37.79527559055118,
"z": 1
},
"handleBounds": {
"source": null,
"target": null
},
"selected": false,
"dragging": false,
"resizing": false,
"initialized": false,
"isParent": false,
"position": {
"x": 151.1811023622047,
"y": 37.79527559055118
},
"data": {
"options": {
"default": "供应商",
"border": [
{
"type": "top",
"isShow": false,
"width": 1,
"color": "#000",
"borderType": "solid"
},
{
"type": "right",
"isShow": false,
"width": 1,
"color": "#000",
"borderType": "solid"
},
{
"type": "bottom",
"isShow": false,
"width": 1,
"color": "#000",
"borderType": "solid"
},
{
"type": "left",
"isShow": false,
"width": 1,
"color": "#000",
"borderType": "solid"
}
]
},
"outputData": {}
},
"events": {},
"name": "text",
"parentNode": "area_d14a13ad_1a78_4171_b54f_93d18abd528d",
"extent": "parent",
"style": {
"width": "94px",
"height": "19px"
}
},
{
"id": "text_899234fc_9ace_49c3_8127_fadeabcbd23d",
"type": "text",
"dimensions": {
"width": 94,
"height": 19
},
"computedPosition": {
"x": 150.97637795275588,
"y": 56.69291338582677,
"z": 1
},
"handleBounds": {
"source": null,
"target": null
},
"selected": false,
"dragging": false,
"resizing": false,
"initialized": false,
"isParent": false,
"position": {
"x": 150.97637795275588,
"y": 56.69291338582677
},
"data": {
"options": {
"default": "客户名称",
"border": [
{
"type": "top",
"isShow": false,
"width": 1,
"color": "#000",
"borderType": "solid"
},
{
"type": "right",
"isShow": false,
"width": 1,
"color": "#000",
"borderType": "solid"
},
{
"type": "bottom",
"isShow": false,
"width": 1,
"color": "#000",
"borderType": "solid"
},
{
"type": "left",
"isShow": false,
"width": 1,
"color": "#000",
"borderType": "solid"
}
]
},
"outputData": {}
},
"events": {},
"name": "text",
"parentNode": "area_d14a13ad_1a78_4171_b54f_93d18abd528d",
"extent": "parent",
"style": {
"width": "94px",
"height": "19px"
}
},
{
"id": "text_8da299d4_a35b_4ba9_bfac_860c200b6cf3",
"type": "text",
"dimensions": {
"width": 94,
"height": 19
},
"computedPosition": {
"x": 245.66929133858267,
"y": 56.69291338582677,
"z": 1
},
"handleBounds": {
"source": null,
"target": null
},
"selected": false,
"dragging": false,
"resizing": false,
"initialized": false,
"isParent": false,
"position": {
"x": 245.66929133858267,
"y": 56.69291338582677
},
"data": {
"options": {
"field": "name",
"default": "",
"border": [
{
"type": "top",
"isShow": false,
"width": 1,
"color": "#000",
"borderType": "solid"
},
{
"type": "right",
"isShow": false,
"width": 1,
"color": "#000",
"borderType": "solid"
},
{
"type": "bottom",
"isShow": false,
"width": 1,
"color": "#000",
"borderType": "solid"
},
{
"type": "left",
"isShow": false,
"width": 1,
"color": "#000",
"borderType": "solid"
}
]
},
"outputData": {}
},
"events": {},
"name": "text",
"parentNode": "area_d14a13ad_1a78_4171_b54f_93d18abd528d",
"extent": "parent",
"style": {
"width": "94px",
"height": "19px"
}
},
{
"id": "text_5a3a87dd_1697_43a1_9678_f20421e1f3df",
"type": "text",
"dimensions": {
"width": 396,
"height": 19
},
"computedPosition": {
"x": 245.66929133858267,
"y": 37.79527559055118,
"z": 1
},
"handleBounds": {
"source": null,
"target": null
},
"selected": false,
"dragging": false,
"resizing": false,
"initialized": false,
"isParent": false,
"position": {
"x": 245.66929133858267,
"y": 37.79527559055118
},
"data": {
"options": {
"field": "DONGLONG HOME TEXTILE CO..,LTD.",
"default": "DONGLONG HOME TEXTILE CO..,LTD.",
"border": [
{
"type": "top",
"isShow": false,
"width": 1,
"color": "#000",
"borderType": "solid"
},
{
"type": "right",
"isShow": false,
"width": 1,
"color": "#000",
"borderType": "solid"
},
{
"type": "bottom",
"isShow": false,
"width": 1,
"color": "#000",
"borderType": "solid"
},
{
"type": "left",
"isShow": false,
"width": 1,
"color": "#000",
"borderType": "solid"
}
]
},
"outputData": {}
},
"events": {},
"name": "text",
"parentNode": "area_d14a13ad_1a78_4171_b54f_93d18abd528d",
"extent": "parent",
"style": {
"width": "396px",
"height": "19px"
}
},
{
"id": "text_e9bde955_7c37_44d0_8c37_265ad44fdd9d",
"type": "text",
"dimensions": {
"width": 75,
"height": 19
},
"computedPosition": {
"x": 170.0787401574803,
"y": 302.3622047244094,
"z": 1
},
"handleBounds": {
"source": null,
"target": null
},
"selected": false,
"dragging": false,
"resizing": false,
"initialized": false,
"isParent": false,
"position": {
"x": 170.0787401574803,
"y": 302.3622047244094
},
"data": {
"options": {
"field": "deviceName",
"default": "",
"border": [
{
"type": "top",
"isShow": false,
"width": 1,
"color": "#000",
"borderType": "solid"
},
{
"type": "right",
"isShow": false,
"width": 1,
"color": "#000",
"borderType": "solid"
},
{
"type": "bottom",
"isShow": false,
"width": 1,
"color": "#000",
"borderType": "solid"
},
{
"type": "left",
"isShow": false,
"width": 1,
"color": "#000",
"borderType": "solid"
}
]
},
"outputData": {}
},
"events": {},
"name": "text",
"parentNode": "area_d14a13ad_1a78_4171_b54f_93d18abd528d",
"extent": "parent",
"style": {
"width": "75px",
"height": "19px"
}
},
{
"id": "QRCode_94877b0d_0e26_4a8e_b159_8d99120725a0",
"type": "QRCode",
"dimensions": {
"width": 189,
"height": 189
},
"computedPosition": {
"x": 415.74803149606294,
"y": 264.56692913385825,
"z": 1001
},
"handleBounds": {
"source": null,
"target": null
},
"selected": true,
"dragging": false,
"resizing": false,
"initialized": false,
"isParent": false,
"position": {
"x": 415.74803149606294,
"y": 264.56692913385825
},
"data": {
"options": {
"default": "123123121"
},
"outputData": {}
},
"events": {},
"name": "QRCode",
"parentNode": "area_d14a13ad_1a78_4171_b54f_93d18abd528d",
"extent": "parent"
}
]`;
window.addEventListener('message', (event) => {
if (isJSON(event.data)) {
let data = JSON.parse(event.data);
if (data.type === 'print') {
printFun();
}
if (data.type === 'setData') {
if (typeof data.value === 'object' && data.value !== null && !Array.isArray(data.value)) {
pageDatas.value = [data.value];
}
if (Array.isArray(data.value)) {
pageDatas.value = data.value;
}
}
if (data.type === 'setTemplate') {
nodes.value = JSON.parse(printNode || '[]');
}
}
});
onMounted(() => {
// nodes.value = JSON.parse(localStorage.getItem('printNodes') || '[]');
nodes.value = JSON.parse(printNode || '[]');
const param = route.query.data;
if (isJSON(param)) {
let data = JSON.parse(param);
if (Array.isArray(data)) {
}
// if()
}
});
const printInfoObj = {
id: 'printInfo',
preview: false, //
beforeOpenCallback(vue) {
console.log('触发打印工具打开前回调');
},
openCallback(vue) {
console.log('触发打印工具打开的回调');
},
closeCallback() {
console.log('触发关闭打印工具回调');
},
previewBeforeOpenCallback() {
console.log('触发预览前回调');
},
previewOpenCallback() {
console.log('触发预览的回调');
}
};
const switchPrinter = (e) => {
console.log(e);
printType.value = e;
};
const printFun = (e) => {
if (printType.value === -1) {
isPrint.value = true;
nextTick(() => {
const element = printRef.value;
let eles = element.querySelectorAll('.content');
const pros = [];
eles.forEach((ele, index) => {
pros.push(
html2canvas(ele).then(canvas => {
const imgData = canvas.toDataURL('image/png');
const pdf = new jsPDF();
pdf.addImage(imgData, 'PNG', 0, 0);
pdf.save(`${new Date().getTime()}-${index}.pdf`);
})
);
});
Promise.all(pros).then((values) => {
isPrint.value = false;
});
});
} else if (printType.value === 0) {
isPrint.value = true;
printPngList.value = [];
nextTick(() => {
const element = printRef.value;
let eles = element.querySelectorAll('.content');
const pros = [];
eles.forEach((ele, index) => {
pros.push(
html2canvas(ele).then(canvas => {
const imgData = canvas.toDataURL('image/png');
printPngList.value.push(imgData);
})
);
});
Promise.all(pros).then((values) => {
window.print();
isPrint.value = false;
printPngList.value = [];
});
});
} else {
}
};
const closePrint = () => {
isView.value = false;
};
const openPrint = (pages, templateId) => {
isView.value = false;
nextTick(() => {
nodes.value = JSON.parse(localStorage.getItem('printNodes') || '[]');
isView.value = true;
let pageData = [];
if (Array.isArray(pages)) {
pageData = pages;
}
if (typeof pages !== 'object' || pages === null) {
pageData = [pages];
}
console.log(pageData);
pageDatas.value = pageData || [];
});
};
const printName = () => {
if (printType.value === -1) {
return '导出PDF';
} else if (printType.value === 0) {
return '本地打印';
} else {
let name = printers?.value?.find(e => e.id === printType?.value)?.name;
return name || '';
}
};
defineExpose({
openPrint
// closePrint
});
</script>
<style scoped>
.content {
position: relative;
overflow: hidden;
background-repeat: no-repeat;
background-size: 100% 100%;
border: 1px solid #ccc;
}
.node {
position: absolute;
}
.left {
display: inline-block;
width: calc(100% - 200px);
}
.right {
vertical-align: top;
display: inline-block;
width: 200px;
}
</style>
<style>
.print-page {
page-break-after: always;
text-align: center;
padding: 20px;
background: white;
}
.print-image {
max-width: 100%;
height: auto;
}
/* 打印样式:仅显示图片区域 */
@media print {
body * {
visibility: hidden !important;
}
#printArea,
#printArea * {
visibility: visible !important;
}
#printArea {
position: absolute;
top: 0;
left: 0;
width: 100%;
}
.print-page {
page-break-after: always;
}
}
</style>

@ -51,11 +51,89 @@
<!-- </el-tag>-->
<!-- <el-tag :draggable="true" @dragstart="onDragStart($event, 'circle',pid)" class="mx-1" size="large">圆形-->
<!-- </el-tag>-->
<!-- <h4>表单组件</h4>-->
<!-- <el-tag :draggable="true" @dragstart="onDragStart($event, 'text',pid,{name:'deviceName'})" class="mx-1"-->
<!-- size="large">-->
<!-- 设备名称-->
<!-- </el-tag>-->
<h4>表单组件</h4>
<el-tag :draggable="true" @dragstart="onDragStart($event, 'text',pid,{name:'PlanCode'})" class="mx-1"
size="large">
计划号
</el-tag>
<el-tag :draggable="true" @dragstart="onDragStart($event, 'text',pid,{name:'CardRecordCode'})" class="mx-1"
size="large">
卡片编号
</el-tag>
<el-tag :draggable="true" @dragstart="onDragStart($event, 'text',pid,{name:'ClassesName'})" class="mx-1"
size="large">
班次
</el-tag>
<el-tag :draggable="true" @dragstart="onDragStart($event, 'text',pid,{name:'TeamName'})" class="mx-1"
size="large">
班组
</el-tag>
<el-tag :draggable="true" @dragstart="onDragStart($event, 'text',pid,{name:'MaterialSpec'})" class="mx-1"
size="large">
物料规格
</el-tag>
<el-tag :draggable="true" @dragstart="onDragStart($event, 'text',pid,{name:'MachineName'})" class="mx-1"
size="large">
机台
</el-tag>
<el-tag :draggable="true" @dragstart="onDragStart($event, 'text',pid,{name:'ValidDate'})" class="mx-1"
size="large">
有效期/
</el-tag>
<el-tag :draggable="true" @dragstart="onDragStart($event, 'text',pid,{name:'ToolingCode'})" class="mx-1"
size="large">
工装编号
</el-tag>
<el-tag :draggable="true" @dragstart="onDragStart($event, 'text',pid,{name:'Width'})" class="mx-1"
size="large">
宽度/毫米
</el-tag>
<el-tag :draggable="true" @dragstart="onDragStart($event, 'text',pid,{name:'RealBeginTime'})" class="mx-1"
size="large">
开始时间
</el-tag>
<el-tag :draggable="true" @dragstart="onDragStart($event, 'text',pid,{name:'RealEndTime'})" class="mx-1"
size="large">
结束时间
</el-tag>
<el-tag :draggable="true" @dragstart="onDragStart($event, 'text',pid,{name:'CompleteAmount'})" class="mx-1"
size="large">
数量
</el-tag>
<el-tag :draggable="true" @dragstart="onDragStart($event, 'text',pid,{name:'Batch'})" class="mx-1"
size="large">
车次/批次
</el-tag>
<el-tag :draggable="true" @dragstart="onDragStart($event, 'text',pid,{name:'ContinueTime'})" class="mx-1"
size="large">
连续打印数
</el-tag>
<el-tag :draggable="true" @dragstart="onDragStart($event, 'text',pid,{name:'Remark'})" class="mx-1"
size="large">
备注
</el-tag>
<el-tag :draggable="true" @dragstart="onDragStart($event, 'text',pid,{name:'BarCode'})" class="mx-1"
size="large">
条形码
</el-tag>
<h4>选择框组件</h4>
<el-tag :draggable="true" @dragstart="onDragStart($event, 'select',pid,{name:'UserListSel',list:'UserList'})" class="mx-1"
size="large">
操作人
</el-tag>
<el-tag :draggable="true" @dragstart="onDragStart($event, 'select',pid,{name:'ResultListSel',list:'ResultList'})" class="mx-1"
size="large">
自检结果
</el-tag>
<el-tag :draggable="true" @dragstart="onDragStart($event, 'select',pid,{name:'UnitListSel',list:'UnitList'})" class="mx-1"
size="large">
单位
</el-tag>
<el-tag :draggable="true" @dragstart="onDragStart($event, 'select',pid,{name:'StationListSel',list:'StationList'})" class="mx-1"
size="large">
工位
</el-tag>
</div>
<div class="content" @drop="onDrop">
<div class="flowArea" :style="{width:zoom * cmToPx(pageWidth)+'px',height:zoom * cmToPx(pageHeight)+'px'}">

@ -6,7 +6,7 @@
v-if="!props.isView && !props.isHideHandle && props.selected" />
<div class="custom-node"
:style="{...border(),textAlign:props.data.options.align,width:props.dimensions.width+'px',lineHeight:props.dimensions.height+'px',height:props.dimensions.height+'px',pointerEvents:props.isView?'auto': 'none'}">
<el-input class="inputEl" v-model="text" style="width: 100%;height: 100%"
<el-input class="inputEl" v-model="text" style="width: 100%;height: 100%" @change="spanChange"
v-if="!props.isPrint" />
<div class="printDiv" :style="{justifyContent: props.data.options.verticalAlign || 'center'}"
v-if="props.isPrint">
@ -18,9 +18,9 @@
</div>
</template>
<script setup>
import { defineProps } from 'vue';
import { defineProps,defineEmits } from 'vue';
import { NodeResizer } from '@vue-flow/node-resizer';
const emit = defineEmits(['submit'])
const props = defineProps({
isView: {
type: Boolean,
@ -58,7 +58,7 @@ const props = defineProps({
const text = ref('');
const options = ref([]);
const spanChange = (val) => {
text.value = val;
emit('update', val)
};
watch(() => JSON.parse(JSON.stringify(props.data.options.default)), (obj1, obj2) => {
if (JSON.stringify(obj1) !== JSON.stringify(obj2)) {

@ -28,11 +28,12 @@
</div>
</template>
<script setup>
import { defineProps } from 'vue';
import { defineProps,defineEmits } from 'vue';
import { NodeResizer } from '@vue-flow/node-resizer';
import { listData } from '@/api/system/dict/data/index';
import request from '@/utils/request';
const emit = defineEmits(['submit'])
const props = defineProps({
isView: {
type: Boolean,
@ -102,6 +103,7 @@ const getEleData = async () => {
};
const spanChange = (val) => {
text.value = val;
emit('update', val)
};
onMounted(() => {
getEleData();

@ -12,8 +12,8 @@ const cmToPx = (cm) => {
};
const getOption = (e, name) => {
let commonOption = { field: name || '' };
const getOption = (e, option) => {
let commonOption = { field: option?.name || '' };
if (e === 'text') {
return {
...commonOption, horizontalAlign: 'center', default: '', isBold: false,
@ -52,7 +52,7 @@ const getOption = (e, name) => {
...commonOption, dic: '',
default: '',
JScript: '',
selectField:'',
selectField: option?.list || '',
selectOptions: [],
horizontalAlign: 'center',
verticalAlign: 'center',
@ -100,7 +100,7 @@ const getNodeSize = (e) => {
const tool = () => {
const nodeType = ref('');
const parentId = ref('');
const defaultName = ref('');
const defaultName = ref({});
const { addNodes, screenToFlowCoordinate, onNodesInitialized, updateNode } = useVueFlow();
const onDragStart = (event, type, pid, options) => {
if (event.dataTransfer) {
@ -110,7 +110,7 @@ const tool = () => {
nodeType.value = type;
parentId.value = pid;
defaultName.value = options?.name;
defaultName.value = options || {};
document.addEventListener('drop', onDragEnd);
};
const onDragEnd = () => {

Loading…
Cancel
Save