This commit is contained in:
2026-08-05 09:49:02 +08:00
parent df63049fd1
commit 3e62cc1263
16 changed files with 9271 additions and 497 deletions
+436 -53
View File
@@ -2,8 +2,8 @@
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scale=no">
<title>PDA集装箱拣货</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>柏悦物流 PDA · 仓储作业平台</title>
<style>
:root {
--primary: #1a73e8;
@@ -1019,6 +1019,232 @@
}
.logout-btn:active { transform: scale(0.95); }
/* ========== PDA 工作台与业务导航 ========== */
.workbench-page.hidden,
.operation-page.hidden,
.profile-page.hidden { display: none; }
.app-shell { min-height: 100vh; background: var(--bg); padding-bottom: 28px; }
.app-topbar {
background: linear-gradient(135deg, #155eef 0%, #2878ff 100%);
color: white;
padding: 16px 16px 22px;
border-radius: 0 0 22px 22px;
box-shadow: 0 8px 24px rgba(21,94,239,.22);
}
.app-topbar-row { display:flex; align-items:center; justify-content:space-between; gap:12px; }
.app-brand { display:flex; align-items:center; gap:10px; }
.app-brand-mark { width:38px; height:38px; border-radius:12px; background:rgba(255,255,255,.18); display:flex; align-items:center; justify-content:center; font-size:20px; }
.app-brand-title { font-size:18px; font-weight:700; letter-spacing:.5px; }
.app-brand-sub { font-size:11px; opacity:.72; margin-top:2px; }
.profile-entry { width:42px; height:42px; border-radius:14px; border:1px solid rgba(255,255,255,.25); background:rgba(255,255,255,.16); color:#fff; cursor:pointer; display:flex; align-items:center; justify-content:center; font-size:17px; font-weight:700; }
.profile-entry:active { transform:scale(.96); }
.welcome-card { margin-top:18px; display:flex; justify-content:space-between; align-items:flex-end; gap:12px; }
.welcome-kicker { font-size:12px; opacity:.75; }
.welcome-name { margin-top:3px; font-size:21px; font-weight:700; }
.welcome-meta { margin-top:5px; font-size:12px; opacity:.82; }
.shift-badge { flex:none; padding:7px 10px; border-radius:10px; background:rgba(255,255,255,.15); font-size:11px; }
.workbench-content { padding:14px 12px 0; }
.today-panel { display:grid; grid-template-columns:repeat(3,1fr); gap:8px; margin-top:-2px; margin-bottom:14px; }
.today-stat { background:#fff; border:1px solid #e5edf8; border-radius:12px; padding:12px 8px; text-align:center; box-shadow:var(--shadow); }
.today-stat-num { font-size:20px; font-weight:750; color:#163b68; line-height:1.1; }
.today-stat-label { margin-top:5px; font-size:11px; color:var(--text-secondary); }
.phase-notice { display:flex; align-items:center; gap:11px; margin:0 0 16px; padding:12px 13px; border:1px solid #cfe0fb; border-radius:13px; background:linear-gradient(135deg,#f6f9ff,#edf4ff); }
.phase-notice-icon { flex:none; width:34px; height:34px; border-radius:11px; background:#155eef; color:#fff; display:flex; align-items:center; justify-content:center; font-size:16px; box-shadow:0 5px 12px rgba(21,94,239,.2); }
.phase-notice-title { font-size:12px; font-weight:700; color:#163b68; }
.phase-notice-desc { margin-top:2px; font-size:10px; color:#6b7f99; }
.section-heading { display:flex; align-items:center; justify-content:space-between; margin:17px 2px 9px; }
.section-heading-title { display:flex; align-items:center; gap:8px; font-size:16px; font-weight:700; color:#172b4d; }
.section-heading-title::before { content:''; width:4px; height:16px; border-radius:3px; background:var(--section-color,#1a73e8); }
.section-heading-count { font-size:11px; color:#8a97a8; }
.module-card { background:#fff; border:1px solid #e6ebf2; border-radius:16px; padding:5px 8px; box-shadow:0 3px 12px rgba(20,49,82,.05); }
.module-grid { display:grid; grid-template-columns:repeat(4,1fr); }
.module-item { position:relative; border:0; background:transparent; padding:12px 3px 11px; min-width:0; cursor:pointer; border-radius:11px; color:#2f3e52; }
.module-item:active { background:#f0f5ff; transform:scale(.97); }
.module-icon { width:42px; height:42px; margin:0 auto 7px; border-radius:13px; display:flex; align-items:center; justify-content:center; font-size:21px; background:var(--icon-bg,#eaf2ff); color:var(--icon-color,#155eef); }
.module-name { font-size:12px; line-height:1.3; white-space:nowrap; }
.module-badge { position:absolute; top:7px; right:5px; min-width:17px; height:17px; padding:0 4px; border-radius:9px; background:#ef4444; color:#fff; font-size:9px; line-height:17px; }
.module-card.inbound { --icon-bg:#eaf2ff; --icon-color:#155eef; }
.module-card.outbound { --icon-bg:#e7f8f3; --icon-color:#0d9488; }
.module-card.internal { --icon-bg:#fff4e5; --icon-color:#e27a16; }
.module-item.disabled { cursor:not-allowed; color:#a8b1bd; opacity:.72; }
.module-item.disabled .module-icon { background:#f1f3f5; color:#aeb7c2; filter:grayscale(1); }
.module-item.disabled:active { background:transparent; transform:none; }
.module-lock { position:absolute; top:8px; right:7px; width:16px; height:16px; border-radius:50%; background:#e7eaee; color:#8d98a6; display:flex; align-items:center; justify-content:center; font-size:8px; }
.module-item.active-menu { margin:5px 3px; padding-top:7px; padding-bottom:7px; border:1px solid #8dd8cd; background:linear-gradient(145deg,#f0fdfa,#e7f8f3); box-shadow:0 5px 13px rgba(13,148,136,.13); color:#0b6f68; }
.module-item.active-menu .module-icon { background:#0d9488; color:#fff; box-shadow:0 6px 12px rgba(13,148,136,.22); }
.module-open-badge { position:absolute; top:-7px; right:-3px; padding:2px 5px; border-radius:7px; background:#0d9488; color:#fff; font-size:8px; font-weight:700; box-shadow:0 3px 8px rgba(13,148,136,.22); }
.section-status { display:inline-flex; align-items:center; gap:4px; padding:3px 7px; border-radius:8px; background:#f0f2f5; color:#929eac; font-size:10px; }
.section-status.open { background:#e7f8f3; color:#0b7b70; font-weight:600; }
.page-topbar { position:sticky; top:0; z-index:90; height:60px; padding:0 12px; display:flex; align-items:center; justify-content:space-between; background:#fff; border-bottom:1px solid var(--border); box-shadow:0 2px 8px rgba(20,49,82,.05); }
.page-back { width:38px; height:38px; border:0; border-radius:11px; background:#f1f5f9; color:#334155; font-size:20px; cursor:pointer; }
.page-title { font-size:17px; font-weight:700; color:#172b4d; }
.page-user { width:36px; height:36px; border:0; border-radius:12px; background:#eaf2ff; color:#155eef; font-size:13px; font-weight:700; cursor:pointer; }
.operation-content { padding:14px 12px 30px; }
.operation-hero { padding:18px; border-radius:17px; color:#fff; background:linear-gradient(135deg,#155eef,#2878ff); box-shadow:0 8px 20px rgba(21,94,239,.18); }
.operation-hero-icon { width:46px; height:46px; border-radius:14px; display:flex; align-items:center; justify-content:center; background:rgba(255,255,255,.17); font-size:24px; margin-bottom:12px; }
.operation-hero-title { font-size:20px; font-weight:700; }
.operation-hero-desc { margin-top:5px; font-size:12px; line-height:1.6; opacity:.83; }
.task-card { margin-top:12px; background:#fff; border:1px solid #e4eaf2; border-radius:15px; padding:15px; box-shadow:var(--shadow); }
.task-card-title { font-size:14px; font-weight:700; color:#243b53; margin-bottom:12px; }
.task-row { display:flex; align-items:center; gap:11px; padding:11px 0; border-top:1px solid #edf1f5; }
.task-row:first-of-type { border-top:0; }
.task-row-icon { width:34px; height:34px; border-radius:10px; background:#edf4ff; display:flex; align-items:center; justify-content:center; }
.task-row-main { flex:1; min-width:0; }
.task-row-name { font-size:13px; font-weight:600; color:#334e68; }
.task-row-desc { margin-top:3px; font-size:11px; color:#829ab1; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.task-row-arrow { color:#9fb0c3; }
.scan-action { width:100%; margin-top:14px; padding:13px; border:0; border-radius:12px; background:#155eef; color:#fff; font-size:14px; font-weight:700; cursor:pointer; }
.profile-cover { background:linear-gradient(135deg,#155eef,#2878ff); height:150px; padding:16px; color:#fff; }
.profile-card { margin:-62px 14px 14px; background:#fff; border-radius:18px; padding:18px; box-shadow:0 10px 28px rgba(20,49,82,.13); text-align:center; position:relative; }
.profile-avatar { width:68px; height:68px; border-radius:22px; margin:-50px auto 10px; display:flex; align-items:center; justify-content:center; background:#eaf2ff; border:4px solid #fff; color:#155eef; font-size:25px; font-weight:800; }
.profile-name { font-size:19px; font-weight:700; color:#172b4d; }
.profile-role { margin-top:4px; font-size:12px; color:#728196; }
.profile-stats { display:grid; grid-template-columns:repeat(3,1fr); margin-top:16px; padding-top:14px; border-top:1px solid #edf1f5; }
.profile-stat strong { display:block; color:#163b68; font-size:17px; }
.profile-stat span { font-size:10px; color:#8a97a8; }
.profile-list { margin:12px; background:#fff; border-radius:16px; padding:2px 14px; box-shadow:var(--shadow); }
.profile-list-item { display:flex; align-items:center; gap:12px; padding:15px 0; border-bottom:1px solid #edf1f5; font-size:13px; color:#334e68; }
.profile-list-item:last-child { border-bottom:0; }
.profile-list-icon { width:32px; height:32px; border-radius:10px; background:#eef4ff; display:flex; align-items:center; justify-content:center; }
.profile-list-value { margin-left:auto; color:#829ab1; font-size:12px; }
.profile-logout { width:calc(100% - 24px); margin:4px 12px 24px; padding:13px; border:1px solid #fecaca; border-radius:12px; background:#fff; color:#dc2626; font-size:14px; font-weight:600; cursor:pointer; }
/* ========== 统一视觉升级 ========== */
:root {
--primary:#1769e0;
--primary-light:#eaf2ff;
--success:#078775;
--success-light:#e1f6f1;
--bg:#f3f6fa;
--text:#172033;
--text-secondary:#68758a;
--border:#dfe5ee;
--shadow:0 3px 12px rgba(23,32,51,.07);
--radius:10px;
}
button, input { font-family:inherit; }
button { -webkit-tap-highlight-color:transparent; }
button:focus-visible, input:focus-visible { outline:3px solid rgba(23,105,224,.18); outline-offset:2px; }
/* 登录 */
.login-page {
justify-content:flex-start;
padding:0 22px 28px;
background:linear-gradient(180deg,#123b72 0 258px,#f3f6fa 258px 100%);
}
.login-logo { margin:0 -22px; padding:54px 22px 42px; text-align:left; }
.login-brand-line { display:flex; align-items:center; gap:14px; }
.login-logo-icon {
flex:none; width:58px; height:58px; margin:0; border-radius:14px;
background:rgba(255,255,255,.14); border:1px solid rgba(255,255,255,.2);
box-shadow:none;
}
.login-logo-icon svg { width:31px; height:31px; }
.login-logo-title { font-size:21px; letter-spacing:0; }
.login-logo-sub { color:rgba(255,255,255,.72); font-size:12px; margin-top:5px; }
.login-status { display:flex; align-items:center; gap:6px; margin-top:25px; color:rgba(255,255,255,.8); font-size:11px; }
.login-status::before { content:''; width:7px; height:7px; border-radius:50%; background:#48d5bc; box-shadow:0 0 0 4px rgba(72,213,188,.12); }
.login-card {
margin-top:-18px; border:1px solid #e2e7ef; border-radius:12px; padding:22px 20px 18px;
box-shadow:0 12px 30px rgba(18,59,114,.12);
}
.login-card-title { font-size:18px; font-weight:750; color:#172033; }
.login-card-desc { margin:5px 0 20px; color:#78869a; font-size:12px; }
.login-field { margin-bottom:15px; }
.login-field-label { color:#445168; font-weight:600; margin-bottom:7px; }
.login-input-wrap { position:relative; }
.login-input-icon { position:absolute; left:13px; top:50%; transform:translateY(-50%); color:#8290a4; display:flex; }
.login-input-icon svg { width:18px; height:18px; }
.login-field-input {
height:48px; padding:0 42px; border:1px solid #d8e0eb; border-radius:8px;
background:#f9fbfd; color:#172033; font-size:16px;
}
.login-field-input:focus { border-color:var(--primary); background:#fff; box-shadow:0 0 0 3px rgba(23,105,224,.08); }
.password-toggle { position:absolute; right:4px; top:4px; width:40px; height:40px; border:0; background:transparent; color:#6f7d91; border-radius:7px; cursor:pointer; display:flex; align-items:center; justify-content:center; }
.password-toggle svg { width:19px; height:19px; }
.login-error { padding:9px 11px; border-radius:7px; background:#fff1f1; }
.login-btn { height:48px; padding:0; margin-top:5px; border-radius:8px; background:#1769e0; box-shadow:0 6px 14px rgba(23,105,224,.2); }
.login-demo-tip { margin-top:13px; padding:10px 12px; border-radius:7px; background:#f2f5f9; color:#6b788c; font-size:11px; text-align:center; }
/* 工作台 */
.app-topbar { padding:15px 16px 24px; border-radius:0 0 16px 16px; background:linear-gradient(140deg,#123b72,#1769e0); box-shadow:0 7px 20px rgba(18,59,114,.2); }
.app-brand-mark { width:36px; height:36px; border-radius:9px; font-size:18px; }
.app-brand-title { font-size:17px; letter-spacing:0; }
.profile-entry { width:40px; height:40px; border-radius:10px; }
.welcome-card { margin-top:20px; align-items:center; }
.welcome-name { font-size:20px; }
.shift-badge { display:flex; align-items:center; gap:6px; border:1px solid rgba(255,255,255,.16); border-radius:8px; }
.shift-badge::before { content:''; width:6px; height:6px; border-radius:50%; background:#5ee6c8; }
.workbench-content { padding:14px 12px 22px; }
.today-panel { gap:7px; margin-top:-1px; }
.today-stat { border-radius:9px; padding:12px 6px; }
.today-stat-num { font-size:21px; color:#123b72; }
.phase-notice { border-radius:9px; background:#eef5ff; }
.phase-notice-icon { width:32px; height:32px; border-radius:8px; box-shadow:none; }
.section-heading { margin:18px 2px 8px; }
.section-heading-title { font-size:15px; }
.module-card { border-radius:10px; padding:4px 6px; box-shadow:var(--shadow); }
.module-item { min-height:78px; border-radius:8px; }
.module-icon { width:40px; height:40px; border-radius:10px; font-size:20px; }
.module-item.disabled { opacity:.58; }
.module-lock { background:#dfe4ea; }
.module-item.active-menu { margin:3px; border-radius:9px; border-color:#74cfbf; background:#e8f8f4; box-shadow:0 4px 10px rgba(7,135,117,.14); }
.module-open-badge { top:-6px; right:-2px; border-radius:5px; }
/* 个人中心 */
.profile-cover { height:132px; background:linear-gradient(140deg,#123b72,#1769e0); }
.profile-cover .page-back { background:rgba(255,255,255,.14); color:#fff; }
.profile-card { border-radius:12px; margin:-49px 12px 12px; padding:18px; }
.profile-avatar { border-radius:16px; }
.profile-list { border:1px solid #e3e8ef; border-radius:10px; box-shadow:none; }
.profile-list-icon { border-radius:8px; }
.profile-logout { border-radius:9px; }
/* 集装箱拣货 */
.header { padding:13px 14px 12px; background:linear-gradient(135deg,#123b72,#1769e0); box-shadow:0 3px 12px rgba(18,59,114,.22); }
.header-title { font-size:17px; }
.header-badge { border-radius:6px; }
.header-sub { display:flex; flex-wrap:wrap; gap:3px 10px; margin-top:7px; }
.header-sub span { margin-right:0; }
.box-select-wrap { margin:12px 12px 8px; }
.box-select-btn { min-height:46px; border:1px solid #c8d9f4; border-radius:9px; color:#174d91; box-shadow:none; }
.scan-section { margin:8px 12px; padding:12px; border:1px solid #d8e4f4; border-radius:10px; box-shadow:var(--shadow); }
.scan-section::before { content:'扫码拣货'; display:block; margin-bottom:8px; color:#394860; font-size:12px; font-weight:700; }
.scan-input { height:46px; padding-top:0; padding-bottom:0; border:1px solid #cfd9e7; border-radius:8px; background:#f8fafc; }
.scan-btn { width:46px; height:46px; border-radius:8px; background:#1769e0; }
.info-cards { margin:8px 12px; gap:8px; }
.info-card { min-width:0; border:1px solid #e0e6ee; border-radius:9px; padding:11px 12px; box-shadow:none; }
.info-card-value { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; font-size:14px; }
.progress-section { margin:8px 12px; border:1px solid #e0e6ee; border-radius:9px; box-shadow:none; }
.progress-bar-bg { height:7px; }
.progress-bar-fill { background:#078775; }
.pick-list { margin:8px 12px 12px; }
.pick-item { border:1px solid #e1e7ef; border-radius:9px; padding:14px; box-shadow:0 2px 8px rgba(23,32,51,.05); }
.pick-item.active { border-left:4px solid var(--primary); box-shadow:0 3px 12px rgba(23,105,224,.1); }
.pick-item-location, .pick-item-order { border-radius:5px; }
.pick-btn { min-height:42px; border-radius:7px; font-weight:600; }
.pick-btn-confirm { background:#078775; }
.pick-btn-partial { background:#eef4ff; color:#1769e0; border-color:#9ebcec; }
.submit-section { padding:10px 12px max(12px,env(safe-area-inset-bottom)); box-shadow:0 -4px 14px rgba(23,32,51,.08); }
.container-stat { border-radius:7px; min-height:34px; }
.submit-btn { min-height:48px; border-radius:8px; background:#1769e0; }
.partial-modal, .skip-modal, .boxlist-modal { border-radius:14px 14px 0 0; }
.complete-modal { border-radius:12px; }
@media (max-width:360px) {
.module-name { font-size:11px; }
.module-icon { width:38px; height:38px; }
.welcome-name { font-size:19px; }
.login-page { padding-left:16px; padding-right:16px; }
.login-logo { margin-left:-16px; margin-right:-16px; padding-left:18px; padding-right:18px; }
.pick-item-actions { gap:6px; }
.pick-btn { font-size:12px; }
}
</style>
</head>
<body>
@@ -1029,51 +1255,128 @@
<!-- ===== 登录页 ===== -->
<div class="login-page" id="loginPage">
<div class="login-logo">
<div class="login-logo-icon">
<svg viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2">
<rect x="3" y="3" width="18" height="18" rx="2"/>
<path d="M3 9h18M9 3v18"/>
</svg>
<div class="login-brand-line">
<div class="login-logo-icon">
<svg viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2">
<rect x="3" y="3" width="18" height="18" rx="2"/>
<path d="M3 9h18M9 3v18"/>
</svg>
</div>
<div><div class="login-logo-title">柏悦物流 PDA</div><div class="login-logo-sub">仓储移动作业平台</div></div>
</div>
<div class="login-logo-title">柏悦物流 · PDA拣货</div>
<div class="login-logo-sub">集装箱拣货作业系统</div>
<div class="login-status">作业系统运行正常</div>
</div>
<div class="login-card">
<div class="login-card-title">账号登录</div>
<div class="login-card-desc">请输入作业人员账号进入工作台</div>
<div class="login-field">
<div class="login-field-label">工号 / 用户名</div>
<input class="login-field-input" id="loginUser" placeholder="请输入工号" autocomplete="off">
<div class="login-field-label">用户名</div>
<div class="login-input-wrap">
<span class="login-input-icon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="8" r="4"/><path d="M4 21a8 8 0 0116 0"/></svg></span>
<input class="login-field-input" id="loginUser" placeholder="请输入用户名" autocomplete="username">
</div>
</div>
<div class="login-field">
<div class="login-field-label">密码</div>
<input class="login-field-input" id="loginPass" type="password" placeholder="请输入密码">
</div>
<div class="login-field">
<div class="login-field-label">作业仓库</div>
<select class="login-field-select" id="loginWarehouse">
<option value="仓库 A">仓库 A</option>
<option value="仓库 B">仓库 B</option>
<option value="仓库 C">仓库 C</option>
</select>
</div>
<div class="login-error" id="loginError">工号或密码错误</div>
<button class="login-btn" onclick="handleLogin()">登录</button>
<div class="login-accounts">
<div class="login-accounts-title">快捷登录(演示账号)</div>
<div class="login-quick-btns">
<button class="login-quick-btn" onclick="quickLogin('W001','张伟','拣货员')">
<span class="login-quick-btn-name">W001 张伟</span>
<span class="login-quick-btn-role"> · 拣货员</span>
</button>
<button class="login-quick-btn" onclick="quickLogin('W002','李敏','拣货组长')">
<span class="login-quick-btn-name">W002 李敏</span>
<span class="login-quick-btn-role"> · 拣货组长</span>
</button>
<button class="login-quick-btn" onclick="quickLogin('W003','王磊','仓管员')">
<span class="login-quick-btn-name">W003 王磊</span>
<span class="login-quick-btn-role"> · 仓管员</span>
<div class="login-input-wrap">
<span class="login-input-icon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="4" y="10" width="16" height="11" rx="2"/><path d="M8 10V7a4 4 0 018 0v3"/></svg></span>
<input class="login-field-input" id="loginPass" type="password" placeholder="请输入密码" autocomplete="current-password">
<button class="password-toggle" id="passwordToggle" type="button" onclick="togglePassword()" aria-label="显示密码">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M2 12s3.5-6 10-6 10 6 10 6-3.5 6-10 6S2 12 2 12z"/><circle cx="12" cy="12" r="2.5"/></svg>
</button>
</div>
</div>
<div class="login-error" id="loginError">用户名或密码错误</div>
<button class="login-btn" onclick="handleLogin()">登录</button>
<div class="login-demo-tip">演示账号:W001 密码:123456</div>
</div>
</div>
<!-- ===== PDA 工作台 ===== -->
<div class="workbench-page hidden" id="workbenchPage">
<div class="app-shell">
<div class="app-topbar">
<div class="app-topbar-row">
<div class="app-brand">
<div class="app-brand-mark">▦</div>
<div><div class="app-brand-title">柏悦物流 PDA</div><div class="app-brand-sub">仓储移动作业平台</div></div>
</div>
<button class="profile-entry" id="workbenchAvatar" onclick="openProfile()" aria-label="个人中心">张</button>
</div>
<div class="welcome-card">
<div>
<div class="welcome-kicker">欢迎回来</div>
<div class="welcome-name" id="workbenchUserName">张伟</div>
<div class="welcome-meta"><span id="workbenchRole">拣货员</span> · <span id="workbenchWarehouse">洛杉矶仓</span></div>
</div>
<div class="shift-badge">白班 · 作业中</div>
</div>
</div>
<div class="workbench-content">
<div class="today-panel">
<div class="today-stat"><div class="today-stat-num">3</div><div class="today-stat-label">待拣集装箱</div></div>
<div class="today-stat"><div class="today-stat-num">0</div><div class="today-stat-label">今日已完成</div></div>
<div class="today-stat"><div class="today-stat-num">17</div><div class="today-stat-label">待拣货品</div></div>
</div>
<div class="phase-notice"><div class="phase-notice-icon">✓</div><div><div class="phase-notice-title">一期作业范围</div><div class="phase-notice-desc">当前仅开放“集装箱拣货”,其他功能将在后续版本启用</div></div></div>
<div class="section-heading" style="--section-color:#aeb7c2"><div class="section-heading-title">入库</div><div class="section-status">暂未开放</div></div>
<div class="module-card inbound"><div class="module-grid">
<button class="module-item disabled" type="button" disabled aria-disabled="true"><span class="module-lock">●</span><span class="module-icon">📥</span><span class="module-name">收货登记</span></button>
<button class="module-item disabled" type="button" disabled aria-disabled="true"><span class="module-lock">●</span><span class="module-icon">🗄️</span><span class="module-name">入库上架</span></button>
<button class="module-item disabled" type="button" disabled aria-disabled="true"><span class="module-lock">●</span><span class="module-icon">📐</span><span class="module-name">入库测量</span></button>
<button class="module-item disabled" type="button" disabled aria-disabled="true"><span class="module-lock">●</span><span class="module-icon">↩️</span><span class="module-name">退货入库</span></button>
</div></div>
<div class="section-heading" style="--section-color:#0d9488"><div class="section-heading-title">出库</div><div class="section-status open">本期开放 1 项</div></div>
<div class="module-card outbound"><div class="module-grid">
<button class="module-item disabled" type="button" disabled aria-disabled="true"><span class="module-lock">●</span><span class="module-icon">📋</span><span class="module-name">波次拣货</span></button>
<button class="module-item active-menu" type="button" onclick="openPicking()"><span class="module-open-badge">本期开放</span><span class="module-badge">3</span><span class="module-icon">📦</span><span class="module-name">集装箱拣货</span></button>
<button class="module-item disabled" type="button" disabled aria-disabled="true"><span class="module-lock">●</span><span class="module-icon">✅</span><span class="module-name">复核装箱</span></button>
<button class="module-item disabled" type="button" disabled aria-disabled="true"><span class="module-lock">●</span><span class="module-icon">🚚</span><span class="module-name">出库交接</span></button>
</div></div>
<div class="section-heading" style="--section-color:#aeb7c2"><div class="section-heading-title">库内作业</div><div class="section-status">暂未开放</div></div>
<div class="module-card internal"><div class="module-grid">
<button class="module-item disabled" type="button" disabled aria-disabled="true"><span class="module-lock">●</span><span class="module-icon">🔄</span><span class="module-name">移库作业</span></button>
<button class="module-item disabled" type="button" disabled aria-disabled="true"><span class="module-lock">●</span><span class="module-icon">📊</span><span class="module-name">库存盘点</span></button>
<button class="module-item disabled" type="button" disabled aria-disabled="true"><span class="module-lock">●</span><span class="module-icon">🔍</span><span class="module-name">库位查询</span></button>
<button class="module-item disabled" type="button" disabled aria-disabled="true"><span class="module-lock">●</span><span class="module-icon">⚠️</span><span class="module-name">异常处理</span></button>
</div></div>
</div>
</div>
</div>
<!-- ===== 通用作业页 ===== -->
<div class="operation-page hidden" id="operationPage">
<div class="app-shell">
<div class="page-topbar"><button class="page-back" onclick="backToWorkbench()">‹</button><div class="page-title" id="operationTitle">作业</div><button class="page-user" id="operationAvatar" onclick="openProfile()">张</button></div>
<div class="operation-content">
<div class="operation-hero"><div class="operation-hero-icon" id="operationIcon">📦</div><div class="operation-hero-title" id="operationHeroTitle">作业任务</div><div class="operation-hero-desc" id="operationDescription">扫描任务单或货物条码开始作业。</div></div>
<div class="task-card"><div class="task-card-title">待处理任务</div><div id="operationTaskList"></div></div>
<button class="scan-action" onclick="showToast('请扫描任务单或货物条码','success')">▦ 扫码开始作业</button>
</div>
</div>
</div>
<!-- ===== 个人中心 ===== -->
<div class="profile-page hidden" id="profilePage">
<div class="app-shell">
<div class="profile-cover"><button class="page-back" onclick="backFromProfile()">‹</button></div>
<div class="profile-card">
<div class="profile-avatar" id="profileAvatar">张</div><div class="profile-name" id="profileName">张伟</div><div class="profile-role" id="profileRole">W001 · 拣货员</div>
<div class="profile-stats"><div class="profile-stat"><strong>28</strong><span>今日完成</span></div><div class="profile-stat"><strong>156</strong><span>本月任务</span></div><div class="profile-stat"><strong>99.2%</strong><span>作业准确率</span></div></div>
</div>
<div class="profile-list">
<div class="profile-list-item"><span class="profile-list-icon">🏢</span><span>当前仓库</span><span class="profile-list-value" id="profileWarehouse">洛杉矶仓</span></div>
<div class="profile-list-item"><span class="profile-list-icon">🕘</span><span>当前班次</span><span class="profile-list-value">白班 08:00–17:00</span></div>
<div class="profile-list-item"><span class="profile-list-icon">🔐</span><span>修改密码</span><span class="profile-list-value">›</span></div>
<div class="profile-list-item"><span class="profile-list-icon">⚙️</span><span>系统设置</span><span class="profile-list-value">›</span></div>
<div class="profile-list-item"><span class="profile-list-icon">ℹ️</span><span>版本信息</span><span class="profile-list-value">V1.0.0</span></div>
</div>
<button class="profile-logout" onclick="handleLogout()">退出登录</button>
</div>
</div>
@@ -1081,10 +1384,10 @@
<div class="main-page hidden" id="mainPage">
<div class="header">
<div class="header-top">
<div class="header-title">集装箱拣货</div>
<div style="display:flex;align-items:center;gap:8px"><button class="logout-btn" onclick="backToWorkbench()" style="font-size:18px;padding:3px 9px">‹</button><div class="header-title">集装箱拣货</div></div>
<div style="display:flex;align-items:center;gap:8px;">
<div class="header-badge" id="headerBadge">仓库 A</div>
<button class="logout-btn" onclick="handleLogout()">退出</button>
<button class="logout-btn" id="pickingAvatar" onclick="openProfile()">张</button>
</div>
</div>
<div class="header-sub">
@@ -1229,51 +1532,127 @@
<script>
// ===== 登录逻辑 =====
const DEMO_ACCOUNTS = {
'W001': { pass: '123456', name: '张伟', role: '拣货员' },
'W002': { pass: '123456', name: '李敏', role: '拣货组长' },
'W003': { pass: '123456', name: '王磊', role: '仓管员' },
'W001': { pass: '123456', name: '张伟', role: '拣货员', warehouse: '洛杉矶仓' },
'W002': { pass: '123456', name: '李敏', role: '拣货组长', warehouse: '洛杉矶仓' },
'W003': { pass: '123456', name: '王磊', role: '仓管员', warehouse: '新泽西仓' },
};
let currentUser = null;
let profileReturnPage = 'workbenchPage';
function togglePassword() {
const input = document.getElementById('loginPass');
const button = document.getElementById('passwordToggle');
const showing = input.type === 'text';
input.type = showing ? 'password' : 'text';
button.setAttribute('aria-label', showing ? '显示密码' : '隐藏密码');
}
function handleLogin() {
const userId = document.getElementById('loginUser').value.trim();
const password = document.getElementById('loginPass').value;
const warehouse = document.getElementById('loginWarehouse').value;
if (!userId) { showLoginError('请输入工号'); return; }
if (!userId) { showLoginError('请输入用户名'); return; }
if (!password) { showLoginError('请输入密码'); return; }
// 检查账号
const account = DEMO_ACCOUNTS[userId];
if (!account || account.pass !== password) {
showLoginError('工号或密码错误');
showLoginError('用户名或密码错误');
return;
}
currentUser = { id: userId, name: account.name, role: account.role, warehouse: warehouse };
currentUser = { id: userId, name: account.name, role: account.role, warehouse: account.warehouse };
enterMainPage();
}
function quickLogin(id, name, role) {
currentUser = { id: id, name: name, role: role, warehouse: document.getElementById('loginWarehouse').value };
currentUser = { id: id, name: name, role: role, warehouse: (DEMO_ACCOUNTS[id] && DEMO_ACCOUNTS[id].warehouse) || '洛杉矶仓' };
enterMainPage();
}
function enterMainPage() {
document.getElementById('loginPage').classList.add('hidden');
document.getElementById('mainPage').classList.remove('hidden');
showAppPage('workbenchPage');
updateUserUI();
initStates();
updateContainerStats();
hideLoginError();
showToast(currentUser.name + ',欢迎登录', 'success');
}
function showAppPage(pageId) {
['workbenchPage','operationPage','profilePage','mainPage'].forEach(id => {
document.getElementById(id).classList.toggle('hidden', id !== pageId);
});
window.scrollTo(0, 0);
}
function updateUserUI() {
const initial = currentUser.name.slice(0, 1);
document.getElementById('headerBadge').textContent = currentUser.warehouse;
document.getElementById('headerUser').textContent = currentUser.name + ' · ' + currentUser.role;
hideLoginError();
initStates();
document.getElementById('workbenchUserName').textContent = currentUser.name;
document.getElementById('workbenchRole').textContent = currentUser.role;
document.getElementById('workbenchWarehouse').textContent = currentUser.warehouse;
document.getElementById('profileName').textContent = currentUser.name;
document.getElementById('profileRole').textContent = currentUser.id + ' · ' + currentUser.role;
document.getElementById('profileWarehouse').textContent = currentUser.warehouse;
['workbenchAvatar','operationAvatar','profileAvatar','pickingAvatar'].forEach(id => {
document.getElementById(id).textContent = initial;
});
}
function backToWorkbench() {
showAppPage('workbenchPage');
}
function openPicking() {
showAppPage('mainPage');
render();
showToast(currentUser.name + ',欢迎登录', 'success');
}
function openProfile() {
const visible = ['workbenchPage','operationPage','mainPage'].find(id => !document.getElementById(id).classList.contains('hidden'));
profileReturnPage = visible || 'workbenchPage';
showAppPage('profilePage');
}
function backFromProfile() {
showAppPage(profileReturnPage || 'workbenchPage');
}
const OPERATION_CONFIG = {
'inbound-receive': { icon:'📥', desc:'扫描入库单和货物条码,完成到仓签收与数量核验。', tasks:[['IN-260728-018','义乌欧业 · 18箱'],['IN-260728-021','青岛远航 · 12箱'],['IN-260728-026','深圳璟智 · 8箱']] },
'inbound-shelve': { icon:'🗄️', desc:'根据系统推荐库位完成货物上架,并确认实际存放位置。', tasks:[['SH-260728-008','A区 · 5项待上架'],['SH-260728-011','C区 · 3项待上架']] },
'inbound-measure': { icon:'📐', desc:'采集货物长宽高、重量与箱数,提交测量结果。', tasks:[['MS-260728-015','待测量 6箱'],['MS-260728-017','待复测 2箱']] },
'return-inbound': { icon:'↩️', desc:'核验退货信息、商品状态与数量,完成退件入库。', tasks:[['RT-260728-006','客户退货 · 4件'],['RT-260728-009','FBA退件 · 7件']] },
'wave-picking': { icon:'📋', desc:'按波次任务集中拣选多个订单,提高出库作业效率。', tasks:[['WV-260728-003','12单 · 36件'],['WV-260728-005','8单 · 24件']] },
'packing-review': { icon:'✅', desc:'扫描订单与商品,复核数量后完成装箱封包。', tasks:[['PK-260728-012','待复核 5箱'],['PK-260728-014','待复核 3箱']] },
'outbound-handover': { icon:'🚚', desc:'核对承运车辆、司机和出库货物,完成交接签字。', tasks:[['HO-260728-004','顺通车队 · 8托'],['HO-260728-007','宏达车队 · 12托']] },
'stock-transfer': { icon:'🔄', desc:'扫描原库位、商品和目标库位,完成库存移位。', tasks:[['MV-260728-019','A-03 → C-08 · 6件'],['MV-260728-022','B-01 → D-02 · 4件']] },
'stock-check': { icon:'📊', desc:'按盘点任务核对系统库存与实物数量,记录差异。', tasks:[['CK-260728-002','A区循环盘点'],['CK-260728-006','C区抽样盘点']] },
'location-query': { icon:'🔍', desc:'扫描 SKU、箱号或库位码,快速查询库存位置与数量。', tasks:[['快捷查询','支持 SKU / 箱号 / 库位码']] },
'exception': { icon:'⚠️', desc:'处理破损、短少、错货、库位异常等仓内问题。', tasks:[['EX-260728-003','数量差异 · 待复核'],['EX-260728-005','包装破损 · 待处理']] }
};
function openOperation(title, key) {
const config = OPERATION_CONFIG[key] || { icon:'📦', desc:'扫描任务单或货物条码开始作业。', tasks:[] };
document.getElementById('operationTitle').textContent = title;
document.getElementById('operationHeroTitle').textContent = title;
document.getElementById('operationIcon').textContent = config.icon;
document.getElementById('operationDescription').textContent = config.desc;
document.getElementById('operationTaskList').innerHTML = config.tasks.map((task, index) => `
<div class="task-row" onclick="showToast('已选择任务:${task[0]}','success')">
<div class="task-row-icon">${index + 1}</div>
<div class="task-row-main"><div class="task-row-name">${task[0]}</div><div class="task-row-desc">${task[1]}</div></div>
<div class="task-row-arrow">›</div>
</div>`).join('') || '<div style="padding:22px 0;text-align:center;color:#829ab1;font-size:12px">暂无待处理任务</div>';
showAppPage('operationPage');
}
function handleLogout() {
currentUser = null;
document.getElementById('loginPage').classList.remove('hidden');
document.getElementById('mainPage').classList.add('hidden');
['workbenchPage','operationPage','profilePage','mainPage'].forEach(id => document.getElementById(id).classList.add('hidden'));
// 清空表单
document.getElementById('loginUser').value = '';
document.getElementById('loginPass').value = '';
@@ -1296,6 +1675,10 @@ function hideLoginError() {
document.getElementById('loginError').classList.remove('show');
}
document.getElementById('loginPass').addEventListener('keydown', event => {
if (event.key === 'Enter') handleLogin();
});
// ===== 数据 =====
const BOXES = [
{
+204 -189
View File
@@ -1,210 +1,225 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 680 1170" width="100%" role="img" font-family="'PingFang SC','Microsoft YaHei','Hiragino Sans GB',sans-serif">
<title>头程与尾程物流流程图</title>
<desc>头程三大节点(下单、到仓、出仓)经装船发运进入尾程五大节点(到港前、到港、到仓、出仓、签收)的完整流程,左右两栏结构</desc>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1600 1100" width="1600" height="1100" role="img" aria-labelledby="title desc">
<title id="title">跨境物流全链路流程图</title>
<desc id="desc">从头程下单、到仓计费、出仓及装船发运,到尾程到港前、到港、到仓、出仓和签收的完整业务流程。</desc>
<defs>
<marker id="arrow" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
<path d="M2 1L8 5L2 9" fill="none" stroke="context-stroke" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<linearGradient id="pageBg" x1="0" y1="0" x2="1" y2="1">
<stop offset="0" stop-color="#F5F9FF"/>
<stop offset="1" stop-color="#F7FBFA"/>
</linearGradient>
<linearGradient id="firstMile" x1="0" y1="0" x2="1" y2="0">
<stop offset="0" stop-color="#155EEF"/>
<stop offset="1" stop-color="#2878FF"/>
</linearGradient>
<linearGradient id="lastMile" x1="0" y1="0" x2="1" y2="0">
<stop offset="0" stop-color="#087E8B"/>
<stop offset="1" stop-color="#16A085"/>
</linearGradient>
<linearGradient id="transit" x1="0" y1="0" x2="1" y2="0">
<stop offset="0" stop-color="#EAF2FF"/>
<stop offset="0.5" stop-color="#DDF5F1"/>
<stop offset="1" stop-color="#EAF2FF"/>
</linearGradient>
<filter id="shadow" x="-15%" y="-15%" width="130%" height="140%">
<feDropShadow dx="0" dy="8" stdDeviation="10" flood-color="#16324F" flood-opacity="0.09"/>
</filter>
<filter id="softShadow" x="-20%" y="-20%" width="140%" height="150%">
<feDropShadow dx="0" dy="4" stdDeviation="6" flood-color="#0F3057" flood-opacity="0.10"/>
</filter>
<marker id="arrowBlue" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="7" markerHeight="7" orient="auto">
<path d="M1 1L8 5L1 9" fill="none" stroke="#7AA7ED" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/>
</marker>
<marker id="arrowGreen" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="7" markerHeight="7" orient="auto">
<path d="M1 1L8 5L1 9" fill="none" stroke="#62B8AD" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/>
</marker>
<style>
text{font-family:"PingFang SC","Microsoft YaHei","Noto Sans SC",Arial,sans-serif}
.title{font-size:34px;font-weight:700;fill:#102A43;letter-spacing:1px}
.subtitle{font-size:15px;fill:#627D98}
.lane-title{font-size:22px;font-weight:700;fill:#fff}
.lane-en{font-size:11px;font-weight:600;fill:#fff;opacity:.72;letter-spacing:1.7px}
.phase-title{font-size:18px;font-weight:700;fill:#102A43}
.phase-no{font-size:11px;font-weight:700;fill:#fff;letter-spacing:.5px}
.step{font-size:13px;fill:#334E68}
.step-small{font-size:12px;fill:#334E68}
.step-no{font-size:10px;font-weight:700;fill:#fff}
.summary-label{font-size:11px;font-weight:700;fill:#627D98;letter-spacing:1px}
.summary-value{font-size:15px;font-weight:700;fill:#243B53}
</style>
</defs>
<line x1="340" y1="12" x2="340" y2="1160" stroke="#5F5E5A" stroke-width="1" stroke-dasharray="4 4" opacity="0.5"/>
<rect width="1600" height="1100" fill="url(#pageBg)"/>
<circle cx="1490" cy="50" r="180" fill="#D9F1ED" opacity=".42"/>
<circle cx="90" cy="1080" r="220" fill="#DFEBFF" opacity=".48"/>
<rect x="20" y="20" width="310" height="40" rx="8" fill="#185FA5"/>
<text x="175" y="40" text-anchor="middle" dominant-baseline="central" font-size="14" font-weight="500" fill="#FFFFFF">头程物流</text>
<rect x="350" y="20" width="320" height="40" rx="8" fill="#444441"/>
<text x="510" y="40" text-anchor="middle" dominant-baseline="central" font-size="13" font-weight="500" fill="#F1EFE8">尾程物流(装船发运后)</text>
<line x1="332" y1="40" x2="347" y2="40" stroke="#7b8190" stroke-width="1.5" marker-end="url(#arrow)"/>
<rect x="20" y="72" width="310" height="30" rx="6" fill="#185FA5"/>
<text x="175" y="87" text-anchor="middle" dominant-baseline="central" font-size="13" font-weight="500" fill="#E6F1FB">一、下单</text>
<g stroke="#85B7EB" stroke-width="1">
<line x1="175" y1="150" x2="175" y2="158"/>
<line x1="175" y1="198" x2="175" y2="206"/>
<line x1="175" y1="246" x2="175" y2="254"/>
</g>
<g>
<rect x="30" y="110" width="290" height="40" rx="8" fill="#042C53" stroke="#85B7EB" stroke-width="0.5"/>
<circle cx="52" cy="130" r="13" fill="#185FA5"/><text x="52" y="130" text-anchor="middle" dominant-baseline="central" font-size="11" font-weight="500" fill="#E6F1FB">1</text>
<text x="74" y="130" dominant-baseline="central" font-size="12" fill="#B5D4F4">客户下单</text>
<rect x="30" y="158" width="290" height="40" rx="8" fill="#042C53" stroke="#85B7EB" stroke-width="0.5"/>
<circle cx="52" cy="178" r="13" fill="#185FA5"/><text x="52" y="178" text-anchor="middle" dominant-baseline="central" font-size="11" font-weight="500" fill="#E6F1FB">2</text>
<text x="74" y="178" dominant-baseline="central" font-size="12" fill="#B5D4F4">委托我们下单</text>
<rect x="30" y="206" width="290" height="40" rx="8" fill="#042C53" stroke="#85B7EB" stroke-width="0.5"/>
<circle cx="52" cy="226" r="13" fill="#185FA5"/><text x="52" y="226" text-anchor="middle" dominant-baseline="central" font-size="11" font-weight="500" fill="#E6F1FB">3</text>
<text x="74" y="226" dominant-baseline="central" font-size="12" fill="#B5D4F4">快速下单(只有唛头)</text>
<rect x="30" y="254" width="290" height="40" rx="8" fill="#042C53" stroke="#85B7EB" stroke-width="0.5"/>
<circle cx="52" cy="274" r="13" fill="#185FA5"/><text x="52" y="274" text-anchor="middle" dominant-baseline="central" font-size="11" font-weight="500" fill="#E6F1FB">4</text>
<text x="74" y="274" dominant-baseline="central" font-size="12" fill="#B5D4F4">换标下单(中转、退货)</text>
<!-- 标题与概览 -->
<text x="52" y="58" class="title">跨境物流全链路流程</text>
<text x="52" y="88" class="subtitle">从客户下单到海外签收 · 头程与尾程全节点协同</text>
<g transform="translate(1195 28)">
<rect width="112" height="60" rx="14" fill="#fff" stroke="#D9E2EC"/>
<text x="18" y="22" class="summary-label">业务阶段</text><text x="18" y="45" class="summary-value">8 个阶段</text>
<rect x="124" width="112" height="60" rx="14" fill="#fff" stroke="#D9E2EC"/>
<text x="142" y="22" class="summary-label">关键动作</text><text x="142" y="45" class="summary-value">36 个节点</text>
<rect x="248" width="112" height="60" rx="14" fill="#fff" stroke="#D9E2EC"/>
<text x="266" y="22" class="summary-label">最终结果</text><text x="266" y="45" class="summary-value">完成签收</text>
</g>
<rect x="20" y="314" width="310" height="30" rx="6" fill="#3B6D11"/>
<text x="175" y="329" text-anchor="middle" dominant-baseline="central" font-size="13" font-weight="500" fill="#EAF3DE">二、到仓</text>
<g stroke="#97C459" stroke-width="1">
<line x1="175" y1="392" x2="175" y2="400"/>
<line x1="175" y1="440" x2="175" y2="448"/>
<line x1="175" y1="488" x2="175" y2="496"/>
<line x1="175" y1="536" x2="175" y2="544"/>
<!-- 头程泳道 -->
<rect x="30" y="120" width="1540" height="430" rx="24" fill="#FFFFFF" stroke="#D7E4F4" filter="url(#shadow)"/>
<path d="M54 120H1546A24 24 0 0 1 1570 144V194H30V144A24 24 0 0 1 54 120Z" fill="url(#firstMile)"/>
<g transform="translate(58 142)">
<circle cx="22" cy="22" r="22" fill="#fff" opacity=".16"/>
<path d="M10 23h24M14 23v11h16V23M17 19v-6h10v6M21 27h3" fill="none" stroke="#fff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<text x="58" y="18" class="lane-title">头程物流</text>
<text x="58" y="38" class="lane-en">FIRST-MILE LOGISTICS · 国内集货与出口</text>
</g>
<g>
<rect x="30" y="352" width="290" height="40" rx="8" fill="#173404" stroke="#97C459" stroke-width="0.5"/>
<circle cx="52" cy="372" r="13" fill="#3B6D11"/><text x="52" y="372" text-anchor="middle" dominant-baseline="central" font-size="11" font-weight="500" fill="#EAF3DE">1</text>
<text x="74" y="372" dominant-baseline="central" font-size="12" fill="#C0DD97">预约取货</text>
<rect x="30" y="400" width="290" height="40" rx="8" fill="#173404" stroke="#97C459" stroke-width="0.5"/>
<circle cx="52" cy="420" r="13" fill="#3B6D11"/><text x="52" y="420" text-anchor="middle" dominant-baseline="central" font-size="11" font-weight="500" fill="#EAF3DE">2</text>
<text x="74" y="420" dominant-baseline="central" font-size="12" fill="#C0DD97">送货上门</text>
<rect x="30" y="448" width="290" height="40" rx="8" fill="#173404" stroke="#97C459" stroke-width="0.5"/>
<circle cx="52" cy="468" r="13" fill="#3B6D11"/><text x="52" y="468" text-anchor="middle" dominant-baseline="central" font-size="11" font-weight="500" fill="#EAF3DE">3</text>
<text x="74" y="468" dominant-baseline="central" font-size="12" fill="#C0DD97">入库测量(称重计费)</text>
<rect x="30" y="496" width="290" height="40" rx="8" fill="#173404" stroke="#97C459" stroke-width="0.5"/>
<circle cx="52" cy="516" r="13" fill="#3B6D11"/><text x="52" y="516" text-anchor="middle" dominant-baseline="central" font-size="11" font-weight="500" fill="#EAF3DE">4</text>
<text x="74" y="516" dominant-baseline="central" font-size="12" fill="#C0DD97">调整差异核对</text>
<rect x="30" y="544" width="290" height="40" rx="8" fill="#173404" stroke="#97C459" stroke-width="0.5"/>
<circle cx="52" cy="564" r="13" fill="#3B6D11"/><text x="52" y="564" text-anchor="middle" dominant-baseline="central" font-size="11" font-weight="500" fill="#EAF3DE">5</text>
<text x="74" y="564" dominant-baseline="central" font-size="12" fill="#C0DD97">仓库作业(指定库位)</text>
<g transform="translate(1306 145)">
<rect width="210" height="42" rx="21" fill="#fff" opacity=".15"/>
<text x="105" y="26" text-anchor="middle" font-size="13" font-weight="600" fill="#fff">下单 → 到仓 → 出仓</text>
</g>
<rect x="20" y="604" width="310" height="30" rx="6" fill="#BA7517"/>
<text x="175" y="619" text-anchor="middle" dominant-baseline="central" font-size="13" font-weight="500" fill="#FAEEDA">三、出仓</text>
<g stroke="#EF9F27" stroke-width="1">
<line x1="175" y1="682" x2="175" y2="690"/>
<line x1="175" y1="730" x2="175" y2="738"/>
<line x1="175" y1="778" x2="175" y2="786"/>
<line x1="175" y1="826" x2="175" y2="834"/>
<line x1="175" y1="874" x2="175" y2="882"/>
<line x1="175" y1="922" x2="175" y2="930"/>
<line x1="175" y1="970" x2="175" y2="978"/>
<line x1="175" y1="1018" x2="175" y2="1026"/>
<line x1="175" y1="1066" x2="175" y2="1074"/>
</g>
<g>
<rect x="30" y="642" width="290" height="40" rx="8" fill="#412402" stroke="#EF9F27" stroke-width="0.5"/>
<circle cx="52" cy="662" r="13" fill="#BA7517"/><text x="52" y="662" text-anchor="middle" dominant-baseline="central" font-size="11" font-weight="500" fill="#FAEEDA">1</text>
<text x="74" y="662" dominant-baseline="central" font-size="12" fill="#FAC775">智能排柜</text>
<rect x="30" y="690" width="290" height="40" rx="8" fill="#412402" stroke="#EF9F27" stroke-width="0.5"/>
<circle cx="52" cy="710" r="13" fill="#BA7517"/><text x="52" y="710" text-anchor="middle" dominant-baseline="central" font-size="11" font-weight="500" fill="#FAEEDA">2</text>
<text x="74" y="710" dominant-baseline="central" font-size="12" fill="#FAC775">订舱</text>
<rect x="30" y="738" width="290" height="40" rx="8" fill="#412402" stroke="#EF9F27" stroke-width="0.5"/>
<circle cx="52" cy="758" r="13" fill="#BA7517"/><text x="52" y="758" text-anchor="middle" dominant-baseline="central" font-size="11" font-weight="500" fill="#FAEEDA">3</text>
<text x="74" y="758" dominant-baseline="central" font-size="12" fill="#FAC775">预约托车</text>
<rect x="30" y="786" width="290" height="40" rx="8" fill="#412402" stroke="#EF9F27" stroke-width="0.5"/>
<circle cx="52" cy="806" r="13" fill="#BA7517"/><text x="52" y="806" text-anchor="middle" dominant-baseline="central" font-size="11" font-weight="500" fill="#FAEEDA">4</text>
<text x="74" y="806" dominant-baseline="central" font-size="12" fill="#FAC775">PDA拣货</text>
<rect x="30" y="834" width="290" height="40" rx="8" fill="#412402" stroke="#EF9F27" stroke-width="0.5"/>
<circle cx="52" cy="854" r="13" fill="#BA7517"/><text x="52" y="854" text-anchor="middle" dominant-baseline="central" font-size="11" font-weight="500" fill="#FAEEDA">5</text>
<text x="74" y="854" dominant-baseline="central" font-size="12" fill="#FAC775">拍货柜及铅封照上传</text>
<rect x="30" y="882" width="290" height="40" rx="8" fill="#412402" stroke="#EF9F27" stroke-width="0.5"/>
<circle cx="52" cy="902" r="13" fill="#BA7517"/><text x="52" y="902" text-anchor="middle" dominant-baseline="central" font-size="11" font-weight="500" fill="#FAEEDA">6</text>
<text x="74" y="902" dominant-baseline="central" font-size="12" fill="#FAC775">客户上传报关资料</text>
<rect x="30" y="930" width="290" height="40" rx="8" fill="#412402" stroke="#EF9F27" stroke-width="0.5"/>
<circle cx="52" cy="950" r="13" fill="#BA7517"/><text x="52" y="950" text-anchor="middle" dominant-baseline="central" font-size="11" font-weight="500" fill="#FAEEDA">7</text>
<text x="74" y="950" dominant-baseline="central" font-size="12" fill="#FAC775">整理给到报关代理报关</text>
<rect x="30" y="978" width="290" height="40" rx="8" fill="#412402" stroke="#EF9F27" stroke-width="0.5"/>
<circle cx="52" cy="998" r="13" fill="#BA7517"/><text x="52" y="998" text-anchor="middle" dominant-baseline="central" font-size="11" font-weight="500" fill="#FAEEDA">8</text>
<text x="74" y="998" dominant-baseline="central" font-size="12" fill="#FAC775">回执上传到系统供客户下载</text>
<rect x="30" y="1026" width="290" height="40" rx="8" fill="#412402" stroke="#EF9F27" stroke-width="0.5"/>
<circle cx="52" cy="1046" r="13" fill="#BA7517"/><text x="52" y="1046" text-anchor="middle" dominant-baseline="central" font-size="11" font-weight="500" fill="#FAEEDA">9</text>
<text x="74" y="1046" dominant-baseline="central" font-size="12" fill="#FAC775">查港务信息(预计开船、到港等)</text>
</g>
<rect x="60" y="1074" width="230" height="28" rx="14" fill="none" stroke="#EF9F27" stroke-width="1"/>
<text x="175" y="1088" text-anchor="middle" dominant-baseline="central" font-size="13" fill="#EF9F27">出仓完成 · 装船发运</text>
<!-- 头程阶段连接 -->
<path d="M435 365H474" stroke="#7AA7ED" stroke-width="2" marker-end="url(#arrowBlue)"/>
<path d="M850 365H889" stroke="#7AA7ED" stroke-width="2" marker-end="url(#arrowBlue)"/>
<rect x="350" y="72" width="320" height="30" rx="6" fill="#0F6E56"/>
<text x="510" y="87" text-anchor="middle" dominant-baseline="central" font-size="13" font-weight="500" fill="#E1F5EE">一、到港前(船在海上)</text>
<g stroke="#5DCAA5" stroke-width="1">
<line x1="510" y1="150" x2="510" y2="158"/>
<line x1="510" y1="198" x2="510" y2="206"/>
<line x1="510" y1="246" x2="510" y2="254"/>
</g>
<g>
<rect x="360" y="110" width="300" height="40" rx="8" fill="#04342C" stroke="#5DCAA5" stroke-width="0.5"/>
<circle cx="382" cy="130" r="13" fill="#0F6E56"/><text x="382" y="130" text-anchor="middle" dominant-baseline="central" font-size="11" font-weight="500" fill="#E1F5EE">1</text>
<text x="404" y="130" dominant-baseline="central" font-size="12" fill="#E1F5EE">FBA 仓预约</text>
<rect x="360" y="158" width="300" height="40" rx="8" fill="#04342C" stroke="#5DCAA5" stroke-width="0.5"/>
<circle cx="382" cy="178" r="13" fill="#0F6E56"/><text x="382" y="178" text-anchor="middle" dominant-baseline="central" font-size="11" font-weight="500" fill="#E1F5EE">2</text>
<text x="404" y="178" dominant-baseline="central" font-size="12" fill="#E1F5EE">BOL 预清货(时间、费用、目的仓)</text>
<rect x="360" y="206" width="300" height="40" rx="8" fill="#04342C" stroke="#5DCAA5" stroke-width="0.5"/>
<circle cx="382" cy="226" r="13" fill="#0F6E56"/><text x="382" y="226" text-anchor="middle" dominant-baseline="central" font-size="11" font-weight="500" fill="#E1F5EE">3</text>
<text x="404" y="226" dominant-baseline="central" font-size="12" fill="#E1F5EE">清关资料上传到对应的货柜</text>
<rect x="360" y="254" width="300" height="40" rx="8" fill="#04342C" stroke="#5DCAA5" stroke-width="0.5"/>
<circle cx="382" cy="274" r="13" fill="#0F6E56"/><text x="382" y="274" text-anchor="middle" dominant-baseline="central" font-size="11" font-weight="500" fill="#E1F5EE">4</text>
<text x="404" y="274" dominant-baseline="central" font-size="12" fill="#E1F5EE">明细备注货物中转等</text>
<!-- 一、下单 -->
<g transform="translate(55 220)">
<rect width="380" height="300" rx="18" fill="#F8FBFF" stroke="#C9DBF7"/>
<circle cx="32" cy="32" r="17" fill="#155EEF"/><text x="32" y="36" text-anchor="middle" class="phase-no">01</text>
<text x="60" y="39" class="phase-title">下单</text>
<text x="326" y="37" font-size="11" fill="#829AB1">4 个动作</text>
<line x1="20" y1="64" x2="360" y2="64" stroke="#D9E8FA"/>
<g transform="translate(20 82)">
<rect width="340" height="42" rx="10" fill="#fff" stroke="#DFEAF8"/><circle cx="22" cy="21" r="11" fill="#3B82F6"/><text x="22" y="25" text-anchor="middle" class="step-no">1</text><text x="44" y="26" class="step">客户下单</text>
<rect y="52" width="340" height="42" rx="10" fill="#fff" stroke="#DFEAF8"/><circle cx="22" cy="73" r="11" fill="#3B82F6"/><text x="22" y="77" text-anchor="middle" class="step-no">2</text><text x="44" y="78" class="step">委托我们下单</text>
<rect y="104" width="340" height="42" rx="10" fill="#fff" stroke="#DFEAF8"/><circle cx="22" cy="125" r="11" fill="#3B82F6"/><text x="22" y="129" text-anchor="middle" class="step-no">3</text><text x="44" y="130" class="step">快速下单(只有唛头)</text>
<rect y="156" width="340" height="42" rx="10" fill="#fff" stroke="#DFEAF8"/><circle cx="22" cy="177" r="11" fill="#3B82F6"/><text x="22" y="181" text-anchor="middle" class="step-no">4</text><text x="44" y="182" class="step">换标下单(中转、退货)</text>
</g>
</g>
<rect x="350" y="314" width="320" height="30" rx="6" fill="#A32D2D"/>
<text x="510" y="329" text-anchor="middle" dominant-baseline="central" font-size="13" font-weight="500" fill="#FCEBEB">二、到港</text>
<g stroke="#F09595" stroke-width="1">
<line x1="510" y1="392" x2="510" y2="400"/>
</g>
<g>
<rect x="360" y="352" width="300" height="40" rx="8" fill="#501313" stroke="#F09595" stroke-width="0.5"/>
<circle cx="382" cy="372" r="13" fill="#A32D2D"/><text x="382" y="372" text-anchor="middle" dominant-baseline="central" font-size="11" font-weight="500" fill="#FCEBEB">1</text>
<text x="404" y="372" dominant-baseline="central" font-size="12" fill="#FCEBEB">清关放行</text>
<rect x="360" y="400" width="300" height="40" rx="8" fill="#501313" stroke="#F09595" stroke-width="0.5"/>
<circle cx="382" cy="420" r="13" fill="#A32D2D"/><text x="382" y="420" text-anchor="middle" dominant-baseline="central" font-size="11" font-weight="500" fill="#FCEBEB">2</text>
<text x="404" y="420" dominant-baseline="central" font-size="12" fill="#FCEBEB">DO或PU邮发并通知码头车队提柜</text>
<!-- 二、到仓 -->
<g transform="translate(470 220)">
<rect width="380" height="300" rx="18" fill="#F8FBFF" stroke="#C9DBF7"/>
<circle cx="32" cy="32" r="17" fill="#155EEF"/><text x="32" y="36" text-anchor="middle" class="phase-no">02</text>
<text x="60" y="39" class="phase-title">到仓</text>
<text x="326" y="37" font-size="11" fill="#829AB1">6 个动作</text>
<line x1="20" y1="64" x2="360" y2="64" stroke="#D9E8FA"/>
<g transform="translate(20 76)">
<rect width="340" height="32" rx="8" fill="#fff" stroke="#DFEAF8"/><circle cx="20" cy="16" r="10" fill="#3B82F6"/><text x="20" y="20" text-anchor="middle" class="step-no">1</text><text x="40" y="21" class="step">预约取货</text>
<rect y="36" width="340" height="32" rx="8" fill="#fff" stroke="#DFEAF8"/><circle cx="20" cy="52" r="10" fill="#3B82F6"/><text x="20" y="56" text-anchor="middle" class="step-no">2</text><text x="40" y="57" class="step">送货上门</text>
<rect y="72" width="340" height="32" rx="8" fill="#fff" stroke="#DFEAF8"/><circle cx="20" cy="88" r="10" fill="#3B82F6"/><text x="20" y="92" text-anchor="middle" class="step-no">3</text><text x="40" y="93" class="step">入库测量(称重计费)</text>
<rect y="108" width="340" height="32" rx="8" fill="#fff" stroke="#DFEAF8"/><circle cx="20" cy="124" r="10" fill="#3B82F6"/><text x="20" y="128" text-anchor="middle" class="step-no">4</text><text x="40" y="129" class="step">调整差异核对</text>
<rect y="144" width="340" height="32" rx="8" fill="#fff" stroke="#DFEAF8"/><circle cx="20" cy="160" r="10" fill="#3B82F6"/><text x="20" y="164" text-anchor="middle" class="step-no">5</text><text x="40" y="165" class="step">仓库作业(指定库位)</text>
<rect y="180" width="340" height="32" rx="8" fill="#EAF2FF" stroke="#BFD3F5"/><circle cx="20" cy="196" r="10" fill="#155EEF"/><text x="20" y="200" text-anchor="middle" class="step-no">6</text><text x="40" y="201" class="step" font-weight="600">计费</text>
</g>
</g>
<rect x="350" y="460" width="320" height="30" rx="6" fill="#534AB7"/>
<text x="510" y="475" text-anchor="middle" dominant-baseline="central" font-size="13" font-weight="500" fill="#EEEDFE">三、到仓</text>
<g stroke="#AFA9EC" stroke-width="1">
<line x1="510" y1="538" x2="510" y2="546"/>
<line x1="510" y1="586" x2="510" y2="594"/>
</g>
<g>
<rect x="360" y="498" width="300" height="40" rx="8" fill="#26215C" stroke="#AFA9EC" stroke-width="0.5"/>
<circle cx="382" cy="518" r="13" fill="#534AB7"/><text x="382" y="518" text-anchor="middle" dominant-baseline="central" font-size="11" font-weight="500" fill="#EEEDFE">1</text>
<text x="404" y="518" dominant-baseline="central" font-size="12" fill="#EEEDFE">开柜拍照比对</text>
<rect x="360" y="546" width="300" height="40" rx="8" fill="#26215C" stroke="#AFA9EC" stroke-width="0.5"/>
<circle cx="382" cy="566" r="13" fill="#534AB7"/><text x="382" y="566" text-anchor="middle" dominant-baseline="central" font-size="11" font-weight="500" fill="#EEEDFE">2</text>
<text x="404" y="566" dominant-baseline="central" font-size="12" fill="#EEEDFE">根据 PDA 需求打托作业</text>
<rect x="360" y="594" width="300" height="40" rx="8" fill="#26215C" stroke="#AFA9EC" stroke-width="0.5"/>
<circle cx="382" cy="614" r="13" fill="#534AB7"/><text x="382" y="614" text-anchor="middle" dominant-baseline="central" font-size="11" font-weight="500" fill="#EEEDFE">3</text>
<text x="404" y="614" dominant-baseline="central" font-size="12" fill="#EEEDFE">派送车队筛选预约</text>
<!-- 三、出仓 -->
<g transform="translate(885 220)">
<rect width="660" height="300" rx="18" fill="#F8FBFF" stroke="#C9DBF7"/>
<circle cx="32" cy="32" r="17" fill="#155EEF"/><text x="32" y="36" text-anchor="middle" class="phase-no">03</text>
<text x="60" y="39" class="phase-title">出仓</text>
<text x="604" y="37" font-size="11" fill="#829AB1">9 个动作</text>
<line x1="20" y1="64" x2="640" y2="64" stroke="#D9E8FA"/>
<g transform="translate(20 76)">
<rect width="300" height="36" rx="9" fill="#fff" stroke="#DFEAF8"/><circle cx="20" cy="18" r="10" fill="#3B82F6"/><text x="20" y="22" text-anchor="middle" class="step-no">1</text><text x="40" y="23" class="step-small">智能排柜</text>
<rect y="42" width="300" height="36" rx="9" fill="#fff" stroke="#DFEAF8"/><circle cx="20" cy="60" r="10" fill="#3B82F6"/><text x="20" y="64" text-anchor="middle" class="step-no">2</text><text x="40" y="65" class="step-small">订舱</text>
<rect y="84" width="300" height="36" rx="9" fill="#fff" stroke="#DFEAF8"/><circle cx="20" cy="102" r="10" fill="#3B82F6"/><text x="20" y="106" text-anchor="middle" class="step-no">3</text><text x="40" y="107" class="step-small">预约托车</text>
<rect y="126" width="300" height="36" rx="9" fill="#fff" stroke="#DFEAF8"/><circle cx="20" cy="144" r="10" fill="#3B82F6"/><text x="20" y="148" text-anchor="middle" class="step-no">4</text><text x="40" y="149" class="step-small">PDA 拣货</text>
<rect y="168" width="300" height="36" rx="9" fill="#fff" stroke="#DFEAF8"/><circle cx="20" cy="186" r="10" fill="#3B82F6"/><text x="20" y="190" text-anchor="middle" class="step-no">5</text><text x="40" y="191" class="step-small">拍货柜及铅封照上传</text>
<rect x="320" width="300" height="36" rx="9" fill="#fff" stroke="#DFEAF8"/><circle cx="340" cy="18" r="10" fill="#3B82F6"/><text x="340" y="22" text-anchor="middle" class="step-no">6</text><text x="360" y="23" class="step-small">客户上传报关资料</text>
<rect x="320" y="42" width="300" height="36" rx="9" fill="#fff" stroke="#DFEAF8"/><circle cx="340" cy="60" r="10" fill="#3B82F6"/><text x="340" y="64" text-anchor="middle" class="step-no">7</text><text x="360" y="65" class="step-small">整理给到报关代理报关</text>
<rect x="320" y="84" width="300" height="36" rx="9" fill="#fff" stroke="#DFEAF8"/><circle cx="340" cy="102" r="10" fill="#3B82F6"/><text x="340" y="106" text-anchor="middle" class="step-no">8</text><text x="360" y="107" class="step-small">回执上传系统供客户下载</text>
<rect x="320" y="126" width="300" height="36" rx="9" fill="#fff" stroke="#DFEAF8"/><circle cx="340" cy="144" r="10" fill="#3B82F6"/><text x="340" y="148" text-anchor="middle" class="step-no">9</text><text x="360" y="149" class="step-small">查港务信息(预计开船、到港等)</text>
<g transform="translate(320 171)"><rect width="300" height="32" rx="16" fill="#E7F0FF"/><circle cx="24" cy="16" r="8" fill="#155EEF"/><path d="M20 16h8M24 12v8" stroke="#fff" stroke-width="1.5"/><text x="44" y="21" font-size="12" font-weight="600" fill="#155EEF">完成国内出仓,等待装船</text></g>
</g>
</g>
<rect x="350" y="654" width="320" height="30" rx="6" fill="#993556"/>
<text x="510" y="669" text-anchor="middle" dominant-baseline="central" font-size="13" font-weight="500" fill="#FBEAF0">四、出仓</text>
<g stroke="#ED93B1" stroke-width="1">
<line x1="510" y1="730" x2="510" y2="738"/>
<line x1="510" y1="778" x2="510" y2="786"/>
<line x1="510" y1="826" x2="510" y2="834"/>
<line x1="510" y1="874" x2="510" y2="882"/>
</g>
<g>
<rect x="360" y="692" width="300" height="40" rx="8" fill="#4B1528" stroke="#ED93B1" stroke-width="0.5"/>
<circle cx="382" cy="712" r="13" fill="#993556"/><text x="382" y="712" text-anchor="middle" dominant-baseline="central" font-size="11" font-weight="500" fill="#FBEAF0">1</text>
<text x="404" y="712" dominant-baseline="central" font-size="12" fill="#FBEAF0">预排车转 BOL 送货</text>
<rect x="360" y="740" width="300" height="40" rx="8" fill="#4B1528" stroke="#ED93B1" stroke-width="0.5"/>
<circle cx="382" cy="760" r="13" fill="#993556"/><text x="382" y="760" text-anchor="middle" dominant-baseline="central" font-size="11" font-weight="500" fill="#FBEAF0">2</text>
<text x="404" y="760" dominant-baseline="central" font-size="12" fill="#FBEAF0">PDA拣货装车</text>
<rect x="360" y="788" width="300" height="40" rx="8" fill="#4B1528" stroke="#ED93B1" stroke-width="0.5"/>
<circle cx="382" cy="808" r="13" fill="#993556"/><text x="382" y="808" text-anchor="middle" dominant-baseline="central" font-size="11" font-weight="500" fill="#FBEAF0">3</text>
<text x="404" y="808" dominant-baseline="central" font-size="12" fill="#FBEAF0">派送车队到仓装车</text>
<rect x="360" y="836" width="300" height="40" rx="8" fill="#4B1528" stroke="#ED93B1" stroke-width="0.5"/>
<circle cx="382" cy="856" r="13" fill="#993556"/><text x="382" y="856" text-anchor="middle" dominant-baseline="central" font-size="11" font-weight="500" fill="#FBEAF0">4</text>
<text x="404" y="856" dominant-baseline="central" font-size="12" fill="#FBEAF0">整柜派送</text>
<rect x="360" y="884" width="300" height="40" rx="8" fill="#4B1528" stroke="#ED93B1" stroke-width="0.5"/>
<circle cx="382" cy="904" r="13" fill="#993556"/><text x="382" y="904" text-anchor="middle" dominant-baseline="central" font-size="11" font-weight="500" fill="#FBEAF0">5</text>
<text x="404" y="904" dominant-baseline="central" font-size="12" fill="#FBEAF0">自提出仓(一件代发)</text>
<!-- 海运衔接带 -->
<g transform="translate(350 570)" filter="url(#softShadow)">
<rect width="900" height="74" rx="37" fill="url(#transit)" stroke="#B9D8DF"/>
<path d="M0 37H286M614 37H900" stroke="#78AFC1" stroke-width="1.5" stroke-dasharray="7 7"/>
<g transform="translate(302 12)">
<circle cx="25" cy="25" r="25" fill="#fff"/>
<path d="M11 29h28l-4 7H16l-5-7Zm5-3h19l-3-11H19l-3 11Zm8-11V9h4v6" fill="none" stroke="#087E8B" stroke-width="2" stroke-linejoin="round"/>
<text x="68" y="23" font-size="16" font-weight="700" fill="#0B6070">装船发运 · 国际海运在途</text>
<text x="68" y="43" font-size="12" fill="#527C86">头程完成,进入海外清关与尾程履约</text>
</g>
</g>
<rect x="350" y="944" width="320" height="30" rx="6" fill="#B58900"/>
<text x="510" y="959" text-anchor="middle" dominant-baseline="central" font-size="13" font-weight="500" fill="#F5E6B8">五、签收</text>
<g stroke="#D9B94A" stroke-width="1">
<line x1="510" y1="1020" x2="510" y2="1028"/>
<line x1="510" y1="1068" x2="510" y2="1076"/>
<!-- 尾程泳道 -->
<rect x="30" y="670" width="1540" height="400" rx="24" fill="#FFFFFF" stroke="#CFE7E2" filter="url(#shadow)"/>
<path d="M54 670H1546A24 24 0 0 1 1570 694V744H30V694A24 24 0 0 1 54 670Z" fill="url(#lastMile)"/>
<g transform="translate(58 692)">
<circle cx="22" cy="22" r="22" fill="#fff" opacity=".16"/>
<path d="M10 27h7l3-10h10l3 10h3M15 27a4 4 0 1 0 0 8 4 4 0 0 0 0-8Zm20 0a4 4 0 1 0 0 8 4 4 0 0 0 0-8Z" fill="none" stroke="#fff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<text x="58" y="18" class="lane-title">尾程物流</text>
<text x="58" y="38" class="lane-en">LAST-MILE LOGISTICS · 海外清关、入仓与派送</text>
</g>
<g>
<rect x="360" y="982" width="300" height="40" rx="8" fill="#3A2E00" stroke="#D9B94A" stroke-width="0.5"/>
<circle cx="382" cy="1002" r="13" fill="#B58900"/><text x="382" y="1002" text-anchor="middle" dominant-baseline="central" font-size="11" font-weight="500" fill="#F5E6B8">1</text>
<text x="404" y="1002" dominant-baseline="central" font-size="12" fill="#F5E6B8">私人仓签收回执上传</text>
<rect x="360" y="1030" width="300" height="40" rx="8" fill="#3A2E00" stroke="#D9B94A" stroke-width="0.5"/>
<circle cx="382" cy="1050" r="13" fill="#B58900"/><text x="382" y="1050" text-anchor="middle" dominant-baseline="central" font-size="11" font-weight="500" fill="#F5E6B8">2</text>
<text x="404" y="1050" dominant-baseline="central" font-size="12" fill="#F5E6B8">FBA仓签收回执上传</text>
<rect x="360" y="1078" width="300" height="40" rx="8" fill="#3A2E00" stroke="#D9B94A" stroke-width="0.5"/>
<circle cx="382" cy="1098" r="13" fill="#B58900"/><text x="382" y="1098" text-anchor="middle" dominant-baseline="central" font-size="11" font-weight="500" fill="#F5E6B8">3</text>
<text x="404" y="1098" dominant-baseline="central" font-size="12" fill="#F5E6B8">送仓异常</text>
<g transform="translate(1185 695)">
<rect width="330" height="42" rx="21" fill="#fff" opacity=".15"/>
<text x="165" y="26" text-anchor="middle" font-size="13" font-weight="600" fill="#fff">到港前 → 到港 → 到仓 → 出仓 → 签收</text>
</g>
<rect x="390" y="1126" width="240" height="28" rx="14" fill="none" stroke="#D9B94A" stroke-width="1"/>
<text x="510" y="1140" text-anchor="middle" dominant-baseline="central" font-size="13" fill="#D9B94A">签收完成</text>
</svg>
<!-- 尾程连接线 -->
<path d="M328 900H352" stroke="#62B8AD" stroke-width="2" marker-end="url(#arrowGreen)"/>
<path d="M633 900H657" stroke="#62B8AD" stroke-width="2" marker-end="url(#arrowGreen)"/>
<path d="M938 900H962" stroke="#62B8AD" stroke-width="2" marker-end="url(#arrowGreen)"/>
<path d="M1243 900H1267" stroke="#62B8AD" stroke-width="2" marker-end="url(#arrowGreen)"/>
<!-- 尾程阶段卡片 -->
<g transform="translate(48 770)">
<rect width="280" height="268" rx="16" fill="#F7FCFB" stroke="#CBE7E1"/>
<circle cx="28" cy="29" r="16" fill="#087E8B"/><text x="28" y="33" text-anchor="middle" class="phase-no">01</text><text x="54" y="35" class="phase-title">到港前</text><text x="54" y="53" font-size="11" fill="#648A87">船在海上</text>
<g transform="translate(16 72)">
<rect width="248" height="36" rx="9" fill="#fff" stroke="#D8EBE7"/><circle cx="18" cy="18" r="10" fill="#13A18D"/><text x="18" y="22" text-anchor="middle" class="step-no">1</text><text x="38" y="23" class="step-small">FBA 仓预约</text>
<rect y="42" width="248" height="44" rx="9" fill="#fff" stroke="#D8EBE7"/><circle cx="18" cy="64" r="10" fill="#13A18D"/><text x="18" y="68" text-anchor="middle" class="step-no">2</text><text x="38" y="61" class="step-small">BOL 预清货</text><text x="38" y="77" font-size="10" fill="#829AB1">时间、费用、目的仓</text>
<rect y="92" width="248" height="42" rx="9" fill="#fff" stroke="#D8EBE7"/><circle cx="18" cy="113" r="10" fill="#13A18D"/><text x="18" y="117" text-anchor="middle" class="step-no">3</text><text x="38" y="110" class="step-small">清关资料上传到</text><text x="38" y="126" class="step-small">对应货柜</text>
<rect y="140" width="248" height="36" rx="9" fill="#fff" stroke="#D8EBE7"/><circle cx="18" cy="158" r="10" fill="#13A18D"/><text x="18" y="162" text-anchor="middle" class="step-no">4</text><text x="38" y="163" class="step-small">明细备注货物中转等</text>
</g>
</g>
<g transform="translate(353 770)">
<rect width="280" height="268" rx="16" fill="#F7FCFB" stroke="#CBE7E1"/>
<circle cx="28" cy="29" r="16" fill="#087E8B"/><text x="28" y="33" text-anchor="middle" class="phase-no">02</text><text x="54" y="35" class="phase-title">到港</text>
<g transform="translate(16 82)">
<rect width="248" height="50" rx="9" fill="#fff" stroke="#D8EBE7"/><circle cx="18" cy="25" r="10" fill="#13A18D"/><text x="18" y="29" text-anchor="middle" class="step-no">1</text><text x="38" y="30" class="step-small">清关放行</text>
<rect y="60" width="248" height="64" rx="9" fill="#fff" stroke="#D8EBE7"/><circle cx="18" cy="92" r="10" fill="#13A18D"/><text x="18" y="96" text-anchor="middle" class="step-no">2</text><text x="38" y="88" class="step-small">DO 或 PU 邮发</text><text x="38" y="106" class="step-small">通知码头车队提柜</text>
<rect y="136" width="248" height="38" rx="19" fill="#E3F6F2"/><text x="124" y="160" text-anchor="middle" font-size="12" font-weight="600" fill="#087E8B">完成提柜 · 运往海外仓</text>
</g>
</g>
<g transform="translate(658 770)">
<rect width="280" height="268" rx="16" fill="#F7FCFB" stroke="#CBE7E1"/>
<circle cx="28" cy="29" r="16" fill="#087E8B"/><text x="28" y="33" text-anchor="middle" class="phase-no">03</text><text x="54" y="35" class="phase-title">到仓</text>
<g transform="translate(16 82)">
<rect width="248" height="42" rx="9" fill="#fff" stroke="#D8EBE7"/><circle cx="18" cy="21" r="10" fill="#13A18D"/><text x="18" y="25" text-anchor="middle" class="step-no">1</text><text x="38" y="26" class="step-small">开柜拍照比对</text>
<rect y="50" width="248" height="42" rx="9" fill="#fff" stroke="#D8EBE7"/><circle cx="18" cy="71" r="10" fill="#13A18D"/><text x="18" y="75" text-anchor="middle" class="step-no">2</text><text x="38" y="76" class="step-small">根据 PDA 需求打托作业</text>
<rect y="100" width="248" height="42" rx="9" fill="#fff" stroke="#D8EBE7"/><circle cx="18" cy="121" r="10" fill="#13A18D"/><text x="18" y="125" text-anchor="middle" class="step-no">3</text><text x="38" y="126" class="step-small">派送车队筛选预约</text>
</g>
</g>
<g transform="translate(963 770)">
<rect width="280" height="268" rx="16" fill="#F7FCFB" stroke="#CBE7E1"/>
<circle cx="28" cy="29" r="16" fill="#087E8B"/><text x="28" y="33" text-anchor="middle" class="phase-no">04</text><text x="54" y="35" class="phase-title">出仓</text>
<g transform="translate(16 72)">
<rect width="248" height="34" rx="9" fill="#fff" stroke="#D8EBE7"/><circle cx="18" cy="17" r="9" fill="#13A18D"/><text x="18" y="21" text-anchor="middle" class="step-no">1</text><text x="36" y="22" class="step-small">预排车转 BOL 送货</text>
<rect y="40" width="248" height="34" rx="9" fill="#fff" stroke="#D8EBE7"/><circle cx="18" cy="57" r="9" fill="#13A18D"/><text x="18" y="61" text-anchor="middle" class="step-no">2</text><text x="36" y="62" class="step-small">PDA 拣货装车</text>
<rect y="80" width="248" height="34" rx="9" fill="#fff" stroke="#D8EBE7"/><circle cx="18" cy="97" r="9" fill="#13A18D"/><text x="18" y="101" text-anchor="middle" class="step-no">3</text><text x="36" y="102" class="step-small">派送车队到仓装车</text>
<rect y="120" width="248" height="34" rx="9" fill="#fff" stroke="#D8EBE7"/><circle cx="18" cy="137" r="9" fill="#13A18D"/><text x="18" y="141" text-anchor="middle" class="step-no">4</text><text x="36" y="142" class="step-small">整柜派送</text>
<rect y="160" width="248" height="34" rx="9" fill="#fff" stroke="#D8EBE7"/><circle cx="18" cy="177" r="9" fill="#13A18D"/><text x="18" y="181" text-anchor="middle" class="step-no">5</text><text x="36" y="182" class="step-small">自提出仓(一件代发)</text>
</g>
</g>
<g transform="translate(1268 770)">
<rect width="284" height="268" rx="16" fill="#F7FCFB" stroke="#CBE7E1"/>
<circle cx="28" cy="29" r="16" fill="#087E8B"/><text x="28" y="33" text-anchor="middle" class="phase-no">05</text><text x="54" y="35" class="phase-title">签收</text>
<g transform="translate(16 82)">
<rect width="252" height="42" rx="9" fill="#fff" stroke="#D8EBE7"/><circle cx="18" cy="21" r="10" fill="#13A18D"/><text x="18" y="25" text-anchor="middle" class="step-no">1</text><text x="38" y="26" class="step-small">私人仓签收回执上传</text>
<rect y="50" width="252" height="42" rx="9" fill="#fff" stroke="#D8EBE7"/><circle cx="18" cy="71" r="10" fill="#13A18D"/><text x="18" y="75" text-anchor="middle" class="step-no">2</text><text x="38" y="76" class="step-small">FBA 仓签收回执上传</text>
<rect y="100" width="252" height="42" rx="9" fill="#fff" stroke="#D8EBE7"/><circle cx="18" cy="121" r="10" fill="#13A18D"/><text x="18" y="125" text-anchor="middle" class="step-no">3</text><text x="38" y="126" class="step-small">送仓异常处理</text>
<g transform="translate(0 156)"><rect width="252" height="38" rx="19" fill="#087E8B"/><circle cx="24" cy="19" r="9" fill="#fff" opacity=".2"/><path d="M20 19l3 3 6-7" fill="none" stroke="#fff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/><text x="132" y="24" text-anchor="middle" font-size="13" font-weight="700" fill="#fff">全流程完成 · 已签收</text></g>
</g>
</g>
<text x="800" y="1088" text-anchor="middle" font-size="11" fill="#829AB1">HEAD-HAUL &amp; LAST-MILE LOGISTICS PROCESS · 全程节点可追踪</text>
</svg>

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 881 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 549 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 835 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 492 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

File diff suppressed because it is too large Load Diff
+266
View File
@@ -0,0 +1,266 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>%s</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+SC:wght@300;400;500;600;700;900&family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<script src="https://cdn.tailwindcss.com"></script>
<script>
tailwind.config = { theme: { extend: { colors: { brand: { green:'#4CAF50', greenDark:'#2E7D32', blue:'#1565C0', blueDark:'#0D47A1', teal:'#00838F', light:'#F0F7FF', dark:'#0A1628' } }, fontFamily: { sans:['Inter','Noto Sans SC','system-ui','sans-serif'] } } } };
</script>
<style>
:root { --primary:#1565C0; --primary-dark:#0D47A1; --accent:#4CAF50; --accent-dark:#2E7D32; }
* { scroll-behavior:smooth; }
body { font-family:'Inter','Noto Sans SC',system-ui,sans-serif; overflow-x:hidden; }
.gradient-text { background:linear-gradient(135deg,#1565C0 0%,#4CAF50 100%); -webkit-background-clip:text; -webkit-text-fill-color:transparent; background-clip:text; }
.gradient-bg { background:linear-gradient(135deg,#0A1628 0%,#1565C0 50%,#00838F 100%); }
.btn-primary { background:linear-gradient(135deg,#1565C0 0%,#0D47A1 100%); transition:all .3s ease; }
.btn-primary:hover { transform:translateY(-2px); box-shadow:0 10px 30px rgba(21,101,192,.35); }
.btn-accent { background:linear-gradient(135deg,#4CAF50 0%,#2E7D32 100%); transition:all .3s ease; }
.btn-accent:hover { transform:translateY(-2px); box-shadow:0 10px 30px rgba(76,175,80,.35); }
.input-field { transition:all .3s ease; }
.input-field:focus { border-color:#1565C0; box-shadow:0 0 0 4px rgba(21,101,192,.1); }
.auth-logo { display:block; filter:brightness(0) saturate(100%) invert(20%) sepia(84%) saturate(1926%) hue-rotate(202deg) brightness(94%) contrast(93%); }
.lang-switcher { display:flex; align-items:center; background:rgba(21,101,192,.08); border-radius:9999px; padding:3px; border:1px solid rgba(21,101,192,.15); }
.lang-switcher button { font-size:12px; font-weight:600; padding:4px 9px; border-radius:9999px; color:#0A1628; transition:all .25s ease; white-space:nowrap; }
.lang-switcher button:hover { color:#1565C0; }
.lang-switcher button.active { background:#1565C0; color:#fff; }
</style>
</head>
<body class="text-gray-800 antialiased bg-gray-50">
<!-- 顶部栏 -->
<header class="fixed top-0 inset-x-0 z-50 bg-white/95 backdrop-blur border-b border-gray-100">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 h-16 flex items-center justify-between">
<a href="index.html" class="flex items-center" aria-label="返回官网">
<img src="assets/logo.png" alt="柏悦物流" class="auth-logo" style="width:161px;height:60px;object-fit:contain;">
</a>
<div class="lang-switcher" id="langSwitcher">
<button data-lang="zh" class="active" title="中文">中</button>
<button data-lang="en" title="English">EN</button>
<button data-lang="es" title="Español (México)">🇲🇽</button>
</div>
</div>
</header>
<section id="loginSection" class="min-h-screen pt-24 pb-12 bg-gray-50 flex items-center">
<div class="w-full max-w-6xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="bg-white rounded-3xl shadow-2xl overflow-hidden">
<div class="grid lg:grid-cols-2">
<!-- 左侧视觉 -->
<div class="hidden lg:block relative">
<img src="https://images.unsplash.com/photo-1494412574643-ff11b0a5c1c3?ixlib=rb-4.0.3&auto=format&fit=crop&w=2070&q=80" alt="物流" class="absolute inset-0 w-full h-full object-cover">
<div class="absolute inset-0 gradient-bg opacity-90"></div>
<div class="relative z-10 p-12 h-full flex flex-col justify-between text-white">
<div>
<img src="assets/logo.png" alt="虫虫出海" style="width:161px;height:60px;object-fit:contain;">
<h2 class="text-3xl font-bold mb-4" data-i18n="login_welcome">欢迎回来</h2>
<p class="text-white/80" data-i18n="login_desc">登录虫虫出海平台,实时追踪货物轨迹,管理订单与库存。</p>
</div>
<div class="space-y-4">
<div class="flex items-center space-x-3">
<i class="fas fa-check-circle text-brand-green"></i>
<span data-i18n="login_feat1">全程可视化追踪</span>
</div>
<div class="flex items-center space-x-3">
<i class="fas fa-check-circle text-brand-green"></i>
<span data-i18n="login_feat2">智能订单管理</span>
</div>
<div class="flex items-center space-x-3">
<i class="fas fa-check-circle text-brand-green"></i>
<span data-i18n="login_feat3">在线询价下单</span>
</div>
</div>
</div>
</div>
<!-- 右侧表单 -->
<div class="p-8 sm:p-12 lg:p-16">
<div class="max-w-md mx-auto">
<h2 class="text-3xl font-bold text-gray-900 mb-2" data-i18n="login_title">账号登录</h2>
<p class="text-gray-600 mb-8"><span data-i18n="login_no_account">还没有账号?</span><button onclick="window.location.href='register.html'" class="text-brand-blue font-semibold hover:underline" data-i18n="login_register_link">立即注册</button></p>
<form id="loginForm" class="space-y-5">
<div>
<label class="block text-sm font-medium text-gray-700 mb-2" data-i18n="login_account_label">邮箱 / 手机号</label>
<div class="relative">
<i class="fas fa-user absolute left-4 top-1/2 -translate-y-1/2 text-gray-400"></i>
<input type="text" name="account" required placeholder="请输入邮箱或手机号" data-i18n-ph="login_account_ph" class="input-field w-full pl-11 pr-4 py-3.5 border border-gray-200 rounded-xl outline-none">
</div>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-2" data-i18n="login_password_label">密码</label>
<div class="relative">
<i class="fas fa-lock absolute left-4 top-1/2 -translate-y-1/2 text-gray-400"></i>
<input type="password" name="password" required placeholder="请输入密码" data-i18n-ph="login_password_ph" class="input-field w-full pl-11 pr-12 py-3.5 border border-gray-200 rounded-xl outline-none">
<button type="button" class="toggle-password absolute right-4 top-1/2 -translate-y-1/2 text-gray-400 hover:text-gray-600">
<i class="fas fa-eye"></i>
</button>
</div>
</div>
<div class="flex items-center justify-between text-sm">
<label class="flex items-center text-gray-600 cursor-pointer">
<input type="checkbox" class="w-4 h-4 text-brand-blue rounded border-gray-300 mr-2">
<span data-i18n="login_remember">记住我</span>
</label>
<button type="button" onclick="showToast(t('toast_resetpw'))" class="text-brand-blue hover:underline" data-i18n="login_forgot">忘记密码?</button>
</div>
<button type="submit" class="btn-primary w-full text-white font-bold py-4 rounded-xl text-lg" data-i18n="login_submit">
登 录
</button>
</form>
<div class="mt-8">
<div class="relative">
<div class="absolute inset-0 flex items-center">
<div class="w-full border-t border-gray-200"></div>
</div>
<div class="relative flex justify-center text-sm">
<span class="px-2 bg-white text-gray-500" data-i18n="login_other">其他方式登录</span>
</div>
</div>
<div class="flex justify-center space-x-4 mt-6">
<button onclick="showToast('微信登录即将上线')" class="w-12 h-12 rounded-full border border-gray-200 flex items-center justify-center text-green-600 hover:bg-green-50 transition-colors">
<i class="fab fa-weixin text-xl"></i>
</button>
<button onclick="showToast('企业微信登录即将上线')" class="w-12 h-12 rounded-full border border-gray-200 flex items-center justify-center text-blue-600 hover:bg-blue-50 transition-colors">
<i class="fas fa-briefcase text-xl"></i>
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</section> <!-- Toast 提示 -->
<div id="toast" class="fixed top-24 left-1/2 -translate-x-1/2 z-[60] opacity-0 pointer-events-none transition-all duration-300 transform -translate-y-4">
<div class="bg-gray-900 text-white px-6 py-3 rounded-full shadow-2xl flex items-center space-x-2">
<i class="fas fa-info-circle text-brand-green"></i>
<span id="toastMessage">提示信息</span>
</div>
</div>
<script>
let currentLang = localStorage.getItem('cc_lang') || 'zh';
function t(key) {
return (i18n[currentLang] && i18n[currentLang][key] !== undefined) ? i18n[currentLang][key] : key;
}
const i18n = {
zh: {
login_welcome: "欢迎回来",
login_desc: "登录虫虫出海平台,实时追踪货物轨迹,管理订单与库存。",
login_feat1: "全程可视化追踪",
login_feat2: "智能订单管理",
login_feat3: "在线询价下单",
login_title: "账号登录",
login_no_account: "还没有账号?",
login_register_link: "立即注册",
login_account_label: "邮箱 / 手机号",
login_account_ph: "请输入邮箱或手机号",
login_password_label: "密码",
login_password_ph: "请输入密码",
login_remember: "记住我",
login_forgot: "忘记密码?",
login_submit: "登 录",
login_other: "其他方式登录",
toast_resetpw: "请联系客服重置密码",
toast_login_ok: "登录成功!欢迎回来"
},
en: {
login_welcome: "Welcome Back",
login_desc: "Log in to track shipments in real time and manage orders and inventory.",
login_feat1: "Full Visual Tracking",
login_feat2: "Smart Order Management",
login_feat3: "Online Quoting & Ordering",
login_title: "Account Login",
login_no_account: "No account yet?",
login_register_link: "Sign Up Now",
login_account_label: "Email / Phone",
login_account_ph: "Enter email or phone",
login_password_label: "Password",
login_password_ph: "Enter password",
login_remember: "Remember Me",
login_forgot: "Forgot Password?",
login_submit: "Log In",
login_other: "Other Sign-In Methods",
toast_resetpw: "Please contact support to reset your password",
toast_login_ok: "Login successful! Welcome back"
},
es: {
login_welcome: "Bienvenido de nuevo",
login_desc: "Inicia sesión para rastrear envíos en tiempo real y gestionar pedidos e inventario.",
login_feat1: "Seguimiento visual completo",
login_feat2: "Gestión inteligente de pedidos",
login_feat3: "Cotización y pedidos en línea",
login_title: "Inicio de sesión",
login_no_account: "¿Aún no tienes cuenta?",
login_register_link: "Regístrate ahora",
login_account_label: "Correo / Teléfono",
login_account_ph: "Ingresa correo o teléfono",
login_password_label: "Contraseña",
login_password_ph: "Ingresa tu contraseña",
login_remember: "Recuérdame",
login_forgot: "¿Olvidó su contraseña?",
login_submit: "Iniciar sesión",
login_other: "Otros métodos de acceso",
toast_resetpw: "Contacta a soporte para restablecer tu contraseña",
toast_login_ok: "¡Inicio de sesión exitoso! Bienvenido"
}
};
function applyLanguage(lang) {
if (!i18n[lang]) lang = 'zh';
currentLang = lang;
const langAttr = lang === 'zh' ? 'zh-CN' : (lang === 'es' ? 'es-MX' : 'en');
document.documentElement.setAttribute('lang', langAttr);
document.querySelectorAll('[data-i18n]').forEach(el => {
const k = el.getAttribute('data-i18n');
const v = i18n[lang][k];
if (v !== undefined) { if (v.indexOf('<br>') !== -1) el.innerHTML = v; else el.textContent = v; }
});
document.querySelectorAll('[data-i18n-ph]').forEach(el => {
const k = el.getAttribute('data-i18n-ph');
if (i18n[lang][k] !== undefined) el.setAttribute('placeholder', i18n[lang][k]);
});
document.querySelectorAll('[data-lang]').forEach(b => {
b.classList.toggle('active', b.getAttribute('data-lang') === lang);
});
try { localStorage.setItem('cc_lang', lang); } catch (e) {}
}
document.querySelectorAll('#langSwitcher [data-lang]').forEach(b => {
b.addEventListener('click', () => applyLanguage(b.getAttribute('data-lang')));
});
function showToast(message) {
const toast = document.getElementById('toast');
const toastMessage = document.getElementById('toastMessage');
toastMessage.textContent = message;
toast.classList.remove('opacity-0', 'pointer-events-none', '-translate-y-4');
toast.classList.add('opacity-100', 'translate-y-0');
setTimeout(() => {
toast.classList.add('opacity-0', 'pointer-events-none', '-translate-y-4');
toast.classList.remove('opacity-100', 'translate-y-0');
}, 3000);
}
function updateAuthUI() {}
document.querySelectorAll('.toggle-password').forEach(button => {
button.addEventListener('click', function() {
const input = this.previousElementSibling;
const icon = this.querySelector('i');
if (input.type === 'password') { input.type = 'text'; icon.classList.remove('fa-eye'); icon.classList.add('fa-eye-slash'); }
else { input.type = 'password'; icon.classList.remove('fa-eye-slash'); icon.classList.add('fa-eye'); }
});
});
document.getElementById('loginForm').addEventListener('submit', function(e) {
e.preventDefault();
showToast(t('toast_login_ok'));
setTimeout(() => window.location.href = 'workbench.html', 900);
});
applyLanguage(currentLang);
</script>
</body>
</html>
Binary file not shown.

After

Width:  |  Height:  |  Size: 764 KiB

+286
View File
@@ -0,0 +1,286 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>%s</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+SC:wght@300;400;500;600;700;900&family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<script src="https://cdn.tailwindcss.com"></script>
<script>
tailwind.config = { theme: { extend: { colors: { brand: { green:'#4CAF50', greenDark:'#2E7D32', blue:'#1565C0', blueDark:'#0D47A1', teal:'#00838F', light:'#F0F7FF', dark:'#0A1628' } }, fontFamily: { sans:['Inter','Noto Sans SC','system-ui','sans-serif'] } } } };
</script>
<style>
:root { --primary:#1565C0; --primary-dark:#0D47A1; --accent:#4CAF50; --accent-dark:#2E7D32; }
* { scroll-behavior:smooth; }
body { font-family:'Inter','Noto Sans SC',system-ui,sans-serif; overflow-x:hidden; }
.gradient-text { background:linear-gradient(135deg,#1565C0 0%,#4CAF50 100%); -webkit-background-clip:text; -webkit-text-fill-color:transparent; background-clip:text; }
.gradient-bg { background:linear-gradient(135deg,#0A1628 0%,#1565C0 50%,#00838F 100%); }
.btn-primary { background:linear-gradient(135deg,#1565C0 0%,#0D47A1 100%); transition:all .3s ease; }
.btn-primary:hover { transform:translateY(-2px); box-shadow:0 10px 30px rgba(21,101,192,.35); }
.btn-accent { background:linear-gradient(135deg,#4CAF50 0%,#2E7D32 100%); transition:all .3s ease; }
.btn-accent:hover { transform:translateY(-2px); box-shadow:0 10px 30px rgba(76,175,80,.35); }
.input-field { transition:all .3s ease; }
.input-field:focus { border-color:#1565C0; box-shadow:0 0 0 4px rgba(21,101,192,.1); }
.auth-logo { display:block; filter:brightness(0) saturate(100%) invert(20%) sepia(84%) saturate(1926%) hue-rotate(202deg) brightness(94%) contrast(93%); }
.lang-switcher { display:flex; align-items:center; background:rgba(21,101,192,.08); border-radius:9999px; padding:3px; border:1px solid rgba(21,101,192,.15); }
.lang-switcher button { font-size:12px; font-weight:600; padding:4px 9px; border-radius:9999px; color:#0A1628; transition:all .25s ease; white-space:nowrap; }
.lang-switcher button:hover { color:#1565C0; }
.lang-switcher button.active { background:#1565C0; color:#fff; }
</style>
</head>
<body class="text-gray-800 antialiased bg-gray-50">
<!-- 顶部栏 -->
<header class="fixed top-0 inset-x-0 z-50 bg-white/95 backdrop-blur border-b border-gray-100">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 h-16 flex items-center justify-between">
<a href="index.html" class="flex items-center" aria-label="返回官网">
<img src="assets/logo.png" alt="柏悦物流" class="auth-logo" style="width:161px;height:60px;object-fit:contain;">
</a>
<div class="lang-switcher" id="langSwitcher">
<button data-lang="zh" class="active" title="中文">中</button>
<button data-lang="en" title="English">EN</button>
<button data-lang="es" title="Español (México)">🇲🇽</button>
</div>
</div>
</header>
<section id="registerSection" class="min-h-screen pt-24 pb-12 bg-gray-50 flex items-center">
<div class="w-full max-w-6xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="bg-white rounded-3xl shadow-2xl overflow-hidden">
<div class="grid lg:grid-cols-2">
<!-- 左侧视觉 -->
<div class="hidden lg:block relative">
<img src="https://images.unsplash.com/photo-1566576912321-d58ddd7a6088?ixlib=rb-4.0.3&auto=format&fit=crop&w=2070&q=80" alt="物流仓储" class="absolute inset-0 w-full h-full object-cover">
<div class="absolute inset-0 gradient-bg opacity-90"></div>
<div class="relative z-10 p-12 h-full flex flex-col justify-between text-white">
<div>
<img src="assets/logo.png" alt="虫虫出海" style="width:161px;height:60px;object-fit:contain;">
<h2 class="text-3xl font-bold mb-4" data-i18n="reg_welcome">加入我们</h2>
<p class="text-white/80" data-i18n="reg_welcome_desc">注册虫虫出海企业账号,开启高效跨境物流体验。</p>
</div>
<div class="space-y-4">
<div class="flex items-center space-x-3">
<i class="fas fa-check-circle text-brand-green"></i>
<span data-i18n="reg_feat1">新用户专属优惠</span>
</div>
<div class="flex items-center space-x-3">
<i class="fas fa-check-circle text-brand-green"></i>
<span data-i18n="reg_feat2">免费获取物流方案</span>
</div>
<div class="flex items-center space-x-3">
<i class="fas fa-check-circle text-brand-green"></i>
<span data-i18n="reg_feat3">专属客户经理对接</span>
</div>
</div>
</div>
</div>
<!-- 右侧表单 -->
<div class="p-8 sm:p-12 lg:p-16">
<div class="max-w-md mx-auto">
<h2 class="text-3xl font-bold text-gray-900 mb-2" data-i18n="reg_title">企业注册</h2>
<p class="text-gray-600 mb-8"><span data-i18n="reg_have_account">已有账号?</span><button onclick="window.location.href='login.html'" class="text-brand-blue font-semibold hover:underline" data-i18n="reg_login_link">立即登录</button></p>
<form id="registerForm" class="space-y-5">
<div class="grid sm:grid-cols-2 gap-5">
<div>
<label class="block text-sm font-medium text-gray-700 mb-2" data-i18n="reg_company_label">企业名称</label>
<input type="text" name="company" required placeholder="请输入企业名称" data-i18n-ph="reg_company_ph" class="input-field w-full px-4 py-3.5 border border-gray-200 rounded-xl outline-none">
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-2" data-i18n="reg_contact_label">联系人</label>
<input type="text" name="contact" required placeholder="请输入联系人姓名" data-i18n-ph="reg_contact_ph" class="input-field w-full px-4 py-3.5 border border-gray-200 rounded-xl outline-none">
</div>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-2" data-i18n="reg_email_label">邮箱</label>
<div class="relative">
<i class="fas fa-envelope absolute left-4 top-1/2 -translate-y-1/2 text-gray-400"></i>
<input type="email" name="email" required placeholder="请输入企业邮箱" data-i18n-ph="reg_email_ph" class="input-field w-full pl-11 pr-4 py-3.5 border border-gray-200 rounded-xl outline-none">
</div>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-2" data-i18n="reg_phone_label">手机号</label>
<div class="relative">
<i class="fas fa-phone absolute left-4 top-1/2 -translate-y-1/2 text-gray-400"></i>
<input type="tel" name="phone" required placeholder="请输入手机号" data-i18n-ph="reg_phone_ph" class="input-field w-full pl-11 pr-4 py-3.5 border border-gray-200 rounded-xl outline-none">
</div>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-2" data-i18n="reg_password_label">密码</label>
<div class="relative">
<i class="fas fa-lock absolute left-4 top-1/2 -translate-y-1/2 text-gray-400"></i>
<input type="password" name="password" required placeholder="请设置8-20位密码" data-i18n-ph="reg_password_ph" class="input-field w-full pl-11 pr-12 py-3.5 border border-gray-200 rounded-xl outline-none">
<button type="button" class="toggle-password absolute right-4 top-1/2 -translate-y-1/2 text-gray-400 hover:text-gray-600">
<i class="fas fa-eye"></i>
</button>
</div>
</div>
<div class="flex items-start">
<input type="checkbox" id="agree" required class="w-4 h-4 text-brand-blue rounded border-gray-300 mt-1 mr-2">
<label for="agree" class="text-sm text-gray-600">
<span data-i18n="reg_agree">我已阅读并同意</span> <button type="button" onclick="showToast(t('toast_tos'))" class="text-brand-blue hover:underline" data-i18n="reg_agree_tos">《用户服务协议》</button> 和 <button type="button" onclick="showToast(t('toast_pp'))" class="text-brand-blue hover:underline" data-i18n="reg_agree_pp">《隐私政策》</button>
</label>
</div>
<button type="submit" class="btn-accent w-full text-white font-bold py-4 rounded-xl text-lg" data-i18n="reg_submit">
立即注册
</button>
</form>
</div>
</div>
</div>
</div>
</div>
</section> <!-- Toast 提示 -->
<div id="toast" class="fixed top-24 left-1/2 -translate-x-1/2 z-[60] opacity-0 pointer-events-none transition-all duration-300 transform -translate-y-4">
<div class="bg-gray-900 text-white px-6 py-3 rounded-full shadow-2xl flex items-center space-x-2">
<i class="fas fa-info-circle text-brand-green"></i>
<span id="toastMessage">提示信息</span>
</div>
</div>
<script>
let currentLang = localStorage.getItem('cc_lang') || 'zh';
function t(key) {
return (i18n[currentLang] && i18n[currentLang][key] !== undefined) ? i18n[currentLang][key] : key;
}
const i18n = {
zh: {
reg_welcome: "加入我们",
reg_welcome_desc: "注册虫虫出海企业账号,开启高效跨境物流体验。",
reg_feat1: "新用户专属优惠",
reg_feat2: "免费获取物流方案",
reg_feat3: "专属客户经理对接",
reg_title: "企业注册",
reg_have_account: "已有账号?",
reg_login_link: "立即登录",
reg_company_label: "企业名称",
reg_company_ph: "请输入企业名称",
reg_contact_label: "联系人",
reg_contact_ph: "请输入联系人姓名",
reg_email_label: "邮箱",
reg_email_ph: "请输入企业邮箱",
reg_phone_label: "手机号",
reg_phone_ph: "请输入手机号",
reg_password_label: "密码",
reg_password_ph: "请设置8-20位密码",
reg_agree: "我已阅读并同意",
reg_agree_tos: "《用户服务协议》",
reg_agree_pp: "《隐私政策》",
reg_submit: "立即注册",
toast_tos: "服务协议即将上线",
toast_pp: "隐私政策即将上线",
toast_register_ok: "注册成功!欢迎加入虫虫出海"
},
en: {
reg_welcome: "Join Us",
reg_welcome_desc: "Register a Chongchong Global business account and start efficient cross-border logistics.",
reg_feat1: "Exclusive New-User Offers",
reg_feat2: "Free Logistics Plan",
reg_feat3: "Dedicated Account Manager",
reg_title: "Business Registration",
reg_have_account: "Already have an account?",
reg_login_link: "Log In Now",
reg_company_label: "Company Name",
reg_company_ph: "Enter company name",
reg_contact_label: "Contact Person",
reg_contact_ph: "Enter contact name",
reg_email_label: "Email",
reg_email_ph: "Enter company email",
reg_phone_label: "Phone Number",
reg_phone_ph: "Enter phone number",
reg_password_label: "Password",
reg_password_ph: "Set an 8-20 char password",
reg_agree: "I have read and agree to the",
reg_agree_tos: "User Agreement",
reg_agree_pp: "Privacy Policy",
reg_submit: "Sign Up Now",
toast_tos: "Terms of Service coming soon",
toast_pp: "Privacy Policy coming soon",
toast_register_ok: "Registration successful! Welcome to Chongchong Global"
},
es: {
reg_welcome: "Únete a nosotros",
reg_welcome_desc: "Regístrate en la cuenta empresarial de Chongchong Global y comienza una logística eficiente.",
reg_feat1: "Ofertas exclusivas para nuevos usuarios",
reg_feat2: "Plan logístico gratuito",
reg_feat3: "Gerente de cuenta dedicado",
reg_title: "Registro empresarial",
reg_have_account: "¿Ya tienes una cuenta?",
reg_login_link: "Inicia sesión ahora",
reg_company_label: "Nombre de empresa",
reg_company_ph: "Ingresa el nombre de empresa",
reg_contact_label: "Persona de contacto",
reg_contact_ph: "Ingresa el nombre de contacto",
reg_email_label: "Correo electrónico",
reg_email_ph: "Ingresa el correo empresarial",
reg_phone_label: "Número de teléfono",
reg_phone_ph: "Ingresa tu número de teléfono",
reg_password_label: "Contraseña",
reg_password_ph: "Define una contraseña de 8-20 caracteres",
reg_agree: "He leído y acepto los",
reg_agree_tos: "Términos de servicio",
reg_agree_pp: "Política de privacidad",
reg_submit: "Regístrate ahora",
toast_tos: "Términos de servicio próximamente",
toast_pp: "Política de privacidad próximamente",
toast_register_ok: "¡Registro exitoso! Bienvenido a Chongchong Global"
}
};
function applyLanguage(lang) {
if (!i18n[lang]) lang = 'zh';
currentLang = lang;
const langAttr = lang === 'zh' ? 'zh-CN' : (lang === 'es' ? 'es-MX' : 'en');
document.documentElement.setAttribute('lang', langAttr);
document.querySelectorAll('[data-i18n]').forEach(el => {
const k = el.getAttribute('data-i18n');
const v = i18n[lang][k];
if (v !== undefined) { if (v.indexOf('<br>') !== -1) el.innerHTML = v; else el.textContent = v; }
});
document.querySelectorAll('[data-i18n-ph]').forEach(el => {
const k = el.getAttribute('data-i18n-ph');
if (i18n[lang][k] !== undefined) el.setAttribute('placeholder', i18n[lang][k]);
});
document.querySelectorAll('[data-lang]').forEach(b => {
b.classList.toggle('active', b.getAttribute('data-lang') === lang);
});
try { localStorage.setItem('cc_lang', lang); } catch (e) {}
}
document.querySelectorAll('#langSwitcher [data-lang]').forEach(b => {
b.addEventListener('click', () => applyLanguage(b.getAttribute('data-lang')));
});
function showToast(message) {
const toast = document.getElementById('toast');
const toastMessage = document.getElementById('toastMessage');
toastMessage.textContent = message;
toast.classList.remove('opacity-0', 'pointer-events-none', '-translate-y-4');
toast.classList.add('opacity-100', 'translate-y-0');
setTimeout(() => {
toast.classList.add('opacity-0', 'pointer-events-none', '-translate-y-4');
toast.classList.remove('opacity-100', 'translate-y-0');
}, 3000);
}
function updateAuthUI() {}
document.querySelectorAll('.toggle-password').forEach(button => {
button.addEventListener('click', function() {
const input = this.previousElementSibling;
const icon = this.querySelector('i');
if (input.type === 'password') { input.type = 'text'; icon.classList.remove('fa-eye'); icon.classList.add('fa-eye-slash'); }
else { input.type = 'password'; icon.classList.remove('fa-eye-slash'); icon.classList.add('fa-eye'); }
});
});
document.getElementById('registerForm').addEventListener('submit', function(e) {
e.preventDefault();
showToast(t('toast_register_ok'));
setTimeout(() => window.location.href = 'workbench.html', 900);
});
applyLanguage(currentLang);
</script>
</body>
</html>
File diff suppressed because it is too large Load Diff
Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

+396 -7
View File
@@ -3,7 +3,7 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>虫虫出海 - 移动端</title>
<title>柏悦物流 - 跨境物流服务平台</title>
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.min.js"></script>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
@@ -1712,6 +1712,385 @@
from { opacity: 0; transform: translateX(-50%) translateY(-10px); }
to { opacity: 1; transform: translateX(-50%) translateY(0); }
}
/* ==== 2026 UI REDESIGN: CROSS-BORDER OPERATIONS ==== */
:root {
--navy: #12304a;
--blue: #176b87;
--cyan: #0f8f91;
--mint: #dff5f1;
--orange: #d85b6a;
--ink: #172936;
--muted: #6c7d89;
--line: #dce5e9;
--surface: #ffffff;
--canvas: #eef3f5;
--danger-new: #d84a4a;
}
html { background: var(--canvas); }
body {
background: var(--canvas);
color: var(--ink);
animation: none;
}
body::before, body::after { display: none; }
.app { background: var(--canvas); box-shadow: 0 0 34px rgba(18,48,74,.08); }
.glass-card {
background: var(--surface);
backdrop-filter: none;
-webkit-backdrop-filter: none;
border: 1px solid var(--line);
border-radius: 8px;
box-shadow: 0 2px 8px rgba(18,48,74,.05);
}
.glass-card:hover { transform: none; box-shadow: 0 2px 8px rgba(18,48,74,.05); }
button, input, textarea, select { font-family: inherit; }
button, [onclick] { -webkit-tap-highlight-color: transparent; }
button:focus-visible, input:focus-visible, textarea:focus-visible, select:focus-visible {
outline: 3px solid rgba(15,143,145,.17);
outline-offset: 2px;
}
.btn-primary, .submit-btn, .btn-settle {
background: var(--cyan);
border-radius: 7px;
box-shadow: 0 4px 10px rgba(15,143,145,.18);
}
.btn-primary:hover, .btn-settle:hover { transform: none; box-shadow: 0 4px 10px rgba(15,143,145,.18); }
.input-field {
min-height: 46px;
padding: 12px 13px;
border: 1px solid #cdd9df;
border-radius: 7px;
background: #f9fbfc;
color: var(--ink);
font-size: 16px;
}
.input-field:focus {
border-color: var(--cyan);
background: #fff;
box-shadow: 0 0 0 3px rgba(15,143,145,.09);
transform: none;
}
/* Login */
.login-page {
justify-content: flex-start;
padding: 0 22px 32px;
background: linear-gradient(180deg, var(--navy) 0 280px, var(--canvas) 280px 100%);
}
.login-logo { margin: 0 -22px; padding: 54px 24px 46px; text-align: left; }
.login-logo .logo-icon {
width: 184px; height: 68px; margin: 0 0 14px;
border-radius: 0; box-shadow: none; animation: none;
border: 0; background: transparent;
justify-content: flex-start;
}
.login-logo .logo-icon img { width: 176px !important; height: 66px !important; object-fit: contain; }
.login-logo h1 { display: none; }
.login-logo p { margin-top: 6px; color: rgba(255,255,255,.7); }
.login-card {
margin-top: -20px;
padding: 24px 20px 20px;
border-radius: 8px;
box-shadow: 0 12px 28px rgba(18,48,74,.14);
}
.login-title { font-size: 20px; color: var(--ink); }
.login-subtitle { margin-bottom: 22px; color: var(--muted); }
.form-label { color: #415461; font-weight: 650; }
.switch-link { color: var(--blue); font-weight: 650; }
.login-assurance {
display: flex; justify-content: center; gap: 16px;
margin-top: 18px; color: #7a8992; font-size: 11px;
}
.login-assurance span::before { content: '✓'; margin-right: 4px; color: var(--cyan); font-weight: 800; }
/* Home header and banner */
#dashboardPage { padding: 0 0 78px; background: var(--canvas); }
.home-topbar {
display: flex; align-items: center; justify-content: space-between;
min-height: 68px; padding: 12px 16px;
background: var(--navy); color: #fff;
}
.home-brand { display: flex; align-items: center; gap: 10px; }
.home-brand img { width: 118px; height: 44px; padding: 0; object-fit: contain; background: transparent; border-radius: 0; }
.home-brand > div { display: none; }
.home-brand-name { font-size: 13px; font-weight: 700; }
.home-brand-desc { margin-top: 2px; color: rgba(255,255,255,.62); font-size: 10px; }
.home-notice {
position: relative; width: 38px; height: 38px; border: 1px solid rgba(255,255,255,.18);
border-radius: 7px; background: rgba(255,255,255,.08); color: #fff; cursor: pointer;
display: flex; align-items: center; justify-content: center;
}
.home-notice::after { content: ''; position: absolute; right: 7px; top: 7px; width: 6px; height: 6px; border-radius: 50%; background: var(--orange); border: 2px solid var(--navy); }
.hd-banner-wrap { margin: 0; padding: 12px 12px 0; background: var(--navy); }
.hd-banner { min-width: 100%; height: 186px; border-radius: 8px; padding: 21px 18px; }
.hd-banner-1 { background: linear-gradient(120deg,#176b87,#0f8f91); box-shadow: none; }
.hd-banner-2 { background: linear-gradient(120deg,#a84360,#d85b6a); box-shadow: none; }
.hd-banner::after { background: rgba(255,255,255,.08); }
.hd-banner-pill { background: rgba(255,255,255,.14); border: 1px solid rgba(255,255,255,.18); }
.hd-banner-title { font-size: 25px; letter-spacing: 0; }
.hd-banner-sub { max-width: 250px; color: rgba(255,255,255,.8); }
.hd-banner-cta { color: var(--navy); border-radius: 6px; box-shadow: none; }
.hd-banner-cta svg path { stroke: var(--navy); }
.hd-banner-dots { bottom: 12px; }
.hd-banner-dots .dot { background: rgba(255,255,255,.35); }
.hd-banner-dots .dot.active { background: #fff; }
.hd-body { padding: 12px; }
.hd-feature {
margin-bottom: 12px; padding: 16px;
border-radius: 8px; background: var(--orange); box-shadow: none;
}
.hd-feature::after { background: rgba(255,255,255,.1); }
.hd-feature-arrow { border-radius: 7px; background: rgba(18,48,74,.16); }
.hd-services-card, .hd-price-section, .hd-ship-section, .hd-faq-section {
border: 1px solid var(--line); border-radius: 8px; box-shadow: 0 2px 8px rgba(18,48,74,.05);
}
.hd-services-card { padding: 16px 14px; }
.hd-section-title, .hd-process-title, .hd-ship-title, .hd-faq-title { color: var(--ink); font-size: 15px; }
.hd-section-title::before, .hd-process-title::before, .hd-ship-title::before, .hd-faq-title::before { background: var(--cyan); }
.hd-service {
min-height: 86px; padding: 12px 5px 10px;
border: 1px solid #e0e8eb; border-radius: 7px; background: #f8fbfb;
}
.hd-service:hover { transform: none; border-color: #9ecfd0; box-shadow: none; }
.hd-service::before { display: none; }
.hd-service-icon { width: 40px; height: 40px; border-radius: 7px; background: var(--mint); }
.hd-service-icon svg path, .hd-service-icon svg circle, .hd-service-icon svg rect { stroke: var(--cyan); }
.hd-service-label { color: #324955; }
.hd-process-list { gap: 8px; }
.hd-step-item { padding: 13px 12px; border-radius: 8px; border-color: var(--line); box-shadow: none; }
.hd-step-item:hover { transform: none; box-shadow: none; }
.hd-step-num { width: 28px; height: 28px; border-radius: 6px; background: var(--navy); box-shadow: none; }
.hd-step-icon { border-radius: 7px; background: var(--mint); }
.hd-step-icon svg * { stroke: var(--cyan); }
.hd-step-name { color: var(--ink); font-size: 14px; }
.hd-price-section { background: #fff; }
.hd-price-header { background: #e9f4f4; border-bottom: 1px solid #cfe3e2; }
.hd-price-header .hd-price-title { color: var(--navy); }
.hd-price-sub { color: var(--cyan); }
.hd-price-row { grid-template-columns: 72px 1fr 64px 66px; border-radius: 7px; box-shadow: none; border: 1px solid #e4eaed; }
.hd-pr-type { color: var(--navy); }
.hd-pr-price { color: var(--orange); }
.hd-pr-time { color: var(--cyan); background: var(--mint); border-radius: 5px; }
.hd-price-hint { color: var(--muted); }
.hd-consult-bar { border-radius: 8px; border-color: #cfe3e2; background: #f4fbfa; margin-bottom: 16px; box-shadow: none; }
.hd-consult-avatar { border-radius: 7px; background: var(--mint); }
.hd-consult-btn, .hd-ship-cta { background: var(--cyan); border-radius: 7px; box-shadow: none; }
.hd-ship-item { border-radius: 7px; background: #fff5f7; border-color: #efcbd2; padding: 12px 8px 10px; }
.hd-ship-item:hover { transform: none; box-shadow: none; }
.hd-ship-icon { width: 42px; height: 42px; font-size: 27px; }
.hd-ship-label { color: #a84360; background: none; -webkit-text-fill-color: currentColor; }
.hd-faq-item { border-radius: 0 7px 7px 0; }
.hd-faq-item:hover { background: #f4fbfa; border-left-color: var(--cyan); }
.hd-faq-item::before { background: var(--orange); color: #fff; box-shadow: none; }
.hd-faq-q { color: var(--ink); }
/* Main tabs and pages */
.page { padding: 0 12px 84px; animation: none; }
.order-header {
margin: 0 -12px 14px; padding: 18px 16px 16px;
background: var(--navy); min-height: 66px;
}
.order-title { font-size: 20px; letter-spacing: 0; }
.form-section, .price-section { padding: 16px; margin-bottom: 10px; }
.section-title { color: var(--ink); font-size: 15px; border-bottom-color: #e7edef; }
.radio-group, .check-group { gap: 8px; }
.radio-item, .check-item {
min-height: 43px; padding: 11px 8px;
border: 1px solid #ccd9df; border-radius: 7px; background: #fff;
}
.radio-item.active, .check-item.active, .approval-tab.active {
color: #fff; background: var(--cyan); border-color: var(--cyan); box-shadow: none;
}
.goods-item input { min-height: 42px; border: 1px solid #ccd9df; border-radius: 6px; font-size: 13px; }
.add-goods { border-color: #95caca; border-radius: 7px; color: var(--cyan); }
.price-options { gap: 7px; }
.price-option { border: 1px solid #dbe4e8; border-radius: 7px; }
.price-option.active { border-color: var(--cyan); background: #f0faf8; }
.price-option::before { background: var(--cyan); }
.price-option-price, .selected-value, .order-list-value, .order-amount { color: var(--cyan); }
.price-tag.recommend { background: var(--orange); }
.submit-btn { min-height: 50px; margin-bottom: 12px; }
.stat-grid { gap: 8px; }
.stat-card { background: #fff; border-radius: 8px; }
.stat-value { color: var(--navy); background: none; -webkit-text-fill-color: currentColor; }
.approval-tabs, .order-tabs { background: #edf2f4; border-radius: 7px; }
.approval-tab, .order-tab { border-radius: 6px; }
.order-tab.active { color: var(--cyan); }
.approval-item, .settlement-item, .order-item { border-radius: 8px; padding: 15px; }
.approval-status, .settlement-status, .order-status { border-radius: 5px; }
.btn-approve { background: var(--cyan); border-radius: 7px; }
.btn-reject { border: 1px solid #efc5c5 !important; border-radius: 7px; }
.detail-header { margin: 0 -12px 14px; padding: 13px 12px; background: var(--navy); }
.detail-back { color: #fff; }
.detail-title { color: #fff; }
.profile-header { margin: 0 -12px 12px; padding: 30px 20px 22px; border: 0; border-radius: 0 0 8px 8px; background: var(--navy); }
.profile-avatar { width: 66px; height: 66px; border-radius: 8px; background: var(--cyan); box-shadow: none; }
.profile-name { color: #fff; }
.profile-company { color: rgba(255,255,255,.66); }
.menu-list { border-radius: 8px; }
.menu-item { padding: 14px 16px; }
.menu-item .icon { border-radius: 7px; background: var(--mint); }
.menu-item .icon svg * { stroke: var(--cyan); }
.logout-btn { background: #fff; color: var(--danger-new); border: 1px solid #efc8c8; border-radius: 7px; box-shadow: none; }
/* Bottom navigation */
.tab-bar {
background: rgba(255,255,255,.97);
backdrop-filter: blur(14px);
border-top: 1px solid #dce5e9;
padding: 5px 6px max(6px,env(safe-area-inset-bottom));
box-shadow: 0 -3px 12px rgba(18,48,74,.06);
}
.tab-item { border-radius: 7px; padding: 6px 3px 4px; }
.tab-item .icon-wrap { width: 36px; height: 31px; border-radius: 6px; }
.tab-item.active .icon-wrap { background: var(--mint); transform: none; box-shadow: none; }
.tab-item.active .icon-wrap svg * { stroke: var(--cyan) !important; }
.tab-item.active .label { color: var(--cyan); }
.tab-item.active::after { background: var(--cyan); height: 2px; }
.toast { top: 18px; max-width: calc(100% - 32px); border-radius: 7px; background: var(--navy); }
/* Standalone service pages */
.tab-content { min-height: 100vh; padding: 0 12px 28px; background: var(--canvas); }
.tab-content > .order-header { margin: 0 -12px 14px; }
.tab-content .stat-card { min-width: 0; }
.service-header, .sub-page-header { background: var(--navy) !important; }
.flow-step .step-num { background: var(--cyan); box-shadow: none; }
.flow-step:not(:last-child)::after { background: var(--cyan); }
/* Motion and premium spacing */
@keyframes smoothPageIn {
from { opacity: 0; transform: translateY(8px); }
to { opacity: 1; transform: translateY(0); }
}
@keyframes softReveal {
from { opacity: 0; transform: translateY(12px); }
to { opacity: 1; transform: translateY(0); }
}
.page.active, .tab-content[style*="display: block"] {
animation: smoothPageIn .34s cubic-bezier(.22,1,.36,1) both;
}
.glass-card, .hd-feature, .hd-service, .hd-step-item, .hd-price-row,
.hd-consult-bar, .hd-ship-item, .radio-item, .check-item, .price-option,
.menu-item, .tab-item, .btn-primary, .submit-btn, .btn-settle {
transition: transform .22s cubic-bezier(.22,1,.36,1),
box-shadow .22s ease, border-color .22s ease,
background-color .22s ease, color .22s ease;
}
.hd-feature:active, .hd-service:active, .hd-step-item:active,
.hd-price-row:active, .hd-ship-item:active, .menu-item:active,
.radio-item:active, .check-item:active, .price-option:active {
transform: scale(.985);
}
.btn-primary:active, .submit-btn:active, .btn-settle:active,
.hd-consult-btn:active, .hd-ship-cta:active { transform: scale(.975); }
.app { box-shadow: 0 0 44px rgba(18,48,74,.10); }
.login-page { background: linear-gradient(180deg,#102c45 0 300px,var(--canvas) 300px 100%); }
.login-logo { padding-top: 62px; padding-bottom: 54px; }
.login-logo p { font-size: 13px; letter-spacing: .6px; }
.login-card {
margin-top: -28px; padding: 27px 22px 22px; border-radius: 11px;
border-color: rgba(255,255,255,.9);
box-shadow: 0 18px 46px rgba(18,48,74,.16);
animation: softReveal .52s cubic-bezier(.22,1,.36,1) both;
}
.login-title { font-size: 22px; letter-spacing: -.3px; }
.login-subtitle { margin-top: 5px; margin-bottom: 25px; }
.login-card .btn-primary { min-height: 50px; font-size: 16px; }
.home-topbar {
min-height: 76px; padding: 14px 16px;
background: linear-gradient(110deg,#102c45 0%,#153b56 100%);
border-bottom: 1px solid rgba(255,255,255,.08);
}
.home-notice { width: 40px; height: 40px; border-radius: 9px; }
.hd-banner-wrap { padding: 13px 12px 18px; }
.hd-banner {
height: 202px; padding: 24px 19px; border-radius: 11px;
box-shadow: 0 12px 30px rgba(7,40,54,.18);
}
.hd-banner-title { margin-top: 11px; font-size: 27px; letter-spacing: -.5px; }
.hd-banner-sub { margin-top: 8px; line-height: 1.65; }
.hd-banner-cta { margin-top: 13px; min-height: 37px; padding: 8px 15px; border-radius: 7px; }
.hd-banner-track { scroll-snap-type: x mandatory; scroll-behavior: smooth; }
.hd-banner { scroll-snap-align: center; }
.hd-banner-dots { bottom: 27px; }
.hd-body { padding: 14px 12px 22px; }
.hd-feature {
min-height: 78px; padding: 18px; margin-bottom: 14px; border-radius: 10px;
box-shadow: 0 8px 20px rgba(216,91,106,.18);
}
.hd-feature-title { font-size: 18px; }
.hd-feature-desc { margin-top: 5px; }
.hd-services-card, .hd-price-section, .hd-ship-section, .hd-faq-section,
.hd-consult-bar { border-radius: 10px; }
.hd-services-card { padding: 18px 15px; margin-bottom: 18px; }
.hd-section-title, .hd-process-title, .hd-ship-title, .hd-faq-title {
font-size: 16px; letter-spacing: -.15px;
}
.hd-service-grid { gap: 10px; }
.hd-service { min-height: 94px; padding: 15px 5px 12px; border-radius: 9px; }
.hd-service-icon { width: 43px; height: 43px; margin-bottom: 9px; border-radius: 9px; }
.hd-process-list { gap: 9px; margin-bottom: 19px; }
.hd-step-item { min-height: 72px; padding: 14px; border-radius: 10px; }
.hd-step-num { width: 30px; height: 30px; }
.hd-step-icon { width: 38px; height: 38px; }
.hd-step-desc { margin-top: 4px; }
.hd-price-section { margin-bottom: 14px; }
.hd-price-header { padding: 18px 16px 16px; }
.hd-price-table-wrap { padding: 0 13px 15px; }
.hd-price-row { min-height: 65px; padding: 13px 12px; border-radius: 9px; }
.hd-consult-bar { min-height: 70px; padding: 14px; }
.hd-consult-btn { min-height: 37px; padding: 8px 15px; }
.hd-ship-section, .hd-faq-section { padding: 20px 15px 18px; }
.hd-ship-grid { gap: 9px; }
.hd-ship-item { min-height: 92px; border-radius: 9px; }
.page { padding-left: 13px; padding-right: 13px; }
.order-header {
margin-left: -13px; margin-right: -13px;
min-height: 72px; padding: 21px 17px 17px;
background: linear-gradient(110deg,#102c45,#153b56);
}
.order-title { font-size: 21px; }
.form-section, .price-section { padding: 18px; margin-bottom: 12px; border-radius: 10px; }
.section-title { margin-bottom: 18px; font-size: 16px; }
.form-group { margin-bottom: 19px; }
.input-field { border-radius: 8px; }
.radio-item, .check-item { min-height: 45px; border-radius: 8px; }
.stat-card, .approval-item, .settlement-item, .order-item,
.menu-list { border-radius: 10px; }
.approval-item, .settlement-item { margin-bottom: 12px; }
.approval-tabs, .order-tabs { padding: 4px; border-radius: 9px; }
.approval-tab, .order-tab { min-height: 42px; display:flex; align-items:center; justify-content:center; }
.profile-header { padding-top: 34px; padding-bottom: 26px; border-radius: 0 0 12px 12px; }
.profile-avatar { width: 70px; height: 70px; border-radius: 12px; }
.menu-item { min-height: 63px; }
.tab-bar { padding-top: 7px; }
.tab-item { min-height: 54px; }
.tab-item.active .icon-wrap { transform: translateY(-2px); }
.tab-item.active::after { width: 20px; }
@media (hover:hover) {
.glass-card:hover { transform: translateY(-2px); box-shadow: 0 8px 22px rgba(18,48,74,.09); }
.hd-service:hover, .hd-step-item:hover, .hd-price-row:hover, .hd-ship-item:hover {
transform: translateY(-2px); box-shadow: 0 8px 18px rgba(18,48,74,.08);
}
}
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after { animation-duration: .01ms !important; animation-iteration-count: 1 !important; transition-duration: .01ms !important; scroll-behavior: auto !important; }
}
@media (max-width: 360px) {
.login-page { padding-left: 16px; padding-right: 16px; }
.login-logo { margin-left: -16px; margin-right: -16px; }
.hd-price-row { grid-template-columns: 67px 1fr 59px 62px; gap: 4px; }
.hd-pr-goods, .hd-pr-scene { font-size: 10px; }
.hd-pr-price { font-size: 13px; }
.hd-pr-time { font-size: 10px; padding: 3px 5px; }
.radio-item { font-size: 13px; }
}
</style>
</head>
<body>
@@ -1720,9 +2099,9 @@
<div class="login-page" id="loginPage">
<div class="login-logo">
<div class="logo-icon">
<img src="logo.png" alt="虫虫出海" style="width:48px;height:48px;object-fit:contain;"/>
<img src="baiyue-logo.png" alt="柏悦物流" style="width:176px;height:66px;object-fit:contain;"/>
</div>
<h1>虫虫出海</h1>
<h1>柏悦物流</h1>
<p>跨境物流 · 智慧服务</p>
</div>
<div class="glass-card login-card" id="loginCard">
@@ -1738,10 +2117,11 @@
</div>
<button class="btn-primary" style="width:100%;" onclick="handleLogin()">登录</button>
<div class="switch-link" onclick="showRegister()">没有账号?立即注册</div>
<div class="login-assurance"><span>数据加密</span><span>全链路可追踪</span></div>
</div>
<div class="glass-card login-card" id="registerCard" style="display:none;">
<div class="login-title">创建账号</div>
<div class="login-subtitle">注册以使用虫虫出海服务</div>
<div class="login-subtitle">注册以使用柏悦物流服务</div>
<div class="form-group">
<label class="form-label">手机号</label>
<input type="tel" class="input-field" placeholder="请输入手机号">
@@ -1763,6 +2143,15 @@
<div id="mainApp" style="display:none;">
<!-- DASHBOARD PAGE -->
<div class="page active" id="dashboardPage">
<div class="home-topbar">
<div class="home-brand">
<img src="baiyue-logo.png" alt="柏悦物流">
<div><div class="home-brand-name">跨境物流服务平台</div><div class="home-brand-desc">一站式海外仓配</div></div>
</div>
<button class="home-notice" type="button" aria-label="消息通知" onclick="showToast('暂无新消息')">
<svg width="19" height="19" viewBox="0 0 24 24" fill="none"><path d="M18 8a6 6 0 00-12 0c0 7-3 7-3 9h18c0-2-3-2-3-9M10 21h4" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>
</button>
</div>
<!-- BANNER carousel -->
<div class="hd-banner-wrap">
<div class="hd-banner-track" id="hdBannerTrack">
@@ -4050,8 +4439,8 @@
datasets: [{
label: '订单数',
data: [12, 19, 15, 22, 18, 25, 20],
borderColor: '#667eea',
backgroundColor: 'rgba(102,126,234,0.1)',
borderColor: '#0f8f91',
backgroundColor: 'rgba(15,143,145,0.10)',
fill: true,
tension: 0.4
}]
@@ -4077,7 +4466,7 @@
labels: ['美线普货专线', '美线敏感货专线', '美线快线', '美线FBA直送'],
datasets: [{
data: [45, 25, 20, 10],
backgroundColor: ['#667eea', '#764ba2', '#f093fb', '#22c55e'],
backgroundColor: ['#0f8f91', '#176b87', '#d85b6a', '#55b88d'],
borderWidth: 0
}]
},
File diff suppressed because one or more lines are too long