Files
WorkBuddy/freight-sfa-server/html/index.html
T

250 lines
34 KiB
HTML

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover, user-scalable=no">
<meta name="theme-color" content="#6B5385">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<meta name="apple-mobile-web-app-title" content="货代SFA">
<meta name="mobile-web-app-capable" content="yes">
<meta name="format-detection" content="telephone=no">
<title>客户管理工作台(货代版)</title>
<link rel="icon" href="data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 64 64'><rect width='64' height='64' rx='14' fill='%236B5385'/><text x='50%25' y='52%25' text-anchor='middle' fill='%23F5E9D7' font-size='38' font-family='sans-serif' dominant-baseline='middle' font-weight='700'>S</text></svg>">
<link rel="stylesheet" href="style.css">
</head>
<body>
<!-- ===== 登录 / 注册页 ===== -->
<div class="login-page" id="loginPage">
<div class="login-bg"></div>
<div class="login-card">
<div class="login-logo">
<svg viewBox="0 0 64 64"><rect width="64" height="64" rx="14" fill="#F5E9D7"/><text x="50%" y="52%" text-anchor="middle" fill="#54416A" font-size="38" font-family="sans-serif" dominant-baseline="middle" font-weight="700">S</text></svg>
</div>
<h1 class="login-title">货代 SFA 工作台</h1>
<p class="login-sub">客户 · 商机 · 订舱 · 跟进 全流程管理</p>
<div class="login-tabs">
<button class="login-tab active" data-tab="login">登 录</button>
<button class="login-tab" data-tab="register">注 册</button>
</div>
<div class="login-field">
<label>用户名</label>
<input id="loginUser" autocomplete="username" placeholder="请输入用户名">
</div>
<div class="login-field">
<label>密码</label>
<input id="loginPass" type="password" autocomplete="current-password" placeholder="请输入密码">
</div>
<div class="login-field" id="loginNameField" style="display:none">
<label>显示名称</label>
<input id="loginName" autocomplete="nickname" placeholder="团队内展示的姓名">
</div>
<div class="login-hint" id="loginHint">首个注册账号自动成为管理员</div>
<button class="login-btn" id="loginSubmit">登 录</button>
<div class="login-foot">数据存储于服务端 · 团队共享一套账套</div>
</div>
</div>
<div class="app" id="app" style="display:none">
<header class="header">
<button class="menu-toggle" id="menuToggle" aria-label="菜单">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><line x1="3" y1="6" x2="21" y2="6"/><line x1="3" y1="12" x2="21" y2="12"/><line x1="3" y1="18" x2="21" y2="18"/></svg>
</button>
<div class="header-logo">
<svg viewBox="0 0 64 64"><rect width="64" height="64" rx="14" fill="#F5E9D7"/><text x="50%" y="52%" text-anchor="middle" fill="#54416A" font-size="38" font-family="sans-serif" dominant-baseline="middle" font-weight="700">S</text></svg>
<div class="header-title">客户管理工作台 <small>· 货代销售版</small></div>
</div>
<div class="header-search">
<svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="7"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg>
<input id="globalSearch" type="search" placeholder="搜索客户/商机/订舱号/单号...">
</div>
<div class="header-spacer"></div>
<div class="header-actions">
<div class="sync-indicator" id="syncIndicator" title="服务端连接状态">
<span class="sync-dot" id="syncDot"></span><span id="syncLabel">服务端已连接</span>
</div>
<button class="icon-btn" id="btnQuickAdd" title="快速新建" aria-label="快速新建">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>
</button>
<div class="user-avatar" id="userAvatar">S</div>
</div>
</header>
<aside class="sidebar" id="sidebar">
<div class="side-section">
<div class="side-section-title">首页看板</div>
<div class="side-item" data-route="dashboard"><svg class="ic" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="3" width="7" height="7"/><rect x="14" y="3" width="7" height="7"/><rect x="14" y="14" width="7" height="7"/><rect x="3" y="14" width="7" height="7"/></svg>综合看板</div>
<div class="side-item" data-route="view-funnel"><svg class="ic" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polygon points="22 3 2 3 10 12.46 10 19 14 21 14 12.46"/></svg>销售漏斗 <span class="badge" id="badge-funnel">0</span></div>
<div class="side-item" data-route="view-customers-table"><svg class="ic" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M3 3h18v4H3zM3 10h18v4H3zM3 17h18v4H3z"/></svg>客户全量</div>
<div class="side-item" data-route="view-vip"><svg class="ic" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"/></svg>A类重点 <span class="badge" id="badge-vip">0</span></div>
<div class="side-item" data-route="view-channels"><svg class="ic" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="18" y1="20" x2="18" y2="10"/><line x1="12" y1="20" x2="12" y2="4"/><line x1="6" y1="20" x2="6" y2="14"/></svg>渠道产出 <span class="badge" id="badge-channels">0</span></div>
<div class="side-item" data-route="view-bookings"><svg class="ic" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="6" width="18" height="13" rx="2"/><path d="M16 6V4a2 2 0 0 0-2-2h-4a2 2 0 0 0-2 2v2"/></svg>订舱跟踪 <span class="badge alert-badge" id="badge-bookings-alert">0</span></div>
<div class="side-item" data-route="view-payments"><svg class="ic" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="12" y1="1" x2="12" y2="23"/><path d="M17 5H9.5a3.5 3.5 0 0 0 0 7h5a3.5 3.5 0 0 1 0 7H6"/></svg>回款预警 <span class="badge alert-badge" id="badge-payment">0</span></div>
<div class="side-item" data-route="view-loss"><svg class="ic" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><line x1="15" y1="9" x2="9" y2="15"/><line x1="9" y1="9" x2="15" y2="15"/></svg>丢单复盘 <span class="badge" id="badge-loss">0</span></div>
<div class="side-item" data-route="view-risk"><svg class="ic" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg>高风险客户 <span class="badge alert-badge" id="badge-risk">0</span></div>
</div>
<div class="side-section">
<div class="side-section-title">数据库表</div>
<div class="side-item" data-route="table-clients"><svg class="ic" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg>客户档案 <span class="badge" id="count-clients">0</span></div>
<div class="side-item" data-route="table-inquiries"><svg class="ic" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg>商机询价 <span class="badge" id="count-inquiries">0</span></div>
<div class="side-item" data-route="table-bookings"><svg class="ic" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M3 17h18M3 12h18M3 7h18"/></svg>订舱执行 <span class="badge" id="count-bookings">0</span></div>
<div class="side-item" data-route="table-followups"><svg class="ic" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="9 11 12 14 22 4"/><path d="M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11"/></svg>跟进记录 <span class="badge" id="count-followups">0</span></div>
</div>
<div class="side-divider"></div>
<div class="side-section">
<div class="side-section-title">数据管理</div>
<div class="side-item" data-route="stats"><svg class="ic" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="18" y1="20" x2="18" y2="10"/><line x1="12" y1="20" x2="12" y2="4"/><line x1="6" y1="20" x2="6" y2="14"/></svg>数据统计</div>
<div class="side-item" data-route="settings"><svg class="ic" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg>个人中心</div>
</div>
<div class="side-footer-card">
<h4>已沉淀数据</h4>
<div class="count" id="footTotal">0</div>
<div style="font-size:11px;color:var(--ink-mute);margin-top:2px">条客户/商机/订舱/跟进记录</div>
</div>
</aside>
<main class="main" id="main">
<section class="page active" id="page-dashboard">
<div class="page-head">
<div><h1><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><rect x="3" y="3" width="7" height="7"/><rect x="14" y="3" width="7" height="7"/><rect x="14" y="14" width="7" height="7"/><rect x="3" y="14" width="7" height="7"/></svg>综合看板</h1><p>今日核心指标 · 待办逾期一屏掌握</p></div>
<div class="page-actions">
<button class="btn btn-secondary btn-sm" id="btnRefresh"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="23 4 23 10 17 10"/><polyline points="1 20 1 14 7 14"/><path d="M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15"/></svg>刷新</button>
<button class="btn btn-primary btn-sm" onclick="openForm('client')"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>新建客户</button>
</div>
</div>
<div class="today-bar" id="todayBar">
<div class="label"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg>今天要处理</div>
<div class="today-tasks" id="todayTasks"></div>
<div class="quick-stats">
<div><b id="qs-today-followups">0</b><span>待跟进</span></div>
<div><b id="qs-today-etd">0</b><span>今日开船</span></div>
<div><b id="qs-overdue-payment">0</b><span>逾期回款</span></div>
</div>
</div>
<div class="grid grid-4" style="margin-bottom:18px">
<div class="card stat-card"><div class="kpi-icon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg></div><div class="card-title">客户总数</div><div class="num" id="kpi-clients">0</div><div class="delta">A级核心 <span id="kpi-vip-count" style="font-weight:700;margin-left:4px">0</span></div></div>
<div class="card stat-card"><div class="kpi-icon success"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="22 12 18 12 15 21 9 3 6 12 2 12"/></svg></div><div class="card-title">商机询价中</div><div class="num" id="kpi-inquiries">0</div><div class="delta">已报价 <span id="kpi-quoted" style="font-weight:700;margin-left:4px">0</span></div></div>
<div class="card stat-card"><div class="kpi-icon warning"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="6" width="18" height="13" rx="2"/><path d="M16 6V4a2 2 0 0 0-2-2h-4a2 2 0 0 0-2 2v2"/></svg></div><div class="card-title">订舱执行中</div><div class="num" id="kpi-bookings">0</div><div class="delta">本周开船 <span id="kpi-week-etd" style="font-weight:700;margin-left:4px">0</span></div></div>
<div class="card stat-card"><div class="kpi-icon cream"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="12" y1="1" x2="12" y2="23"/><path d="M17 5H9.5a3.5 3.5 0 0 0 0 7h5a3.5 3.5 0 0 1 0 7H6"/></svg></div><div class="card-title">待回款金额</div><div class="num" id="kpi-pending-pay">¥0</div><div class="delta down">逾期 <span id="kpi-overdue-pay" style="font-weight:700;margin-left:4px">¥0</span></div></div>
</div>
<div class="charts">
<div class="chart-box"><h4><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="18" y1="20" x2="18" y2="10"/><line x1="12" y1="20" x2="12" y2="4"/><line x1="6" y1="20" x2="6" y2="14"/></svg>客户跟进状态分布</h4><svg viewBox="0 0 360 220" id="chart-followup" preserveAspectRatio="xMidYMid meet" style="flex:1;width:100%;height:100%"></svg></div>
<div class="chart-box"><h4><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="6" width="18" height="13" rx="2"/></svg>订舱状态饼图</h4><svg viewBox="0 0 360 220" id="chart-booking" preserveAspectRatio="xMidYMid meet" style="flex:1;width:100%;height:100%"></svg></div>
</div>
<div class="grid grid-2">
<div class="card"><div class="card-title"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="3 6 5 6 21 6"/><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/></svg>本周开船 · 需重点盯货</div><div id="week-etd-list" style="margin-top:10px;display:flex;flex-direction:column;gap:8px"></div></div>
<div class="card"><div class="card-title"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"/><line x1="12" y1="9" x2="12" y2="13"/></svg>逾期回款清单</div><div id="overdue-list" style="margin-top:10px;display:flex;flex-direction:column;gap:8px"></div></div>
</div>
</section>
<section class="page" id="page-view-funnel">
<div class="page-head"><div><h1><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polygon points="22 3 2 3 10 12.46 10 19 14 21 14 12.46"/></svg>销售漏斗看板</h1><p>按客户跟进状态分组 · 拖拽变更状态</p></div></div>
<div class="kanban cols-5" id="funnel-kanban"></div>
</section>
<section class="page" id="page-view-customers-table">
<div class="page-head"><div><h1><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M3 3h18v4H3zM3 10h18v4H3zM3 17h18v4H3z"/></svg>客户分类检索</h1><p>按等级·渠道·供应商多条件筛选汇总</p></div><div class="page-actions"><button class="btn btn-secondary btn-sm" onclick="exportCSV('clients')"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg>导出Excel</button></div></div>
<div class="filter-bar" id="clientFilter">
<input type="search" id="cf-q" placeholder="搜索客户名称..." oninput="renderCustomerTable()">
<select id="cf-type" onchange="renderCustomerTable()"><option value="">全部客户类型</option></select>
<select id="cf-grade" onchange="renderCustomerTable()"><option value="">全部ABC分级</option></select>
<select id="cf-status" onchange="renderCustomerTable()"><option value="">全部跟进状态</option></select>
<select id="cf-source" onchange="renderCustomerTable()"><option value="">全部来源渠道</option></select>
<div class="filter-spacer"></div><span style="font-size:12px;color:var(--ink-mute)"><b id="cf-count">0</b></span>
</div>
<div class="table-wrap"><div class="table-scroll"><table class="data" id="clientTable"><thead></thead><tbody></tbody></table></div></div>
</section>
<section class="page" id="page-view-vip">
<div class="page-head"><div><h1><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"/></svg>A类重点客户仪表盘</h1><p>仅A级核心 · 优先维护</p></div></div>
<div class="grid grid-3" id="vipDashboard" style="margin-bottom:16px"></div>
<div class="table-wrap"><div class="table-scroll"><table class="data" id="vipTable"><thead></thead><tbody></tbody></table></div></div>
</section>
<section class="page" id="page-view-channels">
<div class="page-head"><div><h1><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="18" y1="20" x2="18" y2="10"/><line x1="12" y1="20" x2="12" y2="4"/><line x1="6" y1="20" x2="6" y2="14"/></svg>渠道产出统计</h1><p>按获客渠道 · 复盘渠道价值</p></div></div>
<div id="channelSummary" class="grid grid-4" style="margin-bottom:16px"></div>
<div class="chart-box" style="height:340px;margin-bottom:16px"><h4><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="18" y1="20" x2="18" y2="10"/><line x1="12" y1="20" x2="12" y2="4"/><line x1="6" y1="20" x2="6" y2="14"/></svg>各渠道客户产出 · 优质客户占比</h4><svg viewBox="0 0 760 320" id="chart-channel" preserveAspectRatio="xMidYMid meet" style="flex:1;width:100%;height:100%"></svg></div>
<div class="table-wrap"><div class="table-scroll"><table class="data" id="channelTable"><thead></thead><tbody></tbody></table></div></div>
</section>
<section class="page" id="page-view-bookings">
<div class="page-head"><div><h1><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="6" width="18" height="13" rx="2"/><path d="M16 6V4a2 2 0 0 0-2-2h-4a2 2 0 0 0-2 2v2"/></svg>订舱业务跟踪看板</h1><p>每票货 · 庄家/DDP/船期 全流程跟踪</p></div></div>
<div class="kanban cols-3" id="bookings-kanban"></div>
</section>
<section class="page" id="page-view-payments">
<div class="page-head"><div><h1><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="12" y1="1" x2="12" y2="23"/><path d="M17 5H9.5a3.5 3.5 0 0 0 0 7h5a3.5 3.5 0 0 1 0 7H6"/></svg>回款预警仪表盘</h1><p>筛选未回款·逾期订单 · 管控坏账</p></div></div>
<div class="grid grid-4" id="paymentKPI" style="margin-bottom:16px"></div>
<div class="table-wrap"><div class="table-scroll"><table class="data" id="paymentTable"><thead></thead><tbody></tbody></table></div></div>
</section>
<section class="page" id="page-view-loss">
<div class="page-head"><div><h1><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><line x1="15" y1="9" x2="9" y2="15"/><line x1="9" y1="9" x2="15" y2="15"/></svg>丢单原因统计</h1><p>优化报价·供应商·服务短板</p></div></div>
<div id="lossSummary" class="grid grid-3" style="margin-bottom:16px"></div>
<div class="chart-box" style="height:320px;margin-bottom:16px"><h4><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="12" width="4" height="9"/><rect x="10" y="6" width="4" height="15"/><rect x="17" y="3" width="4" height="18"/></svg>丢单原因分布</h4><svg viewBox="0 0 760 280" id="chart-loss" preserveAspectRatio="xMidYMid meet" style="flex:1;width:100%;height:100%"></svg></div>
<div class="table-wrap"><div class="table-scroll"><table class="data" id="lossTable"><thead></thead><tbody></tbody></table></div></div>
</section>
<section class="page" id="page-view-risk">
<div class="page-head"><div><h1><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg>高风险客户视图</h1><p>统一管控账期·纠纷·欠款风险</p></div></div>
<div id="riskSummary" class="grid grid-3" style="margin-bottom:16px"></div>
<div class="table-wrap"><div class="table-scroll"><table class="data" id="riskTable"><thead></thead><tbody></tbody></table></div></div>
</section>
<section class="page" id="page-table-clients">
<div class="page-head"><div><h1><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg>客户档案表</h1><p>主表 · 通用+按类型展开+财务保密</p></div><div class="page-actions"><button class="btn btn-secondary btn-sm" onclick="openOptionEditor()"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="3"/></svg>选项管理</button><button class="btn btn-secondary btn-sm" onclick="exportCSV('clients')"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg>导出</button><button class="btn btn-primary btn-sm" onclick="openForm('client')"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>新建客户</button></div></div>
<div class="table-wrap"><div class="table-scroll"><table class="data" id="clientListTable"><thead></thead><tbody></tbody></table></div></div>
</section>
<section class="page" id="page-table-inquiries">
<div class="page-head"><div><h1><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg>商机询价表</h1><p>询价 → 多版本报价 → 状态流转</p></div><div class="page-actions"><button class="btn btn-secondary btn-sm" onclick="exportCSV('inquiries')"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg>导出</button><button class="btn btn-primary btn-sm" onclick="openForm('inquiry')"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>新建询价</button></div></div>
<div class="table-wrap"><div class="table-scroll"><table class="data" id="inquiryListTable"><thead></thead><tbody></tbody></table></div></div>
</section>
<section class="page" id="page-table-bookings">
<div class="page-head"><div><h1><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M3 17h18M3 12h18M3 7h18"/></svg>订舱执行记录表</h1><p>本票实际执行供应商·优先级最高</p></div><div class="page-actions"><button class="btn btn-secondary btn-sm" onclick="exportCSV('bookings')"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg>导出</button><button class="btn btn-primary btn-sm" onclick="openForm('booking')"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>新建订舱</button></div></div>
<div class="table-wrap"><div class="table-scroll"><table class="data" id="bookingListTable"><thead></thead><tbody></tbody></table></div></div>
</section>
<section class="page" id="page-table-followups">
<div class="page-head"><div><h1><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="9 11 12 14 22 4"/><path d="M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11"/></svg>跟进记录表</h1><p>沟通·改单·催款全留痕</p></div><div class="page-actions"><button class="btn btn-secondary btn-sm" onclick="exportCSV('followups')"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg>导出</button><button class="btn btn-primary btn-sm" onclick="openForm('followup')"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>新建跟进</button></div></div>
<div class="table-wrap"><div class="table-scroll"><table class="data" id="followupListTable"><thead></thead><tbody></tbody></table></div></div>
</section>
<section class="page" id="page-stats">
<div class="page-head"><div><h1><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="18" y1="20" x2="18" y2="10"/><line x1="12" y1="20" x2="12" y2="4"/><line x1="6" y1="20" x2="6" y2="14"/></svg>数据统计分析</h1><p>渠道·客户价值·业务健康度</p></div></div>
<div class="grid grid-4" style="margin-bottom:18px" id="statsKPI"></div>
<div class="charts">
<div class="chart-box"><h4>客户等级分布</h4><svg viewBox="0 0 360 220" id="chart-grade" preserveAspectRatio="xMidYMid meet" style="flex:1;width:100%;height:100%"></svg></div>
<div class="chart-box"><h4>客户类型分布</h4><svg viewBox="0 0 360 220" id="chart-type" preserveAspectRatio="xMidYMid meet" style="flex:1;width:100%;height:100%"></svg></div>
</div>
</section>
<section class="page" id="page-settings">
<div class="page-head"><div><h1><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg>个人中心 · 数据管理</h1><p>账号 / 备份导入 / 清空 / 桌面挂载</p></div></div>
<div class="profile-card"><div class="avatar">S</div><div class="info"><h3 id="profile-name">货代销售管理员</h3><p>专业货代SFA · 客户/询价/订舱/跟进全闭环</p></div><div class="stats"><div class="item"><div class="num" id="profile-clients">0</div><div class="lbl">客户</div></div><div class="item"><div class="num" id="profile-inq">0</div><div class="lbl">商机</div></div><div class="item"><div class="num" id="profile-bookings">0</div><div class="lbl">订舱</div></div><div class="item"><div class="num" id="profile-fl">0</div><div class="lbl">跟进</div></div></div></div>
<div class="settings-card"><h3><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="3"/><path d="M12 1v6m0 6v6m11-7h-6m-6 0H1"/></svg>我的账号</h3><div class="settings-row"><div><div class="label">当前用户</div><div class="desc" id="acct-desc">-</div></div><button class="btn btn-secondary btn-sm" onclick="logout()">退出登录</button></div></div>
<div class="settings-card"><h3><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg>数据备份</h3><div class="settings-row"><div><div class="label">导出全部数据 (JSON)</div><div class="desc">客户/商机/订舱/跟进记录+自定义字段选项</div></div><button class="btn btn-secondary btn-sm" onclick="exportBackup()">立即导出</button></div><div class="settings-row"><div><div class="label">从备份恢复</div><div class="desc">将覆盖现有数据,请先导出当前数据</div></div><label class="btn btn-secondary btn-sm" style="cursor:pointer">选择文件<input type="file" accept=".json" onchange="importBackup(event)" style="display:none"></label></div><div class="settings-row"><div><div class="label">清空全部数据</div><div class="desc">⚠️ 不可恢复,请确认已备份</div></div><button class="btn btn-danger btn-sm" onclick="clearAllData()">清空</button></div></div>
<div class="settings-card"><h3><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="5" y="2" width="14" height="20" rx="2" ry="2"/><line x1="12" y1="18" x2="12.01" y2="18"/></svg>桌面挂载</h3><div class="settings-row"><div><div class="label">添加到手机主屏幕</div><div class="desc">iPhone Safari·分享→添加到主屏幕 · Android Chrome·菜单→添加到主屏幕</div></div><span style="font-size:12px;color:var(--ink-mute)">已支持 PWA</span></div></div>
<div class="settings-card"><h3><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="3"/><path d="M12 1v6m0 6v6m11-7h-6m-6 0H1"/></svg>显示偏好</h3><div class="settings-row"><div><div class="label">财务字段权限隔离</div><div class="desc">内部底价/约定账期 仅管理员可见(服务端按角色过滤)</div></div><div class="switch on" id="sw-finance" onclick="this.classList.toggle('on')"></div></div><div class="settings-row"><div><div class="label">默认销售姓名</div><div class="desc">录入客户/商机时自动带入</div></div><input type="text" id="ownerPref" value="SALES-Self" onchange="saveOwnerPref(this.value)" style="padding:6px 10px;border:1px solid var(--border);border-radius:6px;font-size:13px"></div></div>
<div class="settings-card"><h3><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><line x1="12" y1="16" x2="12" y2="12"/><line x1="12" y1="8" x2="12.01" y2="8"/></svg>关于本工作台</h3><div class="settings-row"><div class="label">版本</div><div>v1.0.0 · 货代销售SFA</div></div><div class="settings-row"><div class="label">配套数据库</div><div>4 张 · 客户档案·商机询价·订舱执行·跟进记录</div></div><div class="settings-row"><div class="label">存储</div><div>服务端 SQLite · 团队共享账套</div></div></div>
</section>
</main>
</div>
<div class="drawer-mask" id="drawerMask" onclick="document.getElementById('sidebar').classList.remove('open');this.classList.remove('open')"></div>
<div class="modal-mask" id="modal-form"><div class="modal"><div class="modal-head"><h2 id="form-title"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>新建</h2><button class="modal-close" onclick="closeModal('modal-form')"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg></button></div><div class="modal-body" id="form-body"></div><div class="modal-foot"><div class="left"><span style="font-size:11px;color:var(--ink-mute)">水印: <span id="wm-info">未保存</span></span></div><div class="right"><button class="btn btn-secondary" onclick="closeModal('modal-form')">取消</button><button class="btn btn-primary" id="form-submit">保存</button></div></div></div></div>
<div class="modal-mask" id="modal-detail"><div class="modal"><div class="modal-head"><h2 id="detail-title"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><line x1="12" y1="16" x2="12" y2="12"/></svg>详情</h2><button class="modal-close" onclick="closeModal('modal-detail')"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg></button></div><div class="modal-body" id="detail-body"></div><div class="modal-foot"><div class="left"><button class="btn btn-danger btn-sm" id="detail-delete">删除</button><button class="btn btn-secondary btn-sm" id="detail-related">查看关联</button></div><div class="right"><button class="btn btn-secondary" onclick="closeModal('modal-detail')">关闭</button><button class="btn btn-primary" id="detail-edit">编辑</button></div></div></div></div>
<div class="option-editor" id="optionEditor"><div class="option-editor-head"><h3>字段选项管理</h3><button class="modal-close" onclick="document.getElementById('optionEditor').classList.remove('open')"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg></button></div><div class="option-editor-body" id="optionEditorBody"></div><div class="option-editor-foot"><button class="btn btn-primary" style="width:100%" onclick="saveOptionEditor()">保存选项</button></div></div>
<div class="confirm-mask" id="confirmMask"><div class="confirm-box"><h3 id="cf-title">确认</h3><p id="cf-msg"></p><div class="confirm-actions"><button class="btn btn-secondary btn-sm" onclick="cfCancel()">取消</button><button class="btn btn-danger btn-sm" id="cf-ok">确认</button></div></div></div>
<div class="toast" id="toast"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="20 6 9 17 4 12"/></svg><span id="toastText">OK</span></div>
<script src="js/schemas.js"></script>
<script src="js/api.js"></script>
<script src="js/app.js"></script>
<script src="js/main.js"></script>
</body>
</html>