Quellcode durchsuchen

Merge branch 'master' of http://39.106.8.246:3003/BDTP/adm-frontend

qule vor 3 Jahren
Ursprung
Commit
eb3cdb3657

+ 1 - 0
package.json

@@ -15,6 +15,7 @@
     "font-awesome": "^4.7.0",
     "handsontable-pro": "^3.0.0",
     "meri-design": "^1.5.515",
+    "moment": "^2.29.1",
     "vue-router": "^3.5.3",
     "vuex": "^3.6.2"
   },

Datei-Diff unterdrückt, da er zu groß ist
+ 4 - 0
src/assets/images/systemGraph/fontStyle.svg


+ 14 - 3
src/components/systemGraph/addGraph.vue

@@ -62,7 +62,9 @@
 </template>
 <script>
 import { mapState } from "vuex";
-import { sysGraphController } from "@/controller/sysGraphController";
+import { sysGraphController } from "@/controller/systemGraph/sysGraphController";
+import { logicConfig } from "@/logicConfig";
+import { Message } from "element-ui";
 
 export default {
   props: ["isVisible"],
@@ -122,7 +124,7 @@ export default {
         this.selSysType = typeNode.data;
 
         //查询系统类型下的系统模版
-        var templateArr = await sysGraphController.getTemplateBySysCode(
+        var templateArr = await sysGraphController.getTemplateBySysTypeCode(
           this.selSysType.code
         );
         this.systemTemplateArr = templateArr;
@@ -160,8 +162,17 @@ export default {
         };
 
         //新增系统图
-        var templateArr = await sysGraphController.createSysGraph(_paramObj);
+        var createResult = await sysGraphController.createSysGraph(_paramObj);
+        switch (createResult.result) {
+          case logicConfig.resultObj.failure:
+            Message.error("新增失败,原因:" + createResult.reason);
+            break;
+          case logicConfig.resultObj.success:
+            this.$emit("created", createResult.data);
+            break;
+        }
       } catch (error) {
+        Message.error("新增失败,执行异常");
         console.error(error);
       }
       this.fullscreenLoading = false;

+ 484 - 53
src/components/systemGraph/edit.vue

@@ -8,16 +8,24 @@
         />
         <span class="headerTitle">系统图编辑器</span>
         <div class="operBtnDiv" v-if="operState === 0">
-          <span>回到首页</span>
-          <span>编辑系统图</span>
-          <span>上架系统图</span>
-          <span>下架系统图</span>
+          <!-- <span>回到首页</span> -->
+          <span @click="intoEditState">编辑系统图</span>
+          <span
+            v-if="(graphInfo.extraProps || {}).state == 'Draft'"
+            @click="publishGraph"
+            >上架系统图</span
+          >
+          <span
+            v-if="(graphInfo.extraProps || {}).state == 'Publish'"
+            @click="draftGraph"
+            >下架系统图</span
+          >
         </div>
         <div class="operBtnDiv" v-if="operState === 1">
           <span>保存图纸</span>
-          <span>放弃编辑</span>
+          <span @click="cancelClick">放弃编辑</span>
         </div>
-        <span class="delBtn">删除图纸</span>
+        <span class="delBtn" @click="delGraph">删除图纸</span>
       </div>
       <div class="secondOperDivContainer">
         <img
@@ -61,7 +69,7 @@
       <div class="graphInfoContainer" v-if="operState === 0 || operState === 1">
         <div class="graphInfoFirst">
           <span class="graphInfoName">系统图名称</span>
-          <span class="graphInfoFirstEdit">编辑</span>
+          <span class="graphInfoFirstEdit" @click="intoEditState">编辑</span>
         </div>
         <div class="graphInfoContent">
           <span>高压系统1#系统图</span>
@@ -102,16 +110,165 @@
           <span>草稿</span>
         </div>
       </div>
-      <div></div>
+      <div class="graphRegion">
+        <graph ref="graphc" @click="graphClickCall"></graph>
+      </div>
+      <div class="rightDetail" v-if="selGraphPartType != -1">
+        <div v-if="selGraphPartType == 1">
+          <div class="title titleMargin">设备类</div>
+          <div class="titleText eqName" v-text="selEquip.name">进线柜</div>
+          <div class="detailSplitLine"></div>
+          <div class="title titleMargin">
+            <span>x</span>
+            <span
+              class="coridTitleText titleText"
+              v-text="(selEquip.absolutePosition || {}).x"
+              >100</span
+            >
+            <span class="coridTitle2">y</span>
+            <span
+              class="coridTitleText titleText"
+              v-text="(selEquip.absolutePosition || {}).y"
+              >100</span
+            >
+          </div>
+          <div class="title titleMargin">
+            <span>比例</span>
+            <span class="scaleTitleText titleText">100%</span>
+          </div>
+          <div class="detailSplitLine"></div>
+          <div class="title titleMargin">锚点</div>
+          <div
+            class="anchorContainer"
+            v-for="anchor in selEquip.anchorArr"
+            :key="anchor.name"
+          >
+            <span v-text="anchor.name">T3</span>
+            <span>已连接</span>
+          </div>
+        </div>
+        <div v-if="selGraphPartType == 2">
+          <div class="title titleMargin">连线</div>
+          <div class="detailSplitLine"></div>
+          <div>
+            <div class="title titleMargin">起点</div>
+            <div class="coridGroup title">
+              <span>x</span>
+              <span class="coridTitleText titleText">100</span>
+              <span class="coridTitle2">y</span>
+              <span class="coridTitleText titleText">100</span>
+            </div>
+          </div>
+          <div>
+            <div class="title titleMargin">拐点1</div>
+            <div class="coridGroup title">
+              <span>x</span>
+              <span class="coridTitleText titleText">100</span>
+              <span class="coridTitle2">y</span>
+              <span class="coridTitleText titleText">100</span>
+            </div>
+          </div>
+          <div class="detailSplitLine"></div>
+          <div class="title titleMargin">连接关系</div>
+          <div class="titleMargin">
+            <el-select
+              v-model="selLineStartPoint"
+              value-key="id"
+              @change="selStartPointChange"
+            >
+              <div slot="prefix" class="selectPrefix">起点</div>
+              <el-option
+                v-for="item in lineStartPointArr"
+                :key="item.id"
+                :label="item.name"
+                :value="item"
+              >
+              </el-option>
+            </el-select>
+          </div>
+          <div class="titleMargin">
+            <el-select
+              v-model="selLineEndPoint"
+              value-key="id"
+              @change="selEndPointChange"
+            >
+              <div slot="prefix" class="selectPrefix">终点</div>
+              <el-option
+                v-for="item in lineEndPointArr"
+                :key="item.id"
+                :label="item.name"
+                :value="item"
+              >
+              </el-option>
+            </el-select>
+          </div>
+        </div>
+        <div v-if="selGraphPartType == 3">
+          <div class="title titleMargin">文字</div>
+          <div class="titleText eqName">1#进线柜</div>
+          <div class="detailSplitLine"></div>
+          <div class="title titleMargin">
+            <span>x</span>
+            <span class="coridTitleText titleText">100</span>
+            <span class="coridTitle2">y</span>
+            <span class="coridTitleText titleText">100</span>
+          </div>
+          <div class="detailSplitLine"></div>
+          <div class="title titleMargin">字体样式</div>
+          <div class="titleMargin fontSizeContainer">
+            <img
+              src="@/assets/images/systemGraph/fontStyle.svg"
+              class="fontStyleSvg"
+            />
+            <el-select
+              v-model="selFontSize"
+              value-key="id"
+              @change="selFontSizeChange"
+              placeholder=""
+            >
+              <el-option
+                v-for="item in fontSizeArr"
+                :key="item.id"
+                :label="item.name"
+                :value="item"
+              >
+              </el-option>
+            </el-select>
+          </div>
+          <div class="title titleMargin">字体颜色</div>
+          <div class="titleMargin fontColor">
+            <input type="color" v-model="fontColor" />
+            <div v-text="fontColor"></div>
+            <div>100%</div>
+          </div>
+          <div class="title titleMargin">背景颜色</div>
+          <div class="titleMargin fontColor">
+            <input type="color" v-model="backColor" />
+            <div v-text="backColor"></div>
+            <div>100%</div>
+          </div>
+        </div>
+        <div class="delBtn" v-if="selGraphPartType == 1">删除设备</div>
+        <div class="delBtn" v-if="selGraphPartType == 2">删除管线</div>
+        <div class="delBtn" v-if="selGraphPartType == 3">删除文字</div>
+      </div>
     </div>
 
-    <addGraph :isVisible="operState == 2"></addGraph>
+    <addGraph
+      :isVisible="operState == 2"
+      @created="createSuccessed"
+      v-if="operState == 2"
+    ></addGraph>
   </div>
 </template>
 <script>
-import { mapState } from "vuex";
-import { sysGraphController } from "@/controller/sysGraphController";
-import addGraph from './addGraph.vue'
+import { graphStateEnum } from "@/controller/systemGraph/graphStateEnum";
+import { sysGraphController } from "@/controller/systemGraph/sysGraphController";
+import addGraph from "./addGraph.vue";
+import graph from "./graph.vue";
+import { logicConfig } from "@/logicConfig";
+import { Message } from "element-ui";
+import Vue from "vue";
 
 export default {
   props: [],
@@ -147,64 +304,213 @@ export default {
       operState: -1,
       //系统图ID
       diagramId: "",
+      /**
+       * 选择的系统图上的区域的类型
+       * -1 什么也没选; 1 设备;    2 线;   3 文字
+       */
+      selGraphPartType: -1,
+      //线的起点数组,用于右侧详情选择
+      lineStartPointArr: [
+        {
+          id: "111",
+          name: "1#设备-B1",
+        },
+        {
+          id: "222",
+          name: "1#设备-B2",
+        },
+      ],
+      //选择的线的起点,用于右侧详情选择
+      selLineStartPoint: {
+        id: "111",
+        name: "1#设备-B1",
+      },
+      //线的终点数组,用于右侧详情选择
+      lineEndPointArr: [
+        {
+          id: "111",
+          name: "2#设备-B1",
+        },
+        {
+          id: "222",
+          name: "2#设备-B2",
+        },
+      ],
+      //选择的线的终点,用于右侧详情选择
+      selLineEndPoint: {
+        id: "111",
+        name: "2#设备-B1",
+      },
+      //字号数组
+      fontSizeArr: [
+        {
+          id: 12,
+          name: "12px",
+        },
+        {
+          id: 14,
+          name: "14px",
+        },
+        {
+          id: 16,
+          name: "16px",
+        },
+      ],
+      //选择的字号
+      selFontSize: {},
+      //字体颜色
+      fontColor: "#eb5757",
+      //背景颜色
+      backColor: "#ffffff",
+      //系统图数据
+      graphInfo: {},
+      /**
+       * 选择的设备,格式如下:
+       * {
+            id: "",
+            name:'',
+            legendObj: {
+              content: "图的地址或base64串",
+              size: {
+                width: 12,
+                height: 12,
+              },
+            },
+            //设备的绝对位置
+            absolutePosition: {
+              x: 1,
+              y: 1,
+            },
+            anchorArr:[{
+              name:'锚点名称',
+              //锚点相对于设备图例的位置
+              relativePosition:{
+                x:1,y:1
+              }
+            }]
+          }
+       */
+      selEquip: {},
     };
   },
-  computed: {
-    ...mapState(["projects"]),
-  },
+  computed: {},
   methods: {
-    //取消创建
-    cancelCreate: function () {
-      window.close();
+    /**
+     * 新建成功后执行的操作
+     * graphInfo 系统图数据
+     */
+    createSuccessed: function (graphInfo) {
+      //进入编辑状态
+      this.operState = 1;
+      this.graphInfo = graphInfo;
+      this.$refs.graphc.drawEntry(graphInfo);
+    },
+    //线的起点选择事件
+    selStartPointChange: function () {
+      console.log(this.selLineStartPoint);
     },
-    //选择项目后要查询该项目下的专业、系统类型、系统实例
-    selProjectChange: async function () {
+    //线的终点选择事件
+    selEndPointChange: function () {
+      console.log(this.selLineEndPoint);
+    },
+    //字号选择事件
+    selFontSizeChange: function () {},
+    //根据系统图ID获取系统图数据
+    getDiagramById: async function () {
       this.fullscreenLoading = true;
-      this.systemInsArr = [];
-      try {
-        this.systemInsArr = await sysGraphController.getSysInstanceByProject(
-          this.selProject.id,
-          this.selProject.groupCode
-        );
-      } catch (error) {
-        console.error(error);
+      var resultObj = await sysGraphController.getDiagramById(this.diagramId);
+      if (resultObj.result != logicConfig.resultObj.success) {
+        this.fullscreenLoading = false;
+        Message.error(resultObj.reason);
+        return;
       }
+      this.graphInfo = resultObj.data;
+      this.fullscreenLoading = false;
+    },
+    //进入编辑模式
+    intoEditState: function () {
+      this.operState = 1;
+    },
+    /**
+     * 设备、线、文本点击事件的回调
+     * dataObj 解析后的数据
+     * type 1 设备;  2 线;  3 文本
+     */
+    graphClickCall: function (dataObj, type) {
+      this.selGraphPartType = type;
+      this.selEquip = dataObj || {};
+      var _this = this;
+      Vue.nextTick(function () {
+        _this.$refs.graphc.resetDraw();
+      });
+    },
+    /**
+     * 放弃编辑按钮事件
+     */
+    cancelClick: function () {
+      this.operState = 0;
+    },
+    //上架系统图
+    publishGraph: async function () {
+      this.fullscreenLoading = true;
+      var resultObj = await sysGraphController.publishSysGraph(this.diagramId);
       this.fullscreenLoading = false;
+      switch (resultObj.result) {
+        case logicConfig.resultObj.success:
+          this.graphInfo.extraProps.state = graphStateEnum.Publish;
+          return Message.success("上架成功");
+        case logicConfig.resultObj.failure:
+          return Message.success("上架失败,原因:" + (resultObj.reason || ""));
+      }
     },
-    //系统实例选择事件
-    instanceChange: async function () {
+    //下架系统图
+    draftGraph: async function () {
       this.fullscreenLoading = true;
-      try {
-        //此时的数组内为选择的最低级节点,即系统实例
-        var checkedNodes = this.$refs.instanceCascader.getCheckedNodes();
-        //系统类型
-        var typeNode = checkedNodes[0].parent;
-        //查询系统类型下的系统模版
-        var templateArr = await sysGraphController.getTemplateBySysCode(
-          typeNode.data.code
-        );
-        this.systemTemplateArr = templateArr;
-      } catch (error) {
-        console.error(error);
+      var resultObj = await sysGraphController.draftGraph(this.diagramId);
+      this.fullscreenLoading = false;
+      switch (resultObj.result) {
+        case logicConfig.resultObj.success:
+          this.graphInfo.extraProps.state = graphStateEnum.Draft;
+          return Message.success("下架成功");
+        case logicConfig.resultObj.failure:
+          return Message.success("下架失败,原因:" + (resultObj.reason || ""));
       }
+    },
+    //删除系统图
+    delGraph: async function () {
+      this.fullscreenLoading = true;
+      var resultObj = await sysGraphController.delSysGraph(this.diagramId);
       this.fullscreenLoading = false;
+      switch (resultObj.result) {
+        case logicConfig.resultObj.success:
+          return Message.success("删除图纸成功");
+        case logicConfig.resultObj.failure:
+          return Message.success(
+            "删除图纸失败,原因:" + (resultObj.reason || "")
+          );
+      }
     },
-    //新增按钮事件
-    
   },
   created() {
     this.operState = !this.$route.query.ost
       ? -1
       : parseInt(this.$route.query.ost);
-    this.diagramId = !this.$route.query.did
-      ? -1
-      : parseInt(this.$route.query.did);
+    this.diagramId = !this.$route.query.did ? -1 : this.$route.query.did;
     this.selectScale = this.scaleArr[3];
   },
-
-  mounted() {},
+  mounted() {
+    var _this = this;
+    (async function () {
+      //操作状态  0 预览; 1 编辑;  2 新建
+      if (_this.operState === 0 || _this.operState === 1) {
+        await _this.getDiagramById();
+        _this.$refs.graphc.drawEntry(_this.graphInfo);
+      }
+    })();
+  },
   components: {
-      addGraph
+    addGraph,
+    graph,
   },
 };
 </script>
@@ -222,6 +528,7 @@ export default {
   box-shadow: 0px 2px 10px rgb(31 36 41 / 10%);
   display: flex;
   flex-direction: column;
+  z-index: 2;
 }
 
 #divGraphEdit .firstOperDivContainer {
@@ -261,7 +568,6 @@ export default {
 
 #divGraphEdit .imgBar {
   margin-left: 33px;
-  vertical-align: middle;
 }
 
 #divGraphEdit .sanjiaoBar {
@@ -296,12 +602,10 @@ export default {
 }
 
 #divGraphEdit .imgLeftTop {
-  vertical-align: middle;
   margin-left: 26px;
 }
 
 #divGraphEdit .rightLeftTop {
-  vertical-align: middle;
   margin-left: 22px;
 }
 
@@ -345,4 +649,131 @@ export default {
   margin-top: 12px;
   margin-left: 36px;
 }
+
+#divGraphEdit .graphRegion {
+  flex: 1;
+  height: 100%;
+  overflow: hidden;
+}
+
+#divGraphEdit .rightDetail {
+  width: 200px;
+  height: 100%;
+  background: #fafafa;
+  box-shadow: -1px 0px 1px rgb(0 0 0 / 25%);
+  box-sizing: border-box;
+  padding: 6px 12px 12px 12px;
+}
+
+#divGraphEdit .rightDetail > div:first-child {
+  height: 100%;
+}
+
+#divGraphEdit .rightDetail .title {
+  color: #6f777f;
+  font-size: 12px;
+}
+
+#divGraphEdit .rightDetail .titleMargin {
+  margin-top: 19px;
+}
+
+#divGraphEdit .rightDetail .coridGroup {
+  margin-top: 9px;
+}
+
+#divGraphEdit .rightDetail .titleText {
+  font-size: 14px;
+  color: #000000;
+}
+
+#divGraphEdit .rightDetail .eqName {
+  margin-top: 11px;
+}
+
+#divGraphEdit .rightDetail .detailSplitLine {
+  width: 100%;
+  height: 0;
+  margin-top: 19px;
+  border-bottom: 1px solid #979797;
+}
+
+#divGraphEdit .rightDetail .coridTitle2 {
+  margin-left: 45px;
+}
+
+#divGraphEdit .rightDetail .coridTitleText {
+  margin-left: 23px;
+}
+
+#divGraphEdit .rightDetail .scaleTitleText {
+  margin-left: 6px;
+}
+
+#divGraphEdit .rightDetail .anchorContainer {
+  margin-top: 15px;
+}
+
+#divGraphEdit .rightDetail .anchorContainer > span:last-child {
+  margin-left: 22px;
+}
+
+#divGraphEdit .rightDetail .delBtn {
+  color: #eb5757;
+  position: absolute;
+  bottom: 16px;
+  margin-left: 62px;
+}
+
+#divGraphEdit .rightDetail .selectPrefix {
+  color: #000000;
+  font-size: 14px;
+  height: 100%;
+  line-height: 32px;
+}
+
+#divGraphEdit .rightDetail .el-input__inner {
+  padding-left: 42px;
+}
+
+#divGraphEdit .rightDetail .fontSizeContainer .el-input__inner {
+  padding: 0 15px;
+  width: 80px;
+}
+
+#divGraphEdit .rightDetail .fontSizeContainer .el-select {
+  margin-left: 42px;
+}
+
+#divGraphEdit .rightDetail .fontColor {
+  position: relative;
+}
+
+#divGraphEdit .rightDetail .fontColor input {
+  border: none;
+  background: none;
+  width: 30px;
+  height: 31px;
+  padding: 0;
+  top: 0;
+  bottom: 0;
+  position: absolute;
+}
+
+#divGraphEdit .rightDetail .fontColor > div {
+  line-height: 31px;
+  display: inline-block;
+}
+
+#divGraphEdit .rightDetail .fontColor div:nth-child(2) {
+  margin-left: 43px;
+}
+
+#divGraphEdit .rightDetail .fontColor div:nth-child(3) {
+  margin-left: 16px;
+}
+
+#divGraphEdit img {
+  vertical-align: middle;
+}
 </style>

