Pārlūkot izejas kodu

新增设备工艺 电柜 电柜可视化 单位管理

pm 10 mēneši atpakaļ
vecāks
revīzija
24a3dffe2f

+ 52 - 0
src/api/mes/lotoStation/lotoStation.js

@@ -0,0 +1,52 @@
+import request from '@/utils/request'
+
+// 查询电柜列表
+export function listLoto(query) {
+  return request({
+    url: '/iscs/station/getIsLotoStationPage',
+    method: 'get',
+    params: query
+  })
+}
+
+
+// 查询电柜详细
+export function getLotoInfo(deptId) {
+  return request({
+    url: '/iscs/station/selectIsLotoStationById?lotoId=' + deptId,
+    method: 'get'
+  })
+}
+// 查询电柜地图转换数据
+export function getLotoMapInfo(deptId) {
+  return request({
+    url: '/iscs/station/selectLotoMapById?lotoId=' + deptId,
+    method: 'get'
+  })
+}
+
+// 新增电柜
+export function addLoto(data) {
+  return request({
+    url: '/iscs/station/insertIsLotoStation',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改电柜
+export function updateLoto(data) {
+  return request({
+    url: '/iscs/station/updateIsLotoStation',
+    method: 'post',
+    data: data
+  })
+}
+
+// 删除电柜
+export function delLoto(deptId) {
+  return request({
+    url: '/iscs/station/deleteIsLotoStationByLotoIds?lotoIds=' + deptId,
+    method: 'post'
+  })
+}

+ 13 - 5
src/api/system/technology.js → src/api/system/machinery.js

@@ -3,7 +3,7 @@ import request from '@/utils/request'
 // 查询设备工艺列表
 export function listTechnology(query) {
   return request({
-    url: '/iscs/technology/getIsDeviceTechnologyPage',
+    url: '/iscs/machinery/getIsMachineryPage',
     method: 'get',
     params: query
   })
@@ -13,7 +13,7 @@ export function listTechnology(query) {
 // 查询设备工艺详细
 export function getTechnologyInfo(deptId) {
   return request({
-    url: '/iscs/technology/selectIsDeviceTechnologyById?technologyId=' + deptId,
+    url: '/iscs/machinery/selectIsMachineryById?machineryId=' + deptId,
     method: 'get'
   })
 }
@@ -22,16 +22,24 @@ export function getTechnologyInfo(deptId) {
 // 新增设备工艺
 export function addTechnology(data) {
   return request({
-    url: '/iscs/technology/insertIsDeviceTechnology',
+    url: '/iscs/machinery/insertIsMachinery',
     method: 'post',
     data: data
   })
 }
 
+// 保存设备工艺与隔离点的关系
+export function saveMachineryPoints(data) {
+  return request({
+    url: '/iscs/machinery/saveMachineryPoints',
+    method: 'post',
+    data: data
+  })
+}
 // 修改设备工艺
 export function updateTechnology(data) {
   return request({
-    url: '/iscs/technology/updateIsDeviceTechnology',
+    url: '/iscs/machinery/updateIsMachinery',
     method: 'post',
     data: data
   })
@@ -40,7 +48,7 @@ export function updateTechnology(data) {
 // 删除设备工艺
 export function delTechnology(deptId) {
   return request({
-    url: '/iscs/technology/deleteIsDeviceTechnologyByTechnologyIds?technologyIds=' + deptId,
+    url: '/iscs/machinery/deleteIsMachineryByMachineryIds?machineryIds=' + deptId,
     method: 'post'
   })
 }

+ 46 - 0
src/api/system/unit.js

@@ -0,0 +1,46 @@
+import request from '@/utils/request'
+
+// 查询玛氏岗位列表
+export function listUnit(query) {
+  return request({
+    url: '/iscs/unit/getIsUnitPage',
+    method: 'get',
+    params: query
+  })
+}
+
+
+// 查询玛氏岗位详细
+export function getUnitInfo(deptId) {
+  return request({
+    url: '/iscs/unit/selectIsUnitById?unitId=' + deptId,
+    method: 'get'
+  })
+}
+
+
+// 新增玛氏岗位
+export function addUnit(data) {
+  return request({
+    url: '/iscs/unit/insertIsUnit',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改玛氏岗位
+export function updateUnit(data) {
+  return request({
+    url: '/iscs/unit/updateIsUnit',
+    method: 'post',
+    data: data
+  })
+}
+
+// 删除玛氏岗位
+export function delUnit(deptId) {
+  return request({
+    url: '/iscs/unit/deleteIsUnitByUnitIds?unitIds=' + deptId,
+    method: 'post'
+  })
+}

+ 28 - 0
src/router/index.js

@@ -193,6 +193,34 @@ export const dynamicRoutes = [
       }
     ]
   },
+  {
+    path: '/mes/hw/lotoStation/index',
+    component: Layout,
+    hidden: true,
+    permissions: ['iscs:loto:list'],
+    children: [
+      {
+        path: 'MapData',
+        component: () => import('@/views/mes/hw/lotoStation/MapData'),
+        name: 'MapData',
+        meta: { title: '预览', activeMenu: '/mes/hw/lotoStation/MapData' }
+      }
+    ]
+  },
+  {
+    path: '/system/technology/technologyList/index',
+    component: Layout,
+    hidden: true,
+    permissions: ['iscs:machinery:list'],
+    children: [
+      {
+        path: 'MapData',
+        component: () => import('@/views/system/technology/technologyList/MapData'),
+        name: 'MapData',
+        meta: { title: '设置隔离点', activeMenu: '/system/technology/technologyList/MapData' }
+      }
+    ]
+  },
   {
     path: '/system/role-auth',
     component: Layout,

+ 325 - 0
src/views/mes/hw/lotoStation/MapData.vue

@@ -0,0 +1,325 @@
+<template>
+  <div class="mapdata">
+    <div id="container" ref="container" style="width:1200px"></div>
+    <div class="left">
+      <el-card class="box-card">
+        <div slot="header" class="clearfix">
+          <span style="font-size: 18px">地图预览</span>
+          <span
+            style="
+                float: right;
+                padding: 1px 0;
+                font-size: 22px;
+                cursor: pointer;
+              "
+            type="text"
+            @click="goBack"
+          >×</span
+          >
+        </div>
+        <div style="height: 100%;padding-bottom:10px">
+          <el-input v-model="value" type="textarea" :rows="34" ></el-input>
+
+        </div>
+        <div class="bottombtn" style="width:100%;height: 35px;padding: 10px 0 0">
+          <el-button v-no-more-click @click="save" type="primary" icon="el-icon-edit" style="float: right; height: 33px; line-height: 2px">保存</el-button>
+          <el-button v-no-more-click @click="reset" type="primary" icon="el-icon-refresh"  style="float: right; height: 33px; line-height: 2px;margin: 0 10px">重置</el-button>
+          <el-button v-no-more-click @click="view" type="primary" icon="el-icon-view" style="float: right; height: 33px; line-height: 2px">预览</el-button>
+        </div>
+      </el-card>
+
+    </div>
+  </div>
+
+</template>
+
+<script>
+import Konva from "konva";
+import {getLotoMapInfo,getLotoInfo,updateLoto} from '@/api/mes/lotoStation/lotoStation'
+
+
+export default {
+  name: "KonvaExample",
+  data() {
+    return {
+      stage: null,
+      layer: null,
+      selectedStates: [], // 用于存储每个元素的选中状态
+      selectedText: [], // 用于存储未选中的元素文本
+      rects: [], // 白色r        ect合集
+      texts: [], // 白色text合集
+      redrects: [], // 红色rect合集
+      redtexts: [], // 白色text合集
+      value:'',
+      form:{},//拿到单个数据
+      orignData:null,//原始数据
+    };
+  },
+  watch:{
+    '$route.query.lotoId':{
+      handler(newValue){
+        if(newValue){
+          this.getLoToInfo()
+          this.initKonva();
+        }
+      }
+    }
+  },
+  mounted() {
+    this.$nextTick(()=>{
+      this.getLoToInfo()
+    })
+    console.log(this.$route.query.lotoId,'lotoId');
+  },
+
+  methods: {
+    goBack(){
+      this.$router.push('/hw/information/lotoStation');
+    },
+    getLoToInfo(){
+      const lotoId=this.$route.query.lotoId;
+      const sopId=''
+      const ticketId=''
+      getLotoInfo(lotoId).then((response) => {
+        console.log(response,'作业区域信息')
+        this.form=response.data
+      })
+      getLotoMapInfo(lotoId,sopId,ticketId).then(response => {
+        console.log(response,'作业区域预览接口调用');
+        this.form.map=response.data;
+
+        if (response.data) {
+          try {
+            this.value = JSON.stringify(response.data, null, 4);
+            this.orignData=this.value
+          } catch (err) {}
+        }
+        this.initKonva();
+      })
+    },
+    // 重置
+    reset(){
+      this.value = this.orignData;
+      this.initKonva(); // 重新初始化 Konva
+    },
+    // 预览
+    view(){
+      if(this.isJson(this.value)){
+        this.form.map=this.value
+        this.initKonva();
+      }else {
+        this.$message({
+          type: 'error',
+          message: '地图数据格式不正确,请输入有效的 JSON 格式!'
+        });
+      }
+    },
+    save() {
+      this.$confirm('请确认是否保存修改内容', '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+        // 校验 this.value 是否为有效的 JSON
+        if (this.isJson(this.value)) {
+          const mapData = typeof this.value === 'string' ? this.value : JSON.stringify(this.value);
+          const formData = {
+            ...this.form,
+            map: mapData
+          };
+          console.log( formData,'map')
+          updateLoto(formData).then(response => {
+            console.log(response, '修改车间区域地图');
+            this.$router.push('/hw/information/lotoStation');
+            this.$message({
+              type: 'success',
+              message: '保存成功!'
+            });
+          });
+        } else {
+          this.$message({
+            type: 'error',
+            message: '地图数据格式不正确,请输入有效的 JSON 格式!'
+          });
+        }
+      }).catch(() => {
+        // 取消操作
+      });
+    },
+
+    // 校验字符串是否为有效的 JSON
+    isJson(str) {
+      try {
+        JSON.parse(str);
+        return true;
+      } catch (e) {
+        return false;
+      }
+    },
+    initKonva() {
+      // 创建舞台
+      this.stage = new Konva.Stage({
+        container: this.$refs.container, // 容器元素
+        width: 1200,
+        height: 860,
+      });
+
+      // 创建图层
+      this.layer = new Konva.Layer();
+
+      // 创建底图
+      const bgImage = new Image();
+      bgImage.src = require("@/assets/images/table.png");
+      bgImage.onload = () => {
+        const knovaImage = new Konva.Image({
+          x: 330,
+          y: 10,
+          image: bgImage,
+          width: 500,
+          height: 790,
+          draggable: false,
+        });
+        this.layer.add(knovaImage);
+        this.layer.draw();
+      };
+
+      // 绘制无限网格
+      this.drawGrid(50, 50, "#e0e0e0"); // 每个单元格50x50,浅灰色网格
+
+      // 渲染数据
+      const imageSrc = require("@/assets/images/localSetIcon.jpg"); // 图片路径
+      this.renderGrid(imageSrc, 6, 3, 450, 100, 120, 100, 50, 50, 60, 25);
+
+      // 将图层添加到舞台
+      this.stage.add(this.layer);
+      this.layer.draw();
+
+      // 禁止舞台拖拽
+      this.stage.draggable(false);
+    },
+
+    // 绘制无限网格
+    drawGrid(cellWidth, cellHeight, gridColor) {
+      const width = 1200;
+      const height = 860;
+
+      // 绘制竖线
+      for (let i = 0; i <= width; i += cellWidth) {
+        const verticalLine = new Konva.Line({
+          points: [i, 0, i, height],
+          stroke: gridColor,
+          strokeWidth: 1,
+        });
+        this.layer.add(verticalLine);
+      }
+
+      // 绘制横线
+      for (let j = 0; j <= height; j += cellHeight) {
+        const horizontalLine = new Konva.Line({
+          points: [0, j, width, j],
+          stroke: gridColor,
+          strokeWidth: 1,
+        });
+        this.layer.add(horizontalLine);
+      }
+
+      this.layer.draw();
+    },
+
+    renderGrid(imageSrc) {
+      this.selectedStates = []; // 用数组来存储选中状态
+      this.rects = [];
+      this.texts = [];
+      this.bgrects={}
+      this.redrects = [];
+      this.redtexts = [];
+      this.selectedText = [];
+
+      const positions=JSON.parse(this.value)
+
+
+      positions.forEach((pos, index) => {
+        const x = pos.col * 50; // 每个单元格宽度为50
+        const y = pos.row * 50; // 每个单元格高度为50
+        const labelText = pos.pointName; // 对应的文字
+
+        const point = new Image();
+        point.src=pos.pointIcon
+        // point.src = imageSrc;
+        point.onload = () => {
+          const knovaImage = new Konva.Image({
+            x: x,
+            y: y,
+            image: point,
+            width: 50,
+            height: 50,
+            draggable: false,
+          });
+
+          // 底部白色背景
+          const bgrect=new Konva.Rect({
+            x: x - 6,
+            y: y - 5,
+            width: 62,
+            height: 80,
+            cornerRadius: 5,
+            stroke: 'white',
+            strokeWidth: 2,
+            fill: 'white'
+          })
+          this.layer.add(bgrect)
+          this.bgrects[labelText] = bgrect // 用文字作为键存储
+
+          // 普通矩形
+          const rect = new Konva.Rect({
+            x: x + 0,
+            y: y - 1,
+            width: 50,
+            height: 72,
+            cornerRadius: 5,
+            stroke: 'red',
+            strokeWidth: 2,
+            fill: 'white'
+          })
+          this.layer.add(rect)
+          this.rects[labelText] = rect // 用文字作为键存储
+          // 先加底部白色 再添加图片
+          this.layer.add(knovaImage)
+
+          // 普通文字
+          const text = new Konva.Text({
+            x: x + 8,
+            y: y + 50,
+            fontSize: 20,
+            text: labelText,
+            fontFamily: 'Calibri',
+            fill: 'red'
+          })
+          this.layer.add(text)
+          this.texts[labelText] = text // 用文字作为键存储
+
+
+          this.layer.draw();
+        };
+      });
+    },
+  },
+};
+</script>
+
+<style scoped lang="scss">
+#container {
+  width: 100%;
+  height: 100%;
+}
+.mapdata{
+  width: 100%;
+  height: 100%;
+  display: flex;
+}
+.left{
+  flex: 1;
+  display: flex;
+  flex-direction: column;
+}
+</style>

+ 479 - 0
src/views/mes/hw/lotoStation/index.vue

@@ -0,0 +1,479 @@
+<template>
+  <div class="app-container">
+    <el-form
+      :model="queryParams"
+      ref="queryForm"
+      size="small"
+      :inline="true"
+      v-show="showSearch"
+      label-width="100px"
+    >
+      <el-row>
+        <el-form-item label="电柜编码" prop="lotoCode">
+          <el-input
+            v-model="queryParams.lotoCode"
+            placeholder="请输入电柜编码"
+            clearable
+            @lotoup.enter.native="handleQuery"
+          />
+        </el-form-item>
+
+        <el-form-item label="电柜名称" prop="lotoName">
+          <el-input
+            v-model="queryParams.lotoName"
+            placeholder="请输入电柜名称"
+            clearable
+            @lotoup.enter.native="handleQuery"
+          />
+        </el-form-item>
+
+        <el-form-item style="margin-left: 20px">
+          <el-button v-no-more-click
+                     type="primary"
+                     icon="el-icon-search"
+                     size="mini"
+                     @click="handleQuery"
+          >搜索
+          </el-button>
+          <el-button v-no-more-click icon="el-icon-refresh" size="mini" @click="resetQuery"
+          >重置
+          </el-button>
+        </el-form-item>
+      </el-row>
+    </el-form>
+
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button v-no-more-click
+                   type="primary"
+                   plain
+                   icon="el-icon-plus"
+                   size="mini"
+                   @click="handleAdd"
+                   v-hasPermi="['iscs:loto:add']"
+        >新增
+        </el-button>
+      </el-col>
+
+      <el-col :span="1.5">
+        <el-button v-no-more-click
+                   type="danger"
+                   plain
+                   icon="el-icon-delete"
+                   size="mini"
+                   :disabled="multiple"
+                   @click="handleDelete"
+                   v-hasPermi="['iscs:loto:remove']"
+        >批量删除
+        </el-button>
+      </el-col>
+      <right-toolbar
+        :showSearch.sync="showSearch"
+        @queryTable="getList"
+      ></right-toolbar>
+    </el-row>
+
+    <el-table
+      v-loading="loading"
+      :data="repairList"
+      @selection-change="handleSelectionChange"
+    >
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column
+        label="电柜编码"
+        width="150px"
+        align="center"
+        prop="lotoCode"
+      />
+      <el-table-column
+        label="电柜名称"
+        width="180px"
+        align="center"
+        prop="lotoName"
+      />
+      <el-table-column label="所属岗位" align="center" prop="workstationName" />
+
+      <el-table-column
+        label="点位信息"
+        align="center"
+        prop="create"
+        width="200"
+      >
+        <template slot-scope="scope">
+          <el-button
+            v-no-more-click
+            size="mini"
+            type="text"
+            @click="look(scope.row)"
+          >预览
+          </el-button>
+        </template>
+      </el-table-column>
+      <el-table-column
+        label="创建时间"
+        align="center"
+        prop="createTime"
+        width="180"
+      >
+        <template slot-scope="scope">
+          <span>{{ scope.row.createTime }}</span>
+        </template>
+      </el-table-column>
+
+      <el-table-column
+        label="操作"
+        align="center"
+        class-name="small-padding fixed-width"
+        fixed="right"
+      >
+        <template slot-scope="scope">
+          <el-button v-no-more-click
+                     size="mini"
+                     type="text"
+                     icon="el-icon-edit"
+                     @click="handleUpdate(scope.row)"
+                     v-hasPermi="['iscs:loto:edit']"
+          >编辑
+          </el-button>
+          <el-button v-no-more-click
+                     size="mini"
+                     type="text"
+                     icon="el-icon-delete"
+                     @click="handleDelete(scope.row)"
+                     v-hasPermi="['iscs:loto:remove']"
+          >删除
+          </el-button>
+          <!--          <el-button v-no-more-click size="mini" type="text">预览</el-button>-->
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <pagination
+      v-show="total > 0"
+      :total="total"
+      :page.sync="queryParams.current"
+      :limit.sync="queryParams.size"
+      @pagination="getList"
+    />
+
+    <!-- 添加或修改设备维修单对话框 -->
+    <el-dialog :title="title" :visible.sync="open" width="450px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="120px">
+        <el-form-item label="电柜名称" prop="lotoName">
+          <el-input v-model="form.lotoName" placeholder="请输入电柜名称" />
+        </el-form-item>
+        <el-row>
+          <el-col :span="15">
+            <el-form-item label="电柜编码" prop="lotoCode">
+              <el-input
+                v-model="form.lotoCode"
+                placeholder="请输入电柜编码"
+                style="width: 100%"
+              />
+            </el-form-item>
+          </el-col>
+          <el-col :span="8">
+            <el-form-item label-width="80">
+              <el-switch
+                v-model="autoGenFlag"
+                active-color="#13ce66"
+                active-text="自动生成"
+                @change="handleAutoGenChange(autoGenFlag)"
+              >
+              </el-switch>
+            </el-form-item>
+          </el-col>
+        </el-row>
+
+        <el-form-item label="所属mars岗位" prop="workstationId" >
+          <treeselect v-model="form.workstationId" :options="marsOptions" :normalizer="Marsnormalizer" placeholder="选择mars岗位"/>
+        </el-form-item>
+        <el-form-item label="点位信息" prop="map">
+          <el-input
+            v-model="form.map"
+            placeholder="请输入点位信息"
+
+          />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button v-no-more-click type="primary" @click="submitForm">确 定</el-button>
+        <el-button v-no-more-click @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import {
+  listLoto,
+  getLotoInfo,
+  addLoto,
+  updateLoto,
+  delLoto
+} from "@/api/mes/lotoStation/lotoStation";
+import { genCode } from "@/api/system/autocode/rule";
+import Treeselect from "@riophae/vue-treeselect";
+import "@riophae/vue-treeselect/dist/vue-treeselect.css";
+import { listMarsDept } from '@/api/system/marsdept'
+export default {
+  name: "lock",
+  dicts: ["hardware_status"],
+  components: { Treeselect },
+  data() {
+    return {
+      autoGenFlag: false,
+      optType: undefined,
+      // 遮罩层
+      loading: true,
+      // 选中数组
+      ids: [],
+      codes: [],
+      // 非单个禁用
+      single: true,
+      // 非多个禁用
+      multiple: true,
+      // 显示搜索条件
+      showSearch: true,
+      // mars树选项
+      marsOptions: [],
+      // 总条数
+      total: 0,
+      // 设备维修单表格数据
+      repairList: [],
+      // 弹出层标题
+      title: "",
+      // 是否显示弹出层
+      open: false,
+      // 查询参数
+      createTime: "",
+      queryParams: {
+        pages: 1,
+        size: 10,
+        lotoCode: null,
+        lotoName: null,
+
+      },
+      // 表单参数
+      form: {
+      },
+      // 表单校验
+      rules: {
+        lotoCode: [
+          { required: true, message: "电柜编码不能为空", trigger: "blur" },
+        ],
+        lotoName: [
+          { required: true, message: "电柜名称不能为空", trigger: "blur" },
+        ],
+      },
+      // 日期选择
+      pickerOptions: {
+        shortcuts: [
+          {
+            text: "最近一周",
+            onClick(picker) {
+              const end = new Date();
+              const start = new Date();
+              start.setTime(start.getTime() - 3600 * 1000 * 24 * 7);
+              picker.$emit("pick", [start, end]);
+            },
+          },
+          {
+            text: "最近一个月",
+            onClick(picker) {
+              const end = new Date();
+              const start = new Date();
+              start.setTime(start.getTime() - 3600 * 1000 * 24 * 30);
+              picker.$emit("pick", [start, end]);
+            },
+          },
+          {
+            text: "最近三个月",
+            onClick(picker) {
+              const end = new Date();
+              const start = new Date();
+              start.setTime(start.getTime() - 3600 * 1000 * 24 * 90);
+              picker.$emit("pick", [start, end]);
+            },
+          },
+        ],
+      },
+      EditId: 0, //修改判断
+      machinerytypeOptions: [], //锁具机构类型
+    };
+  },
+  created() {
+    this.getList();
+
+  },
+  methods: {
+
+    //自动生成编码
+    handleAutoGenChange(autoGenFlag) {
+      if (autoGenFlag) {
+        genCode("LOTO_STATION_CODE").then((response) => {
+          this.form.lotoCode = response;
+        });
+      } else {
+        this.form.lotoCode = null;
+      }
+    },
+    /** 查询设备维修单列表 */
+
+    getList() {
+      this.loading = true;
+
+      // 电柜数据
+      listLoto(this.queryParams).then((response) => {
+        console.log(response,'电柜')
+        this.repairList = response.data.records;
+        this.total = response.data.total;
+        this.loading = false;
+      });
+      const data={
+        pasge:1,
+        size:-1
+      }
+      listMarsDept(data).then(response => {
+        this.marsOptions = this.handleTree(response.data.records,"workstationId","parentId")
+      })
+    },
+    /** 转换部门数据结构 */
+    Marsnormalizer(node) {
+      if (node.children && !node.children.length) {
+        delete node.children
+      }
+      return {
+        id: node.workstationId,
+        label: node.workstationName,
+        children: node.children
+      }
+    },
+    // 取消按钮
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 表单重置
+    reset() {
+      this.form = {
+        lotoName: null,
+        lotoCode: null,
+
+      };
+
+      this.autoGenFlag = false;
+      this.resetForm("form");
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.current = 1;
+      this.getList();
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.queryParams.lotoCode = "";
+      this.queryParams.lotoName = "";
+      this.queryParams.lotoId = "";
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 多选框选中数据
+    handleSelectionChange(selection) {
+      this.ids = selection.map((item) => item.lotoId);
+      this.codes = selection.map((item) => item.lotoCode);
+      this.single = selection.length !== 1;
+      this.multiple = !selection.length;
+    },
+    /** 新增按钮操作 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.EditId = null;
+      this.title = "新增电柜信息";
+    },
+    /** 修改按钮操作 */
+    handleUpdate(row) {
+      this.reset();
+      this.EditId = row.lotoId || this.ids;
+      getLotoInfo(this.EditId).then((response) => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "编辑电柜信息";
+      });
+    },
+    /** 提交按钮 */
+    submitForm() {
+      this.$refs["form"].validate((valid) => {
+        if (valid) {
+          if (this.EditId != null) {
+            updateLoto(this.form).then((response) => {
+              this.$modal.msgSuccess("修改成功");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            // console.log(this.form, "form");
+            addLoto(this.form).then((response) => {
+              this.$modal.msgSuccess("新增成功");
+              this.open = false;
+              this.EditId = null;
+              this.getList();
+            });
+          }
+        }
+      });
+    },
+    // 地图预览
+    look(row) {
+      console.log(row, "row预览");
+      const data = row.lotoId;
+      this.$router.push(`/mes/hw/lotoStation/index/MapData?lotoId=${data}`);
+      // this.dialogVisibleMap = true; // 显示地图预览弹框
+    },
+    /** 删除按钮操作 */
+    handleDelete(row) {
+      const repairIds = row.lotoId || this.ids;
+      const repairCodes = row.lotoCode || this.codes;
+      this.$modal
+        .confirm('是否确认删除编码为"' + repairCodes + '"的数据项?')
+        .then(function () {
+          return delLoto(repairIds);
+        })
+        .then(() => {
+          this.getList();
+          this.$modal.msgSuccess("删除成功");
+        })
+        .catch(() => {});
+    },
+  },
+};
+</script>
+<style scoped>
+.imgstatus {
+  position: relative;
+  top: 1px;
+  left: 0px;
+}
+
+/deep/ .el-radio__inner {
+  border-radius: 2px;
+}
+
+/deep/ .el-radio__input.is-checked .el-radio__inner::after {
+  content: "";
+  width: 8px;
+  height: 3px;
+  border: 1px solid white;
+  border-top: transparent;
+  border-right: transparent;
+  text-align: center;
+  display: block;
+  position: absolute;
+  top: 3px;
+  left: 2px;
+  transform: rotate(-45deg);
+  border-radius: 0pc;
+  background: none;
+}
+</style>

+ 33 - 5
src/views/mes/md/segregationpoint/index.vue

@@ -150,7 +150,7 @@
           </el-button>
         </template>
       </el-table-column> -->
-      <el-table-column label="隔离点编号" align="center" prop="pointCode">
+      <el-table-column label="隔离点编号" align="center" prop="pointCode" width="100">
         <template slot-scope="scope">
           <el-button
             v-no-more-click
@@ -161,8 +161,10 @@
           </el-button>
         </template>
       </el-table-column>
-      <el-table-column label="隔离点名称" align="center" prop="pointName"/>
-      <el-table-column label="隔离点NFC" align="center" prop="pointNfc">
+      <el-table-column label="隔离点名称" align="center" prop="pointName" />
+      <el-table-column label="隔离点NFC" align="center" prop="pointNfc" >
+      </el-table-column>
+      <el-table-column label="所属电柜" align="center" prop="lotoName" >
       </el-table-column>
       <!-- <el-table-column label="状态" align="center" prop="calendarType">
         <template slot-scope="scope">
@@ -421,7 +423,7 @@
           </el-col>
         </el-row>
         <el-row>
-          <el-col :span="12">
+          <el-col :span="11">
            <el-form-item label="锁具机构名称" prop="lockTypeName">
               <el-input
                 style="width: 300px"
@@ -430,6 +432,22 @@
               />
             </el-form-item>
           </el-col>
+          <el-col :span="12">
+            <el-form-item label="所属电柜" prop="lockTypeName">
+            <el-select
+              style="width: 300px"
+              v-model="form.lotoId"
+              placeholder="请选择所属电柜"
+            >
+              <el-option
+                v-for="dict in lotoOptions"
+                :key="dict.value"
+                :label="dict.label"
+                :value="dict.value"
+              />
+            </el-select>
+            </el-form-item>
+          </el-col>
         </el-row>
 
         <el-row>
@@ -511,7 +529,7 @@ import '@riophae/vue-treeselect/dist/vue-treeselect.css'
 import { listWorkarea } from '@/api/mes/wa/workarea'
 import { listLockType } from '@/api/mes/locktype/locktype'
 import { listPadLockTypeAPI } from '@/api/mes/padLockType/padLockType'
-
+import { listLoto} from "@/api/mes/lotoStation/lotoStation";
 export default {
   name: 'Team',
   components: { Treeselect },
@@ -596,6 +614,7 @@ export default {
       form: {},
       LockTypeOptions: [],//锁具机构类型下拉
       padLockTypeOptions: [],//挂锁类型下拉
+      lotoOptions:[],//电柜下拉
       // 表单校验
       rules: {
         pointCode: [
@@ -674,6 +693,15 @@ export default {
       listPadLockTypeAPI(data).then((response) => {
         this.padLockTypeOptions = this.handleTree(response.data.records, 'lockTypeId')
       })
+    //   所属电柜
+      listLoto(data).then((response) => {
+        this.lotoOptions = response.data.records.map((item) => {
+          return {
+            value: item.lotoId,
+            label: item.lotoName
+          }
+        })
+      })
     },
     /** 转换部门数据结构 */
     normalizer(node) {

+ 34 - 38
src/views/mes/md/workarea/MapData.vue

@@ -230,31 +230,12 @@ export default {
       this.selectedStates = []; // 用数组来存储选中状态
       this.rects = [];
       this.texts = [];
+      this.bgrects={}
       this.redrects = [];
       this.redtexts = [];
       this.selectedText = [];
 
       const positions=JSON.parse(this.value)
-      // const positions = [
-      //   { row: 2, col: 9, pointName: "E-1" },
-      //   { row: 2, col: 11, pointName: "E-2" },
-      //   { row: 2, col: 13, pointName: "E-3" },
-      //   { row: 4, col: 9, pointName: "E-4" },
-      //   { row: 4, col: 11, pointName: "E-5" },
-      //   { row: 4, col: 13, pointName: "E-6" },
-      //   { row: 6, col: 9, pointName: "E-7" },
-      //   { row: 6, col: 11, pointName: "E-8" },
-      //   { row: 6, col: 13, pointName: "E-9" },
-      //   { row: 8, col: 9, pointName: "E-10" },
-      //   { row: 8, col: 11, pointName: "E-11" },
-      //   { row: 8, col: 13, pointName: "E-12" },
-      //   { row: 10, col: 9, pointName: "E-13" },
-      //   { row: 10, col: 11, pointName: "E-14" },
-      //   { row: 10, col: 13, pointName: "E-15" },
-      //   { row: 12, col: 9, pointName: "E-16" },
-      //   { row: 12, col: 11, pointName: "E-17" },
-      //   { row: 12, col: 13, pointName: "E-18" },
-      // ];
 
       positions.forEach((pos, index) => {
         const x = pos.col * 50; // 每个单元格宽度为50
@@ -274,33 +255,48 @@ export default {
             draggable: false,
           });
 
-          this.layer.add(knovaImage);
+
+          // 底部白色背景
+          const bgrect=new Konva.Rect({
+            x: x - 6,
+            y: y - 5,
+            width: 62,
+            height: 80,
+            cornerRadius: 5,
+            stroke: 'white',
+            strokeWidth: 2,
+            fill: 'white'
+          })
+          this.layer.add(bgrect)
+          this.bgrects[labelText] = bgrect // 用文字作为键存储
 
           // 普通矩形
           const rect = new Konva.Rect({
-            x: x - 3,
-            y: y + 55,
-            width: 60,
-            height: 25,
-            cornerRadius: 10,
-            stroke: "red",
+            x: x + 0,
+            y: y - 1,
+            width: 50,
+            height: 72,
+            cornerRadius: 5,
+            stroke: 'red',
             strokeWidth: 2,
-            fill: "white",
-          });
-          this.layer.add(rect);
-          this.rects.push(rect); // 用数组存储
+            fill: 'white'
+          })
+          this.layer.add(rect)
+          this.rects[labelText] = rect // 用文字作为键存储
+          // 先加底部白色 再添加图片
+          this.layer.add(knovaImage)
 
           // 普通文字
           const text = new Konva.Text({
-            x: x + 12,
-            y: y + 60,
+            x: x + 8,
+            y: y + 50,
             fontSize: 20,
             text: labelText,
-            fontFamily: "Calibri",
-            fill: "red",
-          });
-          this.layer.add(text);
-          this.texts.push(text); // 用数组存储
+            fontFamily: 'Calibri',
+            fill: 'red'
+          })
+          this.layer.add(text)
+          this.texts[labelText] = text // 用文字作为键存储
 
           this.layer.draw();
         };

+ 124 - 19
src/views/mes/sop/sopm/NewSop.vue

@@ -31,22 +31,25 @@
       style="
         display: flex;
         flex-direction: column;
-        justify-content: center;
-        align-items: center;
+        justify-content: flex-start;
+        align-items: flex-start;
         position: relative;
       "
       v-show="sopStep == 'second'"
     >
+      <h3 style="margin-left: 20px">LD-R&R SOP</h3>
+      <span style="margin-left: 20px">选择 工艺/设备</span>
       <el-table
-        style="width: 50%; margin: 10px"
+        style="width: 50%; margin: 20px"
         :header-cell-style="{ background: '#004d8c', color: '#FFFFFF' }"
         :data="technologyList"
+
       >
         <el-table-column type="selection" width="55" align="center" />
         <el-table-column
           label="设备/工艺名称"
           align="center"
-          prop="technologyName"
+          prop="machineryName"
         ></el-table-column>
         <el-table-column
           label="所属岗位"
@@ -56,32 +59,38 @@
         <el-table-column
           label="设备/工艺类型"
           align="center"
-          prop="technologyType"
+          prop="machineryType"
+        ></el-table-column>
+        <el-table-column
+          label="岗位类型"
+          align="center"
+          prop="workstationType"
         ></el-table-column>
       </el-table>
-      <h2>sop类型</h2>
+      <h2 style="margin-left: 20px">sop类型</h2>
       <el-radio-group
         v-model="selectedOption"
         size="small"
-        style="display: flex; flex-direction: column; align-items: flex-start"
+        style="display: flex; flex-direction: column; align-items: flex-start;"
       >
-        <el-radio label="开收班" border style="margin: 10px">开收班</el-radio>
-        <el-radio label="清洁" border style="margin: 10px 10px">清洁</el-radio>
-        <el-radio label="换产" border style="margin: 10px 10px">换产</el-radio>
-        <el-radio label="维修" border style="margin: 10px 10px">维修</el-radio>
-        <el-radio label="PM" border style="margin: 10px 10px">PM</el-radio>
+        <el-radio label="开收班" border style="margin: 20px">开收班</el-radio>
+        <el-radio label="清洁" border style="margin: 20px">清洁</el-radio>
+        <el-radio label="换产" border style="margin:20px">换产</el-radio>
+        <el-radio label="维修" border style="margin: 20px">维修</el-radio>
+        <el-radio label="PM" border style="margin: 20px ">PM</el-radio>
       </el-radio-group>
-      <el-button @click="handelChange('third')">开始执行</el-button>
+      <el-button type="primary" style="margin-left: 20px" @click="handelChange('third')">开始执行</el-button>
+      <el-button type="warning" style="margin-left: 140px;margin-top: -35px" @click="handelChange('first')">上一步</el-button>
     </div>
-    <div style="position: relative; display: flex" v-show="sopStep == 'third'">
+    <div style="position: relative; display: flex;" v-show="sopStep == 'third'">
       <div
         class="left"
-        style="width: 25%; display: flex; flex-direction: column"
+        style="width: 35%; display: flex; flex-direction: column"
       >
         <div class="left-top">
           <el-card class="box-card" style="margin: 10px">
             <div slot="header" class="clearfix">
-              <span>工艺/涉笔 工艺图</span>
+              <span>工艺/设备 工艺图</span>
             </div>
             <img src="@/assets/images/techonlogy.png" alt="" />
           </el-card>
@@ -112,7 +121,7 @@
             <div style="width: 700px; height: 600px">
               <div style="width: 100%; height: 100px">
                 <div>
-                  <el-table :data="StepData" show-header="false">
+                  <el-table :data="StepData" :show-header="false" style="margin-top: 100px">
                     <el-table-column label="" prop="step"></el-table-column>
                     <el-table-column label="" prop="number">
                       <template slot-scope="scope">
@@ -123,11 +132,16 @@
                     </el-table-column>
                     <el-table-column label="" prop="status">
                       <template slot-scope="scope">
-                        <span v-if="scope.row.status !== '已执行'">
+                        <span v-if="scope.row.status !== '已执行'&&scope.row.step!=='第5步'">
                           <el-button type="primary" plain size="small"
                             >执行</el-button
                           >
                         </span>
+                        <span v-if="scope.row.status !== '已执行'&&scope.row.step=='第5步'">
+                          <el-button type="primary" plain size="small" @click="addInside"
+                          >执行</el-button
+                          >
+                        </span>
                         <span v-if="scope.row.status == '已执行'">
                           <span
                             style="
@@ -149,6 +163,7 @@
                       width="300"
                     ></el-table-column>
                   </el-table>
+                  <el-button type="warning" style="margin-top: 35px" @click="handelChange('second')">上一步</el-button>
                 </div>
               </div>
             </div>
@@ -156,12 +171,68 @@
         </el-card>
       </div>
     </div>
+    <!-- 添加或修改外部人员对话框 -->
+    <el-dialog
+      :visible.sync="open"
+      width="450px"
+      append-to-body
+      style="margin-top: 13%"
+    >
+      <div slot="title" class="dialog-title">
+        <i></i>
+        <span class="title">添加人员</span>
+      </div>
+      <el-form
+        ref="dialogForm"
+        :model="dialogForm"
+        label-width="100px"
+      >
+        <el-form-item label="选择内部人员" prop="nickName" >
+          <el-select
+            v-model="dialogForm.nickName"
+            placeholder="请选择人员"
+            clearable
+            style="width: 100%"
+            multiple
+          >
+            <el-option
+              v-for="dict in this.listLockerOption"
+              :key="dict.value"
+              :label="dict.label"
+              :value="dict.value"
+            />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="选择外部人员" prop="nickName" >
+          <el-select
+            v-model="dialogForm.nickName"
+            placeholder="请选择人员"
+            clearable
+            style="width: 100%"
+            multiple
+          >
+            <el-option
+              v-for="dict in this.listCoLockerOption"
+              :key="dict.value"
+              :label="dict.label"
+              :value="dict.value"
+            />
+          </el-select>
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <!--  内部人员确认-->
+        <el-button v-no-more-click type="primary" @click="cancel" >确认</el-button>
+        <el-button v-no-more-click @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
   </div>
+
 </template>
 
 <script>
 import { listMarsDept } from "@/api/system/marsdept";
-import { listTechnology } from "@/api/system/technology";
+import { listTechnology } from "@/api/system/machinery";
 import Template from "@/views/print/printtemplate/list.vue";
 
 export default {
@@ -226,6 +297,30 @@ export default {
           content: "拆除锁具,并把隔离开关恢复到正常位置",
         },
       ],
+      listLockerOption:[
+        {
+          label: "张三",
+          value: "1",
+        },
+        {
+          label: "里斯",
+          value: "4",
+        },
+      ],//上锁人数据
+      listCoLockerOption:[
+        {
+          label: "鹿眠",
+          value: "1",
+        },
+        {
+          label: "林涧",
+          value: "4",
+        },
+      ],//上锁人数据
+      open:false,//添加人员
+      dialogForm:[
+
+      ],//人员信息
     };
   },
   mounted() {
@@ -250,6 +345,16 @@ export default {
       console.log(val);
       this.sopStep = val;
     },
+    // 添加内部人员
+    addInside() {
+      console.log('添加内部人员')
+      this.open = true
+      this.title = '添加人员'
+    },
+    // 取消按钮
+    cancel() {
+      this.open = false
+    },
   },
 };
 </script>

+ 395 - 0
src/views/system/technology/technologyList/MapData.vue

@@ -0,0 +1,395 @@
+<template>
+  <div class="mapdata">
+    <div id="container" ref="container" style="width:1200px"></div>
+    <div class="left">
+      <el-card class="box-card">
+        <div slot="header" class="clearfix">
+          <span style="font-size: 18px">电柜信息展示</span>
+          <span
+            style="
+                float: right;
+                padding: 1px 0;
+                font-size: 22px;
+                cursor: pointer;
+              "
+            type="text"
+            @click="goBack"
+          >×</span
+          >
+        </div>
+        <div style="height: 100%;padding-bottom:10px">
+          <el-input v-model="value" type="textarea" :rows="34" disabled></el-input>
+
+        </div>
+        <div class="bottombtn" style="width:100%;height: 35px;padding: 10px 0 0">
+          <el-button v-no-more-click @click="save" type="primary" icon="el-icon-edit" style="float: right; height: 33px; line-height: 2px">保存</el-button>
+          <el-button v-no-more-click @click="close" type="primary" icon="el-icon-close"  style="float: right; height: 33px; line-height: 2px;margin: 0 10px">关闭</el-button>
+<!--          <el-button v-no-more-click @click="reset" type="primary" icon="el-icon-refresh"  style="float: right; height: 33px; line-height: 2px;margin: 0 10px">重置</el-button>-->
+<!--          <el-button v-no-more-click @click="view" type="primary" icon="el-icon-view" style="float: right; height: 33px; line-height: 2px">预览</el-button>-->
+        </div>
+      </el-card>
+
+    </div>
+  </div>
+
+</template>
+
+<script>
+import Konva from "konva";
+import {getLotoMapInfo,getLotoInfo,updateLoto} from '@/api/mes/lotoStation/lotoStation'
+import { getTechnologyInfo, saveMachineryPoints } from '@/api/system/machinery'
+
+export default {
+  name: "KonvaExample",
+  data() {
+    return {
+      stage: null,
+      layer: null,
+      selectedStates: [], // 用于存储每个元素的选中状态
+      selectedText: [], // 用于存储未选中的元素文本
+      rects: [], // 白色r        ect合集
+      texts: [], // 白色text合集
+      redrects: [], // 红色rect合集
+      redtexts: [], // 白色text合集
+      value:'',
+      form:{},//拿到单个数据
+      orignData:null,//原始数据
+      pointIdList:[],//选中的隔离点
+      selectPoints:[],//回显之前选中的隔离点
+    };
+  },
+  watch:{
+    '$route.query.lotoId':{
+      handler(newValue){
+        if(newValue){
+          this.getLoToInfo()
+          this.initKonva();
+        }
+      }
+    }
+  },
+  mounted() {
+
+    this.$nextTick(()=>{
+      this.getLoToInfo()
+    })
+    console.log(this.$route.query.lotoId,'lotoId');
+  },
+
+  methods: {
+    goBack(){
+      this.$router.push('/technology/technologyList');
+    },
+    close(){
+      this.$router.push('/technology/technologyList');
+    },
+    getLoToInfo(){
+      const lotoId=this.$route.query.lotoId;
+      const sopId=''
+      const ticketId=''
+      getLotoInfo(lotoId).then((response) => {
+        console.log(response,'电柜信息')
+        this.form=response.data
+      })
+      getLotoMapInfo(lotoId,sopId,ticketId).then(response => {
+        console.log(response,'电柜预览接口调用');
+        this.form.map=response.data;
+
+        if (response.data) {
+          try {
+            this.value = JSON.stringify(response.data, null, 4);
+            this.orignData=this.value
+          } catch (err) {}
+        }
+        this.initKonva();
+      })
+    //   设备工艺详情
+      getTechnologyInfo(this.$route.query.machineryId).then(response => {
+        console.log(response,'设备/工艺详情');
+        this.selectPoints=response.data.pointIdList;
+      })
+    },
+    // 重置
+    reset(){
+      this.value = this.orignData;
+      this.initKonva(); // 重新初始化 Konva
+    },
+    // 预览
+    view(){
+      if(this.isJson(this.value)){
+        this.form.map=this.value
+        this.initKonva();
+      }else {
+        this.$message({
+          type: 'error',
+          message: '地图数据格式不正确,请输入有效的 JSON 格式!'
+        });
+      }
+    },
+    save() {
+      this.$confirm('请确认是否保存修改内容', '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+        // 校验 this.value 是否为有效的 JSON
+        if (this.isJson(this.value)) {
+          const machineryId=this.$route.query.machineryId
+          const formData = {
+            machineryId:machineryId,
+            pointIdList:this.pointIdList,
+          };
+          console.log(this.form, formData,'map')
+          saveMachineryPoints(formData).then(response => {
+            console.log(response, '修改设备/工艺地图');
+            this.$router.push('/technology/technologyList');
+            this.$message({
+              type: 'success',
+              message: '保存成功!'
+            });
+          });
+        } else {
+          this.$message({
+            type: 'error',
+            message: '地图数据格式不正确,请输入有效的 JSON 格式!'
+          });
+        }
+      }).catch(() => {
+        // 取消操作
+      });
+    },
+
+    // 校验字符串是否为有效的 JSON
+    isJson(str) {
+      try {
+        JSON.parse(str);
+        return true;
+      } catch (e) {
+        return false;
+      }
+    },
+    initKonva() {
+      // 创建舞台
+      this.stage = new Konva.Stage({
+        container: this.$refs.container, // 容器元素
+        width: 1200,
+        height: 860,
+      });
+
+      // 创建图层
+      this.layer = new Konva.Layer();
+
+      // 创建底图
+      const bgImage = new Image();
+      bgImage.src = require("@/assets/images/table.png");
+      bgImage.onload = () => {
+        const knovaImage = new Konva.Image({
+          x: 330,
+          y: 10,
+          image: bgImage,
+          width: 500,
+          height: 790,
+          draggable: false,
+        });
+        this.layer.add(knovaImage);
+        this.layer.draw();
+      };
+
+      // 绘制无限网格
+      this.drawGrid(50, 50, "#e0e0e0"); // 每个单元格50x50,浅灰色网格
+
+      // 渲染数据
+      const imageSrc = require("@/assets/images/localSetIcon.jpg"); // 图片路径
+      this.renderGrid(imageSrc, 6, 3, 450, 100, 120, 100, 50, 50, 60, 25);
+
+      // 将图层添加到舞台
+      this.stage.add(this.layer);
+      this.layer.draw();
+
+      // 禁止舞台拖拽
+      this.stage.draggable(false);
+    },
+
+    // 绘制无限网格
+    drawGrid(cellWidth, cellHeight, gridColor) {
+      const width = 1200;
+      const height = 860;
+
+      // 绘制竖线
+      for (let i = 0; i <= width; i += cellWidth) {
+        const verticalLine = new Konva.Line({
+          points: [i, 0, i, height],
+          stroke: gridColor,
+          strokeWidth: 1,
+        });
+        this.layer.add(verticalLine);
+      }
+
+      // 绘制横线
+      for (let j = 0; j <= height; j += cellHeight) {
+        const horizontalLine = new Konva.Line({
+          points: [0, j, width, j],
+          stroke: gridColor,
+          strokeWidth: 1,
+        });
+        this.layer.add(horizontalLine);
+      }
+
+      this.layer.draw();
+    },
+
+    renderGrid(imageSrc) {
+      this.selectedStates = []; // 用数组来存储选中状态
+      this.rects = {};
+      this.texts = {};
+      this.bgrects = {};
+      this.redrects = {};
+      this.redtexts = {};
+      this.selectedText = [];
+      this.pointIdList = []; // 初始化选中的点ID列表
+
+      const positions = JSON.parse(this.value);
+
+      positions.forEach((pos, index) => {
+        const x = pos.col * 50; // 每个单元格宽度为50
+        const y = pos.row * 50; // 每个单元格高度为50
+        const labelText = pos.pointName; // 对应的文字
+
+        const point = new Image();
+        point.src = pos.pointIcon;
+        point.onload = () => {
+          const knovaImage = new Konva.Image({
+            x: x,
+            y: y,
+            image: point,
+            width: 50,
+            height: 50,
+            draggable: false,
+          });
+
+          // 添加点击事件监听器
+          knovaImage.on('click', () => {
+            const isCurrentlySelected = this.redrects[labelText].visible();
+
+            if (isCurrentlySelected) {
+              // 如果当前已选中,则取消选中
+              this.redrects[labelText].visible(false);
+              this.redtexts[labelText].visible(false);
+              this.pointIdList = this.pointIdList.filter(id => id !== pos.pointId); // 移除ID
+            } else {
+              // 如果当前未选中,则选中
+              this.redrects[labelText].visible(true);
+              this.redtexts[labelText].visible(true);
+              this.pointIdList.push(pos.pointId); // 添加ID
+            }
+
+            this.layer.batchDraw(); // 更新图层显示
+          });
+
+          // 底部白色背景
+          const bgrect = new Konva.Rect({
+            x: x - 6,
+            y: y - 5,
+            width: 62,
+            height: 80,
+            cornerRadius: 5,
+            stroke: 'white',
+            strokeWidth: 2,
+            fill: 'white'
+          });
+          this.layer.add(bgrect);
+          this.bgrects[labelText] = bgrect; // 用文字作为键存储
+
+          // 普通矩形
+          const rect = new Konva.Rect({
+            x: x + 0,
+            y: y - 1,
+            width: 50,
+            height: 72,
+            cornerRadius: 5,
+            stroke: 'red',
+            strokeWidth: 2,
+            fill: 'white'
+          });
+          this.layer.add(rect);
+          this.rects[labelText] = rect; // 用文字作为键存储
+
+          // 先加底部白色 再添加图片
+          this.layer.add(knovaImage);
+
+          // 普通文字
+          const text = new Konva.Text({
+            x: x + 8,
+            y: y + 50,
+            fontSize: 20,
+            text: labelText,
+            fontFamily: 'Calibri',
+            fill: 'red'
+          });
+          this.layer.add(text);
+          this.texts[labelText] = text; // 用文字作为键存储
+
+          // 覆盖层(表示选中状态)
+          const redrect = new Konva.Rect({
+            x: x - 7,
+            y: y - 6,
+            width: 64.1,
+            height: 82,
+            cornerRadius: 5,
+            fill: 'rgba(97, 97, 97, 0.5)', // 半透明灰色
+            visible: false, // 初始状态隐藏
+            listening: false
+          });
+          this.layer.add(redrect);
+          this.redrects[labelText] = redrect; // 用文字作为键存储
+
+          // 创建对号文本
+          const redtext = new Konva.Text({
+            x: x - 5 + 42 / 2, // 水平居中
+            y: y + 62 / 2, // 垂直居中
+            fontSize: 24, // 根据需要调整字体大小
+            text: '✔',
+            fontFamily: 'Arial',
+            fill: 'white',
+            align: 'center',
+            verticalAlign: 'middle',
+            visible: false, // 初始隐藏状态
+            listening: false,
+          });
+          this.layer.add(redtext);
+          this.redtexts[labelText] = redtext; // 用文字作为键存储
+
+          // 检查 selectPoints 是否存在并且不为空
+          if (Array.isArray(this.selectPoints) && this.selectPoints.length > 0) {
+            if (this.selectPoints.includes(pos.pointId)) {
+              // 设置选中状态
+              this.redrects[labelText].visible(true);
+              this.redtexts[labelText].visible(true);
+              this.pointIdList.push(pos.pointId); // 添加ID
+            }
+          }
+
+          this.layer.draw();
+        };
+      });
+    }
+  },
+};
+</script>
+
+<style scoped lang="scss">
+#container {
+  width: 100%;
+  height: 100%;
+}
+.mapdata{
+  width: 100%;
+  height: 100%;
+  display: flex;
+}
+.left{
+  flex: 1;
+  display: flex;
+  flex-direction: column;
+}
+</style>

+ 144 - 46
src/views/system/technology/technologyList/index.vue

@@ -1,17 +1,17 @@
 <template>
   <div class="app-container">
     <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch">
-      <el-form-item label="设备/工艺编号" prop="technologyCode">
+      <el-form-item label="设备/工艺编号" prop="machineryCode">
         <el-input
-          v-model="queryParams.technologyCode"
+          v-model="queryParams.machineryCode"
           placeholder="请输入设备/工艺编号"
           clearable
           @keyup.enter.native="handleQuery"
         />
       </el-form-item>
-      <el-form-item label="设备/工艺名称" prop="technologyName">
+      <el-form-item label="设备/工艺名称" prop="machineryName">
         <el-input
-          v-model="queryParams.technologyName"
+          v-model="queryParams.machineryName"
           placeholder="请输入部门名称"
           clearable
           @keyup.enter.native="handleQuery"
@@ -32,7 +32,7 @@
                    icon="el-icon-plus"
                    size="mini"
                    @click="handleAdd"
-                   v-hasPermi="['iscs:technology:add']"
+                   v-hasPermi="['iscs:machinery:add']"
         >新增
         </el-button>
       </el-col>
@@ -53,17 +53,38 @@
       v-if="refreshTable"
       v-loading="loading"
       :data="deptList"
-      row-key="workstationId"
+      row-key="machineryId"
       :default-expand-all="isExpandAll"
       :tree-props="{children: 'children', hasChildren: 'hasChildren'}"
     >
-      <el-table-column prop="technologyCode" label="设备/工艺编码" width="260"></el-table-column>
-      <el-table-column prop="technologyName" label="设备/工艺名称" width="260"></el-table-column>
-      <el-table-column prop="technologyType" label="设备/工艺类型" width="260"></el-table-column>
-      <el-table-column prop="workstationName" label="所属岗位" width="260"></el-table-column>
+      <el-table-column prop="machineryCode" label="设备/工艺编码" ></el-table-column>
+      <el-table-column prop="machineryName" label="设备/工艺名称" ></el-table-column>
+      <el-table-column prop="machineryType" label="设备/工艺类型" ></el-table-column>
+      <el-table-column prop="workstationName" label="所属岗位" >
+        <template slot-scope="scope">
+          <span>{{ scope.row.workstationName }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column prop="lotoName" label="所属电柜" >
+        <template slot-scope="scope">
+          <el-button type="text" @click="look(scope.row)">{{ scope.row.lotoName }}</el-button>
+        </template>
+      </el-table-column>
+      <el-table-column prop="machineryImg" label="工艺图" >
+        <template slot-scope="scope">
+
+          <img
+            v-if="scope.row.machineryImg"
+            :src="scope.row.machineryImg"
+            alt=""
+            style="width: 50px; height: 50px"
+          />
+          <span v-else>-</span>
+        </template>
+      </el-table-column>
       <el-table-column label="创建时间" align="center" prop="createTime" width="200">
         <template slot-scope="scope">
-          <span>{{ parseTime(scope.row.createTime) }}</span>
+          <span>{{ scope.row.createTime }}</span>
         </template>
       </el-table-column>
       <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
@@ -73,7 +94,7 @@
                      type="text"
                      icon="el-icon-edit"
                      @click="handleUpdate(scope.row)"
-                     v-hasPermi="['iscs:technology:edit']"
+                     v-hasPermi="['iscs:machinery:edit']"
           >修改
           </el-button>
           <el-button v-no-more-click
@@ -81,16 +102,17 @@
                      type="text"
                      icon="el-icon-plus"
                      @click="handleAdd(scope.row)"
-                     v-hasPermi="['iscs:technology:add']"
+                     v-hasPermi="['iscs:machinery:add']"
           >新增
           </el-button>
+<!--          v-if="scope.row.parentId != 0"-->
           <el-button v-no-more-click
-                     v-if="scope.row.parentId != 0"
+
                      size="mini"
                      type="text"
                      icon="el-icon-delete"
                      @click="handleDelete(scope.row)"
-                     v-hasPermi="['iscs:technology:remove']"
+                     v-hasPermi="['iscs:machinery:remove']"
           >删除
           </el-button>
         </template>
@@ -98,21 +120,21 @@
     </el-table>
 
     <!-- 添加或修改部门对话框 -->
-    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
-      <el-form ref="form" :model="form" :rules="rules" label-width="110px">
+    <el-dialog :title="title" :visible.sync="open" width="450px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="120px">
 
         <el-form-item label="上级" prop="parentId" >
-          <treeselect v-model="form.parentId" :options="technologyOptions" :normalizer="normalizer" placeholder="选择上级"/>
+          <treeselect v-model="form.parentId" :options="machineryOptions" :normalizer="normalizer" placeholder="选择上级"/>
         </el-form-item>
 
-        <el-form-item label="设备/工艺名称" prop="technologyName">
-          <el-input v-model="form.technologyName" placeholder="请输入设备/工艺名称"/>
+        <el-form-item label="设备/工艺名称" prop="machineryName">
+          <el-input v-model="form.machineryName" placeholder="请输入设备/工艺名称"/>
         </el-form-item>
         <el-row>
           <el-col :span="18">
-            <el-form-item label="设备/工艺编号" prop="workstationCode">
+            <el-form-item label="设备/工艺编号" prop="machineryCode">
               <el-input
-                v-model="form.technologyCode"
+                v-model="form.machineryCode"
                 placeholder="请输入设备/工艺编号"
               />
             </el-form-item>
@@ -129,11 +151,35 @@
             </el-form-item>
           </el-col>
         </el-row>
-        <el-form-item label="设备/工艺类型" prop="technologyType">
-          <el-input v-model="form.technologyType" placeholder="请输入设备/工艺类型" maxlength="20"/>
-        </el-form-item>
         <el-form-item label="所属mars岗位" prop="workstationId" >
-        <treeselect v-model="form.workstationId" :options="marsOptions" :normalizer="Marsnormalizer" placeholder="选择mars岗位"/>
+          <treeselect v-model="form.workstationId" :options="marsOptions"  :normalizer="Marsnormalizer" placeholder="选择mars岗位"/>
+        </el-form-item>
+        <el-form-item label="所属电柜" prop="lotoId">
+          <el-select
+            style="width: 300px"
+            v-model="form.lotoId"
+            placeholder="请选择所属电柜"
+          >
+            <el-option
+              v-for="dict in LotoOptions"
+              :key="dict.value"
+              :label="dict.label"
+              :value="dict.value"
+            />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="设备/工艺类型" prop="machineryType">
+          <el-input v-model="form.machineryType" placeholder="请输入设备/工艺类型" />
+        </el-form-item>
+
+        <el-form-item label="工艺图" prop="machineryImg">
+          <ImageUploadSingle
+            :limit="1"
+            :value="form.machineryImg"
+            :fileSize="5"
+            @onUploaded="handleIconUplaoded"
+            @onRemoved="handleIconRemoved"
+          ></ImageUploadSingle>
         </el-form-item>
       </el-form>
       <div slot="footer" class="dialog-footer">
@@ -147,11 +193,12 @@
 <script>
 import {
   listTechnology, addTechnology, updateTechnology, delTechnology, getTechnologyInfo
-} from '@/api/system/technology'
+} from '@/api/system/machinery'
 import Treeselect from '@riophae/vue-treeselect'
 import '@riophae/vue-treeselect/dist/vue-treeselect.css'
 import { genCode } from '@/api/system/autocode/rule'
 import { listMarsDept } from '@/api/system/marsdept'
+import {listLoto} from '@/api/mes/lotoStation/lotoStation'
 
 export default {
   name: 'Dept',
@@ -170,7 +217,9 @@ export default {
       // mars树选项
       marsOptions: [],
       //工艺树
-      technologyOptions:[],
+      machineryOptions:[],
+      // 电柜
+      lotoOptions:[],
       // 弹出层标题
       title: '',
       // 是否显示弹出层
@@ -183,33 +232,59 @@ export default {
       queryParams: {
         pages:1,
         size:-1,
-        technologyName: undefined,
-        technologyCode: undefined
+        machineryName: undefined,
+        machineryCode: undefined
       },
+      LotoOptions:[],//电柜绑定
       // 表单参数
       form: {},
       // 表单校验
       rules: {
-        technologyCode: [
+        machineryCode: [
           { required: true, message: '设备/工艺编码不能为空', trigger: 'blur' }
         ],
-        technologyName: [
+        machineryName: [
           { required: true, message: '设备/工艺名称不能为空', trigger: 'blur' }
         ],
+        workstationId:[
+          { required: true, message: '岗位不能为空', trigger: 'blur' }
+        ],
+        lotoId:[
+          { required: true, message: '电柜不能为空', trigger: 'blur' }
+        ]
       }
     }
   },
   created() {
     this.getList()
   },
+  watch:{
+    "form.workstationId":function(newVal,oldVal){
+      if(newVal){
+        const data={
+          pasge:1,
+          size:-1,
+          workstationId:this.form.workstationId
+        }
+        listLoto(data).then(response => {
+          this.LotoOptions = response.data.records.map(item => {
+            return {
+              value: item.lotoId,
+              label: item.lotoName
+            }
+          })
+        })
+      }
+    }
+  },
   methods: {
     /** 查询部门列表 */
     getList() {
       this.loading = true
       listTechnology(this.queryParams).then(response => {
         debugger;
-        this.deptList = this.handleTree(response.data.records,"technologyId","parentId")
-        this.technologyOptions = this.handleTree(response.data.records,"technologyId","parentId")
+        this.deptList = this.handleTree(response.data.records,"machineryId","parentId")
+        this.machineryOptions = this.handleTree(response.data.records,"machineryId","parentId")
         console.log(this.deptList,'设备/工艺列表')
         this.loading = false
       })
@@ -220,6 +295,14 @@ export default {
       listMarsDept(data).then(response => {
         this.marsOptions = this.handleTree(response.data.records,"workstationId","parentId")
       })
+      listLoto(data).then(response => {
+        this.LotoOptions = response.data.records.map(item => {
+          return {
+            value: item.lotoId,
+            label: item.lotoName
+          }
+        })
+      })
     },
     /** 转换部门数据结构 */
     Marsnormalizer(node) {
@@ -237,11 +320,18 @@ export default {
         delete node.children
       }
       return {
-        id: node.technologyId,
-        label: node.technologyName,
+        id: node.machineryId,
+        label: node.machineryName,
         children: node.children
       }
     },
+    // 地图预览
+    look(row) {
+      console.log(row, "row预览");
+      const data = row.lotoId;
+      this.$router.push(`/system/technology/technologyList/index/MapData?lotoId=${data}&machineryId=${row.machineryId}`);
+      // this.dialogVisibleMap = true; // 显示地图预览弹框
+    },
     // 取消按钮
     cancel() {
       this.open = false
@@ -250,9 +340,9 @@ export default {
     // 表单重置
     reset() {
       this.form = {
-        technologyId: undefined,
+        machineryId: undefined,
         parentId: undefined,
-        technologyName: undefined,
+        machineryName: undefined,
       }
       this.autoGenFlag = false;
       this.resetForm('form')
@@ -262,12 +352,20 @@ export default {
       if (autoGenFlag) {
         genCode("TECHNOLOGY_CODE").then((response) => {
           console.log(response,'设备工艺编码');
-          this.form.technologyCode = response;
+          this.form.machineryCode = response;
         });
       } else {
-        this.form.technologyCode = null;
+        this.form.machineryCode = null;
       }
     },
+    //图标上传成功
+    handleIconUplaoded(imgUrl) {
+      this.form.machineryImg = imgUrl[0].url
+    },
+    // 图标移除
+    handleIconRemoved(imgUrl) {
+      this.form.machineryImg = null
+    },
     /** 搜索按钮操作 */
     handleQuery() {
       this.getList()
@@ -289,8 +387,8 @@ export default {
     /** 新增按钮操作 */
     handleAdd(row) {
       this.reset()
-      if (row != null && row.technologyId) {
-        this.form.parentId = row.technologyId;
+      if (row != null && row.machineryId) {
+        this.form.parentId = row.machineryId;
       } else {
         this.form.parentId = 0;
       }
@@ -302,7 +400,7 @@ export default {
     /** 修改按钮操作 */
     handleUpdate(row) {
       this.reset()
-      getTechnologyInfo(row.technologyId).then(response => {
+      getTechnologyInfo(row.machineryId).then(response => {
         this.form = response.data
         this.open = true
         this.title = '修改部门'
@@ -313,7 +411,7 @@ export default {
     submitForm: function() {
       this.$refs['form'].validate(valid => {
         if (valid) {
-          if (this.form.technologyId != undefined) {
+          if (this.form.machineryId != undefined) {
             updateTechnology(this.form).then(response => {
               this.$modal.msgSuccess('修改成功')
               this.open = false
@@ -331,8 +429,8 @@ export default {
     },
     /** 删除按钮操作 */
     handleDelete(row) {
-      this.$modal.confirm('是否确认删除名称为"' + row.technologyName + '"的数据项?').then(function() {
-        return delTechnology(row.technologyId)
+      this.$modal.confirm('是否确认删除名称为"' + row.machineryName + '"的数据项?').then(function() {
+        return delTechnology(row.machineryId)
       }).then(() => {
         this.getList()
         this.$modal.msgSuccess('删除成功')

+ 283 - 0
src/views/system/unit/index.vue

@@ -0,0 +1,283 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch">
+      <el-form-item label="单位名称" prop="unitName">
+        <el-input
+          v-model="queryParams.unitName"
+          placeholder="请输入单位名称"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+
+      <el-form-item>
+        <el-button v-no-more-click type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索
+        </el-button>
+        <el-button v-no-more-click icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
+      </el-form-item>
+    </el-form>
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button v-no-more-click
+                   type="primary"
+                   plain
+                   icon="el-icon-plus"
+                   size="mini"
+                   @click="handleAdd"
+                   v-hasPermi="['iscs:unit:add']"
+        >新增
+        </el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button v-no-more-click
+                   type="info"
+                   plain
+                   icon="el-icon-sort"
+                   size="mini"
+                   @click="toggleExpandAll"
+        >展开/折叠
+        </el-button>
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table
+      v-if="refreshTable"
+      v-loading="loading"
+      :data="deptList"
+      row-key="unitId"
+      :default-expand-all="isExpandAll"
+      :tree-props="{children: 'children', hasChildren: 'hasChildren'}"
+    >
+
+      <el-table-column prop="unitName" label="单位名称" width="260"></el-table-column>
+      <el-table-column prop="unitType" label="单位类型" width="260"></el-table-column>
+      <el-table-column label="创建时间" align="center" prop="createTime" width="200">
+        <template slot-scope="scope">
+          <span>{{ scope.row.createTime }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button v-no-more-click
+                     size="mini"
+                     type="text"
+                     icon="el-icon-edit"
+                     @click="handleUpdate(scope.row)"
+                     v-hasPermi="['iscs:unit:edit']"
+          >修改
+          </el-button>
+          <el-button v-no-more-click
+                     size="mini"
+                     type="text"
+                     icon="el-icon-plus"
+                     @click="handleAdd(scope.row)"
+                     v-hasPermi="['iscs:unit:add']"
+          >新增
+          </el-button>
+<!--          v-if="scope.row.parentId != 0"-->
+          <el-button v-no-more-click
+
+                     size="mini"
+                     type="text"
+                     icon="el-icon-delete"
+                     @click="handleDelete(scope.row)"
+                     v-hasPermi="['iscs:unit:remove']"
+          >删除
+          </el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <!-- 添加或修改部门对话框 -->
+    <el-dialog :title="title" :visible.sync="open" width="600px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+
+        <el-form-item label="上级" prop="parentId" v-if="form.parentId !== 0">
+          <treeselect v-model="form.parentId" :options="deptOptions" :normalizer="normalizer" placeholder="选择上级"/>
+        </el-form-item>
+        <el-form-item label="单位名称" prop="unitName">
+          <el-input v-model="form.unitName" placeholder="请输入单位名称"/>
+        </el-form-item>
+        <el-form-item label="单位类型" prop="unitType">
+          <el-input v-model="form.unitType" placeholder="请输入单位类型" maxlength="20"/>
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button v-no-more-click type="primary" @click="submitForm">确 定</el-button>
+        <el-button v-no-more-click @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import {
+  listUnit,getUnitInfo,addUnit,updateUnit,delUnit,
+} from '@/api/system/unit'
+import Treeselect from '@riophae/vue-treeselect'
+import '@riophae/vue-treeselect/dist/vue-treeselect.css'
+import { genCode } from '@/api/system/autocode/rule'
+
+export default {
+  name: 'Dept',
+  dicts: ['sys_normal_disable'],
+  components: { Treeselect },
+  data() {
+    return {
+      // 遮罩层
+      loading: true,
+      //自动生成编码
+      autoGenFlag: false,
+      // 显示搜索条件
+      showSearch: true,
+      // 表格树数据
+      deptList: [],
+      // 部门树选项
+      deptOptions: [],
+      // 弹出层标题
+      title: '',
+      // 是否显示弹出层
+      open: false,
+      // 是否展开,默认全部展开
+      isExpandAll: true,
+      // 重新渲染表格状态
+      refreshTable: true,
+      // 查询参数
+      queryParams: {
+        pages:1,
+        size:-1,
+        unitName: undefined,
+
+      },
+      // 表单参数
+      form: {},
+      // 表单校验
+      rules: {
+        // parentId: [
+        //   { required: true, message: '上级不能为空', trigger: 'blur' }
+        // ],
+        unitName: [
+          { required: true, message: '部门名称不能为空', trigger: 'blur' }
+        ],
+      }
+    }
+  },
+  created() {
+    this.getList()
+  },
+  methods: {
+    /** 查询部门列表 */
+    getList() {
+      this.loading = true
+      listUnit(this.queryParams).then(response => {
+        debugger;
+        this.deptList = this.handleTree(response.data.records,"unitId","parentId")
+        console.log(this.deptList,'单位列表')
+        this.loading = false
+      })
+    },
+    /** 转换部门数据结构 */
+    normalizer(node) {
+      if (node.children && !node.children.length) {
+        delete node.children
+      }
+      return {
+        id: node.unitId,
+        label: node.unitName,
+        children: node.children
+      }
+    },
+    // 取消按钮
+    cancel() {
+      this.open = false
+      this.reset()
+    },
+    // 表单重置
+    reset() {
+      this.form = {
+        unitId: undefined,
+        parentId: undefined,
+        unitName: undefined,
+      }
+      this.autoGenFlag = false;
+      this.resetForm('form')
+    },
+
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.getList()
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.resetForm('queryForm')
+      this.handleQuery()
+    },
+    /** 新增按钮操作 */
+    handleAdd(row) {
+      this.reset()
+      if (row != null && row.unitId) {
+        this.form.parentId = row.unitId;
+      } else {
+        this.form.parentId = 0;
+      }
+      this.open = true
+      this.title = '添加部门'
+      listUnit(this.queryParams).then(response => {
+        this.deptOptions = this.handleTree(response.data.records,"unitId","parentId")
+      })
+    },
+    /** 展开/折叠操作 */
+    toggleExpandAll() {
+      this.refreshTable = false
+      this.isExpandAll = !this.isExpandAll
+      this.$nextTick(() => {
+        this.refreshTable = true
+      })
+    },
+    /** 修改按钮操作 */
+    handleUpdate(row) {
+      this.reset()
+      getUnitInfo(row.unitId).then(response => {
+        this.form = response.data
+        if (this.form.parentId == 0) {
+          this.form.parentId = undefined
+        }
+        this.open = true
+        this.title = '修改部门'
+      })
+
+    },
+    /** 提交按钮 */
+    submitForm: function() {
+      this.$refs['form'].validate(valid => {
+        if (valid) {
+          if (this.form.unitId != undefined) {
+            updateUnit(this.form).then(response => {
+              this.$modal.msgSuccess('修改成功')
+              this.open = false
+              this.getList()
+            })
+          } else {
+            addUnit(this.form).then(response => {
+              this.$modal.msgSuccess('新增成功')
+              this.open = false
+              this.getList()
+            })
+          }
+        }
+      })
+    },
+    /** 删除按钮操作 */
+    handleDelete(row) {
+      this.$modal.confirm('是否确认删除名称为"' + row.unitName + '"的数据项?').then(function() {
+        return delUnit(row.unitId)
+      }).then(() => {
+        this.getList()
+        this.$modal.msgSuccess('删除成功')
+      }).catch(() => {
+      })
+    }
+  }
+}
+</script>

+ 30 - 1
src/views/system/user/index.vue

@@ -307,6 +307,11 @@
               </el-select>
             </el-form-item>
           </el-col>
+          <el-col :span="12">
+            <el-form-item label="归属单位" prop="unitIds">
+              <treeselect v-model="form.unitIds" :options="UnitOptions" :normalizer="Unitnormalizer" :show-count="true" placeholder="请选择归属单位" />
+            </el-form-item>
+          </el-col>
         </el-row>
         <el-row>
           <el-col :span="24">
@@ -361,6 +366,7 @@ import { getToken } from "@/utils/auth";
 import { treeselect } from "@/api/system/dept";
 import Treeselect from "@riophae/vue-treeselect";
 import "@riophae/vue-treeselect/dist/vue-treeselect.css";
+import { listUnit } from '@/api/system/unit'
 
 export default {
   name: "User",
@@ -386,6 +392,8 @@ export default {
       title: "",
       // 部门树选项
       deptOptions: undefined,
+      // 单位树选项
+      UnitOptions:undefined,
       // 是否显示弹出层
       open: false,
       // 部门名称
@@ -669,8 +677,25 @@ export default {
         console.log(response.data,'部门下拉树形结构')
         this.deptOptions = response.data;
       });
+      const data={
+        pages:1,
+        size:-1
+      }
+      listUnit(data).then(response => {
+        console.log(response,'单位树');
+        this.UnitOptions = this.handleTree(response.data.records, "unitId");
+      })
+    },
+    Unitnormalizer(node){
+      if (node.children && !node.children.length) {
+        delete node.children;
+      }
+      return {
+        id: node.unitId,
+        label: node.unitName,
+        children: node.children
+      };
     },
-
     /** 新增按钮操作 */
     handleAdd() {
       this.reset();
@@ -705,12 +730,14 @@ export default {
         this.roleOptions = response.roles;
         this.form.postIds = response.postIds;
         this.form.roleIds = response.roleIds;
+
         //查找并转换
         if(response.workstationIds){
           this.editTag(response.workstationIds)
         }else {
           this.form.workstationIds=[]
         }
+        this.form.unitIds= response.unitIds;
         this.title = "修改用户";
         this.form.password = "";
       });
@@ -745,6 +772,7 @@ export default {
               return record ? record.workstationId : null;
             }).filter(id => id !== null);
             this.form.workstationIds=workstationIds
+            this.form.unitIds=[this.form.unitIds]
             updateUser(this.form).then(response => {
               this.$modal.msgSuccess("修改成功");
               this.open = false;
@@ -757,6 +785,7 @@ export default {
               return record ? record.workstationId : null;
             }).filter(id => id !== null);
             this.form.workstationIds=workstationIds
+            this.form.unitIds=[this.form.unitIds]
             console.log(this.form,'新增参数')
             addUser(this.form).then(response => {
               this.$modal.msgSuccess("新增成功");