仓管平面图(自定义布局)

不理解的请备注

效果图:

视频不太清楚

1、安装vue-grid-layout

npm install vue-grid-layout --save

2、安装splitPane

npm install vue - splitpane --save

3、代码块分布

4、PositionsList代码

<!-- 文件管理 -->
<template>
  <a-card>
    <a-row type="flex" justify="center">
      <a-col :span="3" :order="1">
        <a-form-item label="长:" :labelCol="{ span: 7 }" :wrapperCol="{ span: 17 }">
          <span
            ><a-input type="number" @change="getLong" :disabled="disabled" v-model="form.longs" placeholder="请输入"
          /></span>
        </a-form-item>
      </a-col>
      <a-col :span="3" :order="2">
        <a-form-item label="宽:" :labelCol="{ span: 7 }" :wrapperCol="{ span: 17 }">
          <span
            ><a-input type="number" :disabled="disabled" @change="getLong" v-model="form.wides" placeholder="请输入"
          /></span>
        </a-form-item>
      </a-col>
      <a-col :span="3" :order="2">
        <a-form-item label="高:" :labelCol="{ span: 7 }" :wrapperCol="{ span: 17 }">
          <span><a-input type="number" @change="getLong" v-model="form.heigts" placeholder="请输入"/></span>
        </a-form-item>
      </a-col>
      <a-col :span="3" :order="4">
        <a-form-item label="层数:" :labelCol="{ span: 7 }" :wrapperCol="{ span: 17 }">
          <span><a-input placeholder="请输入"/></span>
        </a-form-item>
      </a-col>
      <a-col :span="3" :order="5">
        <a-form-item label="行数:" :labelCol="{ span: 7 }" :wrapperCol="{ span: 17 }">
          <span><a-input placeholder="请输入"/></span>
        </a-form-item>
      </a-col>
      <a-col :span="4" :order="6">
        <a-form-item label="缩放大小:" :labelCol="{ span: 7 }" :wrapperCol="{ span: 17 }" class="flexble">
          <a-slider id="test" v-model="scaleRadios" :default-value="scaleRadios" @change="getZoom" />
        </a-form-item>
      </a-col>
      <a-col :span="4" :order="7" style="margin-left:30px">
        <a-space style="margin-top:5px">
          <a-button type="primary" @click="generate" v-if="!disabled" :disabled="disabled">生成仓位图</a-button>
          <a-button type="primary" @click="getreset" v-else>重置</a-button>
          <a-button type="primary">生成区位图</a-button>
        </a-space>
      </a-col>
    </a-row>
    <!-- 仓位图 -->
    <positchart ref="positForm" :scaleRadio="scaleRadio" :round="form" />
  </a-card>
</template>

<script>
import positchart from '@views/erp/housing/modules/positchart'
export default {
  components: {
    positchart
  },
  name: 'PositionsList',
  data() {
    return {
      form: {
        long: 13,
        longs: 13,
        wide: 10,
        wides: 10,
        heigt: 50,
        heigts: 50
      },
      disabled: false,
      scaleRadios: 100,
      scaleRadio: 1
    }
  },
  methods: {
    generate() {
      let that = this
      that.disabled = true
      that.$refs.positForm.handl()
    },
    getLong() {
      this.form.long = this.form.longs - 0
      this.form.wide = this.form.wides - 0
      this.form.heigt = this.form.heigts - 0
    },
    getreset() {
      let that = this
      that.disabled = false
      that.form = {
        long: 13,
        longs: 13,
        wide: 10,
        wides: 10,
        heigt: 50,
        heigts: 50
      }
      that.$refs.positForm.handfe()
    },
    getZoom() {
      this.scaleRadio = this.scaleRadios / 100 - 0
    }
  }
}
</script>
<style></style>

6、positchart代码块

