haojianlong vor 3 Jahren
Ursprung
Commit
f7e85319c4

+ 10 - 0
src/api/datacenter.ts

@@ -30,3 +30,13 @@ export function PartiInstancQuery(postParams: any): any {
     // }
     return httputils.postJson(`${baseApi}/object/zone/query`, postParams);
 }
+
+// 查询设备的所有信息点数组
+export function queryDict(postParams: any): any {
+    return httputils.postJson(`${baseApi}/dict/query`, postParams)
+}
+
+// 查询设备信息
+export function queryEquipMsg(postParams: any): any {
+    return httputils.postJson(`${baseApi}/object/equip/query`, postParams)
+}

+ 14 - 0
src/components/editview/basePlanEditer.vue

@@ -53,6 +53,7 @@ export default {
             initScale: 1,
             planLoading: true, //平面图顶部loading提示
             parser: null, //底图解析后的数据
+            isInitSave:false, //初始化保存
         };
     },
     computed: {
@@ -77,6 +78,13 @@ export default {
     },
     mounted() {
         window.vim = this;
+
+        // 如果为新建图、默认加载后保存使之生成缩略图
+        if(this.$route.query.version == "1.0.1"){
+           this.isInitSave = true
+        }else {
+            this.isInitSave = false
+        }
         // 获取 canvas 的宽高
         this.canvasWidth = this.$refs.basePlan.offsetWidth;
         this.canvasHeight = this.$refs.basePlan.offsetHeight - 10;
@@ -256,6 +264,10 @@ export default {
             this.view.DragMove = true;
             this.view.fitSceneToView();
             // 接口无规则字段时,在底图加载完成后关闭loading
+            // 加载完,如果符合条件,则走自动保存
+            if(this.isInitSave){
+                this.savePlanDraft();
+            }
             if (!this.planContent?.ruleList) {
                 this.planLoading = false;
             }
@@ -561,11 +573,13 @@ export default {
                             if (this.ruleNum === this.loadedRuleNum) this.loadMarkRelation();
                         }
                     }
+
                 }
             } else {
                 this.INITRULELIST([]);
                 if (this.ruleNum === this.loadedRuleNum) this.loadMarkRelation();
             }
+
             // 加载区域显示
             if (res.content.outline) {
                 const outline = res.content.outline;

+ 6 - 6
src/components/editview/leftToolBar/data.js

@@ -87,12 +87,12 @@ export const baseEditItems = [
                         icon: require("./../../../assets/images/leftImgs/" + "infoPoint.png"),
                         activeIcon: require("./../../../assets/images/leftImgs/" + "infoPoint" + "Active" + ".png"),
                     },
-                    {
-                        name: "设备组",
-                        id: "equipList",
-                        icon: require("./../../../assets/images/leftImgs/" + "equipList.png"),
-                        activeIcon: require("./../../../assets/images/leftImgs/" + "equipList" + "Active" + ".png"),
-                    },
+                    // {
+                    //     name: "设备组",
+                    //     id: "equipList",
+                    //     icon: require("./../../../assets/images/leftImgs/" + "equipList.png"),
+                    //     activeIcon: require("./../../../assets/images/leftImgs/" + "equipList" + "Active" + ".png"),
+                    // },
                     {
                         name: "通用实例",
                         id: "publicItem",

+ 103 - 0
src/components/editview/rightPropertyBar/Equation.vue

@@ -0,0 +1,103 @@
+<template>
+  <div class="Equation">
+    <div class="title">输入公式</div>
+    <ul>
+      <li>
+        <el-input
+          type="textarea"
+          :autosize="{ minRows: 2, maxRows: 4 }"
+          v-model="textMsg"
+        ></el-input>
+      </li>
+    </ul>
+  </div>
+</template>
+<script>
+import bus from "@/bus/bus";
+export default {
+  props: ["Equation"],
+  data() {
+    return {};
+  },
+
+  computed: {
+    textMsg: {
+      get: function(params) {
+        return this.Equation.text;
+      },
+      set: function(params) {
+        const oldV = this.Equation.text;
+        this.Equation.text = params;
+        bus.$emit("undoAttr", this.Equation, "text", oldV, params);
+      },
+    },
+  },
+};
+</script>
+<style lang="less" scoped>
+ul,
+li {
+  margin: 0;
+  padding: 0;
+  list-style-type: none;
+}
+.Equation {
+  .title {
+    height: 47px;
+    border-bottom: 1px solid #979797;
+    color: #646c73;
+    font-size: 16px;
+    padding-left: 12px;
+    box-sizing: border-box;
+  }
+  ul {
+    width: calc(~"100% - 24px");
+    margin: -1px 12px 0 12px;
+    li {
+      border-top: 1px solid #979797;
+      .small-title {
+        font-size: 12px;
+        color: #8d9399;
+        margin: 12px 0;
+      }
+      .property {
+        display: flex;
+        align-items: center;
+        justify-content: space-around;
+        .color-box {
+          display: flex;
+          align-items: center;
+          flex-direction: column;
+          .cololorSelect {
+            width: 32px;
+            height: 20px;
+            overflow: hidden;
+            position: relative;
+            margin: 4px 0;
+            .fix-box-1 {
+              margin-top: -8px;
+              margin-left: -8px;
+              /deep/ .el-color-picker__trigger {
+                width: 200px;
+                height: 200px;
+              }
+            }
+          }
+        }
+        .line-width {
+          display: flex;
+          align-items: center;
+          flex-direction: column;
+          margin-left: 8px;
+          position: relative;
+        }
+        span {
+          font-size: 12px;
+          color: #1f2429;
+          margin-top: 4px;
+        }
+      }
+    }
+  }
+}
+</style>

+ 230 - 0
src/components/editview/rightPropertyBar/InfoPoint.vue

@@ -0,0 +1,230 @@
+<!-- 通用信息点 -->
+
+<template>
+  <div class="InfoPoint">
+    <div class="title">通用信息点</div>
+    <el-form
+      label-position="top"
+      label-width="120px"
+      :model="formLabelAlign"
+      :rules="rules"
+      :validate-on-rule-change="true"
+      ref="infopointform"
+    >
+      <el-form-item label="全局编码" prop="EqId">
+        <el-input
+          @keyup.enter.native="submitForm"
+          @blur="submitForm"
+          placeholder="回车或失焦会促发请求"
+          v-model="formLabelAlign.EqId"
+        ></el-input>
+      </el-form-item>
+      <el-form-item label="设备类型(classCode)" prop="classCode">
+        <el-input
+          @keyup.enter.native="submitForm"
+          @blur="submitForm"
+          v-model="formLabelAlign.classCode"
+          placeholder="回车或失焦会促发请求"
+        ></el-input>
+      </el-form-item>
+      <el-form-item label="信息点编码(code)" prop="code">
+        <el-input
+          @keyup.enter.native="submitForm"
+          @blur="submitForm"
+           placeholder="回车或失焦会促发请求"
+          v-model="formLabelAlign.code"
+        ></el-input>
+      </el-form-item>
+      <el-form-item
+        label="信息点名称"
+        v-show="InfoItem && InfoItem.data.properties.infoData"
+      >
+        <el-input
+          @change="changeText"
+          v-model="formLabelAlign.subName"
+        ></el-input>
+      </el-form-item>
+    </el-form>
+  </div>
+</template>
+<script>
+import bus from "@/bus/bus";
+import { queryDict } from "@/api/datacenter";
+export default {
+  data() {
+    return {
+      text: "", //文本
+      formLabelAlign: {
+        EqId: "", //全局code(设备id)
+        classCode: "", //设备类型
+        code: "", //信息点编码
+        subName: "",
+      },
+      rules: {
+        // 校验规则
+        EqId: [{ required: true, message: "请输入全局编码", trigger: "blur" }],
+        classCode: [
+          { required: true, message: "请输入设备类型", trigger: "blur" },
+        ],
+        code: [
+          { required: true, message: "请输入信息点编码", trigger: "blur" },
+        ],
+      },
+      InfoItem: null, //信息点实例
+    };
+  },
+  methods: {
+    // 改变文字
+    changeText(val) {
+      bus.$emit("updateStyle", "text", val);
+    },
+    // 提交表单
+    submitForm() {
+      this.$refs["infopointform"].validate((valid) => {
+        // 做校验判断
+        if (valid) {
+          // 请求信息
+          this.queryMsg();
+        } else {
+          // this.$message.error("信息点参数请求失败!");
+          return false;
+        }
+      });
+    },
+    // 请求公共信息点
+    queryMsg() {
+      const data = {
+        filters: `classCode = '${this.formLabelAlign.classCode}';code = '${this.formLabelAlign.code}'`,
+      };
+      queryDict(data).then((res) => {
+        if (res && res.content && res.content.length) {
+          this.formLabelAlign.subName = res.content[0].aliasName;
+          this.changeText(this.formLabelAlign.subName);
+          // 获取到信息点信息存入实例中的infoData字段
+          if (this.InfoItem) {
+            this.InfoItem.data.properties.infoData = Object.assign(
+              res.content[0],
+              {
+                equipId: this.formLabelAlign.EqId,
+              }
+            );
+          }
+        } else {
+          this.changeText("信息点");
+          if (this.InfoItem) {
+            if (this.InfoItem.data.properties.infoData) {
+              this.$delete(this.InfoItem.data.properties, "infoData");
+            }
+          }
+        }
+      }).catch(()=>{
+         this.$message.error("信息点参数请求失败!");
+      })
+    },
+    // 获取到信息点
+    emitChoice(itemList) {
+      let itemType = null;
+      this.formLabelAlign.EqId = "";
+      this.formLabelAlign.classCode = "";
+      this.formLabelAlign.code = "";
+
+      this.InfoItem = null;
+      if (itemList.length == 1) {
+        const data = itemList[0].data
+          ? itemList[0].data
+          : itemList[0].legendData
+          ? itemList[0].legendData
+          : itemList[0].relationData
+          ? itemList[0].relationData
+          : null;
+        itemType = data.properties.type ? data.properties.type : "";
+      } else {
+        itemType = "";
+      }
+      if (itemType == "InfoPoint") {
+        this.InfoItem = itemList[0];
+        //赋值名称
+        this.formLabelAlign.subName = itemList[0].text;
+        if (itemList[0].data.properties.infoData) {
+          const data = itemList[0].data.properties.infoData;
+          this.formLabelAlign.EqId = data.equipId;
+          this.formLabelAlign.classCode = data.classCode;
+          this.formLabelAlign.code = data.code;
+        }
+      }
+    },
+  },
+  mounted() {
+    bus.$on("emitChoice", this.emitChoice);
+  },
+};
+</script>
+<style lang="less" scoped>
+ul,
+li {
+  margin: 0;
+  padding: 0;
+  list-style-type: none;
+}
+.InfoPoint {
+  padding: 0 12px 0 12px;
+  box-sizing: border-box;
+  .title {
+    height: 47px;
+    border-bottom: 1px solid #979797;
+    color: #646c73;
+    font-size: 16px;
+    padding-left: 12px;
+    box-sizing: border-box;
+  }
+  ul {
+    width: calc(~"100% - 24px");
+    margin: -1px 12px 0 12px;
+    li {
+      border-top: 1px solid #979797;
+      .small-title {
+        font-size: 12px;
+        color: #8d9399;
+        margin: 12px 0;
+      }
+      .property {
+        display: flex;
+        align-items: center;
+        justify-content: space-around;
+        .color-box {
+          display: flex;
+          align-items: center;
+          flex-direction: column;
+          .cololorSelect {
+            width: 32px;
+            height: 20px;
+            overflow: hidden;
+            position: relative;
+            margin: 4px 0;
+            .fix-box-1 {
+              margin-top: -8px;
+              margin-left: -8px;
+              /deep/ .el-color-picker__trigger {
+                width: 200px;
+                height: 200px;
+              }
+            }
+          }
+        }
+        .line-width {
+          display: flex;
+          align-items: center;
+          flex-direction: column;
+          margin-left: 8px;
+          position: relative;
+        }
+        span {
+          font-size: 12px;
+          color: #1f2429;
+          margin-top: 4px;
+        }
+      }
+    }
+  }
+}
+</style>

+ 209 - 0
src/components/editview/rightPropertyBar/PubEquip.vue

@@ -0,0 +1,209 @@
+<!-- 通用实例 -->
+
+<template>
+  <div class="InfoPoint">
+    <div class="title">通用信息点</div>
+    <el-form
+      label-position="top"
+      label-width="120px"
+      :model="formLabelAlign"
+      :rules="rules"
+      :validate-on-rule-change="true"
+      ref="infopointform"
+    >
+      <el-form-item label="全局编码" prop="EqId">
+        <el-input
+          @keyup.enter.native="submitForm"
+          @blur="submitForm"
+          placeholder="回车或失焦会促发请求"
+          v-model="formLabelAlign.EqId"
+        ></el-input>
+      </el-form-item>
+
+      <el-form-item
+        label="信息点名称"
+        v-show="Equipment && Equipment.data.properties.infoData"
+      >
+        <el-input
+          @change="changeText"
+          v-model="formLabelAlign.subName"
+        ></el-input>
+      </el-form-item>
+    </el-form>
+  </div>
+</template>
+<script>
+import bus from "@/bus/bus";
+import { queryDict,queryEquipMsg } from "@/api/datacenter";
+export default {
+  data() {
+    return {
+      text: "", //文本
+      formLabelAlign: {
+        EqId: "", //全局code(设备id)
+        classCode: "", //设备类型
+        code: "", //信息点编码
+        subName: "",
+      },
+      rules: {
+        // 校验规则
+        EqId: [{ required: true, message: "请输入全局编码", trigger: "blur" }],
+      },
+      Equipment: null, //信息点实例
+    };
+  },
+  methods: {
+    // 改变文字
+    changeText(val) {
+      bus.$emit("updateStyle", "text", val);
+    },
+    // 提交表单
+    submitForm() {
+      this.$refs["infopointform"].validate((valid) => {
+        // 做校验判断
+        if (valid) {
+          // 请求信息
+          this.queryMsg();
+        } else {
+          // this.$message.error("信息点参数请求失败!");
+          return false;
+        }
+      });
+    },
+    // 请求公共信息点
+    queryMsg() {
+      const data = {
+        filters: `id='${this.formLabelAlign.EqId}'`,
+      };
+      queryEquipMsg(data).then((res) => {
+        if (res && res.content && res.content.length) {
+          this.formLabelAlign.subName = res.content[0].name;
+          this.changeText(this.formLabelAlign.subName);
+          // 获取到信息点信息存入实例中的infoData字段
+          if (this.Equipment) {
+            this.Equipment.data.properties.infoData = Object.assign(
+              res.content[0],
+              {
+                equipId: this.formLabelAlign.EqId,
+              }
+            );
+          }
+        } else {
+          this.changeText("信息点");
+          if (this.Equipment) {
+            if (this.Equipment.data.properties.infoData) {
+              this.$delete(this.Equipment.data.properties, "infoData");
+            }
+          }
+        }
+      }).catch(()=>{
+         this.$message.error("信息点参数请求失败!");
+      })
+    },
+    // 获取到信息点
+    emitChoice(itemList) {
+      let itemType = null;
+      this.formLabelAlign.EqId = "";
+      this.formLabelAlign.classCode = "";
+      this.formLabelAlign.code = "";
+
+      this.Equipment = null;
+      if (itemList.length == 1) {
+        const data = itemList[0].data
+          ? itemList[0].data
+          : itemList[0].legendData
+          ? itemList[0].legendData
+          : itemList[0].relationData
+          ? itemList[0].relationData
+          : null;
+        itemType = data.properties.type ? data.properties.type : "";
+      } else {
+        itemType = "";
+      }
+      if (itemType == "PublicEquipment") {
+        this.Equipment = itemList[0];
+        //赋值名称
+
+        if (itemList[0].data.properties.infoData) {
+          const data = itemList[0].data.properties.infoData;
+          this.formLabelAlign.EqId = data.equipId;
+          this.formLabelAlign.classCode = data.classCode;
+          this.formLabelAlign.subName = data.name;
+        }
+      }
+    },
+  },
+  mounted() {
+    bus.$on("emitChoice", this.emitChoice);
+  },
+};
+</script>
+<style lang="less" scoped>
+ul,
+li {
+  margin: 0;
+  padding: 0;
+  list-style-type: none;
+}
+.InfoPoint {
+  padding: 0 12px 0 12px;
+  box-sizing: border-box;
+  .title {
+    height: 47px;
+    border-bottom: 1px solid #979797;
+    color: #646c73;
+    font-size: 16px;
+    padding-left: 12px;
+    box-sizing: border-box;
+  }
+  ul {
+    width: calc(~"100% - 24px");
+    margin: -1px 12px 0 12px;
+    li {
+      border-top: 1px solid #979797;
+      .small-title {
+        font-size: 12px;
+        color: #8d9399;
+        margin: 12px 0;
+      }
+      .property {
+        display: flex;
+        align-items: center;
+        justify-content: space-around;
+        .color-box {
+          display: flex;
+          align-items: center;
+          flex-direction: column;
+          .cololorSelect {
+            width: 32px;
+            height: 20px;
+            overflow: hidden;
+            position: relative;
+            margin: 4px 0;
+            .fix-box-1 {
+              margin-top: -8px;
+              margin-left: -8px;
+              /deep/ .el-color-picker__trigger {
+                width: 200px;
+                height: 200px;
+              }
+            }
+          }
+        }
+        .line-width {
+          display: flex;
+          align-items: center;
+          flex-direction: column;
+          margin-left: 8px;
+          position: relative;
+        }
+        span {
+          font-size: 12px;
+          color: #1f2429;
+          margin-top: 4px;
+        }
+      }
+    }
+  }
+}
+</style>

+ 18 - 3
src/components/editview/rightPropertyBar/property.vue

@@ -41,19 +41,30 @@
     ></BaseZone>
     <BaseView v-if="!itemObj"></BaseView>
     <BasePipe
-       :Pipe='itemObj'
+      :Pipe="itemObj"
       v-if="itemObj && itemType == 'BasePipe'"
     ></BasePipe>
+    <Equation
+      :Equation="itemObj"
+      v-if="itemObj && itemType == 'Equation'"
+    ></Equation>
+    <InfoPoint
+      v-show="itemObj && itemType == 'InfoPoint'"
+    ></InfoPoint>
+    <PubEquip v-show="itemObj && itemType == 'PublicEquipment'"></PubEquip>
   </div>
 </template>
 <script>
 import baseTextPro from "./baseTextPro.vue";
-import BasePipe from "./BasePipe.vue"
+import Equation from "./Equation.vue";
+import BasePipe from "./BasePipe.vue";
 import baseLinePro from "./baseLinePro.vue";
 import BaseGraphy from "./BaseGraphy";
 import BaseImagePro from "./BaseImagePro";
 import BgImagePro from "./BgImagePro";
 import BaseEquipment from "./BaseEquipment";
+import InfoPoint from "./InfoPoint"
+import PubEquip from "./PubEquip.vue"
 import BaseZone from "./BaseZone";
 import BaseView from "./BaseView";
 import bus from "@/bus/bus";
@@ -85,7 +96,10 @@ export default {
     BaseEquipment,
     BaseZone,
     BaseView,
-    BasePipe
+    BasePipe,
+    Equation,
+    InfoPoint,
+    PubEquip
   },
   data() {
     return {
@@ -126,6 +140,7 @@ export default {
           : null;
         this.itemType = data?.properties?.type ? data.properties.type : "";
         this.itemObj = itemList[0];
+        console.log('itemObj',this.itemObj)
       } else {
         this.itemType = "";
         this.itemObj = null;

+ 365 - 317
src/components/homeView/createPlanarDialog.vue

@@ -1,339 +1,387 @@
 <template>
-    <el-dialog
-        class="create-dialog"
-        title="新建画布"
-        width="600px"
-        :visible.sync="outerVisible"
-        :close-on-click-modal="false"
-        custom-class="createDialog"
-        @close="closeModal"
-    >
-        <div class="dialog-bodys">
-            <el-form :model="ruleForm" :rules="rules" ref="ruleForm" label-width="100px" class="demo-ruleForm" label-position="top">
-                <el-form-item label="所属楼层" prop="buildFloor">
-                    <el-cascader
-                        ref="buildFloor"
-                        style="width: 260px"
-                        v-model="ruleForm.buildFloor"
-                        :options="buildFloorData"
-                        :props="props"
-                        clearable
-                        size="small"
-                    ></el-cascader>
-                </el-form-item>
-                <el-form-item label="名称" prop="name">
-                    <el-input v-model="ruleForm.name" placeholder="请输入名称" size="small" :maxlength="20" @blur="nameBlur"></el-input>
-                </el-form-item>
-                <el-form-item label="标签" prop="resource">
-                    <div class="tagContainer">
-                        <el-tag :key="tag" v-for="tag in dynamicTags" closable :disable-transitions="false" @close="handleClose(tag)">
-                            {{ tag }}
-                        </el-tag>
-                        <el-input
-                            class="input-new-tag"
-                            v-if="inputVisible"
-                            v-model="inputValue"
-                            ref="saveTagInput"
-                            size="small"
-                            @keyup.enter.native="handleInputConfirm"
-                            @blur="handleInputConfirm"
-                        >
-                        </el-input>
-                        <el-button v-else class="button-new-tag" size="small" @click="showInput">+ 添加</el-button>
-                    </div>
-                </el-form-item>
-                <el-form-item label="所属文件夹" prop="folder">
-                    <el-select v-model="ruleForm.folder" filterable allow-create default-first-option size="small">
-                        <el-option v-for="item in folderData" :key="item.id" :label="item.name" :value="item.id"> </el-option>
-                    </el-select>
-                </el-form-item>
-            </el-form>
-        </div>
-        <div slot="footer" class="dialog-footer">
-            <el-button @click="resetForm('ruleForm')">取消</el-button>
-            <el-button type="primary" @click="submitForm('ruleForm')">确定</el-button>
-        </div>
-    </el-dialog>
+  <el-dialog
+    class="create-dialog"
+    title="新建画布"
+    width="600px"
+    :visible.sync="outerVisible"
+    :close-on-click-modal="false"
+    custom-class="createDialog"
+    @close="closeModal"
+  >
+    <div class="dialog-bodys">
+      <el-form
+        :model="ruleForm"
+        :rules="rules"
+        ref="ruleForm"
+        label-width="100px"
+        class="demo-ruleForm"
+        label-position="top"
+      >
+        <el-form-item label="所属楼层" prop="buildFloor">
+          <el-cascader
+            ref="buildFloor"
+            style="width: 260px"
+            v-model="ruleForm.buildFloor"
+            :options="buildFloorData"
+            :props="props"
+            clearable
+            size="small"
+          ></el-cascader>
+        </el-form-item>
+        <el-form-item label="名称" prop="name">
+          <el-input
+            v-model="ruleForm.name"
+            placeholder="请输入名称"
+            size="small"
+            :maxlength="20"
+            @blur="nameBlur"
+          ></el-input>
+        </el-form-item>
+        <el-form-item label="标签" prop="resource">
+          <div class="tagContainer">
+            <el-tag
+              :key="tag"
+              v-for="tag in dynamicTags"
+              closable
+              :disable-transitions="false"
+              @close="handleClose(tag)"
+            >
+              {{ tag }}
+            </el-tag>
+            <el-input
+              class="input-new-tag"
+              v-if="inputVisible"
+              v-model="inputValue"
+              ref="saveTagInput"
+              size="small"
+              @keyup.enter.native="handleInputConfirm"
+              @blur="handleInputConfirm"
+            >
+            </el-input>
+            <el-button
+              v-else
+              class="button-new-tag"
+              size="small"
+              @click="showInput"
+              >+ 添加</el-button
+            >
+          </div>
+        </el-form-item>
+        <el-form-item label="所属文件夹" prop="folder">
+          <el-select
+            v-model="ruleForm.folder"
+            filterable
+            allow-create
+            default-first-option
+            size="small"
+          >
+            <el-option
+              v-for="item in folderData"
+              :key="item.id"
+              :label="item.name"
+              :value="item.id"
+            >
+            </el-option>
+          </el-select>
+        </el-form-item>
+      </el-form>
+    </div>
+    <div slot="footer" class="dialog-footer">
+      <el-button @click="resetForm('ruleForm')">取消</el-button>
+      <el-button type="primary" @click="submitForm('ruleForm')">确定</el-button>
+    </div>
+  </el-dialog>
 </template>
 <script>
 import { buildingQuery } from "@/api/datacenter";
 import { folderQuery, planarCreate } from "@/api/labsl";
+import { mapState } from "vuex";
 export default {
-    components: {},
-    data() {
-        /**
-         * 自定义楼层校验规则
-         */
-        const validateBuildFloor = (rule, value, callback) => {
-            if (value.length !== 2) {
-                callback(new Error("请选择具体的楼层"));
-            } else {
-                callback();
-            }
-        };
-        return {
-            ruleForm: {
-                buildFloor: [],
-                name: "",
-                folder: "",
-            },
-            rules: {
-                buildFloor: [
-                    { required: true, message: "请选择建筑楼层", trigger: "change" },
-                    { validator: validateBuildFloor, trigger: "change" },
-                ],
-                name: [
-                    { required: true, message: "请输入名称", trigger: "blur" },
-                    { max: 20, message: "最长为20个文字", trigger: "blur" },
-                ],
-                folder: [{ required: true, message: "请选择所属文件夹", trigger: "blur" }],
-            },
-            buildFloorData: [],
-            props: {
-                value: "id",
-                label: "localName",
-                children: "floor",
-            },
-            floorName: "",
-            folderName: "",
-            value: [],
-            outerVisible: false,
-            dynamicTags: [],
-            inputValue: "",
-            inputVisible: false,
-            folderData: [],
-        };
+  components: {},
+  data() {
+    /**
+     * 自定义楼层校验规则
+     */
+    const validateBuildFloor = (rule, value, callback) => {
+      if (value.length !== 2) {
+        callback(new Error("请选择具体的楼层"));
+      } else {
+        callback();
+      }
+    };
+    return {
+      ruleForm: {
+        buildFloor: [],
+        name: "",
+        folder: "",
+      },
+      rules: {
+        buildFloor: [
+          { required: true, message: "请选择建筑楼层", trigger: "change" },
+          { validator: validateBuildFloor, trigger: "change" },
+        ],
+        name: [
+          { required: true, message: "请输入名称", trigger: "blur" },
+          { max: 20, message: "最长为20个文字", trigger: "blur" },
+        ],
+        folder: [
+          { required: true, message: "请选择所属文件夹", trigger: "blur" },
+        ],
+      },
+      buildFloorData: [],
+      props: {
+        value: "id",
+        label: "localName",
+        children: "floor",
+      },
+      floorName: "",
+      folderName: "",
+      value: [],
+      outerVisible: false,
+      dynamicTags: [],
+      inputValue: "",
+      inputVisible: false,
+      folderData: [],
+    };
+  },
+  methods: {
+    nameBlur() {
+      this.ruleForm.name = this.ruleForm.name.trim();
     },
-    methods: {
-        nameBlur() {
-            this.ruleForm.name = this.ruleForm.name.trim()
-        },
-        // 显示创建平面图弹窗
-        showDialog() {
-            this.outerVisible = true;
-        },
-        // 获取建筑楼层数据和文件夹数据
-        getData() {
-            const params1 = {
-                pageNumber: 1,
-                pageSize: 1000,
-                orders: "name asc, createTime desc",
-                cascade: [
-                    {
-                        name: "floor",
-                        orders: "floorSequenceId desc",
-                    },
-                ],
-            };
-            const params2 = {
-                pageNumber: 1,
-                pageSize: 1000,
-                orders: "name asc, createTime desc",
-            };
-            const promise1 = new Promise((resolve) => {
-                const res = buildingQuery(params1);
-                resolve(res);
-            });
-            const promise2 = new Promise((resolve) => {
-                const res = folderQuery(params2);
-                resolve(res);
-            });
-            Promise.all([promise1, promise2]).then((values) => {
-                console.log(values);
-                this.buildFloorData = values[0].content;
-                this.folderData = values[1].content;
-            });
-        },
-        // 展示标签输入框
-        showInput() {
-            this.inputVisible = true;
-            this.$nextTick(() => {
-                this.$refs.saveTagInput.$refs.input.focus();
-            });
-        },
-        // 添加标签
-        handleInputConfirm() {
-            const inputValue = this.inputValue;
-            if (inputValue) {
-                this.dynamicTags.push(inputValue);
-            }
-            this.inputVisible = false;
-            this.inputValue = "";
-        },
-        // 删除标签
-        handleClose(tag) {
-            this.dynamicTags.splice(this.dynamicTags.indexOf(tag), 1);
-        },
-        // 点击确定按钮(校验创建信息并调用创建平面图接口)
-        submitForm(formName) {
-            this.$refs[formName].validate((valid) => {
-                if (valid) {
-                    this.createPlan();
-                } else {
-                    console.log("error submit!!");
-                    return false;
-                }
-            });
-        },
-        // 重置创建平面图信息
-        resetForm(formName) {
-            this.dynamicTags = [];
-            this.$refs[formName].resetFields();
-            this.outerVisible = false;
-        },
-        // 创建平面图接口
-        async createPlan() {
-            /**
-             * 是否选中已有的文件夹对象
-             * folder(undefind/folder对象)
-             */
-            const folder = this.folderData.find((folder) => {
-                return folder.id === this.ruleForm.folder;
-            });
-            const floorNode = this.$refs.buildFloor.getCheckedNodes()[0];
-            const buildingId = this.ruleForm.buildFloor[0];
-            const floorId = this.ruleForm.buildFloor[1];
-            const floorLocalName = floorNode.label;
-            const floorMap = floorNode.data.infos && floorNode.data.infos.floorMap ? floorNode.data.infos.floorMap : "";
-            const folderName = folder ? folder.name : this.ruleForm.folder;
-            const params = {
-                name: this.ruleForm.name,
-                buildingId,
-                floorId,
-            };
+    // 显示创建平面图弹窗
+    showDialog() {
+      this.outerVisible = true;
+    },
+    // 获取建筑楼层数据和文件夹数据
+    getData() {
+      const params1 = {
+        pageNumber: 1,
+        pageSize: 1000,
+        orders: "name asc, createTime desc",
+        cascade: [
+          {
+            name: "floor",
+            orders: "floorSequenceId desc",
+          },
+        ],
+      };
+      const params2 = {
+        pageNumber: 1,
+        pageSize: 1000,
+        orders: "name asc, createTime desc",
+      };
+      const promise1 = new Promise((resolve) => {
+        const res = buildingQuery(params1);
+        resolve(res);
+      });
+      const promise2 = new Promise((resolve) => {
+        const res = folderQuery(params2);
+        resolve(res);
+      });
+      Promise.all([promise1, promise2]).then((values) => {
+        console.log(values);
+        this.buildFloorData = values[0].content;
+        this.folderData = values[1].content;
+      });
+    },
+    // 展示标签输入框
+    showInput() {
+      this.inputVisible = true;
+      this.$nextTick(() => {
+        this.$refs.saveTagInput.$refs.input.focus();
+      });
+    },
+    // 添加标签
+    handleInputConfirm() {
+      const inputValue = this.inputValue;
+      if (inputValue) {
+        this.dynamicTags.push(inputValue);
+      }
+      this.inputVisible = false;
+      this.inputValue = "";
+    },
+    // 删除标签
+    handleClose(tag) {
+      this.dynamicTags.splice(this.dynamicTags.indexOf(tag), 1);
+    },
+    // 点击确定按钮(校验创建信息并调用创建平面图接口)
+    submitForm(formName) {
+      this.$refs[formName].validate((valid) => {
+        if (valid) {
+          this.createPlan();
+        } else {
+          console.log("error submit!!");
+          return false;
+        }
+      });
+    },
+    // 重置创建平面图信息
+    resetForm(formName) {
+      this.dynamicTags = [];
+      this.$refs[formName].resetFields();
+      this.outerVisible = false;
+    },
+    // 创建平面图接口
+    async createPlan() {
+      /**
+       * 是否选中已有的文件夹对象
+       * folder(undefind/folder对象)
+       */
+      const folder = this.folderData.find((folder) => {
+        return folder.id === this.ruleForm.folder;
+      });
+      const floorNode = this.$refs.buildFloor.getCheckedNodes()[0];
+      const buildingId = this.ruleForm.buildFloor[0];
+      const floorId = this.ruleForm.buildFloor[1];
+      const floorLocalName = floorNode.label;
+      const floorMap =
+        floorNode.data.infos && floorNode.data.infos.floorMap
+          ? floorNode.data.infos.floorMap
+          : "";
+      const folderName = folder ? folder.name : this.ruleForm.folder;
+      const params = {
+        name: this.ruleForm.name,
+        buildingId,
+        floorId,
+      };
 
-            // 判断是否添加标签字段
-            if (this.dynamicTags.length) params.label = this.dynamicTags;
-            // 判断是否新建文件夹
-            if (folder) {
-                params.folderId = this.ruleForm.folder;
-            } else {
-                params.folderName = this.ruleForm.folder;
-            }
-            const res = await planarCreate(params);
-            if (res.result === "success" && res.entityList.length) {
-                const entity = res.entityList[0];
-                // this.$emit("createPlanar", {
-                //     folderId: entity.folderId,
-                //     folderName: entity.folderName,
-                // });
-                this.$message.success("新建画布成功!");
-                this.outerVisible = false;
-                this.$router.push({
-                    name: "Editer",
-                    query: {
-                        buildingId: entity.buildingId,
-                        floorId: entity.floorId,
-                        id: entity.id,
-                        graphId: entity.graphId,
-                        folderId: entity.folderId,
-                        name: entity.name,
-                        version: entity.version,
-                        floorMap,
-                        folderName,
-                        floorLocalName,
-                    },
-                });
-            } else {
-                this.$message.info(res.message);
-            }
-        },
-        // 关闭创建弹窗回调(重置创建信息)
-        closeModal() {
-            this.resetForm("ruleForm");
-        },
+      // 判断是否添加标签字段
+      if (this.dynamicTags.length) params.label = this.dynamicTags;
+      // 判断是否新建文件夹
+      if (folder) {
+        params.folderId = this.ruleForm.folder;
+      } else {
+        params.folderName = this.ruleForm.folder;
+      }
+      const res = await planarCreate(params);
+      if (res.result === "success" && res.entityList.length) {
+        const entity = res.entityList[0];
+        // this.$emit("createPlanar", {
+        //     folderId: entity.folderId,
+        //     folderName: entity.folderName,
+        // });
+        this.$message.success("新建画布成功!");
+        this.outerVisible = false;
+        let routeUrl = this.$router.resolve({
+          name: "Editer",
+          query: {
+            buildingId: entity.buildingId,
+            floorId: entity.floorId,
+            id: entity.id,
+            graphId: entity.graphId,
+            folderId: entity.folderId,
+            name: entity.name,
+            version: entity.version,
+            floorMap,
+            folderName,
+            floorLocalName,
+            projectId: this.projectId,
+          },
+        });
+        window.open(routeUrl.href, "_blank");
+      } else {
+        this.$message.info(res.message);
+      }
+    },
+    // 关闭创建弹窗回调(重置创建信息)
+    closeModal() {
+      this.resetForm("ruleForm");
     },
-    watch: {
-        outerVisible(n) {
-            if (n) this.getData();
-        },
+  },
+  computed: {
+    ...mapState(["projectId"]),
+  },
+  watch: {
+    outerVisible(n) {
+      if (n) this.getData();
     },
+  },
 };
 </script>
 <style lang="less" scoped>
 /deep/ .createDialog {
-    /deep/ .el-dialog__header {
-        border-bottom: 1px solid #f0f1f2ff;
+  /deep/ .el-dialog__header {
+    border-bottom: 1px solid #f0f1f2ff;
+  }
+  /deep/ .el-dialog__body {
+    padding: 16px 120px;
+    max-height: 500px;
+    overflow: auto;
+  }
+  .el-dialog__footer {
+    padding: 0 20px 20px;
+    .el-button {
+      padding: 0;
+      width: 80px;
+      height: 32px;
+      text-align: center;
+      line-height: 1;
     }
-    /deep/ .el-dialog__body {
-        padding: 16px 120px;
-        max-height: 500px;
-        overflow: auto;
+  }
+  .el-form-item {
+    margin-bottom: 0;
+    & + .el-form-item {
+      margin-top: 18px;
     }
-    .el-dialog__footer {
-        padding: 0 20px 20px;
-        .el-button {
-            padding: 0;
-            width: 80px;
-            height: 32px;
-            text-align: center;
-            line-height: 1;
-        }
-    }
-    .el-form-item {
-        margin-bottom: 0;
-        & + .el-form-item {
-            margin-top: 18px;
-        }
-    }
-    .el-form-item__label {
-        line-height: 1;
+  }
+  .el-form-item__label {
+    line-height: 1;
+  }
+  .input-new-tag {
+    width: 150px;
+  }
+  .button-new-tag {
+    width: 60px;
+    height: 24px;
+    margin-bottom: 8px;
+    padding: 0;
+    line-height: 1;
+    border-radius: 2px;
+    border: 1px dotted #0091ff;
+    color: #0091ff;
+    &:hover {
+      background: #fff;
+      color: #0091ff;
+      border: 1px dotted #0091ff;
     }
-    .input-new-tag {
-        width: 150px;
-    }
-    .button-new-tag {
-        width: 60px;
-        height: 24px;
-        margin-bottom: 8px;
-        padding: 0;
-        line-height: 1;
-        border-radius: 2px;
-        border: 1px dotted #0091ff;
-        color: #0091ff;
+  }
+  .typeButton {
+    min-width: 122px;
+    height: 32px;
+    text-align: center;
+    line-height: 32px;
+    border-radius: 4px;
+    padding: 0;
+    border: 1px solid #c3c6cb;
+  }
+  .tagContainer {
+    width: 100%;
+    border-radius: 4px;
+    border: 1px solid #c3c6cb;
+    padding: 7px 12px;
+    line-height: 1;
+    .el-tag {
+      background: #eff0f1;
+      border-radius: 2px;
+      color: #1f2429ff;
+      margin: 0 8px 8px 0;
+      padding: 5px 6px 5px 8px;
+      font-size: 14px;
+      height: 24px;
+      line-height: 1;
+      border: none;
+      &:hover {
+        border: none;
+      }
+      .el-icon-close {
+        color: #9ca2a9ff;
+        right: 0;
         &:hover {
-            background: #fff;
-            color: #0091ff;
-            border: 1px dotted #0091ff;
-        }
-    }
-    .typeButton {
-        min-width: 122px;
-        height: 32px;
-        text-align: center;
-        line-height: 32px;
-        border-radius: 4px;
-        padding: 0;
-        border: 1px solid #c3c6cb;
-    }
-    .tagContainer {
-        width: 100%;
-        border-radius: 4px;
-        border: 1px solid #c3c6cb;
-        padding: 7px 12px;
-        line-height: 1;
-        .el-tag {
-            background: #eff0f1;
-            border-radius: 2px;
-            color: #1f2429ff;
-            margin: 0 8px 8px 0;
-            padding: 5px 6px 5px 8px;
-            font-size: 14px;
-            height: 24px;
-            line-height: 1;
-            border: none;
-            &:hover {
-                border: none;
-            }
-            .el-icon-close {
-                color: #9ca2a9ff;
-                right: 0;
-                &:hover {
-                    color: #fff;
-                    background-color: #ccc;
-                }
-            }
+          color: #fff;
+          background-color: #ccc;
         }
+      }
     }
+  }
 }
 </style>

+ 86 - 0
src/lib/PPlanFactory.ts

@@ -0,0 +1,86 @@
+/*
+ * *********************************************************************************************************************
+ *
+ *          !!
+ *        .F88X
+ *        X8888Y
+ *      .}888888N;
+ *        i888888N;        .:!              .I$WI:
+ *          R888888I      .'N88~            i8}+8Y&8"l8i$8>8W~'>W8}8]KW+8IIN"8&
+ *          .R888888I    .;N8888~          .X8'  "8I.!,/8"  !%NY8`"8I8~~8>,88I
+ *            +888888N;  .8888888Y                                  "&&8Y.}8,
+ *            ./888888N;  .R888888Y        .'}~    .>}'.`+>  i}!    "i'  +/'  .'i~  !11,.:">,  .~]!  .i}i
+ *              ~888888%:  .I888888l      .]88~`1/iY88Ii+1'.R$8$8]"888888888>  Y8$  W8E  X8E  W8888'188Il}Y88$*
+ *              18888888    E8888881    .]W%8$`R8X'&8%++N8i,8N%N8+l8%`  .}8N:.R$RE%N88N%N$K$R  188,FE$8%~Y88I
+ *            .E888888I  .i8888888'      .:$8I;88+`E8R:/8N,.>881.`$8E/1/]N8X.Y8N`"KF&&FK!'88*."88K./$88%RN888+~
+ *            8888888I  .,N888888~        ~88i"8W,!N8*.I88.}888%F,i$88"F88"  888:E8X.>88!i88>`888*.}Fl1]*}1YKi'
+ *          i888888N'      I888Y          ]88;/EX*IFKFK88X  K8R  .l8W  88Y  ~88}'88E&%8W.X8N``]88!.$8K  .:W8I
+ *        .i888888N;        I8Y          .&8$  .X88!  i881.:%888>I88  ;88]  +88+.';;;;:.Y88X  18N.,88l  .+88/
+ *      .:R888888I
+ *      .&888888I                                          Copyright (c) 2016-2020.  博锐尚格科技股份有限公司
+ *        ~8888'
+ *        .!88~                                                                     All rights reserved.
+ *
+ * *********************************************************************************************************************
+ */
+
+import { Marker } from "@persagy-web/big"
+import { SBaseInfoPoint } from "./item/SBaseInfoPoint"
+import { SBaseEquation } from "./item/SBaseEquation"
+import { SPubEquipment } from "./item/SPubEquipment"
+import { BigEditFactory } from "@persagy-web/big-edit"
+import { imgBaseUrl } from "@/api/imageservice";
+/**
+ * item 创建工厂
+ *
+ * @author 韩耀龙 <han_yao_long@163.com>
+ */
+export class PPlanFactory extends BigEditFactory {
+
+    /**
+     * 构造函数
+     */
+    constructor() {
+        super()
+    }
+
+    /**
+     * 创建信息点
+     *
+     * @param data  数据
+     * @return 线
+     */
+    createBaseInfoPoint(data: Marker): SBaseInfoPoint {
+        const item = new SBaseInfoPoint(null, data);
+        item.data = data;
+        return item;
+    }
+
+    /**
+     * 创建公式
+     *
+     * @param data  数据
+     * @return 线
+     */
+    createBaseEqation(data: Marker): SBaseEquation {
+        const item = new SBaseEquation(null, data);
+        item.data = data;
+        return item;
+    }
+
+
+    /**
+     * 创建公共图例
+     *
+     * @param data  数据
+     * @return 线
+     */
+    createBasePublicEquipmentEdit(data: Marker): SPubEquipment {
+        const item = new SPubEquipment(null, data);
+         item.url =  imgBaseUrl + data.style.default.url;
+        item.data = data;
+        return item;
+    }
+
+
+}

+ 14 - 3
src/lib/SPlanParser.ts

@@ -23,9 +23,10 @@
  *
  * ****/
 
-import { SParser } from "@persagy-web/big/lib";
-import { BigEditFactory, Legend, Marker, Relation, ElementData } from "@persagy-web/big-edit";
+import { SParser,Legend, Marker, Relation, ElementData  } from "@persagy-web/big/lib";
+import { BigEditFactory } from "@persagy-web/big-edit";
 import { SPlanBackgroundImage } from "./item/SPlanBackgroundImage";
+import { PPlanFactory } from "./PPlanFactory"
 
 /**
  * 平面图解析器
@@ -40,7 +41,7 @@ export class SPlanParser extends SParser {
     /**  管线对象 */
     relations: any = [];
     constructor() {
-        super(new BigEditFactory());
+        super(new PPlanFactory());
     }
 
     /**
@@ -114,6 +115,16 @@ export class SPlanParser extends SParser {
                     break;
                 case "BaseArrowPolygon":
                     item = this.factory.createBasePolygonArrowEdit(data);
+                    break;
+                case "Equation":
+                    item = this.factory.createBaseEqation(data);
+                    break;
+                case "InfoPoint":
+                    item = this.factory.createBaseInfoPoint(data);
+                    break;
+                case "PublicEquipment":
+                    item = this.factory.createBasePublicEquipmentEdit(data);
+
             }
             // 添加的通用元素不是BgImage,是其他元素,设置 zOrder
             if (item) {

+ 128 - 7
src/lib/SPlanScene.ts

@@ -30,7 +30,7 @@ import { SGraphAddCommand, SGraphItem, SGraphPropertyCommand, SGraphSelectContai
 import { SItemStatus, ItemColor } from "@persagy-web/big";
 import { rgbaNum } from "@persagy-web/big-edit/lib/until";
 import { SColor, SFont, SArrowStyleType } from "@persagy-web/draw";
-import { SPlanEquipment, SPlanParser, SPlanZone } from "./";
+import { SPlanEquipment, SPlanParser, SPlanZone, SBaseInfoPoint, SBaseEquation, SPubEquipment } from "./";
 import { SPlanBackgroundImage } from "@/lib/item/SPlanBackgroundImage";
 import { imgBaseUrl } from "@/api/imageservice";
 /**
@@ -74,7 +74,7 @@ export class SPlanScene extends SBaseEditScene {
      *
      * @param list   选中的 item 数组
      */
-    emitChoice(list: any) {}
+    emitChoice(list: any) { }
     /**
      * 修改选中item的对齐方式
      * @param val
@@ -84,6 +84,115 @@ export class SPlanScene extends SBaseEditScene {
     }
 
     /**
+     * 添加公式
+     * @param event
+     */
+    addEquation(event: SMouseEvent, cmd: string): SBaseEquation {
+        const data = {
+            /** 名称 */
+            name: '公式',
+            /** 图标 */
+            type: "Text",
+            /** 位置 */
+            pos: { x: event.x, y: event.y },
+            size: { width: 0, height: 0 },
+            /** 由应用自己定义 */
+            properties: {
+                type: "Equation"           // 自定义类型用于区分mark与node
+            },
+            style: {
+                default: {
+                    text: '请在右侧属性栏填写公式!',
+                    color: "#646c73",
+                    font: 14,
+                    backgroundcolor: "#f7f9facc",
+                }
+            }
+        };
+        const item = new SBaseEquation(null, data);
+        item.moveTo(event.x, event.y);
+        item.moveable = true;
+        this.addItem(item);
+        this.grabItem = null;
+        item.connect("onContextMenu", this, this.getItem);
+        this.finishCreated(item);
+        return item;
+    }
+
+    /**
+     * 添加信息点
+     * @param event
+     */
+    addInfoPoint(event: SMouseEvent, cmd: string): SBaseInfoPoint {
+        const data = {
+            /** 名称 */
+            name: '信息点',
+            /** 图标 */
+            type: "Text",
+            /** 位置 */
+            pos: { x: event.x, y: event.y },
+            size: { width: 0, height: 0 },
+            /** 由应用自己定义 */
+            properties: {
+                type: "InfoPoint"           // 自定义类型用于区分mark与node
+            },
+            style: {
+                default: {
+                    text: '信息点',
+                    color: "#646c73",
+                    font: 14,
+                    backgroundcolor: "#f7f9facc",
+                }
+            }
+        };
+        const item = new SBaseInfoPoint(null, data);
+        item.moveTo(event.x, event.y);
+        item.moveable = true;
+        this.addItem(item);
+        this.grabItem = null;
+        item.connect("onContextMenu", this, this.getItem);
+        this.finishCreated(item);
+        return item;
+    }
+
+    /**
+     * 添加通用实例
+     * @param event
+     */
+    addpublicItem(event: SMouseEvent, cmd: string): SPubEquipment {
+        const data = {
+            /** 名称 */
+            name: '公共实例',
+            /** 图标 */
+            type: "icontxt",
+            /** 位置 */
+            pos: { x: event.x, y: event.y },
+            size: { width: 32, height: 32 },
+            /** 由应用自己定义 */
+            properties: {
+                type: "PublicEquipment"           // 自定义类型用于区分mark与node
+            },
+            style: {
+                default: {
+                    url:'1611558340113.svg',
+                    text: '公共图例',
+                    color: "#646c73",
+                    font: 14,
+                    backgroundcolor: "#f7f9facc",
+                }
+            }
+        };
+        const item = new SPubEquipment(null, data);
+        item.url =  imgBaseUrl + data.style.default.url;
+        item.moveable = true;
+        this.addItem(item);
+        this.grabItem = null;
+        item.connect("onContextMenu", this, this.getItem);
+        this.finishCreated(item);
+        return item;
+    }
+
+    /**
      * 鼠标左键按下
      *
      * @param event   鼠标事件参数
@@ -141,9 +250,6 @@ export class SPlanScene extends SBaseEditScene {
             // 箭头
             item = this.addPolygonArrow(event);
             this.clearCmdStatus();
-        } else if (this.editCmd == "wantou" || this.editCmd == "santong" || this.editCmd == "sitong") {
-            item = this.addPipeUninTool(event, this.editCmd);
-            this.clearCmdStatus();
         } else if (this.editCmd == "EditBasePipe") {
             item = this.addBasePipe(event, this.legendObj);
             item.zOrder = 9600;
@@ -151,6 +257,18 @@ export class SPlanScene extends SBaseEditScene {
         } else if (this.editCmd == "Editoutline") {
             item = this.addMaskItem(event);
             this.clearCmdStatus();
+        } else if (this.editCmd == "equation") {
+            // 添加公式
+            this.addEquation(event, this.editCmd);
+            this.clearCmdStatus();
+        } else if (this.editCmd == "infoPoint") {
+            // 添加信息点
+            this.addInfoPoint(event, this.editCmd);
+            this.clearCmdStatus();
+        } else if (this.editCmd == "publicItem") {
+            // 添加信息点
+            this.addpublicItem(event, this.editCmd);
+            this.clearCmdStatus();
         } else if (this.editCmd == "") {
             super.onMouseDown(event);
         }
@@ -213,7 +331,7 @@ export class SPlanScene extends SBaseEditScene {
     /**
      * 添加蒙板结束事件
      */
-    maskFinishCreated(){
+    maskFinishCreated() {
 
     }
     /**
@@ -467,6 +585,9 @@ export class SPlanScene extends SBaseEditScene {
             "BaseTriangle",
             "BaseRect",
             "BaseArrowPolygon",
+            "Equation",
+            "InfoPoint",
+            "PublicEquipment"
         ];
         const ObjExtInfoType: string[] = ["BaseEquipment"];
         const RelationType: string[] = ["BasePipe"];
@@ -588,7 +709,7 @@ export class SPlanScene extends SBaseEditScene {
         const cpItemList = this.save(false);
 
         const itemList = {
-            markers:  cpItemList?.elements.markers,
+            markers: cpItemList?.elements.markers,
             relations: cpItemList?.elements.relations,
         }
         if (itemList) {

+ 5 - 1
src/lib/index.ts

@@ -9,4 +9,8 @@ import { Example } from "./style/Example";
 import { StyleMap } from "./style/StyleMap";
 import { EquipMap } from "./style/EquipMap";
 import { ZoneMap } from "./style/ZoneMap";
-export { SPlanParser, SPlanScene, SPlanView, SPlanDecorator, SPlanEquipment, SPlanZone, Style, Example, StyleMap, EquipMap, ZoneMap };
+import {SBaseEquation} from "./item/SBaseEquation";
+import {SBaseInfoPoint} from "./item/SBaseInfoPoint";
+import {SPubEquipment} from "./item/SPubEquipment"
+
+export {SPubEquipment,SBaseInfoPoint, SBaseEquation,SPlanParser, SPlanScene, SPlanView, SPlanDecorator, SPlanEquipment, SPlanZone, Style, Example, StyleMap, EquipMap, ZoneMap };

+ 47 - 0
src/lib/item/SBaseEquation.ts

@@ -0,0 +1,47 @@
+/*
+ * *********************************************************************************************************************
+ *
+ *          !!
+ *        .F88X
+ *        X8888Y
+ *      .}888888N;
+ *        i888888N;        .:!              .I$WI:
+ *          R888888I      .'N88~            i8}+8Y&8"l8i$8>8W~'>W8}8]KW+8IIN"8&
+ *          .R888888I    .;N8888~          .X8'  "8I.!,/8"  !%NY8`"8I8~~8>,88I
+ *            +888888N;  .8888888Y                                  "&&8Y.}8,
+ *            ./888888N;  .R888888Y        .'}~    .>}'.`+>  i}!    "i'  +/'  .'i~  !11,.:">,  .~]!  .i}i
+ *              ~888888%:  .I888888l      .]88~`1/iY88Ii+1'.R$8$8]"888888888>  Y8$  W8E  X8E  W8888'188Il}Y88$*
+ *              18888888    E8888881    .]W%8$`R8X'&8%++N8i,8N%N8+l8%`  .}8N:.R$RE%N88N%N$K$R  188,FE$8%~Y88I
+ *            .E888888I  .i8888888'      .:$8I;88+`E8R:/8N,.>881.`$8E/1/]N8X.Y8N`"KF&&FK!'88*."88K./$88%RN888+~
+ *            8888888I  .,N888888~        ~88i"8W,!N8*.I88.}888%F,i$88"F88"  888:E8X.>88!i88>`888*.}Fl1]*}1YKi'
+ *          i888888N'      I888Y          ]88;/EX*IFKFK88X  K8R  .l8W  88Y  ~88}'88E&%8W.X8N``]88!.$8K  .:W8I
+ *        .i888888N;        I8Y          .&8$  .X88!  i881.:%888>I88  ;88]  +88+.';;;;:.Y88X  18N.,88l  .+88/
+ *      .:R888888I
+ *      .&888888I                                          Copyright (c) 2016-2020.  博锐尚格科技股份有限公司
+ *        ~8888'
+ *        .!88~                                                                     All rights reserved.
+ *
+ * *********************************************************************************************************************
+ */
+
+import { SBaseTextEdit } from "@persagy-web/edit"
+import { SGraphItem } from "@persagy-web/graph/lib";
+import { Marker } from "@persagy-web/big/lib";
+
+/**
+ * 公式类
+ *
+ * @author  韩耀龙 <han_yao_long@163.com>
+ */
+export class SBaseEquation extends SBaseTextEdit {
+    /**
+     * 构造函数
+     *
+     * @param parent    指向父对象
+     * @param data      数据
+     */
+    constructor(parent: SGraphItem | null, data: Marker) {
+        super(parent, data);
+        this.data = data;
+    } // Constructor
+}

+ 56 - 0
src/lib/item/SBaseInfoPoint.ts

@@ -0,0 +1,56 @@
+/*
+ * *********************************************************************************************************************
+ *
+ *          !!
+ *        .F88X
+ *        X8888Y
+ *      .}888888N;
+ *        i888888N;        .:!              .I$WI:
+ *          R888888I      .'N88~            i8}+8Y&8"l8i$8>8W~'>W8}8]KW+8IIN"8&
+ *          .R888888I    .;N8888~          .X8'  "8I.!,/8"  !%NY8`"8I8~~8>,88I
+ *            +888888N;  .8888888Y                                  "&&8Y.}8,
+ *            ./888888N;  .R888888Y        .'}~    .>}'.`+>  i}!    "i'  +/'  .'i~  !11,.:">,  .~]!  .i}i
+ *              ~888888%:  .I888888l      .]88~`1/iY88Ii+1'.R$8$8]"888888888>  Y8$  W8E  X8E  W8888'188Il}Y88$*
+ *              18888888    E8888881    .]W%8$`R8X'&8%++N8i,8N%N8+l8%`  .}8N:.R$RE%N88N%N$K$R  188,FE$8%~Y88I
+ *            .E888888I  .i8888888'      .:$8I;88+`E8R:/8N,.>881.`$8E/1/]N8X.Y8N`"KF&&FK!'88*."88K./$88%RN888+~
+ *            8888888I  .,N888888~        ~88i"8W,!N8*.I88.}888%F,i$88"F88"  888:E8X.>88!i88>`888*.}Fl1]*}1YKi'
+ *          i888888N'      I888Y          ]88;/EX*IFKFK88X  K8R  .l8W  88Y  ~88}'88E&%8W.X8N``]88!.$8K  .:W8I
+ *        .i888888N;        I8Y          .&8$  .X88!  i881.:%888>I88  ;88]  +88+.';;;;:.Y88X  18N.,88l  .+88/
+ *      .:R888888I
+ *      .&888888I                                          Copyright (c) 2016-2020.  博锐尚格科技股份有限公司
+ *        ~8888'
+ *        .!88~                                                                     All rights reserved.
+ *
+ * *********************************************************************************************************************
+ */
+
+import { Marker } from "@persagy-web/big/lib";
+import { SBaseTextEdit } from "@persagy-web/edit"
+import { SGraphItem } from "@persagy-web/graph/lib";
+
+/**
+ * 信息点
+ *
+ * @author  韩耀龙 <han_yao_long@163.com>
+ */
+export class SBaseInfoPoint extends SBaseTextEdit {
+    /**
+     * 构造函数
+     *
+     * @param parent    指向父对象
+     * @param data      数据
+     */
+    constructor(parent: SGraphItem | null, data: Marker) {
+        super(parent, data);
+        this.data = data;
+    } // Constructor
+
+    /**
+     * 返回对象储存的相关数据
+     *
+     * @return 相关数据
+     */
+    toData(): any {
+        return super.toData();
+    }
+}

+ 166 - 0
src/lib/item/SPubEquipment.ts

@@ -0,0 +1,166 @@
+/*
+ * *********************************************************************************************************************
+ *
+ *          !!
+ *        .F88X
+ *        X8888Y
+ *      .}888888N;
+ *        i888888N;        .:!              .I$WI:
+ *          R888888I      .'N88~            i8}+8Y&8"l8i$8>8W~'>W8}8]KW+8IIN"8&
+ *          .R888888I    .;N8888~          .X8'  "8I.!,/8"  !%NY8`"8I8~~8>,88I
+ *            +888888N;  .8888888Y                                  "&&8Y.}8,
+ *            ./888888N;  .R888888Y        .'}~    .>}'.`+>  i}!    "i'  +/'  .'i~  !11,.:">,  .~]!  .i}i
+ *              ~888888%:  .I888888l      .]88~`1/iY88Ii+1'.R$8$8]"888888888>  Y8$  W8E  X8E  W8888'188Il}Y88$*
+ *              18888888    E8888881    .]W%8$`R8X'&8%++N8i,8N%N8+l8%`  .}8N:.R$RE%N88N%N$K$R  188,FE$8%~Y88I
+ *            .E888888I  .i8888888'      .:$8I;88+`E8R:/8N,.>881.`$8E/1/]N8X.Y8N`"KF&&FK!'88*."88K./$88%RN888+~
+ *            8888888I  .,N888888~        ~88i"8W,!N8*.I88.}888%F,i$88"F88"  888:E8X.>88!i88>`888*.}Fl1]*}1YKi'
+ *          i888888N'      I888Y          ]88;/EX*IFKFK88X  K8R  .l8W  88Y  ~88}'88E&%8W.X8N``]88!.$8K  .:W8I
+ *        .i888888N;        I8Y          .&8$  .X88!  i881.:%888>I88  ;88]  +88+.';;;;:.Y88X  18N.,88l  .+88/
+ *      .:R888888I
+ *      .&888888I                                          Copyright (c) 2016-2020.  博锐尚格科技股份有限公司
+ *        ~8888'
+ *        .!88~                                                                     All rights reserved.
+ *
+ * *********************************************************************************************************************
+ */
+
+import { SGraphItem, SAnchorItem } from "@persagy-web/graph/lib";
+import { SPoint, SPainter, SColor } from "@persagy-web/draw";
+import { Example } from "../index";
+import { SBaseIconTextEdit, SBaseTextEdit } from "@persagy-web/edit";
+import { svgTobase64, Marker, ItemOrder } from "@persagy-web/big/lib";
+import { v1 as uuidv1 } from "uuid";
+
+/**
+ * 编辑公共设备类(mark 类)
+ *
+ * @author 韩耀龙 <han_yao_long@163.com>
+ */
+export class SPubEquipment extends SBaseIconTextEdit {
+
+    /** 图例url */
+    private _url: string = "";
+    set url(val) {
+        this._url = val;
+        this.initUrl();
+    } // set url()
+    get url(): string {
+        return this._url;
+    } // get url()
+
+
+    //  设备附加数据
+    anotherMsg: string = "";
+
+    /**
+     * 构造函数
+     *
+     * @param parent    指向父对象
+     * @param data      数据
+     */
+    constructor(parent: SGraphItem | null, data: Marker) {
+        super(parent);
+        this.zOrder = 9700;
+        this.isTransform = false;
+        this.sWidth = 32;
+        this.sHeight = 32;
+        this.img.showSelect = false;
+        this.moveable = true;
+        this.selectable = true;
+        this.data = data;
+    } // Constructor
+
+    /**
+     * 设置 data 时对 item 做设置
+     */
+    initData() {
+        // this.data 不能为空
+        if (!this.data) return;
+
+        // 判断 size 是否存在
+        if (this.data.size) {
+            this.sWidth = this.data.size.width;
+            this.sHeight = this.data.size.height;
+        }
+
+        this.img.connect("onMove", this, this.changeAnchorPoint.bind(this));
+
+
+        // 判断是否有锚点数据
+        const anchorPoint = [
+            { pos: { x: this.img.x, y: this.img.y }, anchorId: uuidv1() }
+        ];
+
+        // 没锚点则默认中心点为锚点
+        this.anchorList = anchorPoint.map(t => {
+            let item = new SAnchorItem(this);
+            // 是否存在 anchorId
+            if (t.anchorId) {
+                item.id = t.anchorId;
+            }
+
+            item.moveTo(t.pos.x, t.pos.y);
+            return item;
+        });
+        this.zOrder = ItemOrder.RelationOrder + 10;
+
+
+        this.showAnchor = false;
+        this.anotherMsg = this.data.properties.anotherMsg
+            ? this.data.properties.anotherMsg
+            : "";
+        this.x = this.data.pos.x;
+        this.y = this.data.pos.y;
+        this.moveable = true;
+        this.selectable = true;
+    }
+
+    initUrl() {
+        svgTobase64(this.url)
+            .then((res) => {
+                this.img.url = res ? res : "";
+            })
+            .catch((res) => {
+                this.img.url = res;
+            });
+    }
+
+    /**
+     * 文本位置移动回调函数
+     * @param textItem 移动的文本元素
+     * @param pointList 移动前后位置坐标信息
+     */
+    textMove(textItem: SBaseTextEdit, pointList: SPoint[]) {
+        this.moveText();
+    }
+    moveText() { }
+
+    /**
+     * 返回对象储存的相关数据
+     *
+     * @return	对象储存的相关数据
+     */
+    toData(): any {
+        if (this.data) {
+            // 数据中存在大小 size 属性
+            if (this.data.size) {
+                this.data.size.width = this.sWidth;
+                this.data.size.height = this.sHeight;
+            }
+            this.data.style.default.text = JSON.stringify(this.textItemList);
+            this.data.pos.x = this.pos.x;
+            this.data.pos.y = this.pos.y;
+            this.data.style.default.zorder = this.zOrder;
+        }
+        return this.data
+    }
+
+    /**
+     * Item 绘制操作
+     *
+     * @param painter    绘制对象
+     */
+    onDraw(painter: SPainter): void {
+        super.onDraw(painter);
+    } // Function onDraw()
+}