|
|
@@ -0,0 +1,385 @@
|
|
|
+<template>
|
|
|
+ <div class="mapBox">
|
|
|
+ <div style="width:400px;height: 350px;border: 1px solid black;margin: 10px;position: absolute;z-index: 1;top:0">
|
|
|
+ <h3 style="padding-left: 10px">操作流程:</h3>
|
|
|
+ <div style="display: flex;padding-left: 10px">
|
|
|
+ <h4>1.选择物资柜</h4>
|
|
|
+ <el-select
|
|
|
+ style="width: 215px;margin: 10px 20px;"
|
|
|
+ v-model="queryParams.materialsCabinetId"
|
|
|
+ placeholder="请选择物资柜"
|
|
|
+ @change="handleCabinetChange"
|
|
|
+ >
|
|
|
+ <el-option
|
|
|
+ v-for="dict in cabinets"
|
|
|
+ :key="dict.value"
|
|
|
+ :label="dict.label"
|
|
|
+ :value="dict.value"
|
|
|
+ />
|
|
|
+ </el-select>
|
|
|
+ </div>
|
|
|
+ <div style="display: flex;padding-left: 10px">
|
|
|
+ <h4>2.</h4>
|
|
|
+ <el-button @click="changeDoor(true)" style="width:60px;height:30px;padding:5px 8px;margin: 12px 10px">开柜门</el-button>
|
|
|
+ </div>
|
|
|
+ <div style="display: flex;padding-left: 10px">
|
|
|
+ <h4>3.取物资/还物资</h4>
|
|
|
+<!-- <el-input v-model="inputStatus" style="width:150px"></el-input>-->
|
|
|
+ </div>
|
|
|
+ <div style="display: flex;padding-left: 10px">
|
|
|
+ <h4>4.</h4>
|
|
|
+ <el-button :disabled="!doorOpen" @click="changeDoor(false)" style="width:60px;height:30px;padding:5px 8px;margin: 12px 10px">关柜门</el-button>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ </div>
|
|
|
+ <div id="container" ref="container" style="width: 260vh; height: 90vh; background-color: white;"></div>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+import Konva from "konva";
|
|
|
+import {
|
|
|
+ getIsMaterialsCabinets,
|
|
|
+ listMaterials,
|
|
|
+ selectMaterialsById,
|
|
|
+ updateIsMaterialById
|
|
|
+} from '@/api/mes/material/information'
|
|
|
+
|
|
|
+export default {
|
|
|
+ name: 'Lending',
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ stage: null,
|
|
|
+ layer: null,
|
|
|
+ bgLayer: null,
|
|
|
+ list: [], // 三号柜子的物资
|
|
|
+ listInCabinet: [], // 存储物资柜内的物资
|
|
|
+ listOutOfCabinet: [], // 存储物资柜外的物资
|
|
|
+ cabinets: [], // 物资所属柜
|
|
|
+ doorOpen:false,
|
|
|
+ queryParams: {
|
|
|
+ current: 1,
|
|
|
+ size: -1,
|
|
|
+ materialsCabinetId: null,
|
|
|
+ loanState:null
|
|
|
+ },
|
|
|
+ inputStatus:'当前柜门已关闭',//柜门开关状态
|
|
|
+ materialElements: [], // 存储物资图标对象
|
|
|
+ materialsToUpdate: [], // 存储需要更新的物资
|
|
|
+ };
|
|
|
+ },
|
|
|
+ mounted() {
|
|
|
+ this.$nextTick(() => {
|
|
|
+ this.initKonva();
|
|
|
+ this.inputStatus='当前柜门已关闭'
|
|
|
+ this.materialsCabinets()
|
|
|
+ });
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ changeDoor(value){
|
|
|
+ this.doorOpen = value;
|
|
|
+ if(this.doorOpen){
|
|
|
+ this.$message.success('柜门已打开')
|
|
|
+ this.updateDraggableStatus()
|
|
|
+ this.inputStatus="当前柜门已打开"
|
|
|
+ }else {
|
|
|
+ this.$message.info('柜门已关闭')
|
|
|
+ this.inputStatus="当前柜门已关闭"
|
|
|
+ this.updateMaterialsBatch(); // 柜门关闭时调用批量更新接口
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 获取物资柜信息
|
|
|
+ materialsCabinets() {
|
|
|
+ getIsMaterialsCabinets(this.queryParams).then((response) => {
|
|
|
+ if (response?.data?.records) {
|
|
|
+ this.cabinets = response.data.records.map((item) => ({
|
|
|
+ value: item.cabinetId,
|
|
|
+ label: item.cabinetName
|
|
|
+ }));
|
|
|
+ }
|
|
|
+ });
|
|
|
+ },
|
|
|
+ handleCabinetChange() {
|
|
|
+ // 清空之前渲染的物资元素
|
|
|
+ this.clearMaterialsFromLayer();
|
|
|
+
|
|
|
+ // 获取柜内和柜外物资
|
|
|
+ Promise.all([this.getMaterialsInCabinet(), this.getMaterialsOutOfCabinet()])
|
|
|
+ .then(() => {
|
|
|
+ // 在所有数据获取完成后,统一渲染物资
|
|
|
+ this.addMaterialsToLayer();
|
|
|
+ });
|
|
|
+ },
|
|
|
+
|
|
|
+ getMaterialsInCabinet() {
|
|
|
+ this.queryParams.loanState = '1'; // 设置查询条件为物资柜内
|
|
|
+ return listMaterials(this.queryParams).then((res) => {
|
|
|
+ this.listInCabinet = res.data.records;
|
|
|
+ });
|
|
|
+ },
|
|
|
+
|
|
|
+ getMaterialsOutOfCabinet() {
|
|
|
+ this.queryParams.loanState = '0'; // 设置查询条件为物资柜外
|
|
|
+ const data={
|
|
|
+ current: 1,
|
|
|
+ size: -1,
|
|
|
+ loanState: '0',
|
|
|
+ }
|
|
|
+ return listMaterials(data).then((res) => {
|
|
|
+ this.listOutOfCabinet = res.data.records;
|
|
|
+ });
|
|
|
+ },
|
|
|
+ // 初始化Konva舞台
|
|
|
+ initKonva() {
|
|
|
+ this.stage = new Konva.Stage({
|
|
|
+ container: this.$refs.container,
|
|
|
+ width: 1600,
|
|
|
+ height: 1000,
|
|
|
+ });
|
|
|
+
|
|
|
+ this.bgLayer = new Konva.Layer();
|
|
|
+ const bgImage = new Image();
|
|
|
+ bgImage.src = require('@/assets/images/table.png');
|
|
|
+ bgImage.onload = () => {
|
|
|
+ const konvaImage = new Konva.Image({
|
|
|
+ x: 600,
|
|
|
+ y: 25,
|
|
|
+ image: bgImage,
|
|
|
+ width: 500,
|
|
|
+ height: 700,
|
|
|
+ draggable: false,
|
|
|
+ });
|
|
|
+ this.bgLayer.add(konvaImage);
|
|
|
+ this.bgLayer.draw();
|
|
|
+ };
|
|
|
+ this.stage.add(this.bgLayer);
|
|
|
+ },
|
|
|
+
|
|
|
+ // 清除Konva图层中的所有物资元素
|
|
|
+ clearMaterialsFromLayer() {
|
|
|
+ if (!this.bgLayer) return;
|
|
|
+ const materialNodes = this.bgLayer.find('.material');
|
|
|
+ console.log('清除物资:', materialNodes);
|
|
|
+ materialNodes.forEach(node => node.destroy()); // 清除已渲染的物资元素
|
|
|
+ this.materialElements = []; // 清空已存储的物资图标对象
|
|
|
+ this.bgLayer.draw(); // 重新绘制图层
|
|
|
+ },
|
|
|
+
|
|
|
+ // 物资拖动结束时的处理
|
|
|
+ handleDragEnd(e) {
|
|
|
+ const materialId = e.target.getAttr('materialId'); // 获取物资ID
|
|
|
+ const position = e.target.getClientRect(); // 获取物资当前的位置信息
|
|
|
+ const material = e.target.getAttr('material'); // 获取物资对象
|
|
|
+console.log(material,'物资移动');
|
|
|
+ const isInCabinet = material.inCabinet; // 物资是否在柜子内
|
|
|
+
|
|
|
+ selectMaterialsById(material.materialsId).then((res) => {
|
|
|
+ console.log(res, '一大啊啊啊是');
|
|
|
+ const originalCabinetId = res.data.materialsCabinetId;//原来的柜子ID
|
|
|
+ const currentCabinetId = this.queryParams.materialsCabinetId; // 归还目标柜子ID
|
|
|
+ console.log(originalCabinetId,currentCabinetId, 'originalCabinetId');
|
|
|
+
|
|
|
+ if (!currentCabinetId || position.x < 600 || position.x > 1100 || position.y < 25 || position.y > 725) {
|
|
|
+ // **物资移出柜子**
|
|
|
+ if (isInCabinet) {
|
|
|
+ console.log('1--------')
|
|
|
+ this.materialsToUpdate.push({
|
|
|
+ materialsId: materialId,
|
|
|
+ loanState: 0, // "借出"
|
|
|
+ loanUserId: 106
|
|
|
+ });
|
|
|
+ material.inCabinet = false; // 更新状态
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // **物资归还到柜子**
|
|
|
+ if (!isInCabinet&&originalCabinetId === currentCabinetId) {
|
|
|
+ console.log('2--------')
|
|
|
+ // **物资从外部归还**
|
|
|
+ this.materialsToUpdate.push({
|
|
|
+ materialsId: materialId,
|
|
|
+ loanState: 1, // "归还"
|
|
|
+ restitutionToId: currentCabinetId,
|
|
|
+ restitutionUserId: 106
|
|
|
+ });
|
|
|
+ material.inCabinet = true;
|
|
|
+ material.materialsCabinetId = currentCabinetId; // 更新物资的柜子ID
|
|
|
+ } else if (originalCabinetId !== currentCabinetId) {
|
|
|
+ console.log('3--------')
|
|
|
+ // **物资从柜子 A 归还到柜子 B,需要确认**
|
|
|
+ // 查找柜子名称
|
|
|
+ const originalCabinetName = this.cabinets.find(cabinet => cabinet.value === originalCabinetId)?.label || '未知柜子';
|
|
|
+ const currentCabinetName = this.cabinets.find(cabinet => cabinet.value === currentCabinetId)?.label || '未知柜子';
|
|
|
+ this.$confirm(
|
|
|
+ `物资原本属于 ${originalCabinetName},确定要归还到 ${currentCabinetName} 吗?`,
|
|
|
+ '确认归还',
|
|
|
+ {
|
|
|
+ confirmButtonText: '确定',
|
|
|
+ cancelButtonText: '取消',
|
|
|
+ type: 'warning'
|
|
|
+ }
|
|
|
+ ).then(() => {
|
|
|
+ // **用户确认变更柜子**
|
|
|
+ this.materialsToUpdate.push({
|
|
|
+ materialsId: materialId,
|
|
|
+ loanState: 1,
|
|
|
+ restitutionToId: currentCabinetId,
|
|
|
+ restitutionUserId: 106
|
|
|
+ });
|
|
|
+ material.materialsCabinetId = currentCabinetId; // 更新柜子ID
|
|
|
+ this.bgLayer.draw();
|
|
|
+ }).catch(() => {
|
|
|
+ // **用户取消,还原到原位置**
|
|
|
+ e.target.position({ x: 1200, y: 120 });
|
|
|
+ this.bgLayer.draw();
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ // **物资仍在同一个柜子内**
|
|
|
+ console.log('物资仍在同一个柜子内');
|
|
|
+ // 如果需要,可以在这里添加一些逻辑
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }).catch((error) => {
|
|
|
+ console.error('获取物资信息失败:', error);
|
|
|
+ // 处理错误情况
|
|
|
+ });
|
|
|
+ },
|
|
|
+
|
|
|
+
|
|
|
+ // 将物资添加到Konva图层
|
|
|
+ addMaterialsToLayer() {
|
|
|
+ if (!this.bgLayer) return;
|
|
|
+
|
|
|
+ const itemWidth = 60;
|
|
|
+ const itemHeight = 60;
|
|
|
+ const spacing = 40;
|
|
|
+
|
|
|
+ // 清除之前的物资元素
|
|
|
+ this.clearMaterialsFromLayer();
|
|
|
+
|
|
|
+ // 渲染柜内物资
|
|
|
+ this.listInCabinet.forEach((material, index) => {
|
|
|
+ const x = 720 + (index % 3) * (itemWidth + spacing);
|
|
|
+ const y = 120 + Math.floor(index / 3) * (itemHeight + spacing);
|
|
|
+
|
|
|
+ const materialImage = new Image();
|
|
|
+ materialImage.src = material.materialsTypeIcon;
|
|
|
+ materialImage.onload = () => {
|
|
|
+ const group = new Konva.Group({
|
|
|
+ x: x,
|
|
|
+ y: y,
|
|
|
+ draggable: this.doorOpen, // 初始时根据 doorOpen 状态设置可拖拽
|
|
|
+ name: 'material',
|
|
|
+ materialId: material.materialsId,
|
|
|
+ material: material,
|
|
|
+ });
|
|
|
+
|
|
|
+ const konvaMaterialImage = new Konva.Image({
|
|
|
+ image: materialImage,
|
|
|
+ width: itemWidth,
|
|
|
+ height: itemHeight,
|
|
|
+ });
|
|
|
+
|
|
|
+ const text = new Konva.Text({
|
|
|
+ x: 0,
|
|
|
+ y: itemHeight + 5,
|
|
|
+ text: material.materialsName,
|
|
|
+ fontSize: 12,
|
|
|
+ fill: 'black',
|
|
|
+ align: 'center',
|
|
|
+ width: itemWidth,
|
|
|
+ });
|
|
|
+
|
|
|
+ group.add(konvaMaterialImage);
|
|
|
+ group.add(text);
|
|
|
+
|
|
|
+ // 给物资设置初始的柜内状态
|
|
|
+ material.inCabinet = true; // 设置物资最初处于柜子内
|
|
|
+
|
|
|
+ group.on('dragend', this.handleDragEnd); // 添加dragend事件监听
|
|
|
+
|
|
|
+ this.bgLayer.add(group);
|
|
|
+ this.bgLayer.draw();
|
|
|
+ this.materialElements.push(group);
|
|
|
+ };
|
|
|
+ });
|
|
|
+
|
|
|
+ // 渲染柜外物资
|
|
|
+ this.listOutOfCabinet.forEach((material, index) => {
|
|
|
+ const x = 1200 + (index % 3) * (itemWidth + spacing); // 左侧显示柜外物资
|
|
|
+ const y = 120 + Math.floor(index / 3) * (itemHeight + spacing);
|
|
|
+
|
|
|
+ const materialImage = new Image();
|
|
|
+ materialImage.src = material.materialsTypeIcon;
|
|
|
+ materialImage.onload = () => {
|
|
|
+ const group = new Konva.Group({
|
|
|
+ x: x,
|
|
|
+ y: y,
|
|
|
+ draggable: this.doorOpen, // 初始时设为可拖拽
|
|
|
+ name: 'material',
|
|
|
+ materialId: material.materialsId,
|
|
|
+ material: material,
|
|
|
+ });
|
|
|
+
|
|
|
+ const konvaMaterialImage = new Konva.Image({
|
|
|
+ image: materialImage,
|
|
|
+ width: itemWidth,
|
|
|
+ height: itemHeight,
|
|
|
+ });
|
|
|
+
|
|
|
+ const text = new Konva.Text({
|
|
|
+ x: 0,
|
|
|
+ y: itemHeight + 5,
|
|
|
+ text: material.materialsName,
|
|
|
+ fontSize: 12,
|
|
|
+ fill: 'black',
|
|
|
+ align: 'center',
|
|
|
+ width: itemWidth,
|
|
|
+ });
|
|
|
+
|
|
|
+ group.add(konvaMaterialImage);
|
|
|
+ group.add(text);
|
|
|
+
|
|
|
+ // 给物资设置初始的柜外状态
|
|
|
+ material.inCabinet = false; // 设置物资最初处于柜子外
|
|
|
+
|
|
|
+ group.on('dragend', this.handleDragEnd); // 添加dragend事件监听
|
|
|
+
|
|
|
+ this.bgLayer.add(group);
|
|
|
+ this.bgLayer.draw();
|
|
|
+ this.materialElements.push(group);
|
|
|
+ };
|
|
|
+ });
|
|
|
+ },
|
|
|
+
|
|
|
+// 监听 doorOpen 状态变化时更新物资的 draggable 状态
|
|
|
+ updateDraggableStatus() {
|
|
|
+ this.materialElements.forEach(group => {
|
|
|
+ group.draggable(this.doorOpen); // 动态更新 draggable 状态
|
|
|
+ });
|
|
|
+ this.bgLayer.draw();
|
|
|
+ },
|
|
|
+
|
|
|
+
|
|
|
+ // 批量更新物资状态
|
|
|
+ updateMaterialsBatch() {
|
|
|
+ if (this.materialsToUpdate.length === 0) return; // 如果没有需要更新的物资,直接返回
|
|
|
+ updateIsMaterialById(this.materialsToUpdate).then(response => {
|
|
|
+ if (response.data) {
|
|
|
+ this.$message.success('物资更新成功');
|
|
|
+ this.materialsToUpdate = []; // 清空需要更新的物资列表
|
|
|
+ } else {
|
|
|
+ this.$message.error('物资更新失败');
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+};
|
|
|
+</script>
|
|
|
+
|
|
|
+<style scoped lang="scss">
|
|
|
+.mapBox {
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ //background-color: pink;
|
|
|
+}
|
|
|
+</style>
|