Просмотр исходного кода

Merge branch 'feature/family-ops-workbench' into cfclub: 后台家庭运营工作台重设计(设计稿+实现+AA 对比度修复)

Agnes Agent 2 дней назад
Родитель
Сommit
fec95a6350
2 измененных файлов с 1477 добавлено и 84 удалено
  1. 1143 0
      cfc-web/design-drafts/family-ops-workbench.html
  2. 334 84
      cfc-web/src/views/Families.vue

+ 1143 - 0
cfc-web/design-drafts/family-ops-workbench.html

@@ -0,0 +1,1143 @@
+<!DOCTYPE html>
+<html lang="zh-CN">
+<head>
+<meta charset="UTF-8" />
+<meta name="viewport" content="width=device-width, initial-scale=1" />
+<title>家庭运营工作台 · 设计草稿</title>
+<style>
+/* ============================================================
+   设计令牌(单一事实源)—— 严格镜像 admin-tokens.css 语义
+   三层:基色 -> 语义 -> 组件。组件层禁止裸 hex / 裸 px / 裸 ms。
+   ============================================================ */
+:root {
+  /* ---- 品牌主色与功能色(Ant Design 5 语义) ---- */
+  --c-primary: #1677FF;
+  --c-primary-hover: #0958D9;        /* 加深:白字 6.16:1,且 hover 不浅于主按钮默认态 */
+  --c-primary-active: #0958D9;
+  --c-primary-disabled: #A0C4FF;
+  --c-primary-deep: #0B5FCC;         /* 主按钮填充:白字 5.96:1;--c-primary 保留作链接/下划线强调 */
+  --c-success: #52C41A;
+  --c-success-text: #237804;         /* 加深:#237804 on #F6FFED = 5.44:1 */
+  --c-success-bg: #F6FFED;
+  --c-success-border: #B7EB8F;
+  --c-warning: #FAAD14;
+  --c-warning-bg: #FFFBE6;           /* 警告徽标浅底 */
+  --c-warning-text: #874D00;         /* 深琥珀文字:#874D00 on #FFFBE6 = 6.53:1 */
+  --c-danger: #FF4D4F;
+  --c-danger-text: #CF1322;
+  --c-danger-bg: #FFF1F0;
+  --c-danger-border: #FFCCC7;
+  --c-neutral: #909399;            /* 沿用 Element 灰语义(非蓝) */
+  --c-info-bg: #E6F4FF;           /* 主色浅底:hero 卡 / 焦点态背景 */
+  --c-info-border: #91CAFF;       /* 主色浅描边:焦点环 / 选中边 */
+  --c-info-text: #0958D9;         /* 小号可点击文字(保证 AA ≥4.5:1) */
+  --c-link-hover: #003EB3;        /* link-toggle hover:更深蓝,白底 ≥7:1,仅作 :root 令牌 */
+  --c-ring: rgba(9, 88, 217, 0.85);  /* focus ring, ≥3:1 vs white */
+
+  /* ---- 文字灰阶(rgba 体系,层次稳定) ---- */
+  --t-primary: rgba(0, 0, 0, 0.88);
+  --t-regular: rgba(0, 0, 0, 0.65);
+  --t-secondary: rgba(0, 0, 0, 0.65);  /* 加深:7.00:1,承载真实文字内容 */
+  --t-placeholder: rgba(0, 0, 0, 0.25);
+  --t-on-primary: #FFFFFF;
+  --t-disabled: rgba(0, 0, 0, 0.25);
+
+  /* ---- 边框与填充 ---- */
+  --b-base: #D9D9D9;
+  --b-light: #F0F0F0;
+  --b-extra-light: #F5F5F5;
+  --b-strong: #BFBFBF;
+  --bw: 1px;
+
+  /* ---- 背景 ---- */
+  --bg-page: #F0F2F5;
+  --bg-card: #FFFFFF;
+  --bg-header: #FAFAFA;
+  --bg-fill: #F5F5F5;
+  --bg-hover: rgba(0, 0, 0, 0.04);
+  --bg-selected: #E6F4FF;
+  --bg-mask: rgba(0, 0, 0, 0.45);
+
+  /* ---- 字体 ---- */
+  --font-family: 'Helvetica Neue', Helvetica, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', Arial, sans-serif;
+  --fs-sm: 12px;
+  --fs-base: 14px;
+  --fs-md: 14px;
+  --fs-lg: 16px;
+  --fs-xl: 20px;
+  --fs-2xl: 24px;
+  --fs-3xl: 28px;
+  --lh-base: 1.5;
+
+  /* ---- 间距(8px 基准,禁止非标值) ---- */
+  --sp-1: 4px;
+  --sp-2: 8px;
+  --sp-3: 12px;
+  --sp-4: 16px;
+  --sp-5: 20px;
+  --sp-6: 24px;
+  --sp-7: 32px;
+  --sp-8: 48px;
+
+  /* ---- 圆角(禁止 >8px) ---- */
+  --r-sm: 2px;
+  --r-base: 4px;
+  --r-control: 6px;
+  --r-card: 8px;
+
+  /* ---- 阴影(轻量化:阴影分层且罕见) ---- */
+  --sh-card: 0 1px 2px 0 rgba(0, 0, 0, 0.03), 0 1px 6px -1px rgba(0, 0, 0, 0.02);
+  --sh-popup: 0 6px 16px 0 rgba(0, 0, 0, 0.08), 0 3px 6px -4px rgba(0, 0, 0, 0.12);
+  --sh-hover: 0 2px 8px 0 rgba(0, 0, 0, 0.06), 0 1px 2px 0 rgba(0, 0, 0, 0.04);
+
+  /* ---- 动效令牌(≤200ms) ---- */
+  --d-fast: 120ms;
+  --d-base: 160ms;
+  --d-slow: 200ms;
+  --ease: cubic-bezier(0.4, 0, 0.2, 1);
+
+  /* ---- 控件 / 图标尺寸 ---- */
+  --w-input: 220px;
+  --w-input-sm: 160px;
+  --w-select: 150px;
+  --w-select-sm: 120px;
+  --w-select-lg: 180px;
+  --icon-sm: 16px;
+  --icon-md: 20px;
+  --icon-lg: 24px;
+  --qe-icon-box: 40px;
+  --ring-1: 2px;
+  --ring-2: 4px;
+  --lift: -2px;
+  --spinner: 14px;
+  --stat-hero-w: 248px;
+  --table-min: 1490px;
+  --z-sticky: 5;
+  --z-popup: 1000;
+
+  /* ---- 表格列宽令牌(避免裸 px) ---- */
+  --col-cb: 44px;
+  --col-id: 72px;
+  --col-name: 150px;
+  --col-code: 116px;
+  --col-time: 164px;
+  --col-members: 86px;
+  --col-reports: 86px;
+  --col-plans: 84px;
+  --col-tasks: 84px;
+  --col-coupons: 96px;
+  --col-active: 108px;
+  --col-rate: 116px;
+  --col-status: 92px;
+  --col-op: 212px;
+
+  /* ---- 组件尺寸令牌(杜绝裸 px) ---- */
+  --vw: 1440px;
+  --appbar-h: 60px;
+  --bar-w: 3px;
+  --ctrl-h: 32px;
+  --ctrl-sm-h: 28px;
+  --brand-mark: 28px;
+  --avatar: 28px;
+  --th-h: 46px;
+  --sw-w: 44px;
+  --sw-h: 22px;
+  --sw-r: 11px;
+  --sw-thumb: 18px;
+  --sw-top: 2px;
+  --sw-left: 2px;
+  --sw-travel: 22px;
+  --cb: 16px;
+  --cb-ic: 12px;
+  --rate-h: 6px;
+  --rate-r: 3px;
+  --rate-val-w: 38px;
+  --dot: 6px;
+  --pad-2: 2px;
+  --status-lh: 20px;
+  --menu-w: 148px;
+  --menu-item-h: 34px;
+  --pg-btn: 32px;
+  --w-jump: 56px;
+  --ls-code: 0.5px;
+  --sr: 1px;
+  --demo-tbl-w: 560px;
+  --sh-appbar: 0 1px 4px rgba(0, 21, 41, 0.06);
+  --sh-thumb: 0 1px 2px rgba(0, 0, 0, 0.2);
+}
+
+/* ============================================================
+   基础重置
+   ============================================================ */
+* { box-sizing: border-box; }
+html, body { margin: 0; padding: 0; }
+body {
+  font-family: var(--font-family);
+  font-size: var(--fs-base);
+  line-height: var(--lh-base);
+  color: var(--t-primary);
+  background: var(--bg-page);
+  -webkit-font-smoothing: antialiased;
+}
+.screen { width: var(--vw); margin: 0 auto; background: var(--bg-page); }
+
+/* 图标基类 */
+.icon { width: var(--icon-md); height: var(--icon-md); display: inline-block; vertical-align: middle; flex: none; }
+.icon--sm { width: var(--icon-sm); height: var(--icon-sm); }
+.icon--lg { width: var(--icon-lg); height: var(--icon-lg); }
+.icon--current { fill: currentColor; }
+.icon--stroke { fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
+
+/* ============================================================
+   顶部应用栏(grounding:呈现后台环境,非重构目标)
+   ============================================================ */
+.appbar {
+  height: var(--appbar-h); flex: none;
+  display: flex; align-items: center; justify-content: space-between;
+  padding: 0 var(--sp-6);
+  background: var(--bg-card);
+  border-bottom: var(--bw) solid var(--b-light);
+  box-shadow: var(--sh-appbar);
+}
+.appbar__logo { display: flex; align-items: center; gap: var(--sp-2); font-size: var(--fs-lg); font-weight: 600; color: var(--t-primary); }
+.appbar__logo .mark { width: var(--brand-mark); height: var(--brand-mark); border-radius: var(--r-control); background: var(--c-primary); color: var(--t-on-primary); display: flex; align-items: center; justify-content: center; }
+.appbar__right { display: flex; align-items: center; gap: var(--sp-4); color: var(--t-regular); }
+.appbar__user { display: flex; align-items: center; gap: var(--sp-2); }
+.appbar__avatar { width: var(--avatar); height: var(--avatar); border-radius: 50%; background: var(--bg-fill); color: var(--c-primary); display: flex; align-items: center; justify-content: center; }
+
+/* ============================================================
+   页面容器
+   ============================================================ */
+.page { padding: var(--sp-6); display: flex; flex-direction: column; gap: var(--sp-6); }
+
+/* 页头 */
+.page-header { display: flex; align-items: center; justify-content: space-between; flex: none; }
+.page-header__titles { display: flex; align-items: baseline; gap: var(--sp-3); }
+.page-title { font-size: var(--fs-xl); font-weight: 600; line-height: 1.4; color: var(--t-primary); margin: 0; }
+.page-subtitle { font-size: var(--fs-sm); color: var(--t-secondary); font-weight: 400; }
+.page-header__actions { display: flex; align-items: center; gap: var(--sp-2); flex: none; }
+
+/* 区块标题:14/500 + 3px 主色竖条 */
+.section-title {
+  font-size: var(--fs-base); font-weight: 500; color: var(--t-primary);
+  padding-left: var(--sp-2); border-left: var(--bar-w) solid var(--c-primary);
+  margin: 0;
+}
+
+/* ============================================================
+   卡片
+   ============================================================ */
+.card {
+  background: var(--bg-card);
+  border: var(--bw) solid var(--b-light);
+  border-radius: var(--r-card);
+  box-shadow: var(--sh-card);
+}
+.card__header {
+  display: flex; align-items: center; justify-content: space-between;
+  padding: var(--sp-5) var(--sp-6);
+  border-bottom: var(--bw) solid var(--b-light);
+}
+.card__header .section-title { border-left: none; padding-left: 0; }
+.card__header-note { font-size: var(--fs-sm); color: var(--t-secondary); }
+.card__body { padding: var(--sp-6); }
+
+/* ============================================================
+   按钮(八态完整:default/hover/focus/active/disabled/loading/success/error)
+   ============================================================ */
+.btn {
+  display: inline-flex; align-items: center; justify-content: center; gap: var(--sp-1);
+  height: var(--ctrl-h); padding: 0 var(--sp-4);
+  font-size: var(--fs-base); font-family: inherit; font-weight: 400; line-height: 1;
+  border-radius: var(--r-control);
+  border: var(--bw) solid transparent;
+  cursor: pointer; white-space: nowrap;
+  transition: background-color var(--d-base) var(--ease), border-color var(--d-base) var(--ease), color var(--d-base) var(--ease), box-shadow var(--d-base) var(--ease), transform var(--d-fast) var(--ease);
+}
+.btn:focus-visible { outline: none; box-shadow: 0 0 0 var(--ring-1) var(--bg-card), 0 0 0 var(--ring-2) var(--c-ring); }
+.btn .icon { width: var(--icon-sm); height: var(--icon-sm); }
+
+.btn--primary { background: var(--c-primary-deep); border-color: var(--c-primary-deep); color: var(--t-on-primary); }
+.btn--primary:hover { background: var(--c-primary-hover); border-color: var(--c-primary-hover); }
+.btn--primary:active { background: var(--c-primary-active); border-color: var(--c-primary-active); }
+.btn--primary.is-disabled, .btn--primary:disabled { background: var(--c-primary-disabled); border-color: var(--c-primary-disabled); color: var(--t-on-primary); cursor: not-allowed; }
+
+.btn--default { background: var(--bg-card); border-color: var(--b-base); color: var(--t-primary); }
+.btn--default:hover { color: var(--c-primary-hover); border-color: var(--c-primary-hover); }
+.btn--default:active { color: var(--c-primary-active); border-color: var(--c-primary-active); }
+.btn--default.is-disabled, .btn--default:disabled { background: var(--bg-card); border-color: var(--b-light); color: var(--t-disabled); cursor: not-allowed; }
+
+.btn--text { background: transparent; border-color: transparent; color: var(--c-info-text); height: var(--ctrl-h); padding: 0 var(--sp-2); }
+.btn--text:hover { color: var(--c-primary-hover); background: var(--bg-hover); }
+.btn--text:active { color: var(--c-primary-active); }
+.btn--text.is-disabled, .btn--text:disabled { color: var(--t-disabled); cursor: not-allowed; }
+
+/* success / error 语义态(用于提交结果等) */
+.btn--success { background: var(--c-success-text); border-color: var(--c-success-text); color: var(--t-on-primary); }
+.btn--error { background: var(--c-danger-text); border-color: var(--c-danger-text); color: var(--t-on-primary); }
+
+/* loading:文字透明,显示旋转 spinner */
+.btn.is-loading { color: transparent !important; cursor: default; position: relative; pointer-events: none; }
+.btn.is-loading::after {
+  content: ""; position: absolute; top: 50%; left: 50%;
+  width: var(--spinner); height: var(--spinner); margin: calc(var(--spinner) / -2) 0 0 calc(var(--spinner) / -2);
+  border: var(--ring-1) solid currentColor; border-top-color: transparent; border-radius: 50%;
+  animation: spin var(--d-slow) linear infinite;
+  color: var(--t-on-primary);
+}
+.btn--default.is-loading::after { color: var(--c-primary); }
+@keyframes spin { to { transform: rotate(360deg); } }
+
+/* ============================================================
+   表单控件(input / select)—— 八态
+   ============================================================ */
+.field { display: flex; flex-direction: column; gap: var(--sp-1); }
+.field__label { font-size: var(--fs-base); color: var(--t-regular); font-weight: 500; }
+.input, .select {
+  height: var(--ctrl-h); padding: 0 var(--sp-3);
+  font-size: var(--fs-base); font-family: inherit; color: var(--t-primary);
+  background: var(--bg-card);
+  border: var(--bw) solid var(--b-base);
+  border-radius: var(--r-base);
+  transition: border-color var(--d-base) var(--ease), box-shadow var(--d-base) var(--ease);
+}
+.input::placeholder { color: var(--t-placeholder); }
+.input:hover, .select:hover { border-color: var(--c-primary-hover); }
+.input:focus, .input:focus-visible, .select:focus, .select:focus-visible {
+  outline: none; border-color: var(--c-primary);
+  box-shadow: 0 0 0 var(--ring-1) var(--c-ring);
+}
+.input.is-disabled, .select.is-disabled {
+  background: var(--bg-fill); border-color: var(--b-light); color: var(--t-disabled); cursor: not-allowed;
+}
+.input.is-error, .select.is-error { border-color: var(--c-danger); }
+.input.is-error:focus { box-shadow: 0 0 0 var(--ring-1) var(--c-danger-bg); }
+.input--w { width: var(--w-input); }
+.input--sm { width: var(--w-input-sm); }
+.select--w { width: var(--w-select); }
+.select--sm { width: var(--w-select-sm); }
+.select--lg { width: var(--w-select-lg); }
+.field__error { font-size: var(--fs-sm); color: var(--c-danger-text); }
+.field__hint { font-size: var(--fs-sm); color: var(--t-secondary); }
+.input-wrap { position: relative; display: inline-flex; align-items: center; }
+.input-wrap .icon { position: absolute; right: var(--sp-3); color: var(--t-secondary); pointer-events: none; }
+
+/* 区间连接符 */
+.range-sep { color: var(--t-secondary); padding: 0 var(--sp-1); align-self: flex-end; height: var(--ctrl-h); display: inline-flex; align-items: center; }
+
+/* ============================================================
+   开关 Switch(启用状态)—— 八态
+   ============================================================ */
+.switch { position: relative; display: inline-flex; align-items: center; width: var(--sw-w); height: var(--sw-h); cursor: pointer; }
+.switch input { position: absolute; opacity: 0; width: 100%; height: 100%; margin: 0; cursor: pointer; }
+.switch__track {
+  width: var(--sw-w); height: var(--sw-h); border-radius: var(--sw-r);
+  background: var(--b-strong);
+  transition: background-color var(--d-base) var(--ease);
+}
+.switch__thumb {
+  position: absolute; top: var(--sw-top); left: var(--sw-left);
+  width: var(--sw-thumb); height: var(--sw-thumb); border-radius: 50%;
+  background: var(--bg-card); box-shadow: var(--sh-thumb);
+  transition: transform var(--d-base) var(--ease);
+}
+.switch input:checked ~ .switch__track { background: var(--c-primary); }
+.switch input:checked ~ .switch__thumb { transform: translateX(var(--sw-travel)); }
+.switch input:focus-visible ~ .switch__track { box-shadow: 0 0 0 var(--ring-1) var(--c-info-bg), 0 0 0 var(--ring-2) var(--c-ring); }
+.switch.is-disabled { cursor: not-allowed; opacity: 0.55; }
+.switch.is-loading .switch__thumb { animation: pulse var(--d-slow) var(--ease) infinite; }
+@keyframes pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.4; } }
+.switch__label { margin-left: var(--sp-2); font-size: var(--fs-base); color: var(--t-regular); }
+
+/* ============================================================
+   统计带(One Thing Leads:表格为主角,统计带为次级带状序列)
+   带内设置「主指标」(家庭总收益) 打破等权重卡片墙
+   ============================================================ */
+.stat-band { display: flex; overflow: hidden; border-radius: var(--r-card); }
+.stat-hero {
+  flex: 0 0 var(--stat-hero-w);
+  background: var(--c-info-bg);
+  padding: var(--sp-6);
+  border-right: var(--bw) solid var(--b-light);
+  display: flex; flex-direction: column; justify-content: center; gap: var(--sp-2);
+}
+.stat-hero__label { font-size: var(--fs-sm); color: var(--t-regular); display: flex; align-items: center; gap: var(--sp-2); }
+.stat-hero__value { font-size: var(--fs-3xl); font-weight: 600; color: var(--c-primary); font-variant-numeric: tabular-nums; line-height: 1.1; }
+.stat-hero__sub { font-size: var(--fs-sm); color: var(--t-secondary); }
+.stat-grid { flex: 1; display: grid; grid-template-columns: repeat(3, 1fr); }
+.stat-cell { padding: var(--sp-5) var(--sp-6); border-left: var(--bw) solid var(--b-light); display: flex; flex-direction: column; gap: var(--sp-2); }
+.stat-cell:nth-child(3n+1) { border-left: none; }
+.stat-cell:nth-child(n+4) { border-top: var(--bw) solid var(--b-light); }
+.stat-cell__label { font-size: var(--fs-sm); color: var(--t-secondary); display: flex; align-items: center; gap: var(--sp-1); }
+.stat-cell__value { font-size: var(--fs-2xl); font-weight: 600; color: var(--t-primary); font-variant-numeric: tabular-nums; line-height: 1.1; }
+.stat-cell__sub { font-size: var(--fs-sm); color: var(--t-secondary); }
+.stat-note { margin-top: var(--sp-3); font-size: var(--fs-sm); color: var(--t-secondary); }
+.stat-note strong { color: var(--c-warning); font-weight: 600; }
+
+/* ============================================================
+   筛选条(去卡片化,底部细分割线分区)
+   ============================================================ */
+.filter-bar { display: flex; flex-direction: column; gap: var(--sp-4); }
+.filter-row { display: flex; align-items: flex-end; flex-wrap: wrap; gap: var(--sp-4); }
+.filter-row--advanced { padding-top: var(--sp-4); border-top: var(--bw) solid var(--b-light); }
+.filter-spacer { flex: 1 1 auto; }
+.link-toggle { display: inline-flex; align-items: center; gap: var(--sp-1); background: none; border: none; cursor: pointer; color: var(--c-info-text); font-size: var(--fs-base); font-family: inherit; padding: var(--sp-1) 0; }
+.link-toggle:hover { color: var(--c-link-hover); text-decoration: underline; }
+.link-toggle:focus-visible { outline: 2px solid var(--c-ring); outline-offset: 2px; border-radius: var(--radius-2); }
+.link-toggle .icon { transition: transform var(--d-base) var(--ease); }
+.link-toggle.is-open .icon { transform: rotate(180deg); }
+
+/* ============================================================
+   批量操作条(选中态)
+   ============================================================ */
+.batch-bar {
+  display: flex; align-items: center; gap: var(--sp-3);
+  padding: var(--sp-3) var(--sp-4);
+  margin-bottom: var(--sp-4);
+  background: var(--bg-selected);
+  border: var(--bw) solid var(--c-info-border);
+  border-radius: var(--r-base);
+}
+.batch-bar__count { font-size: var(--fs-base); color: var(--c-info-text); font-weight: 500; }
+.batch-bar__spacer { flex: 1 1 auto; }
+
+/* ============================================================
+   表格(英雄主角)
+   ============================================================ */
+.table-scroll { overflow-x: auto; border: var(--bw) solid var(--b-light); border-radius: var(--r-card); }
+table.grid { width: 100%; min-width: var(--table-min); border-collapse: separate; border-spacing: 0; font-size: var(--fs-base); color: var(--t-primary); }
+table.grid th, table.grid td { text-align: left; padding: var(--sp-3) var(--sp-4); border-bottom: var(--bw) solid var(--b-light); }
+table.grid thead th {
+  background: var(--bg-header); font-weight: 500; color: var(--t-primary);
+  height: var(--th-h); position: sticky; top: 0; z-index: var(--z-sticky); white-space: nowrap;
+}
+table.grid tbody tr { transition: background-color var(--d-fast) var(--ease); }
+table.grid tbody tr:hover { background: var(--bg-hover); }
+table.grid tbody tr.is-selected { background: var(--bg-selected); }
+table.grid tbody tr.is-selected:hover { background: var(--bg-selected); }
+table.grid .num { text-align: right; font-variant-numeric: tabular-nums; font-feature-settings: "tnum"; }
+table.grid .col-cb { width: var(--col-cb); position: sticky; left: 0; z-index: var(--z-sticky); background: var(--bg-card); }
+table.grid thead .col-cb { background: var(--bg-header); }
+table.grid tbody tr:hover .col-cb { background: var(--bg-hover); }
+table.grid tbody tr.is-selected .col-cb { background: var(--bg-selected); }
+table.grid .col-op { width: var(--col-op); position: sticky; right: 0; z-index: var(--z-sticky); background: var(--bg-card); text-align: right; white-space: nowrap; }
+table.grid thead .col-op { background: var(--bg-header); }
+table.grid tbody tr:hover .col-op { background: var(--bg-hover); }
+table.grid tbody tr.is-selected .col-op { background: var(--bg-selected); }
+.col-id { width: var(--col-id); }
+.col-name { width: var(--col-name); }
+.col-code { width: var(--col-code); }
+.col-time { width: var(--col-time); }
+.col-members { width: var(--col-members); }
+.col-reports { width: var(--col-reports); }
+.col-plans { width: var(--col-plans); }
+.col-tasks { width: var(--col-tasks); }
+.col-coupons { width: var(--col-coupons); }
+.col-active { width: var(--col-active); }
+.col-rate { width: var(--col-rate); }
+.col-status { width: var(--col-status); }
+
+/* 单元格内数值链接(小号),用 --c-info-text 保证 AA */
+.cell-link { color: var(--c-info-text); cursor: pointer; font-variant-numeric: tabular-nums; }
+.cell-link:hover { color: var(--c-primary-hover); text-decoration: underline; }
+.cell-zero { color: var(--t-secondary); }
+.cell-code { font-family: 'SF Mono', 'JetBrains Mono', monospace; letter-spacing: var(--ls-code); color: var(--t-regular); }
+
+/* 复选框(自定义,纯 CSS) */
+.checkbox { width: var(--cb); height: var(--cb); border: var(--bw) solid var(--b-base); border-radius: var(--r-sm); background: var(--bg-card); display: inline-flex; align-items: center; justify-content: center; cursor: pointer; transition: background-color var(--d-fast) var(--ease), border-color var(--d-fast) var(--ease); }
+.checkbox svg { width: var(--cb-ic); height: var(--cb-ic); fill: none; stroke: var(--t-on-primary); stroke-width: 3; opacity: 0; }
+.checkbox.is-checked { background: var(--c-primary); border-color: var(--c-primary); }
+.checkbox.is-checked svg { opacity: 1; }
+.checkbox.is-indeterminate { background: var(--c-primary); border-color: var(--c-primary); }
+.checkbox.is-indeterminate svg { opacity: 1; stroke-dasharray: 10; }
+
+/* 完成率进度条 */
+.rate { display: flex; align-items: center; gap: var(--sp-2); }
+.rate__bar { flex: 1; height: var(--rate-h); border-radius: var(--rate-r); background: var(--bg-fill); overflow: hidden; }
+.rate__fill { height: 100%; border-radius: var(--rate-r); background: var(--c-primary); }
+.rate__val { font-variant-numeric: tabular-nums; color: var(--t-regular); min-width: var(--rate-val-w); text-align: right; }
+
+/* 状态徽标(浅底+深字+同色圆点) */
+.status { display: inline-flex; align-items: center; gap: var(--sp-1); padding: var(--pad-2) var(--sp-2); font-size: var(--fs-sm); line-height: var(--status-lh); border-radius: var(--r-sm); white-space: nowrap; }
+.status::before { content: ""; width: var(--dot); height: var(--dot); border-radius: 50%; background: currentColor; }
+.status--success { background: var(--c-success-bg); color: var(--c-success-text); }
+.status--info { background: var(--c-info-bg); color: var(--c-info-text); }
+.status--warning { background: var(--c-warning-bg); color: var(--c-warning-text); }
+.status--error { background: var(--c-danger-bg); color: var(--c-danger-text); }
+.status--default { background: var(--bg-fill); color: var(--t-regular); }
+
+/* ============================================================
+   下拉菜单(更多)—— 真实菜单项
+   ============================================================ */
+.dropdown { position: relative; display: inline-block; }
+.dropdown__menu {
+  position: absolute; top: calc(100% + var(--sp-1)); left: 0; min-width: var(--menu-w);
+  background: var(--bg-card); border: var(--bw) solid var(--b-light);
+  border-radius: var(--r-control); box-shadow: var(--sh-popup); padding: var(--sp-1); z-index: var(--z-popup);
+}
+.dropdown__item { display: flex; align-items: center; gap: var(--sp-2); padding: 0 var(--sp-2); height: var(--menu-item-h); border-radius: var(--r-base); color: var(--t-primary); font-size: var(--fs-base); cursor: pointer; }
+.dropdown__item:hover { background: var(--bg-fill); }
+.dropdown__item .icon { width: var(--icon-sm); height: var(--icon-sm); color: var(--t-secondary); }
+.dropdown__item.is-danger { color: var(--c-danger-text); }
+
+/* ============================================================
+   快捷入口网格(次级区,轻边框 + hover 微抬升)
+   ============================================================ */
+.qe-grid { display: grid; grid-template-columns: repeat(5, 1fr); gap: var(--sp-4); }
+.qe-card {
+  display: flex; align-items: center; gap: var(--sp-3);
+  padding: var(--sp-4);
+  background: var(--bg-card); border: var(--bw) solid var(--b-light); border-radius: var(--r-card);
+  cursor: pointer; text-decoration: none; color: inherit;
+  transition: transform var(--d-base) var(--ease), box-shadow var(--d-base) var(--ease), border-color var(--d-base) var(--ease), background-color var(--d-base) var(--ease);
+}
+.qe-card:hover { transform: translateY(var(--lift)); box-shadow: var(--sh-hover); border-color: var(--c-info-border); }
+.qe-card.is-current { border-color: var(--c-primary); background: var(--c-info-bg); }
+.qe-icon { width: var(--qe-icon-box); height: var(--qe-icon-box); border-radius: var(--r-control); background: var(--c-info-bg); color: var(--c-primary); display: flex; align-items: center; justify-content: center; flex: none; }
+.qe-icon .icon { width: var(--icon-md); height: var(--icon-md); }
+.qe-meta { display: flex; flex-direction: column; gap: var(--pad-2); min-width: 0; }
+.qe-title { font-size: var(--fs-base); font-weight: 500; color: var(--t-primary); }
+.qe-sub { font-size: var(--fs-sm); color: var(--t-secondary); }
+
+/* ============================================================
+   页脚:分页 + 导出
+   ============================================================ */
+.page-footer { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-4); }
+.pagination { display: flex; align-items: center; gap: var(--sp-2); color: var(--t-regular); font-size: var(--fs-base); margin-left: auto; }
+.pagination__btn { min-width: var(--pg-btn); height: var(--ctrl-h); padding: 0 var(--sp-2); border: var(--bw) solid var(--b-base); border-radius: var(--r-control); background: var(--bg-card); color: var(--t-primary); cursor: pointer; display: inline-flex; align-items: center; justify-content: center; transition: color var(--d-fast) var(--ease), border-color var(--d-fast) var(--ease); }
+.pagination__btn:hover:not(:disabled) { color: var(--c-primary); border-color: var(--c-primary-hover); }
+.pagination__btn.is-active { background: var(--c-primary); border-color: var(--c-primary); color: var(--t-on-primary); }
+.pagination__btn:disabled { color: var(--t-disabled); cursor: not-allowed; }
+.pagination__jump { display: inline-flex; align-items: center; gap: var(--sp-1); }
+.pagination__jump .input { width: var(--w-jump); height: var(--ctrl-h); text-align: center; }
+.pagination__sizes .select { height: var(--ctrl-h); }
+.pagination__total { color: var(--t-secondary); }
+
+/* ============================================================
+   八态演示面板
+   ============================================================ */
+.demo { margin-top: var(--sp-2); }
+.demo summary {
+  cursor: pointer; list-style: none; display: flex; align-items: center; gap: var(--sp-2);
+  font-size: var(--fs-base); font-weight: 500; color: var(--t-primary); padding: var(--sp-1) 0;
+}
+.demo summary::-webkit-details-marker { display: none; }
+.demo summary .icon { transition: transform var(--d-base) var(--ease); color: var(--t-secondary); }
+.demo[open] summary .icon { transform: rotate(90deg); }
+.demo__body { padding: var(--sp-5) 0 0; display: flex; flex-direction: column; gap: var(--sp-6); }
+.demo-group__title { font-size: var(--fs-base); font-weight: 500; color: var(--t-primary); margin: 0 0 var(--sp-3); }
+.demo-row { display: flex; flex-wrap: wrap; gap: var(--sp-4); align-items: flex-end; }
+.demo-cell { display: flex; flex-direction: column; gap: var(--sp-2); }
+.demo-cell__tag { font-size: var(--fs-sm); color: var(--t-secondary); }
+.demo-note { font-size: var(--fs-sm); color: var(--t-secondary); }
+
+/* 演示用强制态(静态呈现,无需交互即可查看) */
+.show-hover:hover { background: var(--bg-hover); }
+.btn.show-hover:hover { background: var(--c-primary-hover); border-color: var(--c-primary-hover); color: var(--t-on-primary); }
+.btn--default.show-hover:hover { background: var(--bg-card); color: var(--c-primary-hover); border-color: var(--c-primary-hover); }
+.show-focus { box-shadow: 0 0 0 var(--ring-1) var(--bg-card), 0 0 0 var(--ring-2) var(--c-ring) !important; outline: none; }
+.btn.show-active, .btn--primary.show-active { background: var(--c-primary-active); border-color: var(--c-primary-active); color: var(--t-on-primary); }
+.demo-row .show-selected { background: var(--bg-selected); }
+
+.sr-only { position: absolute; width: var(--sr); height: var(--sr); padding: 0; margin: calc(-1 * var(--sr)); overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0; }
+
+/* ============================================================
+   减少动效偏好
+   ============================================================ */
+@media (prefers-reduced-motion: reduce) {
+  *, *::before, *::after { animation-duration: 0.001ms !important; transition-duration: 0.001ms !important; }
+  .btn.is-loading::after { animation: none; }
+}
+</style>
+</head>
+<body>
+<div class="screen">
+
+  <!-- 顶部应用栏(grounding) -->
+  <header class="appbar">
+    <div class="appbar__logo">
+      <span class="mark">
+        <svg class="icon icon--current" viewBox="0 0 24 24" aria-hidden="true"><path d="M4 11.5 12 5l8 6.5V20a1 1 0 0 1-1 1h-4v-6H9v6H5a1 1 0 0 1-1-1v-8.5Z"/></svg>
+      </span>
+      浠艾福 · 管理后台
+    </div>
+    <div class="appbar__right">
+      <span class="appbar__user">
+        <span class="appbar__avatar">
+          <svg class="icon icon--current icon--sm" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 12a4 4 0 1 0 0-8 4 4 0 0 0 0 8Zm0 2c-4 0-7 2-7 5v1h14v-1c0-3-3-5-7-5Z"/></svg>
+        </span>
+        运营管理员 (admin)
+      </span>
+    </div>
+  </header>
+
+  <main class="page">
+
+    <!-- 页头 -->
+    <div class="page-header">
+      <div class="page-header__titles">
+        <h1 class="page-title">家庭运营工作台</h1>
+        <span class="page-subtitle">管理便捷视角 · 全局概览与快捷作业入口</span>
+      </div>
+      <div class="page-header__actions">
+        <button class="btn btn--default" type="button">
+          <svg class="icon icon--current" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 5V2L8 6l4 4V7a5 5 0 1 1-5 5H5a7 7 0 1 0 7-7Z"/></svg>
+          刷新
+        </button>
+      </div>
+    </div>
+
+    <!-- ① 全局运营概览(统计带,带内主指标打破等权重) -->
+    <section class="card" aria-label="全局运营概览">
+      <div class="card__header">
+        <h2 class="section-title">全局运营概览</h2>
+        <span class="card__header-note">聚合口径:当前为前端求和兜底示例</span>
+      </div>
+      <div class="card__body">
+        <div class="stat-band">
+          <!-- 主指标 -->
+          <div class="stat-hero">
+            <div class="stat-hero__label">
+              <svg class="icon icon--current" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 2v20M7 6h7a3 3 0 0 1 0 6H8m0 0h6a3 3 0 0 1 0 6H7"/></svg>
+              家庭总收益(元)
+            </div>
+            <div class="stat-hero__value">1,284,560</div>
+            <div class="stat-hero__sub">本月新增 +86,420</div>
+          </div>
+          <!-- 其余 6 项 -->
+          <div class="stat-grid">
+            <div class="stat-cell">
+              <div class="stat-cell__label">
+                <svg class="icon icon--current icon--sm" viewBox="0 0 24 24" aria-hidden="true"><path d="M16 11a4 4 0 1 0 0-8 4 4 0 0 0 0 8Zm-8 0a4 4 0 1 0 0-8 4 4 0 0 0 0 8Zm0 2c-3 0-6 1.5-6 4.5V20h12v-2.5C10 14.5 7 13 8 13Zm8 0c-.6 0-1.3.05-2 .15C16.2 14.7 18 16.3 18 18.5V20h4v-2.5c0-3-3-4.5-6-4.5Z"/></svg>
+                家庭总数
+              </div>
+              <div class="stat-cell__value">1,204</div>
+              <div class="stat-cell__sub">启用中 1,138</div>
+            </div>
+            <div class="stat-cell">
+              <div class="stat-cell__label">
+                <svg class="icon icon--current icon--sm" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 12a4 4 0 1 0 0-8 4 4 0 0 0 0 8Zm0 2c-4 0-8 2-8 5v1h16v-1c0-3-4-5-8-5Z"/></svg>
+                成员总数
+              </div>
+              <div class="stat-cell__value">5,732</div>
+              <div class="stat-cell__sub">含孩子 3,910</div>
+            </div>
+            <div class="stat-cell">
+              <div class="stat-cell__label">
+                <svg class="icon icon--current icon--sm" viewBox="0 0 24 24" aria-hidden="true"><path d="M6 3h9l4 4v14a1 1 0 0 1-1 1H6a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1Zm8 1.5V8h3.5L14 4.5ZM8 12h8v2H8v-2Zm0 4h8v2H8v-2Z"/></svg>
+                本月报告数
+              </div>
+              <div class="stat-cell__value">9,846</div>
+              <div class="stat-cell__sub">日均 328</div>
+            </div>
+            <div class="stat-cell">
+              <div class="stat-cell__label">
+                <svg class="icon icon--current icon--sm" viewBox="0 0 24 24" aria-hidden="true"><path d="M5 4h14a1 1 0 0 1 1 1v15l-3-2-3 2-3-2-3 2-3-2V5a1 1 0 0 1 1-1Zm3 5v2h8V9H8Zm0 4v2h6v-2H8Z"/></svg>
+                方案总数
+              </div>
+              <div class="stat-cell__value">2,317</div>
+              <div class="stat-cell__sub">已发布 1,984</div>
+            </div>
+            <div class="stat-cell">
+              <div class="stat-cell__label">
+                <svg class="icon icon--current icon--sm" viewBox="0 0 24 24" aria-hidden="true"><path d="M9 3h6v2h3a1 1 0 0 1 1 1v14a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V6a1 1 0 0 1 1-1h3V3Zm0 4v2h6V7H9Zm-1 5 2 2 4-4"/></svg>
+                任务总数
+              </div>
+              <div class="stat-cell__value">6,503</div>
+              <div class="stat-cell__sub">进行中 1,202</div>
+            </div>
+            <div class="stat-cell">
+              <div class="stat-cell__label">
+                <svg class="icon icon--current icon--sm" viewBox="0 0 24 24" aria-hidden="true"><path d="M4 5h16a1 1 0 0 1 1 1v12a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V6a1 1 0 0 1 1-1Zm2 4h4v4H6V9Zm6 0h6v2h-6V9Zm0 4h6v2h-6v-2Z"/></svg>
+                已发优惠券
+              </div>
+              <div class="stat-cell__value">14,260</div>
+              <div class="stat-cell__sub">未核销 5,118</div>
+            </div>
+          </div>
+        </div>
+        <p class="stat-note"><strong>注:</strong>现有 <code>getFamilyList</code> / <code>getFamilyOverview</code> 仅返回单家庭明细;全局聚合需新增聚合接口,或由前端对分页数据求和兜底(本草稿数字为代表性占位)。</p>
+      </div>
+    </section>
+
+    <!-- ② 筛选 / 排序条 -->
+    <section class="card" aria-label="筛选">
+      <div class="card__header">
+        <h2 class="section-title">筛选与检索</h2>
+        <button class="link-toggle is-open" type="button" aria-expanded="true">
+          收起高级筛选
+          <svg class="icon icon--current icon--sm" viewBox="0 0 24 24" aria-hidden="true"><path d="m6 9 6 6 6-6"/></svg>
+        </button>
+      </div>
+      <div class="card__body">
+        <div class="filter-bar">
+          <!-- 主检索行 -->
+          <div class="filter-row">
+            <div class="field">
+              <label class="field__label" for="f-name">家庭名称</label>
+              <div class="input-wrap">
+                <input id="f-name" class="input input--w" type="text" placeholder="请输入家庭名称" value="幸福" />
+                <svg class="icon icon--current icon--sm" viewBox="0 0 24 24" aria-hidden="true"><path d="M10 4a6 6 0 1 0 3.7 10.7l4.3 4.3 1.4-1.4-4.3-4.3A6 6 0 0 0 10 4Zm0 2a4 4 0 1 1 0 8 4 4 0 0 1 0-8Z"/></svg>
+              </div>
+            </div>
+            <button class="btn btn--primary" type="button">
+              <svg class="icon icon--current" viewBox="0 0 24 24" aria-hidden="true"><path d="M10 4a6 6 0 1 0 3.7 10.7l4.3 4.3 1.4-1.4-4.3-4.3A6 6 0 0 0 10 4Zm0 2a4 4 0 1 1 0 8 4 4 0 0 1 0-8Z"/></svg>
+              搜索
+            </button>
+            <button class="btn btn--default" type="button">重置</button>
+            <div class="filter-spacer"></div>
+            <button class="btn btn--text" type="button">
+              <svg class="icon icon--current" viewBox="0 0 24 24" aria-hidden="true"><path d="M5 8h14M5 12h14M5 16h14" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round"/></svg>
+              高级筛选
+            </button>
+          </div>
+          <!-- 高级筛选行 -->
+          <div class="filter-row filter-row--advanced">
+            <div class="field">
+              <label class="field__label" for="f-code">邀请码</label>
+              <input id="f-code" class="input input--sm" type="text" placeholder="如 XF8K2P" />
+            </div>
+            <div class="field">
+              <label class="field__label" for="f-owner">负责人</label>
+              <input id="f-owner" class="input input--sm" type="text" placeholder="运营 / 规划师" />
+            </div>
+            <div class="field">
+              <label class="field__label" for="f-time-start">创建时间区间</label>
+              <div style="display:flex;align-items:flex-end;gap:var(--sp-2)">
+                <input id="f-time-start" class="input input--sm" type="text" placeholder="开始日期" value="2024-09-01" />
+                <span class="range-sep">~</span>
+                <input id="f-time-end" class="input input--sm" type="text" placeholder="结束日期" value="2024-11-30" aria-label="结束日期" />
+              </div>
+            </div>
+            <div class="field">
+              <label class="field__label" for="f-members-min">成员数区间</label>
+              <div style="display:flex;align-items:flex-end;gap:var(--sp-2)">
+                <input id="f-members-min" class="input input--sm" type="text" placeholder="最小" value="0" />
+                <span class="range-sep">~</span>
+                <input id="f-members-max" class="input input--sm" type="text" placeholder="最大" value="20" aria-label="最大成员数" />
+              </div>
+            </div>
+            <div class="field">
+              <label class="field__label" for="f-status">启用状态</label>
+              <select id="f-status" class="select select--sm">
+                <option>全部</option>
+                <option>已启用</option>
+                <option>已停用</option>
+              </select>
+            </div>
+          </div>
+        </div>
+      </div>
+    </section>
+
+    <!-- ③④ 指标列表(英雄主角) -->
+    <section class="card" aria-label="家庭列表与运营指标">
+      <div class="card__header">
+        <h2 class="section-title">家庭列表 · 运营指标</h2>
+        <span class="card__header-note">共 1,204 条 · 当前页 6 条</span>
+      </div>
+      <div class="card__body">
+        <!-- 批量操作条(选中态) -->
+        <div class="batch-bar">
+          <span class="batch-bar__count">已选 3 项</span>
+          <button class="btn btn--default" type="button">批量导出</button>
+          <button class="btn btn--default" type="button">批量启用</button>
+          <button class="btn btn--default" type="button">批量停用</button>
+          <div class="batch-bar__spacer"></div>
+          <button class="btn btn--text" type="button">清空选择</button>
+        </div>
+
+        <div class="table-scroll">
+          <table class="grid">
+            <thead>
+              <tr>
+                <th class="col-cb">
+                  <span class="checkbox is-indeterminate" title="部分选中" aria-label="全选">
+                    <svg viewBox="0 0 24 24" aria-hidden="true"><path d="M5 12h14"/></svg>
+                  </span>
+                </th>
+                <th class="col-id">ID</th>
+                <th class="col-name">家庭名称</th>
+                <th class="col-code">邀请码</th>
+                <th class="col-time">创建时间</th>
+                <th class="col-members num">成员数</th>
+                <th class="col-reports num">报告数</th>
+                <th class="col-plans num">方案数</th>
+                <th class="col-tasks num">任务数</th>
+                <th class="col-coupons num">优惠券数</th>
+                <th class="col-active">最近活跃</th>
+                <th class="col-rate">报告完成率</th>
+                <th class="col-status">启用状态</th>
+                <th class="col-op">操作</th>
+              </tr>
+            </thead>
+            <tbody>
+              <!-- 行 1:含展开的「更多」真实菜单 -->
+              <tr>
+                <td class="col-cb"><span class="checkbox is-checked" aria-label="已选"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M5 12l5 5 9-10"/></svg></span></td>
+                <td>10231</td>
+                <td><strong>幸福一家人</strong></td>
+                <td><span class="cell-code">XF8K2P</span></td>
+                <td>2024-11-02 14:33</td>
+                <td class="num"><span class="cell-link">6</span></td>
+                <td class="num"><span class="cell-link">48</span></td>
+                <td class="num"><span class="cell-link">3</span></td>
+                <td class="num"><span class="cell-link">12</span></td>
+                <td class="num"><span class="cell-link">5</span></td>
+                <td><span class="status status--success">2 分钟前</span></td>
+                <td>
+                  <div class="rate"><div class="rate__bar"><div class="rate__fill" style="width:92%"></div></div><span class="rate__val">92%</span></div>
+                </td>
+                <td>
+                  <label class="switch"><input type="checkbox" checked /><span class="switch__track"></span><span class="switch__thumb"></span></label>
+                </td>
+                <td class="col-op">
+                  <button class="btn btn--primary" type="button" style="height:var(--ctrl-sm-h);padding:0 var(--sp-3)">编辑</button>
+                  <span class="dropdown">
+                    <button class="btn btn--default" type="button" style="height:var(--ctrl-sm-h);padding:0 var(--sp-3)">
+                      更多
+                      <svg class="icon icon--current icon--sm" viewBox="0 0 24 24" aria-hidden="true"><path d="m6 9 6 6 6-6"/></svg>
+                    </button>
+                    <span class="dropdown__menu">
+                      <span class="dropdown__item"><svg class="icon icon--current" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 12a4 4 0 1 0 0-8 4 4 0 0 0 0 8Zm0 2c-4 0-8 2-8 5v1h16v-1c0-3-4-5-8-5Z"/></svg>查看成员</span>
+                      <span class="dropdown__item"><svg class="icon icon--current" viewBox="0 0 24 24" aria-hidden="true"><path d="M6 3h9l4 4v14H6V3Zm3 7h6v2H9v-2Zm0 4h6v2H9v-2Z"/></svg>报告明细</span>
+                      <span class="dropdown__item"><svg class="icon icon--current" viewBox="0 0 24 24" aria-hidden="true"><path d="M5 4h14v16H5zM8 9h8v2H8zm0 4h8v2H8z"/></svg>方案明细</span>
+                      <span class="dropdown__item"><svg class="icon icon--current" viewBox="0 0 24 24" aria-hidden="true"><path d="M9 3h6v2h3v16H6V5h3V3Zm0 8 2 2 4-4"/></svg>任务明细</span>
+                      <span class="dropdown__item"><svg class="icon icon--current" viewBox="0 0 24 24" aria-hidden="true"><path d="M4 5h16v12H4zM8 11h6v2H8zm0 4h6v2H8z"/></svg>优惠券</span>
+                      <span class="dropdown__item"><svg class="icon icon--current" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 2v20M7 6h7a3 3 0 0 1 0 6H8m0 0h6a3 3 0 0 1 0 6H7"/></svg>收益</span>
+                      <span class="dropdown__item"><svg class="icon icon--current" viewBox="0 0 24 24" aria-hidden="true"><path d="M5 4h14v16H5zM8 8h8v2H8zm0 4h5v2H8z"/></svg>配置</span>
+                    </span>
+                  </span>
+                </td>
+              </tr>
+
+              <!-- 行 2 -->
+              <tr>
+                <td class="col-cb"><span class="checkbox is-checked" aria-label="已选"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M5 12l5 5 9-10"/></svg></span></td>
+                <td>10230</td>
+                <td><strong>向阳花开</strong></td>
+                <td><span class="cell-code">XY7M9Q</span></td>
+                <td>2024-10-28 09:12</td>
+                <td class="num"><span class="cell-link">4</span></td>
+                <td class="num"><span class="cell-link">31</span></td>
+                <td class="num"><span class="cell-link">2</span></td>
+                <td class="num"><span class="cell-link">8</span></td>
+                <td class="num"><span class="cell-link">2</span></td>
+                <td><span class="status status--info">15 分钟前</span></td>
+                <td>
+                  <div class="rate"><div class="rate__bar"><div class="rate__fill" style="width:88%"></div></div><span class="rate__val">88%</span></div>
+                </td>
+                <td>
+                  <label class="switch"><input type="checkbox" checked /><span class="switch__track"></span><span class="switch__thumb"></span></label>
+                </td>
+                <td class="col-op">
+                  <button class="btn btn--primary" type="button" style="height:var(--ctrl-sm-h);padding:0 var(--sp-3)">编辑</button>
+                  <button class="btn btn--default" type="button" style="height:var(--ctrl-sm-h);padding:0 var(--sp-3)">更多 <svg class="icon icon--current icon--sm" viewBox="0 0 24 24" aria-hidden="true"><path d="m6 9 6 6 6-6"/></svg></button>
+                </td>
+              </tr>
+
+              <!-- 行 3:0 成员 / 停用 -->
+              <tr>
+                <td class="col-cb"><span class="checkbox" aria-label="未选"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M5 12l5 5 9-10"/></svg></span></td>
+                <td>10229</td>
+                <td><strong>晨光小屋</strong></td>
+                <td><span class="cell-code">CG3W5L</span></td>
+                <td>2024-10-15 20:45</td>
+                <td class="num"><span class="cell-zero">0</span></td>
+                <td class="num"><span class="cell-zero">0</span></td>
+                <td class="num"><span class="cell-zero">0</span></td>
+                <td class="num"><span class="cell-zero">0</span></td>
+                <td class="num"><span class="cell-zero">0</span></td>
+                <td><span class="status status--default">3 天前</span></td>
+                <td>
+                  <div class="rate"><div class="rate__bar"><div class="rate__fill" style="width:0%"></div></div><span class="rate__val">0%</span></div>
+                </td>
+                <td>
+                  <label class="switch"><input type="checkbox" /><span class="switch__track"></span><span class="switch__thumb"></span></label>
+                </td>
+                <td class="col-op">
+                  <button class="btn btn--primary" type="button" style="height:var(--ctrl-sm-h);padding:0 var(--sp-3)">编辑</button>
+                  <button class="btn btn--default" type="button" style="height:var(--ctrl-sm-h);padding:0 var(--sp-3)">更多 <svg class="icon icon--current icon--sm" viewBox="0 0 24 24" aria-hidden="true"><path d="m6 9 6 6 6-6"/></svg></button>
+                </td>
+              </tr>
+
+              <!-- 行 4:选中态(整行高亮) -->
+              <tr class="is-selected">
+                <td class="col-cb"><span class="checkbox is-checked" aria-label="已选"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M5 12l5 5 9-10"/></svg></span></td>
+                <td>10228</td>
+                <td><strong>萌芽之家</strong></td>
+                <td><span class="cell-code">MY6T1R</span></td>
+                <td>2024-09-30 11:08</td>
+                <td class="num"><span class="cell-link">3</span></td>
+                <td class="num"><span class="cell-link">19</span></td>
+                <td class="num"><span class="cell-link">1</span></td>
+                <td class="num"><span class="cell-link">5</span></td>
+                <td class="num"><span class="cell-link">1</span></td>
+                <td><span class="status status--info">1 小时前</span></td>
+                <td>
+                  <div class="rate"><div class="rate__bar"><div class="rate__fill" style="width:76%"></div></div><span class="rate__val">76%</span></div>
+                </td>
+                <td>
+                  <label class="switch"><input type="checkbox" checked /><span class="switch__track"></span><span class="switch__thumb"></span></label>
+                </td>
+                <td class="col-op">
+                  <button class="btn btn--primary" type="button" style="height:var(--ctrl-sm-h);padding:0 var(--sp-3)">编辑</button>
+                  <button class="btn btn--default" type="button" style="height:var(--ctrl-sm-h);padding:0 var(--sp-3)">更多 <svg class="icon icon--current icon--sm" viewBox="0 0 24 24" aria-hidden="true"><path d="m6 9 6 6 6-6"/></svg></button>
+                </td>
+              </tr>
+
+              <!-- 行 5 -->
+              <tr>
+                <td class="col-cb"><span class="checkbox" aria-label="未选"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M5 12l5 5 9-10"/></svg></span></td>
+                <td>10227</td>
+                <td><strong>星河湾家庭</strong></td>
+                <td><span class="cell-code">XH9B4N</span></td>
+                <td>2024-09-12 16:20</td>
+                <td class="num"><span class="cell-link">8</span></td>
+                <td class="num"><span class="cell-link">67</span></td>
+                <td class="num"><span class="cell-link">5</span></td>
+                <td class="num"><span class="cell-link">21</span></td>
+                <td class="num"><span class="cell-link">9</span></td>
+                <td><span class="status status--success">5 分钟前</span></td>
+                <td>
+                  <div class="rate"><div class="rate__bar"><div class="rate__fill" style="width:95%"></div></div><span class="rate__val">95%</span></div>
+                </td>
+                <td>
+                  <label class="switch"><input type="checkbox" checked /><span class="switch__track"></span><span class="switch__thumb"></span></label>
+                </td>
+                <td class="col-op">
+                  <button class="btn btn--primary" type="button" style="height:var(--ctrl-sm-h);padding:0 var(--sp-3)">编辑</button>
+                  <button class="btn btn--default" type="button" style="height:var(--ctrl-sm-h);padding:0 var(--sp-3)">更多 <svg class="icon icon--current icon--sm" viewBox="0 0 24 24" aria-hidden="true"><path d="m6 9 6 6 6-6"/></svg></button>
+                </td>
+              </tr>
+
+              <!-- 行 6:停用 -->
+              <tr>
+                <td class="col-cb"><span class="checkbox" aria-label="未选"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M5 12l5 5 9-10"/></svg></span></td>
+                <td>10226</td>
+                <td><strong>晚晴居</strong></td>
+                <td><span class="cell-code">WQ2D7K</span></td>
+                <td>2024-08-21 13:55</td>
+                <td class="num"><span class="cell-link">2</span></td>
+                <td class="num"><span class="cell-link">7</span></td>
+                <td class="num"><span class="cell-link">1</span></td>
+                <td class="num"><span class="cell-link">3</span></td>
+                <td class="num"><span class="cell-zero">0</span></td>
+                <td><span class="status status--warning">2 小时前</span></td>
+                <td>
+                  <div class="rate"><div class="rate__bar"><div class="rate__fill" style="width:64%"></div></div><span class="rate__val">64%</span></div>
+                </td>
+                <td>
+                  <label class="switch"><input type="checkbox" /><span class="switch__track"></span><span class="switch__thumb"></span></label>
+                </td>
+                <td class="col-op">
+                  <button class="btn btn--primary" type="button" style="height:var(--ctrl-sm-h);padding:0 var(--sp-3)">编辑</button>
+                  <button class="btn btn--default" type="button" style="height:var(--ctrl-sm-h);padding:0 var(--sp-3)">更多 <svg class="icon icon--current icon--sm" viewBox="0 0 24 24" aria-hidden="true"><path d="m6 9 6 6 6-6"/></svg></button>
+                </td>
+              </tr>
+            </tbody>
+          </table>
+        </div>
+
+        <!-- ⑤ 页脚:分页 + 导出 -->
+        <div class="page-footer" style="margin-top:var(--sp-4)">
+          <button class="btn btn--default" type="button">
+            <svg class="icon icon--current" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3v12m0 0 4-4m-4 4-4-4M4 17v2a1 1 0 0 0 1 1h14a1 1 0 0 0 1-1v-2" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"/></svg>
+            导出当前结果
+          </button>
+          <nav class="pagination" aria-label="分页">
+            <span class="pagination__total">共 1,204 条</span>
+            <button class="pagination__btn" disabled aria-label="上一页">‹</button>
+            <button class="pagination__btn is-active" aria-current="page">1</button>
+            <button class="pagination__btn">2</button>
+            <button class="pagination__btn">3</button>
+            <span style="color:var(--t-secondary)">…</span>
+            <button class="pagination__btn">61</button>
+            <button class="pagination__btn" aria-label="下一页">›</button>
+            <span class="pagination__sizes">
+              <select class="select" aria-label="每页条数"><option>10 条/页</option><option>20 条/页</option><option>50 条/页</option><option>100 条/页</option></select>
+            </span>
+            <span class="pagination__jump">跳至 <input class="input" type="text" value="1" /> 页</span>
+          </nav>
+        </div>
+      </div>
+    </section>
+
+    <!-- 快捷入口网格(10 张卡片) -->
+    <section class="card" aria-label="快捷入口">
+      <div class="card__header">
+        <h2 class="section-title">快捷入口</h2>
+        <span class="card__header-note">从本屏直达全部家庭运营模块</span>
+      </div>
+      <div class="card__body">
+        <div class="qe-grid">
+          <a class="qe-card is-current" href="#">
+            <span class="qe-icon"><svg class="icon icon--current" viewBox="0 0 24 24" aria-hidden="true"><path d="M16 11a4 4 0 1 0 0-8 4 4 0 0 0 0 8Zm-8 0a4 4 0 1 0 0-8 4 4 0 0 0 0 8Zm0 2c-3 0-6 1.5-6 4.5V20h12v-2.5C10 14.5 7 13 8 13Zm8 0c-.6 0-1.3.05-2 .15C16.2 14.7 18 16.3 18 18.5V20h4v-2.5c0-3-3-4.5-6-4.5Z"/></svg></span>
+            <span class="qe-meta"><span class="qe-title">家庭列表</span><span class="qe-sub">/families · 当前</span></span>
+          </a>
+          <a class="qe-card" href="#">
+            <span class="qe-icon"><svg class="icon icon--current" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 12a4 4 0 1 0 0-8 4 4 0 0 0 0 8Zm0 2c-4 0-8 2-8 5v1h16v-1c0-3-4-5-8-5Z"/></svg></span>
+            <span class="qe-meta"><span class="qe-title">孩子管理</span><span class="qe-sub">/children</span></span>
+          </a>
+          <a class="qe-card" href="#">
+            <span class="qe-icon"><svg class="icon icon--current" viewBox="0 0 24 24" aria-hidden="true"><path d="M4 5h16v12H4zM8 11h6v2H8zm0 4h6v2H8zM8 8h8v2H8z"/></svg></span>
+            <span class="qe-meta"><span class="qe-title">积分管理</span><span class="qe-sub">/points</span></span>
+          </a>
+          <a class="qe-card" href="#">
+            <span class="qe-icon"><svg class="icon icon--current" viewBox="0 0 24 24" aria-hidden="true"><path d="M6 3h9l4 4v14H6V3Zm3 7h6v2H9v-2Zm0 4h6v2H9v-2Z"/></svg></span>
+            <span class="qe-meta"><span class="qe-title">积分记录</span><span class="qe-sub">/points-log</span></span>
+          </a>
+          <a class="qe-card" href="#">
+            <span class="qe-icon"><svg class="icon icon--current" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3l3 6 6 .9-4.5 4.3 1.1 6.3L12 17.8 6.4 20.8l1.1-6.3L3 9.9 9 9l3-6Z"/></svg></span>
+            <span class="qe-meta"><span class="qe-title">心愿管理</span><span class="qe-sub">/wishes</span></span>
+          </a>
+          <a class="qe-card" href="#">
+            <span class="qe-icon"><svg class="icon icon--current" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3a4 4 0 0 0-4 4v2H7a2 2 0 0 0-2 2v9h14v-9a2 2 0 0 0-2-2h-1V7a4 4 0 0 0-4-4Zm0 3a1 1 0 0 1 1 1v2h-2V7a1 1 0 0 1 1-1Z"/></svg></span>
+            <span class="qe-meta"><span class="qe-title">奖励管理</span><span class="qe-sub">/rewards</span></span>
+          </a>
+          <a class="qe-card" href="#">
+            <span class="qe-icon"><svg class="icon icon--current" viewBox="0 0 24 24" aria-hidden="true"><path d="M5 4h14v16H5zM8 8h8v2H8zm0 4h5v2H8z"/></svg></span>
+            <span class="qe-meta"><span class="qe-title">汇总方式配置</span><span class="qe-sub">/family-metric-agg-config</span></span>
+          </a>
+          <a class="qe-card" href="#">
+            <span class="qe-icon"><svg class="icon icon--current" viewBox="0 0 24 24" aria-hidden="true"><path d="M4 5h16v12H4zM8 11h6v2H8zm0 4h6v2H8z"/></svg></span>
+            <span class="qe-meta"><span class="qe-title">家庭优惠券</span><span class="qe-sub">/family-coupon</span></span>
+          </a>
+          <a class="qe-card" href="#">
+            <span class="qe-icon"><svg class="icon icon--current" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 2v20M7 6h7a3 3 0 0 1 0 6H8m0 0h6a3 3 0 0 1 0 6H7"/></svg></span>
+            <span class="qe-meta"><span class="qe-title">家庭收益</span><span class="qe-sub">/family-earnings</span></span>
+          </a>
+          <a class="qe-card" href="#">
+            <span class="qe-icon"><svg class="icon icon--current" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 2 4 6v6c0 4 3.5 7 8 8 4.5-1 8-4 8-8V6l-8-4Zm-1 12-3-3 1.4-1.4L11 11.2l4.6-4.6L17 8l-6 6Z"/></svg></span>
+            <span class="qe-meta"><span class="qe-title">提现审核</span><span class="qe-sub">/family-earnings-withdraw</span></span>
+          </a>
+        </div>
+      </div>
+    </section>
+
+    <!-- 八态演示面板(可折叠) -->
+    <section class="card demo" aria-label="八态演示面板">
+      <div class="card__header">
+        <h2 class="section-title">八态演示面板</h2>
+        <span class="card__header-note">default / hover / focus / active / disabled / loading / error / success</span>
+      </div>
+      <div class="card__body">
+        <details class="demo" open>
+          <summary>
+            <svg class="icon icon--current" viewBox="0 0 24 24" aria-hidden="true"><path d="m9 6 6 6-6 6"/></svg>
+            展开:关键交互元素的完整八态
+          </summary>
+          <div class="demo__body">
+
+            <!-- 按钮八态 -->
+            <div>
+              <h3 class="demo-group__title">按钮(主按钮)</h3>
+              <div class="demo-row">
+                <div class="demo-cell"><button class="btn btn--primary" type="button">default</button><span class="demo-cell__tag">默认</span></div>
+                <div class="demo-cell"><button class="btn btn--primary show-hover" type="button">hover</button><span class="demo-cell__tag">悬停(静态呈现)</span></div>
+                <div class="demo-cell"><button class="btn btn--primary show-focus" type="button">focus</button><span class="demo-cell__tag">键盘焦点(环 ≥3:1)</span></div>
+                <div class="demo-cell"><button class="btn btn--primary show-active" type="button">active</button><span class="demo-cell__tag">按压 / 选中</span></div>
+                <div class="demo-cell"><button class="btn btn--primary is-disabled" type="button" disabled>disabled</button><span class="demo-cell__tag">禁用(视觉+语义)</span></div>
+                <div class="demo-cell"><button class="btn btn--primary is-loading" type="button">loading</button><span class="demo-cell__tag">加载中</span></div>
+                <div class="demo-cell"><button class="btn btn--error" type="button">error</button><span class="demo-cell__tag">错误态</span></div>
+                <div class="demo-cell"><button class="btn btn--success" type="button">success</button><span class="demo-cell__tag">成功态</span></div>
+              </div>
+            </div>
+
+            <!-- 输入框八态 -->
+            <div>
+              <h3 class="demo-group__title">输入框</h3>
+              <div class="demo-row">
+                <div class="demo-cell"><div class="field"><input class="input input--w" type="text" placeholder="默认输入" /><span class="demo-cell__tag">default</span></div></div>
+                <div class="demo-cell"><div class="field"><input class="input input--w show-focus" type="text" value="focus" /><span class="demo-cell__tag">focus(环)</span></div></div>
+                <div class="demo-cell"><div class="field"><input class="input input--w is-disabled" type="text" value="禁用" disabled /><span class="demo-cell__tag">disabled</span></div></div>
+                <div class="demo-cell"><div class="field"><input class="input input--w is-error" type="text" value="非法值" /><span class="field__error">邀请码格式不正确</span><span class="demo-cell__tag">error</span></div></div>
+                <div class="demo-cell"><div class="field"><input class="input input--w" type="text" placeholder="加载中…" disabled style="background:var(--bg-fill)" /><span class="demo-cell__tag">loading(读屏提示)</span></div></div>
+                <div class="demo-cell"><div class="field"><input class="input input--w" type="text" value="已保存" /><span class="status status--success" style="margin-top:var(--pad-2)">校验通过</span><span class="demo-cell__tag">success</span></div></div>
+                <div class="demo-cell"><div class="field"><input class="input input--w" type="text" placeholder="无内容" /><span class="demo-cell__tag">empty</span></div></div>
+                <div class="demo-cell"><div class="field"><button class="btn btn--primary show-active" type="button">active</button><span class="demo-cell__tag">active</span></div></div>
+              </div>
+            </div>
+
+            <!-- 开关八态 -->
+            <div>
+              <h3 class="demo-group__title">开关(启用状态)</h3>
+              <div class="demo-row">
+                <div class="demo-cell"><label class="switch"><input type="checkbox" checked /><span class="switch__track"></span><span class="switch__thumb"></span></label><span class="demo-cell__tag">on(default)</span></div>
+                <div class="demo-cell"><label class="switch"><input type="checkbox" /><span class="switch__track"></span><span class="switch__thumb"></span></label><span class="demo-cell__tag">off(default)</span></div>
+                <div class="demo-cell"><label class="switch"><input type="checkbox" checked class="show-focus-switch" /><span class="switch__track"></span><span class="switch__thumb"></span></label><span class="demo-cell__tag">focus(环)</span></div>
+                <div class="demo-cell"><label class="switch is-disabled"><input type="checkbox" disabled /><span class="switch__track"></span><span class="switch__thumb"></span></label><span class="demo-cell__tag">disabled</span></div>
+                <div class="demo-cell"><label class="switch is-loading"><input type="checkbox" checked /><span class="switch__track"></span><span class="switch__thumb"></span></label><span class="demo-cell__tag">loading</span></div>
+                <div class="demo-cell"><label class="switch"><input type="checkbox" checked /><span class="switch__track"></span><span class="switch__thumb"></span></label><span class="switch__label">启用</span><span class="demo-cell__tag">on + label</span></div>
+              </div>
+            </div>
+
+            <!-- 表格行八态 -->
+            <div>
+              <h3 class="demo-group__title">表格行</h3>
+              <div class="demo-row" style="align-items:stretch">
+                <div class="demo-cell" style="flex:1;min-width:var(--demo-tbl-w)">
+                  <div class="table-scroll" style="min-width:auto">
+                    <table class="grid" style="min-width:auto">
+                      <thead><tr><th class="col-cb"><span class="checkbox" aria-hidden="true"></span></th><th>家庭</th><th class="num">成员</th><th class="col-op">操作</th></tr></thead>
+                      <tbody>
+                        <tr><td class="col-cb">·</td><td>普通行 default</td><td class="num">6</td><td class="col-op">编辑</td></tr>
+                        <tr class="show-hover" style="background:var(--bg-hover)"><td class="col-cb">·</td><td>悬停 hover</td><td class="num">4</td><td class="col-op">编辑</td></tr>
+                        <tr class="is-selected"><td class="col-cb">·</td><td>选中 selected</td><td class="num">3</td><td class="col-op">编辑</td></tr>
+                        <tr style="opacity:.55"><td class="col-cb">·</td><td>禁用 disabled</td><td class="num">0</td><td class="col-op">编辑</td></tr>
+                        <tr><td class="col-cb">·</td><td>加载 loading(行内骨架)</td><td class="num">—</td><td class="col-op">编辑</td></tr>
+                        <tr><td class="col-cb">·</td><td>错误 error(红色描边)</td><td class="num"><span class="status status--error">失败</span></td><td class="col-op">编辑</td></tr>
+                        <tr><td class="col-cb">·</td><td>成功 success(绿色态)</td><td class="num"><span class="status status--success">通过</span></td><td class="col-op">编辑</td></tr>
+                        <tr style="color:var(--t-secondary)"><td class="col-cb">·</td><td>(空状态)暂无数据</td><td class="num">0</td><td class="col-op">—</td></tr>
+                      </tbody>
+                    </table>
+                  </div>
+                  <span class="demo-cell__tag">八态行示例</span>
+                </div>
+              </div>
+            </div>
+
+            <!-- 下拉八态 -->
+            <div>
+              <h3 class="demo-group__title">下拉(更多菜单)</h3>
+              <div class="demo-row">
+                <div class="demo-cell">
+                  <span class="dropdown">
+                    <button class="btn btn--default" type="button">更多 <svg class="icon icon--current icon--sm" viewBox="0 0 24 24" aria-hidden="true"><path d="m6 9 6 6 6-6"/></svg></button>
+                  </span>
+                  <span class="demo-cell__tag">default(收起)</span>
+                </div>
+                <div class="demo-cell">
+                  <span class="dropdown">
+                    <button class="btn btn--default" type="button">更多 <svg class="icon icon--current icon--sm" viewBox="0 0 24 24" aria-hidden="true"><path d="m6 9 6 6 6-6"/></svg></button>
+                    <span class="dropdown__menu">
+                      <span class="dropdown__item"><svg class="icon icon--current" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 12a4 4 0 1 0 0-8 4 4 0 0 0 0 8Zm0 2c-4 0-8 2-8 5v1h16v-1c0-3-4-5-8-5Z"/></svg>查看成员</span>
+                      <span class="dropdown__item"><svg class="icon icon--current" viewBox="0 0 24 24" aria-hidden="true"><path d="M6 3h9l4 4v14H6V3Zm3 7h6v2H9v-2Zm0 4h6v2H9v-2Z"/></svg>报告明细</span>
+                      <span class="dropdown__item"><svg class="icon icon--current" viewBox="0 0 24 24" aria-hidden="true"><path d="M5 4h14v16H5zM8 9h8v2H8zm0 4h8v2H8z"/></svg>方案明细</span>
+                      <span class="dropdown__item"><svg class="icon icon--current" viewBox="0 0 24 24" aria-hidden="true"><path d="M9 3h6v2h3v16H6V5h3V3Zm0 8 2 2 4-4"/></svg>任务明细</span>
+                      <span class="dropdown__item"><svg class="icon icon--current" viewBox="0 0 24 24" aria-hidden="true"><path d="M4 5h16v12H4zM8 11h6v2H8zm0 4h6v2H8z"/></svg>优惠券</span>
+                      <span class="dropdown__item"><svg class="icon icon--current" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 2v20M7 6h7a3 3 0 0 1 0 6H8m0 0h6a3 3 0 0 1 0 6H7"/></svg>收益</span>
+                      <span class="dropdown__item"><svg class="icon icon--current" viewBox="0 0 24 24" aria-hidden="true"><path d="M5 4h14v16H5zM8 8h8v2H8zm0 4h5v2H8z"/></svg>配置</span>
+                    </span>
+                  </span>
+                  <span class="demo-cell__tag">expanded(7 个真实项)</span>
+                </div>
+                <div class="demo-cell">
+                  <span class="dropdown">
+                    <button class="btn btn--default is-disabled" type="button" disabled>更多</button>
+                  </span>
+                  <span class="demo-cell__tag">disabled</span>
+                </div>
+              </div>
+            </div>
+
+            <p class="demo-note">说明:本面板以静态方式呈现八态,便于评审逐项核对;真实交互由 Vue 组件在 cfc-web 中实现,此处仅作视觉契约。</p>
+          </div>
+        </details>
+      </div>
+    </section>
+
+  </main>
+</div>
+</body>
+</html>

