You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
420 lines
11 KiB
Vue
420 lines
11 KiB
Vue
<template>
|
|
<ContentWrap>
|
|
<!-- 搜索工作栏 -->
|
|
<el-form
|
|
class="-mb-15px"
|
|
:model="queryParams"
|
|
ref="queryFormRef"
|
|
:inline="true"
|
|
label-width="68px"
|
|
>
|
|
<el-form-item label="选择巷道" prop="srmNumber">
|
|
<el-select
|
|
v-model="queryParams.streetId"
|
|
placeholder="请选择巷道"
|
|
clearable
|
|
@keyup.enter="handleQuery"
|
|
class="!w-240px"
|
|
>
|
|
<el-option
|
|
v-for="dict in streetList"
|
|
:key="dict.id"
|
|
:label="dict.name"
|
|
:value="dict.id"
|
|
/>
|
|
</el-select>
|
|
</el-form-item>
|
|
<el-form-item label="方向" prop="fromDirection">
|
|
<el-select
|
|
v-model="queryParams.direction"
|
|
clearable
|
|
@keyup.enter="handleQuery"
|
|
class="!w-240px"
|
|
>
|
|
<el-option
|
|
v-for="dict in getIntDictOptions(DICT_TYPE.DIRECTION)"
|
|
:key="dict.value"
|
|
:label="dict.label"
|
|
:value="dict.value"
|
|
/>
|
|
</el-select>
|
|
</el-form-item>
|
|
|
|
<el-form-item ><el-button @click="handleQuery" type="primary">搜索</el-button></el-form-item>
|
|
|
|
</el-form>
|
|
</ContentWrap>
|
|
|
|
<!-- 按钮墙 -->
|
|
<ContentWrap>
|
|
<!-- 按钮墙 -->
|
|
<el-tabs :tab-position="top" style="height: 100%" class="demo-tabs">
|
|
<el-tab-pane v-for="(item, index) in columnMap" :key="index" :label="item">
|
|
<el-row v-for="(row, rowIndex) in rows" :key="'row-' + rowIndex">
|
|
<el-col :span="1">{{ row + "层" }}</el-col>
|
|
<el-col :span="1" v-for="(colum, colIndex) in columnLists[index]" :key="'col-' + colIndex">
|
|
<el-button
|
|
style="width: 90%;"
|
|
:type="getButtonType(row, colum)"
|
|
:key="'button-' + colIndex"
|
|
:disabled="isDisabled(row, colum)"
|
|
@click="getDialogVisible(row, colum)"
|
|
>
|
|
{{ row + "-" + colum }}
|
|
</el-button>
|
|
</el-col>
|
|
</el-row>
|
|
</el-tab-pane>
|
|
</el-tabs>
|
|
|
|
|
|
</ContentWrap>
|
|
<ContentWrap v-if="f">
|
|
|
|
<el-row :gutter="20">
|
|
<el-col style="height: 30vh;" :span="5">
|
|
|
|
<el-card style="height: 100%;" shadow="always">
|
|
<p>统计信息:</p>
|
|
<!-- 为 ECharts 准备一个定义了宽高的 DOM -->
|
|
|
|
<Echart style="height:200px;" :options="option" />
|
|
</el-card>
|
|
</el-col>
|
|
<el-col style="height: 30vh;" :span="18">
|
|
|
|
<el-card style="height: 100%;" shadow="always">
|
|
<div style="width: 100%;height: 100%;">
|
|
|
|
<!-- 为 ECharts 准备一个定义了宽高的 DOM -->
|
|
<!-- 遍历 Map 中的每个 key-value 对 -->
|
|
<!-- 遍历 Map 中的每个 key-value 对 -->
|
|
|
|
<div v-for="(title) in buttonByObjectMap.keys()" :key="title">
|
|
<!-- 标题 -->
|
|
<h4>{{ title }}</h4>
|
|
<!-- 遍历每个标题下的按钮数组 -->
|
|
<el-space :size="size" :spacer="spacer">
|
|
<div
|
|
class="mb-15px"
|
|
style="width: 5%;" v-for="(button, index) in buttonByObjectMap.get(title)" :key="index">
|
|
<el-button
|
|
:type="getButtonType(button.row, button.column)"
|
|
:key="'button2-' + index"
|
|
:disabled="isDisabled(button.row, button.column)"
|
|
@click="getDialogVisible(button.row, button.column)"
|
|
>
|
|
{{ button.row }}-{{ button.column }}
|
|
</el-button>
|
|
</div>
|
|
</el-space>
|
|
</div>
|
|
</div>
|
|
|
|
</el-card>
|
|
</el-col>
|
|
</el-row>
|
|
|
|
</ContentWrap>
|
|
|
|
<el-dialog
|
|
v-model="dialogVisible"
|
|
:title="getStreetName()+getDirectionName()+'侧'+rowName+'层'+columnName+'列'"
|
|
width="40%"
|
|
@close="handleClose"
|
|
>
|
|
|
|
<stock :stockId="getStockId()" :key="getStockId()"/>
|
|
</el-dialog>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
|
|
import { StreetApi,StreetVO } from '@/api/logistics/street'
|
|
import { StockApi,StockVO } from '@/api/logistics/stock'
|
|
import stock from '@/views/logistics/stock/stock.vue'
|
|
import { forEach } from 'lodash-es'
|
|
import { EChartsOption } from 'echarts'
|
|
|
|
|
|
import { log } from 'console'
|
|
import Cookies from 'js-cookie';
|
|
|
|
|
|
const message = useMessage() // 消息弹窗
|
|
const { t } = useI18n() // 国际化ist
|
|
|
|
let rows = ref(12);
|
|
let columns = ref(48);
|
|
//最大行列
|
|
const rowMax = ref(20);
|
|
const columnMax = ref(20);
|
|
const columnList = ref<number[]>([]);
|
|
const rowName = ref("")
|
|
const columnName = ref("")
|
|
const currentStockId =ref(0)
|
|
let columnMap = ref<String[]>([]);
|
|
|
|
const buttons = ref<ButtonVo[]>([]);
|
|
const dialogVisible = ref(false)
|
|
const getDialogVisible = (row,colum) => {
|
|
clearTimer()
|
|
rowName.value = row
|
|
columnName.value = colum
|
|
dialogVisible.value = true
|
|
|
|
}
|
|
|
|
// 从 Cookie 加载 queryParams
|
|
const loadQueryParamsFromCookie = () => {
|
|
const savedQueryParams = Cookies.get('queryParams');
|
|
if (savedQueryParams) {
|
|
const parsedParams = JSON.parse(savedQueryParams);
|
|
Object.assign(queryParams, parsedParams); // 更新 reactive 对象
|
|
}
|
|
};
|
|
const columnLists = computed(() => {
|
|
return columnMap.value.map((_, index) => {
|
|
const minIndex = index * columnMax.value + 1;
|
|
const maxIndex = (index + 1) * columnMax.value < columns.value ? (index + 1) * columnMax.value : columns.value;
|
|
const columnList = [];
|
|
for (let i = minIndex; i <= maxIndex; i++) {
|
|
columnList.push(i);
|
|
}
|
|
return columnList;
|
|
});
|
|
});
|
|
|
|
const loading = ref(true) // 列表的加载中
|
|
const total = ref(0) // 列表的总页数
|
|
const queryParams = reactive({
|
|
streetId: 1,
|
|
direction: 1
|
|
})
|
|
interface ButtonVo {
|
|
id?: number; // 可选,因为可能是新创建的对象
|
|
streetId?: number;
|
|
orderNum?: string;
|
|
lotnum?: string;
|
|
checkNum?: string;
|
|
code?: string;
|
|
category?: string;
|
|
count?: number;
|
|
wmsCode?: string;
|
|
wmsCategory?: string;
|
|
wmsCount?: number;
|
|
wmsTrayCode?: string;
|
|
trayCode?: string;
|
|
direction?: number;
|
|
side?: number;
|
|
row?: number;
|
|
column?: number;
|
|
status?: string;
|
|
preoperationPic?: string;
|
|
overoperationPic?: string;
|
|
storageCode?: string;
|
|
checkPic?: string;
|
|
exportTime?: Date;
|
|
subtag?: string;
|
|
reply?: string;
|
|
taskWmsId?: string;
|
|
addre?: string;
|
|
checkId?: number;
|
|
statusVision?: string;
|
|
}
|
|
|
|
// 将 queryParams 存入 Cookie
|
|
const saveQueryParamsToCookie = () => {
|
|
Cookies.set('queryParams', JSON.stringify(queryParams), { expires: 7 }); // 设置有效期为 7 天
|
|
};
|
|
/** 搜索按钮操作 */
|
|
const handleQuery = async () => {
|
|
columnMap.value = []
|
|
const data = await StockApi.getStreetList(queryParams)
|
|
saveQueryParamsToCookie()
|
|
getStreetStatus()
|
|
|
|
rows = ref(data.rows)
|
|
columns =ref(data.columns)
|
|
const page = columns.value/columnMax.value
|
|
|
|
for(var i = 0; i <= page; i++){
|
|
columnMap.value.push(i*columnMax.value+1+"-"+((i+1)*columnMax.value<columns.value?(i+1)*columnMax.value:columns.value))
|
|
}
|
|
|
|
|
|
}
|
|
const handleClose = () => {
|
|
dialogVisible.value = false
|
|
startTimer()
|
|
}
|
|
const isDisabled = (row: number, column: number): boolean => {
|
|
|
|
return !buttonMap.value.has(`${row}-${column}`);
|
|
};
|
|
|
|
const getStockId = (): string => {
|
|
return buttonByIdMap.value.get(`${rowName.value}-${columnName.value}`) ||"";
|
|
};
|
|
const getButtonType = (row: number, column: number): string => {
|
|
|
|
return buttonMap.value.get(`${row}-${column}`) ||"";
|
|
};
|
|
const handleReset = (index) => {
|
|
columnList.value = []
|
|
const minIndex = (index) *columnMax.value +1
|
|
const maxIndex = (index+1) * (columnMax.value)<columns.value?(index+1) * (columnMax.value):columns.value
|
|
|
|
for(var i = minIndex; i <= maxIndex; i++){
|
|
columnList.value.push(i)
|
|
}
|
|
return columnList
|
|
|
|
}
|
|
|
|
// getStreetStatus
|
|
const buttonMap = ref(new Map<string, string>());// 存储 row-column 到 status 的映射
|
|
|
|
// getStreetStatus
|
|
const buttonByIdMap = ref(new Map<string, string>());// 存储 row-column 到 stockId 的映射
|
|
const buttonByStatusMap = ref(new Map<string, number>());// 存储 row-column 到 statusString 的映射
|
|
const buttonByObjectMap = ref(new Map<string, Array<object>>());
|
|
|
|
const getStreetStatus = async () => {
|
|
buttonMap.value = new Map()
|
|
buttonByIdMap.value = new Map()
|
|
buttonByStatusMap.value = new Map()
|
|
buttonByObjectMap.value = new Map()
|
|
const data = await StockApi.getStreetStatus(queryParams)
|
|
for(var i = 0; i < data.length; i++){
|
|
buttonMap.value.set(`${data[i].row}-${data[i].column}`, data[i].colour)
|
|
buttonByIdMap.value.set(`${data[i].row}-${data[i].column}`, data[i].id)
|
|
if(buttonByStatusMap.value.has(data[i].statusString)){
|
|
buttonByStatusMap.value.set(data[i].statusString, buttonByStatusMap.value.get(data[i].statusString)!+1)
|
|
|
|
buttonByObjectMap.value.get(data[i].statusString)?.push(data[i])
|
|
}else{
|
|
buttonByStatusMap.value.set(data[i].statusString, 1)
|
|
buttonByObjectMap.value.set(data[i].statusString, [data[i]])
|
|
}
|
|
|
|
}
|
|
console.log(buttonByObjectMap.value);
|
|
|
|
|
|
}
|
|
|
|
// 监听 buttonByStatusMap 的变化
|
|
watch(buttonByStatusMap, (newMap) => {
|
|
const echartData = Array.from(newMap, ([name, value]) => ({ name, value }))
|
|
option.series[0].data = echartData
|
|
|
|
}, { deep: true })
|
|
|
|
const streetList = ref<StreetVO[]>([]) // 巷道队列
|
|
|
|
const getStreetName = ()=>{
|
|
return streetList.value.find(item => item.id === queryParams.streetId)?.name
|
|
}
|
|
|
|
const getDirectionName = ()=>{
|
|
return getIntDictOptions(DICT_TYPE.DIRECTION).find(item => item.value === queryParams.direction)?.label
|
|
}
|
|
/** 查询巷道列表 */
|
|
const getStringList = () => {
|
|
|
|
try {
|
|
const data = StreetApi.getStreetList()
|
|
data.then((res)=>{
|
|
streetList.value = res
|
|
})
|
|
} finally {
|
|
|
|
}
|
|
}
|
|
|
|
// 构造 ECharts 数据,使用 statusString 作为 name
|
|
const echartData =(()=>{
|
|
|
|
return Array.from(buttonByStatusMap.value, ([name, value]) => ({ name, value }));
|
|
}
|
|
);
|
|
// 定时器相关
|
|
let timer: NodeJS.Timeout | null = null
|
|
|
|
const startTimer = () => {
|
|
timer = setInterval(() => {
|
|
// 在这里添加定时执行的逻辑
|
|
// 例如,每秒更新一次数据
|
|
getStreetStatus()
|
|
}, 15000) // 每秒执行一次
|
|
}
|
|
|
|
const clearTimer = () => {
|
|
if (timer) {
|
|
clearInterval(timer)
|
|
timer = null
|
|
}
|
|
}
|
|
|
|
|
|
// 构造 ECharts 数据,使用 statusString 作为 name
|
|
|
|
const option = reactive({
|
|
tooltip: {
|
|
trigger: 'item'
|
|
},
|
|
legend: {
|
|
top: '5%',
|
|
left: 'center'
|
|
},
|
|
series: [
|
|
{
|
|
type: 'pie',
|
|
radius: ['40%', '70%'],
|
|
avoidLabelOverlap: false,
|
|
itemStyle: {
|
|
borderRadius: 10,
|
|
borderColor: '#fff',
|
|
borderWidth: 2
|
|
},
|
|
label: {
|
|
show: false,
|
|
position: 'center'
|
|
},
|
|
emphasis: {
|
|
label: {
|
|
show: true,
|
|
fontSize: 20,
|
|
fontWeight: 'bold'
|
|
}
|
|
},
|
|
labelLine: {
|
|
show: false
|
|
}, // 自定义颜色
|
|
normal: {
|
|
color: function(params) {
|
|
// 可以根据params.name来返回不同的颜色
|
|
const colorList = ['#87cefa', '#da70d6', '#32cd32', '#ff6347'];
|
|
return colorList[params.dataIndex]; // 根据数据项的index分配颜色
|
|
}
|
|
},
|
|
data: echartData()
|
|
}
|
|
]
|
|
});
|
|
|
|
/** 初始化 **/
|
|
onMounted(() => {
|
|
handleQuery()
|
|
getStringList()
|
|
loadQueryParamsFromCookie()
|
|
|
|
startTimer() // 启动定时器
|
|
handleReset(0)
|
|
})
|
|
|
|
onUnmounted(() => {
|
|
clearTimer() // 清除定时器
|
|
})
|
|
</script> |