Files
JY1.0/docs/warehouse-visualization-preview.html

483 lines
15 KiB
HTML
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.
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>立库可视化功能截图预览</title>
<style>
* { box-sizing: border-box; }
body {
margin: 0;
font-family: "Microsoft YaHei", Arial, sans-serif;
background: #eef2f7;
color: #303133;
}
.app-container { padding: 20px; }
.card {
height: 850px;
background: #fff;
border: 1px solid #e4e7ed;
box-shadow: 0 2px 12px rgba(0,0,0,.06);
}
.tab {
height: 44px;
border-bottom: 1px solid #dcdfe6;
background: #f5f7fa;
display: flex;
align-items: end;
padding-left: 0;
}
.tab span {
display: inline-flex;
align-items: center;
height: 44px;
padding: 0 22px;
background: #fff;
border-right: 1px solid #dcdfe6;
border-top: 2px solid #409eff;
font-size: 14px;
color: #409eff;
}
.toolbar {
margin: 7px 0;
padding: 0 12px;
display: flex;
align-items: center;
gap: 10px;
flex-wrap: wrap;
height: 42px;
}
.toolbar label { font-size: 13px; color: #000; }
.select, .button, .switch {
height: 32px;
border-radius: 4px;
font-size: 13px;
display: inline-flex;
align-items: center;
}
.select {
width: 120px;
border: 1px solid #dcdfe6;
padding: 0 10px;
justify-content: space-between;
color: #606266;
background: #fff;
}
.select::after { content: "⌄"; color: #909399; }
.button {
border: 1px solid transparent;
padding: 0 12px;
color: #fff;
gap: 4px;
}
.primary { background: #409eff; }
.default { background: #fff; color: #606266; border-color: #dcdfe6; }
.success { background: #67c23a; }
.switch {
margin-left: 10px;
gap: 8px;
color: #606266;
}
.switch-track {
width: 42px;
height: 22px;
border-radius: 12px;
background: #409eff;
position: relative;
}
.switch-track::after {
content: "";
position: absolute;
right: 2px;
top: 2px;
width: 18px;
height: 18px;
border-radius: 50%;
background: #fff;
}
.stats {
display: grid;
grid-template-columns: repeat(6, 1fr);
gap: 10px;
margin: 10px 12px;
}
.stat {
border: 1px solid #ebeef5;
border-radius: 4px;
text-align: center;
padding: 10px 0;
box-shadow: 0 2px 8px rgba(0,0,0,.04);
}
.stat .label { color: #909399; font-size: 12px; }
.stat .value { font-size: 20px; font-weight: bold; margin-top: 4px; }
.legend {
margin-bottom: 15px;
display: flex;
align-items: center;
justify-content: center;
gap: 20px;
flex-wrap: wrap;
}
.legend-item {
display: flex;
align-items: center;
font-size: 12px;
}
.legend-color {
width: 20px;
height: 20px;
border-radius: 4px;
border: 1px solid #ddd;
margin-right: 5px;
}
.warehouse-area {
height: 600px;
overflow: auto;
border: 1px solid #e4e7ed;
border-radius: 4px;
margin: 0 12px;
padding: 15px;
background: #f5f7fa;
}
.warehouse-group {
margin-bottom: 30px;
padding: 15px;
background: white;
border-radius: 4px;
box-shadow: 0 2px 4px rgba(0,0,0,.1);
}
.group-title {
text-align: center;
margin-bottom: 10px;
color: #303133;
font-weight: bold;
background: #e8f4fd;
padding: 5px;
border-radius: 4px;
}
table {
width: 100%;
min-width: 1200px;
border-collapse: collapse;
margin: 0 auto;
table-layout: fixed;
}
th, td {
border: 1px solid #e4e7ed;
text-align: center;
height: 40px;
min-width: 40px;
font-size: 12px;
position: relative;
}
th {
background: #f5f7fa;
font-weight: bold;
color: #303133;
}
.row-layer-header, .row-layer-cell {
width: 80px;
min-width: 80px;
background: #e8f4fd;
color: #2196f3;
font-weight: bold;
}
.row-layer-cell { background: #f5f7fa; color: #303133; }
.highlight-row .row-layer-cell {
background: #bbdefb;
color: #1976d2;
}
.highlight-col { background: #bbdefb; color: #1976d2; }
.cell {
cursor: pointer;
font-size: 14px;
font-weight: bold;
transition: all .2s;
}
.cell:hover {
transform: scale(1.08);
z-index: 2;
box-shadow: 0 2px 8px rgba(0,0,0,.2);
}
.status-2 { background: #4caf50; color: #fff; }
.status-1 { background: #ff9800; color: #fff; }
.status-0 { background: #e0e0e0; color: #666; }
.status-9 { background: skyblue; color: #fff; }
.selected {
box-shadow: 0 0 0 2px #2196f3 inset;
outline: 2px solid #2196f3;
outline-offset: -2px;
}
.tooltip {
position: absolute;
bottom: calc(100% + 6px);
left: 50%;
transform: translateX(-50%);
background: rgba(0,0,0,.82);
color: white;
padding: 4px 8px;
border-radius: 4px;
font-size: 12px;
white-space: nowrap;
z-index: 4;
font-weight: normal;
}
.pagination {
text-align: center;
margin-top: 10px;
color: #606266;
font-size: 13px;
}
.page-box {
display: inline-flex;
align-items: center;
gap: 8px;
border: 1px solid #ebeef5;
padding: 6px 10px;
border-radius: 4px;
background: #fff;
}
.page-num {
min-width: 28px;
height: 28px;
border-radius: 3px;
display: inline-flex;
align-items: center;
justify-content: center;
}
.page-current { background: #409eff; color: #fff; }
.modal-backdrop {
display: none;
position: fixed;
inset: 0;
background: rgba(0,0,0,.2);
align-items: center;
justify-content: center;
z-index: 10;
}
body.show-detail #detailModal,
body.show-material #materialModal { display: flex; }
.dialog {
background: #fff;
border-radius: 2px;
box-shadow: 0 4px 18px rgba(0,0,0,.18);
overflow: hidden;
}
.detail-dialog { width: 500px; }
.material-dialog { width: 941px; }
.dialog-title {
height: 54px;
display: flex;
align-items: center;
justify-content: center;
font-size: 18px;
border-bottom: 1px solid #ebeef5;
}
.dialog-body { padding: 20px; }
.detail-box {
padding: 10px;
background: #f5f7fa;
border-radius: 4px;
line-height: 1.7;
}
.dialog-footer {
border-top: 1px solid #ebeef5;
padding: 10px 20px;
text-align: right;
}
.close-button {
height: 32px;
padding: 0 15px;
border: 1px solid #dcdfe6;
background: #fff;
border-radius: 4px;
color: #606266;
}
.material-table {
min-width: 0;
table-layout: auto;
font-size: 13px;
}
.material-table th {
color: #606266;
height: 38px;
background: #f5f7fa;
}
.material-table td { height: 46px; }
.qty { color: #67c23a; font-weight: bold; }
.lockqty { color: #e6a23c; font-weight: bold; }
.unit { font-size: 10px; color: #909399; }
.mode-icon .cell { font-size: 18px; }
.mode-icon .text-symbol { display: none; }
.mode-icon .icon-symbol { display: inline; }
.icon-symbol { display: none; }
.callout {
position: absolute;
right: 30px;
top: 105px;
background: #fffbe6;
border: 1px solid #ffe58f;
color: #6b4c00;
padding: 8px 12px;
border-radius: 4px;
font-size: 13px;
z-index: 5;
display: none;
}
body.show-filter-tip .callout { display: block; }
</style>
</head>
<body>
<div class="app-container">
<div class="card">
<div class="tab"><span>立库可视化</span></div>
<div class="toolbar">
<label>库位筛选</label>
<div class="select" id="aisleSelect">第一巷道</div>
<div class="select" id="rowSelect">03-01</div>
<div class="button primary">🔍 搜索</div>
<div class="button default">↻ 重置</div>
<div class="button success">⟲ 刷新数据</div>
<div class="switch"><span id="modeText">显示文字</span><span class="switch-track"></span></div>
</div>
<div class="callout">筛选区支持按巷道重新取数、按行-层收窄视图,并可切换文字/图标显示模式。</div>
<div class="stats">
<div class="stat"><div class="label">总库位数</div><div class="value">384</div></div>
<div class="stat"><div class="label">有物料有托盘</div><div class="value" style="color:#4caf50">138</div></div>
<div class="stat"><div class="label">有托盘无物料</div><div class="value" style="color:#ff9800">76</div></div>
<div class="stat"><div class="label">空闲库位</div><div class="value" style="color:#9e9e9e">154</div></div>
<div class="stat"><div class="label">使用率</div><div class="value" style="color:#2196f3">55.7%</div></div>
<div class="stat"><div class="label">数据行数</div><div class="value" style="color:#9c27b0">8</div></div>
</div>
<div class="legend">
<div class="legend-item"><div class="legend-color" style="background:#4caf50"></div>有物料有托盘 (物)</div>
<div class="legend-item"><div class="legend-color" style="background:#ff9800"></div>有托盘无物料 (盘)</div>
<div class="legend-item"><div class="legend-color" style="background:#e0e0e0"></div>空库位 (空)</div>
<div class="legend-item"><div class="legend-color" style="background:#bbdefb;border:2px solid #2196f3"></div>选中库位</div>
</div>
<div class="warehouse-area">
<div class="warehouse-group">
<div class="group-title">立库组</div>
<table id="warehouseTable">
<thead>
<tr id="headRow"><th class="row-layer-header">行-层</th></tr>
</thead>
<tbody id="tableBody"></tbody>
</table>
</div>
<div style="text-align:center;margin-top:20px;color:#909399;font-size:12px">显示 8 行数据</div>
</div>
<div class="pagination">
<div class="page-box">
<span>共 8 条</span>
<span>8条/页</span>
<span></span>
<span class="page-num page-current">1</span>
<span></span>
<span>前往 1 页</span>
</div>
</div>
</div>
</div>
<div class="modal-backdrop" id="detailModal">
<div class="dialog detail-dialog">
<div class="dialog-title">库位详情 03-08-01</div>
<div class="dialog-body">
<div class="detail-box">有托盘但无物料,需补充物料。当前库位已被识别为托盘占用状态,适合仓储人员核对托盘与物料绑定情况。</div>
</div>
<div class="dialog-footer"><button class="close-button">关闭</button></div>
</div>
</div>
<div class="modal-backdrop" id="materialModal">
<div class="dialog material-dialog">
<div class="dialog-title">库位信息 03-12-01</div>
<div class="dialog-body">
<table class="material-table">
<thead>
<tr>
<th>物料编号</th>
<th>物料名称</th>
<th>图号</th>
<th>型号</th>
<th>库存数量</th>
<th>锁定库存</th>
<th>批次</th>
</tr>
</thead>
<tbody>
<tr>
<td>02.009.001.0012</td>
<td>直线导轨组件</td>
<td>LRS3056-0312-01</td>
<td>HGW25CA</td>
<td><div class="qty">14.000</div><div class="unit"></div></td>
<td><div class="lockqty">2.000</div><div class="unit"></div></td>
<td>BATCH031201</td>
</tr>
<tr>
<td>02.009.001.0013</td>
<td>滑块组件</td>
<td>LRS3056-0312-02</td>
<td>HGW25CC</td>
<td><div class="qty">6.000</div><div class="unit"></div></td>
<td><div style="color:#909399">0.000</div><div class="unit"></div></td>
<td>BATCH031202</td>
</tr>
</tbody>
</table>
</div>
<div class="dialog-footer"><button class="close-button">关闭</button></div>
</div>
</div>
<script>
const columns = 48;
const rows = ['04-04','04-03','04-02','04-01','03-04','03-03','03-02','03-01'];
const statuses = [2,0,1,2,0,0,2,1,0,2,1,2,0,9,2,0,1,0,2,2,0,1,0,2,0,0,1,2,0,2,0,1,2,0,0,9,2,1,0,2,0,1,2,0,0,2,1,0];
const head = document.getElementById('headRow');
for (let c = 1; c <= columns; c++) {
const th = document.createElement('th');
th.textContent = c;
if (c === 12) th.className = 'highlight-col';
head.appendChild(th);
}
const tbody = document.getElementById('tableBody');
rows.forEach((row, rIndex) => {
const tr = document.createElement('tr');
if (row === '03-01') tr.className = 'highlight-row';
const rowCell = document.createElement('td');
rowCell.className = 'row-layer-cell';
rowCell.textContent = row;
tr.appendChild(rowCell);
for (let c = 1; c <= columns; c++) {
const status = statuses[(c + rIndex * 5) % statuses.length];
const td = document.createElement('td');
td.className = 'cell status-' + status;
if (row === '03-01' && c === 12) td.className += ' selected';
const text = status === 2 ? '物' : status === 1 ? '盘' : status === 9 ? '锁' : '空';
const icon = status === 2 ? '▣' : status === 1 ? '▤' : status === 9 ? '🔒' : '';
td.innerHTML = '<span class="text-symbol">' + text + '</span><span class="icon-symbol">' + icon + '</span>';
if (row === '03-01' && c === 12) {
const tip = document.createElement('span');
tip.className = 'tooltip';
tip.textContent = '有物料有托盘';
td.appendChild(tip);
}
tr.appendChild(td);
}
tbody.appendChild(tr);
});
const params = new URLSearchParams(location.search);
const shot = params.get('shot');
if (shot === 'filter') {
document.body.classList.add('show-filter-tip');
document.body.classList.add('mode-icon');
document.getElementById('modeText').textContent = '显示图标';
document.getElementById('aisleSelect').textContent = '第三巷道';
document.getElementById('rowSelect').textContent = '03-01';
}
if (shot === 'detail') document.body.classList.add('show-detail');
if (shot === 'material') document.body.classList.add('show-material');
</script>
</body>
</html>