Files
workspace/code/fms/fms-vue/demo.html
T
2026-08-05 22:05:06 +08:00

234 lines
18 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>FMS 工作区布局 Demo</title>
<style>
:root {
--nav: #1e3031;
--nav-soft: #2a4141;
--nav-text: #d8e4e1;
--nav-muted: #91aaa5;
--canvas: #eaf0ee;
--panel: #f7faf9;
--panel-raised: #fbfcfb;
--line: #d4dfdc;
--text: #20302e;
--muted: #687875;
--teal: #16877f;
--teal-soft: #d7efeb;
--amber: #c67c2b;
--red: #c8544f;
--shadow: 0 12px 30px rgb(27 54 51 / 8%);
font-family: Inter, "PingFang SC", "Microsoft YaHei", sans-serif;
color: var(--text);
background: var(--canvas);
font-synthesis: none;
}
* { box-sizing: border-box; }
body { margin: 0; min-width: 320px; background: var(--canvas); }
button, input, select { font: inherit; }
button { cursor: pointer; }
.shell { display: flex; height: 100vh; overflow: hidden; }
.nav { width: 236px; flex: none; display: flex; flex-direction: column; color: var(--nav-text); background: var(--nav); transition: width .2s ease; }
.shell.is-collapsed .nav { width: 72px; }
.brand { height: 70px; display: flex; align-items: center; gap: 11px; padding: 0 20px; border-bottom: 1px solid rgb(255 255 255 / 9%); }
.brand-mark { width: 32px; height: 32px; display: grid; place-items: center; flex: none; border-radius: 9px; color: #17312f; background: #a8dfd6; font-size: 15px; font-weight: 800; }
.brand-copy { overflow: hidden; white-space: nowrap; }
.brand-copy strong { display: block; font-size: 14px; letter-spacing: .2px; }
.brand-copy small { display: block; margin-top: 2px; color: var(--nav-muted); font-size: 11px; }
.is-collapsed .brand { justify-content: center; padding: 0; }
.is-collapsed .brand-copy, .is-collapsed .nav-label, .is-collapsed .nav-section { display: none; }
.nav-scroll { flex: 1; padding: 18px 12px; overflow: auto; }
.nav-section { margin: 0 10px 8px; color: #718c87; font-size: 11px; letter-spacing: .08em; }
.nav-item { position: relative; display: flex; align-items: center; gap: 12px; width: 100%; height: 42px; margin: 3px 0; padding: 0 12px; border: 0; border-radius: 8px; color: var(--nav-muted); background: transparent; text-align: left; transition: .15s ease; }
.nav-item:hover { color: var(--nav-text); background: rgb(255 255 255 / 6%); }
.nav-item.active { color: #eafff9; background: var(--nav-soft); }
.nav-item.active::before { position: absolute; left: -12px; width: 3px; height: 22px; border-radius: 0 3px 3px 0; background: #80d4c9; content: ""; }
.nav-icon { width: 20px; flex: none; color: #9fc9c2; font-size: 16px; text-align: center; }
.nav-footer { padding: 12px; border-top: 1px solid rgb(255 255 255 / 9%); }
.profile { display: flex; align-items: center; gap: 10px; padding: 8px; border-radius: 8px; background: rgb(255 255 255 / 5%); }
.avatar { width: 30px; height: 30px; display: grid; place-items: center; flex: none; border-radius: 50%; color: #234240; background: #c2e9e2; font-size: 12px; font-weight: 700; }
.profile-text { overflow: hidden; white-space: nowrap; }
.profile-text strong { display: block; color: var(--nav-text); font-size: 12px; }
.profile-text small { display: block; margin-top: 2px; color: var(--nav-muted); font-size: 11px; }
.collapse-btn { width: 100%; height: 34px; margin-top: 8px; border: 0; border-radius: 7px; color: var(--nav-muted); background: transparent; font-size: 12px; text-align: left; }
.collapse-btn:hover { color: var(--nav-text); background: rgb(255 255 255 / 7%); }
.is-collapsed .collapse-btn { text-align: center; }
.workspace { min-width: 0; flex: 1; display: flex; flex-direction: column; background: var(--canvas); }
.header { height: 64px; display: flex; align-items: center; gap: 20px; flex: none; padding: 0 28px; border-bottom: 1px solid var(--line); background: rgb(247 250 249 / 92%); }
.header-context { min-width: 180px; }
.eyebrow { color: var(--muted); font-size: 11px; }
.header-context strong { display: block; margin-top: 4px; font-size: 15px; }
.search { width: min(420px, 40vw); height: 36px; display: flex; align-items: center; gap: 9px; padding: 0 12px; border: 1px solid var(--line); border-radius: 8px; color: var(--muted); background: var(--panel-raised); }
.search input { width: 100%; border: 0; outline: 0; color: var(--text); background: transparent; font-size: 13px; }
.search kbd { padding: 2px 5px; border: 1px solid var(--line); border-radius: 4px; color: var(--muted); background: var(--canvas); font-size: 10px; }
.header-actions { display: flex; align-items: center; gap: 7px; margin-left: auto; }
.icon-btn { width: 34px; height: 34px; display: grid; place-items: center; border: 0; border-radius: 7px; color: var(--muted); background: transparent; font-size: 16px; }
.icon-btn:hover { color: var(--teal); background: var(--teal-soft); }
.user-chip { height: 36px; display: flex; align-items: center; gap: 8px; padding: 0 8px; border: 1px solid var(--line); border-radius: 8px; color: var(--text); background: var(--panel-raised); font-size: 12px; }
.content { min-height: 0; flex: 1; overflow: auto; padding: 26px 30px 36px; }
.page { width: min(1440px, 100%); margin: 0 auto; }
.page-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 20px; margin-bottom: 22px; }
.breadcrumb { margin-bottom: 8px; color: var(--muted); font-size: 12px; }
h1 { margin: 0; font-size: 24px; line-height: 1.2; letter-spacing: 0; }
.page-desc { margin: 8px 0 0; color: var(--muted); font-size: 13px; }
.head-actions { display: flex; gap: 8px; }
.btn { height: 36px; padding: 0 14px; border: 1px solid var(--line); border-radius: 7px; color: var(--text); background: var(--panel-raised); font-size: 13px; }
.btn:hover { border-color: #9bc9c2; color: var(--teal); }
.btn-primary { border-color: var(--teal); color: #fff; background: var(--teal); }
.btn-primary:hover { color: #fff; background: #11736c; }
.stats { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px; margin-bottom: 16px; }
.stat { min-height: 92px; padding: 16px 18px; border: 1px solid var(--line); border-radius: 10px; background: var(--panel); }
.stat-label { color: var(--muted); font-size: 12px; }
.stat-value { margin-top: 10px; font-size: 23px; font-weight: 700; }
.stat-meta { margin-top: 4px; color: var(--teal); font-size: 11px; }
.stat-meta.warn { color: var(--amber); }
.toolbar { display: flex; align-items: center; justify-content: space-between; gap: 14px; padding: 12px 14px; border: 1px solid var(--line); border-bottom: 0; border-radius: 10px 10px 0 0; background: var(--panel); }
.filters { display: flex; flex: 1; flex-wrap: wrap; gap: 8px; }
.field { height: 34px; min-width: 150px; padding: 0 10px; border: 1px solid var(--line); border-radius: 6px; outline: 0; color: var(--text); background: var(--panel-raised); font-size: 12px; }
.field:focus { border-color: var(--teal); box-shadow: 0 0 0 3px rgb(22 135 127 / 12%); }
.toolbar-tools { display: flex; gap: 6px; }
.toolbar-tools .btn { height: 34px; padding: 0 10px; }
.table-wrap { overflow: auto; border: 1px solid var(--line); border-radius: 0 0 10px 10px; background: var(--panel-raised); box-shadow: var(--shadow); }
table { width: 100%; min-width: 760px; border-collapse: collapse; font-size: 13px; }
th { height: 42px; padding: 0 15px; color: var(--muted); background: #eaf1ef; font-size: 11px; font-weight: 600; text-align: left; white-space: nowrap; }
td { height: 50px; padding: 0 15px; border-top: 1px solid #e4ebe9; white-space: nowrap; }
tr:hover td { background: #f0f7f5; }
.name-cell { display: flex; align-items: center; gap: 9px; }
.entity { width: 28px; height: 28px; display: grid; place-items: center; border-radius: 7px; color: var(--teal); background: var(--teal-soft); font-size: 11px; font-weight: 700; }
.name-cell strong { display: block; font-size: 13px; }
.name-cell small { display: block; margin-top: 2px; color: var(--muted); font-size: 11px; }
.status { display: inline-flex; align-items: center; gap: 5px; color: #277d66; font-size: 12px; }
.status::before { width: 6px; height: 6px; border-radius: 50%; background: currentColor; content: ""; }
.status.warn { color: var(--amber); }
.row-action { border: 0; color: var(--teal); background: transparent; font-size: 12px; }
.row-action:hover { text-decoration: underline; }
.table-foot { display: flex; align-items: center; justify-content: space-between; padding: 12px 15px; color: var(--muted); font-size: 12px; }
.pagination { display: flex; gap: 5px; }
.page-btn { width: 28px; height: 28px; border: 1px solid var(--line); border-radius: 5px; color: var(--muted); background: var(--panel-raised); }
.page-btn.active { border-color: var(--teal); color: #fff; background: var(--teal); }
.toast { position: fixed; right: 24px; bottom: 24px; max-width: 300px; padding: 11px 14px; border: 1px solid #a8d9d1; border-radius: 8px; color: #225e58; background: #e5f5f1; box-shadow: var(--shadow); font-size: 13px; opacity: 0; transform: translateY(8px); pointer-events: none; transition: .2s ease; }
.toast.show { opacity: 1; transform: translateY(0); }
@media (max-width: 900px) {
.nav { width: 72px; }
.brand { justify-content: center; padding: 0; }
.brand-copy, .nav-label, .nav-section, .profile-text { display: none; }
.profile { justify-content: center; }
.header { gap: 10px; padding: 0 16px; }
.header-context { min-width: 100px; }
.search { width: 34px; padding: 0 9px; }
.search input, .search kbd { display: none; }
.content { padding: 20px 16px 28px; }
.stats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 560px) {
.header-context { display: none; }
.page-head { align-items: flex-start; flex-direction: column; }
.head-actions { width: 100%; }
.head-actions .btn { flex: 1; }
.stats { gap: 8px; }
.stat { padding: 13px; }
.stat-value { font-size: 20px; }
.toolbar { align-items: stretch; flex-direction: column; }
.field { width: 100%; }
}
</style>
</head>
<body>
<div class="shell" id="shell">
<aside class="nav">
<div class="brand">
<div class="brand-mark">F</div>
<div class="brand-copy"><strong>FMS 工作台</strong><small>运营管理控制台</small></div>
</div>
<div class="nav-scroll">
<div class="nav-section">工作区</div>
<button class="nav-item active" data-nav="overview"><span class="nav-icon">⌂</span><span class="nav-label">工作台</span></button>
<button class="nav-item" data-nav="partners"><span class="nav-icon">▦</span><span class="nav-label">合作伙伴</span></button>
<button class="nav-item" data-nav="contacts"><span class="nav-icon">◌</span><span class="nav-label">联系人</span></button>
<div class="nav-section" style="margin-top: 25px">系统</div>
<button class="nav-item" data-nav="modules"><span class="nav-icon">◇</span><span class="nav-label">模块管理</span></button>
<button class="nav-item" data-nav="users"><span class="nav-icon">◎</span><span class="nav-label">用户与权限</span></button>
<button class="nav-item" data-nav="logs"><span class="nav-icon">≡</span><span class="nav-label">操作日志</span></button>
</div>
<div class="nav-footer">
<div class="profile"><div class="avatar">林</div><div class="profile-text"><strong>林晓明</strong><small>系统管理员</small></div></div>
<button class="collapse-btn" id="collapseBtn">‹&nbsp; 收起导航</button>
</div>
</aside>
<section class="workspace">
<header class="header">
<div class="header-context"><div class="eyebrow">当前组织</div><strong>华东运营中心</strong></div>
<label class="search"><span>⌕</span><input placeholder="搜索模块、记录或命令" /><kbd>Ctrl K</kbd></label>
<div class="header-actions">
<button class="icon-btn" title="通知">♧</button>
<button class="icon-btn" title="帮助">?</button>
<button class="user-chip"><span class="avatar">林</span><span>林晓明</span><span>⌄</span></button>
</div>
</header>
<main class="content">
<div class="page">
<div class="page-head">
<div><div class="breadcrumb">工作区 / 总览</div><h1>工作台</h1><p class="page-desc">快速了解业务状态,并从最近工作继续。</p></div>
<div class="head-actions"><button class="btn" id="refreshBtn">↻ 刷新数据</button><button class="btn btn-primary" id="createBtn">+ 新建记录</button></div>
</div>
<section class="stats">
<div class="stat"><div class="stat-label">合作伙伴总数</div><div class="stat-value">1,284</div><div class="stat-meta">↑ 8.4% 较上月</div></div>
<div class="stat"><div class="stat-label">本月新增</div><div class="stat-value">86</div><div class="stat-meta">↑ 12 条待审核</div></div>
<div class="stat"><div class="stat-label">待处理事项</div><div class="stat-value">23</div><div class="stat-meta warn">需要关注</div></div>
<div class="stat"><div class="stat-label">系统可用率</div><div class="stat-value">99.98%</div><div class="stat-meta">运行正常</div></div>
</section>
<section>
<div class="toolbar">
<div class="filters"><input class="field" placeholder="搜索名称 / 编号" /><select class="field"><option>全部状态</option><option>正常</option><option>待审核</option></select><select class="field"><option>全部区域</option><option>华东</option><option>华南</option></select></div>
<div class="toolbar-tools"><button class="btn" id="advancedBtn">更多筛选</button><button class="btn" id="columnsBtn">列设置</button></div>
</div>
<div class="table-wrap">
<table>
<thead><tr><th>合作伙伴</th><th>区域</th><th>联系人</th><th>最近更新</th><th>状态</th><th>操作</th></tr></thead>
<tbody>
<tr><td><div class="name-cell"><span class="entity">海</span><span><strong>海岳供应链有限公司</strong><small>PT-20240128</small></span></div></td><td>华东</td><td>周敏</td><td>今天 10:32</td><td><span class="status">正常</span></td><td><button class="row-action">查看详情</button></td></tr>
<tr><td><div class="name-cell"><span class="entity">晨</span><span><strong>晨光科技(苏州)</strong><small>PT-20240119</small></span></div></td><td>华东</td><td>王立</td><td>昨天 16:08</td><td><span class="status">正常</span></td><td><button class="row-action">查看详情</button></td></tr>
<tr><td><div class="name-cell"><span class="entity">南</span><span><strong>南方精密制造</strong><small>PT-20231207</small></span></div></td><td>华南</td><td>陈希</td><td>08-03 14:21</td><td><span class="status warn">待审核</span></td><td><button class="row-action">查看详情</button></td></tr>
<tr><td><div class="name-cell"><span class="entity">远</span><span><strong>远洲物流服务中心</strong><small>PT-20231122</small></span></div></td><td>华北</td><td>李然</td><td>08-01 09:45</td><td><span class="status">正常</span></td><td><button class="row-action">查看详情</button></td></tr>
</tbody>
</table>
<div class="table-foot"><span>显示 1-4 条,共 1,284 条</span><div class="pagination"><button class="page-btn active">1</button><button class="page-btn">2</button><button class="page-btn">3</button><button class="page-btn">›</button></div></div>
</div>
</section>
</div>
</main>
</section>
</div>
<div class="toast" id="toast"></div>
<script>
const shell = document.getElementById("shell");
const toast = document.getElementById("toast");
let toastTimer;
function showToast(message) { toast.textContent = message; toast.classList.add("show"); clearTimeout(toastTimer); toastTimer = setTimeout(() => toast.classList.remove("show"), 2200); }
document.querySelectorAll(".nav-item").forEach((item) => item.addEventListener("click", () => { document.querySelectorAll(".nav-item").forEach((nav) => nav.classList.remove("active")); item.classList.add("active"); showToast(`已切换到${item.textContent.trim()}`); }));
document.getElementById("refreshBtn").addEventListener("click", () => showToast("数据已刷新"));
document.getElementById("createBtn").addEventListener("click", () => showToast("打开新建记录面板"));
document.getElementById("advancedBtn").addEventListener("click", () => showToast("高级筛选可以在抽屉中展开"));
document.getElementById("columnsBtn").addEventListener("click", () => showToast("打开列设置"));
document.getElementById("collapseBtn").addEventListener("click", () => { shell.classList.toggle("is-collapsed"); document.getElementById("collapseBtn").innerHTML = shell.classList.contains("is-collapsed") ? "›" : "‹&nbsp; 收起导航"; });
document.querySelector(".user-chip").addEventListener("click", () => showToast("打开账户菜单"));
</script>
</body>
</html>