|
|
@@ -1,8 +1,20 @@
|
|
|
<template>
|
|
|
<div :class="['warehouse-map', themeClass]">
|
|
|
- <div v-if="gridData.length === 0" class="no-data">暂无数据</div>
|
|
|
- <div v-else ref="mapWrapperRef" class="map-wrapper">
|
|
|
- <div class="map-grid" :style="gridStyle">
|
|
|
+ <div
|
|
|
+ v-if="gridData.length === 0"
|
|
|
+ class="no-data"
|
|
|
+ >
|
|
|
+ 暂无数据
|
|
|
+ </div>
|
|
|
+ <div
|
|
|
+ v-else
|
|
|
+ ref="mapWrapperRef"
|
|
|
+ class="map-wrapper"
|
|
|
+ >
|
|
|
+ <div
|
|
|
+ class="map-grid"
|
|
|
+ :style="gridStyle"
|
|
|
+ >
|
|
|
<div
|
|
|
v-for="(cell, index) in gridData"
|
|
|
:key="index"
|
|
|
@@ -15,8 +27,14 @@
|
|
|
@click="handleCellClick(cell)"
|
|
|
@contextmenu.prevent="handleCellContextMenu(cell)"
|
|
|
>
|
|
|
- <div v-if="isLocationCell(cell) && isCellVisible(cell)" class="cell-content">
|
|
|
- <div class="category-badge" :style="getCategoryStyle(cell)">
|
|
|
+ <div
|
|
|
+ v-if="isLocationCell(cell) && isCellVisible(cell)"
|
|
|
+ class="cell-content"
|
|
|
+ >
|
|
|
+ <div
|
|
|
+ class="category-badge"
|
|
|
+ :style="getCategoryStyle(cell)"
|
|
|
+ >
|
|
|
{{ getHeatLabel(cell) }}
|
|
|
</div>
|
|
|
<div class="loc-group">
|
|
|
@@ -34,11 +52,22 @@
|
|
|
>
|
|
|
{{ cell.locationId }}
|
|
|
</div>
|
|
|
- <div v-if="cell.categoryMismatch" class="location-attribute-tag">热度编号异常</div>
|
|
|
- <div v-if="hasAbnormalLocationAttribute(cell)" class="location-attribute-tag">
|
|
|
+ <div
|
|
|
+ v-if="cell.categoryMismatch"
|
|
|
+ class="location-attribute-tag"
|
|
|
+ >
|
|
|
+ 热度编号异常
|
|
|
+ </div>
|
|
|
+ <div
|
|
|
+ v-if="hasAbnormalLocationAttribute(cell)"
|
|
|
+ class="location-attribute-tag"
|
|
|
+ >
|
|
|
{{ getLocationAttributeLabel(cell) }}
|
|
|
</div>
|
|
|
- <div v-if="cell.containerCode" class="container-code">
|
|
|
+ <div
|
|
|
+ v-if="cell.containerCode"
|
|
|
+ class="container-code"
|
|
|
+ >
|
|
|
{{ cell.containerCode }}
|
|
|
</div>
|
|
|
</div>
|
|
|
@@ -55,7 +84,11 @@
|
|
|
class="cell-tooltip"
|
|
|
:style="tooltipStyle"
|
|
|
>
|
|
|
- <div v-for="(line, index) in tooltipLines" :key="index" class="cell-tooltip-line">
|
|
|
+ <div
|
|
|
+ v-for="(line, index) in tooltipLines"
|
|
|
+ :key="index"
|
|
|
+ class="cell-tooltip-line"
|
|
|
+ >
|
|
|
{{ line }}
|
|
|
</div>
|
|
|
</div>
|
|
|
@@ -354,36 +387,59 @@ const gridStyle = computed(() => {
|
|
|
if (!gridMetrics.value) return {}
|
|
|
|
|
|
const gap = 2
|
|
|
- const horizontalPadding = 24
|
|
|
- const verticalPadding = 12
|
|
|
+ const horizontalPadding = 12
|
|
|
+ const verticalPadding = 8
|
|
|
const availableWidth = Math.max(wrapperSize.value.width - horizontalPadding, 0)
|
|
|
const availableHeight = Math.max(wrapperSize.value.height - verticalPadding, 0)
|
|
|
|
|
|
- const cellWidth =
|
|
|
+ const minX = gridBounds.value?.minX ?? 0
|
|
|
+ const minY = gridBounds.value?.minY ?? 0
|
|
|
+ const rowHasLocation = Array.from({ length: gridMetrics.value.rows }, () => false)
|
|
|
+ const colHasLocation = Array.from({ length: gridMetrics.value.cols }, () => false)
|
|
|
+ const isLocation = (cell: MapCell) => !('type' in cell)
|
|
|
+ for (const cell of gridData.value) {
|
|
|
+ if (!isLocation(cell)) continue
|
|
|
+ const rowIndex = cell.gridRow - minX
|
|
|
+ const colIndex = cell.gridCol - minY
|
|
|
+ if (rowIndex >= 0 && rowIndex < rowHasLocation.length) rowHasLocation[rowIndex] = true
|
|
|
+ if (colIndex >= 0 && colIndex < colHasLocation.length) colHasLocation[colIndex] = true
|
|
|
+ }
|
|
|
+
|
|
|
+ const compressedScale = 2 / 3
|
|
|
+ const rowScales = rowHasLocation.map((hasLocation) => (hasLocation ? 1 : compressedScale))
|
|
|
+ const colScales = colHasLocation.map((hasLocation) => (hasLocation ? 1 : compressedScale))
|
|
|
+ const rowScaleSum = rowScales.reduce((total, scale) => total + scale, 0)
|
|
|
+ const colScaleSum = colScales.reduce((total, scale) => total + scale, 0)
|
|
|
+
|
|
|
+ const baseCellWidth =
|
|
|
availableWidth > 0
|
|
|
- ? Math.max((availableWidth - (gridMetrics.value.cols - 1) * gap) / gridMetrics.value.cols, 28)
|
|
|
+ ? Math.max((availableWidth - (gridMetrics.value.cols - 1) * gap) / colScaleSum, 28)
|
|
|
: 72
|
|
|
- const cellHeight =
|
|
|
+ const baseCellHeight =
|
|
|
availableHeight > 0
|
|
|
- ? Math.max(
|
|
|
- (availableHeight - (gridMetrics.value.rows - 1) * gap) / gridMetrics.value.rows,
|
|
|
- 24
|
|
|
- )
|
|
|
+ ? Math.max((availableHeight - (gridMetrics.value.rows - 1) * gap) / rowScaleSum, 24)
|
|
|
: 60
|
|
|
- const compactSize = Math.min(cellWidth, cellHeight)
|
|
|
+ const compactSize = Math.min(baseCellWidth, baseCellHeight)
|
|
|
|
|
|
const showBadge = compactSize > 38 ? 'inline-flex' : 'none'
|
|
|
const showGroup = compactSize > 58 ? 'block' : 'none'
|
|
|
- const badgeFontSize = compactSize <= 42 ? 7 : compactSize <= 56 ? 8 : 9
|
|
|
- const textFontSize = compactSize <= 56 ? 8 : 9
|
|
|
- const idFontSize = compactSize <= 34 ? 8 : compactSize <= 42 ? 9 : compactSize <= 56 ? 9 : 10
|
|
|
+ const badgeFontSize = Math.max(compactSize <= 42 ? 7 : compactSize <= 56 ? 8 : 9, 8)
|
|
|
+ const textFontSize = Math.max(compactSize <= 56 ? 8 : 9, 8)
|
|
|
+ const idFontSize = Math.max(
|
|
|
+ compactSize <= 34 ? 8 : compactSize <= 42 ? 9 : compactSize <= 56 ? 9 : 10,
|
|
|
+ 9
|
|
|
+ )
|
|
|
const contentGap = compactSize <= 42 ? 1 : 3
|
|
|
- const contentPadding = compactSize <= 42 ? 1 : 3
|
|
|
+ const contentPadding = Math.max(compactSize <= 42 ? 1 : 3, 1)
|
|
|
const groupBorderWidth = compactSize <= 34 ? 1 : 2
|
|
|
|
|
|
return {
|
|
|
- gridTemplateColumns: `repeat(${gridMetrics.value.cols}, ${cellWidth.toFixed(2)}px)`,
|
|
|
- gridAutoRows: `${cellHeight.toFixed(2)}px`,
|
|
|
+ gridTemplateColumns: colScales
|
|
|
+ .map((scale) => `${(baseCellWidth * scale).toFixed(2)}px`)
|
|
|
+ .join(' '),
|
|
|
+ gridTemplateRows: rowScales
|
|
|
+ .map((scale) => `${(baseCellHeight * scale).toFixed(2)}px`)
|
|
|
+ .join(' '),
|
|
|
'--cell-badge-font-size': `${badgeFontSize}px`,
|
|
|
'--cell-group-font-size': `${textFontSize}px`,
|
|
|
'--cell-id-font-size': `${idFontSize}px`,
|
|
|
@@ -893,7 +949,7 @@ onBeforeUnmount(() => {
|
|
|
.map-grid {
|
|
|
display: grid;
|
|
|
gap: 2px;
|
|
|
- padding: 0 12px 12px;
|
|
|
+ padding: 0 6px 8px;
|
|
|
box-sizing: border-box;
|
|
|
width: 100%;
|
|
|
height: 100%;
|
|
|
@@ -1096,6 +1152,7 @@ onBeforeUnmount(() => {
|
|
|
color: var(--special-label);
|
|
|
letter-spacing: 1px;
|
|
|
user-select: none;
|
|
|
+ padding: 1px;
|
|
|
}
|
|
|
|
|
|
.special-cell-label-elevator {
|