Compare commits

...

3 Commits

Author SHA1 Message Date
jhd
20d2df9373 合并远程分支 2026-05-27 12:00:54 +08:00
jhd
6313be9c52 大屏判断逻辑修改 2026-05-27 11:54:52 +08:00
jhd
75f745cdb2 大屏判断逻辑修改 2026-05-27 10:58:17 +08:00

View File

@@ -77,12 +77,12 @@
已占用 <span class="legend-val">{{ statistics.occupied }}</span> 已占用 <span class="legend-val">{{ statistics.occupied }}</span>
</div> </div>
<div class="legend-item"> <div class="legend-item">
<span class="chart-dot maintenance"></span> <span class="chart-dot error"></span>
维护中 <span class="legend-val">{{ statistics.maintenance }}</span> 异常 <span class="legend-val">{{ statistics.error }}</span>
</div> </div>
<div class="legend-item"> <div class="legend-item">
<span class="chart-dot available"></span> <span class="chart-dot available"></span>
可用 <span class="legend-val">{{ statistics.available }}</span> 空闲 <span class="legend-val">{{ statistics.available }}</span>
</div> </div>
</div> </div>
</div> </div>
@@ -109,15 +109,15 @@
<div class="grid-legend"> <div class="grid-legend">
<div class="legend-item"> <div class="legend-item">
<span class="legend-dot available"></span> <span class="legend-dot available"></span>
<span>可用</span> <span>空闲</span>
</div> </div>
<div class="legend-item"> <div class="legend-item">
<span class="legend-dot occupied"></span> <span class="legend-dot occupied"></span>
<span>已占用</span> <span>已占用</span>
</div> </div>
<div class="legend-item"> <div class="legend-item">
<span class="legend-dot maintenance"></span> <span class="legend-dot error"></span>
<span>维护中</span> <span>异常</span>
</div> </div>
<div class="legend-item"> <div class="legend-item">
<span class="legend-dot has-coil-icon"></span> <span class="legend-dot has-coil-icon"></span>
@@ -138,24 +138,24 @@
v-for="wh in gridData[colNum].layer1" v-for="wh in gridData[colNum].layer1"
:key="wh.actualWarehouseId" :key="wh.actualWarehouseId"
class="grid-cell" class="grid-cell"
:class="[getStatusClass(wh), { 'has-coil': !!wh.coilCode }]" :class="[getStatusClass(wh), { 'has-coil': !!wh.currentCoilNo }]"
:style="cellStyle" :style="cellStyle"
@click="showDetail(wh)" @click="showDetail(wh)"
> >
<span class="cell-code">{{ wh.actualWarehouseCode }}</span> <span class="cell-code">{{ wh.actualWarehouseCode }}</span>
<span v-if="wh.coilCode" class="cell-coil-dot"></span> <span v-if="wh.currentCoilNo" class="cell-coil-dot"></span>
</div> </div>
<div v-if="gridData[colNum].layer1.length && gridData[colNum].layer2.length" class="layer-divider"></div> <div v-if="gridData[colNum].layer1.length && gridData[colNum].layer2.length" class="layer-divider"></div>
<div <div
v-for="wh in gridData[colNum].layer2" v-for="wh in gridData[colNum].layer2"
:key="wh.actualWarehouseId" :key="wh.actualWarehouseId"
class="grid-cell" class="grid-cell"
:class="[getStatusClass(wh), { 'has-coil': !!wh.coilCode }]" :class="[getStatusClass(wh), { 'has-coil': !!wh.currentCoilNo }]"
:style="cellStyle" :style="cellStyle"
@click="showDetail(wh)" @click="showDetail(wh)"
> >
<span class="cell-code">{{ wh.actualWarehouseCode }}</span> <span class="cell-code">{{ wh.actualWarehouseCode }}</span>
<span v-if="wh.coilCode" class="cell-coil-dot"></span> <span v-if="wh.currentCoilNo" class="cell-coil-dot"></span>
</div> </div>
</div> </div>
</div> </div>
@@ -187,7 +187,7 @@
</div> </div>
<div class="detail-row"> <div class="detail-row">
<span class="detail-label">钢卷编号</span> <span class="detail-label">钢卷编号</span>
<span class="detail-value" v-if="detailWarehouse.coilCode">📦 {{ detailWarehouse.coilCode }}</span> <span class="detail-value" v-if="detailWarehouse.currentCoilNo">📦 {{ detailWarehouse.currentCoilNo }}</span>
<span class="detail-value empty" v-else></span> <span class="detail-value empty" v-else></span>
</div> </div>
<div class="detail-row"> <div class="detail-row">
@@ -236,8 +236,8 @@ export default {
// 统计数据 // 统计数据
const statistics = reactive({ const statistics = reactive({
total: 0, total: 0,
error: 0,
occupied: 0, occupied: 0,
maintenance: 0,
available: 0, available: 0,
utilization: 0 utilization: 0
}) })
@@ -245,7 +245,7 @@ export default {
// 动画数字 // 动画数字
const animatedTotal = ref(0) const animatedTotal = ref(0)
const animatedOccupied = ref(0) const animatedOccupied = ref(0)
const animatedMaintenance = ref(0) const animatedError = ref(0)
const animatedAvailable = ref(0) const animatedAvailable = ref(0)
const animatedUtilization = ref(0) const animatedUtilization = ref(0)
@@ -491,8 +491,8 @@ export default {
animationDuration: 1200, animationDuration: 1200,
data: [ data: [
{ value: statistics.occupied || 0, name: '已占用', itemStyle: { color: '#7c63ff' } }, { value: statistics.occupied || 0, name: '已占用', itemStyle: { color: '#7c63ff' } },
{ value: statistics.maintenance || 0, name: '维护中', itemStyle: { color: '#ff6b6b' } }, { value: statistics.error || 0, name: '异常', itemStyle: { color: '#ff6b6b' } },
{ value: statistics.available || 0, name: '可用', itemStyle: { color: '#00ff88' } } { value: statistics.available || 0, name: '空闲', itemStyle: { color: '#00ff88' } }
] ]
}], }],
graphic: [ graphic: [
@@ -569,28 +569,26 @@ export default {
// 统计数据 — 与 getStatusClass 逻辑一一对应 // 统计数据 — 与 getStatusClass 逻辑一一对应
const total = warehouseList.value.length const total = warehouseList.value.length
const maintenance = warehouseList.value.filter(w =>
w.isEnabled === 0
).length
const occupied = warehouseList.value.filter(w => const occupied = warehouseList.value.filter(w =>
w.isEnabled !== 0 && w.coilCode w.isEnabled === 0 && w.currentCoilNo
).length ).length
const available = warehouseList.value.filter(w => const available = warehouseList.value.filter(w =>
w.isEnabled !== 0 && !w.coilCode w.isEnabled === 1 && !w.currentCoilNo
).length ).length
const error = total - occupied - available
const usable = occupied + available const usable = occupied + available
const utilization = usable > 0 ? Math.round((occupied / usable) * 100) : 0 const utilization = usable > 0 ? Math.round((occupied / usable) * 100) : 0
// 触发动画 // 触发动画
animateValue(animatedTotal.value, total, (val) => { animatedTotal.value = val }) animateValue(animatedTotal.value, total, (val) => { animatedTotal.value = val })
animateValue(animatedOccupied.value, occupied, (val) => { animatedOccupied.value = val }) animateValue(animatedOccupied.value, occupied, (val) => { animatedOccupied.value = val })
animateValue(animatedMaintenance.value, maintenance, (val) => { animatedMaintenance.value = val }) animateValue(animatedError.value, error, (val) => { animatedError.value = val })
animateValue(animatedAvailable.value, available, (val) => { animatedAvailable.value = val }) animateValue(animatedAvailable.value, available, (val) => { animatedAvailable.value = val })
animateValue(animatedUtilization.value, utilization, (val) => { animatedUtilization.value = val }) animateValue(animatedUtilization.value, utilization, (val) => { animatedUtilization.value = val })
statistics.total = total statistics.total = total
statistics.occupied = occupied statistics.occupied = occupied
statistics.maintenance = maintenance statistics.error = error
statistics.available = available statistics.available = available
statistics.utilization = utilization statistics.utilization = utilization
updateChart() updateChart()
@@ -603,39 +601,52 @@ export default {
// 获取状态文本 // 获取状态文本
const getStatusText = (row) => { const getStatusText = (row) => {
// isEnabled: 0=否, 1=是 if (row.isEnabled === 0 && row.currentCoilNo) {
// coilCode: 有值表示已存放钢卷
if (row.isEnabled === 0) {
return '维护中'
} else if (row.coilCode) {
return '已占用' return '已占用'
} else if (row.isEnabled === 1 && !row.currentCoilNo) {
return '空闲'
} else { } else {
return '可用' return '异常'
} }
} }
// 获取状态样式类 // 获取状态样式类
const getStatusClass = (row) => { const getStatusClass = (row) => {
if (row.isEnabled === 0) { if (row.isEnabled === 0 && row.currentCoilNo) {
return 'maintenance'
} else if (row.coilCode) {
return 'occupied' return 'occupied'
} else { } else if (row.isEnabled === 1 && !row.currentCoilNo) {
return 'available' return 'available'
} else {
return 'error'
} }
} }
// 解析库位编码: F2A101-01-1 → { column: 101, row: 1, layer: 1 } // 解析库位编码:支持三级编码 F2B101-01-1 和四级编码 F2B3-X38-2
const parseWarehouseCode = (code) => { const parseWarehouseCode = (code) => {
if (!code) return null if (!code) return null
const reg = /^([A-Za-z0-9]{3})([^-]+)-(\d{2})-(\d+)$/ // 先尝试四级编码 F2B3-X38-2
const match = code.match(reg) const reg4 = /^([A-Za-z0-9]{3})([^-]+)-X(\d{2})-(\d+)$/
if (!match) return null const match4 = code.match(reg4)
return { if (match4) {
column: Number(match[2]), return {
row: Number(match[3]), level: 4,
layer: match[4] column: Number(match4[2]),
row: Number(match4[3]),
layer: match4[4]
}
} }
// 再尝试三级编码 F2B101-01-1
const reg3 = /^([A-Za-z0-9]{3})([^-]+)-(\d{2})-(\d+)$/
const match3 = code.match(reg3)
if (match3) {
return {
level: 3,
column: Number(match3[2]),
row: Number(match3[3]),
layer: match3[4]
}
}
return null
} }
// 构建网格数据结构:按列分组 → 按层分行 // 构建网格数据结构:按列分组 → 按层分行
@@ -701,7 +712,7 @@ export default {
statistics, statistics,
animatedTotal, animatedTotal,
animatedOccupied, animatedOccupied,
animatedMaintenance, animatedError,
animatedAvailable, animatedAvailable,
animatedUtilization, animatedUtilization,
getParticleStyle, getParticleStyle,
@@ -1142,7 +1153,7 @@ export default {
} }
.chart-dot.occupied { background: #7c63ff; } .chart-dot.occupied { background: #7c63ff; }
.chart-dot.maintenance { background: #ff6b6b; } .chart-dot.error { background: #ff6b6b; }
.chart-dot.available { background: #00ff88; } .chart-dot.available { background: #00ff88; }
.header-badge { .header-badge {
@@ -1229,7 +1240,7 @@ export default {
.legend-dot.available { background: #00ff88; } .legend-dot.available { background: #00ff88; }
.legend-dot.occupied { background: #7c63ff; } .legend-dot.occupied { background: #7c63ff; }
.legend-dot.maintenance { background: #ff6b6b; } .legend-dot.error { background: #ff6b6b; }
.legend-dot.has-coil-icon { .legend-dot.has-coil-icon {
background: transparent; background: transparent;
color: #00d4ff; color: #00d4ff;
@@ -1299,7 +1310,7 @@ export default {
box-shadow: 0 0 8px rgba(124, 99, 255, 0.15); box-shadow: 0 0 8px rgba(124, 99, 255, 0.15);
} }
.grid-cell.maintenance { .grid-cell.error {
background: rgba(255, 107, 107, 0.15); background: rgba(255, 107, 107, 0.15);
border-color: rgba(255, 107, 107, 0.3); border-color: rgba(255, 107, 107, 0.3);
box-shadow: 0 0 8px rgba(255, 107, 107, 0.1); box-shadow: 0 0 8px rgba(255, 107, 107, 0.1);
@@ -1328,7 +1339,7 @@ export default {
box-shadow: 0 0 20px rgba(124, 99, 255, 0.5); box-shadow: 0 0 20px rgba(124, 99, 255, 0.5);
} }
.grid-cell:hover.maintenance { .grid-cell:hover.error {
box-shadow: 0 0 20px rgba(255, 107, 107, 0.5); box-shadow: 0 0 20px rgba(255, 107, 107, 0.5);
} }
@@ -1415,7 +1426,7 @@ export default {
border: 1px solid rgba(0, 255, 136, 0.3); border: 1px solid rgba(0, 255, 136, 0.3);
} }
.detail-dialog .detail-status.maintenance { .detail-dialog .detail-status.error {
background: rgba(255, 107, 107, 0.2); background: rgba(255, 107, 107, 0.2);
color: #ff6b6b; color: #ff6b6b;
border: 1px solid rgba(255, 107, 107, 0.3); border: 1px solid rgba(255, 107, 107, 0.3);