<template>
  <div v-if="layeshow" class="box">
    <splitPane
      :max-percent="100"
      :default-percent="defaultPercentOne"
      :min-percent="11"
      split="vertical"
      class="splitpanes__pane"
      style="height: 650px;"
    >
      <template slot="paneL">
        <!-- <button @click="fullScreenAndExit()">全屏和退出</button> -->
        <lb-card title="操作区" size="default" style="padding:0px;margin:0px;height:650px;">
          <div @drag="drag" @dragend="dragend('operate')" class="operate" draggable="true" unselectable="on">
            操作
          </div>
          <div @drag="drag" @dragend="dragend('workbench')" class="workbench" draggable="true" unselectable="on">
            工作台
          </div>
          <div @drag="drag" @dragend="dragend('Shelves')" class="Shelves" draggable="true" unselectable="on">
            货架
          </div>
          <div @drag="drag" @dragend="dragend('passage')" class="passage" draggable="true" unselectable="on">
            通道
          </div>
        </lb-card>
      </template>
      <template slot="paneR">
        <div class="penclass">
          <a-icon type="bug" style="color:#fff;font-size: 10px;" />
        </div>
        <split-pane :max-percent="100" :default-percent="defaultPercentwe" :min-percent="10" split="vertical">
          <template slot="paneL">
            <lb-card title="显示区" size="default" style="padding:0px;margin:0px;height: 650px;">
              <div id="content" class="layoutBox" :style="`zoom:${scaleRadio ? scaleRadio : 1}`">
                <grid-layout
                  ref="gridlayout"
                  :layout.sync="layout"
                  :col-num="round.long"
                  :row-height="round.heigt"
                  :responsive="false"
                  :vertical-compact="false"
                  :prevent-collision="true"
                  :use-css-transforms="true"
                  :is-draggable="true"
                  :is-resizable="true"
                  class="grid_cals"
                >
                  <!-- 背景框 -->
                  <myGridItemPreview :itemData="backgroundData" />
                  <grid-item
                    :key="item.i"
                    v-for="item in layout"
                    :x="item.x"
                    :y="item.y"
                    :w="item.w"
                    :h="item.h"
                    :i="item.i"
                    :style="{ background: getColor(item.text) }"
                  >
                    <div class="clmodule" @click="getEdit(item)">
                      <span>{{ item.text }}</span>
                    </div>
                  </grid-item>
                </grid-layout>
              </div>
            </lb-card>
          </template>
          <template slot="paneR">
            <div class="penclass">
              <a-icon type="bug" style="color:#fff;font-size: 10px;" />
            </div>
            <div style="margin-top: -5px;">
              <a-tabs type="card" @change="callback" size="small">
                <a-tab-pane v-for="item in tabPane" :key="item.key" :tab="item.title">
                  <positdation ref="dationForm" :jectDation="jectDation" v-if="showpane == 1" />
                  <positgoods v-if="showpane == 2" />
                  <positshelves v-if="showpane == 3" />
                </a-tab-pane>
              </a-tabs>
            </div>
          </template>
        </split-pane>
      </template>
    </splitPane>
  </div>
