docs: initialize documentation repository
|
After Width: | Height: | Size: 881 KiB |
|
After Width: | Height: | Size: 549 KiB |
|
After Width: | Height: | Size: 835 KiB |
|
After Width: | Height: | Size: 1.3 MiB |
|
After Width: | Height: | Size: 492 KiB |
|
After Width: | Height: | Size: 26 KiB |
@@ -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>
|
||||
|
After Width: | Height: | Size: 764 KiB |
@@ -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>
|
||||
|
After Width: | Height: | Size: 764 KiB |
@@ -0,0 +1,210 @@
|
||||
<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>
|
||||
<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"/>
|
||||
</marker>
|
||||
</defs>
|
||||
|
||||
<line x1="340" y1="12" x2="340" y2="1160" stroke="#5F5E5A" stroke-width="1" stroke-dasharray="4 4" opacity="0.5"/>
|
||||
|
||||
<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>
|
||||
</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"/>
|
||||
</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>
|
||||
|
||||
<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>
|
||||
|
||||
<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>
|
||||
|
||||
<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>
|
||||
|
||||
<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>
|
||||
|
||||
<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>
|
||||
|
||||
<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"/>
|
||||
</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>
|
||||
<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>
|
||||
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 26 KiB |
@@ -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>
|
||||
@@ -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>
|
||||
@@ -0,0 +1,880 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>虫虫出海 CHONGCHONG GLOBAL | 工作台</title>
|
||||
<meta name="description" content="虫虫出海工作台 - 海外采购、美国本土卡车、美本土散板一键下单。">
|
||||
<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&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'],
|
||||
},
|
||||
boxShadow: {
|
||||
'card': '0 10px 40px rgba(10, 22, 40, 0.08)',
|
||||
'card-hover': '0 20px 60px rgba(10, 22, 40, 0.15)',
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
* { scroll-behavior: smooth; }
|
||||
body { font-family: 'Inter', 'Noto Sans SC', system-ui, sans-serif; overflow-x: hidden; }
|
||||
|
||||
.btn-primary {
|
||||
background: linear-gradient(135deg, #1565C0 0%, #0D47A1 100%);
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
.btn-primary:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 10px 30px rgba(21, 101, 192, 0.35);
|
||||
}
|
||||
.btn-accent {
|
||||
background: linear-gradient(135deg, #4CAF50 0%, #2E7D32 100%);
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
.btn-accent:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 10px 30px rgba(76, 175, 80, 0.35);
|
||||
}
|
||||
|
||||
/* 语言切换器 */
|
||||
.lang-switcher {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background: rgba(255, 255, 255, 0.15);
|
||||
border-radius: 9999px;
|
||||
padding: 3px;
|
||||
backdrop-filter: blur(10px);
|
||||
border: 1px solid rgba(255, 255, 255, 0.2);
|
||||
}
|
||||
.lang-switcher button {
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
padding: 4px 9px;
|
||||
border-radius: 9999px;
|
||||
color: rgba(255, 255, 255, 0.9);
|
||||
transition: all 0.25s ease;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.lang-switcher button:hover { color: #fff; }
|
||||
.lang-switcher button.active { background: #fff; color: #0D47A1; }
|
||||
|
||||
/* ===== 下单工作台 Dashboard ===== */
|
||||
.dash-view { animation: fadeIn 0.4s ease; }
|
||||
.dash-card {
|
||||
background: #fff;
|
||||
border: 1px solid #eef2f7;
|
||||
border-radius: 1.25rem;
|
||||
box-shadow: 0 10px 40px rgba(10, 22, 40, 0.06);
|
||||
transition: all 0.35s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
cursor: pointer;
|
||||
}
|
||||
.dash-card:hover {
|
||||
transform: translateY(-8px);
|
||||
box-shadow: 0 24px 60px rgba(10, 22, 40, 0.14);
|
||||
border-color: rgba(21, 101, 192, 0.35);
|
||||
}
|
||||
.dash-form-input {
|
||||
width: 100%;
|
||||
padding: 0.75rem 1rem;
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 0.75rem;
|
||||
outline: none;
|
||||
font-size: 0.95rem;
|
||||
color: #1f2937;
|
||||
background: #fff;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
.dash-form-input:focus {
|
||||
border-color: #1565C0;
|
||||
box-shadow: 0 0 0 3px rgba(21, 101, 192, 0.12);
|
||||
}
|
||||
.dash-form-input::placeholder { color: #9ca3af; }
|
||||
.dash-label {
|
||||
display: block;
|
||||
font-size: 0.875rem;
|
||||
font-weight: 600;
|
||||
color: #374151;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
.dash-label .req { color: #ef4444; margin-left: 2px; }
|
||||
.seg-input { position: absolute; opacity: 0; width: 0; height: 0; }
|
||||
.seg-pill {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 6px;
|
||||
padding: 0.65rem 1.1rem;
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 0.75rem;
|
||||
cursor: pointer;
|
||||
font-size: 0.9rem;
|
||||
color: #475569;
|
||||
background: #fff;
|
||||
transition: all 0.2s ease;
|
||||
user-select: none;
|
||||
}
|
||||
.seg-pill:hover { border-color: #cbd5e1; }
|
||||
.seg-input:checked + .seg-pill {
|
||||
border-color: #1565C0;
|
||||
background: #EAF2FD;
|
||||
color: #0D47A1;
|
||||
font-weight: 600;
|
||||
box-shadow: 0 0 0 1px #1565C0 inset;
|
||||
}
|
||||
.dash-topbar {
|
||||
background: rgba(255, 255, 255, 0.92);
|
||||
backdrop-filter: blur(12px);
|
||||
border-bottom: 1px solid #eef2f7;
|
||||
}
|
||||
.dash-sidebar {
|
||||
width: 250px;
|
||||
flex-shrink: 0;
|
||||
background: linear-gradient(180deg, #0B1F3A 0%, #0C2A52 100%);
|
||||
color: #fff;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
height: 100vh;
|
||||
padding: 1.25rem 0.875rem;
|
||||
}
|
||||
.dash-sidebar-brand {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.6rem;
|
||||
padding: 0.4rem 0.55rem 1.1rem;
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.08);
|
||||
margin-bottom: 0.6rem;
|
||||
}
|
||||
.dash-sidebar-brand .brand-name { font-weight: 700; font-size: 1rem; line-height: 1.15; }
|
||||
.dash-sidebar-brand .brand-sub { font-size: 0.62rem; letter-spacing: 0.12em; color: rgba(255, 255, 255, 0.45); }
|
||||
.dash-nav { flex: 1; display: flex; flex-direction: column; gap: 0.25rem; overflow-y: auto; }
|
||||
.dash-nav-group {
|
||||
font-size: 0.68rem; text-transform: uppercase; letter-spacing: 0.1em;
|
||||
color: rgba(255, 255, 255, 0.4); padding: 0.85rem 0.75rem 0.35rem;
|
||||
}
|
||||
.dash-nav-link {
|
||||
display: flex; align-items: center; gap: 0.75rem;
|
||||
padding: 0.72rem 0.85rem; border-radius: 0.75rem;
|
||||
color: rgba(255, 255, 255, 0.72); font-size: 0.92rem; font-weight: 500;
|
||||
cursor: pointer; transition: all 0.2s ease; white-space: nowrap;
|
||||
}
|
||||
.dash-nav-link i { width: 1.2rem; text-align: center; font-size: 0.95rem; }
|
||||
.dash-nav-link:hover { background: rgba(255, 255, 255, 0.07); color: #fff; }
|
||||
.dash-nav-link.active {
|
||||
background: linear-gradient(90deg, #1565C0, #1E88E5); color: #fff;
|
||||
box-shadow: 0 6px 18px rgba(21, 101, 192, 0.4);
|
||||
}
|
||||
.dash-sidebar-bottom {
|
||||
border-top: 1px solid rgba(255, 255, 255, 0.08); padding-top: 0.9rem;
|
||||
display: flex; flex-direction: column; gap: 0.7rem; align-items: stretch;
|
||||
}
|
||||
.dash-sidebar-bottom #langSwitcherDash { align-self: center; }
|
||||
.dash-logout-btn {
|
||||
display: flex; align-items: center; justify-content: center; gap: 0.5rem;
|
||||
padding: 0.6rem; border-radius: 0.7rem; font-size: 0.88rem; font-weight: 600;
|
||||
background: rgba(239, 68, 68, 0.12); color: #fca5a5; cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
.dash-logout-btn:hover { background: rgba(239, 68, 68, 0.22); color: #fff; }
|
||||
.dash-main { flex: 1; min-width: 0; display: flex; flex-direction: column; }
|
||||
.dash-menu-btn {
|
||||
display: none; width: 2.25rem; height: 2.25rem; border-radius: 0.6rem;
|
||||
align-items: center; justify-content: center; color: #374151;
|
||||
background: #f1f5f9; cursor: pointer;
|
||||
}
|
||||
.dash-overlay { display: none; position: fixed; inset: 0; background: rgba(0, 0, 0, 0.45); z-index: 45; }
|
||||
.dash-overlay.show { display: block; }
|
||||
.dash-right {
|
||||
width: 320px; flex-shrink: 0;
|
||||
background: #fff; border-left: 1px solid #eef2f7;
|
||||
padding: 1.5rem 1.25rem;
|
||||
position: sticky; top: 4rem; align-self: flex-start;
|
||||
max-height: calc(100vh - 4rem); overflow-y: auto;
|
||||
}
|
||||
.dash-right-card {
|
||||
background: #f8fafc; border: 1px solid #eef2f7;
|
||||
border-radius: 1rem; padding: 1.25rem; margin-bottom: 1rem;
|
||||
}
|
||||
.dash-right-card h4 {
|
||||
font-size: 0.72rem; font-weight: 700; letter-spacing: 0.06em;
|
||||
text-transform: uppercase; color: #94a3b8; margin-bottom: 0.9rem;
|
||||
}
|
||||
.dash-account { display: flex; align-items: center; gap: 0.75rem; }
|
||||
.dash-account-avatar {
|
||||
width: 2.75rem; height: 2.75rem; border-radius: 0.8rem;
|
||||
background: linear-gradient(135deg, #1565C0, #00BFA5); color: #fff;
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
font-weight: 700; font-size: 1.1rem; flex-shrink: 0;
|
||||
}
|
||||
.dash-account-name { font-weight: 700; color: #0f172a; font-size: 0.95rem; line-height: 1.2; }
|
||||
.dash-account-type { font-size: 0.75rem; color: #64748b; margin-top: 0.15rem; }
|
||||
.dash-stat-row { display: flex; justify-content: space-between; align-items: center; padding: 0.6rem 0; border-bottom: 1px dashed #e2e8f0; }
|
||||
.dash-stat-row:last-child { border-bottom: none; }
|
||||
.dash-stat-label { font-size: 0.85rem; color: #475569; }
|
||||
.dash-stat-value { font-weight: 700; color: #0f172a; font-size: 0.95rem; }
|
||||
.dash-help-item {
|
||||
display: flex; align-items: center; gap: 0.6rem;
|
||||
padding: 0.6rem 0.55rem; border-radius: 0.6rem; cursor: pointer;
|
||||
color: #334155; font-size: 0.9rem; transition: background 0.2s, color 0.2s;
|
||||
}
|
||||
.dash-help-item:hover { background: #eef2f7; color: #1565C0; }
|
||||
.dash-help-item i { color: #00BFA5; width: 1.15rem; text-align: center; }
|
||||
.dash-tip {
|
||||
background: linear-gradient(135deg, rgba(0,191,165,0.08), rgba(21,101,192,0.08));
|
||||
border: 1px solid rgba(0,191,165,0.22); border-radius: 1rem;
|
||||
padding: 1.1rem; font-size: 0.82rem; color: #475569; line-height: 1.65;
|
||||
}
|
||||
.dash-tip i { color: #00BFA5; margin-right: 0.4rem; }
|
||||
.dash-empty { padding: 1rem; color: #94a3b8; }
|
||||
.dash-empty i { font-size: 3rem; color: #cbd5e1; margin-bottom: 1rem; display: block; }
|
||||
@keyframes fadeIn {
|
||||
from { opacity: 0; transform: translateY(10px); }
|
||||
to { opacity: 1; transform: translateY(0); }
|
||||
}
|
||||
@media (max-width: 768px) {
|
||||
.dash-sidebar {
|
||||
position: fixed; left: 0; top: 0; z-index: 50;
|
||||
transform: translateX(-100%); transition: transform 0.3s ease;
|
||||
}
|
||||
.dash-sidebar.open { transform: translateX(0); }
|
||||
.dash-menu-btn { display: inline-flex; }
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="text-gray-800 antialiased bg-gray-50">
|
||||
<!-- 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>
|
||||
|
||||
<!-- 工作台 -->
|
||||
<section id="workbench" class="min-h-screen flex">
|
||||
<aside id="dashSidebar" class="dash-sidebar">
|
||||
<div class="dash-sidebar-brand">
|
||||
<img src="assets/logo.png" alt="虫虫出海" style="width:161px;height:60px;object-fit:contain;">
|
||||
</div>
|
||||
<nav class="dash-nav">
|
||||
<div class="dash-nav-group" data-i18n="dash_menu_main">主导航</div>
|
||||
<a class="dash-nav-link active" data-view="Home" onclick="goDash('Home')"><i class="fas fa-th-large"></i><span data-i18n="dash_menu_overview">业务总览</span></a>
|
||||
<a class="dash-nav-link" data-view="Procurement" onclick="goDash('Procurement')"><i class="fas fa-shopping-cart"></i><span data-i18n="dash_menu_proc">海外采购</span></a>
|
||||
<a class="dash-nav-link" data-view="Truck" onclick="goDash('Truck')"><i class="fas fa-truck-moving"></i><span data-i18n="dash_menu_truck">美国本土卡</span></a>
|
||||
<a class="dash-nav-link" data-view="Pallet" onclick="goDash('Pallet')"><i class="fas fa-pallet"></i><span data-i18n="dash_menu_pallet">美本土散板</span></a>
|
||||
<a class="dash-nav-link" data-view="Orders" onclick="goDash('Orders')"><i class="fas fa-clipboard-list"></i><span data-i18n="dash_menu_orders">我的订单</span></a>
|
||||
</nav>
|
||||
<div class="dash-sidebar-bottom">
|
||||
<div id="langSwitcherDash" class="lang-switcher flex">
|
||||
<button data-lang="zh">中</button>
|
||||
<button data-lang="en">EN</button>
|
||||
<button data-lang="es">🇲🇽</button>
|
||||
</div>
|
||||
<button class="dash-logout-btn" onclick="doLogout()"><i class="fas fa-sign-out-alt"></i><span data-i18n="dash_logout">退出登录</span></button>
|
||||
</div>
|
||||
</aside>
|
||||
<!-- 移动端遮罩 -->
|
||||
<div id="dashOverlay" class="dash-overlay" onclick="toggleDashSidebar()"></div>
|
||||
|
||||
<!-- 主内容区 -->
|
||||
<div class="dash-main">
|
||||
<header class="dash-topbar sticky top-0 z-30">
|
||||
<div class="px-4 sm:px-6 lg:px-10 h-16 flex items-center justify-between">
|
||||
<div class="flex items-center space-x-3">
|
||||
<button class="dash-menu-btn" onclick="toggleDashSidebar()"><i class="fas fa-bars"></i></button>
|
||||
<span class="text-sm text-gray-500" id="dashUserName">Hi, 客户</span>
|
||||
</div>
|
||||
<a href="index.html" class="text-sm text-gray-600 hover:text-brand-blue font-medium px-3 py-2 transition-colors" data-i18n="dash_home_link">返回官网</a>
|
||||
</div>
|
||||
</header>
|
||||
<div class="flex flex-1 min-h-0">
|
||||
<main class="flex-1 px-4 sm:px-6 lg:px-10 py-8 min-w-0">
|
||||
<!-- 视图1:选择业务 -->
|
||||
<div id="dashViewHome" class="dash-view">
|
||||
<div class="mb-10">
|
||||
<h1 class="text-3xl lg:text-4xl font-bold text-gray-900 mb-3" data-i18n="dash_welcome_title">选择业务,快速下单</h1>
|
||||
<p class="text-gray-500" data-i18n="dash_welcome_sub">请选择您需要的业务类型,填写信息后提交订单,我们将尽快为您安排。</p>
|
||||
</div>
|
||||
<div class="grid md:grid-cols-3 gap-6">
|
||||
<div class="dash-card p-8" onclick="openOrder('Procurement')">
|
||||
<div class="w-14 h-14 rounded-2xl bg-gradient-to-br from-brand-blue to-brand-blueDark flex items-center justify-center text-white text-2xl mb-6">
|
||||
<i class="fas fa-shopping-cart"></i>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-2" data-i18n="dash_biz1_title">海外采购</h3>
|
||||
<p class="text-sm text-gray-500 mb-6" data-i18n="dash_biz1_desc">采购代购 · 验货质检 · 集中发货</p>
|
||||
<span class="inline-flex items-center text-brand-blue font-semibold text-sm">
|
||||
<span data-i18n="dash_start">开始下单</span><i class="fas fa-arrow-right ml-2"></i>
|
||||
</span>
|
||||
</div>
|
||||
<div class="dash-card p-8" onclick="openOrder('Truck')">
|
||||
<div class="w-14 h-14 rounded-2xl bg-gradient-to-br from-brand-green to-brand-greenDark flex items-center justify-center text-white text-2xl mb-6">
|
||||
<i class="fas fa-truck-moving"></i>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-2" data-i18n="dash_biz2_title">美国本土卡</h3>
|
||||
<p class="text-sm text-gray-500 mb-6" data-i18n="dash_biz2_desc">港口提柜 · 仓到仓 · 仓到门</p>
|
||||
<span class="inline-flex items-center text-brand-green font-semibold text-sm">
|
||||
<span data-i18n="dash_start">开始下单</span><i class="fas fa-arrow-right ml-2"></i>
|
||||
</span>
|
||||
</div>
|
||||
<div class="dash-card p-8" onclick="openOrder('Pallet')">
|
||||
<div class="w-14 h-14 rounded-2xl bg-gradient-to-br from-brand-teal to-cyan-700 flex items-center justify-center text-white text-2xl mb-6">
|
||||
<i class="fas fa-pallet"></i>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-2" data-i18n="dash_biz3_title">美本土散板</h3>
|
||||
<p class="text-sm text-gray-500 mb-6" data-i18n="dash_biz3_desc">拼车拼载 · 打盘服务 · 灵活派送</p>
|
||||
<span class="inline-flex items-center text-brand-teal font-semibold text-sm">
|
||||
<span data-i18n="dash_start">开始下单</span><i class="fas fa-arrow-right ml-2"></i>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 视图2:海外采购下单 -->
|
||||
<div id="dashViewProcurement" class="dash-view hidden">
|
||||
<button onclick="showDashView('Home')" class="inline-flex items-center text-gray-500 hover:text-brand-blue mb-6 text-sm font-medium">
|
||||
<i class="fas fa-arrow-left mr-2"></i><span data-i18n="dash_back">返回业务选择</span>
|
||||
</button>
|
||||
<div class="bg-white rounded-2xl shadow-card border border-gray-100 p-8 lg:p-10 max-w-3xl">
|
||||
<div class="flex items-center space-x-3 mb-8">
|
||||
<div class="w-11 h-11 rounded-xl bg-gradient-to-br from-brand-blue to-brand-blueDark flex items-center justify-center text-white text-lg"><i class="fas fa-shopping-cart"></i></div>
|
||||
<h2 class="text-2xl font-bold text-gray-900" data-i18n="po_title">海外采购下单</h2>
|
||||
</div>
|
||||
<form class="order-form space-y-5" data-order="海外采购 Overseas Sourcing">
|
||||
<div class="grid sm:grid-cols-2 gap-5">
|
||||
<div>
|
||||
<label class="dash-label"><span data-i18n="po_category">采购品类</span><span class="req">*</span></label>
|
||||
<input type="text" name="采购品类" required class="dash-form-input" placeholder="如:家居用品 / 3C 配件" data-i18n-ph="po_category_ph">
|
||||
</div>
|
||||
<div>
|
||||
<label class="dash-label"><span data-i18n="po_spec">商品规格</span></label>
|
||||
<input type="text" name="商品规格" class="dash-form-input" placeholder="如:尺寸 / 颜色 / 材质" data-i18n-ph="po_spec_ph">
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<label class="dash-label"><span data-i18n="po_link">商品链接</span></label>
|
||||
<input type="url" name="商品链接" class="dash-form-input" placeholder="https://" data-i18n-ph="po_link_ph">
|
||||
</div>
|
||||
<div class="grid sm:grid-cols-2 gap-5">
|
||||
<div>
|
||||
<label class="dash-label"><span data-i18n="po_qty">采购数量</span><span class="req">*</span></label>
|
||||
<input type="number" min="1" name="采购数量" required class="dash-form-input" placeholder="0" data-i18n-ph="po_qty_ph">
|
||||
</div>
|
||||
<div>
|
||||
<label class="dash-label"><span data-i18n="po_price">预算单价</span></label>
|
||||
<div class="relative">
|
||||
<span class="absolute left-4 top-1/2 -translate-y-1/2 text-gray-400 font-medium">$</span>
|
||||
<input type="number" min="0" step="0.01" name="预算单价($)" class="dash-form-input pl-8" placeholder="0.00" data-i18n-ph="po_price_ph">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<label class="dash-label"><span data-i18n="po_address">收货地址</span></label>
|
||||
<input type="text" name="收货地址" class="dash-form-input" placeholder="请输入收货地址" data-i18n-ph="po_address_ph">
|
||||
</div>
|
||||
<div class="grid sm:grid-cols-2 gap-5">
|
||||
<div>
|
||||
<label class="dash-label"><span data-i18n="po_contact">联系人</span><span class="req">*</span></label>
|
||||
<input type="text" name="联系人" required class="dash-form-input" placeholder="请输入联系人姓名" data-i18n-ph="po_contact_ph">
|
||||
</div>
|
||||
<div>
|
||||
<label class="dash-label"><span data-i18n="po_phone">联系电话</span><span class="req">*</span></label>
|
||||
<input type="tel" name="联系电话" required class="dash-form-input" placeholder="请输入联系电话" data-i18n-ph="po_phone_ph">
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<label class="dash-label"><span data-i18n="po_note">订单备注</span></label>
|
||||
<textarea name="订单备注" rows="3" class="dash-form-input" placeholder="其他需求说明(选填)" data-i18n-ph="po_note_ph"></textarea>
|
||||
</div>
|
||||
<div class="flex gap-3 pt-2">
|
||||
<button type="submit" class="btn-primary text-white font-bold px-8 py-3.5 rounded-xl" data-i18n="dash_submit">提交订单</button>
|
||||
<button type="button" onclick="showDashView('Home')" class="px-8 py-3.5 rounded-xl border border-gray-200 text-gray-600 font-medium hover:bg-gray-50" data-i18n="dash_cancel">取消</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 视图3:美国本土卡下单 -->
|
||||
<div id="dashViewTruck" class="dash-view hidden">
|
||||
<button onclick="showDashView('Home')" class="inline-flex items-center text-gray-500 hover:text-brand-blue mb-6 text-sm font-medium">
|
||||
<i class="fas fa-arrow-left mr-2"></i><span data-i18n="dash_back">返回业务选择</span>
|
||||
</button>
|
||||
<div class="bg-white rounded-2xl shadow-card border border-gray-100 p-8 lg:p-10 max-w-3xl">
|
||||
<div class="flex items-center space-x-3 mb-8">
|
||||
<div class="w-11 h-11 rounded-xl bg-gradient-to-br from-brand-green to-brand-greenDark flex items-center justify-center text-white text-lg"><i class="fas fa-truck-moving"></i></div>
|
||||
<h2 class="text-2xl font-bold text-gray-900" data-i18n="tk_title">美国本土卡下单</h2>
|
||||
</div>
|
||||
<form class="order-form space-y-6" data-order="美国本土卡 US Trucking">
|
||||
<div>
|
||||
<label class="dash-label"><span data-i18n="ts_type">运输类型</span><span class="req">*</span></label>
|
||||
<div class="flex flex-wrap gap-3">
|
||||
<label><input type="radio" name="运输类型" value="港口提柜" class="seg-input" checked><span class="seg-pill"><i class="fas fa-anchor text-xs"></i><span data-i18n="ts_type_port">港口提柜</span></span></label>
|
||||
<label><input type="radio" name="运输类型" value="仓到仓" class="seg-input"><span class="seg-pill"><i class="fas fa-warehouse text-xs"></i><span data-i18n="ts_type_w2w">仓到仓</span></span></label>
|
||||
<label><input type="radio" name="运输类型" value="仓到门" class="seg-input"><span class="seg-pill"><i class="fas fa-door-open text-xs"></i><span data-i18n="ts_type_w2d">仓到门</span></span></label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="grid sm:grid-cols-2 gap-5">
|
||||
<div>
|
||||
<label class="dash-label"><span data-i18n="ts_origin">起运地</span><span class="req">*</span></label>
|
||||
<input type="text" name="起运地" required class="dash-form-input" placeholder="城市 / 港口 / 州" data-i18n-ph="ts_origin_ph">
|
||||
</div>
|
||||
<div>
|
||||
<label class="dash-label"><span data-i18n="ts_dest">目的地</span><span class="req">*</span></label>
|
||||
<input type="text" name="目的地" required class="dash-form-input" placeholder="城市 / 州" data-i18n-ph="ts_dest_ph">
|
||||
</div>
|
||||
<div>
|
||||
<label class="dash-label"><span data-i18n="ts_origin_addr">详细地址</span></label>
|
||||
<input type="text" name="起运详细地址" class="dash-form-input" placeholder="街道 / 门牌" data-i18n-ph="ts_origin_addr_ph">
|
||||
</div>
|
||||
<div>
|
||||
<label class="dash-label"><span data-i18n="ts_dest_addr">详细地址 / 码头 / 仓号</span></label>
|
||||
<input type="text" name="目的详细地址/码头/仓号" class="dash-form-input" placeholder="地址 / 码头 / 仓号" data-i18n-ph="ts_dest_addr_ph">
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<label class="dash-label mb-3"><i class="fas fa-box mr-1 text-gray-400"></i><span data-i18n="cargo_title">货物信息</span></label>
|
||||
<div class="grid sm:grid-cols-2 lg:grid-cols-4 gap-4">
|
||||
<div>
|
||||
<label class="text-xs text-gray-500 mb-1 block" data-i18n="cargo_container">柜型</label>
|
||||
<select name="柜型" class="dash-form-input">
|
||||
<option value="20GP">20GP</option>
|
||||
<option value="40GP">40GP</option>
|
||||
<option value="40HQ">40HQ</option>
|
||||
<option value="45HQ">45HQ</option>
|
||||
<option value="LTL" data-i18n="cargo_container_ltl">散货/托盘</option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label class="text-xs text-gray-500 mb-1 block" data-i18n="cargo_pieces">件数</label>
|
||||
<input type="number" min="0" name="件数" class="dash-form-input" placeholder="0">
|
||||
</div>
|
||||
<div>
|
||||
<label class="text-xs text-gray-500 mb-1 block" data-i18n="cargo_weight">总重量 (kg)</label>
|
||||
<input type="number" min="0" step="0.01" name="总重量(kg)" class="dash-form-input" placeholder="0">
|
||||
</div>
|
||||
<div>
|
||||
<label class="text-xs text-gray-500 mb-1 block" data-i18n="cargo_volume">总体积 (m³)</label>
|
||||
<input type="number" min="0" step="0.01" name="总体积(m³)" class="dash-form-input" placeholder="0">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<label class="dash-label mb-3"><i class="fas fa-user mr-1 text-gray-400"></i><span data-i18n="contact_title">联系人信息</span></label>
|
||||
<div class="grid sm:grid-cols-2 gap-5">
|
||||
<div>
|
||||
<label class="dash-label"><span data-i18n="contact_name">联系人</span><span class="req">*</span></label>
|
||||
<input type="text" name="联系人" required class="dash-form-input" placeholder="请输入联系人姓名" data-i18n-ph="contact_name_ph">
|
||||
</div>
|
||||
<div>
|
||||
<label class="dash-label"><span data-i18n="contact_phone">联系方式</span><span class="req">*</span></label>
|
||||
<input type="text" name="联系方式" required class="dash-form-input" placeholder="电话 / 微信 / 邮箱" data-i18n-ph="contact_phone_ph">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="max-w-xs">
|
||||
<label class="dash-label"><span data-i18n="req_time">要求时间</span></label>
|
||||
<input type="date" name="要求时间" class="dash-form-input">
|
||||
</div>
|
||||
<div class="flex gap-3 pt-2">
|
||||
<button type="submit" class="btn-primary text-white font-bold px-8 py-3.5 rounded-xl" data-i18n="dash_submit">提交订单</button>
|
||||
<button type="button" onclick="showDashView('Home')" class="px-8 py-3.5 rounded-xl border border-gray-200 text-gray-600 font-medium hover:bg-gray-50" data-i18n="dash_cancel">取消</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 视图4:美本土散板下单 -->
|
||||
<div id="dashViewPallet" class="dash-view hidden">
|
||||
<button onclick="showDashView('Home')" class="inline-flex items-center text-gray-500 hover:text-brand-blue mb-6 text-sm font-medium">
|
||||
<i class="fas fa-arrow-left mr-2"></i><span data-i18n="dash_back">返回业务选择</span>
|
||||
</button>
|
||||
<div class="bg-white rounded-2xl shadow-card border border-gray-100 p-8 lg:p-10 max-w-3xl">
|
||||
<div class="flex items-center space-x-3 mb-8">
|
||||
<div class="w-11 h-11 rounded-xl bg-gradient-to-br from-brand-teal to-cyan-700 flex items-center justify-center text-white text-lg"><i class="fas fa-pallet"></i></div>
|
||||
<h2 class="text-2xl font-bold text-gray-900" data-i18n="pl_title">美本土散板下单</h2>
|
||||
</div>
|
||||
<form class="order-form space-y-6" data-order="美本土散板 US Pallet">
|
||||
<div class="grid sm:grid-cols-2 gap-5">
|
||||
<div>
|
||||
<label class="dash-label"><span data-i18n="pl_method">运输方式</span><span class="req">*</span></label>
|
||||
<div class="flex flex-wrap gap-3">
|
||||
<label><input type="radio" name="运输方式" value="拼车" class="seg-input" checked><span class="seg-pill"><span data-i18n="pl_method_pool">拼车</span></span></label>
|
||||
<label><input type="radio" name="运输方式" value="优先拼载" class="seg-input"><span class="seg-pill"><span data-i18n="pl_method_priority">优先拼载</span></span></label>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<label class="dash-label"><span data-i18n="pl_palletize">是否打盘</span><span class="req">*</span></label>
|
||||
<div class="flex flex-wrap gap-3">
|
||||
<label><input type="radio" name="是否打盘" value="是" class="seg-input" checked><span class="seg-pill"><span data-i18n="pl_yes">是</span></span></label>
|
||||
<label><input type="radio" name="是否打盘" value="否" class="seg-input"><span class="seg-pill"><span data-i18n="pl_no">否</span></span></label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<label class="dash-label"><span data-i18n="ts_type">运输类型</span><span class="req">*</span></label>
|
||||
<div class="flex flex-wrap gap-3">
|
||||
<label><input type="radio" name="运输类型" value="港口提柜" class="seg-input" checked><span class="seg-pill"><i class="fas fa-anchor text-xs"></i><span data-i18n="ts_type_port">港口提柜</span></span></label>
|
||||
<label><input type="radio" name="运输类型" value="仓到仓" class="seg-input"><span class="seg-pill"><i class="fas fa-warehouse text-xs"></i><span data-i18n="ts_type_w2w">仓到仓</span></span></label>
|
||||
<label><input type="radio" name="运输类型" value="仓到门" class="seg-input"><span class="seg-pill"><i class="fas fa-door-open text-xs"></i><span data-i18n="ts_type_w2d">仓到门</span></span></label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="grid sm:grid-cols-2 gap-5">
|
||||
<div>
|
||||
<label class="dash-label"><span data-i18n="ts_origin">起运地</span><span class="req">*</span></label>
|
||||
<input type="text" name="起运地" required class="dash-form-input" placeholder="城市 / 港口 / 州" data-i18n-ph="ts_origin_ph">
|
||||
</div>
|
||||
<div>
|
||||
<label class="dash-label"><span data-i18n="ts_dest">目的地</span><span class="req">*</span></label>
|
||||
<input type="text" name="目的地" required class="dash-form-input" placeholder="城市 / 州" data-i18n-ph="ts_dest_ph">
|
||||
</div>
|
||||
<div>
|
||||
<label class="dash-label"><span data-i18n="ts_origin_addr">详细地址</span></label>
|
||||
<input type="text" name="起运详细地址" class="dash-form-input" placeholder="街道 / 门牌" data-i18n-ph="ts_origin_addr_ph">
|
||||
</div>
|
||||
<div>
|
||||
<label class="dash-label"><span data-i18n="ts_dest_addr">详细地址 / 码头 / 仓号</span></label>
|
||||
<input type="text" name="目的详细地址/码头/仓号" class="dash-form-input" placeholder="地址 / 码头 / 仓号" data-i18n-ph="ts_dest_addr_ph">
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<label class="dash-label mb-3"><i class="fas fa-box mr-1 text-gray-400"></i><span data-i18n="cargo_title">货物信息</span></label>
|
||||
<div class="grid sm:grid-cols-2 lg:grid-cols-4 gap-4">
|
||||
<div>
|
||||
<label class="text-xs text-gray-500 mb-1 block" data-i18n="cargo_container">柜型</label>
|
||||
<select name="柜型" class="dash-form-input">
|
||||
<option value="20GP">20GP</option>
|
||||
<option value="40GP">40GP</option>
|
||||
<option value="40HQ">40HQ</option>
|
||||
<option value="45HQ">45HQ</option>
|
||||
<option value="LTL" data-i18n="cargo_container_ltl">散货/托盘</option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label class="text-xs text-gray-500 mb-1 block" data-i18n="cargo_pieces">件数</label>
|
||||
<input type="number" min="0" name="件数" class="dash-form-input" placeholder="0">
|
||||
</div>
|
||||
<div>
|
||||
<label class="text-xs text-gray-500 mb-1 block" data-i18n="cargo_weight">总重量 (kg)</label>
|
||||
<input type="number" min="0" step="0.01" name="总重量(kg)" class="dash-form-input" placeholder="0">
|
||||
</div>
|
||||
<div>
|
||||
<label class="text-xs text-gray-500 mb-1 block" data-i18n="cargo_volume">总体积 (m³)</label>
|
||||
<input type="number" min="0" step="0.01" name="总体积(m³)" class="dash-form-input" placeholder="0">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<label class="dash-label mb-3"><i class="fas fa-user mr-1 text-gray-400"></i><span data-i18n="contact_title">联系人信息</span></label>
|
||||
<div class="grid sm:grid-cols-2 gap-5">
|
||||
<div>
|
||||
<label class="dash-label"><span data-i18n="contact_name">联系人</span><span class="req">*</span></label>
|
||||
<input type="text" name="联系人" required class="dash-form-input" placeholder="请输入联系人姓名" data-i18n-ph="contact_name_ph">
|
||||
</div>
|
||||
<div>
|
||||
<label class="dash-label"><span data-i18n="contact_phone">联系方式</span><span class="req">*</span></label>
|
||||
<input type="text" name="联系方式" required class="dash-form-input" placeholder="电话 / 微信 / 邮箱" data-i18n-ph="contact_phone_ph">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="max-w-xs">
|
||||
<label class="dash-label"><span data-i18n="req_time">要求时间</span></label>
|
||||
<input type="date" name="要求时间" class="dash-form-input">
|
||||
</div>
|
||||
<div class="flex gap-3 pt-2">
|
||||
<button type="submit" class="btn-primary text-white font-bold px-8 py-3.5 rounded-xl" data-i18n="dash_submit">提交订单</button>
|
||||
<button type="button" onclick="showDashView('Home')" class="px-8 py-3.5 rounded-xl border border-gray-200 text-gray-600 font-medium hover:bg-gray-50" data-i18n="dash_cancel">取消</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 视图5:我的订单 -->
|
||||
<div id="dashViewOrders" class="dash-view hidden">
|
||||
<div class="bg-white rounded-2xl shadow-card border border-gray-100 p-10 lg:p-14 max-w-3xl mx-auto text-center">
|
||||
<div class="dash-empty">
|
||||
<i class="fas fa-clipboard-list"></i>
|
||||
<h3 class="text-xl font-bold text-gray-700 mb-2" data-i18n="dash_orders_empty">暂无订单</h3>
|
||||
<p class="text-gray-500" data-i18n="dash_orders_hint">您还没有提交任何订单,前往「业务总览」选择服务开始下单吧。</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
<!-- 右侧信息栏 -->
|
||||
<aside id="dashRight" class="dash-right hidden lg:flex flex-col">
|
||||
<div class="dash-right-card">
|
||||
<h4 data-i18n="right_account_title">账户信息</h4>
|
||||
<div class="dash-account">
|
||||
<div class="dash-account-avatar" id="dashAvatar">C</div>
|
||||
<div>
|
||||
<div class="dash-account-name" id="dashAccountName">虫虫出海客户</div>
|
||||
<div class="dash-account-type" data-i18n="right_account_type">企业客户</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="dash-right-card">
|
||||
<h4 data-i18n="right_stat_title">数据概览</h4>
|
||||
<div class="dash-stat-row">
|
||||
<span class="dash-stat-label" data-i18n="right_stat_progress">进行中订单</span>
|
||||
<span class="dash-stat-value" id="statProgress">0</span>
|
||||
</div>
|
||||
<div class="dash-stat-row">
|
||||
<span class="dash-stat-label" data-i18n="right_stat_done">已完成订单</span>
|
||||
<span class="dash-stat-value" id="statDone">0</span>
|
||||
</div>
|
||||
<div class="dash-stat-row">
|
||||
<span class="dash-stat-label" data-i18n="right_stat_month">本月下单</span>
|
||||
<span class="dash-stat-value" id="statMonth">0</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="dash-right-card">
|
||||
<h4 data-i18n="right_help_title">帮助与支持</h4>
|
||||
<div class="dash-help-item" onclick="showToast(t('right_help_cs_toast'))">
|
||||
<i class="fas fa-headset"></i><span data-i18n="right_help_cs">联系客服</span>
|
||||
</div>
|
||||
<div class="dash-help-item" onclick="showToast(t('right_help_faq_toast'))">
|
||||
<i class="fas fa-question-circle"></i><span data-i18n="right_help_faq">常见问题</span>
|
||||
</div>
|
||||
<div class="dash-help-item" onclick="showToast(t('right_help_quote_toast'))">
|
||||
<i class="fas fa-tag"></i><span data-i18n="right_help_quote">获取报价</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="dash-tip">
|
||||
<i class="fas fa-lightbulb"></i>
|
||||
<span data-i18n="right_tip_text">提交订单后,专属客户经理将在 24 小时内与您联系,确认运输方案与报价。</span>
|
||||
</div>
|
||||
</aside>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<script>
|
||||
// 工作台交互
|
||||
function setDashUser(name) {
|
||||
const display = name ? name : '虫虫出海客户';
|
||||
const topEl = document.getElementById('dashUserName');
|
||||
if (topEl) topEl.textContent = 'Hi, ' + display;
|
||||
const accEl = document.getElementById('dashAccountName');
|
||||
if (accEl) accEl.textContent = display;
|
||||
const avEl = document.getElementById('dashAvatar');
|
||||
if (avEl) avEl.textContent = display.charAt(0).toUpperCase();
|
||||
}
|
||||
function showDashView(name) {
|
||||
document.querySelectorAll('#workbench .dash-view').forEach(v => v.classList.add('hidden'));
|
||||
const view = document.getElementById('dashView' + name);
|
||||
if (view) view.classList.remove('hidden');
|
||||
document.querySelectorAll('.dash-nav-link').forEach(l => l.classList.toggle('active', l.getAttribute('data-view') === name));
|
||||
window.scrollTo(0, 0);
|
||||
}
|
||||
function goDash(name) {
|
||||
showDashView(name);
|
||||
closeDashSidebar();
|
||||
}
|
||||
function toggleDashSidebar() {
|
||||
const sb = document.getElementById('dashSidebar');
|
||||
const ov = document.getElementById('dashOverlay');
|
||||
if (!sb) return;
|
||||
const open = sb.classList.toggle('open');
|
||||
if (ov) ov.classList.toggle('show', open);
|
||||
document.body.style.overflow = open ? 'hidden' : '';
|
||||
}
|
||||
function closeDashSidebar() {
|
||||
const sb = document.getElementById('dashSidebar');
|
||||
const ov = document.getElementById('dashOverlay');
|
||||
if (sb) sb.classList.remove('open');
|
||||
if (ov) ov.classList.remove('show');
|
||||
document.body.style.overflow = '';
|
||||
}
|
||||
function openOrder(type) {
|
||||
showDashView(type);
|
||||
}
|
||||
function doLogout() {
|
||||
showToast(t('toast_logout'));
|
||||
setTimeout(() => { window.location.href = 'index.html'; }, 700);
|
||||
}
|
||||
|
||||
// 订单表单提交
|
||||
document.querySelectorAll('.order-form').forEach(form => {
|
||||
form.addEventListener('submit', function(e) {
|
||||
e.preventDefault();
|
||||
showToast(t('toast_order_ok'));
|
||||
this.reset();
|
||||
setTimeout(() => showDashView('Home'), 1200);
|
||||
});
|
||||
});
|
||||
|
||||
// ====== 多语言 i18n ======
|
||||
const i18n = {
|
||||
zh: {
|
||||
dash_home_link: "返回官网", dash_logout: "退出登录",
|
||||
dash_welcome_title: "选择业务,快速下单", dash_welcome_sub: "请选择您需要的业务类型,填写信息后提交订单,我们将尽快为您安排。",
|
||||
dash_biz1_title: "海外采购", dash_biz1_desc: "采购代购 · 验货质检 · 集中发货",
|
||||
dash_biz2_title: "美国本土卡", dash_biz2_desc: "港口提柜 · 仓到仓 · 仓到门",
|
||||
dash_biz3_title: "美本土散板", dash_biz3_desc: "拼车拼载 · 打盘服务 · 灵活派送",
|
||||
dash_start: "开始下单", dash_back: "返回业务选择", dash_submit: "提交订单", dash_cancel: "取消",
|
||||
po_title: "海外采购下单", po_category: "采购品类", po_category_ph: "如:家居用品 / 3C 配件",
|
||||
po_spec: "商品规格", po_spec_ph: "如:尺寸 / 颜色 / 材质", po_link: "商品链接", po_link_ph: "https://",
|
||||
po_qty: "采购数量", po_qty_ph: "0", po_price: "预算单价", po_price_ph: "0.00",
|
||||
po_address: "收货地址", po_address_ph: "请输入收货地址", po_contact: "联系人", po_contact_ph: "请输入联系人姓名",
|
||||
po_phone: "联系电话", po_phone_ph: "请输入联系电话", po_note: "订单备注", po_note_ph: "其他需求说明(选填)",
|
||||
tk_title: "美国本土卡下单",
|
||||
pl_title: "美本土散板下单", pl_method: "运输方式", pl_method_pool: "拼车", pl_method_priority: "优先拼载",
|
||||
pl_palletize: "是否打盘", pl_yes: "是", pl_no: "否",
|
||||
ts_type: "运输类型", ts_type_port: "港口提柜", ts_type_w2w: "仓到仓", ts_type_w2d: "仓到门",
|
||||
ts_origin: "起运地", ts_origin_ph: "城市 / 港口 / 州", ts_dest: "目的地", ts_dest_ph: "城市 / 州",
|
||||
ts_origin_addr: "详细地址", ts_origin_addr_ph: "街道 / 门牌",
|
||||
ts_dest_addr: "详细地址 / 码头 / 仓号", ts_dest_addr_ph: "地址 / 码头 / 仓号",
|
||||
cargo_title: "货物信息", cargo_container: "柜型", cargo_container_ltl: "散货/托盘",
|
||||
cargo_pieces: "件数", cargo_weight: "总重量 (kg)", cargo_volume: "总体积 (m³)",
|
||||
req_time: "要求时间", contact_title: "联系人信息", contact_name: "联系人", contact_name_ph: "请输入联系人姓名", contact_phone: "联系方式", contact_phone_ph: "电话 / 微信 / 邮箱",
|
||||
toast_logout: "已退出登录", toast_order_ok: "订单提交成功,我们将尽快为您安排!",
|
||||
dash_menu_main: "主导航", dash_menu_overview: "业务总览", dash_menu_proc: "海外采购",
|
||||
dash_menu_truck: "美国本土卡", dash_menu_pallet: "美本土散板", dash_menu_orders: "我的订单",
|
||||
dash_orders_empty: "暂无订单", dash_orders_hint: "您还没有提交任何订单,前往「业务总览」选择服务开始下单吧。",
|
||||
right_account_title: "账户信息", right_account_type: "企业客户",
|
||||
right_stat_title: "数据概览", right_stat_progress: "进行中订单", right_stat_done: "已完成订单", right_stat_month: "本月下单",
|
||||
right_help_title: "帮助与支持", right_help_cs: "联系客服", right_help_faq: "常见问题", right_help_quote: "获取报价",
|
||||
right_help_cs_toast: "客服热线:400-XXX-XXXX(工作日 9:00-18:00)", right_help_faq_toast: "常见问题页面即将上线", right_help_quote_toast: "报价顾问将尽快与您联系",
|
||||
right_tip_text: "提交订单后,专属客户经理将在 24 小时内与您联系,确认运输方案与报价。"
|
||||
},
|
||||
en: {
|
||||
dash_home_link: "Back to Site", dash_logout: "Log Out",
|
||||
dash_welcome_title: "Choose a Service to Order", dash_welcome_sub: "Select the service you need, fill in the details, and submit your order — we will arrange it for you shortly.",
|
||||
dash_biz1_title: "Overseas Sourcing", dash_biz1_desc: "Sourcing · Inspection · Consolidation",
|
||||
dash_biz2_title: "US Domestic Trucking", dash_biz2_desc: "Port Pickup · Warehouse-to-Warehouse · Door-to-Door",
|
||||
dash_biz3_title: "US Pallet Break", dash_biz3_desc: "Pooled Freight · Palletizing · Flexible Delivery",
|
||||
dash_start: "Start Order", dash_back: "Back to Services", dash_submit: "Submit Order", dash_cancel: "Cancel",
|
||||
po_title: "Overseas Sourcing Order", po_category: "Product Category", po_category_ph: "e.g. Home goods / 3C accessories",
|
||||
po_spec: "Specs", po_spec_ph: "e.g. Size / Color / Material", po_link: "Product Link", po_link_ph: "https://",
|
||||
po_qty: "Quantity", po_qty_ph: "0", po_price: "Budget Unit Price", po_price_ph: "0.00",
|
||||
po_address: "Shipping Address", po_address_ph: "Enter shipping address", po_contact: "Contact Name", po_contact_ph: "Enter contact name",
|
||||
po_phone: "Contact Phone", po_phone_ph: "Enter phone number", po_note: "Order Notes", po_note_ph: "Other requirements (optional)",
|
||||
tk_title: "US Domestic Trucking Order",
|
||||
pl_title: "US Pallet Break Order", pl_method: "Transport Mode", pl_method_pool: "Pooled", pl_method_priority: "Priority Load",
|
||||
pl_palletize: "Palletize?", pl_yes: "Yes", pl_no: "No",
|
||||
ts_type: "Transport Type", ts_type_port: "Port Pickup", ts_type_w2w: "Warehouse to Warehouse", ts_type_w2d: "Warehouse to Door",
|
||||
ts_origin: "Origin", ts_origin_ph: "City / Port / State", ts_dest: "Destination", ts_dest_ph: "City / State",
|
||||
ts_origin_addr: "Detailed Address", ts_origin_addr_ph: "Street / Number",
|
||||
ts_dest_addr: "Detailed Address / Pier / WH No.", ts_dest_addr_ph: "Address / Pier / WH No.",
|
||||
cargo_title: "Cargo Info", cargo_container: "Container Type", cargo_container_ltl: "Loose / Pallet",
|
||||
cargo_pieces: "Pieces", cargo_weight: "Total Weight (kg)", cargo_volume: "Total Volume (m³)",
|
||||
req_time: "Required By", contact_title: "Contact Info", contact_name: "Contact Person", contact_name_ph: "Enter contact name", contact_phone: "Contact Number", contact_phone_ph: "Phone / WeChat / Email",
|
||||
toast_logout: "Logged out", toast_order_ok: "Order submitted! We will arrange it for you shortly.",
|
||||
dash_menu_main: "Main Menu", dash_menu_overview: "Overview", dash_menu_proc: "Overseas Sourcing",
|
||||
dash_menu_truck: "US Trucking", dash_menu_pallet: "US Pallet Break", dash_menu_orders: "My Orders",
|
||||
dash_orders_empty: "No Orders Yet", dash_orders_hint: "You haven't placed any orders yet. Go to Overview to start a new order.",
|
||||
right_account_title: "Account", right_account_type: "Enterprise Client",
|
||||
right_stat_title: "Overview", right_stat_progress: "In Progress", right_stat_done: "Completed", right_stat_month: "This Month",
|
||||
right_help_title: "Help & Support", right_help_cs: "Contact Support", right_help_faq: "FAQ", right_help_quote: "Get a Quote",
|
||||
right_help_cs_toast: "Support Hotline: 400-XXX-XXXX (Mon-Fri 9:00-18:00)", right_help_faq_toast: "FAQ page coming soon", right_help_quote_toast: "A quoting specialist will contact you shortly",
|
||||
right_tip_text: "After you submit an order, your dedicated account manager will contact you within 24 hours to confirm the shipping plan and quote."
|
||||
},
|
||||
es: {
|
||||
dash_home_link: "Volver al sitio", dash_logout: "Cerrar sesión",
|
||||
dash_welcome_title: "Elige un servicio para pedir", dash_welcome_sub: "Selecciona el servicio que necesitas, completa los datos y envía tu pedido; lo gestionaremos lo antes posible.",
|
||||
dash_biz1_title: "Abastecimiento en el extranjero", dash_biz1_desc: "Compras · Inspección · Consolidación",
|
||||
dash_biz2_title: "Transporte por camión en EE.UU.", dash_biz2_desc: "Recogida en puerto · Almacén a almacén · Puerta a puerta",
|
||||
dash_biz3_title: "Despaletizado en EE.UU.", dash_biz3_desc: "Carga compartida · Paletizado · Entrega flexible",
|
||||
dash_start: "Iniciar pedido", dash_back: "Volver a servicios", dash_submit: "Enviar pedido", dash_cancel: "Cancelar",
|
||||
po_title: "Pedido de abastecimiento", po_category: "Categoría del producto", po_category_ph: "ej. Artículos para el hogar / Accesorios 3C",
|
||||
po_spec: "Especificaciones", po_spec_ph: "ej. Tamaño / Color / Material", po_link: "Enlace del producto", po_link_ph: "https://",
|
||||
po_qty: "Cantidad", po_qty_ph: "0", po_price: "Precio unitario estimado", po_price_ph: "0.00",
|
||||
po_address: "Dirección de envío", po_address_ph: "Ingresa la dirección de envío", po_contact: "Persona de contacto", po_contact_ph: "Ingresa el nombre de contacto",
|
||||
po_phone: "Teléfono de contacto", po_phone_ph: "Ingresa el teléfono", po_note: "Notas del pedido", po_note_ph: "Otros requisitos (opcional)",
|
||||
tk_title: "Pedido de camión en EE.UU.",
|
||||
pl_title: "Pedido de despaletizado en EE.UU.", pl_method: "Modo de transporte", pl_method_pool: "Carga compartida", pl_method_priority: "Carga prioritaria",
|
||||
pl_palletize: "¿Paletizar?", pl_yes: "Sí", pl_no: "No",
|
||||
ts_type: "Tipo de transporte", ts_type_port: "Recogida en puerto", ts_type_w2w: "Almacén a almacén", ts_type_w2d: "Almacén a puerta",
|
||||
ts_origin: "Origen", ts_origin_ph: "Ciudad / Puerto / Estado", ts_dest: "Destino", ts_dest_ph: "Ciudad / Estado",
|
||||
ts_origin_addr: "Dirección detallada", ts_origin_addr_ph: "Calle / Número",
|
||||
ts_dest_addr: "Dirección / Muelle / N.º almacén", ts_dest_addr_ph: "Dirección / Muelle / N.º almacén",
|
||||
cargo_title: "Información de carga", cargo_container: "Tipo de contenedor", cargo_container_ltl: "Carga suelta / Paleta",
|
||||
cargo_pieces: "Piezas", cargo_weight: "Peso total (kg)", cargo_volume: "Volumen total (m³)",
|
||||
req_time: "Fecha requerida", contact_title: "Información de contacto", contact_name: "Persona de contacto", contact_name_ph: "Ingrese el nombre de contacto", contact_phone: "Número de contacto", contact_phone_ph: "Teléfono / WeChat / Email",
|
||||
toast_logout: "Sesión cerrada", toast_order_ok: "¡Pedido enviado! Lo gestionaremos lo antes posible.",
|
||||
dash_menu_main: "Menú principal", dash_menu_overview: "Resumen", dash_menu_proc: "Abastecimiento",
|
||||
dash_menu_truck: "Camión en EE.UU.", dash_menu_pallet: "Despaletizado", dash_menu_orders: "Mis pedidos",
|
||||
dash_orders_empty: "Sin pedidos", dash_orders_hint: "Aún no has enviado pedidos. Ve a Resumen para empezar uno nuevo.",
|
||||
right_account_title: "Cuenta", right_account_type: "Cliente Empresarial",
|
||||
right_stat_title: "Resumen", right_stat_progress: "En Progreso", right_stat_done: "Completados", right_stat_month: "Este Mes",
|
||||
right_help_title: "Ayuda y Soporte", right_help_cs: "Contactar Soporte", right_help_faq: "Preguntas Frecuentes", right_help_quote: "Obtener Cotización",
|
||||
right_help_cs_toast: "Línea de soporte: 400-XXX-XXXX (Lun-Vie 9:00-18:00)", right_help_faq_toast: "Página de preguntas próximamente", right_help_quote_toast: "Un especialista en cotización te contactará pronto",
|
||||
right_tip_text: "Después de enviar el pedido, tu ejecutivo de cuenta te contactará en 24 horas para confirmar el plan de envío y la cotización."
|
||||
}
|
||||
};
|
||||
|
||||
let currentLang = localStorage.getItem('cc_lang') || 'zh';
|
||||
function t(key) {
|
||||
return (i18n[currentLang] && i18n[currentLang][key] !== undefined) ? i18n[currentLang][key] : key;
|
||||
}
|
||||
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');
|
||||
if (i18n[lang][k] !== undefined) el.textContent = i18n[lang][k];
|
||||
});
|
||||
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('#langSwitcherDash [data-lang]').forEach(b => {
|
||||
b.classList.toggle('active', b.getAttribute('data-lang') === lang);
|
||||
});
|
||||
try { localStorage.setItem('cc_lang', lang); } catch (e) {}
|
||||
}
|
||||
document.querySelectorAll('#langSwitcherDash [data-lang]').forEach(b => {
|
||||
b.addEventListener('click', () => applyLanguage(b.getAttribute('data-lang')));
|
||||
});
|
||||
|
||||
// Toast 提示
|
||||
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);
|
||||
}
|
||||
|
||||
// 初始化
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
applyLanguage(currentLang);
|
||||
// 尝试从官网登录带入用户名(URL ?user=xxx)
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
const userParam = params.get('user');
|
||||
if (userParam) {
|
||||
setDashUser(decodeURIComponent(userParam));
|
||||
}
|
||||
});
|
||||
applyLanguage(currentLang);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,455 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>虫虫出海 - 用户登录</title>
|
||||
<style>
|
||||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Hiragino Sans GB', sans-serif;
|
||||
display: flex;
|
||||
min-height: 100vh;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 50%, #f093fb 100%);
|
||||
background-size: 400% 400%;
|
||||
animation: gradientShift 15s ease infinite;
|
||||
}
|
||||
|
||||
@keyframes gradientShift {
|
||||
0% { background-position: 0% 50%; }
|
||||
50% { background-position: 100% 50%; }
|
||||
100% { background-position: 0% 50%; }
|
||||
}
|
||||
|
||||
/* ===== 左侧品牌区 ===== */
|
||||
.brand-side {
|
||||
width: 50%;
|
||||
min-width: 420px;
|
||||
position: relative;
|
||||
background: linear-gradient(155deg, rgba(30,64,175,0.85) 0%, rgba(37,99,235,0.75) 40%, rgba(59,130,246,0.65) 100%);
|
||||
backdrop-filter: blur(20px);
|
||||
-webkit-backdrop-filter: blur(20px);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* 浮动装饰圆圈 */
|
||||
.brand-side::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: -20%; right: -20%;
|
||||
width: 80%; height: 80%;
|
||||
background: radial-gradient(ellipse, rgba(255,255,255,.2) 0%, transparent 70%);
|
||||
animation: float1 8s ease-in-out infinite;
|
||||
pointer-events: none;
|
||||
}
|
||||
.brand-side::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: -15%; left: -15%;
|
||||
width: 70%; height: 70%;
|
||||
background: radial-gradient(ellipse, rgba(147,197,253,.3) 0%, transparent 65%);
|
||||
animation: float2 10s ease-in-out infinite;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
@keyframes float1 {
|
||||
0%, 100% { transform: translate(0, 0) scale(1); }
|
||||
50% { transform: translate(-30px, 30px) scale(1.05); }
|
||||
}
|
||||
@keyframes float2 {
|
||||
0%, 100% { transform: translate(0, 0) scale(1); }
|
||||
50% { transform: translate(20px, -20px) scale(1.1); }
|
||||
}
|
||||
|
||||
.brand-content {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
text-align: center;
|
||||
padding: 40px;
|
||||
animation: fadeInUp 0.8s ease-out;
|
||||
}
|
||||
|
||||
@keyframes fadeInUp {
|
||||
from { opacity: 0; transform: translateY(30px); }
|
||||
to { opacity: 1; transform: translateY(0); }
|
||||
}
|
||||
|
||||
.logo-wrap {
|
||||
width: 100px; height: 100px;
|
||||
margin: 0 auto 24px;
|
||||
border-radius: 26px;
|
||||
overflow: hidden;
|
||||
background: rgba(255,255,255,.95);
|
||||
padding: 12px;
|
||||
box-shadow: 0 12px 40px rgba(0,0,0,.15), 0 0 0 1px rgba(255,255,255,.5) inset;
|
||||
animation: logoFloat 3s ease-in-out infinite;
|
||||
}
|
||||
@keyframes logoFloat {
|
||||
0%, 100% { transform: translateY(0); }
|
||||
50% { transform: translateY(-8px); }
|
||||
}
|
||||
.logo-wrap img { width: 100%; height: 100%; object-fit: contain; }
|
||||
|
||||
.brand-title { font-size: 36px; font-weight: 800; color: #fff; letter-spacing: 4px; text-shadow: 0 4px 20px rgba(0,0,0,.15); }
|
||||
.brand-subtitle { font-size: 15px; color: rgba(255,255,255,.88); margin-top: 12px; letter-spacing: 2px; }
|
||||
|
||||
.feature-list { margin-top: 56px; text-align: left; display: inline-block; }
|
||||
.feature-item {
|
||||
color: rgba(255,255,255,.9);
|
||||
font-size: 15px;
|
||||
line-height: 2.6;
|
||||
padding-left: 24px;
|
||||
position: relative;
|
||||
opacity: 0;
|
||||
animation: fadeInLeft 0.6s ease-out forwards;
|
||||
}
|
||||
.feature-item:nth-child(1) { animation-delay: 0.2s; }
|
||||
.feature-item:nth-child(2) { animation-delay: 0.4s; }
|
||||
.feature-item:nth-child(3) { animation-delay: 0.6s; }
|
||||
@keyframes fadeInLeft {
|
||||
from { opacity: 0; transform: translateX(-20px); }
|
||||
to { opacity: 1; transform: translateX(0); }
|
||||
}
|
||||
.feature-item::before {
|
||||
content: '✓';
|
||||
position: absolute;
|
||||
left: 0; top: 2px;
|
||||
width: 18px; height: 18px;
|
||||
border-radius: 50%;
|
||||
background: rgba(255,255,255,.25);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 11px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
/* ===== 右侧登录区 ===== */
|
||||
.login-side {
|
||||
flex: 1;
|
||||
min-width: 400px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 40px;
|
||||
}
|
||||
|
||||
.login-card {
|
||||
width: 100%;
|
||||
max-width: 420px;
|
||||
padding: 52px 44px;
|
||||
background: rgba(255, 255, 255, 0.95);
|
||||
backdrop-filter: blur(20px);
|
||||
-webkit-backdrop-filter: blur(20px);
|
||||
border-radius: 24px;
|
||||
box-shadow: 0 25px 80px rgba(0,0,0,.15), 0 0 0 1px rgba(255,255,255,.5) inset;
|
||||
animation: cardFloat 0.8s ease-out;
|
||||
}
|
||||
@keyframes cardFloat {
|
||||
from { opacity: 0; transform: translateY(40px) scale(0.95); }
|
||||
to { opacity: 1; transform: translateY(0) scale(1); }
|
||||
}
|
||||
|
||||
/* 标题区 */
|
||||
.card-header { margin-bottom: 36px; }
|
||||
.card-title {
|
||||
font-size: 30px;
|
||||
font-weight: 800;
|
||||
background: linear-gradient(135deg, #1e293b 0%, #334155 100%);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
.card-desc {
|
||||
font-size: 15px;
|
||||
color: #64748b;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
/* 表单 */
|
||||
.form-group { margin-bottom: 22px; }
|
||||
.form-input {
|
||||
width: 100%;
|
||||
height: 52px;
|
||||
border: 2px solid #e2e8f0;
|
||||
border-radius: 14px;
|
||||
padding: 0 18px;
|
||||
font-size: 15px;
|
||||
color: #1e293b;
|
||||
outline: none;
|
||||
transition: all .3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
background: #f8fafc;
|
||||
}
|
||||
.form-input:focus {
|
||||
border-color: #667eea;
|
||||
background: #fff;
|
||||
box-shadow: 0 0 0 4px rgba(102, 126, 234, 0.1);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
.form-input::placeholder { color: #94a3b8; }
|
||||
|
||||
/* 密码框 */
|
||||
.password-wrap { position: relative; }
|
||||
.password-toggle {
|
||||
position: absolute; right: 14px; top: 50%; transform: translateY(-50%);
|
||||
border: none; background: none; cursor: pointer;
|
||||
padding: 6px; color: #64748b; font-size: 18px; line-height: 1;
|
||||
transition: all .2s;
|
||||
}
|
||||
.password-toggle:hover { color: #667eea; transform: translateY(-50%) scale(1.1); }
|
||||
|
||||
/* 验证码 */
|
||||
.captcha-row {
|
||||
display: flex;
|
||||
gap: 14px;
|
||||
align-items: center;
|
||||
}
|
||||
.captcha-row .form-input { flex: 1; }
|
||||
.captcha-img {
|
||||
width: 120px; height: 52px;
|
||||
border: 2px solid #e2e8f0;
|
||||
border-radius: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
font-size: 22px;
|
||||
font-weight: 700;
|
||||
letter-spacing: 6px;
|
||||
transition: all .3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
flex-shrink: 0;
|
||||
background: linear-gradient(135deg, #f0f9ff 0%, #e0f2fe 100%);
|
||||
}
|
||||
.captcha-img:hover {
|
||||
border-color: #667eea;
|
||||
transform: scale(1.05);
|
||||
box-shadow: 0 4px 12px rgba(102, 126, 234, 0.2);
|
||||
}
|
||||
|
||||
/* 按钮 */
|
||||
.submit-btn {
|
||||
width: 100%;
|
||||
height: 54px;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 50%, #f093fb 100%);
|
||||
background-size: 200% 200%;
|
||||
color: #fff;
|
||||
border: none;
|
||||
border-radius: 14px;
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
cursor: pointer;
|
||||
transition: all .3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
letter-spacing: 4px;
|
||||
box-shadow: 0 8px 24px rgba(102, 126, 234, 0.4);
|
||||
}
|
||||
.submit-btn:hover {
|
||||
background-position: 100% 0;
|
||||
transform: translateY(-3px);
|
||||
box-shadow: 0 12px 32px rgba(102, 126, 234, 0.5);
|
||||
}
|
||||
.submit-btn:active { transform: translateY(-1px); }
|
||||
|
||||
/* 底部辅助行 */
|
||||
.form-options {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 28px;
|
||||
}
|
||||
.remember-me {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
font-size: 14px;
|
||||
color: #64748b;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
transition: color .2s;
|
||||
}
|
||||
.remember-me:hover { color: #475569; }
|
||||
.remember-me input { accent-color: #667eea; width: 18px; height: 18px; cursor: pointer; }
|
||||
.forgot-link {
|
||||
font-size: 14px;
|
||||
color: #667eea;
|
||||
text-decoration: none;
|
||||
font-weight: 500;
|
||||
transition: all .2s;
|
||||
}
|
||||
.forgot-link:hover { color: #764ba2; text-decoration: underline; }
|
||||
|
||||
/* 底部注册链接 */
|
||||
.register-tip {
|
||||
text-align: center;
|
||||
margin-top: 28px;
|
||||
font-size: 14px;
|
||||
color: #94a3b8;
|
||||
}
|
||||
.register-tip a {
|
||||
color: #667eea;
|
||||
text-decoration: none;
|
||||
font-weight: 600;
|
||||
transition: all .2s;
|
||||
}
|
||||
.register-tip a:hover { color: #764ba2; text-decoration: underline; }
|
||||
|
||||
/* 错误提示 */
|
||||
.error-msg {
|
||||
font-size: 13px;
|
||||
color: #ef4444;
|
||||
margin-top: 6px;
|
||||
display: none;
|
||||
padding-left: 4px;
|
||||
animation: shake 0.3s ease-out;
|
||||
}
|
||||
.error-msg.show { display: block; }
|
||||
@keyframes shake {
|
||||
0%, 100% { transform: translateX(0); }
|
||||
25% { transform: translateX(-4px); }
|
||||
75% { transform: translateX(4px); }
|
||||
}
|
||||
|
||||
/* 响应式 */
|
||||
@media (max-width: 900px) {
|
||||
body { flex-direction: column; }
|
||||
.brand-side { min-width: auto; min-height: 240px; width: 100%; }
|
||||
.brand-content { padding: 32px; }
|
||||
.feature-list { display: none; }
|
||||
.login-side { min-width: auto; padding: 24px 16px; }
|
||||
.login-card { max-width: 420px; padding: 40px 28px; }
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<!-- 左侧品牌 -->
|
||||
<div class="brand-side">
|
||||
<div class="brand-content">
|
||||
<div class="logo-wrap">
|
||||
<img src="logo.png" alt="Logo">
|
||||
</div>
|
||||
<h1 class="brand-title">虫虫出海</h1>
|
||||
<p class="brand-subtitle">一站式跨境物流服务平台</p>
|
||||
|
||||
<div class="feature-list">
|
||||
<div class="feature-item">安全可靠 · 全程可追踪</div>
|
||||
<div class="feature-item">专业团队 · 快速响应</div>
|
||||
<div class="feature-item">透明报价 · 无隐藏费用</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 右侧登录 -->
|
||||
<div class="login-side">
|
||||
<div class="login-card">
|
||||
<div class="card-header">
|
||||
<h2 class="card-title">欢迎回来</h2>
|
||||
<p class="card-desc">请登录您的账户以继续</p>
|
||||
</div>
|
||||
|
||||
<form id="loginForm" autocomplete="off">
|
||||
<div class="form-group">
|
||||
<input type="text" class="form-input" id="loginUsername" placeholder="用户名">
|
||||
<div class="error-msg" id="loginUserError">请输入用户名</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="password-wrap">
|
||||
<input type="password" class="form-input" id="loginPassword" placeholder="密码">
|
||||
<button type="button" class="password-toggle" onclick="togglePassword()">👁</button>
|
||||
</div>
|
||||
<div class="error-msg" id="loginPassError">请输入密码</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="captcha-row">
|
||||
<input type="text" class="form-input" id="loginCaptcha" placeholder="验证码" maxlength="4">
|
||||
<div class="captcha-img" id="loginCaptchaImg" onclick="refreshCaptcha('login')"></div>
|
||||
</div>
|
||||
<div class="error-msg" id="loginCaptchaError">验证码错误</div>
|
||||
</div>
|
||||
|
||||
<div class="form-options">
|
||||
<label class="remember-me">
|
||||
<input type="checkbox"> 记住我
|
||||
</label>
|
||||
<a href="javascript:void(0)" class="forgot-link">忘记密码?</a>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="submit-btn">登 录</button>
|
||||
</form>
|
||||
|
||||
<div class="register-tip">没有账号?<a href="register.html">立即注册</a></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// 验证码
|
||||
let currentCaptcha = {};
|
||||
|
||||
function generateCaptcha() {
|
||||
const chars = 'ABCDEFGHJKLMNPQRSTUVWXYZabcdefghjkmnpqrstuvwxyz23456789';
|
||||
let c = '';
|
||||
for (let i = 0; i < 4; i++) c += chars.charAt(Math.floor(Math.random() * chars.length));
|
||||
return c;
|
||||
}
|
||||
|
||||
function refreshCaptcha(type) {
|
||||
const c = generateCaptcha();
|
||||
currentCaptcha[type] = c;
|
||||
const el = document.getElementById(type + 'CaptchaImg');
|
||||
if (!el) return;
|
||||
el.textContent = c;
|
||||
el.style.transform = 'rotate(' + (Math.random() * 8 - 4) + 'deg)';
|
||||
el.style.color = ['#2563eb','#3b82f6','#1d4ed8','#1e40af'][Math.floor(Math.random()*4)];
|
||||
}
|
||||
|
||||
refreshCaptcha('login');
|
||||
|
||||
// 密码显隐
|
||||
function togglePassword() {
|
||||
const pw = document.getElementById('loginPassword');
|
||||
pw.type = pw.type === 'password' ? 'text' : 'password';
|
||||
}
|
||||
|
||||
// 表单提交
|
||||
document.getElementById('loginForm').addEventListener('submit', function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
var username = document.getElementById('loginUsername').value.trim();
|
||||
var password = document.getElementById('loginPassword').value;
|
||||
var captcha = document.getElementById('loginCaptcha').value.trim();
|
||||
|
||||
document.querySelectorAll('#loginForm .error-msg').forEach(function(el) { el.classList.remove('show'); });
|
||||
var hasError = false;
|
||||
|
||||
if (!username) { document.getElementById('loginUserError').classList.add('show'); hasError = true; }
|
||||
if (!password) { document.getElementById('loginPassError').classList.add('show'); hasError = true; }
|
||||
if (captcha.toUpperCase() !== currentCaptcha['login'].toUpperCase()) {
|
||||
document.getElementById('loginCaptchaError').classList.add('show');
|
||||
refreshCaptcha('login');
|
||||
hasError = true;
|
||||
}
|
||||
|
||||
if (hasError) return;
|
||||
alert('登录成功!欢迎回来,' + username + '!');
|
||||
});
|
||||
|
||||
// 实时清除错误
|
||||
document.querySelectorAll('.form-input').forEach(function(input) {
|
||||
input.addEventListener('input', function() {
|
||||
var group = this.closest('.form-group');
|
||||
if (!group) return;
|
||||
var err = group.querySelector('.error-msg');
|
||||
if (err) err.classList.remove('show');
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
After Width: | Height: | Size: 764 KiB |
@@ -0,0 +1,511 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>虫虫出海 - 企业注册</title>
|
||||
<style>
|
||||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', sans-serif;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 50%, #f093fb 100%);
|
||||
background-size: 400% 400%;
|
||||
animation: gradientShift 15s ease infinite;
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 40px 20px;
|
||||
position: relative;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
@keyframes gradientShift {
|
||||
0% { background-position: 0% 50%; }
|
||||
50% { background-position: 100% 50%; }
|
||||
100% { background-position: 0% 50%; }
|
||||
}
|
||||
|
||||
/* 装饰性浮动元素 */
|
||||
body::before {
|
||||
content: '';
|
||||
position: fixed;
|
||||
top: -50%;
|
||||
left: -50%;
|
||||
width: 200%;
|
||||
height: 200%;
|
||||
background: radial-gradient(circle, rgba(255,255,255,0.1) 0%, transparent 60%);
|
||||
animation: rotate 30s linear infinite;
|
||||
pointer-events: none;
|
||||
}
|
||||
@keyframes rotate {
|
||||
from { transform: rotate(0deg); }
|
||||
to { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
/* ====== 主容器:居中卡片式 ====== */
|
||||
.container {
|
||||
width: 100%;
|
||||
max-width: 580px;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
animation: fadeInUp 0.8s ease-out;
|
||||
}
|
||||
|
||||
@keyframes fadeInUp {
|
||||
from { opacity: 0; transform: translateY(40px); }
|
||||
to { opacity: 1; transform: translateY(0); }
|
||||
}
|
||||
|
||||
/* 顶部品牌条 */
|
||||
.top-bar {
|
||||
text-align: center;
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
|
||||
.logo-wrap {
|
||||
width: 120px; height: 120px;
|
||||
margin: 0 auto 18px;
|
||||
border-radius: 32px;
|
||||
background: rgba(255,255,255,0.95);
|
||||
padding: 20px;
|
||||
box-shadow: 0 20px 60px rgba(0,0,0,.2), 0 0 0 1px rgba(255,255,255,.5) inset;
|
||||
overflow: hidden;
|
||||
animation: logoFloat 3s ease-in-out infinite;
|
||||
}
|
||||
@keyframes logoFloat {
|
||||
0%, 100% { transform: translateY(0); }
|
||||
50% { transform: translateY(-10px); }
|
||||
}
|
||||
.logo-wrap img { width: 100%; height: 100%; object-fit: contain; filter: none; }
|
||||
.logo-wrap img.no-filter { filter: none; }
|
||||
|
||||
.brand-name {
|
||||
font-size: 30px;
|
||||
font-weight: 800;
|
||||
color: #fff;
|
||||
letter-spacing: 3px;
|
||||
margin-bottom: 6px;
|
||||
text-shadow: 0 4px 20px rgba(0,0,0,.2);
|
||||
}
|
||||
.brand-sub { font-size: 14px; color: rgba(255,255,255,0.85); letter-spacing: 1.5px; }
|
||||
|
||||
/* 卡片 */
|
||||
.form-card {
|
||||
background: rgba(255,255,255,0.96);
|
||||
backdrop-filter: blur(20px);
|
||||
-webkit-backdrop-filter: blur(20px);
|
||||
border-radius: 28px;
|
||||
padding: 44px 40px;
|
||||
box-shadow: 0 25px 80px rgba(0,0,0,.15), 0 0 0 1px rgba(255,255,255,.5) inset;
|
||||
border: none;
|
||||
}
|
||||
|
||||
/* 标题行 */
|
||||
.card-header {
|
||||
display: flex; align-items: center; justify-content: space-between;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
.card-title {
|
||||
font-size: 24px; font-weight: 800;
|
||||
background: linear-gradient(135deg, #1e293b 0%, #475569 100%);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
position: relative;
|
||||
padding-left: 16px;
|
||||
}
|
||||
.card-title::before {
|
||||
content: '';
|
||||
position: absolute; left: 0; top: 2px; bottom: 2px;
|
||||
width: 4px; border-radius: 3px;
|
||||
background: linear-gradient(180deg, #667eea, #764ba2);
|
||||
}
|
||||
.back-link {
|
||||
font-size: 14px; color: #64748b; text-decoration: none;
|
||||
transition: all .2s;
|
||||
font-weight: 500;
|
||||
padding: 6px 12px;
|
||||
border-radius: 8px;
|
||||
}
|
||||
.back-link:hover { color: #667eea; background: rgba(102,126,234,0.08); }
|
||||
.back-link::before { content: '← '; font-size: 14px; }
|
||||
|
||||
/* 分组标题 */
|
||||
.section-label {
|
||||
font-size: 12px; font-weight: 700; color: #94a3b8;
|
||||
text-transform: uppercase; letter-spacing: 2.5px;
|
||||
margin-bottom: 16px; margin-top: 24px;
|
||||
}
|
||||
.section-label:first-of-type { margin-top: 0; }
|
||||
|
||||
/* 表单项 - 单列 */
|
||||
.form-group { margin-bottom: 20px; position: relative; }
|
||||
|
||||
.form-label {
|
||||
display: block; font-size: 14px; font-weight: 600;
|
||||
color: #475569; margin-bottom: 8px;
|
||||
}
|
||||
.form-label .required { color: #ef4444; margin-right: 3px; font-size: 15px; }
|
||||
|
||||
.form-input, .form-select {
|
||||
width: 100%; padding: 14px 18px; font-size: 15px;
|
||||
border: 2px solid #e2e8f0; border-radius: 14px; outline: none;
|
||||
transition: all .3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
background: #f8fafc; color: #1e293b;
|
||||
appearance: none;
|
||||
height: 54px;
|
||||
}
|
||||
.form-input:hover, .form-select:hover {
|
||||
border-color: #cbd5e1;
|
||||
background: #fff;
|
||||
}
|
||||
.form-input:focus, .form-select:focus {
|
||||
border-color: #667eea;
|
||||
background: #fff;
|
||||
box-shadow: 0 0 0 5px rgba(102,126,234,.12);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
.form-input::placeholder { color: #94a3b8; }
|
||||
|
||||
.form-select {
|
||||
cursor: pointer;
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%2394a3b8' stroke-width='2'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
|
||||
background-repeat: no-repeat; background-position: right 18px center; padding-right: 42px;
|
||||
}
|
||||
|
||||
/* 营业执照上传区 */
|
||||
.license-upload-area {
|
||||
border: 2px dashed #cbd5e1;
|
||||
border-radius: 16px; padding: 28px;
|
||||
text-align: center; cursor: pointer;
|
||||
transition: all .3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
background: linear-gradient(135deg, #fafbfc 0%, #f8fafc 100%);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
.license-upload-area:hover {
|
||||
border-color: #667eea;
|
||||
background: linear-gradient(135deg, #eff6ff 0%, #f0f9ff 100%);
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 8px 24px rgba(102,126,234,0.15);
|
||||
}
|
||||
.license-upload-area.has-image {
|
||||
border-style: solid; border-color: #a78bfa; padding: 6px; background: #fff;
|
||||
}
|
||||
.license-upload-area.has-image .upload-placeholder { display: none; }
|
||||
.upload-placeholder .upload-icon-big {
|
||||
font-size: 40px;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
line-height: 1;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.upload-placeholder .upload-hint {
|
||||
font-size: 14px; color: #64748b; font-weight: 600;
|
||||
}
|
||||
.upload-placeholder .upload-desc {
|
||||
font-size: 12px; color: #94a3b8; margin-top: 6px;
|
||||
}
|
||||
.license-preview-img {
|
||||
width: 100%; max-height: 180px; object-fit: cover;
|
||||
border-radius: 12px; display: none;
|
||||
}
|
||||
.has-image .license-preview-img { display: block; }
|
||||
.license-upload-area input[type="file"] { display: none; }
|
||||
|
||||
/* 验证码 */
|
||||
.captcha-group { display: flex; gap: 14px; align-items: stretch; }
|
||||
.captcha-group .form-input { flex: 1; }
|
||||
|
||||
.captcha-img {
|
||||
flex-shrink: 0; width: 130px;
|
||||
height: auto; min-height: 54px;
|
||||
border-radius: 14px; cursor: pointer;
|
||||
border: 2px solid #e2e8f0;
|
||||
background: linear-gradient(135deg, #f0f9ff 0%, #e0f2fe 100%);
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
padding: 0 16px; font-size: 22px; font-weight: 800;
|
||||
letter-spacing: 6px; color: #667eea; user-select: none;
|
||||
transition: all .3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
.captcha-img:hover {
|
||||
border-color: #667eea;
|
||||
background: linear-gradient(135deg, #dbeafe 0%, #cffafe 100%);
|
||||
transform: scale(1.05);
|
||||
box-shadow: 0 6px 20px rgba(102,126,234,0.2);
|
||||
}
|
||||
|
||||
/* 错误提示 */
|
||||
.error-msg {
|
||||
color: #ef4444;
|
||||
font-size: 13px;
|
||||
margin-top: 6px;
|
||||
display: none;
|
||||
padding-left: 4px;
|
||||
animation: shake 0.3s ease-out;
|
||||
}
|
||||
.error-msg.show { display: block; }
|
||||
|
||||
@keyframes shake {
|
||||
0%, 100% { transform: translateX(0); }
|
||||
25% { transform: translateX(-4px); }
|
||||
75% { transform: translateX(4px); }
|
||||
}
|
||||
|
||||
/* 提交按钮 */
|
||||
.submit-btn {
|
||||
width: 100%; padding: 16px; font-size: 16px; font-weight: 700;
|
||||
color: white;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 50%, #f093fb 100%);
|
||||
background-size: 200% 200%;
|
||||
border: none; border-radius: 14px;
|
||||
cursor: pointer;
|
||||
transition: all .3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
box-shadow: 0 10px 30px rgba(102,126,234,.4);
|
||||
letter-spacing: 1.5px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
.submit-btn:hover {
|
||||
background-position: 100% 0;
|
||||
transform: translateY(-3px);
|
||||
box-shadow: 0 16px 40px rgba(102,126,234,.5);
|
||||
}
|
||||
.submit-btn:active { transform: translateY(-1px); }
|
||||
|
||||
/* 底部链接 */
|
||||
.form-footer { text-align: center; margin-top: 22px; font-size: 14px; color: #64748b; }
|
||||
.form-footer a {
|
||||
color: #667eea;
|
||||
text-decoration: none;
|
||||
font-weight: 700;
|
||||
transition: all .2s;
|
||||
}
|
||||
.form-footer a:hover { color: #764ba2; text-decoration: underline; }
|
||||
|
||||
/* 分割线装饰 */
|
||||
.divider {
|
||||
height: 1px;
|
||||
background: linear-gradient(90deg, transparent, #e2e8f0, #cbd5e1, #e2e8f0, transparent);
|
||||
margin: 26px 0;
|
||||
}
|
||||
|
||||
@keyframes cardShake {
|
||||
0%,100%{transform:translateX(0)} 25%{transform:translateX(-8px)} 75%{transform:translateX(8px)}
|
||||
}
|
||||
.shake { animation: cardShake .45s; }
|
||||
|
||||
/* 响应式 */
|
||||
@media (max-width: 580px) {
|
||||
body { padding: 24px 16px; }
|
||||
.form-card { padding: 32px 26px; border-radius: 22px; }
|
||||
.brand-name { font-size: 26px; }
|
||||
.logo-wrap { width: 100px; height: 100px; border-radius: 26px; padding: 16px; }
|
||||
.captcha-group { flex-direction: column; }
|
||||
.captcha-img { width: 100%; min-height: 52px; }
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="container">
|
||||
<!-- 品牌头部 -->
|
||||
<div class="top-bar">
|
||||
<div class="logo-wrap">
|
||||
<img src="logo.png" alt="虫虫出海" class="no-filter">
|
||||
</div>
|
||||
<h1 class="brand-name">虫虫出海</h1>
|
||||
<p class="brand-sub">一站式跨境物流服务平台</p>
|
||||
</div>
|
||||
|
||||
<!-- 注册表单 -->
|
||||
<div class="form-card">
|
||||
<div class="card-header">
|
||||
<h2 class="card-title">企业注册</h2>
|
||||
<a href="login-register.html" class="back-link">返回登录</a>
|
||||
</div>
|
||||
|
||||
<form id="registerForm">
|
||||
|
||||
<!-- 基本信息 -->
|
||||
<div class="section-label">基本信息</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-label"><span class="required">*</span>公司名称</label>
|
||||
<input type="text" class="form-input" id="regCompany" placeholder="请输入完整公司名称" required autocomplete="organization">
|
||||
<div class="error-msg" id="regCompanyError">请输入公司名称</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-label"><span class="required">*</span>法人姓名</label>
|
||||
<input type="text" class="form-input" id="regLegalPerson" placeholder="法人代表姓名" required>
|
||||
<div class="error-msg" id="regLegalPersonError">请输入法人姓名</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-label"><span class="required">*</span>法人电话</label>
|
||||
<input type="tel" class="form-input" id="regLegalPhone" placeholder="用于业务联系的手机号码" required>
|
||||
<div class="error-msg" id="regLegalPhoneError">请输入法人电话</div>
|
||||
</div>
|
||||
|
||||
<div class="divider"></div>
|
||||
|
||||
<!-- 证件信息 -->
|
||||
<div class="section-label">证件信息</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-label"><span class="required">*</span>营业执照 / 证件照</label>
|
||||
<div class="license-upload-area" id="licenseUploadArea" onclick="document.getElementById('regLicenseFile').click()">
|
||||
<div class="upload-placeholder">
|
||||
<div class="upload-icon-big">📄</div>
|
||||
<div class="upload-hint">点击上传证件图片</div>
|
||||
<div class="upload-desc">支持 JPG、PNG 格式,不超过 5MB</div>
|
||||
</div>
|
||||
<img class="license-preview-img" id="licensePreview" alt="">
|
||||
<input type="file" id="regLicenseFile" accept="image/*" onchange="handleLicenseUpload(this)">
|
||||
</div>
|
||||
<div class="error-msg" id="regLicenseError">请上传营业执照或相关证件</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-label">法人身份证号</label>
|
||||
<input type="text" class="form-input" id="regIdCard" placeholder="18位身份证号">
|
||||
</div>
|
||||
|
||||
<div class="divider"></div>
|
||||
|
||||
<!-- 地址与发票 -->
|
||||
<div class="section-label">地址与发票</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-label">国家/地区</label>
|
||||
<select class="form-select" id="regCountry">
|
||||
<option value="中国">中国</option>
|
||||
<option value="中国香港">中国香港</option>
|
||||
<option value="中国台湾">中国台湾</option>
|
||||
<option value="中国澳门">中国澳门</option>
|
||||
<option value="美国">美国</option>
|
||||
<option value="英国">英国</option>
|
||||
<option value="德国">德国</option>
|
||||
<option value="法国">法国</option>
|
||||
<option value="日本">日本</option>
|
||||
<option value="韩国">韩国</option>
|
||||
<option value="澳大利亚">澳大利亚</option>
|
||||
<option value="加拿大">加拿大</option>
|
||||
<option value="其他">其他</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-label">详细地址</label>
|
||||
<input type="text" class="form-input" id="regAddress" placeholder="公司注册地址或经营地址">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-label">发票抬头</label>
|
||||
<input type="text" class="form-input" id="regInvoiceTitle" placeholder="用于开具发票的名称(选填)">
|
||||
</div>
|
||||
|
||||
<div class="divider"></div>
|
||||
|
||||
<!-- 验证码 -->
|
||||
<div class="form-group">
|
||||
<label class="form-label"><span class="required">*</span>验证码</label>
|
||||
<div class="captcha-group">
|
||||
<input type="text" class="form-input" id="regCaptcha" placeholder="输入下方验证码" required maxlength="4">
|
||||
<div class="captcha-img" id="regCaptchaImg" onclick="refreshCaptcha()" title="点击刷新验证码"></div>
|
||||
</div>
|
||||
<div class="error-msg" id="regCaptchaError">验证码错误,请重新输入</div>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="submit-btn">提交注册申请</button>
|
||||
|
||||
<div class="form-footer">
|
||||
已有账号?<a href="login-register.html">立即登录 →</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
let currentCaptcha = '';
|
||||
let licenseUploaded = false;
|
||||
|
||||
function generateCaptcha() {
|
||||
const chars = 'ABCDEFGHJKLMNPQRSTUVWXYZabcdefghjkmnpqrstuvwxyz23456789';
|
||||
let c = '';
|
||||
for (let i = 0; i < 4; i++) c += chars.charAt(Math.floor(Math.random() * chars.length));
|
||||
return c;
|
||||
}
|
||||
|
||||
function refreshCaptcha() {
|
||||
currentCaptcha = generateCaptcha();
|
||||
const img = document.getElementById('regCaptchaImg');
|
||||
img.textContent = currentCaptcha;
|
||||
img.style.transform = 'rotate(' + (Math.random() * 8 - 4) + 'deg)';
|
||||
img.style.color = ['#667eea','#764ba2','#818cf8','#a78bfa'][Math.floor(Math.random()*4)];
|
||||
}
|
||||
|
||||
refreshCaptcha();
|
||||
|
||||
// 营业执照上传
|
||||
function handleLicenseUpload(input) {
|
||||
var file = input.files[0];
|
||||
if (!file) return;
|
||||
if (file.size > 5*1024*1024) { alert('图片大小不能超过 5MB'); input.value=''; return; }
|
||||
var reader = new FileReader();
|
||||
reader.onload = function(e) {
|
||||
var preview = document.getElementById('licensePreview');
|
||||
preview.src = e.target.result;
|
||||
var area = document.getElementById('licenseUploadArea');
|
||||
area.classList.add('has-image');
|
||||
licenseUploaded = true;
|
||||
document.getElementById('regLicenseError').classList.remove('show');
|
||||
};
|
||||
reader.readAsDataURL(file);
|
||||
}
|
||||
|
||||
// 表单提交
|
||||
document.getElementById('registerForm').addEventListener('submit', function(e) {
|
||||
e.preventDefault();
|
||||
var company = document.getElementById('regCompany').value.trim();
|
||||
var legalPerson = document.getElementById('regLegalPerson').value.trim();
|
||||
var legalPhone = document.getElementById('regLegalPhone').value.trim();
|
||||
var captcha = document.getElementById('regCaptcha').value.trim();
|
||||
|
||||
document.querySelectorAll('.error-msg').forEach(function(el){ el.classList.remove('show'); });
|
||||
var hasError = false;
|
||||
|
||||
if (!company) { document.getElementById('regCompanyError').classList.add('show'); hasError=true; }
|
||||
if (!legalPerson) { document.getElementById('regLegalPersonError').classList.add('show'); hasError=true; }
|
||||
if (!legalPhone) { document.getElementById('regLegalPhoneError').classList.add('show'); hasError=true; }
|
||||
if (!licenseUploaded) { document.getElementById('regLicenseError').classList.add('show'); hasError=true; }
|
||||
if (captcha.toUpperCase() !== currentCaptcha.toUpperCase()) {
|
||||
document.getElementById('regCaptchaError').classList.add('show');
|
||||
refreshCaptcha(); hasError=true;
|
||||
}
|
||||
|
||||
if (hasError) {
|
||||
this.querySelector('.submit-btn').classList.add('shake');
|
||||
setTimeout(() => this.querySelector('.submit-btn').classList.remove('shake'), 450);
|
||||
return;
|
||||
}
|
||||
|
||||
alert('注册申请已提交!\n\n公司名称:' + company +
|
||||
'\n\n我们将尽快审核您的资料。');
|
||||
window.location.href = 'login-register.html';
|
||||
});
|
||||
|
||||
// 实时清除错误
|
||||
document.querySelectorAll('.form-input,.form-select').forEach(function(input){
|
||||
input.addEventListener('input', function(){
|
||||
var group = this.closest('.form-group');
|
||||
if (group) { var err = group.querySelector('.error-msg'); if (err) err.classList.remove('show'); }
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
After Width: | Height: | Size: 764 KiB |
@@ -0,0 +1,49 @@
|
||||
const http = require('http');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const PORT = 8081;
|
||||
|
||||
const mimeTypes = {
|
||||
'.html': 'text/html',
|
||||
'.js': 'text/javascript',
|
||||
'.css': 'text/css',
|
||||
'.json': 'application/json',
|
||||
'.png': 'image/png',
|
||||
'.jpg': 'image/jpg',
|
||||
'.gif': 'image/gif',
|
||||
'.svg': 'image/svg+xml',
|
||||
'.ico': 'image/x-icon'
|
||||
};
|
||||
|
||||
const server = http.createServer((req, res) => {
|
||||
console.log(`${req.method} ${req.url}`);
|
||||
|
||||
let filePath = '.' + req.url;
|
||||
if (filePath === './') {
|
||||
filePath = './index.html';
|
||||
}
|
||||
|
||||
const extname = String(path.extname(filePath)).toLowerCase();
|
||||
const contentType = mimeTypes[extname] || 'application/octet-stream';
|
||||
|
||||
fs.readFile(filePath, (error, content) => {
|
||||
if (error) {
|
||||
if (error.code === 'ENOENT') {
|
||||
res.writeHead(404, { 'Content-Type': 'text/html' });
|
||||
res.end('<h1>404 Not Found</h1>', 'utf-8');
|
||||
} else {
|
||||
res.writeHead(500);
|
||||
res.end('Server Error: ' + error.code, 'utf-8');
|
||||
}
|
||||
} else {
|
||||
res.writeHead(200, { 'Content-Type': contentType });
|
||||
res.end(content, 'utf-8');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
server.listen(PORT, () => {
|
||||
console.log(`[TraePreviewUrl]: http://localhost:${PORT}`);
|
||||
console.log(`Server running at http://localhost:${PORT}/`);
|
||||
});
|
||||
@@ -0,0 +1,290 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
柏悦WMS - 分阶段脚本
|
||||
Phase 1: 登录并保存cookies (需要可见浏览器+手动验证码)
|
||||
Phase 2: 加载cookies, headless模式抓取所有页面
|
||||
|
||||
用法:
|
||||
python3 scrape_wms_final.py login # 阶段1: 登录保存cookie
|
||||
python3 scrape_wms_final.py scrape # 阶段2: 用cookie抓取
|
||||
"""
|
||||
import asyncio, json, sys, os, time
|
||||
from playwright.async_api import async_playwright
|
||||
|
||||
BASE = "http://39.101.149.173"
|
||||
API_BASE = "https://adtest.bylogistic.cn"
|
||||
USERNAME = "admin"
|
||||
PASSWORD = "ndui#Emdfj23123"
|
||||
COOKIE_FILE = "/tmp/wms_cookies.json"
|
||||
OUTPUT_DIR = os.path.expanduser("~/Documents/柏悦")
|
||||
os.makedirs(OUTPUT_DIR, exist_ok=True)
|
||||
|
||||
async def phase_login():
|
||||
"""打开浏览器让用户登录,然后保存cookies"""
|
||||
async with async_playwright() as p:
|
||||
browser = await p.chromium.launch(headless=False, args=["--start-maximized"])
|
||||
context = await browser.new_context(viewport={"width": 1440, "height": 900})
|
||||
page = await context.new_page()
|
||||
|
||||
print("=== 打开登录页 ===")
|
||||
await page.goto(f"{BASE}/user/login?redirect=%2Fwms%2FByInstoreList", timeout=30000)
|
||||
await page.wait_for_timeout(2000)
|
||||
|
||||
# 自动填充
|
||||
inputs_text = page.locator("input[type='text']")
|
||||
input_pwd = page.locator("input[type='password']")
|
||||
await inputs_text.nth(0).fill(USERNAME)
|
||||
await input_pwd.fill(PASSWORD)
|
||||
|
||||
print("✅ 账号密码已填写")
|
||||
print("👉 请在浏览器中输入验证码并点击'确定'")
|
||||
print("⏳ 等待登录成功...")
|
||||
|
||||
try:
|
||||
await page.wait_for_function(
|
||||
"() => !window.location.pathname.includes('login')",
|
||||
timeout=300000 # 等5分钟
|
||||
)
|
||||
print(f"✅ 登录成功! URL: {page.url}")
|
||||
except Exception as e:
|
||||
print(f"❌ 等待超时: {e}")
|
||||
try:
|
||||
await browser.close()
|
||||
except:
|
||||
pass
|
||||
return False
|
||||
|
||||
# 立即保存cookies(不等页面加载完)
|
||||
try:
|
||||
await page.wait_for_timeout(3000)
|
||||
except:
|
||||
pass
|
||||
|
||||
try:
|
||||
cookies = await context.cookies()
|
||||
with open(COOKIE_FILE, "w") as f:
|
||||
json.dump(cookies, f, indent=2)
|
||||
print(f"✅ Cookies已保存到 {COOKIE_FILE} ({len(cookies)} 个)")
|
||||
except Exception as ce:
|
||||
print(f"⚠️ Cookie保存出错: {ce}")
|
||||
|
||||
# 截图当前页
|
||||
try:
|
||||
await page.screenshot(path="/tmp/wms_logged_in.png", full_page=True)
|
||||
print("📸 当前页面截图: /tmp/wms_logged_in.png")
|
||||
except Exception as se:
|
||||
print(f"⚠️ 截图出错: {se}")
|
||||
|
||||
# 保持浏览器打开
|
||||
print("\n浏览器将保持10秒后关闭...")
|
||||
try:
|
||||
await asyncio.sleep(10)
|
||||
except:
|
||||
pass
|
||||
|
||||
try:
|
||||
await browser.close()
|
||||
except:
|
||||
pass
|
||||
return True
|
||||
|
||||
async def phase_scrape():
|
||||
"""加载cookies并headless抓取所有页面"""
|
||||
|
||||
# 读取cookies
|
||||
if not os.path.exists(COOKIE_FILE):
|
||||
print(f"❌ Cookie文件不存在: {COOKIE_FILE}")
|
||||
print("请先运行: python3 scrape_wms_final.py login")
|
||||
return
|
||||
|
||||
with open(COOKIE_FILE) as f:
|
||||
saved_cookies = json.load(f)
|
||||
print(f"🍪 加载了 {len(saved_cookies)} 个cookies")
|
||||
|
||||
async with async_playwright() as p:
|
||||
browser = await p.chromium.launch(headless=True)
|
||||
context = await browser.new_context(viewport={"width": 1440, "height": 900})
|
||||
await context.add_cookies(saved_cookies)
|
||||
page = await context.new_page()
|
||||
|
||||
# 监听API
|
||||
all_apis = []
|
||||
page.on("response", lambda r: all_apis.append({
|
||||
"url": r.url, "status": r.status, "method": r.request.method
|
||||
}))
|
||||
|
||||
# 先访问入库单列表(默认首页)
|
||||
print("\n=== 访问系统首页 ===")
|
||||
await page.goto(f"{BASE}/wms/ByInstoreList", timeout=20000)
|
||||
await page.wait_for_timeout(4000)
|
||||
|
||||
if "login" in page.url.lower():
|
||||
print("❌ Cookies已失效,请重新运行 login 命令")
|
||||
await browser.close()
|
||||
return
|
||||
|
||||
print(f"✅ 已进入系统: {page.url}")
|
||||
|
||||
# ===== 抓取菜单结构 =====
|
||||
print("\n=== 抓取菜单结构 ===")
|
||||
|
||||
menu_structure = {}
|
||||
|
||||
# 一级菜单
|
||||
top_menus = page.locator(".ant-menu-submenu-title")
|
||||
top_count = await top_menus.count()
|
||||
|
||||
for i in range(top_count):
|
||||
try:
|
||||
name = (await top_menus.nth(i).inner_text()).strip().split("\n")[0].strip()
|
||||
if not name or len(name) > 20:
|
||||
continue
|
||||
|
||||
# 展开菜单
|
||||
await top_menus.nth(i).click()
|
||||
await page.wait_for_timeout(600)
|
||||
|
||||
# 获取子菜单
|
||||
sub_items = page.locator(".ant-menu-submenu-open .ant-menu-item")
|
||||
subs = []
|
||||
for j in range(await sub_items.count()):
|
||||
try:
|
||||
sn = (await sub_items.nth(j).inner_text()).strip().split("\n")[0]
|
||||
if sn and len(sn) < 30:
|
||||
subs.append(sn)
|
||||
except:
|
||||
pass
|
||||
|
||||
menu_structure[name] = subs
|
||||
print(f" 📂 {name}: {subs}")
|
||||
|
||||
# 收起
|
||||
await top_menus.nth(i).click()
|
||||
await page.wait_for_timeout(300)
|
||||
|
||||
except Exception as e:
|
||||
pass
|
||||
|
||||
# 所有要访问的页面路径
|
||||
pages_to_visit = [
|
||||
("首页", "/wms/Dashboard"),
|
||||
("入库单列表", "/wms/ByInstoreList"),
|
||||
("入库单测量", "/wms/ByInstoreList4Measured"),
|
||||
("测量数据审核", "/wms/ByInstoreList4MeasuredAudit"),
|
||||
("接收审核", "/wms/ByInstoreList4ReceiveAudit"),
|
||||
("客户管理", "/wms/ByCustomerList"),
|
||||
("出库单列表", "/wms/ByOutstoreList"),
|
||||
("派送单列表", "/wms/ByDispatchList"),
|
||||
("货柜管理", "/wms/ByContainerList"),
|
||||
("库存管理", "/wms/ByInventoryList"),
|
||||
("财务结算", "/wms/ByFinanceList"),
|
||||
("托盘管理", "/wms/ByTrayList"),
|
||||
("BOL管理", "/wms/ByBolList"),
|
||||
("用户管理", "/system/UserList"),
|
||||
("角色管理", "/system/RoleList"),
|
||||
("菜单管理", "/system/MenuList"),
|
||||
("字典管理", "/system/DictList"),
|
||||
("参数配置", "/system/ConfigList"),
|
||||
]
|
||||
|
||||
# ===== 逐页抓取 =====
|
||||
print(f"\n=== 逐页抓取 (共{len(pages_to_visit)}页) ===\n")
|
||||
pages_data = {}
|
||||
|
||||
for idx, (name, path) in enumerate(pages_to_visit, 1):
|
||||
try:
|
||||
url = BASE + path
|
||||
print(f"[{idx}/{len(pages_to_visit)}] {name} -> {path}", end=" ... ")
|
||||
|
||||
await page.goto(url, timeout=15000)
|
||||
await page.wait_for_timeout(2500)
|
||||
|
||||
if "login" in page.url.lower():
|
||||
print("❌ 会话过期!")
|
||||
break
|
||||
|
||||
entry = {
|
||||
"title": await page.title(),
|
||||
"url": page.url,
|
||||
}
|
||||
|
||||
# 表格列头
|
||||
headers = []
|
||||
ths = page.locator(".ant-table-thead th, thead th, [class*='table'] th")
|
||||
for i in range(min(await ths.count(), 25)):
|
||||
h = (await ths.nth(i).inner_text()).strip()
|
||||
if h and h not in headers:
|
||||
headers.append(h)
|
||||
|
||||
# 搜索条件字段
|
||||
fields = []
|
||||
labels = page.locator(".ant-form-item-label label, .query-group label, label[for]")
|
||||
for i in range(min(await labels.count(), 20)):
|
||||
t = (await labels.nth(i).inner_text()).strip()
|
||||
if t and t not in fields and len(t) < 30:
|
||||
fields.append(t)
|
||||
|
||||
# 操作按钮
|
||||
buttons = []
|
||||
btns = page.locator(".ant-btn:not(.ant-pagination-item):not(.ant-pagination-options-quick-jumper):not([class*='link'])")
|
||||
for i in range(min(await btns.count(), 15)):
|
||||
b = (await btns.nth(i).inner_text()).strip()
|
||||
if b and b not in buttons and len(b) < 20 and b not in ["刷 新","关 闭"]:
|
||||
buttons.append(b)
|
||||
|
||||
# 统计卡片数字
|
||||
stat_vals = []
|
||||
stats = page.locator("[class*='statistic'] [class*='value'], [class*='number-card'] [class*='value']")
|
||||
for i in range(min(await stats.count(), 10)):
|
||||
s = (await stats.nth(i).inner_text()).strip()
|
||||
if s:
|
||||
stat_vals.append(s)
|
||||
|
||||
entry["table_headers"] = headers
|
||||
entry["search_fields"] = fields
|
||||
entry["buttons"] = buttons
|
||||
entry["statistics"] = stat_vals
|
||||
|
||||
pages_data[name] = entry
|
||||
print(f"✅ 表头:{len(headers)} 字段:{len(fields)} 按钮:{len(buttons)}")
|
||||
|
||||
# 截图每个页面
|
||||
safe_name = name.replace("/", "_").replace("\\", "_")
|
||||
await page.screenshot(path=f"/tmp/wms_page_{safe_name}.png")
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ {e}")
|
||||
pages_data[name] = {"error": str(e)}
|
||||
|
||||
# 保存完整数据
|
||||
full_data = {
|
||||
"system_name": "柏悦物流管理系统 (Baiyue WMS)",
|
||||
"base_url": BASE,
|
||||
"api_base": API_BASE,
|
||||
"scrape_time": time.strftime("%Y-%m-%d %H:%M:%S"),
|
||||
"menu_structure": menu_structure,
|
||||
"pages": pages_data,
|
||||
"api_calls": all_apis[-50:], # 最后50个API调用
|
||||
}
|
||||
|
||||
output_file = os.path.join(OUTPUT_DIR, "wms_system_data.json")
|
||||
with open(output_file, "w", encoding="utf-8") as f:
|
||||
json.dump(full_data, f, indent=2, ensure_ascii=False)
|
||||
|
||||
print(f"\n{'='*60}")
|
||||
print(f"✅ 全部完成!")
|
||||
print(f" - 菜单: {len(menu_structure)} 个一级模块")
|
||||
print(f" - 页面: {len(pages_data)} 个页面")
|
||||
print(f" - 输出: {output_file}")
|
||||
print(f"{'='*60}")
|
||||
|
||||
await browser.close()
|
||||
|
||||
if __name__ == "__main__":
|
||||
cmd = sys.argv[1] if len(sys.argv) > 1 else "login"
|
||||
if cmd == "login":
|
||||
asyncio.run(phase_login())
|
||||
elif cmd == "scrape":
|
||||
asyncio.run(phase_scrape())
|
||||
else:
|
||||
print(f"Usage: python3 {sys.argv[0]} [login|scrape]")
|
||||
@@ -0,0 +1,207 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
从可见浏览器中提取token,然后用API方式抓取所有数据
|
||||
"""
|
||||
import asyncio, json, os, time
|
||||
from playwright.async_api import async_playwright
|
||||
|
||||
BASE = "http://39.101.149.173"
|
||||
USERNAME = "admin"
|
||||
PASSWORD = "ndui#Emdfj23123"
|
||||
TOKEN_FILE = "/tmp/wms_token.json"
|
||||
OUTPUT_DIR = os.path.expanduser("~/Documents/柏悦")
|
||||
|
||||
async def main():
|
||||
async with async_playwright() as p:
|
||||
browser = await p.chromium.launch(headless=False, args=["--start-maximized"])
|
||||
context = await browser.new_context(viewport={"width": 1440, "height": 900})
|
||||
page = await context.new_page()
|
||||
|
||||
print("=== 打开登录页 ===")
|
||||
await page.goto(f"{BASE}/user/login?redirect=%2Fwms%2FByInstoreList", timeout=30000)
|
||||
await page.wait_for_timeout(2000)
|
||||
|
||||
# 填充
|
||||
inputs = page.locator("input[type='text']")
|
||||
pwd = page.locator("input[type='password']")
|
||||
await inputs.nth(0).fill(USERNAME)
|
||||
await pwd.fill(PASSWORD)
|
||||
|
||||
print("👉 请在浏览器中输入验证码并点击确定...")
|
||||
|
||||
try:
|
||||
await page.wait_for_function(
|
||||
"() => !window.location.pathname.includes('login')",
|
||||
timeout=300000
|
||||
)
|
||||
print("✅ 登录成功!")
|
||||
except:
|
||||
print("❌ 超时")
|
||||
await browser.close()
|
||||
return
|
||||
|
||||
await page.wait_for_timeout(3000)
|
||||
|
||||
# ========== 抓取完整菜单结构 ==========
|
||||
print("\n=== 抓取菜单 ===")
|
||||
menu_structure = {}
|
||||
page_list = [] # [(display_name, url_path)]
|
||||
|
||||
top_menus = page.locator(".ant-menu-submenu-title")
|
||||
for i in range(await top_menus.count()):
|
||||
try:
|
||||
name = (await top_menus.nth(i).inner_text()).strip().split("\n")[0].strip()
|
||||
if not name or len(name) > 20:
|
||||
continue
|
||||
|
||||
await top_menus.nth(i).click()
|
||||
await page.wait_for_timeout(500)
|
||||
|
||||
subs = []
|
||||
sub_items = page.locator(".ant-menu-submenu-open .ant-menu-item")
|
||||
for j in range(await sub_items.count()):
|
||||
sn = (await sub_items.nth(j).inner_text()).strip().split("\n")[0]
|
||||
if sn and len(sn) < 30:
|
||||
subs.append(sn)
|
||||
|
||||
menu_structure[name] = subs
|
||||
print(f" {name}: {subs}")
|
||||
|
||||
await top_menus.nth(i).click()
|
||||
await page.wait_for_timeout(300)
|
||||
except:
|
||||
pass
|
||||
|
||||
# ========== 逐页截图抓取 ==========
|
||||
print(f"\n=== 逐页抓取 ===")
|
||||
|
||||
# 构建所有要访问的页面
|
||||
all_pages = [("首页", "/wms/Dashboard")]
|
||||
|
||||
for menu_name, subs in menu_structure.items():
|
||||
for sub in subs:
|
||||
# 推断URL路径
|
||||
path_map = {
|
||||
"入库单列表": "/wms/ByInstoreList",
|
||||
"入库单测量": "/wms/ByInstoreList4Measured",
|
||||
"测量数据审核": "/wms/ByInstoreList4MeasuredAudit",
|
||||
"接收审核": "/wms/ByInstoreList4ReceiveAudit",
|
||||
"客户管理": "/wms/ByCustomerList",
|
||||
"出库单列表": "/wms/ByOutstoreList",
|
||||
"派送单列表": "/wms/ByDispatchList",
|
||||
"BOL管理": "/wms/ByBolList",
|
||||
"货柜管理": "/wms/ByContainerList",
|
||||
"库存管理": "/wms/ByInventoryList",
|
||||
"财务结算": "/wms/ByFinanceList",
|
||||
"托盘管理": "/wms/ByTrayList",
|
||||
"用户管理": "/system/UserList",
|
||||
"角色管理": "/system/RoleList",
|
||||
"菜单管理": "/system/MenuList",
|
||||
"字典管理": "/system/DictList",
|
||||
"参数配置": "/system/ConfigList",
|
||||
"通用配置": "/system/ConfigList",
|
||||
"报表设计": "/wms/Dashboard", # 待确认
|
||||
"消息中心": "/wms/Dashboard",
|
||||
"常见案例": "/wms/Dashboard",
|
||||
"在线开发": "/wms/Dashboard",
|
||||
"系统监控": "/wms/Dashboard",
|
||||
"统计报表": "/wms/Dashboard",
|
||||
}
|
||||
path = path_map.get(sub, "")
|
||||
if path:
|
||||
all_pages.append((f"{menu_name} > {sub}", path))
|
||||
|
||||
# 去重
|
||||
seen = set()
|
||||
unique_pages = []
|
||||
for name, path in all_pages:
|
||||
if path not in seen:
|
||||
seen.add(path)
|
||||
unique_pages.append((name, path))
|
||||
|
||||
pages_data = {}
|
||||
success_count = 0
|
||||
|
||||
for idx, (name, path) in enumerate(unique_pages, 1):
|
||||
try:
|
||||
url = BASE + path
|
||||
print(f"[{idx}/{len(unique_pages)}] {name}", end=" ... ")
|
||||
|
||||
await page.goto(url, timeout=15000)
|
||||
await page.wait_for_timeout(2500)
|
||||
|
||||
if "login" in page.url.lower():
|
||||
print("会话过期!")
|
||||
break
|
||||
|
||||
# 抓表格列头
|
||||
headers = []
|
||||
th_selectors = [".ant-table-thead th", "thead th", "table th"]
|
||||
for ths in th_selectors:
|
||||
els = page.locator(ths)
|
||||
for i in range(min(await els.count(), 30)):
|
||||
try:
|
||||
h = (await els.nth(i).inner_text()).strip()
|
||||
if h and h not in headers:
|
||||
headers.append(h)
|
||||
except:
|
||||
pass
|
||||
|
||||
# 搜索字段
|
||||
fields = []
|
||||
labels = page.locator("label, .ant-form-item-label")
|
||||
for i in range(min(await labels.count(), 25)):
|
||||
try:
|
||||
t = (await labels.nth(i).inner_text()).strip()
|
||||
if t and t not in fields and len(t) < 30:
|
||||
fields.append(t)
|
||||
except:
|
||||
pass
|
||||
|
||||
# 操作按钮
|
||||
buttons = []
|
||||
btns = page.locator("button:not([class*='pagination']):not([class*='quick-jumper'])")
|
||||
for i in range(min(await btns.count(), 20)):
|
||||
try:
|
||||
b = (await btns.nth(i).inner_text()).strip()
|
||||
if b and b not in buttons and len(b) < 25:
|
||||
buttons.append(b)
|
||||
except:
|
||||
pass
|
||||
|
||||
pages_data[name] = {
|
||||
"url": url,
|
||||
"title": await page.title(),
|
||||
"table_headers": headers,
|
||||
"search_fields": fields,
|
||||
"buttons": buttons,
|
||||
}
|
||||
|
||||
print(f"✅ headers:{len(headers)} fields:{len(fields)} btns:{len(buttons)}")
|
||||
success_count += 1
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ {str(e)[:80]}")
|
||||
pages_data[name] = {"error": str(e)[:200]}
|
||||
|
||||
# 保存数据
|
||||
output = {
|
||||
"system_name": "柏悦物流管理系统 (Baiyue WMS)",
|
||||
"scrape_time": time.strftime("%Y-%m-%d %H:%M:%S"),
|
||||
"menu_structure": menu_structure,
|
||||
"pages": pages_data,
|
||||
"pages_count": success_count,
|
||||
}
|
||||
|
||||
out_path = os.path.join(OUTPUT_DIR, "wms_full_data.json")
|
||||
with open(out_path, "w", encoding="utf-8") as f:
|
||||
json.dump(output, f, indent=2, ensure_ascii=False)
|
||||
|
||||
print(f"\n✅ 完成! {success_count}/{len(unique_pages)} 页面成功抓取")
|
||||
print(f"输出: {out_path}")
|
||||
|
||||
print("\n浏览器10秒后关闭...")
|
||||
await asyncio.sleep(10)
|
||||
await browser.close()
|
||||
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,322 @@
|
||||
{
|
||||
"system_name": "柏悦物流管理系统 (Baiyue WMS)",
|
||||
"scrape_time": "2026-06-01 12:06:00",
|
||||
"menu_structure": {
|
||||
"客户管理": [
|
||||
"客户公司管理",
|
||||
"用户资料",
|
||||
"海外仓阶梯费用",
|
||||
"客户账户流水"
|
||||
],
|
||||
"入库": [
|
||||
"入库单列表",
|
||||
"入库单测量",
|
||||
"测量数据审核",
|
||||
"接收审核"
|
||||
],
|
||||
"出库": [
|
||||
"派送单列表",
|
||||
"BOL",
|
||||
"自提单"
|
||||
],
|
||||
"货柜管理": [
|
||||
"货柜列表",
|
||||
"装柜清单"
|
||||
],
|
||||
"库存": [
|
||||
"海外仓库存查询",
|
||||
"理货管理",
|
||||
"报损单"
|
||||
],
|
||||
"财务结算": [
|
||||
"客户应收应付",
|
||||
"客户对账单",
|
||||
"结算单位应付",
|
||||
"结算单位对账单",
|
||||
"洛杉矶仓储成本"
|
||||
],
|
||||
"托盘管理": [
|
||||
"托盘列表",
|
||||
"生成托盘"
|
||||
],
|
||||
"通用": [
|
||||
"产品信息",
|
||||
"费用项目",
|
||||
"FBA编码地址",
|
||||
"托盘管理",
|
||||
"库位/货架管理",
|
||||
"订单流转路径",
|
||||
"快递公司",
|
||||
"往来单位"
|
||||
],
|
||||
"常见案例": [
|
||||
"自定义组件",
|
||||
"对象存储"
|
||||
],
|
||||
"在线开发": [
|
||||
"Online表单开发"
|
||||
],
|
||||
"报表设计": [
|
||||
"积木报表设计",
|
||||
"生产销售监控",
|
||||
"智慧物流监控"
|
||||
],
|
||||
"消息中心": [
|
||||
"模板管理",
|
||||
"消息管理",
|
||||
"我的消息"
|
||||
],
|
||||
"系统管理": [
|
||||
"用户管理",
|
||||
"角色管理",
|
||||
"菜单管理",
|
||||
"租户管理",
|
||||
"部门管理",
|
||||
"我的部门",
|
||||
"职务管理",
|
||||
"通讯录",
|
||||
"数据字典",
|
||||
"分类字典",
|
||||
"系统通告",
|
||||
"菜单管理2"
|
||||
],
|
||||
"系统监控": [
|
||||
"在线用户",
|
||||
"路由网关",
|
||||
"定时任务",
|
||||
"日志管理",
|
||||
"数据日志",
|
||||
"SQL监控",
|
||||
"在线文档"
|
||||
]
|
||||
},
|
||||
"pages": {
|
||||
"首页": {
|
||||
"url": "http://39.101.149.173/wms/Dashboard",
|
||||
"title": "柏悦物流管理系统",
|
||||
"table_headers": [],
|
||||
"search_fields": [],
|
||||
"buttons": [
|
||||
"返回首页"
|
||||
]
|
||||
},
|
||||
"入库 > 入库单列表": {
|
||||
"url": "http://39.101.149.173/wms/ByInstoreList",
|
||||
"title": "入库单列表 · 柏悦物流管理系统",
|
||||
"table_headers": [
|
||||
"仓库",
|
||||
"交货仓",
|
||||
"配载状态",
|
||||
"是否扣货",
|
||||
"扣货理由",
|
||||
"集装箱号",
|
||||
"柜号",
|
||||
"公司",
|
||||
"业务类型",
|
||||
"提货方式",
|
||||
"提货时间",
|
||||
"提货联系人电话",
|
||||
"提货地址",
|
||||
"提货邮编",
|
||||
"提货联系人邮箱",
|
||||
"渠道",
|
||||
"买单/退税",
|
||||
"是否整柜",
|
||||
"商检验",
|
||||
"开船时间",
|
||||
"到港时间",
|
||||
"总箱数",
|
||||
"总毛重(T.K.GW)"
|
||||
],
|
||||
"search_fields": [
|
||||
"定位仓库",
|
||||
"交货仓",
|
||||
"入仓码",
|
||||
"订单状态",
|
||||
"费用审核状态"
|
||||
],
|
||||
"buttons": [
|
||||
"查询",
|
||||
"重置",
|
||||
"国内仓下单",
|
||||
"海外分仓下单",
|
||||
"整托下单",
|
||||
"高级查询",
|
||||
"导出报表",
|
||||
"导出入库清单总表",
|
||||
"导出唛头",
|
||||
"导出FBA流转单ZIP",
|
||||
"下载"
|
||||
]
|
||||
},
|
||||
"入库 > 入库单测量": {
|
||||
"url": "http://39.101.149.173/wms/ByInstoreList4Measured",
|
||||
"title": "入库单测量 · 柏悦物流管理系统",
|
||||
"table_headers": [
|
||||
"入仓码",
|
||||
"仓库",
|
||||
"订单状态",
|
||||
"配载状态",
|
||||
"测量数据审核状态",
|
||||
"唛头文件",
|
||||
"是否扣货",
|
||||
"扣货理由",
|
||||
"公司",
|
||||
"业务类型",
|
||||
"渠道",
|
||||
"买单/退税",
|
||||
"是否整柜",
|
||||
"商检验",
|
||||
"总箱数",
|
||||
"总毛重(T.K.GW)",
|
||||
"总体积(m³)",
|
||||
"总材积重",
|
||||
"总净重(T.K.NW)",
|
||||
"目的仓类型",
|
||||
"目的仓",
|
||||
"货件编号",
|
||||
"测量完成时间",
|
||||
"操作"
|
||||
],
|
||||
"search_fields": [
|
||||
"仓库",
|
||||
"入仓码",
|
||||
"公司",
|
||||
"FBA货件编号"
|
||||
],
|
||||
"buttons": [
|
||||
"查询",
|
||||
"重置",
|
||||
"下载"
|
||||
]
|
||||
},
|
||||
"入库 > 测量数据审核": {
|
||||
"url": "http://39.101.149.173/wms/ByInstoreList4MeasuredAudit",
|
||||
"title": "测量数据审核 · 柏悦物流管理系统",
|
||||
"table_headers": [
|
||||
"入仓码",
|
||||
"仓库",
|
||||
"订单状态",
|
||||
"配载状态",
|
||||
"测量数据审核状态",
|
||||
"唛头文件",
|
||||
"是否扣货",
|
||||
"扣货理由",
|
||||
"公司",
|
||||
"业务类型",
|
||||
"渠道",
|
||||
"买单/退税",
|
||||
"是否整柜",
|
||||
"商检验",
|
||||
"总箱数",
|
||||
"总毛重(T.K.GW)",
|
||||
"总体积(m³)",
|
||||
"总材积重",
|
||||
"总净重(T.K.NW)",
|
||||
"目的仓类型",
|
||||
"目的仓",
|
||||
"货件编号",
|
||||
"测量完成时间",
|
||||
"操作"
|
||||
],
|
||||
"search_fields": [
|
||||
"仓库",
|
||||
"入仓码",
|
||||
"公司",
|
||||
"FBA货件编号"
|
||||
],
|
||||
"buttons": [
|
||||
"查询",
|
||||
"重置",
|
||||
"下载"
|
||||
]
|
||||
},
|
||||
"入库 > 接收审核": {
|
||||
"url": "http://39.101.149.173/wms/ByInstoreList4ReceiveAudit",
|
||||
"title": "接收审核 · 柏悦物流管理系统",
|
||||
"table_headers": [
|
||||
"入仓码",
|
||||
"仓库",
|
||||
"订单状态",
|
||||
"配载状态",
|
||||
"测量数据审核状态",
|
||||
"唛头文件",
|
||||
"是否扣货",
|
||||
"扣货理由",
|
||||
"公司",
|
||||
"业务类型",
|
||||
"渠道",
|
||||
"买单/退税",
|
||||
"是否整柜",
|
||||
"商检验",
|
||||
"总箱数",
|
||||
"总毛重(T.K.GW)",
|
||||
"总体积(m³)",
|
||||
"总材积重",
|
||||
"总净重(T.K.NW)",
|
||||
"目的仓类型",
|
||||
"目的仓",
|
||||
"货件编号",
|
||||
"测量完成时间",
|
||||
"操作"
|
||||
],
|
||||
"search_fields": [
|
||||
"仓库",
|
||||
"入仓码",
|
||||
"公司",
|
||||
"FBA货件编号"
|
||||
],
|
||||
"buttons": [
|
||||
"查询",
|
||||
"重置",
|
||||
"下载"
|
||||
]
|
||||
},
|
||||
"出库 > 派送单列表": {
|
||||
"url": "http://39.101.149.173/wms/ByDispatchList",
|
||||
"title": "柏悦物流管理系统",
|
||||
"table_headers": [],
|
||||
"search_fields": [],
|
||||
"buttons": [
|
||||
"返回首页"
|
||||
]
|
||||
},
|
||||
"通用 > 托盘管理": {
|
||||
"url": "http://39.101.149.173/wms/ByTrayList",
|
||||
"title": "柏悦物流管理系统",
|
||||
"table_headers": [],
|
||||
"search_fields": [],
|
||||
"buttons": [
|
||||
"返回首页"
|
||||
]
|
||||
},
|
||||
"系统管理 > 用户管理": {
|
||||
"url": "http://39.101.149.173/system/UserList",
|
||||
"title": "柏悦物流管理系统",
|
||||
"table_headers": [],
|
||||
"search_fields": [],
|
||||
"buttons": [
|
||||
"返回首页"
|
||||
]
|
||||
},
|
||||
"系统管理 > 角色管理": {
|
||||
"url": "http://39.101.149.173/system/RoleList",
|
||||
"title": "柏悦物流管理系统",
|
||||
"table_headers": [],
|
||||
"search_fields": [],
|
||||
"buttons": [
|
||||
"返回首页"
|
||||
]
|
||||
},
|
||||
"系统管理 > 菜单管理": {
|
||||
"url": "http://39.101.149.173/system/MenuList",
|
||||
"title": "柏悦物流管理系统",
|
||||
"table_headers": [],
|
||||
"search_fields": [],
|
||||
"buttons": [
|
||||
"返回首页"
|
||||
]
|
||||
}
|
||||
},
|
||||
"pages_count": 10
|
||||
}
|
||||
@@ -0,0 +1,393 @@
|
||||
{
|
||||
"menu_items": [
|
||||
{
|
||||
"text": "首页",
|
||||
"selector": ".ant-menu-item",
|
||||
"href": ""
|
||||
},
|
||||
{
|
||||
"text": "入库单列表",
|
||||
"selector": ".ant-menu-item",
|
||||
"href": ""
|
||||
},
|
||||
{
|
||||
"text": "入库单测量",
|
||||
"selector": ".ant-menu-item",
|
||||
"href": ""
|
||||
},
|
||||
{
|
||||
"text": "测量数据审核",
|
||||
"selector": ".ant-menu-item",
|
||||
"href": ""
|
||||
},
|
||||
{
|
||||
"text": "接收审核",
|
||||
"selector": ".ant-menu-item",
|
||||
"href": ""
|
||||
},
|
||||
{
|
||||
"text": "刷 新",
|
||||
"selector": ".ant-menu-item",
|
||||
"href": ""
|
||||
},
|
||||
{
|
||||
"text": "关闭左侧",
|
||||
"selector": ".ant-menu-item",
|
||||
"href": ""
|
||||
},
|
||||
{
|
||||
"text": "关闭右侧",
|
||||
"selector": ".ant-menu-item",
|
||||
"href": ""
|
||||
},
|
||||
{
|
||||
"text": "关闭其它",
|
||||
"selector": ".ant-menu-item",
|
||||
"href": ""
|
||||
},
|
||||
{
|
||||
"text": "客户管理",
|
||||
"selector": ".ant-menu-submenu-title",
|
||||
"href": ""
|
||||
},
|
||||
{
|
||||
"text": "入库",
|
||||
"selector": ".ant-menu-submenu-title",
|
||||
"href": ""
|
||||
},
|
||||
{
|
||||
"text": "出库",
|
||||
"selector": ".ant-menu-submenu-title",
|
||||
"href": ""
|
||||
},
|
||||
{
|
||||
"text": "货柜管理",
|
||||
"selector": ".ant-menu-submenu-title",
|
||||
"href": ""
|
||||
},
|
||||
{
|
||||
"text": "库存",
|
||||
"selector": ".ant-menu-submenu-title",
|
||||
"href": ""
|
||||
},
|
||||
{
|
||||
"text": "财务结算",
|
||||
"selector": ".ant-menu-submenu-title",
|
||||
"href": ""
|
||||
},
|
||||
{
|
||||
"text": "托盘管理",
|
||||
"selector": ".ant-menu-submenu-title",
|
||||
"href": ""
|
||||
},
|
||||
{
|
||||
"text": "通用",
|
||||
"selector": ".ant-menu-submenu-title",
|
||||
"href": ""
|
||||
},
|
||||
{
|
||||
"text": "常见案例",
|
||||
"selector": ".ant-menu-submenu-title",
|
||||
"href": ""
|
||||
},
|
||||
{
|
||||
"text": "在线开发",
|
||||
"selector": ".ant-menu-submenu-title",
|
||||
"href": ""
|
||||
},
|
||||
{
|
||||
"text": "报表设计",
|
||||
"selector": ".ant-menu-submenu-title",
|
||||
"href": ""
|
||||
},
|
||||
{
|
||||
"text": "消息中心",
|
||||
"selector": ".ant-menu-submenu-title",
|
||||
"href": ""
|
||||
},
|
||||
{
|
||||
"text": "系统管理",
|
||||
"selector": ".ant-menu-submenu-title",
|
||||
"href": ""
|
||||
},
|
||||
{
|
||||
"text": "系统监控",
|
||||
"selector": ".ant-menu-submenu-title",
|
||||
"href": ""
|
||||
},
|
||||
{
|
||||
"text": "统计报表",
|
||||
"selector": ".ant-menu-submenu-title",
|
||||
"href": ""
|
||||
},
|
||||
{
|
||||
"text": "入库 入库单列表 入库单测量 测量数据审核 接收审核",
|
||||
"selector": "li[role='menuitem']",
|
||||
"href": ""
|
||||
},
|
||||
{
|
||||
"text": "定位仓库 请选择仓库",
|
||||
"selector": "[class*='menu'] [class*='item']",
|
||||
"href": ""
|
||||
},
|
||||
{
|
||||
"text": "定位仓库",
|
||||
"selector": "[class*='menu'] [class*='item']",
|
||||
"href": ""
|
||||
},
|
||||
{
|
||||
"text": "请选择仓库",
|
||||
"selector": "[class*='menu'] [class*='item']",
|
||||
"href": ""
|
||||
},
|
||||
{
|
||||
"text": "交货仓 请选择交货仓",
|
||||
"selector": "[class*='menu'] [class*='item']",
|
||||
"href": ""
|
||||
},
|
||||
{
|
||||
"text": "交货仓",
|
||||
"selector": "[class*='menu'] [class*='item']",
|
||||
"href": ""
|
||||
},
|
||||
{
|
||||
"text": "请选择交货仓",
|
||||
"selector": "[class*='menu'] [class*='item']",
|
||||
"href": ""
|
||||
},
|
||||
{
|
||||
"text": "入仓码",
|
||||
"selector": "[class*='menu'] [class*='item']",
|
||||
"href": ""
|
||||
},
|
||||
{
|
||||
"text": "订单状态 请选择订单状态",
|
||||
"selector": "[class*='menu'] [class*='item']",
|
||||
"href": ""
|
||||
},
|
||||
{
|
||||
"text": "订单状态",
|
||||
"selector": "[class*='menu'] [class*='item']",
|
||||
"href": ""
|
||||
},
|
||||
{
|
||||
"text": "请选择订单状态",
|
||||
"selector": "[class*='menu'] [class*='item']",
|
||||
"href": ""
|
||||
},
|
||||
{
|
||||
"text": "费用审核状态 请选择费用审核状态",
|
||||
"selector": "[class*='menu'] [class*='item']",
|
||||
"href": ""
|
||||
},
|
||||
{
|
||||
"text": "费用审核状态",
|
||||
"selector": "[class*='menu'] [class*='item']",
|
||||
"href": ""
|
||||
},
|
||||
{
|
||||
"text": "请选择费用审核状态",
|
||||
"selector": "[class*='menu'] [class*='item']",
|
||||
"href": ""
|
||||
},
|
||||
{
|
||||
"text": "1",
|
||||
"selector": "[class*='menu'] [class*='item']",
|
||||
"href": ""
|
||||
},
|
||||
{
|
||||
"text": "2",
|
||||
"selector": "[class*='menu'] [class*='item']",
|
||||
"href": ""
|
||||
},
|
||||
{
|
||||
"text": "3",
|
||||
"selector": "[class*='menu'] [class*='item']",
|
||||
"href": ""
|
||||
},
|
||||
{
|
||||
"text": "4",
|
||||
"selector": "[class*='menu'] [class*='item']",
|
||||
"href": ""
|
||||
},
|
||||
{
|
||||
"text": "5",
|
||||
"selector": "[class*='menu'] [class*='item']",
|
||||
"href": ""
|
||||
},
|
||||
{
|
||||
"text": "•••",
|
||||
"selector": "[class*='menu'] [class*='item']",
|
||||
"href": ""
|
||||
},
|
||||
{
|
||||
"text": "36",
|
||||
"selector": "[class*='menu'] [class*='item']",
|
||||
"href": ""
|
||||
}
|
||||
],
|
||||
"all_links": [
|
||||
"/system/ConfigList",
|
||||
"/system/DictList",
|
||||
"/system/MenuList",
|
||||
"/system/RoleList",
|
||||
"/system/UserList",
|
||||
"/wms/ByBolList",
|
||||
"/wms/ByContainerList",
|
||||
"/wms/ByCustomerList",
|
||||
"/wms/ByDispatchList",
|
||||
"/wms/ByFinanceList",
|
||||
"/wms/ByInstoreList",
|
||||
"/wms/ByInstoreList4Measured",
|
||||
"/wms/ByInstoreList4MeasuredAudit",
|
||||
"/wms/ByInstoreList4ReceiveAudit",
|
||||
"/wms/ByInventoryList",
|
||||
"/wms/ByOutstoreList",
|
||||
"/wms/ByTrayList",
|
||||
"/wms/Dashboard",
|
||||
"/wms/home",
|
||||
"/wms/index"
|
||||
],
|
||||
"api_calls": [
|
||||
{
|
||||
"url": "http://39.101.149.173/user/login?redirect=%2Fwms%2FByInstoreList",
|
||||
"status": 200,
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"url": "https://adtest.bylogistic.cn/sys/randomImage/1780285671792?_t=1780285671",
|
||||
"status": 200,
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"url": "https://adtest.bylogistic.cn/sys/randomImage/1780285691766?_t=1780285691",
|
||||
"status": 200,
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"url": "https://adtest.bylogistic.cn/sys/randomImage/1780285694400?_t=1780285694",
|
||||
"status": 200,
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"url": "https://adtest.bylogistic.cn/sys/login",
|
||||
"status": 200,
|
||||
"method": "POST"
|
||||
},
|
||||
{
|
||||
"url": "https://adtest.bylogistic.cn/sys/randomImage/1780285703728?_t=1780285703",
|
||||
"status": 200,
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"url": "https://adtest.bylogistic.cn/sys/login",
|
||||
"status": 200,
|
||||
"method": "POST"
|
||||
},
|
||||
{
|
||||
"url": "https://adtest.bylogistic.cn/sys/randomImage/1780285711155?_t=1780285711",
|
||||
"status": 200,
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"url": "https://adtest.bylogistic.cn/sys/login",
|
||||
"status": 200,
|
||||
"method": "POST"
|
||||
},
|
||||
{
|
||||
"url": "http://39.101.149.173/user/login?redirect=%2Fwms%2FByInstoreList",
|
||||
"status": 200,
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"url": "https://adtest.bylogistic.cn/sys/randomImage/1780285725968?_t=1780285725",
|
||||
"status": 200,
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"url": "https://adtest.bylogistic.cn/sys/randomImage/1780285750913?_t=1780285750",
|
||||
"status": 200,
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"url": "https://adtest.bylogistic.cn/sys/login",
|
||||
"status": 200,
|
||||
"method": "POST"
|
||||
},
|
||||
{
|
||||
"url": "https://adtest.bylogistic.cn/sys/permission/getUserPermissionByToken?_t=1780285758",
|
||||
"status": 200,
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"url": "https://adtest.bylogistic.cn/sys/dict/getDictItems/by_company,company_name,id",
|
||||
"status": 200,
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"url": "https://adtest.bylogistic.cn/sys/dict/getDictItems/by_order_status,name,value,value%20not%20in%20(1001%5E%5E1002)",
|
||||
"status": 200,
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"url": "https://adtest.bylogistic.cn/sys/dict/getDictItems/by_customer,realname,id",
|
||||
"status": 200,
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"url": "https://adtest.bylogistic.cn/sys/dict/getDictItems/by_store,store_name,store_no",
|
||||
"status": 200,
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"url": "https://adtest.bylogistic.cn/sys/dict/getDictItems/by_order_status,name,value",
|
||||
"status": 200,
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"url": "https://adtest.bylogistic.cn/sys/dict/getDictItems/by_store,store_name,store_no,parent_store_id!=''",
|
||||
"status": 200,
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"url": "https://adtest.bylogistic.cn/sys/dict/getDictItems/by_order_path,path_name,id",
|
||||
"status": 200,
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"url": "https://adtest.bylogistic.cn/sys/dict/getDictItems/by_fba,fba_no,fba_no",
|
||||
"status": 200,
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"url": "https://adtest.bylogistic.cn/sys/annountCement/listByUser?_t=1780285758",
|
||||
"status": 200,
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"url": "https://adtest.bylogistic.cn/sys/permission/getUserPermissionByToken?_t=1780285762",
|
||||
"status": 200,
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"url": "https://adtest.bylogistic.cn/sys/loginfo?_t=1780285763",
|
||||
"status": 200,
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"url": "https://adtest.bylogistic.cn/sys/visitInfo?_t=1780285763",
|
||||
"status": 200,
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"url": "https://adtest.bylogistic.cn/sys/annountCement/listByUser?_t=1780285763",
|
||||
"status": 200,
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"url": "https://adtest.bylogistic.cn/sys/permission/getUserPermissionByToken?_t=1780285764",
|
||||
"status": 200,
|
||||
"method": "GET"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
{
|
||||
"/system/ConfigList": {
|
||||
"title": "柏悦物流管理系统",
|
||||
"url": "http://39.101.149.173/dashboard/analysis",
|
||||
"headers": [],
|
||||
"buttons": [],
|
||||
"form_fields": [],
|
||||
"content_preview": "欢迎进入 柏悦物流管理系统\n欢迎您,管理员 退出登录\n首页\nCopyright 2022 BaiYue Logisitcs"
|
||||
},
|
||||
"/system/DictList": {
|
||||
"error": "Page.wait_for_timeout: Target page, context or browser has been closed"
|
||||
},
|
||||
"/system/MenuList": {
|
||||
"error": "Page.goto: Target page, context or browser has been closed"
|
||||
},
|
||||
"/system/RoleList": {
|
||||
"error": "Page.goto: Target page, context or browser has been closed"
|
||||
},
|
||||
"/system/UserList": {
|
||||
"error": "Page.goto: Target page, context or browser has been closed"
|
||||
},
|
||||
"/wms/ByBolList": {
|
||||
"error": "Page.goto: Target page, context or browser has been closed"
|
||||
},
|
||||
"/wms/ByContainerList": {
|
||||
"error": "Page.goto: Target page, context or browser has been closed"
|
||||
},
|
||||
"/wms/ByCustomerList": {
|
||||
"error": "Page.goto: Target page, context or browser has been closed"
|
||||
},
|
||||
"/wms/ByDispatchList": {
|
||||
"error": "Page.goto: Target page, context or browser has been closed"
|
||||
},
|
||||
"/wms/ByFinanceList": {
|
||||
"error": "Page.goto: Target page, context or browser has been closed"
|
||||
},
|
||||
"/wms/ByInstoreList": {
|
||||
"error": "Page.goto: Target page, context or browser has been closed"
|
||||
},
|
||||
"/wms/ByInstoreList4Measured": {
|
||||
"error": "Page.goto: Target page, context or browser has been closed"
|
||||
},
|
||||
"/wms/ByInstoreList4MeasuredAudit": {
|
||||
"error": "Page.goto: Target page, context or browser has been closed"
|
||||
},
|
||||
"/wms/ByInstoreList4ReceiveAudit": {
|
||||
"error": "Page.goto: Target page, context or browser has been closed"
|
||||
},
|
||||
"/wms/ByInventoryList": {
|
||||
"error": "Page.goto: Target page, context or browser has been closed"
|
||||
},
|
||||
"/wms/ByOutstoreList": {
|
||||
"error": "Page.goto: Target page, context or browser has been closed"
|
||||
},
|
||||
"/wms/ByTrayList": {
|
||||
"error": "Page.goto: Target page, context or browser has been closed"
|
||||
},
|
||||
"/wms/Dashboard": {
|
||||
"error": "Page.goto: Target page, context or browser has been closed"
|
||||
},
|
||||
"/wms/home": {
|
||||
"error": "Page.goto: Target page, context or browser has been closed"
|
||||
},
|
||||
"/wms/index": {
|
||||
"error": "Page.goto: Target page, context or browser has been closed"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,510 @@
|
||||
# 柏悦物流管理系统(Baiyue WMS)系统文档
|
||||
|
||||
> **版本**: 基于测试系统 2026-06-01 抓取分析
|
||||
> **访问地址**: http://39.101.149.173
|
||||
> **后端API**: https://adtest.bylogistic.cn
|
||||
> **技术栈**: Ant Design Vue + Spring Boot + MySQL + Redis
|
||||
> **测试账号**: admin / ndui#Emdfj23123
|
||||
|
||||
---
|
||||
|
||||
## 目录
|
||||
|
||||
1. [系统概述](#1-系统概述)
|
||||
2. [技术架构](#2-技术架构)
|
||||
3. [首页仪表盘](#3-首页仪表盘)
|
||||
4. [客户管理模块](#4-客户管理模块)
|
||||
5. [入库管理模块](#5-入库管理模块)
|
||||
6. [出库管理模块](#6-出库管理模块)
|
||||
7. [货柜管理模块](#7-货柜管理模块)
|
||||
8. [库存管理模块](#8-库存管理模块)
|
||||
9. [财务结算模块](#9-财务结算模块)
|
||||
10. [托盘管理模块](#10-托盘管理模块)
|
||||
11. [通用配置模块](#11-通用配置模块)
|
||||
12. [常见案例模块](#12-常见案例模块)
|
||||
13. [在线开发模块](#13-在线开发模块)
|
||||
14. [报表设计模块](#14-报表设计模块)
|
||||
15. [消息中心模块](#15-消息中心模块)
|
||||
16. [系统管理模块](#16-系统管理模块)
|
||||
17. [系统监控模块](#17-系统监控模块)
|
||||
18. [API接口清单](#18-api接口清单)
|
||||
|
||||
---
|
||||
|
||||
## 1. 系统概述
|
||||
|
||||
柏悦物流管理系统(Baiyue WMS)是一套面向跨境物流仓储行业的综合管理系统,覆盖从**客户管理 → 入库 → 出库 → 货柜管理 → 库存 → 托盘 → 财务结算**的全链路业务流程。
|
||||
|
||||
### 1.1 核心业务流程
|
||||
|
||||
```
|
||||
客户下单 → 入库单 → 入库测量 → 测量审核 → 接收审核 → 库存管理
|
||||
↓
|
||||
出库单 → BOL/派送 → 托盘管理 → 货柜管理 → 财务结算
|
||||
```
|
||||
|
||||
### 1.2 系统模块总览
|
||||
|
||||
| 序号 | 模块 | 子页面数 | 说明 |
|
||||
|------|------|----------|------|
|
||||
| 1 | 首页 | 1 | 数据看板/仪表盘 |
|
||||
| 2 | 客户管理 | 4 | 客户公司、用户、阶梯费用、流水 |
|
||||
| 3 | 入库 | 4 | 入库单、测量、审核、接收 |
|
||||
| 4 | 出库 | 3 | 派送单、BOL、自提单 |
|
||||
| 5 | 货柜管理 | 2 | 货柜列表、装柜清单 |
|
||||
| 6 | 库存 | 3 | 海外仓库存查询、理货、报损 |
|
||||
| 7 | 财务结算 | 5 | 应收应付、对账单、仓储成本 |
|
||||
| 8 | 托盘管理 | 2 | 托盘列表、生成托盘 |
|
||||
| 9 | 通用 | 8 | 产品、费用、FBA地址、库位等 |
|
||||
| 10 | 常见案例 | 2 | 自定义组件、对象存储 |
|
||||
| 11 | 在线开发 | 1 | Online表单开发 |
|
||||
| 12 | 报表设计 | 3 | 积木报表、生产监控、物流监控 |
|
||||
| 13 | 消息中心 | 3 | 模板、消息管理、我的消息 |
|
||||
| 14 | 系统管理 | 12 | 用户、角色、菜单、租户等 |
|
||||
| 15 | 系统监控 | 7 | 在线用户、日志、定时任务等 |
|
||||
| 16 | 统计报表 | - | 报表设计入口 |
|
||||
|
||||
---
|
||||
|
||||
## 2. 技术架构
|
||||
|
||||
### 2.1 前端技术
|
||||
|
||||
- **框架**: Vue.js(SPA 单页应用)
|
||||
- **UI 组件库**: Ant Design Vue
|
||||
- **路由**: Vue Router(Hash 模式)
|
||||
- **状态管理**: Vuex
|
||||
- **图表**: 集成数据可视化组件
|
||||
|
||||
### 2.2 后端技术
|
||||
|
||||
- **框架**: Spring Boot(推测,基于 Spring 生态)
|
||||
- **数据库**: MySQL
|
||||
- **缓存**: Redis
|
||||
- **认证**: Token-based(JWT)
|
||||
- **API 风格**: RESTful
|
||||
|
||||
### 2.3 认证流程
|
||||
|
||||
```
|
||||
用户登录 → POST /sys/login → 返回 Token
|
||||
后续请求 → Header: Authorization: Bearer {token}
|
||||
权限验证 → GET /sys/permission/getUserPermissionByToken
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. 首页仪表盘
|
||||
|
||||
- **URL**: `/wms/Dashboard`
|
||||
- **页面标题**: 柏悦物流管理系统
|
||||
|
||||
首页提供系统总览数据看板,展示关键业务指标(订单数、库存状态、财务概况等)。
|
||||
|
||||
---
|
||||
|
||||
## 4. 客户管理模块
|
||||
|
||||
### 4.1 客户公司管理
|
||||
|
||||
管理客户公司的基本信息,包括公司名称、联系方式、合作状态等。
|
||||
|
||||
### 4.2 用户资料
|
||||
|
||||
管理客户下的用户账号资料,包括登录账号、角色权限等。
|
||||
|
||||
### 4.3 海外仓阶梯费用
|
||||
|
||||
配置客户在海外仓的阶梯式费用规则,按不同量级设置不同单价。
|
||||
|
||||
### 4.4 客户账户流水
|
||||
|
||||
查看客户账户的资金流水明细,包括充值、消费、退款等记录。
|
||||
|
||||
---
|
||||
|
||||
## 5. 入库管理模块
|
||||
|
||||
入库是系统的核心业务流程模块,包含四个阶段:入库单创建 → 测量 → 测量审核 → 接收审核。
|
||||
|
||||
### 5.1 入库单列表
|
||||
|
||||
- **URL**: `/wms/ByInstoreList`
|
||||
- **页面标题**: 入库单列表 · 柏悦物流管理系统
|
||||
|
||||
#### 搜索条件
|
||||
|
||||
| 字段 | 说明 |
|
||||
|------|------|
|
||||
| 定位仓库 | 筛选指定仓库的入库单 |
|
||||
| 交货仓 | 筛选指定交货仓的入库单 |
|
||||
| 入仓码 | 按入仓码精确查询 |
|
||||
| 订单状态 | 按订单状态筛选(如:待处理、处理中、已完成) |
|
||||
| 费用审核状态 | 按费用审核状态筛选 |
|
||||
|
||||
#### 表格列头(23列)
|
||||
|
||||
| 列名 | 说明 |
|
||||
|------|------|
|
||||
| 仓库 | 入库目标仓库 |
|
||||
| 交货仓 | 货物来源交货仓 |
|
||||
| 配载状态 | 货物配载状态 |
|
||||
| 是否扣货 | 是否被扣货标记 |
|
||||
| 扣货理由 | 扣货原因说明 |
|
||||
| 集装箱号 | 集装箱编号 |
|
||||
| 柜号 | 货柜编号 |
|
||||
| 公司 | 客户公司名称 |
|
||||
| 业务类型 | 业务分类 |
|
||||
| 提货方式 | 提货方式(自提/送货等) |
|
||||
| 提货时间 | 预约提货时间 |
|
||||
| 提货联系人电话 | 提货联系人电话 |
|
||||
| 提货地址 | 提货地址详情 |
|
||||
| 提货邮编 | 提货地邮编 |
|
||||
| 提货联系人邮箱 | 提货联系人邮箱 |
|
||||
| 渠道 | 业务渠道来源 |
|
||||
| 买单/退税 | 贸易方式(买单/退税) |
|
||||
| 是否整柜 | 整柜/拼柜标记 |
|
||||
| 商检验 | 商检检验标记 |
|
||||
| 开船时间 | 预计开船时间 |
|
||||
| 到港时间 | 预计到港时间 |
|
||||
| 总箱数 | 货物总箱数 |
|
||||
| 总毛重(T.K.GW) | 总毛重(吨/公斤) |
|
||||
|
||||
#### 操作按钮
|
||||
|
||||
| 按钮 | 功能 |
|
||||
|------|------|
|
||||
| 查询 | 根据搜索条件查询数据 |
|
||||
| 重置 | 清空搜索条件 |
|
||||
| 国内仓下单 | 创建国内仓入库单 |
|
||||
| 海外分仓下单 | 创建海外分仓入库单 |
|
||||
| 整托下单 | 以整托方式创建入库单 |
|
||||
| 高级查询 | 打开高级筛选面板 |
|
||||
| 导出报表 | 导出当前查询结果为Excel |
|
||||
| 导出入库清单总表 | 导出完整的入库清单 |
|
||||
| 导出唛头 | 导出唛头标签文件 |
|
||||
| 导出FBA流转单ZIP | 导出FBA流转单压缩包 |
|
||||
| 下载 | 下载选中记录的相关文件 |
|
||||
|
||||
### 5.2 入库单测量
|
||||
|
||||
- **URL**: `/wms/ByInstoreList4Measured`
|
||||
- **页面标题**: 入库单测量 · 柏悦物流管理系统
|
||||
|
||||
对入库货物进行实际测量,记录测量数据。
|
||||
|
||||
#### 搜索条件
|
||||
|
||||
| 字段 | 说明 |
|
||||
|------|------|
|
||||
| 仓库 | 筛选仓库 |
|
||||
| 入仓码 | 按入仓码查询 |
|
||||
| 公司 | 按客户公司筛选 |
|
||||
| FBA货件编号 | 按FBA货件编号查询 |
|
||||
|
||||
#### 表格列头(24列)
|
||||
|
||||
| 列名 | 说明 |
|
||||
|------|------|
|
||||
| 入仓码 | 入仓编码 |
|
||||
| 仓库 | 目标仓库 |
|
||||
| 订单状态 | 订单处理状态 |
|
||||
| 配载状态 | 配载情况 |
|
||||
| 测量数据审核状态 | 测量审核进度 |
|
||||
| 唛头文件 | 唛头标签文件 |
|
||||
| 是否扣货 | 扣货标记 |
|
||||
| 扣货理由 | 扣货原因 |
|
||||
| 公司 | 客户公司 |
|
||||
| 业务类型 | 业务分类 |
|
||||
| 渠道 | 业务渠道 |
|
||||
| 买单/退税 | 贸易方式 |
|
||||
| 是否整柜 | 整柜/拼柜 |
|
||||
| 商检验 | 商检状态 |
|
||||
| 总箱数 | 货物总箱数 |
|
||||
| 总毛重(T.K.GW) | 总毛重 |
|
||||
| 总体积(m³) | 货物总体积 |
|
||||
| 总材积重 | 材积重量 |
|
||||
| 总净重(T.K.NW) | 总净重 |
|
||||
| 目的仓类型 | 目的仓库类型 |
|
||||
| 目的仓 | 目的仓库 |
|
||||
| 货件编号 | 货件编号 |
|
||||
| 测量完成时间 | 测量完成时间 |
|
||||
| 操作 | 操作按钮列 |
|
||||
|
||||
#### 操作按钮
|
||||
|
||||
| 按钮 | 功能 |
|
||||
|------|------|
|
||||
| 查询 | 根据条件查询 |
|
||||
| 重置 | 清空条件 |
|
||||
| 下载 | 下载数据 |
|
||||
|
||||
### 5.3 测量数据审核
|
||||
|
||||
- **URL**: `/wms/ByInstoreList4MeasuredAudit`
|
||||
- **页面标题**: 测量数据审核 · 柏悦物流管理系统
|
||||
|
||||
对测量数据进行审核确认。表头和搜索条件与入库单测量一致。
|
||||
|
||||
### 5.4 接收审核
|
||||
|
||||
- **URL**: `/wms/ByInstoreList4ReceiveAudit`
|
||||
- **页面标题**: 接收审核 · 柏悦物流管理系统
|
||||
|
||||
最终接收审核环节,确认货物入库完成。表头和搜索条件与入库单测量一致。
|
||||
|
||||
---
|
||||
|
||||
## 6. 出库管理模块
|
||||
|
||||
### 6.1 派送单列表
|
||||
|
||||
- **URL**: `/wms/ByDispatchList`
|
||||
|
||||
管理出库派送订单,包括派送地址、物流方式、派送状态等。
|
||||
|
||||
### 6.2 BOL(提单管理)
|
||||
|
||||
- **URL**: `/wms/ByBolList`
|
||||
|
||||
管理 Bill of Lading(提单),是国际物流中的重要单证。包括提单号、船名航次、发货人、收货人等。
|
||||
|
||||
### 6.3 自提单
|
||||
|
||||
管理客户自提订单,记录自提预约、提货人信息等。
|
||||
|
||||
---
|
||||
|
||||
## 7. 货柜管理模块
|
||||
|
||||
### 7.1 货柜列表
|
||||
|
||||
- **URL**: `/wms/ByContainerList`
|
||||
|
||||
管理所有货柜信息,包括柜号、类型、尺寸、状态、当前位置等。
|
||||
|
||||
### 7.2 装柜清单
|
||||
|
||||
记录每个货柜的装柜明细,展示柜内货物列表和装载方案。
|
||||
|
||||
---
|
||||
|
||||
## 8. 库存管理模块
|
||||
|
||||
### 8.1 海外仓库存查询
|
||||
|
||||
- **URL**: `/wms/ByInventoryList`
|
||||
|
||||
查询海外仓当前库存情况,支持按仓库、产品、SKU等维度查询。
|
||||
|
||||
### 8.2 理货管理
|
||||
|
||||
对库存货物进行盘点、整理、移位等操作。
|
||||
|
||||
### 8.3 报损单
|
||||
|
||||
管理货物损耗/损坏的报损申请和审批流程。
|
||||
|
||||
---
|
||||
|
||||
## 9. 财务结算模块
|
||||
|
||||
### 9.1 客户应收应付
|
||||
|
||||
- **URL**: `/wms/ByFinanceList`
|
||||
|
||||
管理每个客户的应收账款和应付账款明细。
|
||||
|
||||
### 9.2 客户对账单
|
||||
|
||||
生成和查看客户对账单,用于与客户进行账务核对。
|
||||
|
||||
### 9.3 结算单位应付
|
||||
|
||||
按结算单位(如承运商、仓库方)管理应付账款。
|
||||
|
||||
### 9.4 结算单位对账单
|
||||
|
||||
生成结算单位的对账单。
|
||||
|
||||
### 9.5 洛杉矶仓储成本
|
||||
|
||||
专门针对洛杉矶仓库的仓储成本核算和分析。
|
||||
|
||||
---
|
||||
|
||||
## 10. 托盘管理模块
|
||||
|
||||
### 10.1 托盘列表
|
||||
|
||||
- **URL**: `/wms/ByTrayList`
|
||||
|
||||
管理所有托盘信息,包括托盘编号、规格、状态、关联货物等。
|
||||
|
||||
### 10.2 生成托盘
|
||||
|
||||
根据入库货物自动/手动生成托盘,分配货物到托盘。
|
||||
|
||||
---
|
||||
|
||||
## 11. 通用配置模块
|
||||
|
||||
系统基础数据和配置管理。
|
||||
|
||||
| 子模块 | 说明 |
|
||||
|--------|------|
|
||||
| 产品信息 | 管理产品/货品基础信息(名称、规格、HS编码等) |
|
||||
| 费用项目 | 定义各类费用项目(仓储费、操作费、运输费等) |
|
||||
| FBA编码地址 | 管理Amazon FBA仓库编码和地址信息 |
|
||||
| 托盘管理 | 托盘基础配置 |
|
||||
| 库位/货架管理 | 仓库库位和货架的编号和配置 |
|
||||
| 订单流转路径 | 定义订单在不同节点之间的流转规则 |
|
||||
| 快递公司 | 合作的快递/物流公司信息 |
|
||||
| 往来单位 | 管理供应商、承运商等往来单位信息 |
|
||||
|
||||
---
|
||||
|
||||
## 12. 常见案例模块
|
||||
|
||||
### 12.1 自定义组件
|
||||
|
||||
展示系统自定义组件的使用示例和开发指南。
|
||||
|
||||
### 12.2 对象存储
|
||||
|
||||
文件/对象存储功能的配置和使用说明。
|
||||
|
||||
---
|
||||
|
||||
## 13. 在线开发模块
|
||||
|
||||
### 13.1 Online表单开发
|
||||
|
||||
低代码表单开发工具,允许管理员在线设计和配置业务表单,无需编写代码。
|
||||
|
||||
---
|
||||
|
||||
## 14. 报表设计模块
|
||||
|
||||
### 14.1 积木报表设计
|
||||
|
||||
可视化报表设计器,支持拖拽式设计各类业务报表。
|
||||
|
||||
### 14.2 生产销售监控
|
||||
|
||||
展示生产和销售的监控数据看板。
|
||||
|
||||
### 14.3 智慧物流监控
|
||||
|
||||
物流全链路监控大屏,展示实时物流数据。
|
||||
|
||||
---
|
||||
|
||||
## 15. 消息中心模块
|
||||
|
||||
### 15.1 模板管理
|
||||
|
||||
管理系统通知的消息模板,支持短信、邮件、站内信等类型。
|
||||
|
||||
### 15.2 消息管理
|
||||
|
||||
查看和管理所有已发送的系统消息。
|
||||
|
||||
### 15.3 我的消息
|
||||
|
||||
当前登录用户收到的个人消息列表。
|
||||
|
||||
---
|
||||
|
||||
## 16. 系统管理模块
|
||||
|
||||
系统后台管理功能。
|
||||
|
||||
| 子模块 | 说明 |
|
||||
|--------|------|
|
||||
| 用户管理 | 管理系统用户账号(创建、编辑、禁用、重置密码) |
|
||||
| 角色管理 | 定义角色并分配权限 |
|
||||
| 菜单管理 | 配置系统导航菜单结构 |
|
||||
| 租户管理 | 多租户隔离管理(适用于SaaS模式) |
|
||||
| 部门管理 | 组织架构部门管理 |
|
||||
| 我的部门 | 当前用户所属部门信息 |
|
||||
| 职务管理 | 定义系统内职务 |
|
||||
| 通讯录 | 系统用户通讯录 |
|
||||
| 数据字典 | 系统枚举值和字典数据维护 |
|
||||
| 分类字典 | 分类树形字典维护 |
|
||||
| 系统通告 | 发布系统级公告通知 |
|
||||
| 菜单管理2 | 菜单管理的增强版/备用入口 |
|
||||
|
||||
---
|
||||
|
||||
## 17. 系统监控模块
|
||||
|
||||
系统运行状态监控和运维管理。
|
||||
|
||||
| 子模块 | 说明 |
|
||||
|--------|------|
|
||||
| 在线用户 | 查看当前在线用户列表,支持强制下线 |
|
||||
| 路由网关 | 查看系统路由配置和网关状态 |
|
||||
| 定时任务 | 管理系统的定时任务(Cron Job) |
|
||||
| 日志管理 | 查看系统操作日志 |
|
||||
| 数据日志 | 数据变更日志记录 |
|
||||
| SQL监控 | SQL执行监控(基于Druid连接池) |
|
||||
| 在线文档 | 系统API文档(Swagger/Knife4j) |
|
||||
|
||||
---
|
||||
|
||||
## 18. API接口清单
|
||||
|
||||
系统后端API部署在 `https://adtest.bylogistic.cn`,以下为已发现的API端点:
|
||||
|
||||
### 认证相关
|
||||
|
||||
| 接口 | 方法 | 说明 |
|
||||
|------|------|------|
|
||||
| `/sys/login` | POST | 用户登录 |
|
||||
| `/sys/randomImage/{timestamp}` | GET | 获取验证码图片 |
|
||||
| `/sys/permission/getUserPermissionByToken` | GET | 获取用户权限 |
|
||||
|
||||
### 数据字典
|
||||
|
||||
| 接口 | 方法 | 说明 |
|
||||
|------|------|------|
|
||||
| `/sys/dict/getDictItems/by_company` | GET | 获取公司字典 |
|
||||
| `/sys/dict/getDictItems/by_order_status` | GET | 获取订单状态字典 |
|
||||
| `/sys/dict/getDictItems/by_customer` | GET | 获取客户字典 |
|
||||
| `/sys/dict/getDictItems/by_store` | GET | 获取仓库字典 |
|
||||
| `/sys/dict/getDictItems/by_order_path` | GET | 获取订单路径字典 |
|
||||
| `/sys/dict/getDictItems/by_fba` | GET | 获取FBA编码字典 |
|
||||
|
||||
### 系统功能
|
||||
|
||||
| 接口 | 方法 | 说明 |
|
||||
|------|------|------|
|
||||
| `/sys/annountCement/listByUser` | GET | 获取用户公告列表 |
|
||||
| `/sys/loginfo` | GET | 系统日志信息 |
|
||||
| `/sys/visitInfo` | GET | 访问统计信息 |
|
||||
|
||||
---
|
||||
|
||||
## 附录:SKU明细区域列头
|
||||
|
||||
在入库单详情页面,SKU明细表格包含以下列:
|
||||
|
||||
| 列名 | 说明 |
|
||||
|------|------|
|
||||
| 操作 | 编辑/删除操作 |
|
||||
| # | 序号 |
|
||||
| 报关HS_CODE | 报关用HS海关编码 |
|
||||
| 货品图片 | 货品图片预览 |
|
||||
| 仓/储/微(快递)码/纱 | 仓储编码/微信码/快递码 |
|
||||
| 中品名 | 中文品名 |
|
||||
| 英品名 | 英文品名 |
|
||||
| 清关HS_CODE | 清关用HS海关编码 |
|
||||
| 箱规长(cm) | 外箱长度 |
|
||||
| 箱规宽(cm) | 外箱宽度 |
|
||||
|
||||
---
|
||||
|
||||
> **文档生成时间**: 2026-06-01
|
||||
> **数据来源**: 测试系统 http://39.101.149.173 实际登录抓取
|
||||
> **说明**: 部分页面因SPA路由限制未能获取完整表头信息,已根据菜单结构推断标注。如需补充具体页面详情,请登录系统确认后更新。
|
||||