Files
aerologic-app/documents/5.5寸手持端设计文件/08_进港仓库/进港仓库.html
YANG JIANKUAN db062c8ee3 feat: 完成国际出港移库/出库交接页面5.5寸手机端适配
- 落地手机端双形态适配框架:同名布局+资源限定符(layout/手机、
  layout-sw600dp/平板)自动切换,DeviceUtil 设备形态判定,7个
  手机版公共组件(PhoneSearchBar/StatusTab/DataLayout/FilterPanel/
  BottomBar/StatBox/KvItem)
- 完成「国际出港移库」「国际出港出库交接」两页手机端适配,新增
  各自详情页(IntExpMoveDetailActivity/IntExpOutHandoverDetailActivity)
- 手机端首页菜单接入"出港移库""出库交接"入口
- 修复手机端进入页面先横屏后转竖屏的闪屏问题:Manifest 全项目
  192 处改为 screenOrientation="unspecified",由 BaseActivity
  按设备形态运行时锁定方向
- 修复该方案的中间版本在平板端引入的回归(先竖后横 + UI放大1.6倍)
- AutoSize 补充手机竖屏 390×844 设计基准
- 修复 CHANGELOG.md 因脚本异常导致的内容重复损坏(膨胀至12万行),
  恢复正常结构并补充本次变更记录

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-29 14:18:29 +08:00