</template>
<script>
import VueDragResize from 'vue-drag-resize'
import { GridLayout, GridItem } from 'vue-grid-layout'
import splitPane from 'vue-splitpane'
import LbCard from '@views/Acom/LbCard'
// 基础信息
import positdation from '@views/erp/housing/modals/positdation'
// 货品
import positgoods from '@views/erp/housing/modals/positgoods'
// 货架信息
import positshelves from '@views/erp/housing/modals/positshelves'
import uuid from 'uuid'
let mouseXY = { x: null, y: null }
let DragPos = { x: null, y: null, w: 1, h: 1, i: null }
import myGridItemPreview from '@views/erp/housing/modules/itemPreview'
export default {
  components: {
    GridLayout,
    GridItem,
    myGridItemPreview,
    splitPane,
    LbCard,
    positgoods,
    VueDragResize,
    positdation,
    positshelves
  },
  props: {
    round: {
      type: Object,
      required: true
    },
    scaleRadio: {
      type: Number
    }
  },
  data() {
    return {
      // tabs
      jectDation: {},
      tabPane: [
        {
          title: '基础信息',
          key: 1
        },
        {
          title: '货品信息',
          key: 2
        },
        {
          title: '货架详情',
          key: 3
        }
      ],
      showpane: 0,
      layout: [
        {
          x: 0,
          y: 0,
          w: 1,
          h: 2,
          i: '0',
          id: '0',
          text: '货架',
          name: '0-001',
          warehouse: '1层',
          client: '云数联客户',
          type: '货架',
          attribute: '塔型货架',
          MaxLength: 2,
          width: 1
        }
      ],
      backgroundData: [],
      defaultPercentOne: 11,
      layeshow: false,
      defaultPercentwe: 80
    }
  },
  beforeCreate() {
    // 屏幕高度
    this.screenHeight = document.documentElement.clientHeight
  },
  mounted() {
    document.addEventListener(
      'dragover',
      function(e) {
        mouseXY.x = e.clientX
        mouseXY.y = e.clientY
      },
      false
    )
  },
  beforeDestroy() {},
  methods: {
    // tabs
    callback(key) {
      let that = this
      that.showpane = key
    },
    // 显示
    handl() {
      let that = this
      this.initPreviewData()
      that.layeshow = true
      console.log(this.round)
    },
    // 隐藏
    handfe() {
      let that = this
      that.layeshow = false
    },
    initPreviewData() {
      this.backgroundData = []
      for (let i = 0; i < this.round.long; i++) {
        for (let j = 0; j < this.round.wide; j++) {
          this.backgroundData.push({
            x: i,
            y: j,
            w: 1,
            h: 1,
            i: uuid // 防止 key 重复
          })
        }
      }
    },
    getEdit(item) {
      console.log(item)
      let that = this
      that.showpane = 1
      that.jectDation = item
    },
    drag(e) {
      let parentRect = document.getElementById('content').getBoundingClientRect()
      let mouseInGrid = false
      if (
        mouseXY.x > parentRect.left &&
        mouseXY.x < parentRect.right &&
        mouseXY.y > parentRect.top &&
        mouseXY.y < parentRect.bottom
      ) {
        mouseInGrid = true
      }
      if (mouseInGrid === true && this.layout.findIndex(item => item.i === 'drop') === -1) {
        this.layout.push({
          x: (this.layout.length * 2) % (this.colNum || this.round.long),
          y: this.layout.length + (this.colNum || this.round.long), // puts it at the bottom
          w: 1,
          h: 1,
          i: 'drop'
        })
      }
      let index = this.layout.findIndex(item => item.i === 'drop')
      if (index !== -1) {
        try {
          // this.$refs.gridlayout.$children[this.layout.length].$refs.item.style.display = 'none'
        } catch {}
        let el = this.$refs.gridlayout.$children[index]
        el.dragging = { top: mouseXY.y - parentRect.top, left: mouseXY.x - parentRect.left }
        let new_pos = el.calcXY(mouseXY.y - parentRect.top, mouseXY.x - parentRect.left)
        if (mouseInGrid === true) {
          this.$refs.gridlayout.dragEvent('dragstart', 'drop', new_pos.x, new_pos.y, 1, 1)
          DragPos.i = String(index)
          DragPos.x = this.layout[index].x
          DragPos.y = this.layout[index].y
        }
        if (mouseInGrid === false) {
          this.$refs.gridlayout.dragEvent('dragend', 'drop', new_pos.x, new_pos.y, 1, 1)
          this.layout = this.layout.filter(obj => obj.i !== 'drop')
        }
      }
    },
    dragend(text) {
      let obj = {}
      if (text == 'operate') {
        obj.text = '操作'
        obj.h = 1
      }
      if (text == 'workbench') {
        obj.text = '工作台'
        obj.h = 1
      }
      if (text == 'Shelves') {
        obj.text = '货架'
        obj.h = 2
      }
      if (text == 'passage') {
        obj.text = '通道'
        obj.h = 3
      }
      let parentRect = document.getElementById('content').getBoundingClientRect()
      let mouseInGrid = false
      if (
        mouseXY.x > parentRect.left &&
        mouseXY.x < parentRect.right &&
        mouseXY.y > parentRect.top &&
        mouseXY.y < parentRect.bottom
      ) {
        mouseInGrid = true
      }
      if (mouseInGrid === true) {
        this.layout = this.layout.filter(obj => obj.i !== 'drop')
        this.layout.push({
          x: DragPos.x,
          y: DragPos.y,
          w: 1,
          h: obj.h,
          i: DragPos.i,
          moved: true,
          text: obj.text,
          type: obj.text,
          name: obj.h + DragPos.i,
          id: '0-' + obj.h + DragPos.i,
          warehouse: '1层',
          client: '云数联客户',
          attribute: '塔型货架',
          MaxLength: obj.h,
          width: 1
        })
        console.log(this.layout)
        try {
          this.$refs.gridLayout.$children[this.layout.length].$refs.item.style.display = 'block'
        } catch {}
      }
    },
    closeItemHandle(item) {
      // 预览与正式数据公用一个 item 因此,需两者都清除数据
      this.layout.splice(this.layout.findIndex(i => i.i == item.i))
      this.backgroundData.splice(this.backgroundData.findIndex(i => i.i == item.i))
    },
    // 颜色
    getColor(text) {
      let color = ''
      if (text == '操作') color = 'green'
      if (text == '工作台') color = 'red'
      if (text == '货架') color = 'blue'
      if (text == '通道') color = 'orange'
      return color
    },
    // 全屏
    // 点击事件
    fullScreenAndExit() {
      const el = document.querySelector('.box')
      this.toggleFullScreen(el)
    },
    /**
     * 切换全屏
     * @param {HTMLElement} element dom元素
     */
    toggleFullScreen(element) {
      if (!this.isFullScreen) {
        this.fullScreen(element)
      } else {
        this.exitFullScreen()
      }
      this.isFullScreen = !this.isFullScreen
    },
    /**
     * 全屏
     * @param {HTMLElement} element dom元素
     */
    fullScreen(element) {
      const requestMethod =
        element.requestFullScreen ||
        element.webkitRequestFullScreen ||
        element.mozRequestFullScreen ||
        element.msRequestFullScreen

      if (requestMethod) {
        requestMethod.call(element)
      }
      if (typeof window.ActiveXObject !== 'undefined') {
        let wscript = new ActiveXObject('WScript.Shell')
        if (wscript !== null) {
          wscript.SendKeys('{F11}')
        }
      }
    },
    /**
     * 退出全屏
     */
    exitFullScreen() {
      const documentElement = document
      const cfs =
        documentElement.cancelFullScreen ||
        documentElement.webkitCancelFullScreen ||
        documentElement.mozCancelFullScreen ||
        documentElement.exitFullScreen

      if (cfs) {
        cfs.call(documentElement)
      } else if (typeof window.ActiveXObject !== 'undefined') {
        // for IE,这里和fullScreen相同,模拟按下F11键退出全屏
        const wscript = new ActiveXObject('WScript.Shell')
        if (wscript != null) {
          wscript.SendKeys('{F11}')
        }
      }
    }
  }
}
</script>

<style lang="less" scoped>
.penclass {
  position: absolute;
  background: blue;
  top: 40%;
  left: -5px;
  width: 10px;
  height: 45px;
  display: flex;
  justify-content: center;
  align-self: center;
  align-items: center;
  border-radius: 10px;
}
// 操作区
.operate {
  height: 60px;
  background: green;
  margin: 10px 0;
  padding: 10px;
  display: flex;
  justify-content: center;
  align-items: center;
  color: #fff;
}
// 货架版
.Shelves {
  height: 120px;
  background: blue;
  margin: 10px 0;
  padding: 10px;
  display: flex;
  justify-content: center;
  align-items: center;
  color: #fff;
}
// 工作台
.workbench {
  height: 60px;
  background: red;
  margin: 10px 0;
  padding: 10px;
  display: flex;
  justify-content: center;
  align-items: center;
  color: #fff;
}
// 通道版
.passage {
  height: 180px;
  background: orange;
  margin: 10px 0;
  padding: 10px;
  display: flex;
  justify-content: center;
  align-items: center;
  color: #fff;
}
.clmodule {
  display: flex;
  justify-content: center;
  align-items: center;
  align-self: center;
  height: 100%;
  color: #fff;
}
.vue-grid-item .no-drag {
  height: 100%;
  width: 100%;
}
.vue-grid-item .minMax {
  font-size: 12px;
}
.vue-grid-item .add {
  cursor: pointer;
}

