Эх сурвалжийг харах

锁定站拖拽左右修复,渲染延迟问题,新增物资相关页面

pm 9 сар өмнө
parent
commit
46889cf276

BIN
src/assets/images/table_map1.png


BIN
src/assets/images/table_map2.png


BIN
src/assets/images/table_map3.png


+ 1 - 1
src/views/mes/dv/technology/technologyList/index.vue

@@ -6,7 +6,7 @@
         <div class="head-container">
           <el-input
             v-model="queryParams.workstationName"
-            placeholder="请输入岗位名称"
+            placeholder="请在下方选择岗位名称"
             clearable
             size="small"
             prefix-icon="el-icon-search"

+ 106 - 66
src/views/mes/hw/lotoStation/MapData.vue

@@ -64,18 +64,26 @@ export default {
         if(newValue){
           this.getLoToInfo()
           this.initKonva();
+          this.getIsIsolationPointPage()
         }
       }
     }
   },
+  beforeRouteEnter(to, from, next) {
+    next(vm=>{
+      vm.getLoToInfo()
+      vm.initKonva()
+      vm.getIsIsolationPointPage()
+    })
+  },
   mounted() {
-    this.getIsIsolationPointPage()
     this.$nextTick(()=>{
       this.getLoToInfo()
+      this.getIsIsolationPointPage()
+      this.initKonva();
     })
     console.log(this.$route.query.lotoId,'lotoId');
   },