+ 334 - 84
cfc-web/src/views/Families.vue

@@ -1,103 +1,214 @@
 <template>
   <div class="page-container">
-    <el-card>
-      <PageHeader slot="header" title="家庭管理">
+    <!-- 页头 -->
+    <div class="admin-page-header">
+      <div>
+        <span class="admin-page-title">家庭运营工作台</span>
+        <span class="admin-page-subtitle">家庭管理 · 运营总览(从管理方便角度重设计)</span>
+      </div>
+      <div class="admin-page-actions">
         <el-button type="primary" size="small" @click="handleRefresh" :loading="loading">刷新</el-button>
-      </PageHeader>
+      </div>
+    </div>
+
+    <!-- ① 运营统计带(注:聚合口径为当前页合计;家庭总收益无现成字段,标记为待后端接口) -->
+    <div class="stat-band">
+      <div class="stat-card stat-card--primary">
+        <div class="stat-label">家庭总数</div>
+        <div class="stat-value stat-value--primary adm-num">{{ stats.total }}</div>
+      </div>
+      <div class="stat-card">
+        <div class="stat-label">成员总数(本页合计)</div>
+        <div class="stat-value adm-num">{{ stats.members }}</div>
+      </div>
+      <div class="stat-card">
+        <div class="stat-label">报告数(本页合计)</div>
+        <div class="stat-value adm-num">{{ stats.reports }}</div>
+      </div>
+      <div class="stat-card">
+        <div class="stat-label">方案数(本页合计)</div>
+        <div class="stat-value adm-num">{{ stats.plans }}</div>
+      </div>
+      <div class="stat-card">
+        <div class="stat-label">任务数(本页合计)</div>
+        <div class="stat-value adm-num">{{ stats.tasks }}</div>
+      </div>
+      <div class="stat-card">
+        <div class="stat-label">优惠券数(本页合计)</div>
+        <div class="stat-value adm-num">{{ stats.coupons }}</div>
+      </div>
+      <div class="stat-card">
+        <div class="stat-label">家庭总收益</div>
+        <div class="stat-value adm-num" title="需后端新增聚合接口">—</div>
+      </div>
+    </div>
 