.layoutBox {
  width: 100%;
  height: 100%;
}
// .grid_cals {
//   width: 100%;
//   overflow-x: auto;
//   display: -webkit-box;
//   -webkit-overflow-scrolling: touch;
//   min-height: 600px;
// }
// .grid_cals::-webkit-scrollbar {
//   display: none;
// }
</style>

7、itemPreview代码块

<template>
  <div>
    <grid-item
      v-for="item in itemData"
      :x="item.x"
      :y="item.y"
      :w="item.w"
      :h="item.h"
      :i="item.i"
      :key="item.i"
      :is-draggable="false"
      :is-resizable="false"
      class="grid-item"
    />
  </div>
</template>

<script>
import { GridItem } from 'vue-grid-layout'
export default {
  name: 'VueLayoutItem',

  props: ['itemData'],

  components: { GridItem }
}
</script>

<style lang="less" scoped>
.grid-item {
  // border-top: 2px solid rgba(1, 153, 209, 0.5);
  border: #999 dashed 1px;
  display: flex;
  justify-content: center;
  align-items: center;
  color: #fff;
}
</style>

8、positdation代码块

<!-- 基础信息 -->
<template>
  <div>
    <span v-if="Object.keys(parent).length == 0">
      <a-empty
        image="https://gw.alipayobjects.com/mdn/miniapp_social/afts/img/A*pevERLJC9v0AAAAAAAAAAABjAQAAAQ/original"
      />
    </span>
    <a-row v-else>
      <a-col :span="24">
        <a-form-model-item label="库位编号:" :labelCol="{ span: 6 }" :wrapperCol="{ span: 15 }">
          <a-input placeholder="" v-model="parent.name" />
        </a-form-model-item>
      </a-col>
      <a-col :span="24">
        <a-form-model-item label="所在仓库:" :labelCol="{ span: 6 }" :wrapperCol="{ span: 15 }">
          <a-input placeholder="" v-model="parent.warehouse" />
        </a-form-model-item>
      </a-col>
      <a-col :span="24">
        <a-form-model-item label="所属客户:" :labelCol="{ span: 6 }" :wrapperCol="{ span: 15 }">
          <a-input placeholder="" v-model="parent.client" />
        </a-form-model-item>
      </a-col>
      <a-col :span="24">
        <a-form-model-item label="库位类型:" :labelCol="{ span: 6 }" :wrapperCol="{ span: 15 }">
          <a-input placeholder="" v-model="parent.type" />
        </a-form-model-item>
      </a-col>
      <a-col :span="24">
        <a-form-model-item label="库位属性:" :labelCol="{ span: 6 }" :wrapperCol="{ span: 15 }">
          <a-input placeholder="" v-model="parent.attribute" />
        </a-form-model-item>
      </a-col>
      <a-col :span="24">
        <a-form-model-item label="最大长度:" :labelCol="{ span: 6 }" :wrapperCol="{ span: 15 }">
          <a-input placeholder="" v-model="parent.MaxLength" />
        </a-form-model-item>
      </a-col>
      <a-col :span="24">
        <a-form-model-item label="最大宽度:" :labelCol="{ span: 6 }" :wrapperCol="{ span: 15 }">
          <a-input placeholder="" v-model="parent.width" />
        </a-form-model-item>
      </a-col>
      <a-col :span="12" style="margin-top: 50px;">
        <span style="display: flex;justify-content: center;"><a-button type="primary">修改</a-button></span>
      </a-col>
      <a-col :span="12" style="margin-top: 50px;">
        <span style="display: flex;justify-content: center;"><a-button type="primary">确定</a-button></span>
      </a-col>
    </a-row>
  </div>
</template>
<script>
export default {
  name: 'positdation',
  data() {
    return {
      parent: {}
    }
  },
  props: {
    jectDation: {
      type: Object,
      required: true
    }
  },
  watch: {
    jectDation: {
      immediate: true,
      handler(val) {
        let that = this
        that.parent = val
      }
    }
  },
  methods: {
    // 传递过来的参数
    getDation(item) {
      let that = this
      that.parent = {}
      that.parent = item
    }
  }
}
</script>
<style lang="less" scoped></style>

9、positgoods和positshelves为空文件

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

My&Liu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值