+ 422 - 0
src/components/systemGraph/graph.vue

@@ -0,0 +1,422 @@
+<template>
+  <div :id="maxContainerId" class="graphParentContainer"></div>
+</template>
+<script>
+import * as PIXI from "pixi.js";
+
+export default {
+  props: [],
+  data() {
+    return {
+      maxContainerId:
+        new Date().getTime().toString() +
+        "_" +
+        Math.random().toString().substring(2),
+      /*
+       * 设备数组格式如下
+       * {
+            id: "",
+            name:'',
+            legendObj: {
+              content: "图的地址或base64串",
+              size: {
+                width: 12,
+                height: 12,
+              },
+            },
+            //设备的绝对位置
+            absolutePosition: {
+              x: 1,
+              y: 1,
+            },
+            anchorArr:[{
+              name:'锚点名称',
+              //锚点相对于设备图例的位置
+              relativePosition:{
+                x:1,y:1
+              }
+            }]
+          }
+      */
+      nodeArr: [],
+      //线数组
+      lineArr: [],
+      //文本数组
+      labelArr: [],
+      //存放图形用的一些信息点
+      canvasProObj: {
+        //基于canvas画布的中心点坐标,需要动态计算得到
+        centerPointerPx: { x: 0, y: 0 },
+        //原始缩放比例,动态计算得到的,因为图形默认显示时是要适应容器大小的,所以相比原始坐标会有比例变化
+        originalScale: 1,
+        //x轴差值,通过此值让x轴左右两端对称
+        xJiaValue: 0,
+        //y轴差值,通过此值让y轴上下两端对称
+        yJiaValue: 0,
+        //缓存纹理对象
+        textureSource: {},
+        //缩放系数
+        pixiScale: 1,
+        //原点X坐标
+        positionPxX: 0,
+        //原点Y坐标
+        positionPxY: 0,
+        //缩放时每次变化的递进值
+        deep: 0.1,
+        //鼠标状态,0 普通状态;-1 鼠标按下
+        mouseState: 0,
+        //上一个鼠标位置信息
+        prevMousePosition: {},
+      },
+    };
+  },
+  computed: {},
+  methods: {
+    //绘图入口
+    drawEntry: function (graphInfo) {
+      //把原始数据转为易于绘图的数据
+      var graphDataObj = this.parseDataToDraw(graphInfo);
+      this.nodeArr = graphDataObj.nodeArr;
+      this.lineArr = graphDataObj.lineArr;
+      this.labelArr = graphDataObj.labelArr;
+
+      this.drawGraph();
+    },
+    //重绘
+    resetDraw: function () {
+      this.drawGraph();
+    },
+    //绘图
+    drawGraph: function () {
+      var _this = this;
+      // let type = "WebGL";
+      // if (!PIXI.utils.isWebGLSupported()) {
+      //   type = "canvas";
+      // }
+
+      var pixiContainer = document.getElementById(this.maxContainerId);
+
+      //--------------------------------------------创建舞台
+      //存在舞台时,先清空舞台内的所有元素
+      if (!!_this.pixiApp) {
+        while (_this.pixiApp.stage.children.length > 0) {
+          _this.pixiApp.stage.removeChildAt(0);
+        }
+      }
+
+      var pixiApp;
+      if (_this.pixiApp == null) {
+        pixiApp = new PIXI.Application({
+          width: pixiContainer.clientWidth, // default: 800 宽度
+          height: pixiContainer.clientHeight, // default: 600 高度
+          antialias: true, // default: false 反锯齿
+          transparent: true, // default: false 透明度
+          resolution: 1, // default: 1 分辨率
+          //backgroundColor: "0xffffff",
+        });
+        pixiApp.renderer.autoResize = true;
+        pixiContainer.appendChild(pixiApp.view);
+        _this.pixiApp = pixiApp;
+      } else pixiApp = _this.pixiApp;
+
+      _this.computeOriginZuobPosition();
+
+      //图例
+      _this.nodeArr.forEach((_dataObj) => {
+        //2022.1.30版,图例用矩形框代替
+        var graphicsRect = new PIXI.Graphics();
+        graphicsRect.lineStyle({
+          width: 1,
+          color: "0x0091ff",
+          alpha: 1,
+          alignment: 0.5,
+        });
+        let newCordObj = _this.convertCoordToLeftOrigina({
+          x: _dataObj.absolutePosition.x,
+          y: _dataObj.absolutePosition.y,
+        });
+        var newWidth =
+          _dataObj.legendObj.size.width * _this.canvasProObj.originalScale;
+        var newHeight =
+          _dataObj.legendObj.size.height * _this.canvasProObj.originalScale;
+        graphicsRect.drawRect(newCordObj.x, newCordObj.y, newWidth, newHeight);
+        graphicsRect.hitArea = graphicsRect.getBounds();
+
+        graphicsRect.name = _dataObj.id;
+        //启用事件
+        graphicsRect.interactive = true;
+        graphicsRect.on("click", (event) => {
+          _this.clickEventCall(event, 1);
+        });
+
+        pixiApp.stage.addChild(graphicsRect);
+        return;
+
+        var _legendObj = _dataObj.legendObj;
+        // 创建一个纹理
+        if (!_this.canvasProObj.textureSource[_legendObj.image.content]) {
+          _this.canvasProObj.textureSource[_legendObj.image.content] =
+            PIXI.Texture.from(_legendObj.image.content);
+        }
+
+        //加载纹理
+        var spriteInstanceCoord = _this.convertCoordToLeftOrigina({
+          x: _dataObj.position.x,
+          y: _dataObj.position.y,
+        });
+        var spriteWidth =
+          _legendObj.defaultSize.width * _this.canvasProObj.originalScale;
+        var spriteHeight =
+          _legendObj.defaultSize.height * _this.canvasProObj.originalScale;
+
+        var legendSprite = new PIXI.Sprite(
+          _this.canvasProObj.textureSource[_legendObj.image.content]
+        );
+        legendSprite.x = spriteInstanceCoord.x;
+        legendSprite.y = spriteInstanceCoord.y;
+        legendSprite.width = spriteWidth;
+        legendSprite.height = spriteHeight;
+        pixiApp.stage.addChild(legendSprite);
+      });
+
+      return;
+      //画线
+      _this.dataSource.view.diagram.lines.forEach((_cLine) => {
+        var lineColor = "0x" + _cLine.style.lineColor.substring(1);
+        var lineInstance = new PIXI.Graphics();
+        lineInstance.lineStyle(_cLine.style.lineWidth, lineColor, 1, 0, false);
+
+        var _newStart = _this.convertCoordToLeftOrigina({
+          x: _cLine.path[0].x,
+          y: _cLine.path[0].y,
+        });
+
+        var _newEnd = _this.convertCoordToLeftOrigina({
+          x: _cLine.path[1].x,
+          y: _cLine.path[1].y,
+        });
+
+        lineInstance.moveTo(_newStart.x, _newStart.y);
+        lineInstance.lineTo(_newEnd.x, _newEnd.y);
+
+        pixiApp.stage.addChild(lineInstance);
+      });
+    },
+    /**
+     * 解析数据成易于图形使用的格式
+     */
+    parseDataToDraw: function (graphInfo) {
+      var nodeArr = [];
+      //线数组
+      var lineArr = [];
+      //文本数组
+      var labelArr = [];
+
+      var rootContainerArr = graphInfo.template.frame.children;
+
+      parseNode(rootContainerArr, graphInfo.template.frame.location);
+
+      return {
+        nodeArr,
+        lineArr,
+        labelArr,
+      };
+
+      /**
+       * 递归解析设备(node)、文本(label)
+       * dataArr 参照后台接口返回的diagram对象里的graphInfo.template.frame.children
+       * absolutePosition 绝对位置{x:1,y:1}    其值是compType为"container"的每一级的location相加得出的值
+       */
+      function parseNode(dataArr, absolutePosition) {
+        dataArr.forEach((_dataObj) => {
+          var newAbsolutePosition = {
+            x: _dataObj.location.x + absolutePosition.x,
+            y: _dataObj.location.y + absolutePosition.y,
+          };
+          switch (_dataObj.compType) {
+            //容器
+            case "container":
+              parseNode(_dataObj.children, newAbsolutePosition);
+              break;
+            //设备
+            case "equipmentNode":
+              let anchorArr = [];
+              let anchorKeys = Object.keys(_dataObj.anchorLocations || {});
+              anchorKeys.forEach((_anchorKey) => {
+                anchorArr.push({
+                  name: _anchorKey,
+                  //锚点相对于设备图例的位置
+                  relativePosition: _dataObj.anchorLocations[_anchorKey],
+                });
+              });
+
+              nodeArr.push({
+                id: _dataObj.id,
+                name: _dataObj.dataObject.localName,
+                //2022.1.30版本图例以矩形框代替
+                legendObj: {
+                  content: "图的地址或base64串",
+                  size: {
+                    width: _dataObj.size.x,
+                    height: _dataObj.size.y,
+                  },
+                },
+                //设备的绝对位置
+                absolutePosition: newAbsolutePosition,
+                anchorArr: anchorArr,
+              });
+              break;
+          }
+        });
+      }
+    },
+    /**
+     * 1、X轴的原始坐标两端可能是不对称的;Y轴的原始坐标两端也可能是不对称的,所以计算各自的差值,以便把两端对称起来,以此把图形显示到正中间
+     * 2、计算原始坐标值的缩放系数,因为原始坐标和像素坐标是不对应的,所以要根据最大原始坐标(每一个坐标的绝对值进行比较)和最大像素坐标做比率缩放
+     * 3、计算中心点像素坐标
+     */
+    computeOriginZuobPosition: function () {
+      var _this = this;
+
+      var pixiContainer = document.getElementById(this.maxContainerId);
+      var maxPxX = pixiContainer.clientWidth;
+      var maxPxY = pixiContainer.clientHeight;
+      //基于canvas画布的中心点坐标
+      _this.canvasProObj.centerPointerPx = {
+        x: maxPxX / 2,
+        y: maxPxY / 2,
+      };
+
+      var originaMinX = null, //原始最小坐标X
+        originaMaxX = null, //原始最大坐标X
+        originaMinY = null, //原始最小坐标Y
+        originaMaxY = null; //原始最大坐标Y
+
+      /**
+       * 取得X轴的原始最小坐标和最大坐标、
+       * 取得Y轴的原始最小坐标和最大坐标、
+       */
+      compute();
+
+      //计算X轴差值
+      var xJiaValue = (maxPxX - originaMaxX - originaMinX) / 2;
+      xJiaValue = originaMinX + xJiaValue < 0 ? 0 - originaMinX : xJiaValue;
+
+      //计算Y轴差值
+      var yJiaValue = (maxPxY - originaMaxY - originaMinY) / 2;
+      yJiaValue = originaMinY + yJiaValue < 0 ? 0 - originaMinY : yJiaValue;
+
+      _this.canvasProObj.xJiaValue = xJiaValue;
+      _this.canvasProObj.yJiaValue = yJiaValue;
+
+      //让每一个的X、Y坐标加上差值,改为在画图时再加差值,这样就减少了此处的循环
+      setScale();
+
+      /**
+       * 取得X轴的原始最小坐标和最大坐标、
+       * 取得Y轴的原始最小坐标和最大坐标、
+       */
+      function compute() {
+        _this.nodeArr.forEach((_c) => {
+          var _legendObj = _c.legendObj;
+          originaMinX =
+            originaMinX == null
+              ? _c.absolutePosition.x
+              : Math.min(originaMinX, _c.absolutePosition.x);
+          originaMaxX =
+            originaMaxX == null
+              ? _c.absolutePosition.x + _legendObj.size.width
+              : Math.max(
+                  originaMaxX,
+                  _c.absolutePosition.x + _legendObj.size.width
+                );
+
+          originaMinY =
+            originaMinY == null ? _c.absolutePosition.y : Math.min(originaMinY);
+
+          originaMaxY =
+            originaMaxY == null
+              ? _c.absolutePosition.y + _legendObj.size.height
+              : Math.max(
+                  originaMaxY,
+                  _c.absolutePosition.y + _legendObj.size.height
+                );
+        });
+
+        _this.lineArr.forEach((_cLine) => {
+          _cLine.path.forEach((_c) => {
+            originaMinX =
+              originaMinX == null ? _c.x : Math.min(originaMinX, _c.x);
+            originaMaxX =
+              originaMaxX == null ? _c.x : Math.max(originaMaxX, _c.x);
+
+            originaMinY =
+              originaMinY == null ? _c.y : Math.min(originaMinY, _c.y);
+            originaMaxY =
+              originaMaxY == null ? _c.y : Math.max(originaMaxY, _c.y);
+          });
+        });
+      }
+
+      //计算缩放系数
+      function setScale() {
+        var xScale = maxPxX / (originaMaxX + xJiaValue);
+        var yScale = maxPxY / (originaMaxY + yJiaValue);
+        _this.canvasProObj.originalScale = Math.min(xScale, yScale);
+        //当图形区域能显示全的时候不再进行缩放
+        _this.canvasProObj.originalScale = Math.min(
+          1,
+          _this.canvasProObj.originalScale
+        );
+      }
+    },
+    /**
+     * 把坐标转为缩放后的坐标
+     * _obj:{x:1,y:1}
+     */
+    convertCoordToLeftOrigina: function (_obj) {
+      _obj.x =
+        (_obj.x + this.canvasProObj.xJiaValue) *
+        this.canvasProObj.originalScale;
+      _obj.y =
+        (_obj.y + this.canvasProObj.yJiaValue) *
+        this.canvasProObj.originalScale;
+
+      return _obj;
+    },
+
+    /**
+     * 设备、线、文本点击事件的回调
+     * type 1 设备;  2 线;  3 文本
+     */
+    clickEventCall: function (event, type) {
+      var graphInstance = event.target || event.currentTarget;
+      var dataId = graphInstance.name;
+      var dataArr =
+        type == 1
+          ? this.nodeArr
+          : type == 2
+          ? this.lineArr
+          : type == 3
+          ? this.labelArr
+          : [];
+      var dataObj = dataArr.filter((_data) => {
+        return _data.id == dataId;
+      })[0];
+      this.$emit("click", dataObj, type);
+    },
+  },
+  created() {},
+
+  mounted() {},
+  components: {},
+};
+</script>
+
+<style scoped>
+.graphParentContainer {
+  width: 100%;
+  height: 100%;
+  background: #ffffff;
+}
+</style>