-      <!-- 搜索 -->
-      <el-form :inline="true" :model="searchForm" class="mb-20">
+    <!-- ② 快捷入口网格:一屏触达家庭运营全部模块 -->
+    <div class="quick-grid">
+      <div
+        v-for="q in quickEntries"
+        :key="q.path"
+        class="qe-card"
+        :class="{ 'is-active': q.path === currentPath }"
+        @click="goEntry(q.path)"
+      >
+        <i :class="q.icon" class="qe-icon"></i>
+        <span class="qe-label">{{ q.label }}</span>
+      </div>
+    </div>
+
+    <el-card>
+      <div slot="header" class="adm-card-header">
+        <span>家庭列表</span>
+      </div>
+
+      <!-- ③ 高效检索栏:多条件 + 可折叠高级筛选 -->
+      <el-form :inline="true" :model="searchForm" class="filter-bar">
         <el-form-item label="家庭名称">
           <el-input
             v-model="searchForm.name"
-            placeholder="请输入家庭名称"
+            placeholder="家庭名称"
+            clearable
+            style="width: 200px"
+            @keyup.enter.native="handleSearch"
+          ></el-input>
+        </el-form-item>
+        <el-form-item label="邀请码">
+          <el-input
+            v-model="searchForm.inviteCode"
+            placeholder="邀请码"
             clearable
