Files
FT546MWS/ruoyi-ui/src/views/kpi/spacePlan/index.vue
猫猫guowen dc8f2d329a KPI
2025-12-29 16:35:26 +08:00

421 lines
12 KiB
Vue

<template>
<div class="app-container">
<div class="search-box">
<el-form :model="queryParams" ref="queryForm" :inline="true">
<!-- 仓库 -->
<!-- <el-form-item label="仓库" prop="warehouseId">-->
<!-- <el-select v-model="queryParams.warehouseId" placeholder="请选择仓库" @change="handleWarehouseChange">-->
<!-- <el-option-->
<!-- v-for="dict in warehouseOptions"-->
<!-- :key="dict.warehouseId"-->
<!-- :label="dict.warehouseName"-->
<!-- :value="dict.warehouseId"-->
<!-- />-->
<!-- </el-select>-->
<!-- </el-form-item>-->
<!-- 层数 -->
<el-form-item label="层数">
<el-select v-model="queryParams.theFloor" style="width: 150px" @change="handleFloorChange">
<el-option v-for="item in floorOptions" :key="item.value" :label="item.label" :value="item.value"/>
</el-select>
</el-form-item>
<!-- 排 -->
<!-- <el-form-item label="排">
<el-select v-model="queryParams.thePlatoon" style="width: 150px" @change="handlePlatoonChange">
<el-option v-for="item in platoonOptions" :key="item.value" :label="item.label" :value="item.value"/>
</el-select>
</el-form-item>-->
</el-form>
</div>
<div class="chart-container">
<div id="container" v-show="queryParams.warehouseId !== '04'" style="height: 80vh"></div>
</div>
</div>
</template>
<script>
import * as echarts from 'echarts'
import {getRoadways, getPlatoons, getChartData, getChartMag, getFloors} from "@/api/kpi/spacePlan"
import {listWarehouse} from "@/api/bas/warehouse";
import VueI18n from 'vue-i18n';
export default {
name: 'SpacePlan',
data() {
return {
// 查询参数
queryParams: {
warehouseId: '01',
roadwayId: '1',
thePlatoon: '',
theFloor: '1',
platoon: '1',
specifications: '',
quantity_x: '',
quantity_j: '',
layer_quantity: '',
classgroup_number: '',
class_workshop_date_time: '',
class_now_date_time: '',
print_date: '',
lot_no: '',
},
// 仓库选项
warehouseOptions: [],
// 巷道选项
roadwayOptions: [],
floorOptions: [],
// 排号选项
platoonOptions: [],
// 图表实例
normalChart: null,
specialChart: null,
// 加载状态记录
loadingKeys: {},
// 图表数据
chartData: {
x: [],
y: [],
empty: [],
full: [],
inAllot: [],
outAllot: [],
inCheck: [],
outCheck: [],
resultsOf: [],
outCargo: [],
theLocked: []
},
queryWarehouseParam:{
pageNum: 1,
pageSize: 99,
typeData:[1]
}
}
},
mounted() {
this.getWarehouseList()
this.initCharts()
this.handleWarehouseChange()
},
methods: {
/** 查询仓库列表 */
getWarehouseList() {
listWarehouse(this.queryWarehouseParam).then(response => {
this.warehouseOptions = response.rows;
});
// this.warehouseOptions = [{warehouseId: "01", warehouseName: "仓库1"}, {warehouseId: "02", warehouseName: "仓库2"}];
},
// 初始化图表
initCharts() {
this.normalChart = echarts.init(document.getElementById('container'))
},
// 仓库变化处理
handleWarehouseChange() {
// 重置巷道和排号
this.queryParams.roadwayId = ''
this.queryParams.thePlatoon = ''
this.floorOptions = []
this.platoonOptions = []
// 获取层数列表
getFloors({ warehouseId: this.queryParams.warehouseId }).then(response => {
const floors = response.data.data || []
if (floors && floors.length > 0) {
this.floorOptions = floors.map(f => {
const lbl = f.label != null ? f.label : (f.name != null ? f.name : (f.title != null ? f.title : (f.value != null ? (String(f.value) + '排') : '')))
const val = f.value != null ? String(f.value) : String((lbl || '').replace(/[^\d]/g, ''))
return { label: lbl, value: val }
})
this.queryParams.theFloor = this.floorOptions[0].value
this.loadChartData()
} else {
this.floorOptions = []
this.queryParams.theFloor = null
}
})
},
// 巷道变化处理
handleFloorChange() {
console.log( this.queryParams.theFloor)
this.loadChartData()
},
// 加载普通仓库图表数据
loadChartData() {
getChartData(this.queryParams).then(response => {
const data = response.data
// 调整坐标值以匹配实际位置
const adjustCoordinates = (data) => {
return data.map(item => [item[0] - 1, item[1] - 1, item[2]]);
};
this.chartData.x = eval('(' + data["column"] + ')');
this.chartData.y = eval('(' + data["floor"] + ')');
this.chartData.empty = adjustCoordinates(eval('(' + data["empty"] + ')'));
this.chartData.full = adjustCoordinates(eval('(' + data["full"] + ')'));
this.chartData.inAllot = adjustCoordinates(eval('(' + data["inAllot"] + ')'));
this.chartData.outAllot = adjustCoordinates(eval('(' + data["outAllot"] + ')'));
this.chartData.inCheck = adjustCoordinates(eval('(' + data["inCheck"] + ')'));
this.chartData.outCheck = adjustCoordinates(eval('(' + data["outCheck"] + ')'));
this.updateNormalChart()
})
},
// 更新普通仓库图表
updateNormalChart() {
const option = {
tooltip: {
trigger: 'item',
formatter: (params) => {
return this.formatTooltip(params)
}
},
title: {
text: '库位分布平面图',
subtext: (() => {
const sel = this.floorOptions.find(o => String(o.value) === String(this.queryParams.theFloor))
return sel && sel.label ? sel.label : ''
})()
},
grid: {
width: '90%',
height: '70%',
top: '20%',
left: '5%'
},
xAxis: {
type: 'category',
data: this.chartData.x,
splitArea: {show: true}
},
yAxis: {
type: 'category',
data: this.chartData.y,
splitArea: {show: true}
},
visualMap: {
show: false,
min: 1,
max: 6,
calculable: true,
orient: 'horizontal',
left: 'center',
inRange: {
color: ['#AEEEEE', '#FF9900', '#FFFF00', '#00CC00', '#FF0000', '#0000FF']
}
},
legend: {
data: [
{
// 图例:空位
name: '空位',
itemStyle: { color: '#AEEEEE' }
},
{
// 图例:满位
name: '满位',
itemStyle: { color: '#FF9900' }
},
{
// 图例:入库分配
name: '入库分配',
itemStyle: { color: '#FFFF00' }
},
{
// 图例:出库分配
name: '出库分配',
itemStyle: { color: '#00cc00' }
},
{
// 图例:入库需盘点
name: '入库需盘点',
itemStyle: { color: '#FF0000' }
},
{
// 图例:出库需盘点
name: '出库需盘点',
itemStyle: { color: '#0000FF' }
}
],
textStyle: {
color: '#333'
}
},
series: [
{
// 空位
name: '空位',
type: 'heatmap',
data: this.chartData.empty,
itemStyle: {
borderColor: '#fff',
borderWidth: 2
}
},
{
// 满位
name: '满位',
type: 'heatmap',
data: this.chartData.full,
itemStyle: {
borderColor: '#fff',
borderWidth: 2
}
},
{
// 入库分配
name: '入库分配',
type: 'heatmap',
data: this.chartData.inAllot,
itemStyle: {
borderColor: '#fff',
borderWidth: 2
}
},
{
// 出库分配
name: '出库分配',
type: 'heatmap',
data: this.chartData.outAllot,
itemStyle: {
borderColor: '#fff',
borderWidth: 2
}
},
{
// 入库需盘点
name: '入库需盘点',
type: 'heatmap',
data: this.chartData.inCheck,
itemStyle: {
borderColor: '#fff',
borderWidth: 2
}
},
{
// 出库需盘点
name: '出库需盘点',
type: 'heatmap',
data: this.chartData.outCheck,
itemStyle: {
borderColor: '#fff',
borderWidth: 2
}
}
]
}
this.normalChart.setOption(option)
},
// 防抖函数
debounce(func, wait) {
let timeout;
return function (...args) {
const context = this;
clearTimeout(timeout);
timeout = setTimeout(() => func.apply(context, args), wait);
};
},
// 格式化普通仓库提示信息
formatTooltip(params) {
if (params.seriesName !== '满位') {
// 排
if (this.$i18n.locale ==='zh-cn') {
return params.seriesName + '<br>' + (params.data[1] + 1) + '排' + (params.data[0] + 1) + '列' + this.queryParams.theFloor+ '层';
}
else{
return params.seriesName + '<br>' + (params.data[1] + 1) + '排' + (params.data[0] + 1) + '列' + this.queryParams.theFloor+ '层';
}
}
const returnData = {
"thePlatoon": params.data[1] + 1,
"theColumn": params.data[0] + 1,
"theFloor": this.queryParams.theFloor,
"warehouseId": this.queryParams.warehouseId
};
// 生成唯一标识
const key = `${params.seriesName}-${params.data[0]}-${params.data[1]}`;
// 如果已经在加载中,返回基本信息
if (this.loadingKeys && this.loadingKeys[key]) {
if (this.$i18n.locale === 'zh-cn') {
return params.seriesName + '<br>' + (params.data[1] + 1) + '排' + (params.data[0] + 1) + '列' + this.queryParams.theFloor + '层';
} else {
return params.seriesName + '<br>' + (params.data[1] + 1) + '排' + (params.data[0] + 1) + '列' + this.queryParams.theFloor+ '层';
}
}
// 返回基本信息
const baseStr = `${params.seriesName}<br>${(params.data[1] + 1)}排${params.data[0] + 1}列${this.queryParams.theFloor}层`;
// 设置加载状态
if (!this.loadingKeys) this.loadingKeys = {};
this.loadingKeys[key] = true;
// 使用防抖函数包装请求
this.debounce(() => {
getChartMag(returnData)
.then(response => {
const msg = response.data.msg;
const str = `${baseStr}<br>${msg}`;
this.normalChart.setOption({
tooltip: {
formatter: (p) => {
if (p.seriesName === params.seriesName &&
p.data[0] === params.data[0] &&
p.data[1] === params.data[1]) {
return str;
}
return this.formatTooltip(p);
}
}
});
})
.catch(error => {
// 提示:获取货位信息失败
console.error('获取货位信息失败:', error);
})
.finally(() => {
// 清除加载状态
delete this.loadingKeys[key];
});
}, 300)();
return baseStr;
},
}
}
</script>
<style scoped>
.app-container {
padding: 20px;
}
.search-box {
background-color: #fff;
padding: 20px;
margin-bottom: 20px;
border-radius: 4px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
}
.chart-container {
background-color: #fff;
padding: 20px;
border-radius: 4px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
}
</style>