+ 34 - 13
src/components/systemGraph/index.vue

@@ -29,9 +29,13 @@
           <el-table-column prop="createTime" label="创建时间">
           </el-table-column>
           <el-table-column label="操作" width="100">
-            <template>
-              <el-button type="text" size="small">预览</el-button>
-              <el-button type="text" size="small">编辑</el-button>
+            <template slot-scope="scope">
+              <el-button type="text" size="small" @click="viewGraph(scope.row)"
+                >预览</el-button
+              >
+              <el-button type="text" size="small" @click="editGraph(scope.row)"
+                >编辑</el-button
+              >
             </template>
           </el-table-column>
         </el-table>
@@ -58,7 +62,7 @@
 import { mapState } from "vuex";
 import { logicConfig } from "@/logicConfig";
 import packageConfig from "../../../package.json";
-import { sysGraphController } from "@/controller/sysGraphController";
+import { sysGraphController } from "@/controller/systemGraph/sysGraphController";
 
 export default {
   props: [],
@@ -101,15 +105,20 @@ export default {
     //新建系统图
     createSystemGraph: function () {
       this.state = 2;
-      window.open(
-        "/" +
-          packageConfig.name +
-          logicConfig.routerNameConfig.systemGraphEditName +
-          "?ost=" +
-          this.state +
-          "&did=" +
-          (this.selDiagram.id || "")
-      );
+      this.selDiagram = {};
+      this.openGraphPage();
+    },
+    //预览系统图
+    viewGraph: function (item) {
+      this.state = 0;
+      this.selDiagram = item;
+      this.openGraphPage();
+    },
+    //编辑系统图
+    editGraph: function (item) {
+      this.state = 1;
+      this.selDiagram = item;
+      this.openGraphPage();
     },
     //从allGraphArr中取出对应页数的数据
     getCurrPageData: function () {
@@ -138,6 +147,18 @@ export default {
         this.fullscreenLoading = false;
       }
     },
+    //打开系统图新增、预览、编辑页面
+    openGraphPage: function () {
+      window.open(
+        "/" +
+          packageConfig.name +
+          logicConfig.routerNameConfig.systemGraphEditName +
+          "?ost=" +
+          this.state +
+          "&did=" +
+          (this.selDiagram.id || "")
+      );
+    },
   },
   created() {
     this.getData();

+ 0 - 118
src/controller/sysGraphController.ts

@@ -1,118 +0,0 @@
-import { sysGraphHttpUtils } from "@/utils/http/sysGraphHttpUtils";
-import { logicConfig } from "@/logicConfig";
-
-export class sysGraphController {
-    private static sysGraphHttpUtilsInstance = new sysGraphHttpUtils();
-    /**
-     * 查询系统图列表
-     * @param grpphName 系统图名称
-     */
-    static async getDiagrams(grpphName: string) {
-        var resultObj = await this.sysGraphHttpUtilsInstance.postRequest('/diagram/getDiagrams', { name: grpphName });
-        if (resultObj.result != logicConfig.resultObj.success)
-            console.error(resultObj.reason);
-        var newDataArr = [];
-        var dataArr = resultObj.data || [];
-        dataArr.forEach(_c => {
-            //图状态(Draft: 未发布, WaitCheck: 待审核, Checked: 审核完成, Recyle: 回收站, Publish: 发布)
-            _c.stateName = _c.state == 'Draft' ? '草稿' : _c.state == 'Publish' ? '上架' : _c.state == 'Recyle' ? '下架' : '';
-            newDataArr.push({
-                id: _c.id,
-                name: _c.name,
-                sysType: _c.system,
-                sysInstance: _c.systemId,
-                sysTemplate: _c.templateId,
-                //state: i % 3 == 1 ? 'Publish' : i % 3 == 2 ? 'Draft' : 'Recyle',
-                createTime: '2021/12/27 13:13'
-            });
-        });
-        return newDataArr;
-    }
-
-    /**
-     * 根据项目查询该项目下的专业>系统类型>系统实例
-     * @param projectId 项目ID
-     * @param groupCode 集团编码
-     */
-    static async getSysInstanceByProject(projectId: string, groupCode: string) {
-        var url = '/diagram/major/system/instance?projectId=' + projectId + '&groupCode=' + groupCode;
-        var resultObj = await this.sysGraphHttpUtilsInstance.postRequest(url, {});
-        if (resultObj.result != logicConfig.resultObj.success)
-            console.error(resultObj.reason);
-        var dataArr = resultObj.data || [];
-        var newDataArr = [];
-
-        dataArr.forEach(_c => {
-            //_c为专业
-            let zhuanye = { value: _c.id, label: _c.label, code: _c.code, children: [] };
-            let sysTypeArr = [];
-            (_c.children || []).forEach(_c2 => {
-                //_c2为系统类型
-                let sysType = { value: _c2.id, label: _c2.aliasName, code: _c2.code, children: [] };
-                let sysInstanceArr = [];
-                (_c2.children || []).forEach(_c3 => {
-                    //_c3为系统实例
-                    sysInstanceArr.push({ value: _c3.id, label: _c3.name, code: _c3.code });
-                });
-                sysType.children = sysInstanceArr;
-                sysTypeArr.push(sysType);
-            });
-            zhuanye.children = sysTypeArr;
-            newDataArr.push(zhuanye);
-        });
-        return newDataArr;
-    }
-
-    /**
-     * 根据系统类型查询系统图模板,数据结构:系统图类型 ->  系统图模版
-     * @param sysCode 系统类型编码
-     */
-    static async getTemplateBySysCode(sysCode: string) {
-        var url = '/diagram/systemType/template';
-        var resultObj = await this.sysGraphHttpUtilsInstance.postRequest(url, { system: sysCode });
-        if (resultObj.result != logicConfig.resultObj.success)
-            console.error(resultObj.reason);
-        var dataArr = resultObj.data || [];
-        var newDataArr = [];
-
-        dataArr.forEach(_sysGraphType => {
-            //_sysGraphType为系统图类型
-            let sysGraphType = { value: _sysGraphType.id, label: _sysGraphType.name, code: _sysGraphType.code, children: [] };
-            let templateArr = [];
-            (_sysGraphType.children || []).forEach(_template => {
-                //_template为系统类型
-                let template = { value: _template.id, label: _template.name, code: _template.code };
-                templateArr.push(template);
-            });
-            sysGraphType.children = templateArr;
-            newDataArr.push(sysGraphType);
-        });
-        return newDataArr;
-    }
-
-    /**
-     * 新增系统图
-     * @param _paramObj {name:'系统图名称',type:'系统图类型编码',templateId:'引用的模板id',system:'所属的系统类型',projectId:'项目id',systemId:'对应的系统实例id',groupCode:'集团编码',}
-     */
-    static async createSysGraph(_paramObj: any) {
-        var url = '/diagram/newDiagram';
-        var resultObj = await this.sysGraphHttpUtilsInstance.postRequest(url, _paramObj);
-        if (resultObj.result != logicConfig.resultObj.success) {
-            console.error(resultObj.reason);
-            return resultObj;
-        }
-
-        var dataObj = resultObj.data || {};
-        if (!dataObj.id)
-            return { result: logicConfig.resultObj.failure, reason: '确实系统图ID' };
-
-        //新增成功后,要加载数据
-        var loadDataUrl = '/diagram/loadData';
-        var loadResultObj = await this.sysGraphHttpUtilsInstance.postRequest(loadDataUrl, { id: dataObj.id });
-        if(loadResultObj.result!=logicConfig.resultObj.success){
-            return { result: logicConfig.resultObj.failure, reason: '加载模板数据失败,原因:' + loadResultObj.reason };
-        }
-console.log(loadResultObj.data);
-        return loadResultObj.data;
-    }
-}

+ 15 - 0
src/controller/systemGraph/graphStateEnum.ts

@@ -0,0 +1,15 @@
+/**
+ * 系统图状态枚举
+ */
+export enum graphStateEnum {
+    //未发布
+    Draft = "Draft",
+    //待审核
+    WaitCheck = "WaitCheck",
+    //审核完成
+    Checked = "Checked",
+    //回收站
+    Recyle = "Recyle",
+    //发布
+    Publish = "Publish",
+}

Datei-Diff unterdrückt, da er zu groß ist
+ 10383 - 0
src/controller/systemGraph/sysGraphController.ts


+ 2 - 2
vue.config.js

@@ -22,8 +22,8 @@ module.exports = {
       },
       '/sysGraphService': {
         // 此处的写法,目的是为了 将 /2dapi/jsonz 替换target的值
-        target: 'http://127.0.0.1:8833',
-        // target: 'http://develop.ysbdtp.com/adm-diagram',
+        // target: 'http://127.0.0.1:8833',
+        target: 'http://develop.ysbdtp.com/adm-diagram',
         // 允许跨域
         changeOrigin: true,
         pathRewrite: {