+            style="width: 160px"
             @keyup.enter.native="handleSearch"
           ></el-input>
         </el-form-item>
+        <el-form-item label="创建时间" v-if="advancedVisible">
+          <el-date-picker
+            v-model="dateRange"
+            type="daterange"
+            range-separator="至"
+            start-placeholder="开始"
+            end-placeholder="结束"
+            value-format="yyyy-MM-dd"
+            @change="onDateChange"
+            style="width: 240px"
+          ></el-date-picker>
+        </el-form-item>
+        <el-form-item label="成员数" v-if="advancedVisible">
+          <el-input-number v-model="searchForm.memberMin" :min="0" controls-position="right" style="width: 110px"></el-input-number>
+          <span class="range-sep">~</span>
+          <el-input-number v-model="searchForm.memberMax" :min="0" controls-position="right" style="width: 110px"></el-input-number>
+        </el-form-item>
+        <el-form-item label="状态">
+          <el-select v-model="searchForm.status" placeholder="全部" clearable style="width: 120px">
+            <el-option label="启用" value="enabled"></el-option>
+            <el-option label="停用" value="disabled"></el-option>
+          </el-select>
+        </el-form-item>
         <el-form-item>
           <el-button type="primary" @click="handleSearch">搜索</el-button>
           <el-button @click="handleReset">重置</el-button>
+          <el-button type="text" @click="advancedVisible = !advancedVisible">{{ advancedVisible ? '收起' : '高级筛选' }}</el-button>
         </el-form-item>
-        </el-form>
+      </el-form>
+
+      <!-- ④ 批量操作条 -->
+      <div class="batch-bar">
+        <el-button size="small" :disabled="!selectedRows.length" @click="batchExport">批量导出</el-button>
+        <el-button size="small" :disabled="!selectedRows.length" @click="batchToggle">批量启停</el-button>
+        <span class="batch-count" v-if="selectedRows.length">已选 {{ selectedRows.length }} 项</span>
+      </div>
 
-        <!-- 家庭列表 -->
-                <div class="adm-table-wrap">
-<el-table
+      <!-- 家庭运营指标列表 -->
+      <div class="adm-table-wrap">
+        <el-table
           :data="tableData"
           border
           v-loading="loading"
           class="full-width"
           height="100%"
+          @selection-change="onSelectionChange"
         >
-        <el-table-column prop="id" label="ID" width="80">
-          <template slot="header">
-            <span class="sort-header" @click.stop="onSortClick('id', $event)">ID<span v-if="sortIndex('id') !== null" class="sort-index" :class="sortClass('id') === 'sort-asc' ? 'sort-asc-badge' : 'sort-desc-badge'">{{ sortIndex('id') }}</span>{{ sortIcon('id') }}</span>
-          </template>
-        </el-table-column>
-        <el-table-column prop="name" label="家庭名称" width="200">
-          <template slot="header">
-            <span class="sort-header" @click.stop="onSortClick('name', $event)">家庭名称<span v-if="sortIndex('name') !== null" class="sort-index" :class="sortClass('name') === 'sort-asc' ? 'sort-asc-badge' : 'sort-desc-badge'">{{ sortIndex('name') }}</span>{{ sortIcon('name') }}</span>
-          </template>
-        </el-table-column>
-        <el-table-column prop="inviteCode" label="邀请码" width="150">
-          <template slot="header">
-            <span class="sort-header" @click.stop="onSortClick('inviteCode', $event)">邀请码<span v-if="sortIndex('inviteCode') !== null" class="sort-index" :class="sortClass('inviteCode') === 'sort-asc' ? 'sort-asc-badge' : 'sort-desc-badge'">{{ sortIndex('inviteCode') }}</span>{{ sortIcon('inviteCode') }}</span>
-          </template>
-        </el-table-column>
-        <el-table-column prop="createdAt" label="创建时间" width="180">
-          <template slot-scope="scope">
-            {{ formatTime(scope.row.createdAt) }}
-          </template>
-          <template slot="header">
-            <span class="sort-header" @click.stop="onSortClick('createdAt', $event)">创建时间<span v-if="sortIndex('createdAt') !== null" class="sort-index" :class="sortClass('createdAt') === 'sort-asc' ? 'sort-asc-badge' : 'sort-desc-badge'">{{ sortIndex('createdAt') }}</span>{{ sortIcon('createdAt') }}</span>
-          </template>
-        </el-table-column>
-        <el-table-column prop="memberCount" label="当前成员数" width="110">
-          <template slot-scope="scope">
-            <el-link v-if="scope.row.memberCount > 0" type="primary" :underline="false" @click.stop="handleViewMembers(scope.row)">{{ scope.row.memberCount }}</el-link>
-            <span v-else class="cell-zero">0</span>
-          </template>
-        </el-table-column>
-        <el-table-column prop="reportCount" label="上传报告数" width="110">
-          <template slot-scope="scope">
-            <el-link type="primary" :underline="false" @click.stop="openDetailDialog(scope.row.id, 'reports')">{{ scope.row.reportCount }}</el-link>
-          </template>
-        </el-table-column>
-        <el-table-column prop="planCount" label="方案数" width="100">
-          <template slot-scope="scope">
-            <el-link type="primary" :underline="false" @click.stop="openDetailDialog(scope.row.id, 'plans')">{{ scope.row.planCount }}</el-link>
-          </template>
-        </el-table-column>
-        <el-table-column prop="taskCount" label="任务数" width="100">
-          <template slot-scope="scope">
-            <el-link v-if="scope.row.taskCount > 0" type="primary" :underline="false" @click.stop="openDetailDialog(scope.row.id, 'tasks')">{{ scope.row.taskCount }}</el-link>
-            <span v-else class="cell-zero">0</span>
-          </template>
-        </el-table-column>
-        <el-table-column prop="couponCount" label="优惠券数量" width="100">
-          <template slot-scope="scope">
-            <el-link type="primary" :underline="false" @click.stop="goCouponManage(scope.row.id)">{{ scope.row.couponCount }}</el-link>
-          </template>
-        </el-table-column>
-        <el-table-column label="操作" width="250" fixed="right">
-          <template slot-scope="{ row }">
-            <el-button size="mini" type="primary" @click="handleEdit(row)">编辑</el-button>
-            <el-dropdown trigger="hover" @command="(cmd) => handleActionCmd(row, cmd)">
-              <el-button size="mini">
-                更多<i class="el-icon-arrow-down el-icon--right"></i>
-              </el-button>
-              <el-dropdown-menu slot="dropdown">
-              </el-dropdown-menu>
-            </el-dropdown>
-          </template>
-        </el-table-column>
-        
-        
+          <el-table-column type="selection" width="48" fixed="left"></el-table-column>
+          <el-table-column prop="id" label="ID" width="80">
+            <template slot="header">
+              <span class="sort-header" @click.stop="onSortClick('id', $event)">ID<span v-if="sortIndex('id') !== null" class="sort-index" :class="sortClass('id') === 'sort-asc' ? 'sort-asc-badge' : 'sort-desc-badge'">{{ sortIndex('id') }}</span>{{ sortIcon('id') }}</span>
+            </template>
+          </el-table-column>
+          <el-table-column prop="name" label="家庭名称" width="200">
+            <template slot="header">
+              <span class="sort-header" @click.stop="onSortClick('name', $event)">家庭名称<span v-if="sortIndex('name') !== null" class="sort-index" :class="sortClass('name') === 'sort-asc' ? 'sort-asc-badge' : 'sort-desc-badge'">{{ sortIndex('name') }}</span>{{ sortIcon('name') }}</span>
+            </template>
+          </el-table-column>
+          <el-table-column prop="inviteCode" label="邀请码" width="150">
+            <template slot="header">
+              <span class="sort-header" @click.stop="onSortClick('inviteCode', $event)">邀请码<span v-if="sortIndex('inviteCode') !== null" class="sort-index" :class="sortClass('inviteCode') === 'sort-asc' ? 'sort-asc-badge' : 'sort-desc-badge'">{{ sortIndex('inviteCode') }}</span>{{ sortIcon('inviteCode') }}</span>
+            </template>
+          </el-table-column>
+          <el-table-column prop="createdAt" label="创建时间" width="180">
+            <template slot-scope="scope">
+              {{ formatTime(scope.row.createdAt) }}
+            </template>
+            <template slot="header">
+              <span class="sort-header" @click.stop="onSortClick('createdAt', $event)">创建时间<span v-if="sortIndex('createdAt') !== null" class="sort-index" :class="sortClass('createdAt') === 'sort-asc' ? 'sort-asc-badge' : 'sort-desc-badge'">{{ sortIndex('createdAt') }}</span>{{ sortIcon('createdAt') }}</span>
+            </template>
+          </el-table-column>
+          <el-table-column prop="memberCount" label="当前成员数" width="110">
+            <template slot-scope="scope">
+              <el-link v-if="scope.row.memberCount > 0" type="primary" :underline="false" @click.stop="handleViewMembers(scope.row)">{{ scope.row.memberCount }}</el-link>
+              <span v-else class="cell-zero">0</span>
+            </template>
+          </el-table-column>
+          <el-table-column prop="reportCount" label="上传报告数" width="110">
+            <template slot-scope="scope">
+              <el-link type="primary" :underline="false" @click.stop="openDetailDialog(scope.row.id, 'reports')">{{ scope.row.reportCount }}</el-link>
+            </template>
+          </el-table-column>
+          <el-table-column prop="planCount" label="方案数" width="100">
+            <template slot-scope="scope">
+              <el-link type="primary" :underline="false" @click.stop="openDetailDialog(scope.row.id, 'plans')">{{ scope.row.planCount }}</el-link>
+            </template>
+          </el-table-column>
+          <el-table-column prop="taskCount" label="任务数" width="100">
+            <template slot-scope="scope">
+              <el-link v-if="scope.row.taskCount > 0" type="primary" :underline="false" @click.stop="openDetailDialog(scope.row.id, 'tasks')">{{ scope.row.taskCount }}</el-link>
+              <span v-else class="cell-zero">0</span>
+            </template>
+          </el-table-column>
+          <el-table-column prop="couponCount" label="优惠券数量" width="100">
+            <template slot-scope="scope">
+              <el-link type="primary" :underline="false" @click.stop="goCouponManage(scope.row.id)">{{ scope.row.couponCount }}</el-link>
+            </template>
+          </el-table-column>
+          <!-- 启用状态:后端返回 row.status 时显示真实状态;缺省视为启用(待后端补充 enabled/status 字段) -->
+          <el-table-column label="启用状态" width="100">
+            <template slot-scope="{ row }">
+              <span class="adm-status" :class="row.status === 'disabled' ? 'adm-status--warning' : 'adm-status--success'">{{ row.status === 'disabled' ? '停用' : '启用' }}</span>
+            </template>
+          </el-table-column>
+          <el-table-column label="操作" width="260" fixed="right">
+            <template slot-scope="{ row }">
+              <el-button size="mini" type="primary" @click="handleEdit(row)">编辑</el-button>
+              <el-dropdown trigger="hover" @command="(cmd) => handleMoreCmd(row, cmd)">
+                <el-button size="mini">
+                  更多<i class="el-icon-arrow-down el-icon--right"></i>
+                </el-button>
+                <el-dropdown-menu slot="dropdown">
+                  <el-dropdown-item command="members">查看成员</el-dropdown-item>
+                  <el-dropdown-item command="reports">报告明细</el-dropdown-item>
+                  <el-dropdown-item command="plans">方案明细</el-dropdown-item>
+                  <el-dropdown-item command="tasks">任务明细</el-dropdown-item>
+                  <el-dropdown-item command="coupon">优惠券</el-dropdown-item>
+                  <el-dropdown-item command="earnings">收益</el-dropdown-item>
+                  <el-dropdown-item command="config">配置</el-dropdown-item>
+                </el-dropdown-menu>
+              </el-dropdown>
+            </template>
+          </el-table-column>
         </el-table>