-
   methods: {
     goBack(){
       this.$router.push('/hw/information/lotoStation');
@@ -110,11 +118,14 @@ export default {
       getIsIsolationPointPage(data).then(res=>{
         console.log(res,'所有隔离点')
         // 过滤掉 originData 中已经存在的数据
-        // const filter = res.data.records.filter(record => {
-        //   // 判断 res.data.records 中的 record 是否不在 this.filterData 中
-        //   return !this.filterData.some(item => item.pointId === record.pointId);
-        // });
-        this.allPoints = res.data.records.map(item => {
+        const data1 = res.data.records;
+        const data2 = this.filterData;
+        const filteredData = data1.filter(item1 =>
+          !data2.some(item2 => item1.pointId === item2.pointId) // 比较 pointId 是否存在于 data2 中
+        );
+        // console.log(data1,data2,filteredData,'过滤之后的隔离点')
+
+        this.allPoints = filteredData.map(item => {
           return {
             pointId: item.pointId,
             pointName: item.pointName,
@@ -143,6 +154,8 @@ export default {
       if(this.isJson(this.value)){
         this.form.map=this.value
         this.initKonva();
+        this.getIsIsolationPointPage()
+
       }else {
         this.$message({
           type: 'error',
@@ -202,11 +215,13 @@ export default {
 
       // 创建图层
       this.layer = new Konva.Layer();
-
+// 绘制隔离点等其他内容
+      this.drawGrid(50, 50, "#e0e0e0"); // 每个单元格50x50,浅灰色网格
       // 创建底图
       const bgImage = new Image();
       bgImage.src = require("@/assets/images/table.png");
       bgImage.onload = () => {
+        // 创建背景图并添加到图层
         const knovaImage = new Konva.Image({
           x: 330,
           y: 10,
@@ -216,38 +231,37 @@ export default {
           draggable: false,
         });
         this.layer.add(knovaImage);
+
+        // 创建所有隔离点父盒子 放置于网格线上
+        const allPointsBox = new Konva.Rect({
+          x: 1000,
+          y: 10,
+          width: 200,
+          height: 800,
+          cornerRadius: 5,
+          stroke: 'black',
+          strokeWidth: 2,
+          fill: 'white',
+        });
+        this.layer.add(allPointsBox);
+
+        // 调用函数将隔离点添加到 allPointsBox
+        this.addPointsToAllPointsBox(allPointsBox);
+
+        // 渲染数据
+        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.drawGrid(50, 50, "#e0e0e0"); // 每个单元格50x50,浅灰色网格
-      // 创建所有隔离点父盒子 放置于网格线上
-      const allPointsBox=new Konva.Rect({
-        x: 1000,
-        y: 10,
-        width: 200,
-        height: 800,
-        cornerRadius: 5,
-        stroke: 'black',
-        strokeWidth: 2,
-        fill: 'white'
-      })
-      this.layer.add(allPointsBox);
-      this.layer.draw();
-      // 调用函数将隔离点添加到 allPointsBox
-      this.addPointsToAllPointsBox(allPointsBox);
-      // 渲染数据
-      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;
@@ -416,18 +430,16 @@ export default {
         });
       }
     },
-
     renderGrid(imageSrc) {
       this.selectedStates = []; // 用数组来存储选中状态
       this.rects = [];
       this.texts = [];
-      this.bgrects={}
+      this.bgrects = {};
       this.redrects = [];
       this.redtexts = [];
       this.selectedText = [];
 
-      const positions=JSON.parse(this.value)
-
+      const positions = JSON.parse(this.value);
 
       positions.forEach((pos, index) => {
         const x = pos.col * 50; // 每个单元格宽度为50
@@ -435,65 +447,93 @@ export default {
         const labelText = pos.pointName; // 对应的文字
 
         const point = new Image();
-        point.src=pos.pointIcon
+        point.src = pos.pointIcon;
 
         point.onload = () => {
-          const knovaImage = new Konva.Image({
+          // 创建一个新的Group来包含整个隔离点
+          const group = new Konva.Group({
             x: x,
             y: y,
-            image: point,
-            width: 50,
-            height: 50,
-            draggable: false,
+            draggable: true, // 设置为可拖拽
           });
 
           // 底部白色背景
-          const bgrect=new Konva.Rect({
-            x: x - 6,
-            y: y - 5,
+          const bgrect = new Konva.Rect({
+            x: -6,
+            y: -5,
             width: 62,
             height: 80,
             cornerRadius: 5,
             stroke: 'white',
             strokeWidth: 2,
-            fill: 'white'
-          })
-          this.layer.add(bgrect)
-          this.bgrects[labelText] = bgrect // 用文字作为键存储
+            fill: 'white',
+          });
 
           // 普通矩形
           const rect = new Konva.Rect({
-            x: x + 0,
-            y: y - 1,
+            x: 0,
+            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)
+            fill: 'white',
+          });
+
+          // 图片
+          const knovaImage = new Konva.Image({
+            x: 0,
+            y: 0,
+            image: point,
+            width: 50,
+            height: 50,
+          });
 
-          // 普通文字
+          // 文字
           const text = new Konva.Text({
-            x: x + 8,
-            y: y + 50,
+            x: 8,
+            y: 50,
             fontSize: 17,
             text: labelText,
             fontFamily: 'Calibri',
-            fill: 'red'
-          })
-          this.layer.add(text)
-          this.texts[labelText] = text // 用文字作为键存储
+            fill: 'red',
+          });
+
+          // 将所有元素添加到group中
+          group.add(bgrect);
+          group.add(rect);
+          group.add(knovaImage);
+          group.add(text);
+
+          // 将group添加到layer
+          this.layer.add(group);
+
+          // 监听拖拽结束事件
+          group.on('dragend', () => {
+            // 获取拖拽的内容对应的点名称
+            const labelText = group.findOne('Text').text();
+
+            // 从 positions 中删除对应的内容
+            const indexToRemove = positions.findIndex(item => item.pointName === labelText);
+            if (indexToRemove !== -1) {
+              positions.splice(indexToRemove, 1);
+            }
+
+            // 更新 this.value,删除对应的数据
+            this.value = JSON.stringify(positions, null, 4);
 
+            // 在控制台查看结果
+            console.log('Updated positions:', positions);
+          });
 
           this.layer.draw();
         };
       });
-    },
+    }
+
+
+
   },
 };
 </script>

+ 445 - 0
src/views/mes/material/Inspectionrecords/index.vue

@@ -0,0 +1,445 @@
+<template>
+  <div class="app-container">
+    <el-form
+      :model="queryParams"
+      ref="queryForm"
+      size="small"
+      :inline="true"
+      v-show="showSearch"
+      label-width="100px"
+    >
+      <el-form-item label="计划名称" prop="materialsCode">
+        <el-input
+          v-model="queryParams.materialsCode"
+          placeholder="请输入计划名称"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="计划日期">
+        <el-date-picker
+          style="width: 215px"
+          :default-time="['00:00:00', '23:59:59']"
+          v-model="restitutionTime"
+          type="datetimerange"
+          :picker-options="pickerOptions"
+          range-separator="-"
+          start-placeholder="开始日期"
+          end-placeholder="结束日期"
+          align="right"
+        >
+        </el-date-picker>
+      </el-form-item>
+      <el-form-item label="岗位" prop="workstationId">
+        <treeselect
+          style="width: 218px"
+          v-model="queryParams.workstationId"
+          :options="marsOptions"
+          :normalizer="normalizer"
+          placeholder="选择岗位"
+        />
+      </el-form-item>
+      <el-form-item label="物资柜" prop="cabinetIdStr">
+        <el-select
+          style="width: 208px"
+          v-model="queryParams.cabinetIdStr"
+          placeholder="请选择物资柜"
+          multiple
+          clearable
+        >
+          <el-option
+            v-for="dict in cabinets"
+            :key="dict.value"
+            :label="dict.label"
+            :value="dict.value"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="物资名称" prop="materialsName">
+        <el-input
+          v-model="queryParams.materialsName"
+          placeholder="请输入物资名称"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="物资类型" prop="materialsTypeId">
+        <treeselect
+          style="width: 215px"
+          v-model="queryParams.materialsTypeId"
+          :options="materialstypeOptions"
+          :normalizer="materialnormalizer"
+          placeholder="请选择物资类型"
+        />
+      </el-form-item>
+      <el-form-item label="状态" prop="status">
+        <el-select v-model="queryParams.status" placeholder="状态">
+          <el-option
+            v-for="dict in dict.type.checking_status"
+            :key="dict.value"
+            :label="dict.label"
+            :value="dict.value"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="异常原因" prop="cabinetIdStr">
+        <el-select
+          style="width: 208px"
+          v-model="queryParams.cabinetIdStr"
+          placeholder="请选择异常原因"
+          multiple
+          clearable
+        >
+          <el-option
+            v-for="dict in cabinets"
+            :key="dict.value"
+            :label="dict.label"
+            :value="dict.value"
+          />
+        </el-select>
+      </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-table
+      v-loading="loading"
+      :data="materialsList"
+      @selection-change="handleSelectionChange"
+    >
+      <el-table-column type="selection" width="55" align="center"/>
+      <el-table-column label="计划名称" align="center" prop="checkName">
+      </el-table-column>
+      <el-table-column label="岗位" align="center" prop="workstationId">
+      </el-table-column>
+      <el-table-column label="物资柜" align="center" prop="cabinetIdStr">
+      </el-table-column>
+      <el-table-column label="物资编号" align="center" prop="materialsId">
+      </el-table-column>
+      <el-table-column label="物资名称" align="center" prop="materialsName" />
+      <el-table-column label="物资类型" align="center" prop="materialsTypeName" />
+      <el-table-column
+        label="物资图片"
+        align="center"
+        prop="materialsTypePicture"
+      >
+        <template slot-scope="scope">
+          <img
+            v-if="scope.row.materialsTypePicture"
+            :src="scope.row.materialsTypePicture"
+            alt=""
+            style="width: 50px; height: 50px"
+          />
+          <span v-else>-</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="RFID" align="center" prop="RFID">
+      </el-table-column>
+
+      <el-table-column
+        label="检查时间"
+        align="center"
+        prop="cron"
+      >
+        <template slot-scope="scope">
+          {{ cronDescription(scope.row.cron) }}
+        </template>
+      </el-table-column>
+      <el-table-column label="状态" align="center" prop="status">
+        <template slot-scope="scope">
+          <dict-tag :options="dict.type.checking_status" :value="scope.row.status"/>
+        </template>
+      </el-table-column>
+      <el-table-column label="异常原因" align="center" prop="RFID">
+      </el-table-column>
+      <el-table-column label="更换记录" align="center" prop="status">
+        <template slot-scope="scope">
+          <el-button type="text" @click="goto">查看</el-button>
+        </template>
+      </el-table-column>
+
+    </el-table>
+    <pagination
+      v-show="total > 0"
+      :total="total"
+      :page.sync="queryParams.pages"
+      :limit.sync="queryParams.size"
+      @pagination="getList"
+    />
+
+  </div>
+</template>
+
+<script>
+import {
+  listCheckTask,
+  addCheckTask,
+  getPlanPerson,
+  updateCheckTask,
+  deleteCheckTask,
+  selectCheckTaskById,
+  getIsCheckTaskCabinets
+} from '@/api/mes/material/plan'
+import { genCode } from '@/api/system/autocode/rule'
+import Crontab from '@/components/Crontab/index.vue'
+import cronstrue from 'cronstrue/i18n';
+import Treeselect from '@riophae/vue-treeselect'
+import '@riophae/vue-treeselect/dist/vue-treeselect.css'
+import { listMarsDept } from '@/api/system/marsdept'
+import { listType } from '@/api/mes/material/typeindex'
+import Template from '@/views/print/printtemplate/list.vue'
+
+export default {
+  name: 'Team',
+  components: { Template, Treeselect, Crontab },
+  dicts: ['material_status','checking_status'],
+  data() {
+    return {
+      //自动生成编码
+      autoGenFlag: false,
+      optType: undefined,
+      // 遮罩层
+      loading: true,
+      // 选中数组
+      ids: [],
+      codes: [],
+      // 非单个禁用
+      single: true,
+      // 非多个禁用
+      multiple: true,
+      // 显示搜索条件
+      showSearch: true,
+      // 总条数
+      total: 0,
+      // 班组表格数据
+      materialsList: [],
+      // mars树选项
+      marsOptions: [],
+
+      // 查询参数
+      createTime: '',
+      queryParams: {
+        pages: 1,
+        size: 10,
+        materialsCode: null,
+        materialsName: null,
+        loanState: null,
+        materialsCabinetId: null,
+        materialsTypeId: null,
+        startTime: '',
+        endTime: ''
+      },
+      // 查询参数
+      queryParamsCabinets: {
+        current: 1,
+        size: -1
+      },
+
+      // 表单参数
+      form: {},
+      cabinets: [], //物资所属柜
+      planPersonOption: [],// 检查人员
+      // 表单校验
+      rules: {
+        userIdStr: [
+          { required: true, message: '人员不能为空', trigger: 'blur' }
+        ],
+        checkName: [
+          { required: true, message: '任务名称不能为空', trigger: 'blur' }
+        ],
+        cron: [
+          { 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]);
+            },
+          },
+        ],
+      },
+      materialstypeOptions:[],
+    }
+  },
+  created() {
+    this.getList()
+    this.getTreeselect()
+    this.materialsCabinets()
+  },
+
+  methods: {
+
+    /** 查询物资信息列表 */
+    getList() {
+      this.loading = true
+      // 格式化日期并更新 queryParams
+      if (Array.isArray(this.createTime) && this.createTime.length === 2) {
+        this.queryParams.startTime = this.formatDate(this.createTime[0])
+        this.queryParams.endTime = this.formatDate(this.createTime[1])
+      }
+      listCheckTask(this.queryParams).then((response) => {
+        console.log(response, '获取物资信息allList ')
+        this.materialsList = response.data.records
+        this.total = response.data.total
+        this.machinerytypeList = this.handleTree(
+          response.data.records,
+          'materialsTypeId',
+          'parentId',
+          'children'
+        )
+        this.loading = false
+      })
+
+    },
+    /** 查询物资类型下拉树结构 */
+    getTreeselect() {
+      const data = {
+        current: 1,
+        size: -1
+      }
+      listType(data).then((response) => {
+        console.log(response,'物资类型树形结构')
+        this.materialstypeOptions = this.handleTree(
+          response.data.records,
+          'materialsTypeId',
+          'parentId',
+          'children'
+        )
+      })
+    },
+    /** 查询物资柜结构 */
+    materialsCabinets() {
+      getIsCheckTaskCabinets(this.queryParamsCabinets).then((response) => {
+        if (response?.data?.records) {
+          // 提取 cabinetId 和 cabinetName
+          this.cabinets = response.data.records.map((item) => ({
+            value: item.cabinetId,
+            label: item.cabinetName
+          }))
+        }
+        // 岗位查询
+        const data1 = {
+          pasge: 1,
+          size: -1
+        }
+        listMarsDept(data1).then((response) => {
+          this.marsOptions = this.handleTree(response.data.records,"workstationId","parentId")
+        })
+      })
+      // 巡检人员
+      const data = {
+        pageNum: 1,
+        pageSize: 99999
+      }
+      getPlanPerson(data).then((res) => {
+        console.log(res, '巡检人员信息')
+        this.planPersonOption = res.rows.map((item) => {
+          return {
+            label: item.nickName,
+            value: item.userId
+          }
+        })
+      })
+    },
+    /** 查询岗位下拉树结构 */
+    normalizer(node) {
+      if (node.children && !node.children.length) {
+        delete node.children
+      }
+      return {
+        id: node.workstationId,
+        label: node.workstationName,
+        children: node.children
+      }
+    },
+    /** 查询物资类型下拉树结构 */
+    materialnormalizer(node) {
+      if (node.children && !node.children.length) {
+        delete node.children
+      }
+      return {
+        id: node.materialsTypeId,
+        label: node.materialsTypeName,
+        children: node.children
+      }
+    },
+
+    // 表单重置
+    reset() {
+      this.form = {
+        cron: undefined
+      }
+      this.resetForm('form')
+      this.autoGenFlag = false
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.pages = 1
+      this.getList()
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.resetForm('queryForm')
+      this.handleQuery()
+    },
+    // 多选框选中数据
+    handleSelectionChange(selection) {
+      this.ids = selection.map((item) => item.checkId)
+      this.single = selection.length !== 1
+      this.multiple = !selection.length
+    },
+
+
+
+
+  }
+}
+</script>
+<style lang="scss" src="@/assets/styles/dialog-title.scss" scoped>
+.el-input-width {
+  width: 380px !important;
+
+}
+</style>

+ 1 - 1
src/views/mes/material/collectionmanagement/index.vue

@@ -445,7 +445,7 @@ export default {
     getTreeselect() {
       const data = {
         current: 1,
-        size: 99999
+        size: -1
       }
 
       listType(data).then((response) => {

+ 13 - 0
src/views/mes/material/lockers/Map.vue

@@ -0,0 +1,13 @@
+<template>
+
+</template>
+<script>
+export default {
+  name: 'Map'
+}
+</script>
+
+
+<style scoped lang="scss">
+
+</style>

+ 237 - 153
src/views/mes/material/lockers/index.vue

@@ -1,141 +1,212 @@
 <template>
   <div class="app-container">
-    <el-form
-      :model="queryParams"
-      ref="queryForm"
-      size="small"
-      :inline="true"
-      v-show="showSearch"
-      label-width="100px"
+    <el-radio-group v-model="tabPosition" style="margin: 5px">
+      <el-radio-button label="first">物资柜位置</el-radio-button>
+      <el-radio-button label="second">物资柜列表</el-radio-button>
+    </el-radio-group>
+    <div
+      style="
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        position: relative;
+      "
+      v-show="tabPosition == 'first'"
     >
-      <el-form-item label="物资柜编码" prop="cabinetCode">
-        <el-input
-          v-model="queryParams.cabinetCode"
-          placeholder="请输入物资柜编码"
-          clearable
-          @keyup.enter.native="handleQuery"
+      <!-- 缩放容器 -->
+      <div
+        ref="mapContainer"
+        :style="{
+          transform: `scale(${scaleFactor})`,
+          transformOrigin: 'top left',
+          width: '1250px',
+          height: '700px',
+          position: 'relative',
+
+        }"
+      >
+        <img
+          style="width: 100%; height: 100%"
+          src="@/assets/images/marsBg.png"
+          alt=""
         />
-      </el-form-item>
-      <el-form-item label="物资柜名称" prop="cabinetName">
-        <el-input
-          v-model="queryParams.cabinetName"
-          placeholder="请输入物资柜名称"
-          clearable
-          @keyup.enter.native="handleQuery"
+        <img
+          v-for="(cabinet, index) in TicketListPage"
+          :key="cabinet.cabinetId"
+          :style="{
+    width: '35px',
+    height: '35px',
+    position: 'absolute',
+    cursor: 'pointer',
+    // 图标垂直居中
+    top: `${deptXLGCenter.top - 53}px`,
+    // 图标水平居中,动态计算偏移
+    left: `${deptXLGCenter.left - (TicketListPage.length * 35 + (TicketListPage.length - 1) * 5) / 2 + index * 40}px`,
+  }"
+          :src="require('@/assets/images/table_map2.png')"
+          alt=""
+          @click="handleCabinetClick(cabinet)"
         />
-      </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:cabinet: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="['mes:mat:info:batchremove']"
-        >批量删除
-        </el-button>
-      </el-col>
 
-      <right-toolbar
-        :showSearch.sync="showSearch"
-        @queryTable="getList"
-      ></right-toolbar>
-    </el-row>
+        <!-- deptCCO 区域的图标 -->
+        <img
+          v-for="(cabinet, index) in COCOTicketListPage"
+          :key="cabinet.cabinetId"
+          :style="{
+    width: '35px',
+    height: '35px',
+    position: 'absolute',
+    cursor: 'pointer',
+    // 图标垂直居中
+    top: `${deptCCOCenter.top - 53}px`,
+    // 图标水平居中,动态计算偏移
+    left: `${deptCCOCenter.left - (COCOTicketListPage.length * 35 + (COCOTicketListPage.length - 1) * 5) / 2 + index * 40}px`,
+  }"
+          :src="require('@/assets/images/table_map2.png')"
+          alt=""
+          @click="handleCabinetClick(cabinet)"
+        />
+        <div class="deptXLG" >R&R</div>
+        <div class="deptCCO" >CCO</div>
+      </div>
+    </div>
+    <div v-if="tabPosition == 'second'">
+      <el-form
+        :model="queryParams"
+        ref="queryForm"
+        size="small"
+        :inline="true"
+        v-show="showSearch"
+        label-width="100px"
+      >
+        <el-form-item label="物资柜编码" prop="cabinetCode">
+          <el-input
+            v-model="queryParams.cabinetCode"
+            placeholder="请输入物资柜编码"
+            clearable
+            @keyup.enter.native="handleQuery"
+          />
+        </el-form-item>
+        <el-form-item label="物资柜名称" prop="cabinetName">
+          <el-input
+            v-model="queryParams.cabinetName"
+            placeholder="请输入物资柜名称"
+            clearable
+            @keyup.enter.native="handleQuery"
+          />
+        </el-form-item>
 
-    <el-table
-      v-loading="loading"
-      :data="materialsList"
-      @selection-change="handleSelectionChange"
-    >
-      <el-table-column type="selection" width="55" align="center"/>
-      <el-table-column label="物资柜编码" align="center" prop="cabinetCode">
-      </el-table-column>
-      <el-table-column label="物资柜名称" align="center" prop="cabinetName"/>
-      <el-table-column
-        label="硬件名称"
-        align="center"
-        prop="hardwareName"
-      />
-<!--      <el-table-column-->
-<!--        label="工作区域"-->
-<!--        align="center"-->
-<!--        prop="workareaName"-->
-<!--      />-->
-      <el-table-column label="创建时间" align="center" prop="createTime"/>
-      <el-table-column label="更新时间" align="center" prop="updateTime"/>
 
-      <el-table-column
-        label="操作"
-        align="center"
-        class-name="small-padding fixed-width"
-      >
-        <template slot-scope="scope">
+        <el-form-item>
           <el-button
             v-no-more-click
+            type="primary"
+            icon="el-icon-search"
             size="mini"
-            type="text"
-            icon="el-icon-edit"
-            @click="handleUpdate(scope.row)"
-            v-hasPermi="['iscs:cabinet:edit']"
-          >编辑
-          </el-button>
+            @click="handleQuery"
+          >搜索
+          </el-button
+          >
           <el-button
             v-no-more-click
+            icon="el-icon-refresh"
             size="mini"
-            type="text"
+            @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:cabinet:add']"
+          >新增
+          </el-button>
+        </el-col>
+        <el-col :span="1.5">
+          <el-button
+            v-no-more-click
+            type="danger"
+            plain
             icon="el-icon-delete"
-            @click="handleDelete(scope.row)"
-            v-hasPermi="['iscs:cabinet:remove']"
-          >删除
+            size="mini"
+            :disabled="multiple"
+            @click="handleDelete"
+            v-hasPermi="['mes:mat:info:batchremove']"
+          >批量删除
           </el-button>
-        </template>
-      </el-table-column>
-    </el-table>
-    <pagination
-      v-show="total > 0"
-      :total="total"
-      :page.sync="queryParams.pages"
-      :limit.sync="queryParams.size"
-      @pagination="getList"
-    />
+        </el-col>
+
+        <right-toolbar
+          :showSearch.sync="showSearch"
+          @queryTable="getList"
+        ></right-toolbar>
+      </el-row>
+      <el-table
+        v-loading="loading"
+        :data="materialsList"
+        @selection-change="handleSelectionChange"
+      >
+        <el-table-column type="selection" width="55" align="center"/>
+        <el-table-column label="物资柜编码" align="center" prop="cabinetCode">
+        </el-table-column>
+        <el-table-column label="物资柜名称" align="center" prop="cabinetName"/>
+        <el-table-column
+          label="硬件名称"
+          align="center"
+          prop="hardwareName"
+        />
+        <!--      <el-table-column-->
+        <!--        label="工作区域"-->
+        <!--        align="center"-->
+        <!--        prop="workareaName"-->
+        <!--      />-->
+        <el-table-column label="创建时间" align="center" prop="createTime"/>
+        <el-table-column label="更新时间" align="center" prop="updateTime"/>
+
+        <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:cabinet:edit']"
+            >编辑
+            </el-button>
+            <el-button
+              v-no-more-click
+              size="mini"
+              type="text"
+              icon="el-icon-delete"
+              @click="handleDelete(scope.row)"
+              v-hasPermi="['iscs:cabinet:remove']"
+            >删除
+            </el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+      <pagination
+        v-show="total > 0"
+        :total="total"
+        :page.sync="queryParams.pages"
+        :limit.sync="queryParams.size"
+        @pagination="getList"
+      />
+    </div>
+
     <!-- 添加或修改班组对话框 -->
     <el-dialog :visible.sync="open" width="510px" append-to-body>
       <div slot="title" class="dialog-title">
@@ -240,7 +311,7 @@ import { genCode } from '@/api/system/autocode/rule'
 export default {
   name: 'Team',
   components: {
-    Treeselect,UploadFile
+    Treeselect
   },
   dicts: ['material_status'],
   data() {
@@ -248,6 +319,7 @@ export default {
       //自动生成编码
       autoGenFlag: false,
       optType: undefined,
+      tabPosition:'first',//顶部切换
       // 遮罩层
       loading: true,
       // 选中数组
@@ -317,10 +389,8 @@ export default {
           }
         ]
       },
-
       // 表单参数
       form: {},
-
       // 表单校验
       rules: {
         cabinetCode: [
@@ -334,14 +404,38 @@ export default {
             require:true,message:'硬件名称不能为空',trigger:'blur'
           }
         ],
-        // workareaId:[
-        //   {
-        //     require:true,message:'工作区域不能为空',trigger:'blur'
-        //   }
-        // ]
-      },
 
-      workareaOptions: []
+      },
+      workareaOptions: [],
+      TicketListPage:[],//R&R岗位
+      COCOTicketListPage:[],//CCO岗位
+      scaleFactor: 1, // 缩放比例,初始值为1
+      deptXLGPosition: {
+        left: 500,
+        top: 260,
+        width: 65,
+        height: 25
+      },
+      deptCCOPosition: {
+        left: 670,
+        top: 480,
+        width: 65,
+        height: 25
+      }
+    }
+  },
+  computed:{
+    deptXLGCenter() {
+      return {
+        left: this.deptXLGPosition.left + this.deptXLGPosition.width / 2,
+        top: this.deptXLGPosition.top + this.deptXLGPosition.height / 2
+      }
+    },
+    deptCCOCenter() {
+      return {
+        left: this.deptCCOPosition.left + this.deptCCOPosition.width / 2,
+        top: this.deptCCOPosition.top + this.deptCCOPosition.height / 2
+      }
     }
   },
   created() {
@@ -359,27 +453,11 @@ export default {
             label: item.hardwareName
           }
         })
-        // console.log(response, this.hardWareList, '获取硬件信息')
+
       })
-      // listWorkarea(this.queryParams).then((response) => {
-      //   debugger;
-      //   var depts = this.handleTree(response.data.records, 'workareaId')
-      //
-      //   this.workareaOptions = depts
-      //   this.loading = false
-      // })
+
     },
-    /** 转换数据结构 */
-    // normalizer(node) {
-    //   if (node.children && !node.children.length) {
-    //     delete node.children
-    //   }
-    //   return {
-    //     id: node.workareaId,
-    //     label: node.workareaName,
-    //     children: node.children
-    //   }
-    // },
+
     /** 查询物资类型下拉树结构 */
     getTreeselect() {
       const data = {
@@ -416,8 +494,11 @@ export default {
         this.queryParams.endTime = this.formatDate(this.createTime[1])
       }
       getMaterialsCabinet(this.queryParams).then((response) => {
-        // console.log(response, "获取物资信息allList ");
         this.materialsList = response.data.records
+        console.log(response,'所有物资柜')
+        this.TicketListPage=response.data.records.filter((item) => {return item.workstationId=='8'})
+
+        this.COCOTicketListPage=response.data.records.filter((item) => {return item.workstationId=='7'})
         this.total = response.data.total
         this.machinerytypeList = this.handleTree(
           response.data.records,
@@ -428,7 +509,10 @@ export default {
         this.loading = false
       })
     },
-
+    // 物资柜跳转详情
+    handleCabinetClick(cabinet){
+      console.log(cabinet,'详情拿到的')
+    },
     // 取消按钮
     cancel() {
       this.open = false

+ 425 - 0
src/views/mes/material/replacementrecords/index.vue

@@ -0,0 +1,425 @@
+<template>
+  <div class="app-container">
+    <el-form
+      :model="queryParams"
+      ref="queryForm"
+      size="small"
+      :inline="true"
+      v-show="showSearch"
+      label-width="100px"
+    >
+      <el-form-item label="物资柜" prop="cabinetIdStr">
+        <el-select
+          style="width: 208px"
+          v-model="queryParams.cabinetIdStr"
+          placeholder="请选择物资柜"
+          multiple
+          clearable
+        >
+          <el-option
+            v-for="dict in cabinets"
+            :key="dict.value"
+            :label="dict.label"
+            :value="dict.value"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="物资类型" prop="materialsTypeId">
+        <treeselect
+          style="width: 215px"
+          v-model="queryParams.materialsTypeId"
+          :options="materialstypeOptions"
+          :normalizer="materialnormalizer"
+          placeholder="请选择物资类型"
+        />
+      </el-form-item>
+      <el-form-item label="更换人" prop="materialsCode">
+        <el-input
+          v-model="queryParams.materialsCode"
+          placeholder="请输入检查员"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="更换时间">
+        <el-date-picker
+          style="width: 215px"
+          :default-time="['00:00:00', '23:59:59']"
+          v-model="restitutionTime"
+          type="datetimerange"
+          :picker-options="pickerOptions"
+          range-separator="-"
+          start-placeholder="开始日期"
+          end-placeholder="结束日期"
+          align="right"
+        >
+        </el-date-picker>
+      </el-form-item>
+      <el-form-item label="原物资编号" prop="materialsName">
+        <el-input
+          v-model="queryParams.materialsName"
+          placeholder="请输入原物资编号"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="原RFID" prop="materialsName">
+        <el-input
+          v-model="queryParams.materialsName"
+          placeholder="请输入原物资编号"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="新物资编号" prop="materialsName">
+        <el-input
+          v-model="queryParams.materialsName"
+          placeholder="请输入原物资编号"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="新RFID" prop="materialsName">
+        <el-input
+          v-model="queryParams.materialsName"
+          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-table
+      v-loading="loading"
+      :data="materialsList"
+      @selection-change="handleSelectionChange"
+    >
+      <el-table-column type="selection" width="55" align="center"/>
+      <el-table-column label="物资柜" align="center" prop="checkName">
+      </el-table-column>
+      <el-table-column label="物资名称" align="center" prop="materialsName" />
+      <el-table-column label="物资类型" align="center" prop="materialsTypeName" />
+      <el-table-column
+        label="物资图片"
+        align="center"
+        prop="materialsTypePicture"
+      >
+        <template slot-scope="scope">
+          <img
+            v-if="scope.row.materialsTypePicture"
+            :src="scope.row.materialsTypePicture"
+            alt=""
+            style="width: 50px; height: 50px"
+          />
+          <span v-else>-</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="原物资编号" align="center" prop="materialsId">
+      </el-table-column>
+      <el-table-column label="原RFID" align="center" prop="RFID">
+      </el-table-column>
+      <el-table-column label="新物资编号" align="center" prop="materialsId">
+      </el-table-column>
+      <el-table-column label="新RFID" align="center" prop="RFID">
+      </el-table-column>
+      <el-table-column
+        label="更换人"
+        align="center"
+        prop="cron"
+      >
+      </el-table-column>
+      <el-table-column label="更换时间" align="center" prop="status">
+        <template slot-scope="scope">
+          <el-button type="text" @click="goto">查看</el-button>
+        </template>
+      </el-table-column>
+
+    </el-table>
+    <pagination
+      v-show="total > 0"
+      :total="total"
+      :page.sync="queryParams.pages"
+      :limit.sync="queryParams.size"
+      @pagination="getList"
+    />
+
+  </div>
+</template>
+
+<script>
+import {
+  listCheckTask,
+  addCheckTask,
+  getPlanPerson,
+  updateCheckTask,
+  deleteCheckTask,
+  selectCheckTaskById,
+  getIsCheckTaskCabinets
+} from '@/api/mes/material/plan'
+import { genCode } from '@/api/system/autocode/rule'
+import Crontab from '@/components/Crontab/index.vue'
+import cronstrue from 'cronstrue/i18n';
+import Treeselect from '@riophae/vue-treeselect'
+import '@riophae/vue-treeselect/dist/vue-treeselect.css'
+import { listMarsDept } from '@/api/system/marsdept'
+import { listType } from '@/api/mes/material/typeindex'
+import Template from '@/views/print/printtemplate/list.vue'
+
+export default {
+  name: 'Team',
+  components: { Template, Treeselect, Crontab },
+  dicts: ['material_status','checking_status'],
+  data() {
+    return {
+      //自动生成编码
+      autoGenFlag: false,
+      optType: undefined,
+      // 遮罩层
+      loading: true,
+      // 选中数组
+      ids: [],
+      codes: [],
+      // 非单个禁用
+      single: true,
+      // 非多个禁用
+      multiple: true,
+      // 显示搜索条件
+      showSearch: true,
+      // 总条数
+      total: 0,
+      // 班组表格数据
+      materialsList: [],
+      // mars树选项
+      marsOptions: [],
+
+      // 查询参数
+      createTime: '',
+      queryParams: {
+        pages: 1,
+        size: 10,
+        materialsCode: null,
+        materialsName: null,
+        loanState: null,
+        materialsCabinetId: null,
+        materialsTypeId: null,
+        startTime: '',
+        endTime: ''
+      },
+      // 查询参数
+      queryParamsCabinets: {
+        current: 1,
+        size: -1
+      },
+
+      // 表单参数
+      form: {},
+      cabinets: [], //物资所属柜
+      planPersonOption: [],// 检查人员
+      // 表单校验
+      rules: {
+        userIdStr: [
+          { required: true, message: '人员不能为空', trigger: 'blur' }
+        ],
+        checkName: [
+          { required: true, message: '任务名称不能为空', trigger: 'blur' }
+        ],
+        cron: [
+          { 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]);
+            },
+          },
+        ],
+      },
+      materialstypeOptions:[],
+    }
+  },
+  created() {
+    this.getList()
+    this.getTreeselect()
+    this.materialsCabinets()
+  },
+
+  methods: {
+
+    /** 查询物资信息列表 */
+    getList() {
+      this.loading = true
+      // 格式化日期并更新 queryParams
+      if (Array.isArray(this.createTime) && this.createTime.length === 2) {
+        this.queryParams.startTime = this.formatDate(this.createTime[0])
+        this.queryParams.endTime = this.formatDate(this.createTime[1])
+      }
+      listCheckTask(this.queryParams).then((response) => {
+        console.log(response, '获取物资信息allList ')
+        this.materialsList = response.data.records
+        this.total = response.data.total
+        this.machinerytypeList = this.handleTree(
+          response.data.records,
+          'materialsTypeId',
+          'parentId',
+          'children'
+        )
+        this.loading = false
+      })
+
+    },
+    /** 查询物资类型下拉树结构 */
+    getTreeselect() {
+      const data = {
+        current: 1,
+        size: -1
+      }
+      listType(data).then((response) => {
+        console.log(response,'物资类型树形结构')
+        this.materialstypeOptions = this.handleTree(
+          response.data.records,
+          'materialsTypeId',
+          'parentId',
+          'children'
+        )
+      })
+    },
+    /** 查询物资柜结构 */
+    materialsCabinets() {
+      getIsCheckTaskCabinets(this.queryParamsCabinets).then((response) => {
+        if (response?.data?.records) {
+          // 提取 cabinetId 和 cabinetName
+          this.cabinets = response.data.records.map((item) => ({
+            value: item.cabinetId,
+            label: item.cabinetName
+          }))
+        }
+        // 岗位查询
+        const data1 = {
+          pasge: 1,
+          size: -1
+        }
+        listMarsDept(data1).then((response) => {
+          this.marsOptions = this.handleTree(response.data.records,"workstationId","parentId")
+        })
+      })
+      // 巡检人员
+      const data = {
+        pageNum: 1,
+        pageSize: 99999
+      }
+      getPlanPerson(data).then((res) => {
+        console.log(res, '巡检人员信息')
+        this.planPersonOption = res.rows.map((item) => {
+          return {
+            label: item.nickName,
+            value: item.userId
+          }
+        })
+      })
+    },
+    /** 查询岗位下拉树结构 */
+    normalizer(node) {
+      if (node.children && !node.children.length) {
+        delete node.children
+      }
+      return {
+        id: node.workstationId,
+        label: node.workstationName,
+        children: node.children
+      }
+    },
+    /** 查询物资类型下拉树结构 */
+    materialnormalizer(node) {
+      if (node.children && !node.children.length) {
+        delete node.children
+      }
+      return {
+        id: node.materialsTypeId,
+        label: node.materialsTypeName,
+        children: node.children
+      }
+    },
+
+    // 表单重置
+    reset() {
+      this.form = {
+        cron: undefined
+      }
+      this.resetForm('form')
+      this.autoGenFlag = false
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.pages = 1
+      this.getList()
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.resetForm('queryForm')
+      this.handleQuery()
+    },
+    // 多选框选中数据
+    handleSelectionChange(selection) {
+      this.ids = selection.map((item) => item.checkId)
+      this.single = selection.length !== 1
+      this.multiple = !selection.length
+    },
+
+
+
+
+  }
+}
+</script>
+<style lang="scss" src="@/assets/styles/dialog-title.scss" scoped>
+.el-input-width {
+  width: 380px !important;
+
+}
+</style>

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

@@ -6,6 +6,7 @@
           v-model="queryParams.unitId"
           placeholder="请输入单位名称"
           clearable
+          oninput="value=value.replace(/[^\d.]/g,'')"
           @keyup.enter.native="handleQuery"
         />
       </el-form-item>