daShangDao_miniProgram/components/WarehouserSelector.vue
2025-11-24 10:25:20 +08:00

508 lines
13 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<!-- <view class="form-container"> -->
<!-- <view class="view-container"> -->
<view class="view-item view-item-3">
<view class="label" @click="onLabelClick">货区</view>
<view class="select" @click="openPicker">
{{ selectedStorage || '请选择货区' }}
</view>
<u-picker :show="showPicker" ref="uPicker" :columns="columns" @cancel="cancelPicker" @confirm="confirmPicker"
@change="changeHandler"></u-picker>
</view>
<!-- </view> -->
<!-- </view> -->
</template>
<script>
export default {
name: 'WarehouseSelector',
props: {
// 初始选中的货区
initialStorage: {
type: String,
default: ''
},
// 原始warehouse对象
initialWarehouse: {
type: Object,
default: null
}
},
data() {
return {
showPicker: false,
selectedStorage: this.initialStorage,
warehouse: '',
shelf: '',
location: '',
columns: [
[], // 仓库列表
[], // 货架列表
[] // 货位列表
],
shelves: [], // 货架列表
locations: [], // 货位列表
selectedWarehouse: null,
selectedSheId: null,
selectedFreId: null
};
},
mounted() {
this.initData();
this.loadStorageSelection();
},
watch: {
// 监听initialWarehouse变化,重新初始化
initialWarehouse: {
handler(newValue) {
if (newValue) {
this.selectedWarehouse = newValue;
this.initData();
}
},
immediate: true
},
selectedWarehouse: {
handler(newVal, oldVal) {
if (newVal) {
// 重新拉取货架和货位数据
this.columns[0] = [newVal.name];
this.fetchShelves(newVal.id).then(shelves => {
if (shelves.length > 0) {
this.columns[1] = shelves.map(item => item.code);
this.fetchLocations(shelves[0].id).then(locations => {
this.columns[2] = locations.map(item => item.code);
// 在数据加载完成后,尝试加载该仓库的货区状态
this.$nextTick(() => {
this.loadStorageSelection();
});
});
} else {
this.columns[1] = [];
this.columns[2] = [];
// 没有货架数据时也要尝试加载货区状态(可能会清空)
this.$nextTick(() => {
this.loadStorageSelection();
});
}
});
// 如果是仓库切换(不是初始化),先清空当前状态
if (oldVal && oldVal.id !== newVal.id) {
console.log(`仓库从${oldVal.id}切换到${newVal.id},清空当前货区状态`);
this.clearStorageSelection();
}
} else {
// 没有选择仓库时清空状态
this.clearStorageSelection();
}
},
immediate: true
}
},
methods: {
// 保存货区选择状态到本地存储
saveStorageSelection() {
// 只有在选择了仓库的情况下才保存货区状态
if (!this.selectedWarehouse || !this.selectedWarehouse.id) {
console.log('未选择仓库,不保存货区状态');
return;
}
const storageData = {
selectedStorage: this.selectedStorage,
warehouse: this.warehouse,
shelf: this.shelf,
location: this.location,
selectedSheId: this.selectedSheId,
selectedFreId: this.selectedFreId
};
// 使用仓库ID作为键的一部分为每个仓库单独保存货区状态
const storageKey = `selectedStorageData_${this.selectedWarehouse.id}`;
uni.setStorageSync(storageKey, storageData);
console.log(`保存仓库${this.selectedWarehouse.id}的货区选择状态:`, storageData);
},
// 从本地存储加载货区选择状态
loadStorageSelection() {
try {
// 只有在选择了仓库的情况下才加载货区状态
if (!this.selectedWarehouse || !this.selectedWarehouse.id) {
console.log('未选择仓库,清空货区状态');
this.clearStorageSelection();
return;
}
// 根据仓库ID加载对应的货区状态
const storageKey = `selectedStorageData_${this.selectedWarehouse.id}`;
const storageData = uni.getStorageSync(storageKey);
if (storageData) {
console.log(`加载仓库${this.selectedWarehouse.id}的货区选择状态:`, storageData);
this.selectedStorage = storageData.selectedStorage || '';
this.warehouse = storageData.warehouse || '';
this.shelf = storageData.shelf || '';
this.location = storageData.location || '';
this.selectedSheId = storageData.selectedSheId || null;
this.selectedFreId = storageData.selectedFreId || null;
// 强制更新视图
this.$forceUpdate();
} else {
console.log(`仓库${this.selectedWarehouse.id}没有保存的货区状态,清空当前状态`);
this.clearStorageSelection();
}
} catch (error) {
console.error('加载货区选择状态失败:', error);
}
},
// 清空货区选择状态
clearStorageSelection() {
this.selectedStorage = '';
this.warehouse = '';
this.shelf = '';
this.location = '';
this.selectedSheId = null;
this.selectedFreId = null;
// 重置选择器的值
this.selectedValues = ['', '', ''];
// 强制更新视图
this.$forceUpdate();
console.log('已清空货区选择状态');
},
// 初始化数据
async initData() {
if (this.initialWarehouse) {
this.selectedWarehouse = this.initialWarehouse;
// 设置仓库列
this.columns[0] = [this.initialWarehouse.name];
// 加载货架数据
if (this.initialWarehouse.id) {
const shelves = await this.fetchShelves(this.initialWarehouse.id);
// console.log('初始化货架数据:', shelves);
// 如果存在货架数据,加载第一个货架的货位数据
if (shelves && shelves.length > 0) {
await this.fetchLocations(shelves[0].id);
}
}
}
},
// 更新选中的货区数据
updateSelectedStorage(data) {
// console.log('更新货区数据:', data);
if (data) {
this.selectedStorage = data.storage;
this.warehouse = data.warehouse;
this.shelf = data.shelf;
this.location = data.location;
this.selectedSheId = data.shelfId;
this.selectedFreId = data.locationId;
// 强制更新视图
this.$forceUpdate();
}
},
// 打开选择器
openPicker() {
// 在打开选择器前确保数据已加载
if (this.columns[0].length === 0 && this.selectedWarehouse) {
this.columns[0] = [this.selectedWarehouse.name];
}
this.showPicker = true;
},
// 点击标签
onLabelClick() {
this.$emit('label-click');
},
// 取消选择
cancelPicker() {
this.showPicker = false;
},
// 确认选择
confirmPicker(e) {
const {
value
} = e;
const [warehouse, shelf, location] = value;
// 只有当三个值都存在时才保存选中的值
if (warehouse && shelf && location) {
this.warehouse = warehouse;
this.shelf = shelf;
this.location = location;
// 更新显示文本
this.selectedStorage = `${warehouse} / ${shelf} / ${location}`;
// 查找选中项的ID
const selectedShelf = this.shelves.find(item => item.code === shelf);
const selectedLocation = this.locations.find(item => item.code === location);
// 保存选中ID
this.selectedSheId = selectedShelf?.id;
this.selectedFreId = selectedLocation?.id;
// 保存选择状态到本地存储
this.saveStorageSelection();
// 向父组件发送选中数据
this.$emit('storage-selected', {
storage: this.selectedStorage,
warehouse: this.warehouse,
shelf: this.shelf,
location: this.location,
shelfId: this.selectedSheId,
locationId: this.selectedFreId
});
} else {
// 如果不完整,提示用户
uni.showToast({
title: '请完整选择仓库、货架和货位',
icon: 'none'
});
}
this.showPicker = false;
},
// 处理picker列变化
async changeHandler(e) {
// 防御性检查确保e和必要的属性存在
if (!e) {
console.warn('changeHandler: 事件对象为空');
return;
}
// console.log('选择器变化:', e);
// 获取列索引和选中的索引数组
const {
columnIndex,
index
} = e;
// 如果是选择了仓库第0列
if (columnIndex === 0) {
// 获取选中的仓库
const warehouseName = this.columns[0][index];
// 使用仓库ID获取货架数据
if (this.selectedWarehouse && this.selectedWarehouse.id) {
await this.fetchShelves(this.selectedWarehouse.id);
}
}
// 如果是选择了货架第1列
if (columnIndex === 1 && this.shelves.length > 0) {
// 获取选中的货架
const selectedShelf = this.shelves[index];
// console.log('选中货架:', selectedShelf);
// 保存选中的货架ID
if (selectedShelf && selectedShelf.id) {
this.selectedSheId = selectedShelf.id;
await this.fetchLocations(selectedShelf.id);
}
}
},
// 获取货架列表
async fetchShelves(depotId) {
try {
// console.log('获取货架数据,仓库ID:', depotId);
const response = await uni.request({
url: 'https://api.buzhiyushu.cn/shelves/shelves/sheNamelist',
data: {
depotId
}
});
// 使用数组解构获取响应结果
const [err, res] = Array.isArray(response) ? response : [null, response];
if (!res?.data?.rows) {
console.error('获取货架数据失败,返回空数据');
return [];
}
this.shelves = res.data.rows; // 保存货架列表
this.columns[1] = this.shelves.map(item => item.code || '未知货架');
// console.log('获取到货架数据:', this.shelves);
// console.log('货架选项:', this.columns[1]);
// 更新UI
this.$nextTick(() => {
if (this.$refs.uPicker) {
this.$refs.uPicker.setColumnValues(1, this.columns[1]);
// 清空货位列
this.$refs.uPicker.setColumnValues(2, []);
}
});
return this.shelves;
} catch (error) {
console.error('获取货架失败:', error);
return [];
}
},
// 获取货位列表
async fetchLocations(sheId) {
if (!sheId) {
console.error('获取货位列表失败未提供货架ID');
return [];
}
try {
// console.log('获取货位数据,货架ID:', sheId);
const response = await uni.request({
url: 'https://api.buzhiyushu.cn/shelves/shelves/freNamelist',
method: 'GET',
data: {
sheId
}
});
// 使用数组解构获取响应结果
const [err, res] = Array.isArray(response) ? response : [null, response];
if (err) {
console.error('获取货位请求错误:', err);
return [];
}
if (!res || !res.data || !res.data.rows) {
console.error('货位响应数据格式不正确');
return [];
}
const locations = res.data.rows;
// console.log('获取到货位数据:', locations);
// 保存货位数据
this.locations = locations;
// 更新货位列
this.columns[2] = locations.map(item => item.code || '未知货位');
// console.log('货位选项:', this.columns[2]);
// 更新UI
this.$nextTick(() => {
if (this.$refs.uPicker) {
this.$refs.uPicker.setColumnValues(2, this.columns[2]);
}
});
return locations;
} catch (error) {
console.error('获取货位列表失败:', error);
return [];
}
}
},
created() {
// 监听外部更新事件
this.$on('storage-selected', this.updateSelectedStorage);
},
beforeDestroy() {
// 移除事件监听
this.$off('storage-selected', this.updateSelectedStorage);
}
}
</script>
<style scoped>
.view-container {
display: flex;
background-color: #fff;
margin-bottom: 20rpx;
overflow: hidden;
}
.view-item {
flex: 1;
display: flex;
align-items: center;
/* 垂直居中 */
padding: 3rpx 0;
text-align: center;
color: #666;
position: relative;
/* border-bottom: 1px solid #ccc; */
}
.view-item-3 {
flex: 3 !important;
}
.view-item-4 {
flex: 4 !important;
}
.view-item-6 {
flex: 6 !important;
}
.view-item-7 {
flex: 7 !important;
}
.view-item>.label {
padding: 0rpx 15rpx;
text-align: center;
height: 60rpx;
line-height: 60rpx;
color: #000;
font-size: 28rpx;
background-color: #ccc;
border-radius: 8rpx;
margin-right: 20rpx;
flex-shrink: 0;
}
.view-item>.select {
padding: 16rpx 0rpx;
text-align: center;
width: 100%;
height: 40rpx;
font-size: 18rpx;
line-height: 45rpx;
}
.form-container {
padding-left: 10rpx;
background-color: #fff;
}
::v-deep .u-picker__view__column__item[class*="data-v-"] {
font-size: 30rpx !important;
}
/* 确保选择器文本也使用相同大小 */
.view-item>.select {
font-size: 23rpx !important;
}
::v-deep .data-v-55c89db1 .u-toolbar__wrapper__confirm.data-v-55c89db1 {
color: #3c9cff;
font-size: 45rpx;
padding: 0 15rpx;
}
</style>