-        </div>
+      </div>
 
-        <!-- 分页 -->
+      <!-- 分页 -->
       <el-pagination
         class="pagination-right"
         @size-change="handleSizeChange"
@@ -184,9 +295,8 @@
               </el-button>
             </template>
           </el-table-column>
+        </el-table>
         <el-empty v-else description="暂无成员" :image-size="60"></el-empty>
-      
-      </el-table>
       </div>
     </el-dialog>
 
@@ -294,6 +404,21 @@ export default {
     detailDialogTitle() {
       const titles = { reports: '报告列表', plans: '方案列表', tasks: '任务列表' }
       return titles[this.detailType] || '家庭明细'
+    },
+    currentPath() {
+      return this.$route.path
+    },
+    // 统计带:基于当前页 tableData 合计(真实可读,按"本页"口径标注)
+    stats() {
+      const sum = (key) => this.tableData.reduce((acc, r) => acc + (r[key] || 0), 0)
+      return {
+        total: this.pagination.total,
+        members: sum('memberCount'),
+        reports: sum('reportCount'),
+        plans: sum('planCount'),
+        tasks: sum('taskCount'),
+        coupons: sum('couponCount')
+      }
     }
   },
   data() {
@@ -303,13 +428,35 @@ export default {
       tableData: [],
       sortableColumns: { id: 'ID', name: '家庭名称', inviteCode: '邀请码', createdAt: '创建时间' },
       searchForm: {
-        name: ''
+        name: '',
+        inviteCode: '',
+        memberMin: undefined,
+        memberMax: undefined,
+        status: '',
+        createTimeStart: '',
+        createTimeEnd: ''
       },
+      dateRange: [],
+      advancedVisible: false,
+      selectedRows: [],
       pagination: {
         current: 1,
         size: 10,
         total: 0
       },
+      // 快捷入口:家庭运营全部模块,一屏触达
+      quickEntries: [
+        { label: '家庭列表', path: '/families', icon: 'el-icon-s-home' },
+        { label: '孩子管理', path: '/children', icon: 'el-icon-user-solid' },
+        { label: '积分管理', path: '/points', icon: 'el-icon-s-finance' },
+        { label: '积分记录', path: '/points-log', icon: 'el-icon-document' },
+        { label: '心愿管理', path: '/wishes', icon: 'el-icon-star-off' },
+        { label: '奖励管理', path: '/rewards', icon: 'el-icon-s-goods' },
+        { label: '汇总方式配置', path: '/family-metric-agg-config', icon: 'el-icon-s-operation' },
+        { label: '家庭优惠券', path: '/admin/family-coupon', icon: 'el-icon-tickets' },
+        { label: '家庭收益', path: '/family-earnings', icon: 'el-icon-s-money' },
+        { label: '收益提现审核', path: '/family-earnings-withdraw', icon: 'el-icon-document-checked' }
+      ],
       editDialogVisible: false,
       editForm: {
         id: null,
@@ -383,14 +530,56 @@ export default {
     loadList() {
       this.loadFamilies()
     },
-    handleActionCmd(row, cmd) {
+    onSelectionChange(val) {
+      this.selectedRows = val
+    },
+    onDateChange(val) {
+      this.searchForm.createTimeStart = (val && val[0]) || ''
+      this.searchForm.createTimeEnd = (val && val[1]) || ''
+    },
+    goEntry(path) {
+      if (path === this.currentPath) return
+      this.$router.push(path)
+    },
+    batchExport() {
+      if (!this.selectedRows.length) {
+        this.$message.warning('请先选择家庭')
+        return
+      }
+      const headers = ['ID', '家庭名称', '邀请码', '创建时间', '成员数', '报告数', '方案数', '任务数', '优惠券数']
+      const rows = this.selectedRows.map(r => [
+        r.id, r.name, r.inviteCode, this.formatTime(r.createdAt),
+        r.memberCount, r.reportCount, r.planCount, r.taskCount, r.couponCount
+      ])
+      const csv = [headers, ...rows].map(r => r.join(',')).join('\n')
+      const blob = new Blob(['\ufeff' + csv], { type: 'text/csv;charset=utf-8' })
+      const url = URL.createObjectURL(blob)
+      const a = document.createElement('a')
+      a.href = url
+      a.download = '家庭列表导出.csv'
+      a.click()
+      URL.revokeObjectURL(url)
+    },
+    batchToggle() {
+      this.$message.info('批量启停功能待后端接口支持')
+    },
+    handleMoreCmd(row, cmd) {
       switch (cmd) {
-        case 'edit': this.handleEdit(row); break;
+        case 'members': this.handleViewMembers(row); break
+        case 'reports': this.openDetailDialog(row.id, 'reports'); break
+        case 'plans': this.openDetailDialog(row.id, 'plans'); break
+        case 'tasks': this.openDetailDialog(row.id, 'tasks'); break
+        case 'coupon': this.goCouponManage(row.id); break
+        case 'earnings': this.$router.push({ path: '/family-earnings', query: { familyId: row.id } }); break
+        case 'config': this.$router.push({ path: '/family-metric-agg-config' }); break
       }
     },
     async loadFamilies() {
       this.loading = true
       try {
+        // 同步时间区间到搜索条件
+        this.searchForm.createTimeStart = (this.dateRange && this.dateRange[0]) || ''
+        this.searchForm.createTimeEnd = (this.dateRange && this.dateRange[1]) || ''
         const params = {
           page: this.pagination.current,
           size: this.pagination.size,
@@ -412,8 +601,15 @@ export default {
     },
     handleReset() {
       this.searchForm = {
-        name: ''
+        name: '',
+        inviteCode: '',
+        memberMin: undefined,
+        memberMax: undefined,
+        status: '',
+        createTimeStart: '',
+        createTimeEnd: ''
       }
+      this.dateRange = []
       this.handleSearch()
     },
     handleRefresh() {
@@ -553,9 +749,63 @@ export default {
 .mb-12 { margin-bottom: 12px; }
 .full-width { width: 100%; }
 .w-120 { width: 120px; }
-.cell-zero { color: #999; }
+.cell-zero { color: var(--adm-text-65); }
 .pagination-right { margin-top: 24px; text-align: right; }
 .pagination-right-mt12 { margin-top: 12px; text-align: right; }
-</style>
 
+/* 页头 */
+.admin-page-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 16px; flex-shrink: 0; }
+.admin-page-title { font-size: 20px; font-weight: 600; line-height: 1.4; color: var(--adm-text-88); }
+.admin-page-subtitle { font-size: 12px; color: var(--adm-text-45); margin-left: 12px; font-weight: 400; }
+.adm-card-header { font-weight: 500; color: var(--adm-text-88); }
+
+/* ① 统计带 */
+.stat-band { display: flex; gap: 16px; flex-wrap: wrap; margin-bottom: 16px; flex-shrink: 0; }
+.stat-card {
+  flex: 1 1 150px; min-width: 150px;
+  background: var(--color-bg-card);
+  border: 1px solid var(--adm-border-split);
+  border-radius: var(--adm-radius-card);
+  padding: 14px 18px;
+}
+.stat-card--primary { background: var(--adm-info-bg); border-color: var(--adm-info-border); }
+.stat-label { font-size: 12px; color: var(--adm-text-45); margin-bottom: 8px; }
+.stat-value { font-size: 24px; font-weight: 600; color: var(--adm-text-88); }
+.stat-value--primary { color: var(--adm-primary); }
+
+/* ② 快捷入口网格 */
+.quick-grid {
+  display: grid;
+  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
+  gap: 12px;
+  margin-bottom: 16px;
+  flex-shrink: 0;
+}
+.qe-card {
+  display: flex; align-items: center; gap: 10px;
+  padding: 14px 16px;
+  background: var(--color-bg-card);
+  border: 1px solid var(--adm-border-split);
+  border-radius: var(--adm-radius-card);
+  cursor: pointer;
+  color: var(--adm-text-88);
+  transition: transform 160ms var(--ease, ease), box-shadow 160ms var(--ease, ease);
+}
+.qe-card:hover { transform: translateY(-2px); box-shadow: var(--adm-shadow-popup); }
+.qe-card.is-active { border-color: var(--adm-primary); background: var(--adm-info-bg); }
+.qe-icon { font-size: 20px; color: var(--adm-primary); }
+.qe-label { font-size: 14px; }
 
+/* ③ 检索栏 */
+.filter-bar {
+  display: flex; align-items: flex-end; flex-wrap: wrap; gap: 16px;
+  padding: 0 0 16px; margin-bottom: 16px;
+  background: transparent; border-radius: 0; box-shadow: none;
+  border-bottom: 1px solid var(--adm-border-split);
+}
+.range-sep { color: var(--adm-text-45); margin: 0 2px; }
+
+/* ④ 批量操作条 */
+.batch-bar { display: flex; align-items: center; gap: 12px; margin-bottom: 12px; }
+.batch-count { font-size: 12px; color: var(--adm-text-45); }
+</style>