feat(组件): 为DragResizeBox添加localStorage持久化功能

添加storageKey属性支持将位置和尺寸保存到localStorage
初始化时优先读取存储值,拖动结束后自动保存
同时优化了CoilSelector的钢卷地图显示逻辑
This commit is contained in:
砂糖
2026-03-12 10:41:19 +08:00
parent 3c96211cc5
commit c766904b45
3 changed files with 108 additions and 15 deletions

View File

@@ -20,7 +20,7 @@
<el-dialog title="选择钢卷" :visible.sync="dialogVisible" :width="dialogWidth" :close-on-click-modal="false"
@close="handleClose" append-to-body :fullscreen="orderBy">
<!-- 搜索区域 -->
<el-form v-if="!rangeMode" :model="queryParams" class="search-form">
<el-form v-if="!rangeMode" inline :model="queryParams" class="search-form">
<!-- <el-form-item label="类型">
<el-select v-model="queryParams.selectType" placeholder="请选择类型" size="small">
<el-option label="成品" value="product" />
@@ -62,12 +62,13 @@
</el-form-item>
<el-form-item label="实际库区" v-if="orderBy">
<actual-warehouse-select v-model="queryParams.actualWarehouseId" placeholder="请选择实际库区" canSelectLevel2
canSelectDisabled @select="handleWarehouseChange" />
canSelectDisabled :clearInput="false" clearable />
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="small" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="small" @click="resetQuery">重置</el-button>
<el-checkbox style="margin-left: 10px;" v-model="showCoilMap" size="small">显示钢卷地图</el-checkbox>
</el-form-item>
</el-form>
@@ -122,8 +123,13 @@
</div>
<!-- 一个可以拖拽和调节大小的浮层 -->
<DragResizeBox v-if="selectedNodeId" @size-change="handleSizeChange">
<div style="height: 100%; width: 100%; overflow-y: scroll;">
<DragResizeBox v-if="showCoilMap" @size-change="handleSizeChange" storageKey="coil-map">
<div style="height: 100%; width: 100%; overflow-y: scroll; display: flex; background-color: #fff;">
<div style="min-width: 150px; position: sticky; top: 0;" v-loading="treeLoading">
<el-tree ref="warehouseTreeRef" :data="warehouseTree" :props="treeProps" node-key="actualWarehouseId"
@node-click="handleNodeClick" :expand-on-click-node="false" highlight-current class="warehouse-tree">
</el-tree>
</div>
<warehouse-bird-mini ref="warehouseBirdMini" v-loading="warehouseLoading" :warehouseList="warehouseList" :id="selectedNodeId"
:canToggle="false" :canRelease="false" />
</div>
@@ -135,6 +141,7 @@
<script>
import { listMaterialCoil } from '@/api/wms/coil';
import { listActualWarehouse } from "@/api/wms/actualWarehouse";
import { treeActualWarehouseTwoLevel } from "@/api/wms/actualWarehouse";
import MemoInput from '@/components/MemoInput/index.vue';
import MutiSelect from '@/components/MutiSelect/index.vue';
import { defaultColumns } from './data';
@@ -216,6 +223,7 @@ export default {
},
data() {
return {
showCoilMap: false,
loading: false,
coilList: [],
total: 0,
@@ -242,6 +250,9 @@ export default {
warehouseList: [],
selectedNodeId: null,
warehouseLoading: false,
warehouseTree: [],
treeProps: { label: "actualWarehouseName", children: "children" },
treeLoading: false,
};
},
computed: {
@@ -323,6 +334,9 @@ export default {
if (this.initialCoil) {
this.selectedCoil = this.initialCoil;
}
if (this.orderBy) {
this.getWarehouseTree();
}
},
methods: {
// 获取库位列表
@@ -336,6 +350,22 @@ export default {
this.warehouseLoading = false;
});
},
handleNodeClick(data) {
console.log('data', data);
if (data.actualWarehouseType != 2) {
return;
}
this.selectedNodeId = data.actualWarehouseId;
this.getWarehouseList(data.actualWarehouseId);
},
// 获取树形数据
getWarehouseTree() {
this.treeLoading = true;
treeActualWarehouseTwoLevel()
.then((res) => { this.warehouseTree = res.data || []; })
.catch((err) => { this.$message.error("获取仓库树形数据失败:" + err.message); })
.finally(() => { this.treeLoading = false; });
},
// 处理大小变化
handleSizeChange(size) {
console.log('size', size);
@@ -587,13 +617,6 @@ export default {
margin-top: 4px;
}
.search-form {
margin-bottom: 20px;
display: flex;
align-items: center;
gap: 16px;
}
::v-deep .el-dialog__body {
padding: 20px;
max-height: calc(100vh - 200px);

View File

@@ -48,6 +48,11 @@ export default {
minSize: {
type: Object,
default: () => ({ width: 100, height: 80 })
},
// 用于localStorage存储的唯一标识
storageKey: {
type: String,
default: ''
}
},
data() {
@@ -67,9 +72,8 @@ export default {
};
},
mounted() {
// 初始化位置和尺寸
this.position = { ...this.initPosition };
this.size = { ...this.initSize };
// 初始化位置和尺寸优先从localStorage读取
this.initFromStorage();
// 监听全局鼠标移动和松开事件
document.addEventListener('mousemove', this.handleMouseMove);
document.addEventListener('mouseup', this.handleMouseUp);
@@ -83,6 +87,68 @@ export default {
window.removeEventListener('resize', this.updateScreenSize);
},
methods: {
/**
* 从localStorage初始化位置和尺寸
* 有key时优先读取存储值无则使用props传入的初始值
*/
initFromStorage() {
if (this.storageKey) {
try {
const storageKey = `dnd-ps-${this.storageKey}`;
const storedData = localStorage.getItem(storageKey);
if (storedData) {
const { position, size } = JSON.parse(storedData);
// 验证存储的数据是否合法,防止异常值
const isValidPosition = position && typeof position.x === 'number' && typeof position.y === 'number';
const isValidSize = size && typeof size.width === 'number' && typeof size.height === 'number';
if (isValidPosition && isValidSize) {
// 使用存储的位置和尺寸(确保不小于最小尺寸)
this.position = {
x: Math.max(0, position.x),
y: Math.max(0, position.y)
};
this.size = {
width: Math.max(this.minSize.width, size.width),
height: Math.max(this.minSize.height, size.height)
};
return;
}
}
} catch (error) {
console.warn('读取拖拽元素存储数据失败,使用默认值:', error);
}
}
// 无存储数据或存储异常时使用props初始值
this.position = { ...this.initPosition };
this.size = { ...this.initSize };
},
/**
* 将当前位置和尺寸保存到localStorage
*/
saveToStorage() {
if (this.storageKey) {
try {
const storageKey = `dnd-ps-${this.storageKey}`;
const saveData = {
position: { ...this.position },
size: { ...this.size },
updateTime: new Date().getTime()
};
console.log('saveData', saveData);
localStorage.setItem(storageKey, JSON.stringify(saveData));
// 触发存储成功事件
this.$emit('save-success', saveData);
} catch (error) {
console.error('保存拖拽元素数据失败:', error);
this.$emit('save-fail', error);
}
}
},
/**
* 更新屏幕尺寸(窗口大小变化时)
*/
@@ -174,6 +240,9 @@ export default {
// 恢复鼠标样式
document.body.style.cursor = 'default';
// 保存当前状态到localStorage有key时
this.saveToStorage();
// 触发结束事件
this.$emit('drag-end', { position: { ...this.position }, size: { ...this.size } });
}
@@ -203,6 +272,7 @@ export default {
overflow: hidden;
pointer-events: auto; /* 元素本身响应鼠标事件 */
z-index: 9999; /* 确保元素在最上层 */
background-color: #ffffff; /* 添加背景色,提升可视性 */
}
/* 元素内容区 */

View File

@@ -89,7 +89,7 @@ export default {
methods: {
// 处理分列数据调整
resize() {
this.$refs.warehouseInterlaced.handleResize();
this.$refs.warehouseInterlaced?.handleResize();
},
handleSplitWarehouse(warehouse) {
this.$emit('split-warehouse', warehouse);