前言
vue3+vue-flow实现拖拽矩形框,端点连线,自定义宽高
一、下载插件
"@vue-flow/background": "^1.3.2",
"@vue-flow/controls": "^1.1.2",
"@vue-flow/core": "^1.42.4",
"@vue-flow/minimap": "^1.5.2",
"@vue-flow/node-resizer": "^1.4.0",
二、直接上代码
1.taskDetail.vue
代码如下(示例):
<template>
<div class="app-container" style="height: calc(100vh - 100px)">
<div class="taskcard-box">
<el-card class="left-box" shadow="never">
<!-- <TaskFlow ref="taskFlowRef" v-bind="taskFlowParams" /> -->
<TaskFlow ref="taskFlowRef" :detailInfo="taskFlowParams" :key="1" v-model:unusedPort="unusedPort" />
</el-card>
<el-card class="right-box custom_right_box" shadow="never">
<el-tabs type="border-card" class="demo-tabs">
<el-tab-pane label="设置">
<el-space direction="vertical">
<el-form ref="formRef" :model="form" :rules="rules" label-width="auto">
<el-form-item label="所属项目:">
<!-- <SpProjectSelect v-model="project.id" url="/project/listPage" method="post" disabled /> -->
</el-form-item>
<el-form-item label="任务名称:" prop="taskName">
<el-input v-model="form.taskName" placeholder="请输入任务名称" />
</el-form-item>
<el-form-item label="宽度:">
<el-input-number v-model="taskFlowParams.width" :min="800" :max="100000" />
</el-form-item>
<el-form-item label="高度:">
<el-input-number v-model="taskFlowParams.height" :min="800" :max="100000" />
</el-form-item>
<el-form-item label="时间间隔(ms):" prop="taskInterval">
<el-input-number v-model="form.taskInterval" :min="1" :max="10000000" />
</el-form-item>
<el-form-item label="任务周期:" prop="taskType">
<sp-select-dict v-model="form.taskType" dictType="task-type" />
</el-form-item>
<el-form-item label="状态:" prop="taskStatus">
<el-switch size="large" v-model="form.taskStatus" active-value="0" inactive-value="1" inline-prompt active-text="启用" inactive-text="禁用" />
</el-form-item>
</el-form>
</el-space>
</el-tab-pane>
<el-tab-pane label="组件">
<ComponentTree />
</el-tab-pane>
</el-tabs>
<div class="btn-box">
<el-button @click="back">返回</el-button>
<el-button type="primary" @click="save">保存</el-button>
</div>
</el-card>
</div>
</div>
</template>
<script setup>
import TaskFlow from "@/views/comChunk/leftContent.vue";
import ComponentTree from "@/components/componentTree/ComponentTree.vue";
import { addTaskApi, taskUpdateByIdApi, getTaskDetailByIdApi } from "@/api/flow";
import { ElMessage ,ElLoading} from "element-plus";
const route = useRoute();
const router = useRouter();
const taskFlowRef = ref();
const formRef= ref()
onMounted(() => {
if (route.query.id) {
form.value.id = route.query.id;
getDetail();
}
});
const data = reactive({
form: {
id: null,
configJson: {
height: 600,
width: 1200,
},
taskStatus: "0",
taskType: "",
taskJson: {},
taskName: "",
taskInterval: null,
},
taskFlowParams: {
data: {},
width: 1200,
height: 600,
background: {
color: "#fffbe6", // 设置画布背景颜色
},
grid: {
size: 10, // 网格大小 10px
visible: true, // 渲染网格背景
},
},
rules: {
taskName: [{ required: true, message: "任务名称不能为空", trigger: "blur" }],
taskType: [{ required: true, message: "任务类型不能为空", trigger: "blur" }],
taskInterval: [
{
required: true,
type: "number",
message: "时间间隔不能为空",
trigger: "blur",
},
],
},
unusedPort: [],
});
const { form, taskFlowParams, rules, unusedPort } = toRefs(data);
const getDetail = async () => {
const res = await getTaskDetailByIdApi({ id: form.value.id });
if (res.code == 200 && res.data) {
form.value = {...form.value ,...res.data };
const edgesData = res.data?.taskJson?.cells.filter((item) => item.shape === "edge");
const nodesData = res.data?.taskJson?.cells.filter((item) => item.shape !== "edge");
await nextTick(() => {
nodesData.forEach((item) => taskFlowRef.value?.addNodesToFlow(item));
taskFlowRef.value?.addEdgesToFlow(edgesData);
});
// 确保 taskFlowParams 变化不会导致递归
taskFlowParams.value = { ...taskFlowParams.value, width: res.data.configJson.width, height: res.data.configJson.height };
}
};
/* 保存 */
let loading = ref(null);
const save = async () => {
formRef.value?.validate(async (valid) => {
if (!valid) return;
loading.value = ElLoading.service({
text: "Loading",
background: "rgba(0, 0, 0, 0.7)",
});
try {
let data = {
...form.value,
id: form.value?.id ? form.value.id : undefined,
};
let nodesData = taskFlowRef.value?.nodes;
let edgesData = taskFlowRef.value?.edges;
data.taskJson = await processModuleJson(nodesData, edgesData);
data.configJson = {
height: taskFlowParams.height || 600,
width: taskFlowParams.width || 1200,
};
// data.imageUrl = "";
console.log("form.value", form.value);
console.log("data", data);
console.log("data", data.id);
const res = !data.id ? await addTaskApi({ ...data }) : await taskUpdateByIdApi({ ...data });
console.log(res);
if (res.code == 200) {
ElMessage({
type: "success",
message: data.id ? "修改成功" : "添加成功",
});
router.back()
}
} finally {
loading.value.close();
}
});
};
/* 处理moduleJson数据 */
const processModuleJson = (nodesData, edgesData) => {
let nodeArr = nodesData.map((item) => {
// console.log(item);
let ports = {};
if (item.data.ports?.items && item.data.ports?.items.length > 0) {
ports = item.data.ports;
} else {
ports = {
groups: {
in: {
position: { name: "left" },
}, // 你可以自定义 `in` 端口组的属性
out: {
lable: { position: { name: "right" } },
position: { name: "right" },
}, // 你可以自定义 `out` 端口组的属性
},
items: item.data.ports || [], // 这里存放原来的 ports 数组
};
}
let tools = {};
if (item.data.tools?.items && item.data.tools?.items.length > 0) {
tools = item.data.tools;
} else {
tools = {
items: item.data.tools,
};
}
return {
// ...item,
portMarkup: [],
router: {},
size: {},
...item.data,
shape: "rect",
componentId: item.data.componentId,
id: item.id,
ports: ports,
tools: tools,
position: item.position,
width: item.dimensions.width,
height: item.dimensions.height,
};
});
let edgeArr = edgesData.map((item) => {
return {
...item,
shape: "edge",
source: {
cell: item.source,
port: item.sourceHandle,
},
target: {
cell: item.target,
port: item.targetHandle,
},
};
});
// form.value.moduleJson = {
// cells: [...nodesData, ...edgesData],
// };
return { cells: [...nodeArr, ...edgeArr] };
};
const back = ()=>{
router.back()
}
</script>
<style lang="scss" scoped>
.taskcard-box {
display: flex;
justify-content: space-between;
align-items: flex-start;
width: 100%;
height: 100%;
}
.right-box {
width: 350px;
height: 100%;
}
.left-box {
flex: 1;
max-height: calc(100vh - 100px);
overflow: auto;
margin-right: 10px;
}
.btn-box {
display: flex;
justify-content: flex-end;
align-items: center;
margin-top: 10px;
}
.demo-tabs {
max-height: calc(100vh - 180px);
overflow: scroll;
}
</style>
2.读入数据
代码如下(示例):
data = pd.read_csv(
'https://labfile.oss.aliyuncs.com/courses/1283/adult.data.csv')
print(data.head())
该处使用的url网络请求的数据。
总结
提示:这里对文章进行总结:
例如:以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。