refactor(客户管理): 完成客户管理模块UI与架构全面调整

1.  调整菜单与路由:重命名客户信息/客户账号为客户档案管理/客户小程序授权管理,移除客户建筑/房间路由,新增空间拓扑路由
2.  后端新增客户统计接口`/customers/stats`,前端同步API与类型定义
3.  重构客户档案与小程序授权页面,仅保留数据库支持字段,移除无支撑功能
4.  新增空间拓扑页面,合并建筑与房间管理为树形拓扑视图
5.  更新数据库种子数据与权限配置,清理废弃菜单与绑定关系
6.  补充UI设计文档与规范说明
This commit is contained in:
andyesfly committed 2026-09-09 17:31:24 +08:00
1 parent 2a06cfea6d
commit c60caa4770
35 files changed
+7524 -1961

No files matched your search

@@ -0,0 +1,200 @@
---
name: Industrial Precision
colors:
surface: '#ffffff'
surface-dim: '#ccdbf1'
surface-bright: '#f8f9ff'
surface-container-lowest: '#ffffff'
surface-container-low: '#eef4ff'
surface-container: '#e5efff'
surface-container-high: '#dbe9ff'
surface-container-highest: '#d5e4fa'
on-surface: '#0d1c2c'
on-surface-variant: '#424655'
inverse-surface: '#233142'
inverse-on-surface: '#e9f1ff'
outline: '#727787'
outline-variant: '#c2c6d8'
surface-tint: '#0056d2'
primary: '#0054cd'
on-primary: '#ffffff'
primary-container: '#136bfb'
on-primary-container: '#fefcff'
inverse-primary: '#b2c5ff'
secondary: '#712ae2'
on-secondary: '#ffffff'
secondary-container: '#8a4cfc'
on-secondary-container: '#fffbff'
tertiary: '#00685f'
on-tertiary: '#ffffff'
tertiary-container: '#008378'
on-tertiary-container: '#f4fffc'
error: '#ba1a1a'
on-error: '#ffffff'
error-container: '#ffdad6'
on-error-container: '#93000a'
primary-fixed: '#dae2ff'
primary-fixed-dim: '#b2c5ff'
on-primary-fixed: '#001847'
on-primary-fixed-variant: '#0040a1'
secondary-fixed: '#eaddff'
secondary-fixed-dim: '#d2bbff'
on-secondary-fixed: '#25005a'
on-secondary-fixed-variant: '#5a00c6'
tertiary-fixed: '#89f5e7'
tertiary-fixed-dim: '#6bd8cb'
on-tertiary-fixed: '#00201d'
on-tertiary-fixed-variant: '#005049'
background: '#f8f9ff'
on-background: '#0d1c2c'
surface-variant: '#d5e4fa'
bg-page: '#eef3f8'
text-muted: '#5b6b7e'
border-rule: '#dbe4ee'
status-warn: '#e0852b'
status-error: '#dc2626'
accent-subtle: rgba(29,111,255,0.08)
typography:
display-lg:
fontFamily: hankenGrotesk
fontSize: 32px
fontWeight: '700'
lineHeight: 40px
headline-md:
fontFamily: hankenGrotesk
fontSize: 23px
fontWeight: '700'
lineHeight: 28px
title-sm:
fontFamily: hankenGrotesk
fontSize: 17px
fontWeight: '700'
lineHeight: 24px
body-md:
fontFamily: hankenGrotesk
fontSize: 15px
fontWeight: '400'
lineHeight: 24px
label-bold:
fontFamily: hankenGrotesk
fontSize: 13px
fontWeight: '700'
lineHeight: 16px
data-mono:
fontFamily: jetbrainsMono
fontSize: 12px
fontWeight: '500'
lineHeight: 16px
caption-sm:
fontFamily: hankenGrotesk
fontSize: 12px
fontWeight: '700'
lineHeight: 14px
headline-md-mobile:
fontFamily: hankenGrotesk
fontSize: 20px
fontWeight: '700'
lineHeight: 26px
rounded:
sm: 0.25rem
DEFAULT: 0.5rem
md: 0.75rem
lg: 1rem
xl: 1.5rem
full: 9999px
spacing:
base: 4px
xs: 8px
sm: 12px
md: 16px
lg: 24px
xl: 40px
container-max: 1200px
gutter: 16px
---
## Brand & Style
The design system is engineered for the **Xintong Smart Power Operation Management APP**, targeting power engineers and grid operators. The brand personality is **Professional, Efficient, and Industrial Tech**. It emphasizes reliability through a structured, high-density interface that transforms complex electrical data into actionable insights.
The design style is a blend of **Corporate Modern** and **Information-Dense Minimalism**. It utilizes a "Layered Surface" approach where data is organized into logical card blocks, using subtle elevations and clear semantic color-coding to denote system status. The aesthetic is clean and functional, avoiding decorative elements in favor of technical precision and rapid scanability.
- **Professionalism:** High-contrast typography and a restrained color palette.
- **Efficiency:** Condensed layouts that prioritize data visualization and task status.
- **Reliability:** Solid borders, consistent spacing, and clear state indicators.
## Colors
The color architecture is strictly functional, mapping specifically to the operation layers of the power management system.
- **Primary (Deep Blue):** Reserved for core branding, navigation, and "Client" layer interactions.
- **Secondary (Purple):** Dedicated to "Gateway" operations and task-specific management.
- **Tertiary (Teal):** Used for "Service" layer success states and optimized performance indicators.
- **Neutral (Ink):** Used for primary text to ensure maximum legibility against light surfaces.
**Semantic Usage:**
- Use **status-warn (Amber)** for non-critical alerts or data synchronization states.
- Use **status-error (Red)** for critical power failures or permission denials.
- The **bg-page** provides a soft, low-strain canvas for long-duration monitoring, while **surface** (White) distinguishes interactive cards and data containers.
## Typography
This design system uses **Hanken Grotesk** as the primary typeface for its sharp, contemporary feel that bridges the gap between industrial and tech. **JetBrains Mono** is employed for technical data, device IDs, and numerical values to emphasize the system's engineering DNA.
- **Hierarchy:** Use `display-lg` for dashboard summaries. `title-sm` is the default for card headers.
- **Data Visualization:** All tabular data and technical strings must use `data-mono` for character alignment and clarity.
- **Mobile Adaptation:** For mobile screens, headlines should scale down to `headline-md-mobile` to maintain visual balance while preserving authority.
## Layout & Spacing
The layout utilizes a **Flexible Grid System** with a focus on logical grouping through card-based containment.
- **Grid:** A 12-column grid is used for desktop views, transitioning to a single-column stacked layout for mobile.
- **Rhythm:** An 8px-based spacing scale ensures vertical consistency. Use `lg (24px)` for outer card padding and `md (16px)` for internal element spacing.
- **Mobile Margins:** Standard mobile side margins are set to `md (16px)` to maximize screen real estate for dense data tables.
- **Sectioning:** Distinct operational modules should be separated by `xl (40px)` of vertical space to prevent cognitive overload.
## Elevation & Depth
This design system conveys hierarchy through **Tonal Layering** and **Subtle Ambient Shadows**. We avoid heavy skeuomorphism in favor of a "Flat-Plus" approach.
- **Base Layer:** The page background (`bg-page`) sits at the lowest elevation.
- **Mid Layer (Cards):** UI cards use a white surface with a subtle shadow (`0 4px 14px rgba(0,0,0,.07)`) to appear slightly lifted.
- **Interactive Layer:** On hover or active state, cards may transition to a higher elevation (`0 8px 28px rgba(0,0,0,.1)`) with a slight upward translation of -2px.
- **Overlays:** Modals and dropdowns use the highest z-index with a distinct backdrop blur to maintain focus on the task at hand.
- **Gradients:** Use soft radial gradients in the background (Blue/Purple) to create environmental depth without interfering with content legibility.
## Shapes
The shape language is **Rounded**, balancing industrial rigidity with modern software approachability.
- **Cards & Sections:** Use the standard `rounded-lg (1rem)` for primary containers.
- **Nodes & Blocks:** Architecture and data nodes use `rounded (0.5rem)` to fit more compactly within layouts.
- **Interactive Elements:** Buttons and tags use a "Pill-shape" (`rounded-xl` or 999px) to distinguish them from structural containers.
- **Borders:** Use `1px solid` with the `border-rule` color for most containers. Active states or primary focus areas may increase to `1.5px`.
## Components
**Buttons:**
- **Primary:** Solid `primary_color` with white text. Pill-shaped.
- **Secondary:** Transparent with `primary_color` border or subtle purple tint for operation tasks.
- **Danger:** Solid `status-error` for irreversible actions.
**Cards:**
- White background, `1px` border-rule, and `rounded-lg` corners.
- Headers should have a `18px` internal padding and a bottom border to separate from the content body.
**Input Fields:**
- Soft white background with `1px` border.
- Focused states should use a `primary_color` border with a subtle outer glow.
**Chips & Tags:**
- Used for status (e.g., "Active", "Offline").
- Backgrounds should use `8% opacity` versions of the semantic colors (Blue, Green, Red) with bolded text in the 100% opacity color.
**Data Visualization:**
- Charts should use the primary blue and secondary purple as the main data series colors.
- Use `data-mono` for all axis labels and tooltips to ensure technical accuracy.
**Status Indicators:**
- Small `7px` circular dots used within lists or architecture nodes to show real-time connectivity status.
@@ -0,0 +1,177 @@
<!DOCTYPE html><html lang="zh-CN" style=""><head><meta charset="utf-8"><meta content="width=device-width, initial-scale=1.0" name="viewport"><link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:wght,FILL@100..700,0..1&amp;display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=hankenGrotesk:wght@100..900&amp;display=swap" rel="stylesheet"><style>@layer base{html,body{margin:0;padding:0;}body{overscroll-behavior:none;}main>:first-child{margin-top:0!important;}main>:last-child{margin-bottom:0!important;}}::-webkit-scrollbar{display:none;}</style><script src="https://cdn.tailwindcss.com?plugins=forms,container-queries"></script><script id="tailwind-config">tailwind.config={"darkMode":"class","theme":{"extend":{"colors":{"surface-container-low":"#eef4ff","inverse-primary":"#b2c5ff","on-tertiary-fixed":"#00201d","on-error-container":"#93000a","primary":"#0054cd","on-secondary-container":"#fffbff","secondary-fixed-dim":"#d2bbff","on-tertiary-container":"#f4fffc","border-rule":"#dbe4ee","error":"#ba1a1a","surface-bright":"#f8f9ff","on-error":"#ffffff","tertiary-fixed":"#89f5e7","tertiary-container":"#008378","text-muted":"#5b6b7e","outline-variant":"#c2c6d8","inverse-surface":"#233142","surface":"#ffffff","on-primary":"#ffffff","status-error":"#dc2626","on-primary-container":"#fefcff","status-warn":"#e0852b","surface-container":"#e5efff","error-container":"#ffdad6","bg-page":"#eef3f8","primary-fixed":"#dae2ff","on-tertiary":"#ffffff","on-secondary":"#ffffff","tertiary-fixed-dim":"#6bd8cb","surface-variant":"#d5e4fa","on-primary-fixed":"#001847","surface-container-lowest":"#ffffff","on-background":"#0d1c2c","secondary":"#712ae2","on-primary-fixed-variant":"#0040a1","on-tertiary-fixed-variant":"#005049","tertiary":"#00685f","secondary-container":"#8a4cfc","surface-tint":"#0056d2","inverse-on-surface":"#e9f1ff","on-surface":"#0d1c2c","surface-container-high":"#dbe9ff","on-secondary-fixed-variant":"#5a00c6","background":"#f8f9ff","surface-container-highest":"#d5e4fa","primary-fixed-dim":"#b2c5ff","outline":"#727787","secondary-fixed":"#eaddff","accent-subtle":"rgba(29,111,255,0.08)","primary-container":"#136bfb","on-surface-variant":"#424655","surface-dim":"#ccdbf1","on-secondary-fixed":"#25005a"},"borderRadius":{"DEFAULT":"0.25rem","lg":"0.5rem","xl":"0.75rem","full":"9999px"},"spacing":{"gutter":"16px","sm":"12px","base":"4px","xl":"40px","lg":"24px","container-max":"1200px","md":"16px","xs":"8px"},"fontFamily":{"data-mono":["jetbrainsMono"],"headline-md-mobile":["hankenGrotesk"],"body-md":["hankenGrotesk"],"label-bold":["hankenGrotesk"],"display-lg":["hankenGrotesk"],"caption-sm":["hankenGrotesk"],"headline-md":["hankenGrotesk"],"title-sm":["hankenGrotesk"]},"fontSize":{"data-mono":["12px",{"lineHeight":"16px","fontWeight":"500"}],"headline-md-mobile":["20px",{"lineHeight":"26px","fontWeight":"700"}],"body-md":["15px",{"lineHeight":"24px","fontWeight":"400"}],"label-bold":["13px",{"lineHeight":"16px","fontWeight":"700"}],"display-lg":["32px",{"lineHeight":"40px","fontWeight":"700"}],"caption-sm":["12px",{"lineHeight":"14px","fontWeight":"700"}],"headline-md":["23px",{"lineHeight":"28px","fontWeight":"700"}],"title-sm":["17px",{"lineHeight":"24px","fontWeight":"700"}]}}}}</script></head><body class="bg-bg-page font-body-md text-body-md text-on-surface antialiased"><aside class="fixed left-0 top-0 h-full w-64 bg-inverse-surface z-50 flex flex-col justify-between shadow-[0_1px_8px_rgba(0,0,0,0.04)]"><div class="flex flex-col"><div class="h-16 px-md flex items-center gap-xs bg-inverse-surface"><img alt="Xintong Power logo, industrial technology style, electric bolt and smart connectivity icon, professional, modern, high precision, deep blue palette.. Design context: - Primary color: #1d6fff
- Font: hankenGrotesk
- Mode: light
- Roundness: rounded-md
. The logo should be visually consistent with these brand tokens." class="h-8 w-auto object-contain" src="https://lh3.googleusercontent.com/aida/AEtjO1VpTaoSkZCyImEBOewVJbw8cN4OK_4XN0nYWf-d6prkZBdtwy8_i4RFQPli9kdGdwctP8bUQgQk3yLHoUJzYawS5_rm4a_iDAdFxgEcJm0oLqXiMHJ4KIqg8lTf2EdzS9w08_C-fdfalXZmfY_o9mNwGjr7KB5oPG_MHTU9vVSLrJTz4e0Lv7VNEf16_F81a5fH6QJk6fVBQhWTCesvcyO9LLqZ3nOoMdpFh4_7nHayUU88Ni14Re8Q80c"><div class="flex flex-col ml-xs"><span class="font-label-bold text-label-bold text-inverse-on-surface tracking-wide">鑫潼智电</span><span class="font-caption-sm text-caption-sm text-inverse-primary tracking-wider">XT-POWER OS</span></div></div><nav class="flex flex-col gap-base px-sm pt-md" data-active-classes="bg-primary text-on-primary font-label-bold rounded-lg shadow-sm"><a class="flex items-center gap-sm px-sm py-xs rounded-lg text-inverse-on-surface/80 hover:bg-inverse-surface/80 hover:text-inverse-on-surface transition-colors" data-path="workbench" href="#"><span class="material-symbols-outlined text-[20px]">space_dashboard</span><span class="font-body-md text-body-md">运营工作台</span></a><a aria-current="page" class="flex items-center gap-sm px-sm py-xs transition-colors bg-primary text-on-primary font-label-bold rounded-lg shadow-sm" data-path="customer-management" href="#"><span class="material-symbols-outlined text-[20px]">groups</span><span class="font-body-md text-body-md">客户管理</span></a><a class="flex items-center gap-sm px-sm py-xs rounded-lg text-inverse-on-surface/80 hover:bg-inverse-surface/80 hover:text-inverse-on-surface transition-colors" data-path="project-management" href="#"><span class="material-symbols-outlined text-[20px]">lan</span><span class="font-body-md text-body-md">项目管理</span></a><a class="flex items-center gap-sm px-sm py-xs rounded-lg text-inverse-on-surface/80 hover:bg-inverse-surface/80 hover:text-inverse-on-surface transition-colors" data-path="dispatch-orders" href="#"><span class="material-symbols-outlined text-[20px]">assignment</span><span class="font-body-md text-body-md">运营派单</span></a><a class="flex items-center gap-sm px-sm py-xs rounded-lg text-inverse-on-surface/80 hover:bg-inverse-surface/80 hover:text-inverse-on-surface transition-colors" data-path="device-monitoring" href="#"><span class="material-symbols-outlined text-[20px]">bolt</span><span class="font-body-md text-body-md">设备监控</span></a><a class="flex items-center gap-sm px-sm py-xs rounded-lg text-inverse-on-surface/80 hover:bg-inverse-surface/80 hover:text-inverse-on-surface transition-colors" data-path="statistics-reports" href="#"><span class="material-symbols-outlined text-[20px]">analytics</span><span class="font-body-md text-body-md">统计报表</span></a><a class="flex items-center gap-sm px-sm py-xs rounded-lg text-inverse-on-surface/80 hover:bg-inverse-surface/80 hover:text-inverse-on-surface transition-colors" data-path="system-settings" href="#"><span class="material-symbols-outlined text-[20px]">settings</span><span class="font-body-md text-body-md">系统管理</span></a></nav></div><div class="p-sm m-sm rounded-lg bg-surface-container-low/10 flex flex-col gap-xs"><div class="flex items-center justify-between"><span class="font-caption-sm text-caption-sm text-inverse-on-surface/70">边缘网关通信</span><span class="flex h-2 w-2 relative"><span class="animate-ping absolute inline-flex h-full w-full rounded-full bg-tertiary-fixed opacity-75"></span><span class="relative inline-flex rounded-full h-2 w-2 bg-tertiary-fixed"></span></span></div><div class="flex items-baseline justify-between"><span class="font-data-mono text-data-mono text-tertiary-fixed">在线 99.98%</span><span class="font-caption-sm text-caption-sm text-inverse-on-surface/50">ICC链路</span></div></div></aside><div class="pl-64"><header class="fixed top-0 left-64 right-0 h-16 bg-surface/95 backdrop-blur-xl shadow-[0_1px_8px_rgba(0,0,0,0.04)] z-40 flex items-center justify-between px-lg"><div class="flex items-center gap-md"><div class="flex items-center gap-xs px-sm py-base rounded-full bg-surface-container-low"><span class="w-2 h-2 rounded-full bg-tertiary"></span><span class="font-caption-sm text-caption-sm text-tertiary">ICC 实时数据同步正常</span></div><div class="relative flex items-center"><span class="material-symbols-outlined absolute left-sm text-text-muted text-[18px]">search</span><input class="w-80 h-9 pl-xl pr-sm rounded-lg bg-surface-container-low text-on-surface placeholder:text-text-muted placeholder:text-[13px] text-body-md outline-none focus:bg-surface focus:shadow-sm transition-all" placeholder="按项目号 / 客户 / 变电站 / 工单号检索..." type="text"></div></div><div class="flex items-center gap-md"><button class="relative flex items-center justify-center w-9 h-9 rounded-lg hover:bg-surface-container-low hover:text-on-surface text-on-surface-variant transition-colors" type="button"><span class="material-symbols-outlined text-[20px]">notificatLine truncated
<!-- Top Command & KPI Header Section -->
<div class="px-lg pt-lg pb-lg flex flex-col gap-lg bg-surface/60 backdrop-blur-md">
<!-- Breadcrumb & Main Actions -->
<div class="flex flex-wrap items-center justify-between gap-md">
<div class="flex flex-col">
<div class="flex items-center gap-xs font-caption-sm text-caption-sm text-text-muted mb-base">
<span class="">运营管控体系</span>
<span class="material-symbols-outlined text-[14px]">chevron_right</span>
<span class="">L3 业务服务层</span>
<span class="material-symbols-outlined text-[14px]">chevron_right</span>
<span class="text-primary font-label-bold">客户档案与空间拓扑</span>
</div>
<div class="flex items-center gap-sm">
<h1 class="font-headline-md text-headline-md text-on-surface tracking-tight">客户档案管理</h1>
<span class="px-2.5 py-1 rounded-full bg-primary/10 text-primary font-data-mono text-data-mono font-medium">Customer Directory &amp; Tenant Topology</span>
</div>
<p class="font-body-md text-body-md text-text-muted mt-1.5 max-w-3xl leading-relaxed">
集中统管全省电力托管单位、用电建筑空间三级拓扑、大华 ICC 边缘物联网设备映射及终端微信小程序访问权限。
</p>
</div>
<!-- Action Buttons -->
<div class="flex items-center gap-sm">
<button class="h-10 px-md rounded-full bg-surface-container text-on-surface hover:bg-surface-variant font-label-bold text-label-bold flex items-center gap-xs shadow-sm transition-all duration-150" type="button">
<span class="material-symbols-outlined text-[18px]">file_download</span>
<span class="">导出客户档案</span>
</button>
<button class="h-10 px-md rounded-full bg-surface-container text-primary hover:bg-surface-container-high font-label-bold text-label-bold flex items-center gap-xs shadow-sm transition-all duration-150" type="button">
<span class="material-symbols-outlined text-[18px] animate-spin" id="syncIcon">sync</span>
<span class="">从大华 ICC 同步</span>
</button>
<button class="h-10 px-lg rounded-full bg-primary hover:bg-primary-container text-on-primary font-label-bold text-label-bold flex items-center gap-xs shadow-md hover:shadow-lg transition-all duration-200" type="button">
<span class="material-symbols-outlined text-[18px]">add</span>
<span class="">+ 新增托管客户</span>
</button>
</div>
</div>
<!-- 4 Industrial Metric KPI Cards -->
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4 mt-1"><div class="p-4 rounded-xl bg-surface shadow-sm border border-border-rule/40 flex items-center justify-between"><div class="flex flex-col gap-1"><span class="font-caption-sm text-caption-sm text-text-muted">托管客户总数</span><div class="flex items-baseline gap-2"><span class="font-headline-md text-headline-md font-bold text-on-surface tracking-tight">128</span><span class="font-caption-sm text-caption-sm text-text-muted">家</span></div><div class="flex items-center gap-1 font-caption-sm text-[12px] text-tertiary font-medium"><span class="material-symbols-outlined text-[14px]">trending_up</span><span class="">本月新增 +4 · 覆盖全省 8 地市</span></div></div><div class="w-10 h-10 rounded-xl bg-primary/10 text-primary flex items-center justify-center shrink-0"><span class="material-symbols-outlined text-[22px]">domain</span></div></div><div class="p-4 rounded-xl bg-surface shadow-sm border border-border-rule/40 flex items-center justify-between"><div class="flex flex-col gap-1"><span class="font-caption-sm text-caption-sm text-text-muted">接入智能建筑数</span><div class="flex items-baseline gap-2"><span class="font-headline-md text-headline-md font-bold text-on-surface tracking-tight">342</span><span class="font-caption-sm text-caption-sm text-text-muted">栋</span></div><div class="flex items-center gap-1 font-caption-sm text-[12px] text-text-muted"><span class="material-symbols-outlined text-[14px] text-primary">verified</span><span class="">高校·三甲·园区 100% 空间建模</span></div></div><div class="w-10 h-10 rounded-xl bg-secondary/10 text-secondary flex items-center justify-center shrink-0"><span class="material-symbols-outlined text-[22px]">apartment</span></div></div><div class="p-4 rounded-xl bg-surface shadow-sm border border-border-rule/40 flex items-center justify-between"><div class="flex flex-col gap-1"><span class="font-caption-sm text-caption-sm text-text-muted">监控配电回路</span><div class="flex items-baseline gap-2"><span class="font-headline-md text-headline-md font-bold text-on-surface tracking-tight">3,676</span><span class="font-caption-sm text-caption-sm text-text-muted">路</span></div><div class="flex items-center gap-1 font-caption-sm text-[12px] text-tertiary font-medium"><span class="w-2 h-2 rounded-full bg-tertiary inline-block mr-0.5"></span><span class="">在线监测率 99.1% · 34 闭环</span></div></div><div class="w-10 h-10 rounded-xl bg-tertiary/10 text-tertiary flex items-center justify-center shrink-0"><span class="material-symbols-outlined text-[22px]">bolt</span></div></div><div class="p-4 rounded-xl bg-surface shadow-sm border border-border-rule/40 flex items-center justify-between"><div class="flex flex-col gap-1"><span class="font-caption-sm text-caption-sm text-text-muted">小程序授权客户</span><div class="flex items-baseline gap-2"><span class="font-headline-md text-headline-md font-bold text-on-surface tracking-tight">216</span><span class="font-caption-sm text-caption-sm text-text-muted">人</span></div><div class="flex items-center gap-1 font-caption-sm text-[12px] text-text-muted"><span class="material-symbols-outlined text-[14px] text-secondary">smartphone</span><span class="">7日活跃 189 人 · JWT认证正常</span></div></div><div class="w-10 h-10 rounded-xl bg-surface-container text-on-surface-variant flex items-center justify-center shrink-0"><span class="material-symbols-outlined text-[22px]">group</span></div></div></div></div>
<!-- Main Work Area (Filter + Split View) -->
<div class="p-lg flex flex-col gap-lg">
<!-- Filter Card -->
<div class="rounded-xl bg-surface p-5 shadow-sm flex flex-col gap-4">
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-5 gap-4">
<!-- Search Keyword -->
<div class="flex flex-col gap-1.5">
<label class="font-caption-sm text-caption-sm text-text-muted">关键词检索</label>
<div class="relative flex items-center">
<span class="material-symbols-outlined absolute left-sm text-text-muted text-[18px]">search</span>
<input class="w-full h-10 pl-xl pr-sm rounded-lg bg-surface-container-low text-on-surface placeholder:text-text-muted text-body-md outline-none focus:ring-1 focus:ring-primary focus:bg-surface transition-all" placeholder="客户名称 / 统一代码 / 负责人" type="text" value="武汉软件工程">
</div>
</div>
<!-- Province / Region Cascader -->
<div class="flex flex-col gap-1.5">
<label class="font-caption-sm text-caption-sm text-text-muted">所属行政区划</label>
<div class="relative flex items-center">
<span class="material-symbols-outlined absolute left-sm text-text-muted text-[18px]">location_on</span>
<select class="w-full h-10 pl-xl pr-md rounded-lg bg-surface-container-low text-on-surface text-body-md outline-none appearance-none focus:ring-1 focus:ring-primary">
<option>全省范围 (湖北省)</option>
<option selected="">武汉市 · 江夏区</option>
<option>武汉市 · 洪山区</option>
<option>武汉市 · 武昌区</option>
<option>宜昌市 · 西陵区</option>
<option>襄阳市 · 襄城区</option>
</select>
<span class="material-symbols-outlined absolute right-sm text-text-muted pointer-events-none text-[18px]">expand_more</span>
</div>
</div>
<!-- Industry Type -->
<div class="flex flex-col gap-1.5">
<label class="font-caption-sm text-caption-sm text-text-muted">行业属性</label>
<div class="relative flex items-center">
<span class="material-symbols-outlined absolute left-sm text-text-muted text-[18px]">category</span>
<select class="w-full h-10 pl-xl pr-md rounded-lg bg-surface-container-low text-on-surface text-body-md outline-none appearance-none focus:ring-1 focus:ring-primary">
<option>全部行业大类</option>
<option selected="">教育科研 (高校 / 职业院校)</option>
<option>医疗卫生 (三甲 / 专科)</option>
<option>高新产业园 (光谷)</option>
<option>商业综合体</option>
<option>党政机关 / 市政公用</option>
</select>
<span class="material-symbols-outlined absolute right-sm text-text-muted pointer-events-none text-[18px]">expand_more</span>
</div>
</div>
<!-- Contract Status -->
<div class="flex flex-col gap-1.5">
<label class="font-caption-sm text-caption-sm text-text-muted">托管服务状态</label>
<div class="relative flex items-center">
<span class="material-symbols-outlined absolute left-sm text-text-muted text-[18px]">verified</span>
<select class="w-full h-10 pl-xl pr-md rounded-lg bg-surface-container-low text-on-surface text-body-md outline-none appearance-none focus:ring-1 focus:ring-primary">
<option>全部状态</option>
<option selected="">正常托管中</option>
<option>方案施工 / 网关调试</option>
<option>竣工待验收</option>
<option>合同即将到期 (30天内)</option>
</select>
<span class="material-symbols-outlined absolute right-sm text-text-muted pointer-events-none text-[18px]">expand_more</span>
</div>
</div>
<!-- Sales Rep & Operations -->
<div class="flex flex-col gap-1.5">
<label class="font-caption-sm text-caption-sm text-text-muted">责任业务经理</label>
<div class="relative flex items-center">
<span class="material-symbols-outlined absolute left-sm text-text-muted text-[18px]">person_pin</span>
<select class="w-full h-10 pl-xl pr-md rounded-lg bg-surface-container-low text-on-surface text-body-md outline-none appearance-none focus:ring-1 focus:ring-primary">
<option>全部工程师/业务经理</option>
<option selected="">陈建军 (业务一部)</option>
<option>李明 (医疗保障组)</option>
<option>王工 (园区电务)</option>
</select>
<span class="material-symbols-outlined absolute right-sm text-text-muted pointer-events-none text-[18px]">expand_more</span>
</div>
</div>
</div>
<!-- Action Bottom in Filter -->
<div class="flex items-center justify-between pt-2 border-t border-border-rule/40 flex-wrap gap-2">
<div class="flex items-center gap-2 flex-wrap">
<span class="font-caption-sm text-caption-sm text-text-muted mr-1">快速标签过滤:</span>
<span class="px-2.5 py-1 rounded-full bg-primary text-on-primary font-caption-sm text-[12px] cursor-pointer whitespace-nowrap shadow-xs">全部重点单位 (48)</span>
<span class="px-2.5 py-1 rounded-full bg-surface-container text-on-surface-variant hover:bg-surface-variant font-caption-sm text-[12px] cursor-pointer whitespace-nowrap transition-colors">含高压一次配电</span>
<span class="px-2.5 py-1 rounded-full bg-surface-container text-on-surface-variant hover:bg-surface-variant font-caption-sm text-[12px] cursor-pointer whitespace-nowrap transition-colors">大华边缘网关异常 (0)</span>
</div>
<div class="flex items-center gap-sm ml-auto">
<button class="px-4 py-1.5 rounded-lg bg-surface hover:bg-surface-container-low text-text-muted font-label-bold text-label-bold transition-colors" type="button">重置</button>
<button class="px-5 py-1.5 rounded-lg bg-primary text-on-primary hover:bg-primary-container font-label-bold text-label-bold flex items-center gap-xs shadow-sm transition-colors" type="button">
<span class="material-symbols-outlined text-[16px]">tune</span>
<span class="">查询检索</span>
</button>
</div>
</div>
</div>
<!-- Split Master-Detail Layout (Optimized ratio: 69% / 31% on 2xl, 8 cols / 4 cols on xl) -->
<div class="w-full flex flex-col gap-sm"><div class="bg-surface rounded-xl shadow-sm overflow-hidden flex flex-col"><div class="p-4 bg-surface flex items-center justify-between border-b border-border-rule/50"><div class="flex items-center gap-3"><span class="font-title-sm text-title-sm text-on-surface">托管客户清单</span><span class="px-2 py-0.5 rounded bg-surface-container text-on-surface-variant font-data-mono text-[12px]">共 128 家 / 当前显示 4 家</span></div><div class="flex items-center gap-1.5 text-text-muted"><button class="p-1.5 rounded-lg hover:bg-surface-container-low text-on-surface-variant transition-colors" title="刷新列表"><span class="material-symbols-outlined text-[18px]">refresh</span></button><button class="p-1.5 rounded-lg hover:bg-surface-container-low text-on-surface-variant transition-colors" title="自定义表头列"><span class="material-symbols-outlined text-[18px]">view_column</span></button></div></div><div class="overflow-x-auto"><table class="w-full text-left border-collapse min-w-[760px]"><thead><tr class="bg-surface-container-low/70 text-text-muted font-caption-sm text-caption-sm border-b border-border-rule/40"><th class="py-3.5 px-5 font-semibold w-[26%]">客户主体与性质</th><th class="py-3.5 px-4 font-semibold w-[25%]">建筑/配电拓扑</th><th class="py-3.5 px-4 font-semibold w-[18%]">托管周期 &amp; 费用</th><th class="py-3.5 px-4 font-semibold w-[16%]">ICC设备状态</th><th class="py-3.5 px-5 font-semibold w-[15%] text-right pr-5">空间拓扑与操作</th></tr></thead><tbody class="divide-y divide-border-rule/30 text-body-md text-on-surface"><tr class="bg-surface-container/30 hover:bg-surface-container/60 transition-colors cursor-pointer"><td class="py-4 px-5 align-top"><div class="flex items-start gap-3"><div class="w-10 h-10 rounded-xl bg-primary/10 text-primary flex-shrink-0 flex items-center justify-center"><span class="material-symbols-outlined text-[22px]">school</span></div><div class="flex flex-col gap-1 min-w-0"><div class="flex items-center gap-2 flex-wrap"><span class="font-label-bold text-[14px] text-on-surface hover:text-primary whitespace-nowrap">武汉软件工程职业学院</span><span class="px-2 py-0.5 rounded bg-primary text-on-primary font-caption-sm text-[11px] whitespace-nowrap">A级重要</span></div><span class="font-data-mono text-[12px] text-text-muted">PRJ-HB-WH-00192 · 高教职业本科</span><span class="font-caption-sm text-[12px] text-text-muted flex items-center gap-1"><span class="material-symbols-outlined text-[14px] text-primary/70 shrink-0">place</span><span class="truncate">江夏区藏龙岛科技园光谷大道117号</span></span></div></div></td><td class="py-4 px-4 align-top"><div class="flex flex-col gap-1.5"><div class="flex items-center gap-2"><span class="font-label-bold text-[13px] text-on-surface">5 栋建筑空间</span><span class="px-1.5 py-0.5 bg-surface-container-high rounded text-text-muted font-data-mono text-[11px]">36回路</span></div><span class="font-caption-sm text-[12px] text-text-muted">宿舍楼、实训中心A/B、配电总房</span><div class="flex items-center gap-2 mt-0.5 font-data-mono text-[11px] text-text-muted"><span class="px-1.5 py-0.5 bg-surface-container-low rounded">48台断路器</span><span class="px-1.5 py-0.5 bg-surface-container-low rounded">4台网关</span></div></div></td><td class="py-4 px-4 align-top"><div class="flex flex-col gap-1"><span class="font-data-mono text-label-bold text-on-surface text-[13px]">2024.03 - 2027.03</span><span class="font-caption-sm text-[12px] text-text-muted">3年全托管 · ¥18.6万/年</span><span class="font-caption-sm text-[12px] text-on-surface-variant flex items-center gap-1"><span class="material-symbols-outlined text-[13px] text-text-muted">badge</span><span class="">经理: 陈建军</span></span></div></td><td class="py-4 px-4 align-top"><div class="flex flex-col gap-1"><div class="flex items-center gap-1.5"><span class="w-2 h-2 rounded-full bg-tertiary"></span><span class="font-label-bold text-[12px] text-tertiary whitespace-nowrap">已联通 4/4 台</span></div><span class="font-data-mono text-[11px] text-text-muted">ICC: 192.168.10.88</span><span class="px-2 py-0.5 rounded bg-tertiary/10 text-tertiary font-caption-sm text-[11px] inline-flex items-center w-fit gap-1 mt-1"><span class="w-1.5 h-1.5 rounded-full bg-tertiary"></span><span class="whitespace-nowrap">正常托管中</span></span></div></td><td class="py-4 px-5 align-top text-right"><div class="flex flex-col items-end gap-1.5"><div class="flex items-center gap-1.5"><button class="px-3 py-1.5 rounded-lg bg-primary text-on-primary font-label-bold text-[12px] hover:bg-primary-container shadow-xs whitespace-nowrap transition-colors flex items-center gap-1"><span class="material-symbols-outlined text-[14px]">account_tree</span><span class="">空间拓扑</span></button><button class="px-2.5 py-1.5 rounded-lg bg-surface-container hover:bg-surface-variant teLine truncated
</div>
</div>
<script>
function switchTab(tabIndex) {
// Buttons styling
const tabs = [1, 2, 3];
tabs.forEach(i => {
const btn = document.getElementById('tabBtn' + i);
const content = document.getElementById('tabContent' + i);
if (i === tabIndex) {
btn.classList.add('text-primary', 'border-primary');
btn.classList.remove('text-text-muted', 'border-transparent');
content.classList.remove('hidden');
} else {
btn.classList.remove('text-primary', 'border-primary');
btn.classList.add('text-text-muted', 'border-transparent');
content.classList.add('hidden');
}
});
}
function toggleDrawer() {
const drawer = document.getElementById('detailDrawer');
drawer.scrollIntoView({ behavior: 'smooth', block: 'start' });
}
function selectRow(index) {
// Visual feedback micro-interaction
const syncIcon = document.getElementById('syncIcon');
syncIcon.classList.add('animate-spin');
setTimeout(() => {
syncIcon.classList.remove('animate-spin');
}, 400);
}
</script></main></div>
</body></html>
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB