提交预览x6

This commit is contained in:
limengnan 2026-01-17 14:59:23 +08:00
parent b1577e324a
commit 41fb70bb78
5 changed files with 370 additions and 383 deletions

View File

@ -3,7 +3,7 @@ import request from '@/utils/request';
//获取所有项目列表
export function searchAlgorithmsPage(queryParams:any){
return request({
url: '/api/algorithms/search' ,
url: '/algorithms/search' ,
method: 'get',
params:queryParams
});
@ -15,7 +15,7 @@ export function searchAlgorithmsPage(queryParams:any){
//新增项目
export function addAlgorithms(data:any){
return request({
url:'/api/algorithms' ,
url:'/algorithms' ,
method: 'Post',
data: data
});
@ -25,7 +25,7 @@ export function addAlgorithms(data:any){
//更新项目信息
export function updateAlgorithms (queryParams:any){
return request({
url:'/api/algorithms' ,
url:'/algorithms' ,
method: 'PUT',
data: queryParams
});
@ -35,7 +35,7 @@ export function updateAlgorithms (queryParams:any){
//单个删除项目
export function deleteAlgorithms (queryParams:any){
return request({
url:'/api/algorithms/'+queryParams.id ,
url:'/algorithms/'+queryParams.id ,
method: 'delete'
// params: queryParams
});
@ -43,7 +43,7 @@ export function deleteAlgorithms (queryParams:any){
//多选删除项目
export function deleteBatchAlgorithms (queryParams:any){
return request({
url:'/api/algorithms',
url:'/algorithms',
method: 'delete',
data: queryParams
});

Binary file not shown.

After

Width:  |  Height:  |  Size: 423 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 457 B

View File

@ -0,0 +1,129 @@
<script lang="ts">
export default {
name: "x6查看结果数据",
};
</script>
<script setup lang="ts">
import { onMounted, ref, nextTick } from "vue";
import { ElForm, ElMessage, ElMessageBox } from "element-plus";
import { getByScenario } from "@/api/business/scenario";
const emit = defineEmits([ 'closeEditdevice']);
const props = defineProps({
deviceId: {
required: false,
type: String,
default: ''
},
scenarioId: {
required: false,
type: String,
default: ''
},
})
const scenarioResultData:any = ref([])
function getScenarioResults(){
scenarioResultData.value = []
getByScenario({
scenarioId: props.scenarioId,
deviceId: props.deviceId,
pageNum:1,
pageSize:999
}).then((res:any) => {
scenarioResultData.value = res.data.records
})
}
onMounted(() => {
getScenarioResults()
});
</script>
<template>
<div class="editdevice-box">
</div>
</template>
<style scoped>
.editdevice-box{
width: 100%;
height: calc(100vh - 200px);
}
.editdevice_navigation_left{
width: 110px;
height: 32px;
line-height: 32px;
text-align: center;
cursor: pointer;
font-family: 'Arial Normal', 'Arial';
font-weight: 400;
font-style: normal;
font-size: 14px;
color: #363636;
background-image: url('@/assets/x6/navleft.png');
}
.editdevice_navigation_left:hover{
color: #266fff ;
}
.editdevice_navigation_activeleft{
background-image: url('@/assets/x6/navleft_active.png');
color: #fff !important;
}
.editdevice_navigation_right{
width: 110px;
height: 32px;
line-height: 32px;
text-align: center;
cursor: pointer;
font-family: 'Arial Normal', 'Arial';
font-weight: 400;
font-style: normal;
font-size: 14px;
color: #363636;
background-image: url('@/assets/x6/navright.png');
}
.editdevice_navigation_right:hover{
color: #266fff ;
}
.editdevice_navigation_activeright{
background-image: url('@/assets/x6/navright_active.png');
color: #fff !important;
}
</style>
<style>
.el-table .el-table--enable-row-hover .el-table__body tr:hover > td{
background-color: #194764 !important;
}
.editdevice-box .el-table .el-table__row.current-row td{
background-color: #f3faff !important;
border-top:1px solid #14aaff;
border-bottom:1px solid #14aaff
}
.editdevice-box .el-table .el-table__row.current-row td:last-child{
border-right:1px solid #14aaff;
}
.editdevice-box .el-table .el-table__row.current-row td:first-child{
border-left:1px solid #14aaff;
}
.editdevice-box .el-table .el-table__row.current-row:last-child td{
border-bottom:1px solid #14aaff
}
.el-table__inner-wrapper:before{
background-color: transparent !important;
border-top: 1px solid var(--el-table-border-color);
}
.el-table--border:before{
background-color: transparent !important;
border-top: 1px solid var(--el-table-border-color);
}
</style>

View File

@ -18,12 +18,13 @@ import {
import { updateProjects,projectsById} from "@/api/business/project";
import { getByScenario } from "@/api/business/scenario";
import textimg from '@/assets/x6/text.png'
import chartsimg from '@/assets/x6/charts.png'
import Createscenario from '@/views/component/scenario/createscenario.vue'
import ScenarioModel from '@/views/component/scenario/index.vue'
import AdddeviceModel from './adddevice.vue';
import TableModels from './tableModel.vue';
import EditdeviceModel from './editdevice.vue';
import MaterialModels from './materialmodel.vue';
import ChangesettingsModels from './changesettings.vue';
@ -41,15 +42,18 @@ const props = defineProps({
const deviceTypetype:any = ref('') //
const isAdddevice = ref(false) //
const isEditdevice = ref(false) //
const isMaterialModel = ref(false) //
const projectInfo:any = ref({}) //
const isScenario = ref(false) //
const isDisplay = ref(true) //
const isExpansionandcontraction = ref(false) //
const scenarioResults:any = ref({}) //
const deviceId = ref('') // id
const customImageData:any = ref([]) //
//
let graph: Graph
const scenarioId:any = ref('') // id
function getScenarioResults(){
scenarioResults.value = {}
getByScenario({
scenarioId: scenarioId.value,
pageNum:1,
@ -57,9 +61,107 @@ function getScenarioResults(){
}).then((res:any) => {
console.log(res.data.records)
res.data.records
scenarioResults.value = groupByDeviceId(res.data.records)
for (const key in scenarioResults.value) {
if (!Object.hasOwn(scenarioResults.value, key)) continue;
const element = scenarioResults.value[key];
for(let i = 0;i<customImageData.value.length;i++){
if(key == customImageData.value[i].id){
customImageData.value[i].scenarioResults = element
console.log(customImageData.value[i])
addAttrText(customImageData.value[i])
}
}
}
})
}
function addAttrText(item:any){
item.attrs.text = item.deviceName
graph.addNode({
x: item.position.x ,
y: item.position.y + 160,
width: 100,
height: 30,
label: 'keff' + item.scenarioResults[item.scenarioResults.length - 1].keffValue,
attrs: {
body: {
stroke: 'transparent',
fill: 'transparent',
strokeWidth: 1,
},
text: {
text: '',
fill: item.scenarioResults[item.scenarioResults.length - 1].keffValue > 0.98 ? '#ff4d4f' : '#363636', //
fontSize: 14,
},
},
})
graph.addNode({
shape: 'image-node',
x: item.position.x + 135 ,
y: item.position.y + 167,
width: 14,
height: 14,
correlationId: item.id,
type:'charts',
attrs: {
img: {
width: 14,
height: 14,
'xlink:href': chartsimg,
},
label: {
text: '',
},
},
})
graph.addNode({
shape: 'image-node',
x: item.position.x + 110 ,
y: item.position.y + 167,
width: 14,
height: 14,
correlationId: item.id,
type:'text',
attrs: {
img: {
width: 14,
height: 14,
'xlink:href': textimg,
},
label: {
text: '',
},
},
})
}
function groupByDeviceId(data:any) { // id
//
if (!Array.isArray(data)) {
throw new Error('输入必须是数组类型');
}
return data.reduce((acc, item) => {
// deviceId
const key = item.deviceId;
if (!key) {
console.warn('跳过无deviceId的元素:', item);
return acc;
}
// deviceId
if (!acc[key]) {
acc[key] = [];
}
//
acc[key].push(item);
return acc;
}, {}); //
}
onMounted(() => {
scenarioId.value = route.query.scenarioId
// #region
@ -251,16 +353,116 @@ onMounted(() => {
},
true,
)
Graph.registerNode(
'image-node',
{
inherit: 'rect',
width: 120,
height: 60,
markup: [
{
tagName: 'rect',
selector: 'body',
},
{
tagName: 'image',
selector: 'img',
},
{
tagName: 'text',
selector: 'label',
},
],
attrs: {
body: {
stroke: 'transparent',
strokeWidth: 1,
fill: 'transparent',
rx: 6,
ry: 6,
},
img: {
'xlink:href': 'https://gw.alipayobjects.com/zos/antfincdn/FLrTNDvlna/antv.png',
width: 24,
height: 24,
x: 0,
y: 0,
},
label: {
text: 'Image Node',
fill: '#333',
fontSize: 12,
refX: 0.5,
refY: 0.5,
textAnchor: 'middle',
dy: 10,
},
},
},
true,
)
// Graph.registerNode(
// 'image-charts',
// {
// inherit: 'rect',
// width: 120,
// height: 60,
// markup: [
// {
// tagName: 'rect',
// selector: 'body',
// },
// {
// tagName: 'image',
// selector: 'img',
// },
// {
// tagName: 'text',
// selector: 'label',
// },
// ],
// attrs: {
// body: {
// stroke: 'transparent',
// strokeWidth: 1,
// fill: 'transparent',
// rx: 6,
// ry: 6,
// },
// img: {
// 'xlink:href': 'https://gw.alipayobjects.com/zos/antfincdn/FLrTNDvlna/antv.png',
// width: 24,
// height: 24,
// x: 0,
// y: 0,
// },
// label: {
// text: 'Image Node',
// fill: '#333',
// fontSize: 12,
// refX: 0.5,
// refY: 0.5,
// textAnchor: 'middle',
// dy: 10,
// },
// },
// },
// true,
// )
projectsById({projectId:route.query.projectId}).then((res:any) => {
if(res.topology != null && res.topology != ''){
projectInfo.value = res
if (!graph || !projectInfo.value || !projectInfo.value.topology) return;
graph.clearCells();
const topology:any = JSON.parse(projectInfo.value.topology)
customImageData.value = []
if(!topology.designData)return
// shape
// const validCells = Array.isArray(topology.designData) ? topology.designData.filter(cell => cell.shape) : []
//
for(let i = 0;i<topology.designData.length;i++){
if(topology.designData[i].shape == 'custom-image'){
customImageData.value.push(topology.designData[i])
}
}
graph.fromJSON(topology.designData);
getScenarioResults()
}
@ -294,98 +496,20 @@ onMounted(() => {
// #endregion
graph.on('node:contextmenu', ({ e, node }) => {
selectedNode.value = node
e.preventDefault()
//
const pos = node.position?.() || { x: 0, y: 0 }
showContextMenu(pos.x, pos.y)
})
function showContextMenu(x: number, y: number) {
left.value = x + 260
top.value = y - 50
graph.on('node:click', ({ e, node }) => {
if(node?.store?.data?.type == 'charts'){
deviceId.value = node?.store?.data?.correlationId
isMenuShow.value = true
//
//
return
}
if(node?.store?.data?.type == 'text'){
deviceId.value = node?.store?.data?.correlationId
isTableModel.value = true
return
}
})
// Graph
// graph.on('node:added', (args:any) => {
// console.log('', args)
// const { node } = args
// // 线
// if (node.data && node.data.lineStyle) {
// // 线线
// const lineStyle = node.data.lineStyle
// graph.options.connecting.createEdge = () => {
// return new Shape.Edge({
// attrs: {
// line: {
// stroke: '#A2B1C3',
// strokeWidth: 2,
// strokeDasharray: lineStyle.strokeDasharray,
// targetMarker: lineStyle.targetMarker,
// sourceMarker: lineStyle.sourceMarker
// }
// },
// zIndex: 0
// })
// }
// // 线
// setTimeout(() => {
// graph.removeNode(node)
// }, 100)
// } else {
// if(node.store && node.store.data && node.store.data.shape === 'rect'){
// return
// }
// nodeId.value = node.id
// if(node.store.data.attrs.text.text == ''){
// deviceTypetype.value = 'FlatTank'
// }else if(node.store.data.attrs.text.text == ''){
// deviceTypetype.value = 'CylindricalTank'
// }else if(node.store.data.attrs.text.text == ''){
// deviceTypetype.value = 'AnnularTank'
// }else if(node.store.data.attrs.text.text == ''){
// deviceTypetype.value = 'TubeBundleTank'
// }else if(node.store.data.attrs.text.text == ''){
// deviceTypetype.value = 'ExtractionColumn'
// }else if(node.store.data.attrs.text.text == ''){
// deviceTypetype.value = 'FluidizedBed'
// }else if(node.store.data.attrs.text.text == ''){
// deviceTypetype.value = 'ACFTank'
// }
// //
// node.size(160, 160)
// //
// node.attr('body/fill', 'none')
// //
// node.attr('image/refX', 0)
// node.attr('image/refY', 0)
// node.attr('image/width', 160) //
// node.attr('image/height', 160) //
// //
// node.attr('text/text', '')
// node.attr('label/text', '')
// isAdddevice.value = true
// }
// })
// #endregion
// #endregion
})
@ -393,39 +517,11 @@ const left = ref(0)
const top = ref(0)
const isMenuShow = ref(false)
const selectedNode:any = ref(null)
function deleteNode() { //
graph.removeNode(selectedNode.value)
isMenuShow.value = false
}
function copyNode() { //
if (selectedNode.value) {
try {
//
const position = selectedNode.value.position()
// 使
const newNode = selectedNode.value.clone()
// 50px
newNode.position(position.x + 50, position.y + 50)
//
graph.addNode(newNode)
isMenuShow.value = false
} catch (error) {
console.error('节点复制失败:', error)
}
}
}
function closeAntvx6() {
router.push('/business/project/index')
}
function revokeClick(){
graph.undo()
}
function removeClick(){
graph.clearCells();
}
function bigClick(){
graph.zoom(0.1)
}
@ -433,257 +529,16 @@ function smallClick(){
graph.zoom(-0.1)
}
const nodeId = ref("")
const isTableModel = ref(false)
function dialogTableModel(){ //
isTableModel.value = false;
}
function analysisAdd(){
dialogVisible.value = true;
}
const dialogVisible = ref(false)
function closeCreatescenario(){ //
dialogVisible.value = false;
}
function simulationClick() { //
isScenario.value = true;
}
//
function handleClose() {
isScenario.value = false;
}
function dialogAdddevice(){ //
graph.undo()
isAdddevice.value = false;
}
const selectedDevice = ref({})
function closeAdddevice(e:any){ //
selectedDevice.value = e
let retrievedNode:any = graph.getCellById(nodeId.value)
retrievedNode.store.data.deviceInfo = e
isAdddevice.value = false;
}
const deviceInfo:any = ref({}) //
function EditdeviceClick(){ //
deviceInfo.value = selectedNode.value.store.data.deviceInfo
nodeId.value = selectedNode.value.id
if(deviceInfo.value != null){
deviceTypetype.value = deviceInfo.value.type
}
isEditdevice.value = true;
}
function closeEditdevice(e:any){ //
selectedDevice.value = e
let retrievedNode:any = graph.getCellById(nodeId.value)
retrievedNode.store.data.deviceInfo = e
isEditdevice.value = false;
}
function dialogEditdevice(){ //
isEditdevice.value = false;
}
const materialInfo:any = ref({}) //
const selectedMaterial:any = ref({})
function MaterialModelClick(){ //
deviceInfo.value = selectedNode.value.store.data.deviceInfo
materialInfo.value = {}
if(selectedNode.value.store.data.materialInfo != null){
materialInfo.value = selectedNode.value.store.data.materialInfo
}
nodeId.value = selectedNode.value.id
if(materialInfo.value != null){
deviceTypetype.value = materialInfo.value.type
}
isMaterialModel.value = true;
}
function dialogMaterialModel(){ //
isMaterialModel.value = false;
}
function closeMaterialModel(e:any){ //
if(e == false){
isMaterialModel.value = false;
return
}
selectedMaterial.value = e
let retrievedNode:any = graph.getCellById(nodeId.value)
retrievedNode.store.data.materialInfo = e
isMaterialModel.value = false;
}
const isChangesettings = ref(false)
const changesettingsData:any = ref([]) //
function dialogChangesettings(){ //
isChangesettings.value = false;
}
function ChangesettingsClick(){ //
changesettingsData.value = []
if(selectedNode.value.store.data.deviceInfo == null){
ElMessage({
type: "error",
message: "请先添加设备信息",
});
return
}
if(selectedNode.value.store.data.materialInfo == null){
ElMessage({
type: "error",
message: "请先添加物料信息",
});
return
}
deviceInfo.value = selectedNode.value.store.data.deviceInfo
materialInfo.value = selectedNode.value.store.data.materialInfo
if(selectedNode.value.store.data.changesettings != null){
changesettingsData.value = selectedNode.value.store.data.changesettings
}
nodeId.value = selectedNode.value.id
if(materialInfo.value != null){
deviceTypetype.value = materialInfo.value.type
}
isChangesettings.value = true;
}
function closeChangesettingsModel(e:any){ //
if(e == false){
isChangesettings.value = false;
return
}
selectedMaterial.value = e
let retrievedNode:any = graph.getCellById(nodeId.value)
retrievedNode.store.data.changesettings = e
isChangesettings.value = false;
}
function setFormulaInit(formula:any) {
// const formula = "(B)*0.2+(A)*1.0+0.5";
// *+)
const regex = /\*(\d+\.?\d*)/g;
const coefficients = [];
let match;
//
while ((match = regex.exec(formula)) !== null) {
coefficients.push(parseFloat(match[1])); //
}
console.log(coefficients); // : [0.2, 1.0]
return coefficients
}
function getBias(formula:any){
// +
// +
const regex = /\+(\d+\.?\d*)$/;
const match = formula.match(regex);
const constant = parseFloat(match[1]);
return constant
}
function saveDesign() { //
try {
// JSON
const designData:any = graph.toJSON()
let cells:any = []
if(designData !=null && designData.cells.length>0){
cells = designData.cells
}
let devices = []
for(let i=0;i<cells.length;i++){
if(cells[i].shape == 'custom-image'){
let tempData:any = {}
if(cells[i].changesettings && cells[i].changesettings.length > 0){
for(let j=0;j<cells[i].changesettings.length;j++){
if(cells[i].changesettings[j].formula != '' && cells[i].changesettings[j].formula != null){
const key = cells[i].changesettings[j].name as string
const unit = cells[i].changesettings[j].unit
const name = cells[i].changesettings[j].name
const delay= cells[i].changesettings[j].delay
let tempSources = []
for(let k=0;k<setFormulaInit(cells[i].changesettings[j].formula).length;k++){
tempSources.push({
entityType: 'material', //B
entityId: cells[i].materialInfo.materialId , //materialId : cdeeca2e-1e0c-4bdd-b946-f347c104752c
property: name, // g/L
coefficient: setFormulaInit(cells[i].changesettings[j].formula)[k], //0.2
delay: { enabled: true, time: delay, unit: 's' } // 5
})
}
tempData[key] = {
name: tempData[key],
type:'influence',
unit:unit,
base:0,
bias: getBias(cells[i].changesettings[j].formula) || 0,
sources:tempSources,
expression:cells[i].changesettings[j].formula
}
}
}
}
devices.push({
deviceId:cells[i].id,
name:cells[i].deviceInfo.name,
type:cells[i].deviceInfo.type,
properties:{},
material: cells[i].materialInfo != null ? {
materialId:cells[i].id,
name:cells[i].materialInfo.name,
properties:tempData
}:{}
})
}
}
const topology = {
projectId: projectInfo.value.projectId,
name: projectInfo.value.name,
devices:devices,
pipelines:[],
systemboundaries:[],
globalDisplay:{
device:{
showProperties:[]
},
material:{
showProperties:[]
},
},
designData:cells
}
console.log(topology)
//
const saveData = {
projectId: projectInfo.value.projectId,
topology: JSON.stringify(topology)
}
updateProjects(saveData).then((res:any) => {
if(res === true){
ElMessage({
type: "success",
message: "保存成功",
});
}
});
//
return saveData
} catch (error) {
console.error('保存设计失败:', error)
return null
}
}
</script>
<template>
@ -720,12 +575,12 @@ function saveDesign() { // 保存设计
</div>
<div id="graph-container" style="width: 100%; height: calc(100% - 60px);">
<div class="context-menu" v-if="isMenuShow" :style="{left: left +'px', top: top+'px'}">
<img src="@/assets/x6/info.png" alt="图标" title="设备信息" style="cursor: pointer;" @click="EditdeviceClick">
<!-- <img src="@/assets/x6/info.png" alt="图标" title="设备信息" style="cursor: pointer;" @click="EditdeviceClick">
<img src="@/assets/x6/material.png" alt="图标" title="物料信息" style="cursor: pointer;" @click="MaterialModelClick">
<img src="@/assets/x6/change.png" alt="图标" title="变动设置" style="cursor: pointer;" @click="ChangesettingsClick">
<img src="@/assets/x6/copy.png" alt="图标" title="复制" style="cursor: pointer;" @click="copyNode">
<img src="@/assets/x6/del.png" alt="图标" title="删除" style="cursor: pointer;"
@click="deleteNode">
@click="deleteNode"> -->
</div>
<div class="line-style-box">
<div class="expansionandcontraction-box" v-if="isExpansionandcontraction == false" @click="isExpansionandcontraction = true">
@ -742,6 +597,9 @@ function saveDesign() { // 保存设计
</div>
</div>
<el-dialog v-model="isTableModel" :close-on-click-modal="false" :modal="false" draggable :before-close="dialogTableModel" title="设备分析列表" append-to-body width="1430px">
<TableModels v-id="isTableModel" :deviceId="deviceId" :scenarioId="scenarioId"/>
</el-dialog>
</div>
</template>