xyc
2024-08-02 7abc95a191d2c1a9bb9ff8fd7fb05470a0d4e86b
Merge remote-tracking branch 'origin/master'

# Conflicts:
# modules/mainPart/src/main/java/com/zt/life/modules/mainPart/taskReliability/service/SimulatAssessService.java
21个文件已修改
7个文件已添加
2个文件已删除
5328 ■■■■■ 已修改文件
modules/mainPart/src/main/java/com/zt/life/modules/mainPart/basicInfo/controller/XhProductModelController.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
modules/mainPart/src/main/java/com/zt/life/modules/mainPart/basicInfo/service/XhProductModelService.java 18 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
modules/mainPart/src/main/java/com/zt/life/modules/mainPart/taskReliability/controller/SimulatAssessController.java 84 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
modules/mainPart/src/main/java/com/zt/life/modules/mainPart/taskReliability/dao/SimulatAssessDao.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
modules/mainPart/src/main/java/com/zt/life/modules/mainPart/taskReliability/dao/TimeDiagramDao.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
modules/mainPart/src/main/java/com/zt/life/modules/mainPart/taskReliability/dto/ModelDto.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
modules/mainPart/src/main/java/com/zt/life/modules/mainPart/taskReliability/model/SimulatAssess.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
modules/mainPart/src/main/java/com/zt/life/modules/mainPart/taskReliability/model/SimulatAssessTaskPhaseModel.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
modules/mainPart/src/main/java/com/zt/life/modules/mainPart/taskReliability/model/TimeDiagram.java 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
modules/mainPart/src/main/java/com/zt/life/modules/mainPart/taskReliability/service/SimulatAssessService.java 532 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
modules/mainPart/src/main/resources/mapper/taskReliability/SimulatAssessDao.xml 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
modules/mainPart/src/main/resources/mapper/taskReliability/TimeDiagram.xml 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
web/src/views/layout/main-content.vue 32 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
web/src/views/modules/baseReliability/ParamDataBasic.vue 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
web/src/views/modules/basicInfo/ParamData.vue 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
web/src/views/modules/basicInfo/ProductModelTree.vue 25 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
web/src/views/modules/basicInfo/XhProductModel-AddOrUpdate.vue 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
web/src/views/modules/basicInfo/XhProductModel.vue 15 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
web/src/views/modules/taskReliability/ConfigNode/tempNode.vue 256 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
web/src/views/modules/taskReliability/ModelLine-AddOrUpdate.vue 65 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
web/src/views/modules/taskReliability/ModelLine.vue 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
web/src/views/modules/taskReliability/ModelRbd.vue 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
web/src/views/modules/taskReliability/ModelView.vue 2009 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
web/src/views/modules/taskReliability/OperatConditModel.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
web/src/views/modules/taskReliability/SimulatAssess.vue 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
web/src/views/modules/taskReliability/SimulatCurve.vue 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
web/src/views/modules/taskReliability/SimulatHistory.vue 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
web/src/views/modules/taskReliability/TimeDiagram.vue 789 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
web/src/views/modules/taskReliability/TimeDiagramTemp.vue 1207 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zt/common/src/main/java/com/zt/common/utils/JsonUtils2.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
modules/mainPart/src/main/java/com/zt/life/modules/mainPart/basicInfo/controller/XhProductModelController.java
@@ -63,8 +63,8 @@
    }
    @GetMapping("tree")
    public Result<List<XhProductModel>> getTreeList(Boolean showXdy, Integer ztShow) {
        List<XhProductModel> list = xhProductModelService.getAllTree(showXdy, ztShow);
    public Result<List<XhProductModel>> getTreeList(Boolean showXdy, Integer ztShow,Long productId) {
        List<XhProductModel> list = xhProductModelService.getAllTree(showXdy, ztShow,productId);
        return Result.ok(list);
    }
modules/mainPart/src/main/java/com/zt/life/modules/mainPart/basicInfo/service/XhProductModelService.java
@@ -61,12 +61,18 @@
        super.deleteLogic(ids);
    }
    public List<XhProductModel> getAllTree(Boolean showXdy, Integer ztShow) {
    public List<XhProductModel> getAllTree(Boolean showXdy, Integer ztShow, Long productId) {
        List<XhProductModel> productList = null;
        if (showXdy) {
            if (productId != null) {
                productList = baseDao.selectList(new QueryWrapper<XhProductModel>().eq(Constant.TableColumn.IS_DELETE,
                        Constant.Bool.NO).ne("product_type", 5).and(wrapper -> wrapper.eq("ship_id", productId).or().eq("id", productId)).orderByAsc(Constant.TableColumn.SORT));
            } else {
            productList = baseDao.selectList(new QueryWrapper<XhProductModel>().eq(Constant.TableColumn.IS_DELETE,
                    Constant.Bool.NO).ne("product_type", 5).orderByAsc(Constant.TableColumn.SORT));
            }
        } else {
            if (productId == null) {
            if (ztShow == 1) {
                productList = baseDao.selectList(new QueryWrapper<XhProductModel>().eq(Constant.TableColumn.IS_DELETE,
                        Constant.Bool.NO).lt("product_type", 5).ne("product_type", 10).orderByAsc(Constant.TableColumn.SORT));
@@ -83,7 +89,15 @@
                productList = baseDao.selectList(new QueryWrapper<XhProductModel>().eq(Constant.TableColumn.IS_DELETE,
                        Constant.Bool.NO).gt("product_type", 1).orderByAsc(Constant.TableColumn.SORT));
            }
            } else {
                if (ztShow == 4) {
                    productList = baseDao.selectList(new QueryWrapper<XhProductModel>().eq(Constant.TableColumn.IS_DELETE,
                            Constant.Bool.NO).lt("product_type", 5).ne("product_type", 1).and(wrapper -> wrapper.eq("ship_id", productId).or().eq("id", productId)).orderByAsc(Constant.TableColumn.SORT));
                } else if (ztShow == 5) {
                    productList = baseDao.selectList(new QueryWrapper<XhProductModel>().eq(Constant.TableColumn.IS_DELETE,
                            Constant.Bool.NO).gt("product_type", 1).and(wrapper -> wrapper.eq("ship_id", productId).or().eq("id", productId)).orderByAsc(Constant.TableColumn.SORT));
                }
            }
        }
        return TreeUtils.build(productList);
    }
modules/mainPart/src/main/java/com/zt/life/modules/mainPart/taskReliability/controller/SimulatAssessController.java
@@ -18,11 +18,13 @@
import com.zt.life.modules.mainPart.taskReliability.model.CurveParam;
import com.zt.life.modules.mainPart.taskReliability.model.SimulatAssess;
import com.zt.life.modules.mainPart.taskReliability.model.Task;
import com.zt.life.modules.mainPart.taskReliability.model.TimeDiagram;
import com.zt.life.modules.mainPart.taskReliability.service.SimulatAssessService;
import com.zt.life.modules.mainPart.taskReliability.service.TaskService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@@ -52,7 +54,6 @@
public class SimulatAssessController {
    private static final Logger logger = LoggerFactory.getLogger(SimulatAssessController.class);
    private static final String taskTypeProgress = "calcprog";
    private List<Map<String, Double>> dialgram = new ArrayList<>();
    @Autowired
    private RedisTemplate redisTemplate;
@@ -62,16 +63,15 @@
    @Autowired
    private TaskService taskService;
    @Value("${data.reliaSimLib.resultHome}")
    private String path;
    @Autowired
    private SimulatAssessService simulatAssessService;
    private JSONObject xmlJSONObj;
    private JSONObject dialgramJson;
   /* @GetMapping("page")
    @ApiOperation("分页")
@@ -149,7 +149,7 @@
    public SimulaDataDto getResultData(SimulatAssess simulatAssess) {
        SimulaDataDto data = new SimulaDataDto();
        CurveParam param = new CurveParam();
        Double samplPeriod = simulatAssess.getSamplPeriod().doubleValue();
        Double samplPeriod = Double.valueOf(simulatAssess.getSamplPeriod());
        Task task = taskService.get(simulatAssess.getTaskModelId());
        samplPeriod = samplPeriod / 60;
        List<Double> xList = new ArrayList<>();
@@ -191,62 +191,33 @@
    }
    @GetMapping("getStatus")
    public Result<List<ProductStatusDto>> getStatus(Long productId, Long taskId, Long fzId) {
        String filePath = path + "/" + fzId + "/" + "status.json";
        ObjectMapper mapper = new ObjectMapper();
        String jsonStr = null;
        try {
            // 使用 ObjectMapper 的 readValue 方法,将文件中的 JSON 数据转换为一个 Java 对象
            // 这里使用 Object 类作为泛型参数,表示任意类型的对象
            Object obj = mapper.readValue(new File(filePath), Object.class);
            // 使用 ObjectMapper 的 writeValueAsString 方法,将 Java 对象转换为 JSON 字符串
            jsonStr = mapper.writeValueAsString(obj);
        } catch (IOException e) {
            // 处理异常
            e.printStackTrace();
        }
        dialgramJson = new JSONObject(jsonStr);
        List<ProductStatusDto> childList = this.getStatusData(productId, taskId);
        return Result.ok(childList);
    public Result<String> getTimeDiagram(Long productId, Long taskId, Long fzId) {
        String data = simulatAssessService.getTimeDiagram(productId, taskId, fzId);
        return  Result.ok(data);
    }
    public List<ProductStatusDto> getStatusData(Long productId, Long taskId) {
        List<ProductStatusDto> childList = simulatAssessService.getChildren(productId, taskId);
        for (ProductStatusDto item : childList) {
            if (dialgram.size() > 0) {
                dialgram.clear();
            }
            JSONArray jsonArray = dialgramJson.getJSONArray(String.valueOf(item.getId()));
            if (jsonArray != null) {
                this.processJSONArray(jsonArray, item);
            }
        }
        return childList;
    @GetMapping("getDiagram")
    @ApiOperation("查询流程图")
    @LogOperation("查询流程图")
    public Result<TimeDiagram> getDiagram(String projectId, String diagramId, String showType, String isShow, String digramParams, String majorId, Integer winWidth, Integer winHeight) throws Exception {
        if (StringUtils.isBlank(diagramId))
            diagramId = projectId;
        TimeDiagram diagram = simulatAssessService.getDiagram(projectId, diagramId, showType, isShow, digramParams, majorId, winWidth, winHeight);
        return Result.ok(diagram);
    }
    public void processJSONArray(JSONArray jsonArray, ProductStatusDto productStatusDto) {
        String status = null;
        Double times = null;
        for (int i = 0; i < jsonArray.size(); i++) {
            Object item = jsonArray.get(i);
            if (item instanceof JSONArray) {
                processJSONArray((JSONArray) item, productStatusDto); // 递归调用
            } else {
                if (item instanceof Double) {
                    times = (Double) item;
                } else {
                    status = String.valueOf(item);
                }
            }
        }
        if (status != null || times != null) {
            StatusDto statusDto =new StatusDto();
            statusDto.setTimes(times);
            statusDto.setStatus(status);
            productStatusDto.getStatusList().add(statusDto);
        }
    @PutMapping("saveDiagram")
    @ApiOperation("查询流程图")
    @LogOperation("查询流程图")
    public Result saveDiagram(@RequestBody TimeDiagram diagram) {
        // 效验数据
        //ValidatorUtils.validateEntity(project.getProject(), UpdateGroup.class, DefaultGroup.class);
        if (diagram.getConfigChange() == null)
            diagram.setConfigChange(0);
        diagram.setSaveStatus(2);
        simulatAssessService.updateDiagram(diagram);
        //simulatAssessService.combineDiagram(diagram);
        return Result.ok();
    }
    @GetMapping("getCalcProgress")
@@ -278,7 +249,6 @@
        return Result.ok();
    }
}
modules/mainPart/src/main/java/com/zt/life/modules/mainPart/taskReliability/dao/SimulatAssessDao.java
@@ -1,12 +1,16 @@
package com.zt.life.modules.mainPart.taskReliability.dao;
import com.zt.common.dao.BaseDao;
import com.zt.life.modules.mainPart.taskReliability.dto.ModelDto;
import com.zt.life.modules.mainPart.taskReliability.dto.ProductStatusDto;
import com.zt.life.modules.mainPart.taskReliability.model.SimulatAssess;
import com.zt.life.modules.mainPart.taskReliability.model.SimulatAssessTaskPhaseModel;
import com.zt.life.modules.mainPart.taskReliability.model.TimeDiagram;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
import java.util.Map;
/**
@@ -26,4 +30,10 @@
    SimulatAssess getParams(Long id, Long taskModelId);
    List<ProductStatusDto> getChildren(Long productId, Long taskId);
    List<SimulatAssessTaskPhaseModel> getTaskPhaseModelByTaskId(Long taskId);
    List<TimeDiagram> getTimeDiagram(Map<String, Object> params);
    List<SimulatAssessTaskPhaseModel> getModelList(Long productId, Long fzId);
}
modules/mainPart/src/main/java/com/zt/life/modules/mainPart/taskReliability/dao/TimeDiagramDao.java
New file
@@ -0,0 +1,23 @@
package com.zt.life.modules.mainPart.taskReliability.dao;
import com.zt.common.dao.BaseDao;
import com.zt.life.modules.mainPart.taskReliability.model.Task;
import com.zt.life.modules.mainPart.taskReliability.model.TaskPhase;
import com.zt.life.modules.mainPart.taskReliability.model.TaskPhaseModel;
import com.zt.life.modules.mainPart.taskReliability.model.TimeDiagram;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
import java.util.Map;
/**
 * task
 *
 * @author zt generator
 * @since 1.0.0 2024-03-15
 */
@Mapper
public interface TimeDiagramDao extends BaseDao<TimeDiagram> {
}
modules/mainPart/src/main/java/com/zt/life/modules/mainPart/taskReliability/dto/ModelDto.java
New file
@@ -0,0 +1,15 @@
package com.zt.life.modules.mainPart.taskReliability.dto;
import lombok.Data;
@Data
public class ModelDto {
    private Long phaseId ;
    private String phaseName ;
    private Double phaseDurationRate ;
    private Double operatConditDurationRate ;
    private Long operatConditId ;
    private String operatConditName ;
    private Long modelId ;
    private String modelName ;
}
modules/mainPart/src/main/java/com/zt/life/modules/mainPart/taskReliability/model/SimulatAssess.java
@@ -22,8 +22,6 @@
public class SimulatAssess extends BusiEntity {
    private static final long serialVersionUID = 1L;
    @ApiModelProperty(value = "上级ID")
    private Long pid;
    @ApiModelProperty(value = "产品节点ID")
    private Long productId;
modules/mainPart/src/main/java/com/zt/life/modules/mainPart/taskReliability/model/SimulatAssessTaskPhaseModel.java
@@ -66,4 +66,6 @@
    @ApiModelProperty(value = "备注")
    private String remark;
    private Integer sort;
}
modules/mainPart/src/main/java/com/zt/life/modules/mainPart/taskReliability/model/TimeDiagram.java
New file
@@ -0,0 +1,47 @@
package com.zt.life.modules.mainPart.taskReliability.model;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.zt.common.entity.CompanyEntity;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("time_diagram")
public class TimeDiagram extends CompanyEntity {
    private static final long serialVersionUID = 1L;
    @ApiModelProperty(value = "PROJECT_ID")
    private Long projectId;
    @ApiModelProperty(value = "DIAGRAM_ID")
    private Long diagramId;
    @ApiModelProperty(value = "专业")
    @TableField(exist = false)
    private String majorId;
    @ApiModelProperty(value = "xml文档")
    private String content;
    @ApiModelProperty(value = "发布文档")
    private String publishContent;
    @ApiModelProperty(value = "发布状态")
    private Integer hasPublish;
    @ApiModelProperty(value = "保存状态")
    private Integer saveStatus;
    @ApiModelProperty(value = "配置改变")
    private Integer configChange;
    @ApiModelProperty(value = "备注")
    private String remark;
    @ApiModelProperty(value = "浏览")
    @TableField(exist = false)
    private String isShow;
    @ApiModelProperty(value = "状态")
    @TableField(exist = false)
    private String status;
}
modules/mainPart/src/main/java/com/zt/life/modules/mainPart/taskReliability/service/SimulatAssessService.java
@@ -1,6 +1,11 @@
package com.zt.life.modules.mainPart.taskReliability.service;
import com.alibaba.fastjson.JSONObject;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.spire.pdf.tables.table.convert.Convert;
import com.zt.common.exception.RenException;
import com.zt.common.service.BaseService;
import com.zt.common.servlet.Result;
import com.zt.common.utils.UUIDUtil;
@@ -9,6 +14,12 @@
import com.zt.life.modules.mainPart.basicInfo.model.ParamData;
import com.zt.life.modules.mainPart.basicInfo.model.XhProductModel;
import com.zt.life.modules.mainPart.taskReliability.dao.*;
import com.zt.common.servlet.Result;
import com.zt.common.utils.JsonUtils2;
import com.zt.common.utils.UUIDUtil;
import com.zt.life.modules.mainPart.taskReliability.dao.SimulatAssessDao;
import com.zt.life.modules.mainPart.taskReliability.dao.TimeDiagramDao;
import com.zt.life.modules.mainPart.taskReliability.dto.ModelDto;
import com.zt.life.modules.mainPart.taskReliability.dto.ProductStatusDto;
import com.zt.life.modules.mainPart.taskReliability.dto.TaskModelCheckResult;
import com.zt.life.modules.mainPart.taskReliability.model.*;
@@ -19,9 +30,14 @@
import org.dom4j.io.XMLWriter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.zt.life.modules.mainPart.taskReliability.dto.StatusDto;
import com.zt.life.modules.mainPart.taskReliability.model.SimulatAssess;
import com.zt.life.modules.mainPart.taskReliability.model.SimulatAssessTaskPhaseModel;
import com.zt.life.modules.mainPart.taskReliability.model.TimeDiagram;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -30,7 +46,13 @@
import java.io.InputStreamReader;
import java.io.StringWriter;
import java.util.ArrayList;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.stream.Collectors;
import java.util.Map;
import java.util.stream.Collectors;
@@ -77,6 +99,21 @@
    @Autowired
    private ParamDataDao paramDataDao;
    @Autowired
    private TimeDiagramDao timeDiagramDao;
    @Value("${data.reliaSimLib.resultHome}")
    private String path;
    private JSONObject dialgramJson;
    String templetStr = "{\"cells\":[]}";
    Map<String, JSONObject> templetsMap = new HashMap<>();
    Map<String, String> templetsStrMap = new HashMap<>();
    /**
     * 分页查询
     *
@@ -108,10 +145,503 @@
        return baseDao.getParams(id, taskModelId);
    }
    public List<ProductStatusDto> getChildren(Long productId, Long taskId) {
    public List<ProductStatusDto> getProduct(Long productId, Long taskId) {
        return baseDao.getChildren(productId, taskId);
    }
    public String getTimeDiagram(Long productId, Long taskId, Long fzId) {
        String filePath = path + "/" + fzId + "/" + "status.json";
        ObjectMapper mapper = new ObjectMapper();
        String jsonStr = null;
        try {
            // 使用 ObjectMapper 的 readValue 方法,将文件中的 JSON 数据转换为一个 Java 对象
            // 这里使用 Object 类作为泛型参数,表示任意类型的对象
            Object obj = mapper.readValue(new File(filePath), Object.class);
            // 使用 ObjectMapper 的 writeValueAsString 方法,将 Java 对象转换为 JSON 字符串
            jsonStr = mapper.writeValueAsString(obj);
        } catch (IOException e) {
            // 处理异常
            e.printStackTrace();
            throw new RenException("文件不存在或者文件打不开");
        }
        dialgramJson = new JSONObject(jsonStr);
        // 阶段模型
        List<SimulatAssessTaskPhaseModel> modelDtoList = baseDao.getModelList(productId, fzId);
        // 所有阶段模型的节点集合 (线条)
        List<ProductStatusDto> list = this.getStatusData(productId, taskId);
        // 每次仿真记录
        SimulatAssess simulatAssess = this.get(fzId);
        JSONObject jsonObject = new JSONObject(templetStr);
        JSONArray jsonArray = jsonObject.getJSONArray("cells");
        this.getPetsInfo();
        double x1 = 0;
        double x2 = 0;
        int y = 0;
        int groupY = 0;
        int spaceHeight = 20;
        int groupHeight = 20;
        double pointNumPerHour = 60.0 / simulatAssess.getSamplPeriod();
        //时序图线
        for (int i = 0; i < list.size(); i++) {
            x1 = 0;
            groupY = groupHeight * i;
            ProductStatusDto dto = list.get(i);
            for (StatusDto status : dto.getStatusList()) {
                switch (status.getStatus()) {
                    case "O":
                        y = groupY;
                        break;
                    case "F":
                        y = groupY;// + spaceHeight;
                        break;
                    case "I":
                    case "S":
                    case "M":
                        y = groupY;// + 2 * spaceHeight;
                        break;
                }
                x2 = x1 + status.getTimes() * pointNumPerHour + 5;
                JSONObject lineJson = new JSONObject(templetsStrMap.get(status.getStatus()));
                setlineXy(lineJson, x1, y, x2, y, "");
                JsonUtils2.setJsonValueByPath(lineJson, "id".split("/"), UUIDUtil.generateId().toString());
                x1 = x2 - 5;
                jsonArray.add(lineJson);
            }
            JSONObject textJson = new JSONObject(templetsStrMap.get("text"));
            JsonUtils2.setJsonValueByPath(textJson, "id".split("/"), UUIDUtil.generateId().toString());
            JsonUtils2.setJsonValueByPath(textJson, "attrs/label/textWrap/text".split("/"), dto.getName());
            JsonUtils2.setJsonValueByPath(textJson, "position/x".split("/"), 20);
            JsonUtils2.setJsonValueByPath(textJson, "position/y".split("/"), y - 15);
            jsonArray.add(textJson);
        }
        //图例
        int spaceWitdth = 80;
        x1 = -spaceWitdth;
        x2 = -11;
        y = -100;
        String[] tlArr = "O,F,I,S,M".split(",");
        for (String s : tlArr) {
            JSONObject f = templetsMap.get(s);
            x1 = x1 + spaceWitdth;
            x2 = x2 + spaceWitdth;
            setlineXy(f, x1, y, x2, y, null);
            jsonArray.add(f);
        }
        //阶段模型及刻度
        x1 = 0;
        x2 = 0;
        double y1 = -60;
        y = -30;
        double y2 = -10;
        JSONObject modelJson = new JSONObject(templetsStrMap.get("model"));
        setlineXy(modelJson, x1, y1, x1, y2, null);
        jsonArray.add(modelJson);
        double totalHours = 0;
        for (int i = 0; i < modelDtoList.size(); i++) {
            JSONObject modelJson2 = new JSONObject(templetsStrMap.get("model"));
            SimulatAssessTaskPhaseModel modelDto = modelDtoList.get(i);
            totalHours = totalHours + modelDto.getGkDuration();
            x2 = x2 + modelDto.getGkDuration() * pointNumPerHour;
            if (i < modelDtoList.size() - 1) {
                setlineXy(modelJson2, x2, y1, x2, y, null);
            } else {
                setlineXy(modelJson2, x2, y1, x2, y2, null);
            }
            jsonArray.add(modelJson2);
            JSONObject textJson = new JSONObject(templetsStrMap.get("text"));
            JsonUtils2.setJsonValueByPath(textJson, "data/dataId".split("/"), modelDto.getGkId());
            JsonUtils2.setJsonValueByPath(textJson, "id".split("/"), UUIDUtil.generateId().toString());
            JsonUtils2.setJsonValueByPath(textJson, "attrs/label/textWrap/text".split("/"), modelDto.getGkName());
            JsonUtils2.setJsonValueByPath(textJson, "position/x".split("/"), x1 + 30);
            JsonUtils2.setJsonValueByPath(textJson, "position/y".split("/"), y1);
            jsonArray.add(textJson);
            x1 = x2;
        }
        JSONObject modelJson3 = new JSONObject(templetsStrMap.get("model"));
        setlineXy(modelJson3, 0, y, x2, y, null);
        jsonArray.add(modelJson3);
        double curPointHour = 50, periodHour = 50;
        while (curPointHour < totalHours) {
            JSONObject modelJson4 = new JSONObject(templetsStrMap.get("model"));
            double x = curPointHour * pointNumPerHour;
            setlineXy(modelJson4, x, y, x, y, null);
            jsonArray.add(modelJson4);
        }
        return jsonObject.toString();
    }
    public void setlineXy(JSONObject lineJson, double x1, double y1, double x2, double y2, String text) {
        JsonUtils2.setJsonValueByPath(lineJson, "source/x".split("/"), x1);
        JsonUtils2.setJsonValueByPath(lineJson, "source/y".split("/"), y1);
        JsonUtils2.setJsonValueByPath(lineJson, "target/x".split("/"), x2);
        JsonUtils2.setJsonValueByPath(lineJson, "target/y".split("/"), y2);
        if (text != null) {
            JsonUtils2.setArrJsonValueByPath(lineJson, "labels".split("/"), null, "0", "attrs/text/text", "");
        }
    }
    public void getPetsInfo() {
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("projectId", 10000);
        params.put("diagramId", 10000);
        List<TimeDiagram> list_style = baseDao.getTimeDiagram(params);
        if (list_style.size() > 0) {
            String modelStr = list_style.get(0).getContent();
            JSONObject modelJson = new JSONObject(modelStr);
            JSONArray modelJsonArray = modelJson.getJSONArray("cells");
            for (int i = 0; i < modelJsonArray.size(); i++
            ) {
                JSONObject jsonObject = modelJsonArray.getJSONObject(i);
                if (jsonObject.get("shape").equals("edge")) {
                    JSONArray tmpArray = jsonObject.getJSONArray("labels");
                    JSONObject tmpJSONObject = (JSONObject) tmpArray.get(0);
                    Object nodeMarker = JsonUtils2.getJsonValueByPath(tmpJSONObject, "attrs/text/text".split("/"));
                    if ("运行".equals(nodeMarker)) {
                        templetsMap.put("O", jsonObject);
                        templetsStrMap.put("O", jsonObject.toString());
                    }
                    if ("故障".equals(nodeMarker)) {
                        templetsMap.put("F", jsonObject);
                        templetsStrMap.put("F", jsonObject.toString());
                    }
                    if ("空闲".equals(nodeMarker)) {
                        templetsMap.put("I", jsonObject);
                        templetsStrMap.put("I", jsonObject.toString());
                    }
                    if ("备份".equals(nodeMarker)) {
                        templetsMap.put("S", jsonObject);
                        templetsStrMap.put("S", jsonObject.toString());
                    }
                    if ("未用".equals(nodeMarker)) {
                        templetsMap.put("M", jsonObject);
                        templetsStrMap.put("M", jsonObject.toString());
                    }
                    if ("模型".equals(nodeMarker)) {
                        JsonUtils2.setJsonValueByPath(tmpJSONObject, "attrs/text/text".split("/"), "");
                        templetsMap.put("model", jsonObject);
                        templetsStrMap.put("model", jsonObject.toString());
                    }
                } else if (jsonObject.get("shape").equals("custom-rect")) {
                    Object nodeMarker = JsonUtils2.getJsonValueByPath(jsonObject, "attrs/label/textWrap/text".split("/"));
                    if ("文字模板1".equals(nodeMarker)) {
                        templetsMap.put("text", jsonObject);
                        templetsStrMap.put("text", jsonObject.toString());
                    }
                } else if (jsonObject.get("shape").equals("image")) {
                    Object nodeMarker = JsonUtils2.getJsonValueByPath(jsonObject, "data/imagePost".split("/"));
                    if ("center".equals(nodeMarker)) {
                        templetsMap.put("center", jsonObject);
                        templetsStrMap.put("center", jsonObject.toString());
                    }
                    if ("top".equals(nodeMarker)) {
                        templetsMap.put("top", jsonObject);
                        templetsStrMap.put("top", jsonObject.toString());
                    }
                    if ("right".equals(nodeMarker)) {
                        templetsMap.put("right", jsonObject);
                        templetsStrMap.put("right", jsonObject.toString());
                    }
                    if ("bottom".equals(nodeMarker)) {
                        templetsMap.put("bottom", jsonObject);
                        templetsStrMap.put("bottom", jsonObject.toString());
                    }
                    if ("left".equals(nodeMarker)) {
                        templetsMap.put("left", jsonObject);
                        templetsStrMap.put("left", jsonObject.toString());
                    }
                }
            }
        }
    }
    public List<ProductStatusDto> getStatusData(Long productId, Long taskId) {
        List<ProductStatusDto> childList = this.getProduct(productId, taskId);
        for (ProductStatusDto item : childList) {
            JSONArray jsonArray = dialgramJson.getJSONArray(String.valueOf(item.getId()));
            if (jsonArray != null) {
                this.processJSONArray(jsonArray, item, taskId);
            }
        }
        return childList;
    }
    public void processJSONArray(JSONArray jsonArray, ProductStatusDto productStatusDto, Long taskId) {
        List<SimulatAssessTaskPhaseModel> phaseModelList = baseDao.getTaskPhaseModelByTaskId(taskId);
        String status = null;
        Double times = null;
        JSONArray jsonArray2 = jsonArray.getJSONArray(0);
        for (int j = 0; j < jsonArray2.size(); j++) {
            JSONArray jsonArray3 = jsonArray2.getJSONArray(j);
            if (jsonArray3.size() == 0) {
                StatusDto statusDto = new StatusDto();
                statusDto.setTimes(phaseModelList.get(j).getGkDuration());
                statusDto.setStatus("");
                productStatusDto.getStatusList().add(statusDto);
            } else {
                for (int a = 0; a < jsonArray3.size(); a++) {
                    JSONArray jsonArray4 = jsonArray3.getJSONArray(a);
                    for (int b = 0; b < jsonArray4.size(); b++) {
                        Object item = jsonArray4.get(b);
                        if (item instanceof Double) {
                            times = (Double) item;
                        } else {
                            status = String.valueOf(item);
                        }
                    }
                    if (status != null || times != null) {
                        StatusDto statusDto = new StatusDto();
                        statusDto.setTimes(times);
                        statusDto.setStatus(status);
                        productStatusDto.getStatusList().add(statusDto);
                    }
                }
            }
        }
    }
    public TimeDiagram getDiagram(String projectId, String diagramId, String showType, String isShow, String digramParams, String majorId, Integer winWidth, Integer winHeight) {
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("projectId", projectId);
        params.put("diagramId", diagramId);
        TimeDiagram diagram = null;
        List<TimeDiagram> list = baseDao.getTimeDiagram(params);
        if (list.size() > 0) {
            diagram = list.get(0);
        } else {
            diagram = new TimeDiagram();
            diagram.setProjectId(Convert.toLong(projectId));
            diagram.setDiagramId(Convert.toLong(diagramId));
        }
        return diagram;
    }
    public void updateDiagram(TimeDiagram diagram) {
        timeDiagramDao.updateById(diagram);
    }
/*    public void combineDiagram(TimeDiagram networkDiagram) {
        if (!networkDiagram.getDiagramId().equals(1L) && !networkDiagram.getDiagramId().equals(2L))
            return null;
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("projectId", networkDiagram.getProjectId());
        ProjectNetworkDiagram combineDiagram = null;
        params.put("diagramId", 100);
        List<ProjectNetworkDiagram> list = baseDao.getList(params);
        if (list.size() > 0) {
            combineDiagram = list.get(0);
        }
        ProjectNetworkDiagram phaseDiagram = null;
        params.put("diagramId", 1);
        List<ProjectNetworkDiagram> list1 = baseDao.getList(params);
        if (list1.size() > 0) {
            phaseDiagram = list1.get(0);
        }
        ProjectNetworkDiagram inspectDiagram = null;
        params.put("diagramId", 2);
        List<ProjectNetworkDiagram> list2 = baseDao.getList(params);
        if (list2.size() > 0) {
            inspectDiagram = list2.get(0);
        }
        String jsonStr = "";
        Map<String, Map<String, String>> leftMap = new Hashtable<>();
        Map<String, Map<String, String>> rightMap = new Hashtable<>();
        if (phaseDiagram != null && inspectDiagram != null) {
            String inspectJsonStr = inspectDiagram.getContent();
            JSONObject inspectJsonObj = new JSONObject(inspectJsonStr);
            JSONArray inspectJsonArray = inspectJsonObj.getJSONArray("cells");
            String phaseJsonStr = phaseDiagram.getContent();
            JSONObject phaseJsonObj = new JSONObject(phaseJsonStr);
            JSONArray phaseJsonArray = phaseJsonObj.getJSONArray("cells");
            JSONArray leftArray = inspectJsonArray.stream().filter(iter -> "edge".equals(((JSONObject) iter).get("shape"))
                    && "left".equals(((JSONObject) iter).get("phaseType"))).collect(Collectors.toCollection(JSONArray::new));
            int leftPhaseMaxX = 0;
            int phaseY = 0;
            String leftPhaseMaxId = "";
            for (int i = 0; i < leftArray.size(); i++) {
                Map<String, String> tmpMap = new Hashtable<>();
                JSONObject lineObject = (JSONObject) leftArray.get(i);
                String phaseId = lineObject.getStr("phaseId");
                JSONArray phaseArray = phaseJsonArray.stream().filter(iter -> "custom-circle".equals(((JSONObject) iter).get("shape"))
                        && phaseId.equals(((JSONObject) iter).get("id"))).collect(Collectors.toCollection(JSONArray::new));
                tmpMap.put("lineId", lineObject.getStr("id"));
                tmpMap.put("phaseId", phaseId);
                String portId = "";
                if (phaseArray.size() > 0) {
                    JSONObject phaseObject = (JSONObject) phaseArray.get(0);
                    Object portIdObject = JsonUtils2.getArrJsonValueByPath(phaseObject, "ports/items/".split("/"), "group", "right", "id");
                    //portId = portIdObject == null ? "" : portIdObject.toString();
                    Object xObject = JsonUtils2.getJsonValueByPath(phaseObject, "position/x".split("/"));
                    int x = xObject == null ? 0 : Convert.toInt(xObject.toString());
                    if (x > leftPhaseMaxX) {
                        leftPhaseMaxX = x;
                        leftPhaseMaxId = phaseObject.getStr("id");
                    }
                    if (phaseY == 0) {
                        Object yObject = JsonUtils2.getJsonValueByPath(phaseObject, "position/y".split("/"));
                        phaseY = yObject == null ? 0 : Convert.toInt(yObject.toString());
                    }
                }
                tmpMap.put("portId", portId);
                leftMap.put(lineObject.getStr("id"), tmpMap);
            }
            JSONArray rightArray = inspectJsonArray.stream().filter(iter -> "edge".equals(((JSONObject) iter).get("shape"))
                    && "right".equals(((JSONObject) iter).get("phaseType"))).collect(Collectors.toCollection(JSONArray::new));
            int rightPhaseMinX = 10000000;
            String rightPhaseMinId = "";
            for (int i = 0; i < rightArray.size(); i++) {
                Map<String, String> tmpMap = new Hashtable<>();
                JSONObject lineObject = (JSONObject) rightArray.get(i);
                String phaseId = lineObject.getStr("phaseId");
                JSONArray phaseArray = phaseJsonArray.stream().filter(iter -> "custom-circle".equals(((JSONObject) iter).get("shape"))
                        && phaseId.equals(((JSONObject) iter).get("id"))).collect(Collectors.toCollection(JSONArray::new));
                tmpMap.put("lineId", lineObject.getStr("id"));
                tmpMap.put("phaseId", phaseId);
                String portId = "";
                if (phaseArray.size() > 0) {
                    JSONObject phaseObject = (JSONObject) phaseArray.get(0);
                    Object portIdObject = JsonUtils2.getArrJsonValueByPath(phaseObject, "ports/items/".split("/"), "group", "left", "id");
                    //portId = portIdObject == null ? "" : portIdObject.toString();
                    Object xObject = JsonUtils2.getJsonValueByPath(phaseObject, "position/x".split("/"));
                    int x = xObject == null ? 100000000 : Convert.toInt(xObject.toString());
                    if (x < rightPhaseMinX) {
                        rightPhaseMinX = x;
                        rightPhaseMinId = phaseObject.getStr("id");
                    }
                }
                tmpMap.put("portId", portId);
                rightMap.put(lineObject.getStr("id"), tmpMap);
            }
            JSONArray startArray = inspectJsonArray.stream().filter(iter -> "custom-circle".equals(((JSONObject) iter).get("shape"))
                    && "10000".equals(((JSONObject) iter).get("id"))).collect(Collectors.toCollection(JSONArray::new));
            int inspectBeginX = 0;
            int inspectY = 0;
            if (startArray.size() > 0) {
                JSONObject inspectObject = (JSONObject) startArray.get(0);
                Object xObject = JsonUtils2.getJsonValueByPath(inspectObject, "position/x".split("/"));
                inspectBeginX = xObject == null ? 0 : Convert.toInt(xObject.toString());
                Object yObject = JsonUtils2.getJsonValueByPath(inspectObject, "position/y".split("/"));
                inspectY = yObject == null ? 0 : Convert.toInt(yObject.toString());
            }
            JSONArray endArray = inspectJsonArray.stream().filter(iter -> "custom-circle".equals(((JSONObject) iter).get("shape"))
                    && "20000".equals(((JSONObject) iter).get("id"))).collect(Collectors.toCollection(JSONArray::new));
            int inspectEndX = 10000000;
            if (endArray.size() > 0) {
                JSONObject inspectObject = (JSONObject) endArray.get(0);
                Object xObject = JsonUtils2.getJsonValueByPath(inspectObject, "position/x".split("/"));
                inspectEndX = xObject == null ? 100000000 : Convert.toInt(xObject.toString());
            }
            JSONObject beginObject = null;
            JSONObject endObject = null;
            for (int i = 0; i < inspectJsonArray.size(); i++) {
                JSONObject inspectObject = (JSONObject) inspectJsonArray.get(i);
                String inspectObjectId = inspectObject.getStr("id");
                if (leftMap.get(inspectObjectId) != null) {
                    JsonUtils2.setJsonValueByPath(inspectObject, "target/cell".split("/"), leftMap.get(inspectObjectId).get("phaseId"));
                    JsonUtils2.setJsonValueByPath(inspectObject, "target/port".split("/"), leftMap.get(inspectObjectId).get("portId"));
                }
                if (rightMap.get(inspectObjectId) != null) {
                    JsonUtils2.setJsonValueByPath(inspectObject, "target/cell".split("/"), rightMap.get(inspectObjectId).get("phaseId"));
                    JsonUtils2.setJsonValueByPath(inspectObject, "target/port".split("/"), rightMap.get(inspectObjectId).get("portId"));
                }
                if ("10000".equals(inspectObjectId)) {
                    //inspectJsonArray.remove(inspectObject);
                    beginObject = inspectObject;
                }
                if ("20000".equals(inspectObjectId)) {
                    //inspectJsonArray.remove(inspectObject);
                    endObject = inspectObject;
                }
            }
            if (endObject != null)
                inspectJsonArray.remove(endObject);
            if (beginObject != null)
                inspectJsonArray.remove(beginObject);
            for (int i = 0; i < phaseJsonArray.size(); i++) {
                JSONObject phaseObject = (JSONObject) phaseJsonArray.get(i);
                if ("custom-circle".equals(phaseObject.getStr("shape"))) {
                    Object xObject = JsonUtils2.getJsonValueByPath(phaseObject, "position/x".split("/"));
                    Object yObject = JsonUtils2.getJsonValueByPath(phaseObject, "position/y".split("/"));
                    int x = Convert.toInt(xObject.toString());
                    int y = Convert.toInt(yObject.toString());
                    if (x <= leftPhaseMaxX)
                        x = x + (inspectBeginX - leftPhaseMaxX);
                    else if (x >= rightPhaseMinX)
                        x = x + (inspectEndX - rightPhaseMinX);
                    y = y + (inspectY - phaseY);
                    JsonUtils2.setJsonValueByPath(phaseObject, "position/x".split("/"), x);
                    JsonUtils2.setJsonValueByPath(phaseObject, "position/y".split("/"), y);
                }
            }
            for (int i = 0; i < phaseJsonArray.size(); i++) {
                JSONObject phaseObject = (JSONObject) phaseJsonArray.get(i);
                if ("edge".equals(phaseObject.getStr("shape"))) {
                    Object sourceId = JsonUtils2.getJsonValueByPath(phaseObject, "source/cell".split("/"));
                    Object targetId = JsonUtils2.getJsonValueByPath(phaseObject, "target/cell".split("/"));
                    if (leftPhaseMaxId.equals(sourceId) && rightPhaseMinId.equals(targetId)) {
                        phaseJsonArray.remove(phaseObject);
                    }
                }
            }
            inspectJsonArray.addAll(phaseJsonArray);
            jsonStr = inspectJsonObj.toString();
        } else if (phaseDiagram != null) {
            jsonStr = phaseDiagram.getContent();
        } else if (inspectDiagram != null) {
            jsonStr = inspectDiagram.getContent();
        }
        if (combineDiagram != null) {
            combineDiagram.setContent(jsonStr);
            baseDao.updateById(combineDiagram);
        } else {
            combineDiagram = new ProjectNetworkDiagram();
            combineDiagram.setProjectId(networkDiagram.getProjectId());
            combineDiagram.setDiagramId(100L);
            combineDiagram.setContent(jsonStr);
            baseDao.insert(combineDiagram);
        }
        return combineDiagram;
    }*/
    @Transactional(rollbackFor = Exception.class)
    public Result simulate(SimulatAssess simulatAssess) {
        Result result = null;
modules/mainPart/src/main/resources/mapper/taskReliability/SimulatAssessDao.xml
@@ -4,12 +4,12 @@
<mapper namespace="com.zt.life.modules.mainPart.taskReliability.dao.SimulatAssessDao">
    <select id="getList" resultType="com.zt.life.modules.mainPart.taskReliability.model.SimulatAssess">
        select *
        select id, CONCAT_WS(' ', name, CREATE_DATE) AS name
        from simulat_assess
        where product_id = ${productId}
          and task_model_id = ${taskModelId}
          and IS_DELETE = 0
        order by name desc
        order by CREATE_DATE desc
    </select>
    <select id="getNumById" resultType="java.lang.Integer">
        select COUNT(*)
@@ -26,10 +26,11 @@
          and a.IS_DELETE = 0
    </select>
    <select id="getChildren" resultType="com.zt.life.modules.mainPart.taskReliability.dto.ProductStatusDto">
        select * from (
        select *
        from (
                          SELECT f.id,f.name, 0 as sort
                          FROM product_model f
                          WHERE f.id = 1813102074724945921
                 WHERE f.id = ${productId}
                            AND f.is_delete = 0
                          union
                          SELECT f.id,f.name,f.sort
@@ -55,4 +56,59 @@
                      ) as f
        ORDER BY f.sort
    </select>
    <select id="getTaskPhaseModelByTaskId"
            resultType="com.zt.life.modules.mainPart.taskReliability.model.SimulatAssessTaskPhaseModel">
        select *
        from simulat_assess_task_phase_model
        where is_delete = 0
          and task_id = ${taskId}
        order by sort
    </select>
    <select id="getTimeDiagram" resultType="com.zt.life.modules.mainPart.taskReliability.model.TimeDiagram">
        select *
        from time_diagram
        where is_delete = 0
        <if test="projectId!=null and projectId!=''">
            and PROJECT_ID = #{projectId}
        </if>
        <if test="diagramId!=null and diagramId!=''">
            and DIAGRAM_ID = #{diagramId}
        </if>
        <if test="hasPublish!=null and hasPublish!=''">
            and HAS_PUBLISH = #{hasPublish}
        </if>
    </select>
    <select id="getModelListOld" resultType="com.zt.life.modules.mainPart.taskReliability.dto.ModelDto">
        SELECT a.id   AS phase_id,
               a.phase_name,
               a.phase_duration_rate,
               b.operat_condit_duration_rate,
               b.operat_condit_id,
               c.NAME AS operat_condit_name,
               d.model_id,
               e.model_name
        FROM `task_phase` a,
             task_phase_model b,
             operat_condit c,
             operat_condit_model d,
             model_rbd e
        WHERE a.task_id = ${taskId}
          and d.product_id = ${productId}
          AND a.is_delete = 0
          AND b.is_delete = 0
          AND c.id = b.operat_condit_id
          AND c.is_delete = 0
          AND d.operat_condit_id = c.id
          AND d.is_delete = 0
          and e.is_delete = 0
          and d.model_id = e.id
        order by c.CREATE_DATE
    </select>
    <select id="getModelList" resultType="com.zt.life.modules.mainPart.taskReliability.model.SimulatAssessTaskPhaseModel">
        SELECT *
        FROM simulat_assess_task_phase_model
        WHERE fz_id = ${fzId}
          AND is_delete = 0
        order by sort
    </select>
</mapper>
modules/mainPart/src/main/resources/mapper/taskReliability/TimeDiagram.xml
New file
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zt.life.modules.mainPart.taskReliability.dao.TimeDiagramDao">
</mapper>
web/src/views/layout/main-content.vue
@@ -12,9 +12,14 @@
          <!--<el-dropdown-item @click.native="tabsCloseAllHandle()">{{ $t('contentTabs.closeAll') }}</el-dropdown-item>-->
        <!--</el-dropdown-menu>-->
      <!--</el-dropdown>-->
      <el-form :inline="true" style="position:absolute;right:10px; margin-top:3px;z-index:9;overflow: hidden;white-space: nowrap">
        <zt-button class="CloseHandle" type="primary" @click.native="tabsCloseOtherHandle()">{{ $t('contentTabs.closeOther') }}</zt-button>
        <zt-button class="CloseHandle" type="primary" @click.native="tabsCloseAllHandle()">{{ $t('contentTabs.closeAll') }}</zt-button>
      <el-form :inline="true"
               style="position:absolute;right:10px; margin-top:3px;z-index:9;overflow: hidden;white-space: nowrap">
        <zt-button class="CloseHandle" type="primary" @click.native="tabsCloseOtherHandle()">{{
          $t('contentTabs.closeOther') }}
        </zt-button>
        <zt-button class="CloseHandle" type="primary" @click.native="tabsCloseAllHandle()">{{ $t('contentTabs.closeAll')
          }}
        </zt-button>
      </el-form>
      <el-tabs class="tabNext" v-model="$store.state.contentTabsActiveName" @tab-click="tabSelectedHandle"
               @tab-remove="tabRemoveHandle"
@@ -82,12 +87,25 @@
    },
    computed: {
      key() {
        return this.$route.name !== undefined? this.$route.name + +new Date(): this.$route + +new Date()
        let key = ''
        if (this.$route.name !== undefined) {
          let tab = this.$store.state.contentTabs.filter(item => item.name === this.$route.name)[0]
          console.log(tab, 'key this.$store.state.contentTabs')
          key = this.$route.name
          if (!tab.isRefresh) {
            key += +new Date()
          }
        } else {
          key = this.$route + +new Date()
        }
        console.log(key, 'key')
        return key
      }
    },
    methods: {
      // tabs, 是否通过iframe展示
      tabIsIframe(url) {
        console.log(isURL(url), 'isURL(url)')
        return isURL(url)
      },
      reload() {
@@ -98,8 +116,9 @@
      },
      // tabs, 选中tab
      tabSelectedHandle(tab) {
        console.log(tab, 'tabSelectedHandle1')
        tab = this.$store.state.contentTabs.filter(item => item.name === tab.name)[0]
        if (tab && (tab.name === 'miantainHome-home' || 'replaceProblemHome-home')) {
        if (tab && (tab.name === 'miantainHome-home' || tab.name === 'replaceProblemHome-home')) {
          this.$nextTick(() => {
            this.$router.push({
              'name': tab.name,
@@ -110,6 +129,7 @@
          })
          // this.reload()
        } else if (tab && tab.name !== this.$router.history.current.name) {
          console.log(tab, 'tabSelectedHandle3')
          this.$nextTick(() => {
            this.$router.push({
              'name': tab.name,
@@ -193,9 +213,11 @@
  .zt .tabNext>.el-tabs__header>.el-tabs__nav-wrap{
    width:80% ;
  }
  .zt .tabNext .el-tabs__nav-wrap.is-scrollable{
    width:80% ;
  }
  #tab-home{
    padding-left: 10px;
  }
web/src/views/modules/baseReliability/ParamDataBasic.vue
@@ -84,6 +84,10 @@
        }
      },
    },
    mounted() {
      this.$refs.modelTree.getProductList()
      console.log(this.pageCode, 'this.pageCode this.pageCode')
    },
    methods: {
      onProductSelected(data) {
        this.defultKey = []
web/src/views/modules/basicInfo/ParamData.vue
@@ -3,7 +3,7 @@
    <el-row :gutter="5">
      <el-col :span="4">
        <div class="fa-card-a" style="margin-right: 5px;height: calc(100vh - 123px)">
          <product-model-tree @on-selected="onProductSelected" @on-default="onDefault" showXdy="false" :isShow="false"/>
          <product-model-tree ref="modelTree" @on-selected="onProductSelected" @on-default="onDefault" showXdy="false" :isShow="false"/>
        </div>
      </el-col>
      <el-col :span="20">
@@ -381,14 +381,12 @@
      SelectTyModel
    },
    mounted() {
      this.$refs.modelTree.getProductList()
      this.pageCode = this.$route.query.pageCode
      this.dataForm.pageCode = this.$route.query.pageCode
      console.log(this.pageCode, 'this.pageCode this.pageCode')
    },
    methods: {
      handleClick() {
      },
      add() {
        this.$refs.SelectTyModel.$refs.dialog.init(null, {
          type: this.dataForm.productType + 1,
web/src/views/modules/basicInfo/ProductModelTree.vue
@@ -7,7 +7,9 @@
      size="small"
      clearable
    ></el-input>-->
    <el-button v-if="isShow" type="primary" @click="add()" style="margin: 10px 0 0 10px;padding: 9px 18px !important;">新增型号</el-button>
    <el-button v-if="isShow" type="primary" @click="add()"
               style="margin: 10px 0 0 10px;padding: 9px 18px !important;">新增型号
    </el-button>
    <el-divider></el-divider>
    <el-tree
      style="height: 90%;overflow: auto"
@@ -45,6 +47,10 @@
        type: Number,
        default: 1
      },
      productId: {
        type: Number,
        default: null
      },
    },
    data() {
@@ -69,19 +75,20 @@
      AddOrUpdate
    }
    ,
    mounted() {
    /* mounted() {
      this.getProductList()
    },
     },*/
    methods: {
      // 获取系统列表
      async getProductList() {
        let params = {
          showXdy: this.showXdy,
          ztShow: this.basic
          ztShow: this.basic,
          productId: this.productId
        }
        let res = await this.$http.get('/basicInfo/XhProductModel/tree', {params: params})
        this.productList = res.data
        if (this.basic) {
        if (this.basic === '3') {
          if (this.productList && this.productList[0].children) {
            this.defaultId = this.productList[0].children[0].id
            this.$nextTick(() => {
@@ -89,6 +96,14 @@
            });
            this.$emit('on-default', this.defaultId)
          }
        } else{
          if (this.productList[0].id) {
            this.defaultId = this.productList[0].id
            this.$nextTick(() => {
              this.$refs.tree.setCurrentKey(this.defaultId); //一定要加这个选中了否则样式没有出来
            });
            this.$emit('on-default', this.defaultId)
          }
        }
        console.log(res.data, 'async getProductList()')
      },
web/src/views/modules/basicInfo/XhProductModel-AddOrUpdate.vue
@@ -43,6 +43,7 @@
          id: '',
          pid: '',
          name: '',
          shipId: '',
          productType: '',
          operatImg: '',
          operatImgName: '',
@@ -57,6 +58,9 @@
    },
    methods: {
      init(id, params) {
        if (params.shipId) {
          this.dataForm.shipId = params.shipId
        }
        if (params.type === 'xh') {
          this.isShow = false
          this.dataForm.pid = null
web/src/views/modules/basicInfo/XhProductModel.vue
@@ -71,6 +71,7 @@
      return {
        url: `${window.SITE_CONFIG['apiURL']}/sysPictureBase/getSvgImage?token=${Cookies.get('token')}&id=`,
        productType: '',
        shipId: '',
        dataForm: {
          name: '',
          type: '',
@@ -86,17 +87,26 @@
      AddOrUpdate,
      SelectTyModel
    },
    mounted() {
      this.$refs.ProductModelTree.getProductList()
    },
    methods: {
      add() {
        this.dataForm.type = this.productType
        if (this.dataForm.type !== '1') {
          this.$refs.SelectTyModel.$refs.dialog.init(null, {type: this.dataForm.type, id: this.dataForm.pid})
          this.$refs.SelectTyModel.$refs.dialog.init(null, {
            type: this.dataForm.type,
            id: this.dataForm.pid,
            shipId: this.shipId
          })
        } else {
          this.$refs.AddOrUpdate.$refs.dialog.init(null, {id: null, type: 'zt', pid: this.dataForm.pid})
        }
      },
      addCell() {
        this.$refs.AddOrUpdate.$refs.dialog.init(null, {type: 10, pid: this.dataForm.pid})
        this.$refs.AddOrUpdate.$refs.dialog.init(null, {
          type: 10, pid: this.dataForm.pid, shipId: this.shipId
        })
      },
      cellStyle({column}) {
        if (column.label === '名称') {
@@ -115,6 +125,7 @@
      },
      onProductSelected(data) {
        console.log(data, 'onProductSelected')
        this.shipId = data.shipId
        this.dataForm.pid = data.id
        this.dataForm.type = data.productType
        this.productType = data.productType
web/src/views/modules/taskReliability/ConfigNode/tempNode.vue
New file
@@ -0,0 +1,256 @@
<template>
  <div style="position: absolute;top:6%;right:0;background:#cccccc;width: 300px;" :style="'height:'+ left_p + 'px'">
  <el-card style="height: 100%">
    <el-tabs v-model="activeName" id="tabPane">
      <el-tab-pane label="文本"  name="first">
        <el-row :gutter="5" align="middle" style="margin-top:20px">
          <el-col :span=8 style="font-size: 16px;line-height: 38px">文本大小</el-col>
          <el-col :span=16>
            <el-slider :min=8 :max=20 :step=1 v-model="globalGridAttr.nodeFontSize" @change="onFontSizeChange"></el-slider>
          </el-col>
        </el-row>
        <el-row :gutter="5" align="middle" style="margin-top:20px">
          <el-col :span=8 style="font-size: 16px;line-height: 40px">字体颜色</el-col>
          <el-col :span=16>
            <el-color-picker  v-model="globalGridAttr.nodeColor" style="width: 100%" @change="onColorChange"></el-color-picker>
          </el-col>
        </el-row>
        <el-row v-show="shape!=='custom-text' || shape!=='custom-circle1'" :gutter="5" align="middle" style="margin-top:20px">
          <el-col :span=8 style="font-size: 16px;line-height: 32px">项目名称</el-col>
          <el-col :span=16 >
            <el-input  @click.native='showDialog' v-model="globalGridAttr.inspectName" style="width:100%"></el-input>
          </el-col>
        </el-row>
        <el-row :gutter="5" v-show="shape!=='custom-circle1'"  align="middle" style="margin-top:20px">
          <el-col :span=8 style="font-size: 16px;line-height: 32px">过程名称</el-col>
          <el-col :span=16 >
            <el-input  v-model="globalGridAttr.nodeText" style="width:100%" @change="onTextChange"></el-input>
          </el-col>
        </el-row>
        <el-row v-show="shape!=='custom-text'" :gutter="5" align="middle" style="margin-top:20px">
          <el-col :span=8 style="font-size: 16px;line-height: 32px">日期</el-col>
          <el-col :span=16 >
            <el-date-picker v-model="globalGridAttr.nodeDate" type="date" placeholder="选择日期" value-format="yyyy-MM-dd"
                            style="width: 100%" @change="onDateChange">
            </el-date-picker>
          </el-col>
        </el-row>
      </el-tab-pane>
      <el-tab-pane label="节点"  name="second">
        <el-row align="middle" style="margin-top:20px">
          <el-col :span=8 style="font-size: 16px;line-height: 40px">边框颜色</el-col>
          <el-col :span=16>
            <el-color-picker v-model="globalGridAttr.nodeStroke" style="width: 100%" @change="onStrokeChange"></el-color-picker>
          </el-col>
        </el-row>
        <el-row align="middle"style="margin-top:20px">
          <el-col :span=8 style="font-size: 16px;line-height: 38px">边框宽度</el-col>
          <el-col :span=16>
            <el-slider :min=1 :max=20 :step=1 v-model="globalGridAttr.nodeStrokeWidth" @change="onStrokeWidthChange"></el-slider>
          </el-col>
        </el-row>
        <el-row align="middle" style="margin-top:20px">
          <el-col :span=8 style="font-size: 16px;line-height: 40px">颜色</el-col>
          <el-col :span=16>
            <el-color-picker  v-model="globalGridAttr.nodeFill" style="width: 100%" @change="onFillChange"></el-color-picker>
          </el-col>
        </el-row>
      </el-tab-pane>
    </el-tabs>
  </el-card>
    <el-dialog ref="detailedDialog"  title="选择项目" width='85%' :visible.sync="dialogVisible ">
      <Inspection @func="procResult" ref="inspectionNode" />
    </el-dialog>
  </div>
</template>
<script>
import { Graph, Shape, Node, Addon, Cell,FunctionExt} from '@antv/x6';
import Inspection from './project-list-select'
// const {inject} = require("vue");
export default {
  name: "index",
  data(){
    return{
      data:{
        dataId:'',
        finishDate: '',
        inspectName:''
      },
      date:'',
      text:'',
      dateId:'',
      content:'',
      dialogVisible:false,
      activeName: 'first',
      // globalGridAttr:{},
      curCel:Cell,
      left_p:document.documentElement.clientHeight*0.9,
    }
  },
  components:{
    Inspection
  },
  props:{
    id: {
      type: String,
    },
    shape:{
      type: String
    },
    refY2:{
      type: Number
    },
    globalGridAttr:{
      type: Object,
    },
    graph:{
      type: String,
    },
    projectId:{
      type: String,
    },
    diagramId:{
      type: String,
    }
  },
  watch:{
    'id'(val,oldVal){
      this.curCel = this.nodeOpt(this.id,this.globalGridAttr)
    }
  },
  mounted() {
    // this.curCel = this.nodeOpt(this.id,this.globalGridAttr)
  },
  methods:{
    showDialog() {
      let param = {projectId:this.projectId,diagramId:this.diagramId}
      console.log(param, 'dialog init param')
      this.dialogVisible = true;
      this.$nextTick(()=>{
        this.$refs.inspectionNode.init(param)
      })
    },
    procResult(node) {
      // console.log(node,'node')
      this.text =node.nodeName
      this.dateId = node.nodeId
      this.globalGridAttr.dataId = this.dateId
      this.globalGridAttr.inspectName = this.text
      this.globalGridAttr.nodeText = this.text
      this.data={
        dataId:this.dateId,
        inspectName:this.text
      }
      this.curCel.setData(this.data)
      this.curCel.attr('text/text', this.text)
      this.curCel.attr('data/dataId', this.dateId)
      this.curCel.attr('data/inspectName', this.text)
      this.curCel = this.nodeOpt(this.id,this.globalGridAttr)
      this.dialogVisible = false
      // console.log(node,'dialog窗口返回值')
    },
    // 改变边框颜色
    onStrokeChange(e){
      let val = e
      this.globalGridAttr.nodeStroke = val
     this.curCel.attr('body/stroke', val)
    },
    //改变边框大小
    onStrokeWidthChange(e){
      let val =e
      this.globalGridAttr.nodeStrokeWidth = val
      this.curCel.attr('body/strokeWidth', val)
    },
    //改变文本颜色
    onFillChange(e){
      let val = e
      this.globalGridAttr.nodeFill=val
      this.curCel.attr('body/fill', val)
      // this.curCel.attr('title/fill', val)
    },
    // 改变字体大小
    onFontSizeChange(e){
      let val =e
      this.globalGridAttr.nodeFontSize = val
      this.curCel.attr('text/fontSize', val)
      this.curCel.attr('title/fontSize', val)
    },
    // 改变字体颜色
    onColorChange(e){
      let val =e
      this.globalGridAttr.nodeColor = val
      this.curCel.attr('text/fill', val)
      this.curCel.attr('title/fill', val)
      this.curCel.attr('text/style/color', val)
      this.curCel.attr('title/style/color', val)
      this.curCel = this.nodeOpt(this.id,this.globalGridAttr)
    },
    // 改变文本
    onTextChange(e){
      this.text =e
      this.globalGridAttr.nodeText = this.text
      this.curCel.attr('label/textWrap/text', this.text)
      this.curCel = this.nodeOpt(this.id,this.globalGridAttr)
    },
    onDateChange(e){
      this.date =e
       this.globalGridAttr.nodeDate = this.date
       this.data={
        finishDate:this.date,
      }
      this.curCel.setData(this.data)
      if(this.shape=='custom-circle1'){
        this.curCel.attr('text/text', this.date)
      }
      this.curCel.attr('title/text', this.date)
      this.curCel = this.nodeOpt(this.id,this.globalGridAttr)
    },
    nodeOpt(id, globalGridAttr){
      this.curCel=null
      if(id){
        let cell =  this.graph.getCellById(id)
        // console.log(cell,'let cell 123456')
        if (!cell || !cell.isNode()) {
          return
        }
        this.curCel = cell
        globalGridAttr.nodeStroke = cell.attr('body/stroke')
        globalGridAttr.nodeStrokeWidth = cell.attr('body/strokeWidth')
        globalGridAttr.nodeFill = cell.attr('body/fill')
        // globalGridAttr.nodeFontSize = cell.attr('text/fontSize')
        // globalGridAttr.nodeFontSize = cell.attr('title/fontSize')
        globalGridAttr.nodeFontSize = cell.attr('text/fontSize')?cell.attr('text/fontSize'):cell.attr('title/fontSize')
        globalGridAttr.nodeColor = cell.attr('text/fill') ? cell.attr('text/fill'):cell.attr('title/fill')?cell.attr('title/fill'):cell.attr('label/text/fill')
        // globalGridAttr.nodeColor = cell.attr('text/fill')
        // globalGridAttr.nodeColor = cell.attr('title/fill')
        // globalGridAttr.nodeColor = cell.attr('text/style/color')
        // globalGridAttr.nodeColor =  cell.attr('title/style/color')
        globalGridAttr.nodeUsers = cell.attr('approve/users')
        globalGridAttr.nodeText = cell.attr('label/textWrap/text')
        console.log(globalGridAttr.nodeText,'globalGridAttr.nodeText')
        if(this.shape=='custom-circle1'){
          globalGridAttr.nodeDate = cell.attr('text/text')
        }
        globalGridAttr.nodeDate = cell.attr('title/text')
        globalGridAttr.dataId = cell.getData().dataId
        globalGridAttr.inspectName =cell.getData().inspectName
        // console.log(globalGridAttr.inspectName,globalGridAttr.dataId,globalGridAttr.nodeDate,'globalGridAttr.inspectName,globalGridAttr.dataId,globalGridAttr.nodeDate 789')
        cell.getData()
        // console.log( cell.getData(),' cell.getData() 909')
      }
      return this.curCel;
    }
  }
}
</script>
<style >
#tabPane .el-tabs__header.is-top .el-tabs__nav-scroll{
width: 100% !important;
}
#tabPane .el-color-picker__trigger{
  width: 100%;
}
</style>
web/src/views/modules/taskReliability/ModelLine-AddOrUpdate.vue
File was deleted
web/src/views/modules/taskReliability/ModelLine.vue
File was deleted
web/src/views/modules/taskReliability/ModelRbd.vue
@@ -3,7 +3,7 @@
    <el-row :gutter="5">
      <el-col :span="5">
        <div class="fa-card-a" style="margin-right: 5px;height: calc(100vh - 123px)">
          <product-model-tree @on-selected="onProductSelected" @on-default="onDefault" showXdy="true" :isShow="false"/>
          <product-model-tree ref="ProductModelTree" @on-selected="onProductSelected" @on-default="onDefault" showXdy="true" :isShow="false"/>
        </div>
      </el-col>
      <el-col :span="19">
@@ -72,7 +72,7 @@
      }
    },
    mounted() {
      this.$refs.ProductModelTree.getProductList()
    },
    components: {
      ProductModelTree,
web/src/views/modules/taskReliability/ModelView.vue
New file
@@ -0,0 +1,2009 @@
<template>
  <div>
        <div class="fa-card-a">
          <div id="containerImg" style="border: 1px solid #EAEBEE;border-radius: 6px;
        box-shadow: 0 2px 12px 0 rgb(0 0 0 / 10%);height: 100%">
          </div>
          <config-node ref="configNode" v-show="type === 'node'"/>
          <config-edge ref="configEdge" v-show="type === 'edge'"/>
        </div>
  </div>
</template>
<script>
  import {Graph, Shape, Addon, Cell} from '@antv/x6'
  import ConfigNode from './ConfigNode/configNode.vue'
  import ConfigEdge from './ConfigEdge/configEdge.vue'
  import {setHartBeat} from '@/commonJS/common';
  import Cookies from 'js-cookie'
  import {getUUID} from '../../../../packages/utils'
  export default {
    name: 'RBD-edit-img',
    props: {
      projectId: {
        type: String
      },
      diagarmId: {
        type: String
      },
      pageCode: {
        default: 'wlt_pz'
      },
      flowCode: {
        type: String,
        default: 'wltFlow'
      },
    },
    components: {
      ConfigNode,
      ConfigEdge
    },
    computed: {
      RBDDefault() {
        let url = `${window.SITE_CONFIG['apiURL']}/sysPictureBase/getSvgImage?token=${Cookies.get('token')}&id=`
        let result = `
        {
          "cells":
          [
            {
              "position": {
                "x": -600,
                "y": 0
              },
              "size": {
                "width": 60,
                "height": 40
              },
              "attrs": {
                "text": {
                  "refY": "100%",
                  "textVerticalAnchor": "top",
                  "text": "start",
                  "refY2": 4
                },
                "image": {
                  "xlink:href": "${url}10011"
                }
              },
              "visible": true,
              "shape": "image",
              "id": "10000",
              "data": {
                "type": "imageNodes",
                "endNodeId": "20000",
                "dataId": "",
                "nodeType": "start",
                "nodeTypeExt": "",
                "voteNum": ""
              },
              "ports": {
                "groups": {
                  "top": {
                    "position": {
                      "name": "top"
                    },
                    "attrs": {
                      "circle": {
                        "r": 4,
                        "magnet": true,
                        "stroke": "#5F95FF",
                        "strokeWidth": 1,
                        "fill": "#fff",
                        "style": {
                          "visibility": "hidden"
                        }
                      }
                    }
                  },
                  "right": {
                    "position": {
                      "name": "right"
                    },
                    "attrs": {
                      "circle": {
                        "r": 4,
                        "magnet": true,
                        "stroke": "#5F95FF",
                        "strokeWidth": 1,
                        "fill": "#fff",
                        "style": {
                          "visibility": "hidden"
                        }
                      }
                    }
                  },
                  "bottom": {
                    "position": {
                      "name": "bottom"
                    },
                    "attrs": {
                      "circle": {
                        "r": 4,
                        "magnet": true,
                        "stroke": "#5F95FF",
                        "strokeWidth": 1,
                        "fill": "#fff",
                        "style": {
                          "visibility": "hidden"
                        }
                      }
                    }
                  },
                  "left": {
                    "position": {
                      "name": "left"
                    },
                    "attrs": {
                      "circle": {
                        "r": 4,
                        "magnet": true,
                        "stroke": "#5F95FF",
                        "strokeWidth": 1,
                        "fill": "#fff",
                        "style": {
                          "visibility": "hidden"
                        }
                      }
                    }
                  }
                },
                "items": [
                  {
                    "id": "top1",
                    "group": "top"
                  },
                  {
                    "id": "right1",
                    "group": "right"
                  },
                  {
                    "id": "bottom1",
                    "group": "bottom"
                  },
                  {
                    "id": "left1",
                    "group": "left"
                  }
                ]
              },
              "zIndex": 1
            },
            {
              "position": {
                "x": 0,
                "y": 0
              },
              "size": {
                "width": 60,
                "height": 40
              },
              "attrs": {
                "text": {
                  "refY": "100%",
                  "textVerticalAnchor": "top",
                  "text": "dashedBox",
                  "refY2": 4
                },
                "image": {
                  "xlink:href": "${url}10015"
                }
              },
              "visible": true,
              "shape": "image",
              "id": 15000,
              "data": {
                "type": "imageNodes",
                "dataId": "",
                "nodeType": "dashedBox",
                "nodeTypeExt": "",
                "voteNum": ""
              },
              "ports": {
                "groups": {
                  "top": {
                    "position": {
                      "name": "top"
                    },
                    "attrs": {
                      "circle": {
                        "r": 4,
                        "magnet": true,
                        "stroke": "#5F95FF",
                        "strokeWidth": 1,
                        "fill": "#fff",
                        "style": {
                          "visibility": "hidden"
                        }
                      }
                    }
                  },
                  "right": {
                    "position": {
                      "name": "right"
                    },
                    "attrs": {
                      "circle": {
                        "r": 4,
                        "magnet": true,
                        "stroke": "#5F95FF",
                        "strokeWidth": 1,
                        "fill": "#fff",
                        "style": {
                          "visibility": "hidden"
                        }
                      }
                    }
                  },
                  "bottom": {
                    "position": {
                      "name": "bottom"
                    },
                    "attrs": {
                      "circle": {
                        "r": 4,
                        "magnet": true,
                        "stroke": "#5F95FF",
                        "strokeWidth": 1,
                        "fill": "#fff",
                        "style": {
                          "visibility": "hidden"
                        }
                      }
                    }
                  },
                  "left": {
                    "position": {
                      "name": "left"
                    },
                    "attrs": {
                      "circle": {
                        "r": 4,
                        "magnet": true,
                        "stroke": "#5F95FF",
                        "strokeWidth": 1,
                        "fill": "#fff",
                        "style": {
                          "visibility": "hidden"
                        }
                      }
                    }
                  }
                },
                "items": [
                  {
                    "id": "top1",
                    "group": "top"
                  },
                  {
                    "id": "right1",
                    "group": "right"
                  },
                  {
                    "id": "bottom1",
                    "group": "bottom"
                  },
                  {
                    "id": "left1",
                    "group": "left"
                  }
                ]
              },
              "zIndex": 2
            },
            {
              "position": {
                "x": 600,
                "y": 0
              },
              "size": {
                "width": 60,
                "height": 40
              },
              "attrs": {
                "text": {
                  "refY": "100%",
                  "textVerticalAnchor": "top",
                  "text": "end",
                  "refY2": 4
                },
                "image": {
                  "xlink:href": "${url}10012"
                }
              },
              "visible": true,
              "shape": "image",
              "id": "20000",
              "data": {
                "type": "imageNodes",
                "startNodeId": "10000",
                "dataId": "",
                "nodeType": "end",
                "nodeTypeExt": "",
                "voteNum": ""
              },
              "ports": {
                "groups": {
                  "top": {
                    "position": {
                      "name": "top"
                    },
                    "attrs": {
                      "circle": {
                        "r": 4,
                        "magnet": true,
                        "stroke": "#5F95FF",
                        "strokeWidth": 1,
                        "fill": "#fff",
                        "style": {
                          "visibility": "hidden"
                        }
                      }
                    }
                  },
                  "right": {
                    "position": {
                      "name": "right"
                    },
                    "attrs": {
                      "circle": {
                        "r": 4,
                        "magnet": true,
                        "stroke": "#5F95FF",
                        "strokeWidth": 1,
                        "fill": "#fff",
                        "style": {
                          "visibility": "hidden"
                        }
                      }
                    }
                  },
                  "bottom": {
                    "position": {
                      "name": "bottom"
                    },
                    "attrs": {
                      "circle": {
                        "r": 4,
                        "magnet": true,
                        "stroke": "#5F95FF",
                        "strokeWidth": 1,
                        "fill": "#fff",
                        "style": {
                          "visibility": "hidden"
                        }
                      }
                    }
                  },
                  "left": {
                    "position": {
                      "name": "left"
                    },
                    "attrs": {
                      "circle": {
                        "r": 4,
                        "magnet": true,
                        "stroke": "#5F95FF",
                        "strokeWidth": 1,
                        "fill": "#fff",
                        "style": {
                          "visibility": "hidden"
                        }
                      }
                    }
                  }
                },
                "items": [
                  {
                    "id": "top1",
                    "group": "top"
                  },
                  {
                    "id": "right1",
                    "group": "right"
                  },
                  {
                    "id": "bottom1",
                    "group": "bottom"
                  },
                  {
                    "id": "left1",
                    "group": "left"
                  }
                ]
              },
              "zIndex": 3
            },
            {
              "shape": "edge",
              "id": "66c81c68-0827-4a3c-8343-e2c453d3e9e7",
              "router": {
                "name": "manhattan"
              },
              "connector": {
                "name": "rounded"
              },
              "source": {
                "cell": "10000",
                "port": "right1"
              },
              "target": {
                "cell": 15000,
                "port": "left1"
              },
              "zIndex": 4
            },
            {
              "shape": "edge",
              "id": "a0f3cf90-6d37-4ee0-a254-90b4ec2b6a7f",
              "router": {
                "name": "manhattan"
              },
              "connector": {
                "name": "rounded"
              },
              "source": {
                "cell": 15000,
                "port": "right1"
              },
              "target": {
                "cell": "20000",
                "port": "left1"
              },
              "zIndex": 5
            }
          ]
        }
        `
        return JSON.parse(result)
      }
    },
    data() {
      return {
        nodeX:'',
        nodeY:'',
        isFirstLoad: true,
        hasMoveNode: false,
        hasMoveSingleNode: null,
        nodeAdded: false,
        connectNode: {},
        modelId: '',
        modelName: '',
        modelType: '',
        timer: null,
        imagesList: [
          {
            imgPath: 'parallel',
            imgName: 'parallel',
            nodeType: 'parallel',
            imgWidth: 50,
            imgHeight: 50,
            imgId: '9',
            data: {}
          },
          {imgPath: 'vote', imgName: 'vote', nodeType: 'vote', imgWidth: 50, imgHeight: 50, imgId: '6', data: {}},
          {
            imgPath: 'switch',
            imgName: 'switch',
            nodeType: 'switch',
            imgWidth: 50,
            imgHeight: 50,
            imgId: '5',
            data: {}
          },
          {
            imgPath: 'bridgeConnection',
            imgName: 'bridgeConnection',
            nodeType: 'bridgeConnection',
            imgWidth: 50,
            imgHeight: 50,
            imgId: '10',
            data: {}
          },
        ],
        imagesList2: [],
        nodeType: '',
        first: true,
        shape: '',
        projectList: [],
        diagramList: [],
        diagramId: '',
        projectId: '',
        diagramJson: '',
        diagramIdDisabled: false,
        dataForm: {
          id: null,
          pid: null,
          model_tag: '',
          model_name: '',
          product_id: null,
          content: null,
          publishContent: null,
          hasPublish: 0,
          urlPref: '',
          nodeArr: []
        },
        type: '',
        id: '',
        graph: null,
        globalGridAttr: {
          productType: '',
          voteNum: '',
          repairMttcr: '',
          repairMttcrOtherParams2: '',
          repairMttcrOtherParams3: '',
          repairDistribType: '',
          reliabDistribType: '',
          taskMtbcfOtherParams2: '',
          taskMtbcfOtherParams3: '',
          isRepair: 0,
          taskMtbcf: '',
          numberInputValue: '',
          statusImg: '',
          nodeTypeExt: '',
          type: 'mesh',
          size: 10,
          color: '#e5e5e5',
          thickness: 1,
          colorSecond: '#d0d0d0',
          thicknessSecond: 1,
          factor: 4,
          bgColor: '#e5e5e5',
          showImage: true,
          repeat: 'watermark',
          position: 'center',
          bgSize: JSON.stringify({width: 150, height: 150}),
          opacity: 0.1,
          stroke: '#5F95FF',
          strokeWidth: 1,
          connector: 'rounded',
          router: 'manhattan',
          label: '',
          nodeStroke: '#5F95FF',
          nodeStrokeWidth: 1,
          nodeFill: '#ffffff',
          nodeFontSize: 12,
          nodeColor: '#080808',
          nodeText: '',
          nodeDate: '',
          nodeUsers: '',
          nodeDataDate: '',
          nodeDataText: '',
          dataId: '',
          inspectName: '',
          distance: 0.5,
          angle: 0,
        },
        isReady: false,
        curCel: Cell,
        left_p: document.documentElement.clientHeight - 100,
        ports: {
          groups: {
            top: {
              position: {name: 'top'},
              attrs: {
                circle: {
                  r: 4,
                  magnet: true,
                  stroke: '#5F95FF',
                  strokeWidth: 1,
                  fill: '#fff',
                  style: {
                    visibility: 'hidden',
                  },
                },
              },
            },
            right: {
              position: {name: 'right'},
              attrs: {
                circle: {
                  r: 4,
                  magnet: true,
                  stroke: '#5F95FF',
                  strokeWidth: 1,
                  fill: '#fff',
                  style: {
                    visibility: 'hidden',
                  },
                },
              },
            },
            bottom: {
              position: {name: 'bottom'},
              attrs: {
                circle: {
                  r: 4,
                  magnet: true,
                  stroke: '#5F95FF',
                  strokeWidth: 1,
                  fill: '#fff',
                  style: {
                    visibility: 'hidden',
                  },
                },
              },
            },
            left: {
              position: {name: 'left'},
              attrs: {
                circle: {
                  r: 4,
                  magnet: true,
                  stroke: '#5F95FF',
                  strokeWidth: 1,
                  fill: '#fff',
                  style: {
                    visibility: 'hidden',
                  },
                },
              },
            },
          },
          items: [
            {
              id: 'top1',
              group: 'top',
            },
            {
              id: 'right1',
              group: 'right',
            },
            {
              id: 'bottom1',
              group: 'bottom',
            },
            {
              id: 'left1',
              group: 'left',
            },
          ],
        }
      }
    },
    watch: {
      '$route.params.configId'() {
        this.projectId = this.$route.params.projectId
        console.log(this.$route.params.projectId, 'this.$route.params.projectId')
        console.log(this.$route.params.diagramId, 'this.$route.params.diagramId')
      }
    },
    mounted() {
      this.type = 'grid'
    },
    methods: {
      init(row) {
        this.modelName = row.modelName
        this.dataForm.id = row.id
        this.initDigram()
        console.log(this.dataForm, 'init(row){')
      },
      async getDiagram(modelId) {
        this.isFirstLoad = true;
        let params = {
          modelId: modelId,
          urlPref: window.SITE_CONFIG['apiURL'],
          token: Cookies.get('token'),
        }
        let res = await this.$http.get(`/taskReliability/ModelLine/getDiagram`, {params: params})
        this.dataForm = res.data
        if (res.data.content != null) {
          console.log(this.dataForm, 'getDiagram datafrom')
          console.log(res.data, 'getDiagram res.data')
          this.diagramJson = JSON.parse(this.dataForm.content)
          this.graph.fromJSON(this.diagramJson)
          this.isFirstLoad = false;
          console.log(this.diagramJson.cells.length, 'this.diagramJson.cells.length')
          this.graph.positionContent('left')
          // this.graph.centerContent()
          // this.graph.zoomToFit()
        } else {
          this.graph.fromJSON(this.RBDDefault)
          this.isFirstLoad = false
        }
      },
      async clearDiagram() {
        // this.graph.fromJSON(this.emptyJson)
        console.log(this.RBDDefault, 'clearDiagram')
        this.graph.fromJSON(this.RBDDefault)
        this.graph.positionContent('left')
        this.isFirstLoad = false;
      },
      async initDigram() {
        this.timer = setHartBeat(10, 240);
        console.log(document.documentElement.clientWidth, 'document.documentElement.clientWidth')
        console.log(document.documentElement.clientHeight, 'document.documentElement.clientHeight')
        this.graph = new Graph({
          container: document.getElementById('containerImg'),
          width: document.documentElement.clientWidth,
          height: document.documentElement.clientHeight - 200,
          // async: true,
          grid: {
            visible: true,
          },
          autoResize: true,
          history: {
            enabled: true,
            beforeAddCommand(event, args) {
              if (args.key === 'tools') {
                // console.log(args.key, 'event, args')
                return false
              }
            },
          },
          scroller: {
            enabled: true,
            pageVisible: true,
            autoResize: true,
            pageBreak: true,
            pannable: true,
            minVisibleWidth: 200,
            minVisibleHeight: 200,
            modifiers: 'shift',
          },
          mousewheel: {
            enabled: true,
            zoomAtMousePosition: true,
            modifiers: 'ctrl',
            minScale: 0.5,
            maxScale: 3,
          },
          connecting: {
            router: {
              name: 'manhattan',
            },
            connector: {
              name: 'rounded',
              args: {
                radius: 5,
              },
            },
            anchor: 'center',
            connectionPoint: 'anchor',
            allowBlank: false,
            allowLoop:false, // 是否允许创建循环连线,即边的起始节点和终止节点为同一节点,默认为 true
            snap: {
              radius: 20,
            },
            createEdge() {
              return new Shape.Edge({
                attrs: {
                  line: {
                    //  sourceMarker: 'block', // 实心箭头
                    stroke: '#A2B1C3',
                    strokeWidth: 2,
                    targetMarker: null
                  }
                },
                labels: [{
                  attrs: {
                    body: {
                      stroke: '#5F95FF',
                    },
                    text: {
                      text: ''
                    }
                  },
                  position: {
                    distance: 0.5,
                    angle: 180,
                    options: {
                      keepGradient: true,
                      ensureLegibility: true
                    }
                  }
                }],
                tools: {
                  name: 'segments',
                  args: {
                    attrs: {fill: '#666'},
                  },
                },
                zIndex: -100,
              })
            },
            validateConnection({targetMagnet}) {
              return !!targetMagnet
            },
          },
          highlighting: {
            magnetAdsorbed: {
              name: 'stroke',
              args: {
                attrs: {
                  fill: '#5F95FF',
                  stroke: '#5F95FF',
                },
              },
            },
          },
          resizing: true,
          rotating: true,
          selecting: {
            enabled: true,
            rubberband: true,
            rubberEdge: true,
            showNodeSelectionBox: true,
          },
          snapline: true,
          keyboard: true,
          clipboard: true,
        })
        this.graph.centerContent()
        this.graph.bindKey(['meta+c', 'ctrl+c'], () => {
          const cells = this.graph.getSelectedCells()
          if (cells.length) {
            this.graph.copy(cells)
          }
          return false
        })
        this.graph.bindKey(['meta+x', 'ctrl+x'], () => {
          const cells = this.graph.getSelectedCells()
          if (cells.length) {
            this.graph.cut(cells)
          }
          return false
        })
        this.graph.bindKey(['meta+v', 'ctrl+v'], () => {
          if (!this.graph.isClipboardEmpty()) {
            const cells = this.graph.paste({offset: 32})
            this.graph.cleanSelection()
            this.graph.select(cells)
          }
          return false
        })
// select all
        this.graph.bindKey(['meta+a', 'ctrl+a'], () => {
          const nodes = this.graph.getNodes()
          if (nodes) {
            this.graph.select(nodes)
          }
        })
//delete
        this.graph.bindKey('delete', () => {
          this.deleteCompment()
        })
// zoom
        this.graph.bindKey(['ctrl+1', 'meta+1'], () => {
          const zoom = this.graph.zoom()
          if (zoom < 1.5) {
            this.graph.zoom(0.1)
          }
        })
        this.graph.bindKey(['ctrl+2', 'meta+2'], () => {
          const zoom = this.graph.zoom()
          if (zoom > 0.5) {
            this.graph.zoom(-0.1)
          }
        })
        this.graph.on('blank:click', ({cell}) => {
          this.type = 'grid'
        })
        // 监听节点添加事件
        this.graph.on('node:added', ({node}) => {
          if (this.isFirstLoad) {
            return
          }
          if (node.getData().isSelfCreated) {
            return
          }
          const nodeType = node.getData().nodeType; // 获取节点的类型
          const nodeObj = node
          console.log(123)
          let intersectNode = this.findIntersectsNode(node)
          if (intersectNode) { // 当有节点相交 ==>并行
            this.addBranch(intersectNode, nodeObj)
            return
          } else {
            let isSelfCreated = null
            try {
              isSelfCreated = node.getData().isSelfCreated
            } catch (e) {
            }
            if (!isSelfCreated) {
              let intersectEdge = this.findIntersectsEdge(this.graph, node)
              if (intersectEdge) { // 当有边相交 ==>串联
                this.addNodeAndInsertEdge(intersectEdge, nodeObj)
                return
              } else {
                //提示
              }
            }
          }
          node.remove()
        });
        this.graph.on('cell:contextmenu', ({cell}) => {
          // this.type.value = cell.isNode() ? "node" : "edge"
          this.type = cell.isNode() ? 'node' : 'edge'
          /*          this.shape = cell.shape
                    this.id = cell.id*/
          if (this.type === 'node') {
            //this.nodeType = cell.getData().nodeType
            this.$refs.configNode.loadData(cell)
          } else {
            this.$refs.configNode.loadData(cell)
          }
        })
        //单击边节点
        this.graph.on('edge:click', ({edge}) => {
        })
        // 控制连接桩显示/隐藏
        this.graph.on('node:delete', ({view, e}) => {
          e.stopPropagation()
          view.cell.remove()
        })
        this.graph.on('node:customevent', ({name, view, e}) => {
          if (name === 'node:delete') {
            e.stopPropagation()
            view.cell.remove()
          }
        })
        // 双击编辑
        this.graph.on('cell:dblclick', ({cell, e}) => {
          const isNode = cell.isNode()
          const name = cell.isNode() ? 'node-editor' : 'edge-editor'
          cell.removeTool(name)
          cell.addTools({
            name,
            args: {
              event: e,
              attrs: {
                backgroundColor: isNode ? '#EFF4FF' : '#FFF',
                text: {
                  fontSize: 16,
                  fill: '#262626',
                },
              },
            },
          })
        })
        this.graph.on('node:mouseenter', ({node}) => {
          const container = document.getElementById('containerImg')
          const ports = container.querySelectorAll(
            '.x6-port-body',
          )
          this.showPorts(ports, true)
        })
        this.graph.on('node:mouseleave', ({node}) => {
          // if (node.hasTool('button-remove')) {
          //   node.removeTool('button-remove')
          // }
          const container = document.getElementById('containerImg')
          const ports = container.querySelectorAll(
            '.x6-port-body',
          )
          this.showPorts(ports, false)
        })
        this.graph.on('edge:mouseenter', ({cell}) => {
          // alert(123)
          cell.addTools([
            {
              name: 'source-arrowhead',
            },
            {
              name: 'target-arrowhead',
              args: {
                attrs: {
                  fill: 'red',
                },
              },
            },
            {
              name: 'segments',
              args: {snapRadius: 20, attrs: {fill: '#444'}}
            },
          ])
        })
        this.graph.on('edge:mouseleave', ({cell}) => {
          cell.removeTools()
        })
        await this.getDiagram(this.dataForm.id)
      },
      showPorts(ports, show) {
        for (let i = 0, len = ports.length; i < len; i = i + 1) {
          ports[i].style.visibility = show ? 'visible' : 'hidden'
        }
      },
      reset() {
        this.graph.drawBackground({color: '#fff'})
        const nodes = this.graph.getNodes()
        const edges = this.graph.getEdges()
        nodes.forEach((node) => {
          node.attr('body/stroke', '#5F95FF')
        })
        edges.forEach((edge) => {
          edge.attr('line/stroke', '#5F95FF')
          edge.prop('labels/0', {
            attrs: {
              body: {
                stroke: '#5F95FF',
              },
            },
          })
        })
      },
      deleteCompment() {
        const cells = this.graph.getSelectedCells()
        console.log(cells, 'cells')
        if (cells.length === 1) {
          let node = cells[0]
          if (!node.isNode()) {
            this.$confirm('是否删除该连接线?', '提示', {
              confirmButtonText: '确定',
              cancelButtonText: '取消',
              type: 'warning'
            }).then(() => {
              node.remove()
              this.$message({
                type: 'success',
                message: '删除成功!'
              })
            }).catch(() => {
              this.$message({
                type: 'info',
                message: '已取消删除'
              })
            })
            // this.$message({message: '请选中节点', type: 'warning'})
            return false; // 取消操作
          }
          let nodeType = node.getData().nodeType
          let deleteType = 0
          if (nodeType === 'node' || nodeType === 'dashedBox') {
            deleteType = 1
          } else if ('parallel,switch,vote,bridge'.indexOf(nodeType) > -1) {
            deleteType = 2
          }
          let canDelete = false
          if (nodeType === 'start' || nodeType === 'end') {
            this.$message({message: '不允许删除起始和结束节点', type: 'warning'})
            return false; // 取消操作
          }
          if (deleteType > 0) {
            let startNode = null
            if (deleteType === 1) {
              startNode = node
            } else if (deleteType === 2) {
              startNode = this.graph.getCellById(node.getData().startNodeId)
            }
            let isSeriesNode = this.isSeriesNode(startNode, node)
            let isMultipleBrach = this.isMultipleBrach(node)
            if (isSeriesNode) {
              //串联
              let inLine = this.getInLinesOfNode(startNode)
              let outLine = this.getOutLinesOfNode(node)
              let inLineIsToLine = this.hasOtherLineToMyLine(inLine[0].id)
              let inNode = isSeriesNode.inNode
              let outNode = isSeriesNode.outNode
              console.log(inLine, outLine, 'inLine,outLine')
              console.log(inNode, outNode, 'inNode,outNode')
              //提示是否要删除
              this.$confirm('是否删除该节点?', '提示', {
                confirmButtonText: '确定',
                cancelButtonText: '取消',
                type: 'warning'
              }).then(() => {
                if (inLineIsToLine) {
                  inLine[0].target = {cell: outNode.id, port: 'left1'}
                } else {
                  outLine[0].source = {cell: inNode.id, port: 'right1'}
                }
                if (deleteType === 1) {
                  node.remove()
                } else {
                  this.deleteCombination(node)
                }
                this.$message({
                  type: 'success',
                  message: '删除成功!'
                })
              }).catch(() => {
                this.$message({
                  type: 'info',
                  message: '已取消删除'
                })
                return false
              })
            }else if (this.isMultipleBrach(node)) {
              //提示是否要删除
              this.$confirm('是否删除该节点?', '提示', {
                confirmButtonText: '确定',
                cancelButtonText: '取消',
                type: 'warning'
              }).then(() => {
                /*                  if (inLineIsToLine) {
                                    inLine[0].target = {cell: outNode.id, port: 'left1'}
                                  } else {
                                    outLine[0].source = {cell: inNode.id, port: 'right1'}
                                  }*/
                if (deleteType === 1)
                  node.remove()
                else
                  this.deleteCombination(node)
                this.$message({
                  type: 'success',
                  message: '删除成功!'
                })
              }).catch(() => {
                this.$message({
                  type: 'info',
                  message: '已取消删除'
                })
                return false
              })
            }else {
              //提示不能删除
              this.$message({message: '该条线路上只有该节点,无法删除', type: 'warning'})
              return false; // 取消操作
            }
          }
        } else {
          //提示不能删除
          this.$message({message: '只能选中一个节点', type: 'warning'})
          return false; // 取消操作
        }
      },
      async search() {
        await this.getDiagram();
      },
      async saveDiagram() {
        console.log(JSON.stringify(this.graph.toJSON()), 'graph.toJSON()')
        //   获取所有子节点
        this.getNodeArr()
        this.dataForm.content = JSON.stringify(this.graph.toJSON())
        this.dataForm.urlPref = window.SITE_CONFIG['apiURL']
        console.log(this.dataForm, 'dataFrom')
        await this.$http[this.dataForm.id === null ? 'post' : 'put'](`/taskReliability/ModelLine/`, this.dataForm).then(async res => {
          if (res.msg === 'success') {
            this.$emit('refreshDataList')
            this.$alert('保存成功', '提示', {
              confirmButtonText: '确定'
            })
          }
        })
      },
      getNodeArr(){
        const nodes = this.graph.getNodes()
        let nodeArr2 = []
        // 检查除当前节点之外的所有节点的包围框是否相交
        for (const node of nodes) {
          console.log(node, 'saveDiagram node')
          if (node.getData().nodeType == 'node'  && node.getData().dataId) {
            nodeArr2.push(node.getData().dataId)
          }
        }
        this.dataForm.nodeArr = nodeArr2
      },
      async analyzeDiagram() {
        console.log(JSON.stringify(this.graph.toJSON()), 'graph.toJSON()')
        // 检查除当前节点之外的所有节点的包围框是否相交
        //   获取所有子节点
        this.getNodeArr()
        const nodes = this.graph.getNodes()
        for (const node of nodes) {
          if(node.getData().nodeType === 'dashedBox'){
            this.$message({message: '该模型中存在虚框,无法保存', type: 'warning'})
            return false; // 取消添加节点操作
          }
          if(node.getData().nodeType === 'vote'){
            const edges = this.graph.getConnectedEdges(node);
            if(node.getData().voteNum>=edges.length){
              this.$message({message: '表决数量不能高于该节点的进线数量', type: 'warning'})
              return false; // 取消添加节点操作
            }
          }
        }
        this.dataForm.content = JSON.stringify(this.graph.toJSON())
        this.dataForm.urlPref = window.SITE_CONFIG['apiURL']
        await this.$http['post'](`/taskReliability/ModelLine/analyze`, this.dataForm).then(async res => {
          if (res.msg === 'success') {
            this.$emit('refreshDataList')
            this.$alert('解析成功', '提示', {
              confirmButtonText: '确定'
            })
          }
        })
      },
      leftAlign() {
        const NODE = this.graph.getSelectedCells()
        let leftX = null
        for (let a of NODE) {
          if (leftX == null || a.getBBox().x < leftX) {
            leftX = a.getBBox().x
          }
        }
        for (let a of NODE) {
          let y = a.getBBox().y
          a.position(leftX, y)
          // console.log(leftX, ':', y, '  x:y')
        }
      },
      topAlign() {
        const NODE = this.graph.getSelectedCells()
        let topY = null
        for (let a of NODE) {
          console.log(a.getBBox(), 'a.getBBox()')
          if (topY == null || a.getBBox().y < topY) {
            topY = a.getBBox().y
          }
        }
        for (let a of NODE) {
          let x = a.getBBox().x
          a.position(x, topY)
        }
      },
      centerAlign() {
        const NODE = this.graph.getSelectedCells()
        let rightX = null
        let leftX = null
        for (let a of NODE) {
          if (leftX == null || a.getBBox().x < leftX) {
            leftX = a.getBBox().x
          }
        }
        for (let a of NODE) {
          if (rightX == null || a.getBBox().x + a.getBBox().width > rightX) {
            rightX = a.getBBox().x + a.getBBox().width
          }
        }
        let centerX = leftX + (rightX - leftX) / 2
        for (let a of NODE) {
          let y = a.getBBox().y
          a.position(centerX - a.getBBox().width / 2, y)
        }
      },
      shuipingAlign() {
        const NODE = this.graph.getSelectedCells()
        let bottomY = null
        let topY = null
        for (let a of NODE) {
          if (topY == null || a.getBBox().y || 0 < topY) {
            topY = a.getBBox().y
          }
        }
        for (let a of NODE) {
          if (bottomY == null || a.getBBox().y + a.getBBox().height > bottomY) {
            bottomY = a.getBBox().y + a.getBBox().height
          }
        }
        let centerY = topY + (bottomY - topY) / 2
        for (let a of NODE) {
          let x = a.getBBox().x
          let centerHei = a.getBBox().height / 2
          a.position(x, centerY - centerHei)
        }
      },
      rightAlign() {
        const NODE = this.graph.getSelectedCells()
        let rightX = null
        for (let a of NODE) {
          if (rightX == null || a.getBBox().x + a.getBBox().width > rightX) {
            rightX = a.getBBox().x + a.getBBox().width
          }
        }
        for (let a of NODE) {
          let y = a.getBBox().y
          a.position(rightX - a.getBBox().width, y)
        }
      },
      bottomAlign() {
        const NODE = this.graph.getSelectedCells()
        let bottomY = null
        for (let a of NODE) {
          if (bottomY == null || (a.getBBox().y + a.getBBox().height) > bottomY) {
            bottomY = a.getBBox().y + a.getBBox().height
          }
        }
        for (let a of NODE) {
          let x = a.getBBox().x
          a.position(x, bottomY - a.getBBox().height)
        }
      },
      close() {
        if (this.timer) {
          window.clearInterval(this.timer)
        }
      },
      // 定义函数来检查两个包围框是否相交
      findIntersectsNode(node) {
        const nodes = this.graph.getNodes()
        let intersectNodes = []
        const bbox1 = node.getBBox();
        // 检查除当前节点之外的所有节点的包围框是否相交
        for (const otherNode of nodes) {
          if (otherNode === node) continue;
          let nodeType = otherNode.getData().nodeType
          if (nodeType === "parallel" || nodeType === "switch" || nodeType === "vote" || nodeType === "dashedBox") {
            const bbox2 = otherNode.getBBox();
            if (bbox1.x < bbox2.x + bbox2.width &&
              bbox1.x + bbox1.width > bbox2.x &&
              bbox1.y < bbox2.y + bbox2.height &&
              bbox1.y + bbox1.height > bbox2.y) {
              intersectNodes.push(otherNode);
            }
          }
        }
        if (intersectNodes.length === 1) {
          //console.log('Intersecting nodes:', intersectNodes.map(n => n)); // 相交节点的对象
          return intersectNodes[0]
        } else {
          //提示用户只能拖到一个有效的节点上
          return null
        }
      },
      // 相交的节点
      addBranch(graphNode, dragNode) { // graphCell是画布上原有的节点。dragNode是当前拖拽的节点
        let graphNodeType = graphNode.getData().nodeType
        let dragNodeType = dragNode.getData().nodeType
        let offHeight = 50
        if (dragNodeType === 'node') {
          offHeight = 60
        } else if (dragNodeType === 'bridgeConnection') {
          offHeight = 175
        } else {
          offHeight = 70
        }
        let centerX = 0, centerY = 0;
        if (graphNodeType === 'dashedBox') { //虚框
          const edges = this.graph.getConnectedEdges(graphNode); // 获取画布上原有的节点所有进来的线
          let inEdges = edges.filter(edge => edge.target.cell === graphNode.id)
          let startNode = null
          let endNode = null
          if (inEdges.length === 1) {
            let startNodeId = inEdges[0].source.cell
            startNode = this.graph.getCellById(startNodeId)
          }
          let outEdges = edges.filter(edge => edge.source.cell === graphNode.id)
          if (outEdges.length === 1) {
            let endNodeId = outEdges[0].target.cell
            endNode = this.graph.getCellById(endNodeId)
          }
          if (startNode && endNode) {
            centerX = graphNode.position().x + graphNode.getBBox().width / 2
            centerY = graphNode.position().y + graphNode.getBBox().height / 2
            let result = this.addNodeAndConnect(graphNode, dragNode, centerX, centerY)
            if (!result) {
              dragNode.remove()
              this.$message({message: '没有足够的空间放置该节点,请扩大剩余空间', type: 'warning'})
              return
            }
            let startPort = 'right1'
            let endPort = 'left1'
            if ((inEdges[0].target.port == 'top1' || outEdges[0].source.port == 'bottom1') && ('parallel,switch,vote,bridge'.indexOf(dragNodeType)) == -1) {
              startPort = 'bottom1'
              endPort = 'top1'
            }
            inEdges[0].target = {cell: result.newStartNode.id, port: endPort}
            outEdges[0].source = {cell: result.newEndNode.id, port: startPort}
            graphNode.remove()
          }
        } else { //并行结构
          const graphNodeStartNodeId = graphNode.getData().startNodeId  // 获取画布上原有节点的开始ID
          const graphNodeStartNode = this.graph.getCellById(graphNodeStartNodeId) // 通过开始ID得到初始节点对象
          let graphNodeY = graphNode.position().y - graphNode.getBBox().height / 2 // 获取画布原有节点的y坐标
          let minY = graphNode.position().y
          let maxY = graphNode.position().y + graphNode.getBBox().height
          const edges = this.graph.getConnectedEdges(graphNode); // 获取画布上原有的节点所有进来的线
          // 获取连接线的路径数据
          let inEdges = edges.filter(edge => edge.target.cell === graphNode.id)
          //遍历这个组合里面所有节点, 修改minY,maxY
          let pointXY = {minY: minY, maxY: maxY}
          console.log(pointXY, 'old')
          this.getYRange(inEdges, graphNodeStartNode, pointXY)
          console.log(pointXY, 'new')
          let minX = graphNodeStartNode.position().x + graphNode.getBBox().width + 15
          let maxX = graphNode.position().x
          let centerX = minX + (maxX - minX) / 2
          let centerY = graphNodeY + graphNode.getBBox().height / 2 - pointXY.minY > pointXY.maxY - (graphNodeY + graphNode.getBBox().height / 2) ?
            pointXY.maxY + offHeight / 2 + 30 : pointXY.minY - offHeight / 2 - 30
          let result = this.addNodeAndConnect(null, dragNode, minX, centerY)
          if (!result) {
            dragNode.remove()
            this.$message({message: '没有足够的空间放置该节点,请扩大剩余空间', type: 'warning'})
            return
          }
          this.graph.addEdge({
            source: {cell: graphNodeStartNode, port: 'right1'},
            target: {cell: result.newStartNode, port: 'left1'},
            router: {name: 'manhattan'},
            connector: {name: 'rounded'}
          })
          this.graph.addEdge({
            source: {cell: result.newEndNode, port: 'right1'},
            target: {cell: graphNode, port: 'left1'},
            router: {name: 'manhattan'},
            connector: {name: 'rounded'}
          })
        }
      },
      addNodeAndConnect(targetNode, dragNode, centerX, centerY) { // graphCell是画布上原有的节点。dragNode是当前拖拽的节点
        let width = 100,
          height = 80,
          leftTopX = centerX,
          leftTopY = centerY
        let dragNodeType = dragNode.getData().nodeType
        if (dragNodeType === 'node') {
          width = 60
          height = 60
        } else if (dragNodeType === 'dashedBox') {
          width = 60
          height = 40
        } else if (dragNodeType === 'bridgeConnection') {
          width = 550
          height = 175
        } else {
          width = 270
          height = 60
        }
        leftTopX = centerX - width / 2
        leftTopY = centerY - height / 2
        if (!this.canPlace(targetNode, dragNode, {leftTopX, leftTopY, width, height})) {
          return false
        }
        if (dragNodeType === 'node' || dragNodeType === 'dashedBox') {
          dragNode.position(leftTopX, leftTopY)
          return {newStartNode: dragNode, newEndNode: dragNode}
        } else if (dragNodeType === 'bridgeConnection') {
          return this.createBridgeConnection(leftTopX, leftTopY, dragNode)
        } else {
          return this.createParallelBrach(leftTopX, centerY, dragNode)
        }
      },
      // 相交的边
      addNodeAndInsertEdge(graphEdge, dragNode) {
        const source = graphEdge.getSourceCell()
        const target = graphEdge.getTargetCell()
        let centerX = 0
        let centerY = 0
        if (!source.isNode() || !target.isNode()) {
          if (source.isNode()) {
            centerX = source.position().x + source.getBBox().width / 2
            centerY = dragNode.position().y + dragNode.getBBox().height / 2
          } else {
            centerX = target.position().x + target.getBBox().width / 2
            centerY = dragNode.position().y + dragNode.getBBox().height / 2
          }
        } else {
          centerX = dragNode.position().x + dragNode.getBBox().width / 2
          centerY = source.position().y + source.getBBox().height / 2
          if (target.getData().nodeType === 'node') {
            centerY = target.position().y + target.getBBox().height / 2
          }
        }
        let startNodeId = graphEdge.source.cell
        let startNode = this.graph.getCellById(startNodeId)
        let endNodeId = graphEdge.target.cell
        let endNode = this.graph.getCellById(endNodeId)
        if (startNode && endNode) {
          let isRight = true;
          let startPort = 'right1'
          let endPort = 'left1'
          if (this.isTopBottom(graphEdge)) {
            startPort = 'bottom1'
            endPort = 'top1'
          }
          if (this.hasOtherLineToMyLine(graphEdge.id)) {
            let leftX = startNode.position().x + startNode.getBBox().width
            let rightX = endNode.position().x
            // let centerX = dragNode.position().x + dragNode.getBBox().width / 2
            if (centerX - leftX < rightX - centerX) {
              isRight = false
            }
          }
          let result = this.addNodeAndConnect(null, dragNode, centerX, centerY)
          if (!result) {
            dragNode.remove()
            this.$message({message: '没有足够的空间放置该节点,请扩大剩余空间', type: 'warning'})
            return
          }
          if (isRight) {
            graphEdge.target = {cell: result.newStartNode.id, port: endPort}
            this.graph.addEdge({
              source: {cell: result.newEndNode, port: startPort},
              target: {cell: endNode, port: endPort},
              router: {name: 'manhattan'},
              connector: {name: 'rounded'}
            })
          } else {
            this.graph.addEdge({
              source: {cell: startNode, port: startPort},
              target: {cell: result.newStartNode, port: endPort},
              router: {name: 'manhattan'},
              connector: {name: 'rounded'}
            })
            graphEdge.source = {cell: result.newEndNode.id, port: startPort}
          }
          // graphEdge.remove()
        }
      },
      findIntersectsEdge(graph, node) {
        const edges = graph.getEdges()
        const bbox = node.getBBox();
        const lines = [bbox.leftLine, bbox.rightLine, bbox.topLine, bbox.bottomLine];
        let res = [];
        edges.forEach((edge) => {
          const view = graph.findViewByCell(edge);
          lines.forEach((line) => {
            if (view) {
              if (view.path.intersectsWithLine(line)) {
                res.push(edge);
              }
            }
          })
        })
        const uniqueArr = res.filter((insEdge, index) =>
          res.findIndex(i => i.id === insEdge.id) === index);
        console.log(uniqueArr, 'uniqueArr')
        if (uniqueArr.length === 1) {
          return uniqueArr[0]
        } else {
          return false
        }
      },
      createParallelBrach(x, y, dragNode) {
        dragNode.position(x + 320, y - dragNode.size().height / 2)
        const connectNode = this.createConnectNode(x + 50, y)
        const dashedBox = this.createDashedBox(x + 150, y)
        dragNode.setData({startNodeId: connectNode.id})
        this.graph.addEdge({
          source: {cell: connectNode, port: 'right1'},
          target: {cell: dashedBox, port: 'left1'},
          router: {name: 'manhattan'},
          connector: {name: 'rounded'}
        })
        this.graph.addEdge({
          source: {cell: dashedBox, port: 'right1'},
          target: {cell: dragNode, port: 'left1'},
          router: {name: 'manhattan'},
          connector: {name: 'rounded'}
        })
        return {newStartNode: connectNode, newEndNode: dragNode}
        /*        this.graph.addEdge({
                  source: {cell: startNode, port: 'right1'},
                  target: {cell: connectNode, port: 'left1'},
                  router: {name: 'manhattan'},
                  connector: {name: 'rounded'}
                })
                this.graph.addEdge({
                  source: {cell: dragNode, port: 'right1'},
                  target: {cell: endNode, port: 'left1'},
                  router: {name: 'manhattan'},
                  connector: {name: 'rounded'}
                })*/
      },
      createBridgeConnection(x, y, dragNode) {
        console.log(x, y, 'leftX centerY')
        const leftTopDashedBox = this.createDashedBox(x + 40, y)
        const rightTopDashedBox = this.createDashedBox(x + 380, y)
        const leftConnectNode = this.createConnectNode(x, y + 87)
        const alignCenterDashedBox = this.createDashedBox(x + 209, y + 87)
        const rightConnectNode = this.createBridgeNode(x + 530, y + 87)
        const leftBottomDashedBox = this.createDashedBox(x + 40, y + 160)
        const rightBottomDashedBox = this.createDashedBox(x + 380, y + 160)
        rightConnectNode.setData({startNodeId: leftConnectNode.id})
        leftConnectNode.setData({endNodeId: rightConnectNode.id})
        /*        this.graph.addEdge({
                  source: {cell: startNode, port: 'right1'},
                  target: {cell: leftConnectNode, port: 'left1'},
                  router: {name: 'manhattan'},
                  connector: {name: 'rounded'},
                })
                this.graph.addEdge({
                  source: {cell: rightConnectNode, port: 'right1'},
                  target: {cell: endNode, port: 'left1'},
                  router: {name: 'manhattan'},
                  connector: {name: 'rounded'}
                })*/
        this.graph.addEdge({
          source: {cell: leftConnectNode, port: 'right1'},
          target: {cell: leftTopDashedBox, port: 'left1'},
          router: {name: 'manhattan'},
          connector: {name: 'rounded'},
        })
        this.graph.addEdge({
          source: {cell: leftConnectNode, port: 'right1'},
          target: {cell: leftBottomDashedBox, port: 'left1'},
          router: {name: 'manhattan'},
          connector: {name: 'rounded'},
        })
        let edgeTop = this.graph.addEdge({
          source: {cell: leftTopDashedBox, port: 'right1'},
          target: {cell: rightTopDashedBox, port: 'left1'},
          router: {name: 'manhattan'},
          connector: {name: 'rounded'},
        })
        let edgeBottom = this.graph.addEdge({
          source: {cell: leftBottomDashedBox, port: 'right1'},
          target: {cell: rightBottomDashedBox, port: 'left1'},
          router: {name: 'manhattan'},
          connector: {name: 'rounded'},
        })
        this.graph.addEdge({
          source: {cell: rightTopDashedBox, port: 'right1'},
          target: {cell: rightConnectNode, port: 'left1'},
          router: {name: 'manhattan'},
          connector: {name: 'rounded'},
        })
        this.graph.addEdge({
          source: {cell: rightBottomDashedBox, port: 'right1'},
          target: {cell: rightConnectNode, port: 'left1'},
          router: {name: 'manhattan'},
          connector: {name: 'rounded'},
        })
        this.graph.addEdge({
          source: {cell: edgeTop},
          target: {cell: alignCenterDashedBox, port: 'top1'},
          router: {name: 'manhattan'},
          connector: {name: 'rounded'},
        })
        this.graph.addEdge({
          source: {cell: alignCenterDashedBox, port: 'bottom1'},
          target: {cell: edgeBottom},
          router: {name: 'manhattan'},
          connector: {name: 'rounded'},
        })
        dragNode.remove()
        return {newStartNode: leftConnectNode, newEndNode: rightConnectNode}
      },
      createDashedBox(x, y) {
        const dashId = getUUID().toString()
        let dashedBox = this.graph.addNode({
          shape: 'image',
          // imageUrl: require('/public/modelImg/' + item.imgPath + '.png'),
          width: 60,
          height: 40,
          id: dashId,
          data: {
            isSelfCreated: true,
            type: 'imageNodes',
            dataId: '',
            nodeType: 'dashedBox',
            nodeTypeExt: '',
            voteNum: ''
          },
          attrs: {
            image: {
              'xlink:href': '/modelImg/dashedBox.svg',
            },
            text: {
              text: 'dashedBox',
              fontSize: 14,
              refX: 0.5,
              refY: '100%',
              refY2: 4,
              textAnchor: 'middle',
              textVerticalAnchor: 'top',
            },
          },
          ports: {...this.ports},
        })
        dashedBox.position(x, y - dashedBox.size().height / 2)
        return dashedBox
      },
      createConnectNode(x, y) {
        const connectId = getUUID().toString()
        const dragNodeId = getUUID().toString()
        let connectNode = this.graph.addNode({
          shape: 'image',
          width: 10,
          height: 10,
          id: connectId,
          data: {
            isSelfCreated: true,
            type: 'imageNodes',
            endNodeId: dragNodeId,
            dataId: '',
            nodeType: 'connect',
            nodeTypeExt: '',
            voteNum: ''
          },
          attrs: {
            image: {
              'xlink:href': '/modelImg/connect.svg',
            },
            text: {
              text: 'connect',
              fontSize: 14,
              refX: 0.5,
              refY: '100%',
              refY2: 4,
              textAnchor: 'middle',
              textVerticalAnchor: 'top',
            },
          },
          ports: {...this.ports},
        })
        connectNode.position(x, y - connectNode.size().height / 2)
        return connectNode
      },
      createBridgeNode(x, y) {
        const connectId = getUUID().toString()
        const dragNodeId = getUUID().toString()
        let bridgeNode = this.graph.addNode({
          shape: 'image',
          width: 30,
          height: 30,
          id: connectId,
          data: {
            isSelfCreated: true,
            type: 'imageNodes',
            endNodeId: dragNodeId,
            dataId: '',
            nodeType: 'bridge',
            nodeTypeExt: '',
            voteNum: ''
          },
          attrs: {
            image: {
              'xlink:href': '/modelImg/connect.svg',
            },
            text: {
              text: 'bridge',
              fontSize: 14,
              refX: 0.5,
              refY: '100%',
              refY2: 4,
              textAnchor: 'middle',
              textVerticalAnchor: 'top',
            },
          },
          ports: {...this.ports},
        })
        bridgeNode.position(x, y - bridgeNode.size().height / 2)
        return bridgeNode
      },
      getYRange(inEdges, startNode, pointXY) {
        for (let inEdge of inEdges) {
          let nodeId = inEdge.source.cell
          let node = this.graph.getCellById(nodeId)
          if (node.position().y < pointXY.minY) {
            pointXY.minY = node.position().y
          }
          if (node.position().y + node.getBBox().height > pointXY.maxY) {
            pointXY.maxY = node.position().y + node.getBBox().height
          }
          if (node.id === startNode.id) {
            continue
          }
          const edges = this.graph.getConnectedEdges(node); // 获取画布上原有的节点所有进来的线
          let inEdgesPrev = edges.filter(edge => edge.target.cell === node.id)
          this.getYRange(inEdgesPrev, startNode, pointXY)
        }
      },
      isSeriesNode(startNode, endNode) {
        let result = false
        let inNode = null
        let outNode = null
        let inEdges = this.getInLinesOfNode(startNode)
        console.log(inEdges, 'inEdges')
        if (inEdges.length === 1) {
          let isMyLineToOtherLine = this.isMyLineToOtherLine(inEdges[0])
          let hasOtherLineToMyLine = this.hasOtherLineToMyLine(inEdges[0].id)
          let inNodeId = inEdges[0].source.cell
          inNode = this.graph.getCellById(inNodeId)
          if (!isMyLineToOtherLine && !hasOtherLineToMyLine) {
            let inNodeType = inNode.getData().nodeType
            console.log(inNodeType, 'inNodeType')
            if ('node,dashedBox,parallel,switch,vote,bridge'.indexOf(inNodeType) > -1) {
              result = true
            }
          }
        }
        let outEdges = this.getOutLinesOfNode(endNode)
        console.log(outEdges, 'outEdges')
        if (outEdges.length === 1) {
          let isMyLineToOtherLine = this.isMyLineToOtherLine(outEdges[0])
          let hasOtherLineToMyLine = this.hasOtherLineToMyLine(outEdges[0].id)
          let outNodeId = outEdges[0].target.cell
          outNode = this.graph.getCellById(outNodeId)
          if (!isMyLineToOtherLine && !hasOtherLineToMyLine) {
            let outNodeType = outNode.getData().nodeType
            if ('node,connect,dashedBox'.indexOf(outNodeType) > -1) {
              result = true
            }
          }
        }
        console.log(result, 'result')
        if (result && inNode && outNode) {
          console.log(inNode, outNode, 'inNode, outNode')
          return {inNode, outNode}
        } else {
          return false
        }
      },
      hasOtherLineToMyLine(edgeId) {
        for (let edge of this.graph.getEdges()) {
          if (edge.source.cell === edgeId || edge.target.cell === edgeId)
            return true
        }
        return false
      },
      isMyLineToOtherLine(myEdge) {
        for (let edge of this.graph.getEdges()) {
          if (myEdge.source.cell === edge.id || myEdge.target.cell === edge.id)
            return true
        }
        return false
      },
      isTopBottom(edge) {
        if (edge.source.port === 'top1' || edge.source.port === 'bottom1' || edge.target.port === 'top1' || edge.target.port === 'bottom1') {
          return true
        }
      },
      isMultipleBrach(node) {
        let outEdges = this.getOutLinesOfNode(node)
        let outNodeId = outEdges[0].target.cell
        if (this.isTopBottom(outEdges[0]))
          return false
        let outNode = this.graph.getCellById(outNodeId)
        if ('bridge,end'.indexOf(outNode.getData().nodeType) > -1) {
          return false
        }
        let inEdges = this.getInLinesOfNode(outNode)
        return inEdges.length > 1;
      },
      deleteCombination(node) {
        let startNode = this.graph.getCellById(node.getData().startNodeId)
        let allCombinationNodes = []
        console.log(startNode, 'startNode')
        this.getAllCombinationNodes(startNode.id, node, allCombinationNodes)
        console.log(allCombinationNodes, 'allCombinationNodes')
        this.graph.removeCells(allCombinationNodes)
      },
      getAllCombinationNodes(startNodeId, node, allCombinationNodes) {
        allCombinationNodes.push(node)
        if (node.id == startNodeId || node.isEdge()) {
          return
        }
        let inEdges = this.getInLinesOfNode(node) // 如果???
        for (let inEdge of inEdges) {
          let lineNode = this.getNodeOfConectLine(inEdge)
          if (lineNode) {
            this.getAllCombinationNodes(startNodeId, lineNode, allCombinationNodes)
          }
          let inNodeId = inEdge.source.cell
          let inNode = this.graph.getCellById(inNodeId)
          if (inNode.isEdge())
            continue
          this.getAllCombinationNodes(startNodeId, inNode, allCombinationNodes)
        }
      },
      getNodeOfConectLine(paramEdge) {
        for (let edge of this.graph.getEdges()) {
          let nodeId = null
          /*          if (edge.source.cell === paramEdge.id){
                      nodeId = edge.target.cell
                    }*/
          if (edge.target.cell === paramEdge.id) {
            nodeId = edge.source.cell
          }
          if (nodeId) {
            let node = this.graph.getCellById(nodeId)
            if (node.isNode())
              return node
          }
        }
        return null
      },
      getInLinesOfNode(node) {
        const edges = this.graph.getConnectedEdges(node); // 获取画布上原有的节点所有进来的线
        console.log(edges, '获取画布上开始节点所有的线 edges')
        return edges.filter(edge => edge.target.cell === node.id)
      },
      getOutLinesOfNode(node) {
        console.log(node, '获取画布上的结束节点 node')
        const edges = this.graph.getConnectedEdges(node); // 获取画布上原有的节点所有进来的线
        console.log(edges, '获取画布上的结束节点所有的线 edges')
        return edges.filter(edge => edge.source.cell === node.id)
      },
      canPlace(targetNode, dragNode, box2) {
        const nodes = this.graph.getNodes()
        let intersectNodes = []
        // 检查除当前节点之外的所有节点的包围框是否相交
        for (const otherNode of nodes) {
          if (otherNode === dragNode || otherNode === targetNode) continue;
          const bbox1 = otherNode.getBBox();
          if (bbox1.x < box2.leftTopX + box2.width &&
            bbox1.x + bbox1.width > box2.leftTopX &&
            bbox1.y < box2.leftTopY + box2.height &&
            bbox1.y + bbox1.height > box2.leftTopY) {
            intersectNodes.push(otherNode);
          }
        }
        console.log(box2, 'box2')
        console.log(intersectNodes, 'intersectNodes')
        return intersectNodes.length <= 0;
      },
      undo() {
        if (this.graph.history.canUndo()) {
          this.graph.history.undo()
        }
      },
      redo() {
        if (this.graph.history.canRedo()) {
          this.graph.history.redo()
        }
      }
    },
  }
</script>
<style>
  #containerImg {
    display: flex;
    border: 1px solid #dfe3e8;
    height: 400px;
    width: 100% !important;
  }
  .x6-graph-scroller.x6-graph-scroller-pannable {
    width: 100% !important;
  }
  /*#stencilImg {*/
  /*  width: 100%;*/
  /*  height: 100%;*/
  /*  position: relative;*/
  /*  border-right: 1px solid #dfe3e8;*/
  /*}*/
  .x6-widget-stencil {
    position: relative;
    height: 100%;
  }
  #stencilImg .x6-graph-svg-viewport {
    height: 100%;
  }
  .x6-widget-stencil-content {
    position: relative;
    height: calc(100% - 32px);
  }
  #stencilImg .x6-widget-stencil.collapsable > .x6-widget-stencil-content {
    top: 0
  }
</style>
web/src/views/modules/taskReliability/OperatConditModel.vue
@@ -146,7 +146,7 @@
        this.dialogVisible2 = true
        let param = {
          id: row.modelId,
          model: row.modelName,
          modelName: row.modelName,
          productId: row.productId
        }
        this.$nextTick(() => {
web/src/views/modules/taskReliability/SimulatAssess.vue
@@ -28,7 +28,7 @@
          <el-col :span="4">
            <div style="margin-right: 5px;height: calc(88vh - 100px)" v-if="isSelect">
              <product-model-tree @on-selected="onTreeSelected" showXdy="false"
                                  ref="ProductModelTree" :isShow="false" basic="4"/>
                                  ref="ProductModelTree" :isShow="false" basic="4" :productId="dataForm.productId"/>
            </div>
          </el-col>
          <el-col :span="20">
@@ -102,6 +102,9 @@
        console.log(data, ' onProductSelected(data)')
        this.dataForm.productId = data.id
        this.getTaskList()
        this.$nextTick(() => {
          this.$refs.ProductModelTree.getProductList()
        })
      },
      onTaskSelected(data) {
        console.log(data, ' onProductSelected(data)')
web/src/views/modules/taskReliability/SimulatCurve.vue
@@ -23,6 +23,7 @@
    components: {},
    methods: {
      async initEcharts(Param) {
        console.log(Param)
        let res = await this.$http.post(`/taskReliability/SimulatAssess/getResultXML`, Param)
        console.log(res.data)
        if (res.data) {
web/src/views/modules/taskReliability/SimulatHistory.vue
@@ -25,7 +25,7 @@
          <el-col :span="4">
            <div style="margin-right: 5px;height: calc(88vh - 100px)" v-if="isSelect">
              <product-model-tree @on-selected="onTreeSelected" showXdy="false"
                                  ref="ProductModelTree" :isShow="false" basic="4"/>
                                  ref="ProductModelTree" :isShow="false" basic="4" :productId="dataForm.productId"/>
            </div>
          </el-col>
          <el-col :span="20">
@@ -113,6 +113,9 @@
        this.dataForm.productId = data.id
        this.getTaskList()
        this.dataForm.taskModelId = ''
        this.$nextTick(() => {
          this.$refs.ProductModelTree.getProductList()
        })
      },
      onTaskSelected(data) {
        console.log(data, ' onProductSelected(data)')
@@ -120,22 +123,21 @@
        this.getSimulatList()
        this.dataForm.id = ''
      },
      onSimulatSelected(data) {
      async onSimulatSelected(data) {
        this.dataForm.id = data.id
        this.dataForm.samplPeriod = data.samplPeriod
        this.getSimulatParams()
        this.$refs.SimulatCurve.initEcharts(this.dataForm)
      },
      async getSimulatParams() {
        let params = {
          id: this.dataForm.id,
          taskModelId: this.dataForm.taskModelId
        }
        let res = await this.$http.get('/taskReliability/SimulatAssess/getSimulatParams', {params: params})
        console.log(res.data.samplPeriod)
        this.dataForm.taskDuration = res.data.taskDuration
        this.dataForm.samplPeriod = res.data.samplPeriod
        this.dataForm.simulatFrequency = res.data.simulatFrequency
      }
        this.$nextTick(() => {
          this.$refs.SimulatCurve.initEcharts(this.dataForm)
        })
      },
    }
  }
</script>
web/src/views/modules/taskReliability/TimeDiagram.vue
@@ -12,36 +12,54 @@
          <zt-form-item label="仿真记录" prop="simulatHis">
            <zt-select v-model="dataForm.id" :datas="simulatList" @change="onSimulatSelected"/>
          </zt-form-item>
          <zt-form-item label="采样周期" prop="samplPeriod">
            <el-input v-model="dataForm.samplPeriod" readonly="false">
            </el-input>
          </zt-form-item>
          <zt-form-item label="仿真次数" prop="simulatFrequency">
            <el-input v-model="dataForm.simulatFrequency" readonly="false">
            </el-input>
          </zt-form-item>
          <zt-form-item >
            <zt-button @click="getDiagram()">查看时序图</zt-button>
          </zt-form-item>
        </el-form>
        <div>
          <el-col :span="4">
            <div style="margin-right: 5px;height: calc(88vh - 100px)" v-if="isSelect">
              <product-model-tree @on-selected="onTreeSelected" showXdy="false"
                                  ref="ProductModelTree" :isShow="false" basic="5"/>
              <product-model-tree @on-selected="onTreeSelected"
                                  ref="ProductModelTree" :isShow="false" :productId="dataForm.productId"/>
            </div>
          </el-col>
          <el-col :span="20">
            <div style="margin-top: 20px">
              <div>
                <SimulatCurve ref="SimulatCurve"></SimulatCurve>
              <div id="container" style="border: 1px solid #EAEBEE;border-radius: 6px;
        box-shadow: 0 2px 12px 0 rgb(0 0 0 / 10%);">
              </div>
            </div>
          </el-col>
        </div>
      </div>
    </el-row>
    <el-dialog v-dialogDrag title="模型设计" top="1vh" width='95%' :visible.sync="dialogVisible2" v-if="dialogVisible2">
      <RBDEditImg ref="rbdEditImg"></RBDEditImg>
    </el-dialog>
  </div>
</template>
<script>
  import SimulatCurve from "./SimulatCurve";
  import ProductModelTree from "../basicInfo/ProductModelTree";
  import {Graph, Shape, Addon, Cell} from '@antv/x6'
  import RBDEditImg from './RBD-edit-img'
  export default {
    data() {
      return {
        dialogVisible2: false,
        timers: '',
        shape: '',
        isSelect: false,
        isShow: false,
        productList: [],
@@ -49,6 +67,42 @@
        taskList: [],
        MTBF: '',
        MTTR: '',
        diagramJson: '',
        graph: null,
        globalGridAttr: {
          type: 'mesh',
          size: 10,
          color: '#e5e5e5',
          thickness: 1,
          colorSecond: '#d0d0d0',
          thicknessSecond: 1,
          factor: 4,
          bgColor: '#e5e5e5',
          showImage: true,
          repeat: 'watermark',
          position: 'center',
          bgSize: JSON.stringify({width: 150, height: 150}),
          opacity: 0.1,
          stroke: '#5F95FF',
          strokeWidth: 1,
          connector: 'normal',
          label: '',
          nodeStroke: '#5F95FF',
          nodeStrokeWidth: 1,
          nodeFill: '#ffffff',
          nodeFontSize: 12,
          nodeColor: '#080808',
          nodeText: '',
          nodeDate: '',
          nodeUsers: '',
          nodeDataDate: '',
          nodeDataText: '',
          dataId: '',
          inspectName: '',
          distance: 0.5,
          angle: 0,
        },
        dataForm: {
          id: '',
          pid: '',
@@ -64,13 +118,692 @@
    },
    mounted() {
      this.getProductList()
      this.init()
    },
    components: {
      ProductModelTree,
      SimulatCurve,
    },
    methods: {
      init() {
        console.log(document.documentElement.clientWidth, 'document.documentElement.clientWidth')
        console.log(document.documentElement.clientHeight, 'document.documentElement.clientHeight')
        this.graph = new Graph({
          container: document.getElementById('container'),
          width: document.documentElement.clientWidth,
          height: document.documentElement.clientHeight - 220,
          // async: true,
          grid: {
            visible: true,
          },
          embedding: {
            enabled: true,
            findParent({node}) {
              const bbox = node.getBBox()
              return this.getNodes().filter((node) => {
                // 只有 data.parent 为 true 的节点才是父节点
                const data = node.getData()
                if (data && data.parent) {
                  const targetBBox = node.getBBox()
                  return bbox.isIntersectWithRect(targetBBox)
                }
                return false
              })
            }
          },
          // translating: {
          //   restrict(view) {
          //     const cell = view.cell
          //     if (cell.isNode()) {
          //       const parent = cell.getParent()
          //       if (parent) {
          //         return parent.getBBox()
          //       }
          //     }
          //
          //     return null
          //   },
          // },
          onToolItemCreated({tool}) {
            const handle = tool
            const options = handle.options
            if (options && options.index % 2 === 1) {
              tool.setAttrs({fill: 'red'})
            }
          },
          autoResize: true,
          history: true,
          // panning: {
          //   enabled: true,
          // },
          scroller: {
            enabled: true,
            pageVisible: true,
            pageBreak: true,
            pannable: true,
          },
          mousewheel: {
            enabled: true,
            zoomAtMousePosition: true,
            modifiers: 'ctrl',
            minScale: 0.1,
            maxScale: 10,
          },
          connecting: {
            router: {
              name: 'normal',
              // args: {
              //   padding: 1,
              // },
            },
            connector: {
              name: 'rounded',
              args: {
                radius: 8,
              },
            },
            // anchor: 'center',
            connectionPoint: 'anchor',
            allowBlank: false,
            snap: {
              radius: 20,
            },
            createEdge() {
              return new Shape.Edge({
                attrs: {
                  line: {
                    stroke: '#A2B1C3',
                    strokeWidth: 2,
                    targetMarker: 'classic'
                  }
                },
                tools: {
                  name: 'vertices',
                },
                labels: [{
                  attrs: {
                    body: {
                      stroke: '#5F95FF',
                    },
                    text: {
                      // fontFamily: '仿宋',
                      text: ''
                    }
                  },
                  // position: {
                  //   distance: 0.5,
                  //   angle: 180,
                  //   options: {
                  //     keepGradient: true,
                  //     ensureLegibility: true
                  //   }
                  // }
                }],
                zIndex: 0,
              })
            },
            // validateConnection({targetMagnet}) {
            //   return !!targetMagnet
            // },
          },
          highlighting: {
            magnetAdsorbed: {
              name: 'stroke',
              args: {
                attrs: {
                  fill: '#5F95FF',
                  stroke: '#5F95FF',
                },
              },
            },
          },
          resizing: {
            enabled: true,
            restricted: true
          },
          rotating: true,
          selecting: {
            enabled: true,
            rubberband: true,
            rubberEdge: true,
            showNodeSelectionBox: true,
          },
          snapline: true,
          keyboard: true,
          clipboard: true,
        })
        this.graph.centerContent()
        const stencil = new Addon.Stencil({
          title: '',
          target: this.graph,
          stencilGraphWidth: 260,
          stencilGraphHeight: 700,
          collapsable: false,
          groups: [
            {
              title: '图元',
              name: 'group1',
              collapsable: false
            }
          ],
          layoutOptions: {
            columns: 2,
            columnWidth: 130,
            rowHeight: 100,
          },
        })
        Graph.registerNode(
          'custom-rect',
          {
            inherit: 'rect',
            width: 86,
            height: 26,
            zIndex: 10,
            data: {
              dataId: '',
              finishDate: '',
              inspectName: ''
            },
            attrs: {
              body: {
                strokeWidth: 1,
                stroke: 'none',
                fill: 'none',
              },
              text: {
                // fontFamily: '仿宋',
                fontSize: 20,
                fill: '#000',
              },
              label: {
                refX: 0,
                refY: 0.5,
                textAnchor: 'start',
                textVerticalAnchor: 'middle',
                textWrap: {
                  text: '文字模板',
                  width: -10,      // 宽度减少 10px
                  ellipsis: false,  // 文本超出显示范围时,自动添加省略号
                  breakWord: true, // 是否截断单词
                }
              },
            },
            ports: {...this.ports},
          },
          true,
        )
        Graph.registerNode(
          'custom-polygon',
          {
            inherit: 'polygon',
            width: 86,
            height: 56,
            attrs: {
              body: {
                strokeWidth: 1,
                stroke: '#5F95FF',
                fill: '#EFF4FF',
              },
              // title:{
              //   text:'',
              //   refX: 40,
              //   refY: 38,
              //   fontSize: 20,
              //   fill: '#262626',
              //   'text-anchor': 'start',
              // },
              text: {
                // refX: 40,
                // refY: 20,
                fontSize: 20,
                fill: '#262626',
                // 'text-anchor': 'start',
              },
            },
            // markup: [
            //   {
            //     tagName: 'polygon',
            //     selector: 'body',
            //   },
            //   {
            //     tagName: 'text',
            //     selector: 'title',
            //   },
            //   {
            //     tagName: 'text',
            //     selector: 'text',
            //   },
            // ],
            ports: {
              ...this.ports
              // items: [
              //   {
              //     group: 'top',
              //   },
              //   {
              //     group: 'bottom',
              //   },
              // ],
            },
          },
          true,
        )
        //
        Graph.registerNode(
          'custom-circle',
          {
            inherit: 'ellipse',
            width: 120,
            height: 120,
            data: {
              dataId: '',
              finishDate: ''
            },
            attrs: {
              body: {
                strokeWidth: 1,
                stroke: '#5F95FF',
                fill: '#EFF4FF',
              },
              //日期
              title: {
                text: '',
                fontSize: 12,
                fill: '#262626',
                refX: 0.5,
                refY: '100%',
                refY2: -10,
                textAnchor: 'middle',
                textVerticalAnchor: 'bottom',
              },
              // 名称
              text: {
                // fontFamily: '仿宋',
                fontSize: 20,
                fill: '#262626',
                textWrap: {
                  width: 80,      // 宽度为 80px换行
                  ellipsis: false,  // 文本超出显示范围时,自动添加省略号
                  breakWord: true, // 是否截断单词
                }
              },
            },
            markup: [
              {
                tagName: 'ellipse',
                selector: 'body',
              },
              {
                tagName: 'text',
                selector: 'title',
              },
              {
                tagName: 'text',
                selector: 'text',
              },
            ],
            ports: {...this.ports},
          },
          true,
        )
        Graph.registerNode(
          'custom-circle1',
          {
            inherit: 'ellipse',
            width: 65,
            height: 65,
            data: {
              dataId: '',
              finishDate: ''
            },
            attrs: {
              body: {
                strokeWidth: 1,
                stroke: '#5F95FF',
                fill: '#EFF4FF',
              },
              //日期
              text: {
                // fontFamily: '仿宋',
                fontSize: 12,
                text: '日期节点',
                fill: '#262626',
              },
            },
            ports: {...this.ports},
          },
          true,
        )
        Graph.registerNode(
          'custom-text',
          {
            inherit: 'text-block',
            width: 86,
            height: 56,
            attrs: {
              body: {
                strokeWidth: 1,
                stroke: '#5F95FF',
                fill: '#EFF4FF',
              },
              text: {
                text: '专业',
                fontSize: 20,
                style: {
                  color: this.globalGridAttr.nodeColor
                },
                refX: '0',
                refY: -0.5,
                refY2: 1,
                textAnchor: 'middle',
                textVerticalAnchor: 'middle',
              },
            },
            markup: [
              {
                tagName: 'rect',
                selector: 'body',
              },
              {
                tagName: 'text',
                selector: 'text',
              },
            ],
            ports: {...this.ports},
          },
          true,
        )
        // 一级网络图的日期文字节点
        const r5 = this.graph.createNode({
          shape: 'custom-circle',
          data: {
            dataId: '',
            finishDate: '',
            inspectName: ''
          },
          label: '阶段',
        })
        // 二级网络图日期节点
        const r6 = this.graph.createNode({
          shape: 'custom-circle1',
          data: {
            dataId: '',
            finishDate: '',
            inspectName: ''
          },
        })
        // 二级网络图文字节点
        const r9 = this.graph.createNode({
          shape: 'custom-rect'
        })
        const scaleImgCenter = this.graph.createNode({
          shape: 'image',
          imageUrl: require('@/assets/img/scale/center.jpg'),
          width: 36,
          height: 20,
          data: {
            imagePost: 'center'
          }
        })
        const scaleImgTop = this.graph.createNode({
          shape: 'image',
          imageUrl: require('@/assets/img/scale/top.jpg'),
          width: 36,
          height: 20,
          data: {
            imagePost: 'top'
          }
        })
        const scaleImgRight = this.graph.createNode({
          shape: 'image',
          imageUrl: require('@/assets/img/scale/right.jpg'),
          width: 36,
          height: 20,
          data: {
            imagePost: 'right'
          }
        })
        const scaleImgBottom = this.graph.createNode({
          shape: 'image',
          imageUrl: require('@/assets/img/scale/bottom.jpg'),
          width: 36,
          height: 20,
          data: {
            imagePost: 'bottom'
          }
        })
        const scaleImgLeft = this.graph.createNode({
          shape: 'image',
          imageUrl: require('@/assets/img/scale/left.jpg'),
          width: 36,
          height: 20,
          data: {
            imagePost: 'left'
          }
        })
        // scaleImgTop.setAttribute('crossOrigin', 'Anonymous')
        stencil.load([r5, r6, r9, scaleImgTop, scaleImgCenter, scaleImgRight, scaleImgBottom, scaleImgLeft], 'group1')
        this.graph.bindKey(['meta+c', 'ctrl+c'], () => {
          const cells = this.graph.getSelectedCells()
          if (cells.length) {
            this.graph.copy(cells)
          }
          return false
        })
        this.graph.bindKey(['meta+x', 'ctrl+x'], () => {
          const cells = this.graph.getSelectedCells()
          if (cells.length) {
            this.graph.cut(cells)
          }
          return false
        })
        // 监听 stencil 的拖拽开始事件
        this.graph.on('node:embed', ({node, e}) => {
          // 阻止事件冒泡
          e.stopPropagation()
          console.log(node.shape, 'node node')
          let parent
          let child
          if (node.shape === 'custom-rect') {
            child = node
          } else {
            parent = node
          }
          console.log('parent:' + parent, 'child:' + child)
          // parent.addChild(child);
        })
        this.graph.bindKey(['meta+v', 'ctrl+v'], () => {
          if (!this.graph.isClipboardEmpty()) {
            const cells = this.graph.paste({offset: 32})
            this.graph.cleanSelection()
            this.graph.select(cells)
          }
          return false
        })
//undo redo
        this.graph.bindKey(['meta+z', 'ctrl+z'], () => {
          if (this.graph.history.canUndo()) {
            this.graph.history.undo()
          }
          return false
        })
        this.graph.bindKey(['meta+shift+z', 'ctrl+shift+z'], () => {
          if (this.graph.history.canRedo()) {
            this.graph.history.redo()
          }
          return false
        })
// select all
        this.graph.bindKey(['meta+a', 'ctrl+a'], () => {
          const nodes = this.graph.getNodes()
          if (nodes) {
            this.graph.select(nodes)
          }
        })
//delete
        this.graph.bindKey('delete', () => {
          const cells = this.graph.getSelectedCells()
          if (cells.length) {
            this.$confirm('是否删除该节点?', '提示', {
              confirmButtonText: '确定',
              cancelButtonText: '取消',
              type: 'warning'
            }).then(() => {
              this.$message({
                type: 'success',
                message: '删除成功!'
              })
              this.graph.removeCells(cells)
            }).catch(() => {
              this.$message({
                type: 'info',
                message: '已取消删除'
              })
            })
          }
        })
// zoom
        this.graph.bindKey(['ctrl+1', 'meta+1'], () => {
          const zoom = this.graph.zoom()
          if (zoom < 1.5) {
            this.graph.zoom(0.1)
          }
        })
        this.graph.bindKey(['ctrl+2', 'meta+2'], () => {
          const zoom = this.graph.zoom()
          if (zoom > 0.5) {
            this.graph.zoom(-0.1)
          }
        })
        this.graph.on('blank:click', ({cell}) => {
          this.type = 'grid'
        })
        this.graph.on('cell:click', ({cell}) => {
          // this.type.value = cell.isNode() ? "node" : "edge"
          this.type = cell.isNode() ? 'node' : 'edge'
          this.shape = cell.shape
          this.id = cell.id
          console.log(this.shape, 'this.shape')
          // this.nodeOpt(this.id, this.globalGridAttr)
        })
        //单击边节点
        this.graph.on('edge:click', ({edge}) => {
          // this.reset()
          edge.attr('line/stroke', '#5F95FF')
          edge.prop('labels/0', {
            attrs: {
              body: {
                stroke: '#5F95FF',
              },
            },
          })
        })
        // 单击node节点
        this.graph.on('node:click', ({node}) => {
          // this.reset()
          if (node.getData().dataId) {
            this.dialogVisible2 = true
            let param = {
              id: node.getData().dataId,
              modelName: node.attr('label/textWrap/text'),
            }
            this.$nextTick(() => {
              this.$refs.rbdEditImg.init(param)
            })
          }
        })
        // 控制连接桩显示/隐藏
        this.graph.on('node:delete', ({view, e}) => {
          e.stopPropagation()
          view.cell.remove()
        })
        this.graph.on('node:customevent', ({name, view, e}) => {
          if (name === 'node:delete') {
            e.stopPropagation()
            view.cell.remove()
          }
        })
        // 双击编辑
        this.graph.on('cell:dblclick', ({cell, e}) => {
          const isNode = cell.isNode()
          const name = cell.isNode() ? 'node-editor' : 'edge-editor'
          cell.removeTool(name)
          cell.addTools({
            name,
            args: {
              event: e,
              attrs: {
                backgroundColor: isNode ? '#EFF4FF' : '#FFF',
                text: {
                  fontSize: 16,
                  fill: '#262626',
                },
              },
            },
          })
        })
        this.graph.on('node:mouseenter', ({node}) => {
          const container = document.getElementById('container')
          const ports = container.querySelectorAll(
            '.x6-port-body',
          )
          this.showPorts(ports, true)
        })
        this.graph.on('node:mouseleave', ({node}) => {
          // if (node.hasTool('button-remove')) {
          //   node.removeTool('button-remove')
          // }
          const container = document.getElementById('container')
          const ports = container.querySelectorAll(
            '.x6-port-body',
          )
          this.showPorts(ports, false)
        })
        this.graph.on('edge:mouseenter', ({cell, view}) => {
          // alert(123)
          cell.addTools([
            {
              name: 'source-arrowhead',
            },
            {
              name: 'target-arrowhead',
              args: {
                attrs: {
                  fill: 'red',
                },
              },
            },
          ])
          cell.addTools(
            [
              {
                name: 'segments',
                args: {snapRadius: 20, attrs: {fill: '#444'}}
              }
            ]
          )
        })
        this.graph.on('edge:mouseleave', ({cell}) => {
          cell.removeTools()
        })
      },
      async getProductList() {
        let res = await this.$http.get('/basicInfo/XhProductModel/getTaskProductList')
        this.productList = res.data
@@ -95,10 +828,18 @@
      async onTreeSelected(data) {
        this.dataForm.productId = data.id
        console.log(this.dataForm.productId)
        if (!this.dataForm.taskModelId) {
          this.$alert("请先选择具体任务")
          return
        }
        if (!this.dataForm.id) {
          this.$alert("请先选择具体仿真记录")
          return
        }
        let params = {
          productId: this.dataForm.productId,
          taskId: this.dataForm.taskModelId,
          fzId: '1722218139013042135'
          fzId: this.dataForm.id
        }
        let res = await this.$http.get('/taskReliability/SimulatAssess/getStatus', {params: params})
        console.log(res.data)
@@ -110,6 +851,9 @@
        this.dataForm.productId = data.id
        this.getTaskList()
        this.dataForm.taskModelId = ''
        this.$nextTick(() => {
          this.$refs.ProductModelTree.getProductList()
        })
      },
      onTaskSelected(data) {
        console.log(data, ' onProductSelected(data)')
@@ -117,10 +861,39 @@
        this.getSimulatList()
        this.dataForm.id = ''
      },
      onSimulatSelected(data) {
      async onSimulatSelected(data) {
        this.dataForm.id = data.id
        this.dataForm.samplPeriod = data.samplPeriod
        this.$refs.SimulatCurve.initEcharts(this.dataForm);
        let param = {
          id: this.dataForm.id,
          taskModelId: this.dataForm.taskModelId
        }
        let result = await this.$http.get('/taskReliability/SimulatAssess/getSimulatParams', {params: param})
        this.dataForm.samplPeriod = result.data.samplPeriod
        this.dataForm.simulatFrequency = result.data.simulatFrequency
      },
      async getDiagram() {
        let params = {
          productId: this.dataForm.productId,
          taskId: this.dataForm.taskModelId,
          fzId: this.dataForm.id
        }
        let res = await this.$http.get('/taskReliability/SimulatAssess/getStatus', {params: params})
        if (res.data !== null) {
          this.diagramJson = JSON.parse(res.data)
          // console.log(this.dataForm.content,'this.Diagram content')
          console.log(this.diagramJson, 'this.Diagram json')
          this.graph.fromJSON(this.diagramJson)
          this.graph.centerContent()
          this.graph.zoomToFit()
          this.graph.freeze()
        } else {
          this.graph.fromJSON(this.emptyJson)
          this.graph.centerContent()
          this.graph.zoomToFit()
          this.graph.freeze()
        }
        console.log(res.data)
      },
    }
  }
web/src/views/modules/taskReliability/TimeDiagramTemp.vue
New file
@@ -0,0 +1,1207 @@
<template>
  <div>
    <el-row :gutter="[8,8]">
      <el-col :span="5">
        <div style="height: 80vh">
          <div class="fa-card-a">
            <div id="stencil"></div>
            <div style="height: 42vh;margin-top: 30px;background: #f5f5f5;padding-bottom:20px ">
              <h3 style="background: #ededed;font-size: 12px;height: 32px;line-height: 32px;padding: 0 5px 0 8px">
                对齐方式</h3>
              <div style="text-align: center">
                <el-tooltip class="item" effect="dark" content="左对齐" placement="left">
                  <el-button class="" style="margin-left: 0;padding: 2px;border: 1px solid #5F95FF;"
                             @click="leftAlign()"><i style="font-size: 2rem;color: #5F95FF"
                                                     class="wt-iconfont icon-zuoduiqi"></i></el-button>
                </el-tooltip>
              </div>
              <div style="text-align: center">
                <el-tooltip class="item" effect="dark" content="居中对齐" placement="left">
                  <el-button style="margin-left: 0;margin-top: 10px;padding: 2px;border: 1px solid #5F95FF"
                             @click="centerAlign()"><i style="font-size: 2rem;color: #5F95FF"
                                                       class="wt-iconfont icon-chuizhiduiqi"></i></el-button>
                </el-tooltip>
              </div>
              <div style="text-align: center">
                <el-tooltip class="item" effect="dark" content="右对齐" placement="left">
                  <el-button style="margin-left: 0;margin-top: 10px;padding: 2px;border: 1px solid #5F95FF"
                             @click="rightAlign()"><i style="font-size: 2rem;color: #5F95FF"
                                                      class="wt-iconfont icon-youduiqi"></i></el-button>
                </el-tooltip>
              </div>
              <div style="text-align: center">
                <el-tooltip class="item" effect="dark" content="顶部对齐" placement="left">
                  <el-button style="margin-left: 0;margin-top: 10px;padding: 2px;border: 1px solid #5F95FF"
                             @click="topAlign()"><i style="font-size: 2rem;color:#5F95FF"
                                                    class="wt-iconfont icon-dingduiqi"></i></el-button>
                </el-tooltip>
              </div>
              <div style="text-align: center">
                <el-tooltip class="item" effect="dark" content="水平对齐" placement="left">
                  <el-button style="margin-left: 0;margin-top: 10px;padding: 2px;border: 1px solid #5F95FF"
                             @click="shuipingAlign()"><i style="font-size: 2rem;color:#5F95FF"
                                                         class="wt-iconfont icon-shuipingduiqi"></i></el-button>
                </el-tooltip>
              </div>
              <div style="text-align: center">
                <el-tooltip class="item" effect="dark" content="底部对齐" placement="left">
                  <el-button style="margin-left: 0;margin-top: 10px;padding: 2px;border: 1px solid #5F95FF"
                             @click="bottomAlign()"><i style="font-size: 2rem;color:#5F95FF"
                                                       class="wt-iconfont icon-diduiqi"></i></el-button>
                </el-tooltip>
              </div>
            </div>
          </div>
        </div>
      </el-col>
      <el-col :span="19">
        <div class="fa-card-a">
          <el-form :inline="true">
            <el-form-item prop="projectId" style="margin-left:10px;width: 180px;">
              <zt-select v-model="projectId" :datas="projectList" clearable placeholder="工程项目"
                         @change="projectChange"></zt-select>
            </el-form-item>
            <el-form-item>
              <el-select v-model="diagramId" :disabled="diagramIdDisabled" placeholder="请选择"
                         @change="diagramIdChanges">
                <el-option v-for="item in diagramList"
                           :key="item.diagramId"
                           :label="item.diagramName"
                           :value="item.diagramId">
                </el-option>
              </el-select>
            </el-form-item>
            <el-form-item>
              <el-button type="primary" @click="saveDiagram()">保存</el-button>
              <!--            <zt-button type="primary" v-show="pageCode === 'wlt_sp' && flowInfo.myStatus ===1"  @click="reject()">驳回</zt-button>-->
            </el-form-item>
          </el-form>
          <div id="container" style="border: 1px solid #EAEBEE;border-radius: 6px;
        box-shadow: 0 2px 12px 0 rgb(0 0 0 / 10%);">
          </div>
          <config-edge ref="configEdge" v-show="type === 'edge'" :id="id" :globalGridAttr="globalGridAttr"
                       :graph="graph"/>
          <config-node v-show="type === 'node'"  :id="id" :globalGridAttr="globalGridAttr"
                       :graph="graph"
                       :shape="shape"/>
        </div>
      </el-col>
    </el-row>
  </div>
</template>
<script>
  import {Graph, Shape, Addon, Cell} from '@antv/x6'
  import {removeCurrentTabHandle} from '@/commonJS/common'
  import ConfigEdge from './ConfigEdge/configEdge.vue'
  import ConfigNode from './ConfigNode/tempNode.vue'
  import EleGallery from "../../../../packages/components/vue-ele-gallery/src/EleGallery";
  export default {
    name: 'avtVx6',
    /*props: {
    },*/
    props: {
      projectId: {
        type: String
      },
      diagarmId: {
        type: String
      },
      pageCode: {
        default: 'wlt_pz'
      },
      flowCode: {
        type: String,
        default: 'wltFlow'
      },
    },
    components: {
      EleGallery,
      ConfigEdge,
      ConfigNode
    },
    data() {
      return {
        first: true,
        shape: '',
        projectList: [],
        diagramList: [],
        diagramId: '',
        projectId: '',
        diagramJson: '',
        diagramIdDisabled: false,
        dataForm: {
          id: null,
          projectId: null,
          diagramId: null,
          content: null,
          publishContent: null,
          hasPublish: 0
        },
        flowInfo: {
          bizId: '',
          bizGroupId: '',
          flowCode: '',
          flowStepMark: '',
          status: 0,
          myStatus: 0
        },
        emptyJson: {
          // 节点
          nodes: [
            {
              id: 'node1', // String,可选,节点的唯一标识
              width: 500,   // Number,可选,节点大小的 width 值
              height: 300,  // Number,可选,节点大小的 height 值
              label: '该项目还未配置厂家网络图',
              attrs: {
                body: {
                  strokeWidth: 0
                },
              }
              //   text: {
              //     text: '该项目还未编制网络图',
              //     // fontSize: 56,
              //     fill: 'rgba(0,0,0,0.7)'
              //   },
              // },
            }
          ],
        },
        type: '',
        id: '',
        graph: null,
        globalGridAttr: {
          type: 'mesh',
          size: 10,
          color: '#e5e5e5',
          thickness: 1,
          colorSecond: '#d0d0d0',
          thicknessSecond: 1,
          factor: 4,
          bgColor: '#e5e5e5',
          showImage: true,
          repeat: 'watermark',
          position: 'center',
          bgSize: JSON.stringify({width: 150, height: 150}),
          opacity: 0.1,
          stroke: '#5F95FF',
          strokeWidth: 1,
          connector: 'normal',
          label: '',
          nodeStroke: '#5F95FF',
          nodeStrokeWidth: 1,
          nodeFill: '#ffffff',
          nodeFontSize: 12,
          nodeColor: '#080808',
          nodeText: '',
          nodeDate: '',
          nodeUsers: '',
          nodeDataDate: '',
          nodeDataText: '',
          dataId: '',
          inspectName: '',
          distance: 0.5,
          angle: 0,
        },
        timer: false,
        isReady: false,
        curCel: Cell,
        left_p: document.documentElement.clientHeight * 0.85,
        ports: {
          groups: {
            top: {
              position: 'top',
              attrs: {
                circle: {
                  r: 4,
                  magnet: true,
                  stroke: '#5F95FF',
                  strokeWidth: 1,
                  fill: '#fff',
                  style: {
                    visibility: 'hidden',
                  },
                },
              },
            },
            right: {
              position: 'right',
              attrs: {
                circle: {
                  r: 4,
                  magnet: true,
                  stroke: '#5F95FF',
                  strokeWidth: 1,
                  fill: '#fff',
                  style: {
                    visibility: 'hidden',
                  },
                },
              },
            },
            bottom: {
              position: 'bottom',
              attrs: {
                circle: {
                  r: 4,
                  magnet: true,
                  stroke: '#5F95FF',
                  strokeWidth: 1,
                  fill: '#fff',
                  style: {
                    visibility: 'hidden',
                  },
                },
              },
            },
            left: {
              position: 'left',
              attrs: {
                circle: {
                  r: 4,
                  magnet: true,
                  stroke: '#5F95FF',
                  strokeWidth: 1,
                  fill: '#fff',
                  style: {
                    visibility: 'hidden',
                  },
                },
              },
            },
          },
          items: [
            {
              group: 'top',
            },
            {
              group: 'right',
            },
            {
              group: 'bottom',
            },
            {
              group: 'left',
            },
          ],
        }
      }
    },
    watch: {
      '$route.params.configId'() {
        // alert('$route.params.projectId change')
        this.projectId = this.$route.params.projectId
        //this.diagramId = this.$route.params.diagramId
        console.log(this.$route.params.projectId, 'this.$route.params.projectId')
        console.log(this.$route.params.diagramId, 'this.$route.params.diagramId')
        this.projectChange2(this.$route.params.diagramId)
      }
    },
    methods: {
      async finish() {
        if (await this.$tip.confirm('确定要进行提交操纵吗?')) {
          let submitForm = {
            params: {
              wfIdCode: 'wltFlow',
              bizId: this.dataForm.projectId,
              stepIdMark: this.pageCode
            }
          }
          let res = await this.$http.get('/wf/approvePass', submitForm)
          if (res.success) {
            await this.$alert('提交成功', '友情提示')
            removeCurrentTabHandle(this)
            this.$EventBus.$emit('taskRefeshEvent', '网络图')
          }
        }
      },
      async getProject() {
        this.projectList.push({id: '10000', name: '样式模板'})
        if (this.$route.params.projectId) {
          this.projectId = this.$route.params.projectId
          this.diagramId = this.$route.params.diagramId
        } else {
          if (this.projectList.length > 0) {
            this.projectId = this.projectList[0].id
            this.diagramId = this.projectId
            console.log(this.diagramId, '123456789')
          }
        }
        await this.projectChange2(this.diagramId)
      },
      async projectChange2(diagramId) {
        await this.getDiagram()
      },
      diagramIdChanges() {
        this.dataForm.diagramId = this.diagramId
        // this.diagramIdChange(this.diagramId)
        this.getDiagram()
      },
      async getDiagram() {
        let includeCj = false
        console.log(this.diagramList, 'this.diagramList')
        console.log(this.diagramId, 'this.diagramId')
        for (let val of this.diagramList) {
          if (val.diagramId == this.diagramId) {
            includeCj = true
            break
          }
        }
        console.log(includeCj, 'includeCj')
        if (this.dataForm.projectId == '10000') {
          this.dataForm.diagramId = '10000'
        }
        let params = {
          projectId: '10000',
          diagramId: '10000',
          showType: 'form',  // form 从数据库读图 noform 根据配置生成图
          isShow: 'no'       // yes 读带状态的图   no 读原图
        }
        console.log(params, 'params')
        //alert(params.diagramId)
        let res = await this.$http.get(`/taskReliability/SimulatAssess/getDiagram`, {params: params})
        if (res.data !== null && res.data.content != null) {
          this.dataForm = res.data
          this.diagramJson = JSON.parse(this.dataForm.content)
          // console.log(this.dataForm.content,'this.Diagram content')
          console.log(this.diagramJson, 'this.Diagram json')
          this.graph.fromJSON(this.diagramJson)
          // this.graph.centerContent()
          // this.graph.zoomToFit()
        } else {
          this.dataForm.id = null
          // await this.$alert('该项目还未编制网络图', '提示', {
          //   confirmButtonText: '确定'
          // })
          this.graph.fromJSON(this.emptyJson)
          // this.graph.centerContent()
          // this.graph.zoomToFit()
          // this.graph.freeze()
        }
      },
      init() {
        console.log(document.documentElement.clientWidth, 'document.documentElement.clientWidth')
        console.log(document.documentElement.clientHeight, 'document.documentElement.clientHeight')
        this.graph = new Graph({
          container: document.getElementById('container'),
          width: document.documentElement.clientWidth,
          height: document.documentElement.clientHeight - 220,
          // async: true,
          grid: {
            visible: true,
          },
          embedding: {
            enabled: true,
            findParent({node}) {
              const bbox = node.getBBox()
              return this.getNodes().filter((node) => {
                // 只有 data.parent 为 true 的节点才是父节点
                const data = node.getData()
                if (data && data.parent) {
                  const targetBBox = node.getBBox()
                  return bbox.isIntersectWithRect(targetBBox)
                }
                return false
              })
            }
          },
          // translating: {
          //   restrict(view) {
          //     const cell = view.cell
          //     if (cell.isNode()) {
          //       const parent = cell.getParent()
          //       if (parent) {
          //         return parent.getBBox()
          //       }
          //     }
          //
          //     return null
          //   },
          // },
          onToolItemCreated({tool}) {
            const handle = tool
            const options = handle.options
            if (options && options.index % 2 === 1) {
              tool.setAttrs({fill: 'red'})
            }
          },
          autoResize: true,
          history: true,
          // panning: {
          //   enabled: true,
          // },
          scroller: {
            enabled: true,
            pageVisible: true,
            pageBreak: true,
            pannable: true,
          },
          mousewheel: {
            enabled: true,
            zoomAtMousePosition: true,
            modifiers: 'ctrl',
            minScale: 0.1,
            maxScale: 10,
          },
          connecting: {
            router: {
              name: 'normal',
              // args: {
              //   padding: 1,
              // },
            },
            connector: {
              name: 'rounded',
              args: {
                radius: 8,
              },
            },
            // anchor: 'center',
            connectionPoint: 'anchor',
            snap: {
              radius: 20,
            },
            createEdge() {
              return new Shape.Edge({
                attrs: {
                  line: {
                    stroke: '#A2B1C3',
                    strokeWidth: 2,
                    targetMarker: 'classic'
                  }
                },
                tools: {
                  name: 'vertices',
                },
                labels: [{
                  attrs: {
                    body: {
                      stroke: '#5F95FF',
                    },
                    text: {
                      // fontFamily: '仿宋',
                      text: ''
                    }
                  },
                  // position: {
                  //   distance: 0.5,
                  //   angle: 180,
                  //   options: {
                  //     keepGradient: true,
                  //     ensureLegibility: true
                  //   }
                  // }
                }],
                zIndex: 0,
              })
            },
            // validateConnection({targetMagnet}) {
            //   return !!targetMagnet
            // },
          },
          highlighting: {
            magnetAdsorbed: {
              name: 'stroke',
              args: {
                attrs: {
                  fill: '#5F95FF',
                  stroke: '#5F95FF',
                },
              },
            },
          },
          resizing: {
            enabled: true,
            restricted: true
          },
          rotating: true,
          selecting: {
            enabled: true,
            rubberband: true,
            rubberEdge: true,
            showNodeSelectionBox: true,
          },
          snapline: true,
          keyboard: true,
          clipboard: true,
        })
        this.graph.centerContent()
        const stencil = new Addon.Stencil({
          title: '',
          target: this.graph,
          stencilGraphWidth: 260,
          stencilGraphHeight: 700,
          collapsable: false,
          groups: [
            {
              title: '图元',
              name: 'group1',
              collapsable: false
            }
          ],
          layoutOptions: {
            columns: 2,
            columnWidth: 130,
            rowHeight: 100,
          },
        })
        document.getElementById('stencil').appendChild(stencil.container)
        Graph.registerNode(
          'custom-rect',
          {
            inherit: 'rect',
            width: 86,
            height: 26,
            zIndex: 10,
            data: {
              dataId: '',
              finishDate: '',
              inspectName: ''
            },
            attrs: {
              body: {
                strokeWidth: 1,
                stroke: 'none',
                fill: 'none',
              },
              text: {
                // fontFamily: '仿宋',
                fontSize: 20,
                fill: '#000',
              },
              label: {
                refX: 0,
                refY: 0.5,
                textAnchor: 'start',
                textVerticalAnchor: 'middle',
                textWrap: {
                  text: '文字模板',
                  width: -10,      // 宽度减少 10px
                  ellipsis: false,  // 文本超出显示范围时,自动添加省略号
                  breakWord: true, // 是否截断单词
                }
              },
            },
            ports: {...this.ports},
          },
          true,
        )
        Graph.registerNode(
          'custom-polygon',
          {
            inherit: 'polygon',
            width: 86,
            height: 56,
            attrs: {
              body: {
                strokeWidth: 1,
                stroke: '#5F95FF',
                fill: '#EFF4FF',
              },
              text: {
                fontSize: 20,
                fill: '#262626',
              },
            },
            ports: {
              ...this.ports
              // items: [
              //   {
              //     group: 'top',
              //   },
              //   {
              //     group: 'bottom',
              //   },
              // ],
            },
          },
          true,
        )
        //
        Graph.registerNode(
          'custom-circle',
          {
            inherit: 'ellipse',
            width: 120,
            height: 120,
            data: {
              dataId: '',
              finishDate: ''
            },
            attrs: {
              body: {
                strokeWidth: 1,
                stroke: '#5F95FF',
                fill: '#EFF4FF',
              },
              //日期
              title: {
                text: '',
                fontSize: 12,
                fill: '#262626',
                refX: 0.5,
                refY: '100%',
                refY2: -10,
                textAnchor: 'middle',
                textVerticalAnchor: 'bottom',
              },
              // 名称
              text: {
                // fontFamily: '仿宋',
                fontSize: 20,
                fill: '#262626',
                textWrap: {
                  width: 80,      // 宽度为 80px换行
                  ellipsis: false,  // 文本超出显示范围时,自动添加省略号
                  breakWord: true, // 是否截断单词
                }
              },
            },
            markup: [
              {
                tagName: 'ellipse',
                selector: 'body',
              },
              {
                tagName: 'text',
                selector: 'title',
              },
              {
                tagName: 'text',
                selector: 'text',
              },
            ],
            ports: {...this.ports},
          },
          true,
        )
        Graph.registerNode(
          'custom-circle1',
          {
            inherit: 'ellipse',
            width: 65,
            height: 65,
            data: {
              dataId: '',
              finishDate: ''
            },
            attrs: {
              body: {
                strokeWidth: 1,
                stroke: '#5F95FF',
                fill: '#EFF4FF',
              },
              //日期
              text: {
                // fontFamily: '仿宋',
                fontSize: 12,
                text: '日期节点',
                fill: '#262626',
              },
            },
            ports: {...this.ports},
          },
          true,
        )
        Graph.registerNode(
          'custom-text',
          {
            inherit: 'text-block',
            width: 86,
            height: 56,
            attrs: {
              body: {
                strokeWidth: 1,
                stroke: '#5F95FF',
                fill: '#EFF4FF',
              },
              text: {
                text: '专业',
                fontSize: 20,
                style: {
                  color: this.globalGridAttr.nodeColor
                },
                refX: '0',
                refY: -0.5,
                refY2: 1,
                textAnchor: 'middle',
                textVerticalAnchor: 'middle',
              },
            },
            markup: [
              {
                tagName: 'rect',
                selector: 'body',
              },
              {
                tagName: 'text',
                selector: 'text',
              },
            ],
            ports: {...this.ports},
          },
          true,
        )
        // 一级网络图的日期文字节点
        const r5 = this.graph.createNode({
          shape: 'custom-circle',
          data: {
            dataId: '',
            finishDate: '',
            inspectName: ''
          },
          label: '阶段',
        })
        // 二级网络图日期节点
        const r6 = this.graph.createNode({
          shape: 'custom-circle1',
          data: {
            dataId: '',
            finishDate: '',
            inspectName: ''
          },
        })
        // 二级网络图文字节点
        const r9 = this.graph.createNode({
          shape: 'custom-rect'
        })
        const scaleImgCenter = this.graph.createNode({
          shape: 'image',
          imageUrl: require('@/assets/img/scale/center.jpg'),
          width: 36,
          height: 20,
          data: {
            imagePost: 'center'
          }
        })
        const scaleImgTop = this.graph.createNode({
          shape: 'image',
          imageUrl: require('@/assets/img/scale/top.jpg'),
          width: 36,
          height: 20,
          data: {
            imagePost: 'top'
          }
        })
        const scaleImgRight = this.graph.createNode({
          shape: 'image',
          imageUrl: require('@/assets/img/scale/right.jpg'),
          width: 36,
          height: 20,
          data: {
            imagePost: 'right'
          }
        })
        const scaleImgBottom = this.graph.createNode({
          shape: 'image',
          imageUrl: require('@/assets/img/scale/bottom.jpg'),
          width: 36,
          height: 20,
          data: {
            imagePost: 'bottom'
          }
        })
        const scaleImgLeft = this.graph.createNode({
          shape: 'image',
          imageUrl: require('@/assets/img/scale/left.jpg'),
          width: 36,
          height: 20,
          data: {
            imagePost: 'left'
          }
        })
        // scaleImgTop.setAttribute('crossOrigin', 'Anonymous')
        stencil.load([r5, r6, r9, scaleImgTop, scaleImgCenter, scaleImgRight, scaleImgBottom, scaleImgLeft], 'group1')
        this.graph.bindKey(['meta+c', 'ctrl+c'], () => {
          const cells = this.graph.getSelectedCells()
          if (cells.length) {
            this.graph.copy(cells)
          }
          return false
        })
        this.graph.bindKey(['meta+x', 'ctrl+x'], () => {
          const cells = this.graph.getSelectedCells()
          if (cells.length) {
            this.graph.cut(cells)
          }
          return false
        })
        // 监听 stencil 的拖拽开始事件
        this.graph.on('node:embed', ({node, e}) => {
          // 阻止事件冒泡
          e.stopPropagation()
          console.log(node.shape, 'node node')
          let parent
          let child
          if (node.shape === 'custom-rect') {
            child = node
          } else {
            parent = node
          }
          console.log('parent:' + parent, 'child:' + child)
          // parent.addChild(child);
        })
        this.graph.bindKey(['meta+v', 'ctrl+v'], () => {
          if (!this.graph.isClipboardEmpty()) {
            const cells = this.graph.paste({offset: 32})
            this.graph.cleanSelection()
            this.graph.select(cells)
          }
          return false
        })
//undo redo
        this.graph.bindKey(['meta+z', 'ctrl+z'], () => {
          if (this.graph.history.canUndo()) {
            this.graph.history.undo()
          }
          return false
        })
        this.graph.bindKey(['meta+shift+z', 'ctrl+shift+z'], () => {
          if (this.graph.history.canRedo()) {
            this.graph.history.redo()
          }
          return false
        })
// select all
        this.graph.bindKey(['meta+a', 'ctrl+a'], () => {
          const nodes = this.graph.getNodes()
          if (nodes) {
            this.graph.select(nodes)
          }
        })
//delete
        this.graph.bindKey('delete', () => {
          const cells = this.graph.getSelectedCells()
          if (cells.length) {
            this.$confirm('是否删除该节点?', '提示', {
              confirmButtonText: '确定',
              cancelButtonText: '取消',
              type: 'warning'
            }).then(() => {
              this.$message({
                type: 'success',
                message: '删除成功!'
              })
              this.graph.removeCells(cells)
            }).catch(() => {
              this.$message({
                type: 'info',
                message: '已取消删除'
              })
            })
          }
        })
// zoom
        this.graph.bindKey(['ctrl+1', 'meta+1'], () => {
          const zoom = this.graph.zoom()
          if (zoom < 1.5) {
            this.graph.zoom(0.1)
          }
        })
        this.graph.bindKey(['ctrl+2', 'meta+2'], () => {
          const zoom = this.graph.zoom()
          if (zoom > 0.5) {
            this.graph.zoom(-0.1)
          }
        })
        this.graph.on('blank:click', ({cell}) => {
          // this.reset()
          // this.type.value = "grid"
          this.type = 'grid'
          // this.id = cell.id
        })
        this.graph.on('cell:click', ({cell}) => {
          // this.type.value = cell.isNode() ? "node" : "edge"
          this.type = cell.isNode() ? 'node' : 'edge'
          this.shape = cell.shape
          this.id = cell.id
          console.log(this.shape, 'this.shape')
          // this.nodeOpt(this.id, this.globalGridAttr)
        })
        //单击边节点
        this.graph.on('edge:click', ({edge}) => {
          // this.reset()
          edge.attr('line/stroke', '#5F95FF')
          edge.prop('labels/0', {
            attrs: {
              body: {
                stroke: '#5F95FF',
              },
            },
          })
        })
        // 单击node节点
        this.graph.on('node:click', ({node}) => {
          // this.reset()
          node.attr('line/stroke', '#5F95FF')
          node.prop('labels/0', {
            attrs: {
              body: {
                stroke: '#5F95FF',
              },
            },
          })
        })
        // 控制连接桩显示/隐藏
        this.graph.on('node:delete', ({view, e}) => {
          e.stopPropagation()
          view.cell.remove()
        })
        this.graph.on('node:customevent', ({name, view, e}) => {
          if (name === 'node:delete') {
            e.stopPropagation()
            view.cell.remove()
          }
        })
        // 双击编辑
        this.graph.on('cell:dblclick', ({cell, e}) => {
          const isNode = cell.isNode()
          const name = cell.isNode() ? 'node-editor' : 'edge-editor'
          cell.removeTool(name)
          cell.addTools({
            name,
            args: {
              event: e,
              attrs: {
                backgroundColor: isNode ? '#EFF4FF' : '#FFF',
                text: {
                  fontSize: 16,
                  fill: '#262626',
                },
              },
            },
          })
        })
        this.graph.on('node:mouseenter', ({node}) => {
          const container = document.getElementById('container')
          const ports = container.querySelectorAll(
            '.x6-port-body',
          )
          this.showPorts(ports, true)
        })
        this.graph.on('node:mouseleave', ({node}) => {
          // if (node.hasTool('button-remove')) {
          //   node.removeTool('button-remove')
          // }
          const container = document.getElementById('container')
          const ports = container.querySelectorAll(
            '.x6-port-body',
          )
          this.showPorts(ports, false)
        })
        this.graph.on('edge:mouseenter', ({cell, view}) => {
          // alert(123)
          cell.addTools([
            {
              name: 'source-arrowhead',
            },
            {
              name: 'target-arrowhead',
              args: {
                attrs: {
                  fill: 'red',
                },
              },
            },
          ])
          cell.addTools(
            [
              {
                name: 'segments',
                args: {snapRadius: 20, attrs: {fill: '#444'}}
              }
            ]
          )
        })
        this.graph.on('edge:mouseleave', ({cell}) => {
          cell.removeTools()
        })
      },
      showPorts(ports, show) {
        for (let i = 0, len = ports.length; i < len; i = i + 1) {
          ports[i].style.visibility = show ? 'visible' : 'hidden'
        }
      },
      async saveDiagram() {
        console.log(JSON.stringify(this.graph.toJSON()), 'graph.toJSON()')
        if (!this.dataForm.diagramId) {
          this.dataForm.diagramId = this.dataForm.projectId
        }
        this.dataForm.hasPublish = 0
        this.dataForm.content = JSON.stringify(this.graph.toJSON())
        console.log(this.dataForm, 'dataFrom')
        await this.$http.put(`/taskReliability/SimulatAssess/saveDiagram`, this.dataForm).then(async res => {
          if (res.msg === 'success') {
            this.$alert('保存成功', '提示', {
              confirmButtonText: '确定'
            })
          }
        })
      },
      leftAlign() {
        const NODE = this.graph.getSelectedCells()
        let leftX = null
        for (let a of NODE) {
          if (leftX == null || a.getBBox().x < leftX) {
            leftX = a.getBBox().x
          }
        }
        for (let a of NODE) {
          let y = a.getBBox().y
          a.position(leftX, y)
          // console.log(leftX, ':', y, '  x:y')
        }
      },
      topAlign() {
        const NODE = this.graph.getSelectedCells()
        let topY = null
        for (let a of NODE) {
          console.log(a.getBBox(), 'a.getBBox()')
          if (topY == null || a.getBBox().y < topY) {
            topY = a.getBBox().y
          }
        }
        for (let a of NODE) {
          let x = a.getBBox().x
          a.position(x, topY)
          // console.log(leftX, ':', y, '  x:y')
        }
      },
      centerAlign() {
        const NODE = this.graph.getSelectedCells()
        let rightX = null
        let leftX = null
        for (let a of NODE) {
          if (leftX == null || a.getBBox().x < leftX) {
            leftX = a.getBBox().x
          }
        }
        for (let a of NODE) {
          if (rightX == null || a.getBBox().x + a.getBBox().width > rightX) {
            rightX = a.getBBox().x + a.getBBox().width
          }
        }
        let centerX = leftX + (rightX - leftX) / 2
        for (let a of NODE) {
          let y = a.getBBox().y
          a.position(centerX - a.getBBox().width / 2, y)
          // console.log(leftX, ':', y, '  x:y')
        }
      },
      shuipingAlign() {
        const NODE = this.graph.getSelectedCells()
        let bottomY = null
        let topY = null
        for (let a of NODE) {
          if (topY == null || a.getBBox().y || 0 < topY) {
            topY = a.getBBox().y
          }
        }
        for (let a of NODE) {
          if (bottomY == null || a.getBBox().y + a.getBBox().height > bottomY) {
            bottomY = a.getBBox().y + a.getBBox().height
          }
        }
        let centerY = topY + (bottomY - topY) / 2
        for (let a of NODE) {
          let x = a.getBBox().x
          let centerHei = a.getBBox().height / 2
          a.position(x, centerY - centerHei)
        }
      },
      rightAlign() {
        const NODE = this.graph.getSelectedCells()
        let rightX = null
        for (let a of NODE) {
          if (rightX == null || a.getBBox().x + a.getBBox().width > rightX) {
            rightX = a.getBBox().x + a.getBBox().width
          }
        }
        for (let a of NODE) {
          let y = a.getBBox().y
          a.position(rightX - a.getBBox().width, y)
        }
      },
      bottomAlign() {
        const NODE = this.graph.getSelectedCells()
        let bottomY = null
        for (let a of NODE) {
          if (bottomY == null || (a.getBBox().y + a.getBBox().height) > bottomY) {
            bottomY = a.getBBox().y + a.getBBox().height
          }
        }
        for (let a of NODE) {
          let x = a.getBBox().x
          a.position(x, bottomY - a.getBBox().height)
        }
      },
    },
    mounted() {
      this.getProject()
      this.init()
      this.type = 'grid'
    }
  }
</script>
<style>
  #container {
    display: flex;
    border: 1px solid #dfe3e8;
    width: 100% !important;
  }
  .x6-graph-scroller.x6-graph-scroller-pannable {
    width: 100% !important;
  }
  #stencil {
    width: 100%;
    height: 350px;
    position: relative;
    border-right: 1px solid #dfe3e8;
  }
  .x6-widget-stencil {
    position: relative;
    height: 100%;
  }
  .x6-widget-stencil-content {
    position: relative;
    height: 100%;
  }
</style>
zt/common/src/main/java/com/zt/common/utils/JsonUtils2.java
@@ -1,12 +1,13 @@
package com.zt.common.utils;
import cn.hutool.core.convert.Convert;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import org.apache.commons.lang3.ArrayUtils;
public class JsonUtils2 {
    public static boolean setArrJsonValueByPath(JSONObject pJSONObject, String[] path, String searchKey, String searchValue, String targetKey, Object value) {
    /*    public static boolean setArrJsonValueByPath(JSONObject pJSONObject, String[] path, String searchKey, String searchValue, String targetKey, Object value) {
        if (path.length == 1) {
            JSONArray jsonArray = pJSONObject.getJSONArray(path[0]);
            for (int i = 0; i < jsonArray.size(); i++
@@ -23,6 +24,34 @@
            setArrJsonValueByPath(sJSONObject, path, searchKey, searchValue, targetKey, value);
        }
        return false;
        }*/
    public static boolean setArrJsonValueByPath(JSONObject pJSONObject, String[] path, String searchKey, String searchValue, String path2, Object value) {
        return setArrJsonValueByPath(pJSONObject, path, searchKey, searchValue, path2.split("/"), value);
    }
    public static boolean setArrJsonValueByPath(JSONObject pJSONObject, String[] path, String searchKey, String searchValue, String[] path2, Object value) {
        if (path.length == 1) {
            JSONArray jsonArray = pJSONObject.getJSONArray(path[0]);
            JSONObject targetJSONObject = null;
            if (searchKey != null) {
                for (int i = 0; i < jsonArray.size(); i++) {
                    JSONObject jsonObject = jsonArray.getJSONObject(i);
                    if (jsonObject.get(searchKey).equals(searchValue)) {
                        targetJSONObject = jsonObject;
                    }
                }
            } else {
                targetJSONObject = jsonArray.getJSONObject(0);
            }
            setJsonValueByPath(targetJSONObject, path2, value);
            return true;
        } else {
            JSONObject sJSONObject = pJSONObject.getJSONObject(path[0]);
            path = ArrayUtils.remove(path, 0);
            setArrJsonValueByPath(sJSONObject, path, searchKey, searchValue, path2, value);
        }
        return false;
    }
    public static Object getArrJsonValueByPath(JSONObject pJSONObject, String[] path, String searchKey, String searchValue, String targetKey) {