924 lines
44 KiB
HTML
Raw Permalink 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 content="width=device-width, initial-scale=1.0" name="viewport"/>
<title>进港仓库</title>
<script src="https://modao.cc/agent-py/static/source/js/tailwindcss.js"></script>
<script src="https://modao.cc/agent-py/static/source/js/iconify-icon.min.js"></script>
<style>
@font-face {
font-family: 'PingFang SC';
src: local('PingFang SC');
}
body {
font-family: 'PingFang SC', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
background-color: #e5e7eb;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
margin: 0;
padding: 20px;
box-sizing: border-box;
}
/* 隐藏滚动条但保留功能 */
.hide-scrollbar::-webkit-scrollbar {
display: none;
}
.hide-scrollbar {
-ms-overflow-style: none;
scrollbar-width: none;
}
.status-tag {
padding: 2px 8px;
border-radius: 4px;
font-size: 11px;
font-weight: 500;
}
.tag-occupied { background-color: #dcfce7; color: #22c55e; } /* 已离港 - 绿色 */
.tag-available { background-color: #dcfce7; color: #22c55e; } /* 已离港 - 绿色 */
.tag-repair { background-color: #fce7e7; color: #ef4444; } /* 离港 - 红色 */
/* 页面切换动画 */
.page {
position: absolute;
inset: 0;
transition: transform 0.3s ease-in-out;
background-color: #f3f4f6;
display: flex;
flex-direction: column;
overflow-y: auto;
-ms-overflow-style: none;
scrollbar-width: none;
}
.page::-webkit-scrollbar {
display: none;
}
.page-hidden-right { transform: translateX(100%); }
.page-hidden-left { transform: translateX(-100%); }
/* 统一的深蓝色调 */
.bg-header-blue { background-color: #2563EB; }
/* 标签页样式 */
.tab-item {
position: relative;
padding: 12px 0;
color: #999;
font-size: 14px;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
flex: 1;
text-align: center;
}
.tab-item.active {
color: #2563eb;
font-weight: bold;
}
.tab-item::after {
content: '';
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
width: 0;
height: 2px;
background-color: #2563eb;
transition: width 0.3s ease;
}
.tab-item.active::after {
width: 40%;
}
/* ========== 筛选弹窗样式 提升层级+动画稳定 ========== */
.filter-overlay {
position: absolute;
inset: 0;
background-color: rgba(0,0,0,0.4);
z-index: 9999;
opacity: 0;
visibility: hidden;
transition: opacity 0.25s ease, visibility 0.25s ease;
}
.filter-overlay.show {
opacity: 1;
visibility: visible;
}
.filter-sheet {
position: absolute;
left: 0;
right: 0;
bottom: 0;
background-color: #fff;
border-top-left-radius: 20px;
border-top-right-radius: 20px;
padding: 20px;
z-index: 10000;
transform: translateY(100%);
transition: transform 0.25s ease-out;
max-height: 80vh;
overflow-y: auto;
}
.filter-sheet.show {
transform: translateY(0);
}
/* 筛选输入框统一样式 */
.filter-input {
width: 100%;
height: 40px;
padding: 0 12px;
background: #f3f4f6;
border: 1px solid #e5e7eb;
border-radius: 8px;
font-size: 14px;
outline: none;
box-sizing: border-box;
}
.filter-input:focus {
border-color: #2563EB;
}
/* 下拉框箭头浅灰色 + 全浏览器兼容修复 */
select.filter-input {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='%239ca3af' viewBox='0 0 16 16'%3E%3Cpath d='M8 11L3 6h10l-5 5z'/%3E%3C/svg%3E");
background-repeat: no-repeat;
background-position: right 12px center;
background-size: 16px;
padding-right: 36px;
}
/* 清除IE默认下拉箭头 */
select.filter-input::-ms-expand {
display: none;
}
@keyframes scan {
0% { top: 0; }
100% { top: 100%; }
}
.scan-line {
animation: scan 2s linear infinite;
}
.custom-scrollbar::-webkit-scrollbar {
display: none;
}
.bottom-drawer {
transition: transform 0.3s ease-in-out;
}
</style>
</head>
<body>
<div class="w-[375px] h-[812px] bg-[#F3F4F6] overflow-hidden flex flex-col relative shadow-2xl rounded-[40px] border-[8px] border-gray-800">
<!-- 状态栏 -->
<div class="h-6 w-full bg-[#2563EB] flex justify-between items-center px-6 text-white text-xs pt-1">
<span>09:41</span>
<div class="flex items-center gap-1">
<iconify-icon icon="material-symbols:signal-cellular-4-bar-rounded"></iconify-icon>
<iconify-icon icon="material-symbols:wifi"></iconify-icon>
<iconify-icon icon="material-symbols:battery-full-rounded"></iconify-icon>
</div>
</div>
<!-- 筛选弹窗容器 移到最外层,层级提升 -->
<div class="filter-overlay" id="filterOverlay"></div>
<div class="filter-sheet" id="filterSheet">
<!-- 顶部标题栏 -->
<div class="relative flex items-center justify-center mb-6">
<button class="absolute right-0 top-0 text-gray-400" onclick="closeFilter()">
<iconify-icon class="text-2xl" icon="mdi:close"></iconify-icon>
</button>
<h2 class="text-[18px] font-bold text-gray-900">筛选条件</h2>
</div>
<!-- 筛选表单区域 -->
<div class="space-y-4 mb-7">
<!-- 1.航班日期 -->
<div>
<label class="block text-[14px] text-gray-700 mb-1.5">航班日期</label>
<div class="flex items-center bg-white border border-gray-200 rounded-lg h-10 px-3 cursor-pointer">
<input class="flex-1 text-[14px] text-gray-800 placeholder-gray-400 outline-none bg-transparent" placeholder="请选择航班日期" readonly="" type="text"/>
<iconify-icon class="text-gray-500 text-[14px] flex-none" icon="mdi:calendar" width="18"></iconify-icon>
</div>
</div>
<!-- 2.航班号 -->
<div>
<label class="block text-[14px] text-gray-700 mb-1.5">航班号</label>
<div class="flex items-center bg-white border border-gray-200 rounded-lg h-10 px-3">
<input class="flex-1 text-[14px] text-gray-800 placeholder-gray-400 outline-none bg-transparent" placeholder="请输入航班号" type="text" id="filterFlightNo">
</div>
</div>
<!-- 3.代理 -->
<div>
<label class="block text-[14px] text-gray-700 mb-1.5">代理</label>
<div class="flex items-center bg-white border border-gray-200 rounded-lg h-10 px-3 cursor-pointer">
<input class="flex-1 text-[14px] text-gray-800 placeholder-gray-400 outline-none bg-transparent" placeholder="请选择代理" readonly="" type="text"/>
<iconify-icon class="text-gray-500 text-[14px] flex-none" icon="mdi:chevron-down" width="18"></iconify-icon>
</div>
</div>
<!-- 4.特码 -->
<div>
<label class="block text-[14px] text-gray-700 mb-1.5">特码</label>
<div class="flex items-center bg-white border border-gray-200 rounded-lg h-10 px-3 cursor-pointer">
<input class="flex-1 text-[14px] text-gray-800 placeholder-gray-400 outline-none bg-transparent" placeholder="请选择特码" readonly="" type="text"/>
<iconify-icon class="text-gray-500 text-[14px] flex-none" icon="mdi:chevron-down" width="18"></iconify-icon>
</div>
</div>
<!-- 5.始发站 -->
<div>
<label class="block text-[14px] text-gray-700 mb-1.5">始发站</label>
<div class="flex items-center bg-white border border-gray-200 rounded-lg h-10 px-3">
<input class="flex-1 text-[14px] text-gray-800 placeholder-gray-400 outline-none bg-transparent" placeholder="请输入始发站" type="text" id="filterOrigin">
</div>
</div>
<!-- 6.运单类型 -->
<div>
<label class="block text-[14px] text-gray-700 mb-1.5">运单类型</label>
<div class="flex items-center bg-white border border-gray-200 rounded-lg h-10 px-3 cursor-pointer">
<input class="flex-1 text-[14px] text-gray-800 placeholder-gray-400 outline-none bg-transparent" placeholder="请选择运单类型" readonly="" type="text"/>
<iconify-icon class="text-gray-500 text-[14px] flex-none" icon="mdi:chevron-down" width="18"></iconify-icon>
</div>
</div>
<!-- 7.业务类型 -->
<div>
<label class="block text-[14px] text-gray-700 mb-1.5">业务类型</label>
<div class="flex items-center bg-white border border-gray-200 rounded-lg h-10 px-3 cursor-pointer">
<input class="flex-1 text-[14px] text-gray-800 placeholder-gray-400 outline-none bg-transparent" placeholder="请选择业务类型" readonly="" type="text"/>
<iconify-icon class="text-gray-500 text-[14px] flex-none" icon="mdi:chevron-down" width="18"></iconify-icon>
</div>
</div>
<!-- 8.品名(中) -->
<div>
<label class="block text-[14px] text-gray-700 mb-1.5">品名(中)</label>
<div class="flex items-center bg-white border border-gray-200 rounded-lg h-10 px-3">
<input class="flex-1 text-[14px] text-gray-800 placeholder-gray-400 outline-none bg-transparent" placeholder="请输入中文品名" type="text" id="filterCnName">
</div>
</div>
</div>
<!-- 底部操作按钮 -->
<div class="flex gap-3">
<button class="flex-1 h-11 bg-gray-100 text-gray-600 rounded-lg text-sm font-medium" onclick="resetFilter()">重置</button>
<button class="flex-1 h-11 bg-[#2563EB] text-white rounded-lg text-sm font-medium" onclick="confirmFilter()">确定</button>
</div>
</div>
<!-- 页面主容器 -->
<div class="flex-1 relative overflow-hidden">
<!-- 列表首页:进港仓库卡片页面 -->
<div class="page z-10" id="listPage">
<!-- 顶部导航栏 -->
<header class="bg-[#2563EB] h-14 flex items-center justify-between px-4 flex-none">
<button class="flex items-center text-white text-sm" onclick="showToast('返回上一级')">
<iconify-icon class="text-2xl" icon="mdi:chevron-left"></iconify-icon>
<span>返回</span>
</button>
<h1 class="text-white font-bold text-lg">进港仓库</h1>
<div class="w-12"></div>
</header>
<!-- 搜索区 -->
<section class="bg-[#F3F4F6] p-3 flex-none">
<div class="flex items-center gap-2">
<div class="flex-1 relative">
<iconify-icon class="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 text-lg" icon="mdi:magnify"></iconify-icon>
<input class="w-full bg-white rounded-full pl-10 pr-10 py-2.5 text-sm shadow-sm border border-gray-200 outline-none" onkeypress="if(event.keyCode==13) showToast('执行搜索')" placeholder="搜索运单号/航班号..." type="text"/>
<button class="absolute right-2 top-1/2 -translate-y-1/2 p-1 text-[#2563EB]" onclick="toggleScanOverlay(true)">
<iconify-icon class="text-lg" icon="mdi:qrcode-scan"></iconify-icon>
</button>
</div>
<button id="filterBtn" class="bg-white p-2.5 rounded-full shadow-sm border border-gray-200 text-[#2563EB] flex items-center justify-center flex-none" onclick="openFilter()">
<iconify-icon class="text-xl" icon="mdi:filter-variant"></iconify-icon>
</button>
</div>
</section>
<!-- 统计栏 -->
<section class="px-3 pb-3 flex justify-between gap-2 flex-none">
<div class="flex-1 bg-white rounded-lg px-3 py-2.5 shadow-sm border-l-[4px] border-l-[#2563EB]">
<div class="text-[11px] text-gray-500">总票数</div>
<div class="text-lg font-bold text-[#2563EB]">8</div>
</div>
<div class="flex-1 bg-white rounded-lg px-3 py-2.5 shadow-sm border-l-[4px] border-l-orange-500">
<div class="text-[11px] text-gray-500">未清仓</div>
<div class="text-lg font-bold text-orange-500">4</div>
</div>
<div class="flex-1 bg-white rounded-lg px-3 py-2.5 shadow-sm border-l-[4px] border-l-[#10B981]">
<div class="text-[11px] text-gray-500">已清仓</div>
<div class="text-lg font-bold text-[#10B981]">4</div>
</div>
</section>
<!-- 卡片列表容器 -->
<main class="flex-1 overflow-y-auto px-3 pb-4 custom-scrollbar" id="cardListContainer">
</main>
<!-- 扫码层 -->
<div class="absolute inset-0 z-50 bg-black hidden flex flex-col" id="scanOverlay">
<div class="p-6 flex justify-between items-center text-white">
<button onclick="toggleScanOverlay(false)">
<iconify-icon class="text-2xl" icon="mdi:close"></iconify-icon>
</button>
<span class="text-sm font-medium">扫描运单条码</span>
<button><iconify-icon class="text-2xl" icon="mdi:flashlight"></iconify-icon></button>
</div>
<div class="flex-1 flex flex-col items-center justify-center p-12">
<div class="w-64 h-64 border-2 border-[#2563EB] relative overflow-hidden rounded-lg">
<div class="absolute top-0 left-0 w-full h-0.5 bg-[#2563EB] shadow-[0_0_10px_#2563EB] scan-line"></div>
<div class="absolute top-0 left-0 w-6 h-6 border-t-4 border-l-4 border-[#2563EB]"></div>
<div class="absolute top-0 right-0 w-6 h-6 border-t-4 border-r-4 border-[#2563EB]"></div>
<div class="absolute bottom-0 left-0 w-6 h-6 border-b-4 border-l-4 border-[#2563EB]"></div>
<div class="absolute bottom-0 right-0 w-6 h-6 border-b-4 border-r-4 border-[#2563EB]"></div>
</div>
<p class="text-white text-xs mt-6 opacity-60 text-center px-4">将条码/二维码放入框内,即可自动扫描</p>
</div>
<div class="h-32 bg-black flex justify-center items-center gap-12 text-white">
<div class="flex flex-col items-center opacity-60">
<iconify-icon class="text-3xl" icon="mdi:image-outline"></iconify-icon>
<span class="text-[10px] mt-1">相册</span>
</div>
<div class="flex flex-col items-center">
<iconify-icon class="text-3xl" icon="mdi:keyboard-outline"></iconify-icon>
<span class="text-[10px] mt-1">手动输入</span>
</div>
</div>
</div>
<!-- Toast -->
<div class="absolute bottom-20 left-1/2 -translate-x-1/2 bg-black bg-opacity-80 text-white text-xs px-4 py-2 rounded-full hidden z-[60] whitespace-nowrap" id="toast">提示内容</div>
</div>
<!-- 进港货物页面(右滑弹出) -->
<div class="page z-20 page-hidden-right !bg-[#f0f2f5]" id="detailPage">
<!-- 头部 -->
<header class="bg-header-blue pt-2 pb-4 px-4 flex items-center relative flex-none">
<button class="flex items-center text-white text-sm absolute left-4 active:opacity-70" onclick="goBack()">
<iconify-icon class="text-xl" icon="mdi:chevron-left"></iconify-icon>
<span>返回</span>
</button>
<h1 class="mx-auto text-white font-bold text-lg">进港货物</h1>
<div class="absolute right-4 flex items-center">
<iconify-icon class="text-red-500 text-2xl" icon="mdi:file-document-edit-outline"></iconify-icon>
</div>
</header>
<!-- 标签页 -->
<div class="bg-white px-4 border-b border-gray-200 flex-none">
<div class="flex justify-around">
<div class="tab-item active cursor-pointer" onclick="switchTab(0)">运单信息</div>
<div class="tab-item cursor-pointer" onclick="switchTab(1)">仓库信息</div>
<div class="tab-item cursor-pointer" onclick="switchTab(2)">库位信息</div>
</div>
</div>
<!-- 详情内容区 -->
<div class="flex-1 overflow-y-auto hide-scrollbar">
<!-- 运单信息标签页 -->
<div class="tab-pane p-3 space-y-3" id="tab-content-0">
<!-- 卡片1基本信息 -->
<div class="bg-white rounded-xl shadow-sm border border-gray-100 overflow-hidden">
<div class="px-4 py-2.5 flex items-center border-b border-gray-100">
<div class="w-1 h-4 bg-blue-500 rounded-full inline-block mr-2"></div>
<span class="text-xs font-semibold text-gray-800" id="det-uldTitle">基本信息</span>
</div>
<div class="p-3 grid grid-cols-2 gap-2">
<!-- Row 1 -->
<div class="bg-gray-50/30 rounded-lg p-2.5 flex flex-col justify-center">
<span class="text-[10px] text-gray-500 text-[14px] mb-0.5">运单号</span>
<span class="text-xs text-gray-800 font-semibold truncate" id="det-billNo"></span>
</div>
<div class="bg-gray-50/30 rounded-lg p-2.5 flex flex-col justify-center">
<span class="text-[10px] text-gray-500 text-[14px] mb-0.5">代理人</span>
<span class="text-xs text-gray-800 font-semibold truncate" id="det-agent"></span>
</div>
<!-- Row 2 -->
<div class="bg-gray-50/30 rounded-lg p-2.5 flex flex-col justify-center">
<span class="text-[10px] text-gray-500 text-[14px] mb-0.5">特码</span>
<span class="text-xs text-gray-800 font-semibold truncate" id="det-code"></span>
</div>
<div class="bg-gray-50/30 rounded-lg p-2.5 flex flex-col justify-center">
<span class="text-[10px] text-gray-500 text-[14px] mb-0.5">承运人</span>
<span class="text-xs text-gray-800 font-semibold truncate" id="det-carrier"></span>
</div>
<!-- Row 3 -->
<div class="bg-gray-50/30 rounded-lg p-2.5 flex flex-col justify-center">
<span class="text-[10px] text-gray-500 text-[14px] mb-0.5">始发站</span>
<span class="text-xs text-gray-800 font-semibold truncate" id="det-route"></span>
</div>
<div class="bg-gray-50/30 rounded-lg p-2.5 flex flex-col justify-center">
<span class="text-[10px] text-gray-500 text-[14px] mb-0.5">中转站</span>
<span class="text-xs text-gray-800 font-semibold truncate" id="det-outboundTime"></span>
</div>
<!-- Row 4 -->
<div class="bg-gray-50/30 rounded-lg p-2.5 flex flex-col justify-center">
<span class="text-[10px] text-gray-500 text-[14px] mb-0.5">目的站</span>
<span class="text-xs text-gray-800 font-semibold truncate" id="det-dest"></span>
</div>
<div class="bg-gray-50/30 rounded-lg p-2.5 flex flex-col justify-center">
<span class="text-[10px] text-gray-500 text-[14px] mb-0.5">UN编号</span>
<span class="text-xs text-gray-800 font-semibold truncate" id="det-unNo"></span>
</div>
<!-- Row 5 -->
<div class="bg-gray-50/30 rounded-lg p-2.5 flex flex-col justify-center" id="det-lockStatus-container">
<span class="text-[10px] text-gray-500 text-[14px] mb-0.5" id="det-lockStatus-label">锁定状态</span>
<div id="det-lockStatus-wrapper">
<span class="text-xs font-semibold" id="det-lockStatus"></span>
</div>
</div>
<div class="bg-gray-50/30 rounded-lg p-2.5 flex flex-col justify-center">
<span class="text-[10px] text-gray-500 text-[14px] mb-0.5">包装类型</span>
<span class="text-xs text-gray-800 font-semibold truncate" id="det-packType"></span>
</div>
<!-- Row 6 -->
<div class="bg-gray-50/30 rounded-lg p-2.5 flex flex-col justify-center">
<span class="text-[10px] text-gray-500 text-[14px] mb-0.5">业务类型</span>
<span class="text-xs text-gray-800 font-semibold truncate" id="det-type"></span>
</div>
<div class="bg-gray-50/30 rounded-lg p-2.5 flex flex-col justify-center">
<span class="text-[10px] text-gray-500 text-[14px] mb-0.5">入库时间</span>
<span class="text-xs text-gray-800 font-semibold truncate" id="det-ciTime"></span>
</div>
<!-- Row 7 -->
<div class="bg-gray-50/30 rounded-lg p-2.5 flex flex-col justify-center col-span-2">
<span class="text-[10px] text-gray-500 text-[14px] mb-0.5">运单类型</span>
<span class="text-xs text-gray-800 font-semibold truncate" id="det-billType"></span>
</div>
<!-- Row 8 -->
<div class="bg-gray-50/30 rounded-lg p-2.5 flex flex-col justify-center col-span-2">
<span class="text-[10px] text-gray-500 text-[14px] mb-0.5">品名(中)</span>
<span class="text-xs text-gray-800 font-semibold truncate" id="det-itemNameCn"></span>
</div>
<!-- Row 9 -->
<div class="bg-gray-50/30 rounded-lg p-2.5 flex flex-col justify-center col-span-2">
<span class="text-[10px] text-gray-500 text-[14px] mb-0.5">品名(英)</span>
<span class="text-xs text-gray-800 font-semibold truncate" id="det-itemNameEn"></span>
</div>
<!-- Row 10 -->
<div class="bg-gray-50/30 rounded-lg p-2.5 flex flex-col justify-center col-span-2">
<span class="text-[10px] text-gray-500 text-[14px] mb-0.5">备注</span>
<span class="text-xs text-gray-800 font-semibold truncate" id="det-remark"></span>
</div>
</div>
</div>
<!-- 卡片2件重信息 -->
<div class="bg-white rounded-xl shadow-sm border border-gray-100 overflow-hidden">
<div class="px-4 py-2.5 flex items-center border-b border-gray-100">
<div class="w-1 h-4 bg-blue-500 rounded-full inline-block mr-2"></div>
<span class="text-xs font-semibold text-gray-800">件重信息</span>
</div>
<div class="p-3 grid grid-cols-3 gap-2">
<div class="bg-gray-50/30 rounded-lg p-2.5 flex flex-col justify-center">
<div class="text-[10px] text-gray-500 text-[14px] mb-0.5">运单件数</div>
<div class="text-xs text-gray-800 font-semibold" id="det-pieces"></div>
</div>
<div class="bg-gray-50/30 rounded-lg p-2.5 flex flex-col justify-center">
<div class="text-[10px] text-gray-500 text-[14px] mb-0.5">运单重量</div>
<div class="text-xs text-gray-800 font-semibold" id="det-weight"></div>
</div>
<div class="bg-gray-50/30 rounded-lg p-2.5 flex flex-col justify-center">
<div class="text-[10px] text-gray-500 text-[14px] mb-0.5">计费重量</div>
<div class="text-xs text-gray-800 font-semibold" id="det-calcWeight"></div>
</div>
<div class="bg-gray-50/30 rounded-lg p-2.5 flex flex-col justify-center">
<div class="text-[10px] text-gray-500 text-[14px] mb-0.5">入库件数</div>
<div class="text-xs text-gray-800 font-semibold" id="det-inPieces"></div>
</div>
<div class="bg-gray-50/30 rounded-lg p-2.5 flex flex-col justify-center">
<div class="text-[10px] text-gray-500 text-[14px] mb-0.5">入库重量</div>
<div class="text-xs text-gray-800 font-semibold" id="det-inWeight"></div>
</div>
<div class="bg-gray-50/30 rounded-lg p-2.5 flex flex-col justify-center opacity-0">
<div class="text-[10px] text-gray-500 text-[14px] mb-0.5"></div>
<div class="text-xs text-gray-800 font-semibold"></div>
</div>
</div>
</div>
<!-- 卡片3回执信息 -->
<div class="bg-white rounded-xl shadow-sm border border-gray-100 overflow-hidden">
<div class="px-4 py-2.5 flex items-center border-b border-gray-100">
<div class="w-1 h-4 bg-blue-500 rounded-full inline-block mr-2"></div>
<span class="text-xs font-semibold text-gray-800">回执信息</span>
</div>
<div class="p-3 grid grid-cols-3 gap-2">
<div class="bg-gray-50/30 rounded-lg p-2.5 flex flex-col justify-center">
<div class="text-[10px] text-gray-500 text-[14px] mb-0.5">原始舱单</div>
<div class="text-xs text-gray-800 font-semibold" id="det-originalManifest"></div>
</div>
<div class="bg-gray-50/30 rounded-lg p-2.5 flex flex-col justify-center">
<div class="text-[10px] text-gray-500 text-[14px] mb-0.5">理货报告</div>
<div class="text-xs text-gray-800 font-semibold" id="det-tallyReport"></div>
</div>
<div class="bg-gray-50/30 rounded-lg p-2.5 flex flex-col justify-center" id="det-customsRelease-container">
<div class="text-[10px] text-gray-500 text-[14px] mb-0.5">海关放行</div>
<div id="det-customsRelease-wrapper">
<div class="text-xs font-semibold" id="det-customsRelease"></div>
</div>
</div>
</div>
</div>
</div>
<!-- 仓库信息标签页 -->
<div class="tab-pane p-3 space-y-3 hidden" id="tab-content-1"></div>
<!-- 库位信息标签页 -->
<div class="tab-pane p-3 space-y-3 hidden" id="tab-content-2"></div>
</div>
</div>
</div>
</div>
<script>
// 运单详情数据源(用于进港货物渲染)
const uldData = {
'78133363396': {
billNo: '78133363396', agent: '中外运', code: 'DGR',
pieces: '444', weight: '555.0', type: '普通货物运输',
inPieces: '444', inWeight: '555.0', calcWeight: '555.0',
carrier: 'CA', route: 'LAX', packType: '纸箱',
billType: '国际进港(国际直航)', unNo: '—', dest: 'HFE',
itemNameCn: '电子元器件', itemNameEn: 'Electronic Components',
lockStatus: '未锁定', outboundTime: '—', remark: '需冷藏存储',
originalManifest: '01', tallyReport: '01', customsRelease: '11',ciTime: '2026-07-08 14:30:00',
warehouse: [
{ batch: '1', pieces: 200, weight: 300.0, flightDate: '2026-07-08', flightNo: 'CA1234',route: 'LAX',dest: 'HFE', time: '2026-07-08 14:30:00' },
{ batch: '2', pieces: 244, weight: 255.0, flightDate: '2026-07-09', flightNo: 'CA5678',route: 'LAX',dest: 'HFE', time: '2026-07-09 09:10:46' }
],
locations: [
{ id: 'A-01-001', inPerson: '张三', inTime: '2026-07-08 14:30', outPerson: '李四', outTime: '2026-07-09 10:00' },
{ id: 'B-02-005', inPerson: '王五', inTime: '2026-07-09 09:10', outPerson: '—', outTime: '—' }
]
},
'78133363397': {
billNo: '78133363397', agent: '徽远', code: 'PER',
pieces: '120', weight: '320.0', type: '普通货物运输',
inPieces: '120', inWeight: '320.0', calcWeight: '320.0',
carrier: 'MU', route: 'PVG-NRT', packType: '托盘',
billType: '国际进港(国际直航)', unNo: '—', dest: 'PVG',
itemNameCn: '服装', itemNameEn: 'Garments',
lockStatus: '未锁定', outboundTime: '—', remark: '易碎品,轻拿轻放',
originalManifest: '01', tallyReport: '01', customsRelease: '11',ciTime: '2026-07-08 14:30:00',
warehouse: [
{ batch: '3', pieces: 60, weight: 150.0, flightDate: '2026-07-07', flightNo: 'MU123', time: '2026-07-07 16:20:00' },
{ batch: '4', pieces: 60, weight: 170.0, flightDate: '2026-07-08', flightNo: 'MU456', time: '2026-07-08 11:00:00' }
],
locations: [
{ id: 'A-03-012', inPerson: '赵六', inTime: '2026-07-07 16:20', outPerson: '钱七', outTime: '2026-07-08 14:00' },
{ id: 'C-01-008', inPerson: '孙八', inTime: '2026-07-08 11:00', outPerson: '—', outTime: '—' }
]
},
'78133363398': {
billNo: '78133363398', agent: '中外运', code: 'NOR',
pieces: '268', weight: '780.0', type: '普通货物运输',
inPieces: '268', inWeight: '780.0', calcWeight: '780.0',
carrier: 'CZ', route: 'CAN-AMS', packType: '托盘',
billType: '国际进港(国际直航)', unNo: '—', dest: 'CAN',
itemNameCn: '机械设备', itemNameEn: 'Machinery Equipment',
lockStatus: '锁定', outboundTime: '2026-07-09 08:00', remark: '需叉车装卸',
originalManifest: '01', tallyReport: '01', customsRelease: '11',ciTime: '2026-07-08 14:30:00',
warehouse: [
{ batch: '5', pieces: 150, weight: 420.0, flightDate: '2026-07-08', flightNo: 'CZ789', time: '2026-07-08 22:15:00' },
{ batch: '6', pieces: 118, weight: 360.0, flightDate: '2026-07-09', flightNo: 'CZ012', time: '2026-07-09 06:30:00' },
{ batch: '7', pieces: 100, weight: 200.0, flightDate: '2026-07-09', flightNo: 'CZ345', time: '2026-07-09 13:00:00' }
],
locations: [
{ id: 'B-01-003', inPerson: '张三', inTime: '2026-07-08 22:15', outPerson: '李四', outTime: '2026-07-09 06:00' },
{ id: 'A-02-010', inPerson: '王五', inTime: '2026-07-09 06:30', outPerson: '—', outTime: '—' },
{ id: 'C-03-007', inPerson: '赵六', inTime: '2026-07-09 13:00', outPerson: '—', outTime: '—' }
]
},
'78133363399': {
billNo: '78133363399', agent: '徽远', code: 'DGR',
pieces: '85', weight: '210.0', type: '危险品运输',
inPieces: '85', inWeight: '210.0', calcWeight: '210.0',
carrier: '3U', route: 'CTU-SIN', packType: '铁箱',
billType: '国际进港(国际直航)', unNo: 'UN3480', dest: 'CTU',
itemNameCn: '锂电池', itemNameEn: 'Lithium Battery',
lockStatus: '锁定', outboundTime: '—', remark: '危险品,单独存放',
originalManifest: '01', tallyReport: '01', customsRelease: '11',ciTime: '2026-07-08 14:30:00',
warehouse: [
{ batch: '8', pieces: 45, weight: 110.0, flightDate: '2026-07-08', flightNo: '3U678', time: '2026-07-08 18:00:00' },
{ batch: '9', pieces: 40, weight: 100.0, flightDate: '2026-07-09', flightNo: '3U901', time: '2026-07-09 07:45:00' }
],
locations: [
{ id: 'D-01-002', inPerson: '钱七', inTime: '2026-07-08 18:00', outPerson: '孙八', outTime: '2026-07-09 08:00' },
{ id: 'A-04-015', inPerson: '张三', inTime: '2026-07-09 07:45', outPerson: '—', outTime: '—' }
]
},
'78133363400': {
billNo: '78133363400', agent: '中外运', code: 'PER',
pieces: '350', weight: '430.0', type: '普通货物运输',
inPieces: '350', inWeight: '430.0', calcWeight: '430.0',
carrier: 'HU', route: 'HKG-HFE', packType: '纸箱',
billType: '国际进港(国际直航)', unNo: '—', dest: 'HFE',
itemNameCn: '食品', itemNameEn: 'Food Products',
lockStatus: '未锁定', outboundTime: '2026-07-09 11:30', remark: '保质期至2026-12',
originalManifest: '01', tallyReport: '01', customsRelease: '11',ciTime: '2026-07-08 14:30:00',
warehouse: [
{ batch: '10', pieces: 180, weight: 220.0, flightDate: '2026-07-07', flightNo: 'HU234', time: '2026-07-07 20:00:00' },
{ batch: '11', pieces: 170, weight: 210.0, flightDate: '2026-07-09', flightNo: 'HU567', time: '2026-07-09 10:30:00' }
],
locations: [
{ id: 'B-02-011', inPerson: '李四', inTime: '2026-07-07 20:00', outPerson: '王五', outTime: '2026-07-08 16:00' },
{ id: 'C-01-009', inPerson: '赵六', inTime: '2026-07-09 10:30', outPerson: '—', outTime: '—' }
]
}
};
// 进港仓库卡片列表数据源
const data = [
{ id: "78133363396", status: "已清仓", flight: "20260702/MU1111", route: "LAX-HFE", pcs: 111, weight: 2300 },
{ id: "78133363397", status: "未清仓", flight: "20260702/MU2222", route: "NRT-HFE", pcs: 85, weight: 1560 },
{ id: "78133363398", status: "已清仓", flight: "20260702/MU3333", route: "FRA-HFE", pcs: 200, weight: 4200 },
{ id: "78133363399", status: "未清仓", flight: "20260702/MU4444", route: "LAX-PVG", pcs: 50, weight: 980 },
{ id: "78133363400", status: "未清仓", flight: "20260702/MU5555", route: "CDG-HFE", pcs: 168, weight: 3150 },
{ id: "78133363401", status: "已清仓", flight: "20260702/MU6666", route: "SIN-HFE", pcs: 92, weight: 1800 },
{ id: "78133363402", status: "未清仓", flight: "20260702/MU7777", route: "LAX-NKG", pcs: 145, weight: 2800 },
{ id: "78133363403", status: "已清仓", flight: "20260702/MU8888", route: "HND-HFE", pcs: 73, weight: 1420 }
];
// 渲染仓库卡片列表
function renderList() {
const container = document.getElementById('cardListContainer');
container.innerHTML = data.map((item) => {
const isCleared = item.status === '已清仓';
const departure = item.route.split('-')[0];
const flightNo = item.flight.split('/')[1];
return `
<div class="bg-white rounded-xl p-4 shadow-sm active:bg-gray-50 transition-colors border border-gray-50 cursor-pointer mb-3" onclick="showDetail('${item.id}')">
<div class="flex justify-between items-center mb-3">
<div class="flex items-center gap-2">
<div class="w-2 h-2 rounded-full bg-blue-500"></div>
<span class="font-bold text-[#1a1a1a]">${item.id}</span>
</div>
<div class="flex items-center gap-2">
${getStatusTag(item.status)}
<iconify-icon class="text-gray-500 text-[14px]" icon="mdi:chevron-right"></iconify-icon>
</div>
</div>
<div class="grid grid-cols-2 gap-y-2 text-[13px] text-gray-500">
<div class="flex items-center gap-2">
<iconify-icon class="text-gray-500 text-[14px]" icon="mdi:package-variant-closed"></iconify-icon>
<span>件数:${item.pcs}</span>
</div>
<div class="flex items-center gap-2">
<iconify-icon class="text-gray-500 text-[14px]" icon="mdi:weight-kilogram"></iconify-icon>
<span>重量:${item.weight}</span>
</div>
<div class="flex items-center gap-2">
<iconify-icon class="text-gray-500 text-[14px]" icon="mdi:airplane"></iconify-icon>
<span>航班号:${flightNo}</span>
</div>
<div class="flex items-center gap-2">
<iconify-icon class="text-gray-500 text-[14px]" icon="mdi:map-marker"></iconify-icon>
<span>始发站:${departure}</span>
</div>
</div>
<div class="grid grid-cols-4 gap-2 mt-3">
<button onclick="event.stopPropagation(); showToast('执行清仓操作:运单号 ${item.id}')"
class="text-xs py-1.5 px-2 rounded-[6px] font-medium h-8 ${isCleared ? 'bg-gray-100 text-gray-400 cursor-not-allowed' : 'bg-[#EFF6FF] text-[#2563EB]'}" ${isCleared ? 'disabled' : ''}>
清仓
</button>
<button onclick="event.stopPropagation(); showToast('修改库位:运单号 ${item.id}')"
class="bg-[#EFF6FF] text-[#2563EB] text-xs py-1.5 px-2 rounded-[6px] font-medium h-8">
修改库位
</button>
<button onclick="event.stopPropagation(); showToast('执行出库:运单号 ${item.id}')"
class="bg-[#EFF6FF] text-[#2563EB] text-xs py-1.5 px-2 rounded-[6px] font-medium h-8">
出库
</button>
<button onclick="event.stopPropagation(); showToast('执行入库:运单号 ${item.id}')"
class="bg-[#EFF6FF] text-[#2563EB] text-xs py-1.5 px-2 rounded-[6px] font-medium h-8">
入库
</button>
</div>
</div>`;
}).join('');
}
// 状态标签渲染
function getStatusTag(status) {
let color = '';
switch(status) {
case '已清仓': color = 'bg-green-100 text-green-600 text-[11px] px-2 h-5 flex items-center rounded-[6px] font-medium'; break;
case '未清仓': color = 'bg-orange-100 text-orange-600 text-[11px] px-2 h-5 flex items-center rounded-[6px] font-medium'; break;
}
return `<span class="${color}">${status}</span>`;
}
// 跳转至进港货物页面,填充数据
function showDetail(id) {
const listPage = document.getElementById('listPage');
const detailPage = document.getElementById('detailPage');
const data = uldData[id];
if (!data) {
showToast("暂无该运单详情数据");
return;
}
// 填充基础信息
document.getElementById('det-billNo').innerText = data.billNo;
document.getElementById('det-agent').innerText = data.agent;
document.getElementById('det-code').innerText = data.code;
document.getElementById('det-carrier').innerText = data.carrier;
document.getElementById('det-route').innerText = data.route;
document.getElementById('det-dest').innerText = data.dest;
document.getElementById('det-billType').innerText = data.billType;
document.getElementById('det-unNo').innerText = data.unNo;
document.getElementById('det-ciTime').innerText = data.ciTime;
// 锁定状态样式
const lockStatusEl = document.getElementById('det-lockStatus');
if (data.lockStatus === '锁定') {
lockStatusEl.innerHTML = '<iconify-icon icon="mdi:lock" class="mr-1"></iconify-icon>锁定';
lockStatusEl.className = 'text-xs font-semibold px-2 py-0.5 rounded-md bg-red-50 text-red-600 inline-flex items-center';
} else {
lockStatusEl.innerText = '—';
lockStatusEl.className = 'text-xs font-semibold text-gray-800';
}
document.getElementById('det-packType').innerText = data.packType;
document.getElementById('det-type').innerText = data.type;
document.getElementById('det-outboundTime').innerText = data.outboundTime || '—';
document.getElementById('det-itemNameCn').innerText = data.itemNameCn || '—';
document.getElementById('det-itemNameEn').innerText = data.itemNameEn || '—';
document.getElementById('det-remark').innerText = data.remark || '—';
// 件重信息
document.getElementById('det-pieces').innerText = data.pieces;
document.getElementById('det-weight').innerText = data.weight;
document.getElementById('det-calcWeight').innerText = data.calcWeight;
document.getElementById('det-inPieces').innerText = data.inPieces;
document.getElementById('det-inWeight').innerText = data.inWeight;
// 海关放行标签
const customsReleaseEl = document.getElementById('det-customsRelease');
if (data.customsRelease === '11') {
customsReleaseEl.innerText = '11';
customsReleaseEl.className = 'text-xs font-semibold px-2 py-0.5 rounded-md bg-green-50 text-green-600 inline-block';
} else {
customsReleaseEl.innerText = data.customsRelease;
customsReleaseEl.className = 'text-xs font-semibold px-2 py-0.5 rounded-md bg-gray-100 text-gray-600 inline-block';
}
document.getElementById('det-originalManifest').innerText = data.originalManifest;
document.getElementById('det-tallyReport').innerText = data.tallyReport;
// 渲染仓库批次
const warehouseContainer = document.getElementById('tab-content-1');
warehouseContainer.innerHTML = '';
data.warehouse.forEach(item => {
warehouseContainer.innerHTML += `
<div class="bg-white rounded-xl shadow-sm border border-gray-100 overflow-hidden">
<div class="flex justify-between items-center pt-3 pb-1.5 px-3 mb-2 border-b border-gray-100">
<div class="flex items-center gap-1.5">
<span class="w-1.5 h-1.5 rounded-full bg-blue-500 inline-block"></span>
<span class="text-xs font-semibold text-gray-900">批次号: ${item.batch}</span>
</div>
</div>
<div class="grid grid-cols-2 gap-1.5 px-3 pb-2">
<div class="bg-gray-50/50 rounded-lg p-2">
<div class="text-[10px] text-gray-500 text-[14px] mb-0.5">件数</div>
<div class="text-xs font-semibold text-gray-800">${item.pieces}</div>
</div>
<div class="bg-gray-50/50 rounded-lg p-2">
<div class="text-[10px] text-gray-500 text-[14px] mb-0.5">重量</div>
<div class="text-xs font-semibold text-gray-800">${parseFloat(item.weight).toFixed(1)} kg</div>
</div>
<div class="bg-gray-50/50 rounded-lg p-2">
<div class="text-[10px] text-gray-500 text-[14px] mb-0.5">航班日期</div>
<div class="text-xs font-semibold text-gray-800">${item.flightDate}</div>
</div>
<div class="bg-gray-50/50 rounded-lg p-2">
<div class="text-[10px] text-gray-500 text-[14px] mb-0.5">航班号</div>
<div class="text-xs font-semibold text-gray-800">${item.flightNo}</div>
</div>
<div class="bg-gray-50/50 rounded-lg p-2">
<div class="text-[10px] text-gray-500 text-[14px] mb-0.5">始发站</div>
<div class="text-xs font-semibold text-gray-800">${item.route}</div>
</div>
<div class="bg-gray-50/50 rounded-lg p-2">
<div class="text-[10px] text-gray-500 text-[14px] mb-0.5">目的站</div>
<div class="text-xs font-semibold text-gray-800">${item.dest}</div>
</div>
</div>
</div>`;
});
// 渲染库位信息
const locationContainer = document.getElementById('tab-content-2');
locationContainer.innerHTML = '';
data.locations.forEach(loc => {
locationContainer.innerHTML += `
<div class="bg-white rounded-xl shadow-sm border border-gray-100 overflow-hidden">
<div class="flex justify-between items-center pt-3 pb-1.5 px-3 mb-2 border-b border-gray-100">
<div class="flex items-center gap-1.5">
<span class="w-1.5 h-1.5 rounded-full bg-blue-500 inline-block"></span>
<span class="text-xs font-bold text-gray-900">${loc.id}</span>
</div>
</div>
<div class="grid grid-cols-2 gap-1.5 px-3 pb-2">
<div class="bg-gray-50/50 rounded-lg p-2">
<div class="text-[10px] text-gray-500 text-[14px] mb-0.5">入库人</div>
<div class="text-xs font-semibold text-gray-800">${loc.inPerson}</div>
</div>
<div class="bg-gray-50/50 rounded-lg p-2">
<div class="text-[10px] text-gray-500 text-[14px] mb-0.5">入库时间</div>
<div class="text-xs font-semibold text-gray-800">${loc.inTime}</div>
</div>
<div class="bg-gray-50/50 rounded-lg p-2">
<div class="text-[10px] text-gray-500 text-[14px] mb-0.5">出库人</div>
<div class="text-xs ${loc.outPerson === '—' ? 'text-gray-500' : 'text-gray-800'} font-semibold">${loc.outPerson}</div>
</div>
<div class="bg-gray-50/50 rounded-lg p-2">
<div class="text-[10px] text-gray-500 text-[14px] mb-0.5">出库时间</div>
<div class="text-xs ${loc.outTime === '—' ? 'text-gray-500' : 'text-gray-800'} font-semibold">${loc.outTime}</div>
</div>
</div>
</div>`;
});
// 默认激活运单信息标签
switchTab(0);
// 页面切换动画:列表左滑隐藏,详情滑入
listPage.classList.add('page-hidden-left');
detailPage.classList.remove('page-hidden-right');
}
// 返回列表页
function goBack() {
const listPage = document.getElementById('listPage');
const detailPage = document.getElementById('detailPage');
listPage.classList.remove('page-hidden-left');
detailPage.classList.add('page-hidden-right');
}
// 切换详情标签页
function switchTab(index) {
const tabs = document.querySelectorAll('.tab-item');
const contents = document.querySelectorAll('.tab-pane');
tabs.forEach((tab, i) => {
if (i === index) {
tab.classList.add('active');
contents[i].classList.remove('hidden');
} else {
tab.classList.remove('active');
contents[i].classList.add('hidden');
}
});
}
// Toast提示
function showToast(msg) {
const toast = document.getElementById('toast');
toast.innerText = msg;
toast.classList.remove('hidden');
setTimeout(() => toast.classList.add('hidden'), 2000);
}
// 筛选弹窗方法
function openFilter() {
const filterOverlay = document.getElementById('filterOverlay');
const filterSheet = document.getElementById('filterSheet');
filterOverlay.classList.add('show');
setTimeout(() => filterSheet.classList.add('show'), 10);
}
function closeFilter() {
const filterOverlay = document.getElementById('filterOverlay');
const filterSheet = document.getElementById('filterSheet');
filterSheet.classList.remove('show');
setTimeout(() => filterOverlay.classList.remove('show'), 250);
}
function resetFilter() {
document.querySelectorAll('.filter-input').forEach(input => {
input.value = '';
});
}
function confirmFilter() {
const params = {
flightDate: document.getElementById('filterFlightDate')?.value || '',
flightNo: document.getElementById('filterFlightNo')?.value || '',
agent: '',
code: '',
origin: document.getElementById('filterOrigin')?.value || '',
billType: '',
bizType: '',
cnName: document.getElementById('filterCnName')?.value || ''
};
console.log('筛选参数:', params);
alert('筛选执行成功,控制台可查看筛选条件');
closeFilter();
}
// 扫码弹窗
function toggleScanOverlay(show) {
const overlay = document.getElementById('scanOverlay');
if (show) overlay.classList.remove('hidden');
else overlay.classList.add('hidden');
}
// 页面加载完成初始化
document.addEventListener('DOMContentLoaded', function() {
renderList();
// 筛选遮罩点击关闭
const filterOverlay = document.getElementById('filterOverlay');
filterOverlay.addEventListener('click', function(e) {
if (e.target === filterOverlay) closeFilter();
});
});
</script>
</body>
</html>