shanxia-mp-loading-demo.html 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615
  1. <!DOCTYPE html>
  2. <html lang="zh-CN">
  3. <head>
  4. <meta charset="UTF-8" />
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  6. <title>山峡化工 · H5 通用加载效果 Demo</title>
  7. <style>
  8. :root {
  9. --brand: #0a9f6d;
  10. --brand-dark: #087f57;
  11. --brand-soft: #e9f9f2;
  12. --bg: #f5f8f7;
  13. --surface: #fff;
  14. --text: #1f2a26;
  15. --muted: #6b7b74;
  16. --border: #dcebe4;
  17. --header: linear-gradient(180deg, #087f57 0%, #087f57 28%, #0a9f6d 78%, #0a9f6d 100%);
  18. }
  19. * { box-sizing: border-box; margin: 0; padding: 0; }
  20. button { font: inherit; cursor: pointer; }
  21. body {
  22. background: #cfd9d4;
  23. color: var(--text);
  24. font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Helvetica Neue", sans-serif;
  25. font-size: 14px;
  26. line-height: 1.5;
  27. min-height: 100vh;
  28. }
  29. .stage { max-width: 1280px; margin: 0 auto; padding: 16px 12px 48px; }
  30. .banner {
  31. background: #1f2a26;
  32. color: #fff;
  33. border-radius: 12px;
  34. padding: 14px 16px;
  35. margin-bottom: 12px;
  36. font-size: 13px;
  37. line-height: 1.65;
  38. }
  39. .banner strong { color: #9fe3c4; }
  40. .banner code {
  41. background: rgba(255,255,255,.12);
  42. padding: 1px 6px;
  43. border-radius: 4px;
  44. font-size: 12px;
  45. }
  46. .switcher {
  47. display: flex;
  48. flex-wrap: wrap;
  49. gap: 8px;
  50. margin-bottom: 14px;
  51. }
  52. .switcher button {
  53. height: 36px;
  54. padding: 0 14px;
  55. border-radius: 999px;
  56. border: 1px solid #b7c9c0;
  57. background: #fff;
  58. color: var(--text);
  59. font-size: 13px;
  60. font-weight: 600;
  61. }
  62. .switcher button[aria-pressed="true"] {
  63. background: var(--brand);
  64. border-color: var(--brand);
  65. color: #fff;
  66. }
  67. .grid {
  68. display: grid;
  69. grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  70. gap: 16px;
  71. align-items: start;
  72. }
  73. .col-label {
  74. margin-bottom: 8px;
  75. padding: 10px 12px;
  76. border-radius: 10px;
  77. background: #fff;
  78. border: 1px solid #b7c9c0;
  79. font-size: 12px;
  80. line-height: 1.55;
  81. min-height: 108px;
  82. }
  83. .col-label h2 { font-size: 15px; margin-bottom: 4px; }
  84. .col-label .rec { color: var(--brand-dark); font-weight: 700; }
  85. .col-label.rec-box { border-color: #b7ebce; background: var(--brand-soft); }
  86. .phone {
  87. position: relative;
  88. background: var(--bg);
  89. border-radius: 28px;
  90. overflow: hidden;
  91. border: 8px solid #24312c;
  92. height: 740px;
  93. box-shadow: 0 18px 40px rgba(0,0,0,.16);
  94. display: flex;
  95. flex-direction: column;
  96. }
  97. .status-bar {
  98. flex: 0 0 auto;
  99. height: 28px;
  100. background: var(--brand-dark);
  101. color: rgba(255,255,255,.88);
  102. display: flex;
  103. align-items: center;
  104. justify-content: space-between;
  105. padding: 0 16px;
  106. font-size: 11px;
  107. }
  108. .scene { display: none; flex: 1; min-height: 0; flex-direction: column; }
  109. body[data-scene="list"] .scene-list,
  110. body[data-scene="more"] .scene-more,
  111. body[data-scene="detail"] .scene-detail,
  112. body[data-scene="sheet"] .scene-sheet { display: flex; }
  113. .header {
  114. flex: 0 0 auto;
  115. background: var(--header);
  116. color: #fff;
  117. padding: 6px 12px 14px;
  118. border-radius: 0 0 22px 22px;
  119. }
  120. .header-row { display: flex; align-items: center; gap: 8px; min-height: 40px; }
  121. .back { color: #fff; font-size: 20px; width: 32px; }
  122. .header h1 { flex: 1; font-size: 17px; font-weight: 700; }
  123. .search, .search-skel {
  124. margin-top: 8px;
  125. height: 36px;
  126. border-radius: 999px;
  127. background: #fff;
  128. }
  129. .search {
  130. display: flex;
  131. align-items: center;
  132. padding: 0 14px;
  133. color: #94a3b8;
  134. font-size: 13px;
  135. }
  136. .filters {
  137. display: grid;
  138. grid-template-columns: 1fr 1fr 1fr;
  139. gap: 8px;
  140. margin-top: 10px;
  141. }
  142. .filters span {
  143. height: 28px;
  144. border-radius: 8px;
  145. background: rgba(255,255,255,.16);
  146. color: #fff;
  147. font-size: 12px;
  148. display: flex;
  149. align-items: center;
  150. justify-content: center;
  151. }
  152. .body {
  153. flex: 1;
  154. min-height: 0;
  155. overflow: auto;
  156. padding: 12px;
  157. }
  158. .card {
  159. background: var(--surface);
  160. border: 1px solid rgba(220,235,228,.9);
  161. border-radius: 14px;
  162. box-shadow: 0 6px 16px rgba(10,159,109,.06);
  163. padding: 14px;
  164. margin-bottom: 12px;
  165. }
  166. .card-top, .skel-top { display: flex; justify-content: space-between; gap: 10px; }
  167. .card h3 { font-size: 15px; }
  168. .meta { margin-top: 4px; font-size: 12px; color: var(--muted); }
  169. .tag {
  170. flex-shrink: 0;
  171. height: 22px;
  172. padding: 0 8px;
  173. border-radius: 999px;
  174. background: var(--brand-soft);
  175. color: var(--brand-dark);
  176. font-size: 11px;
  177. font-weight: 700;
  178. display: inline-flex;
  179. align-items: center;
  180. }
  181. .kv { margin-top: 10px; display: grid; gap: 6px; }
  182. .kv div { display: flex; justify-content: space-between; font-size: 13px; }
  183. .kv span:first-child { color: var(--muted); }
  184. .foot-hint {
  185. display: flex;
  186. gap: 8px;
  187. align-items: center;
  188. justify-content: center;
  189. margin: 4px 0 16px;
  190. font-size: 12px;
  191. color: var(--muted);
  192. }
  193. .skel {
  194. border-radius: 6px;
  195. background: linear-gradient(90deg, #e7f3ed 25%, #f7fbf9 37%, #e7f3ed 63%);
  196. background-size: 400% 100%;
  197. animation: shimmer 1.2s ease infinite;
  198. }
  199. .skel.title { width: 58%; height: 16px; }
  200. .skel.sub { width: 42%; height: 12px; margin-top: 8px; }
  201. .skel.tag { width: 52px; height: 22px; border-radius: 999px; }
  202. .skel.line { width: 100%; height: 12px; }
  203. .skel.short { width: 46%; }
  204. .skel.mid { width: 72%; }
  205. .skel.btn { width: 64px; height: 28px; border-radius: 8px; }
  206. .skel-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 12px; }
  207. .skel-block { height: 36px; border-radius: 10px; margin-top: 10px; }
  208. .caption {
  209. margin: 2px 0 12px;
  210. text-align: center;
  211. font-size: 12px;
  212. color: var(--muted);
  213. }
  214. .pulse {
  215. flex: 1;
  216. display: flex;
  217. flex-direction: column;
  218. align-items: center;
  219. justify-content: center;
  220. gap: 8px;
  221. min-height: 280px;
  222. margin: 12px;
  223. padding: 28px 20px;
  224. text-align: center;
  225. background:
  226. radial-gradient(120% 80% at 50% 0%, rgba(10,159,109,.14), transparent 55%),
  227. linear-gradient(180deg, #f3faf6, #f5f8f7);
  228. border-radius: 16px;
  229. }
  230. .pulse.compact { min-height: 0; margin: 0; padding: 28px 16px 36px; background: transparent; }
  231. .orb {
  232. width: 28px;
  233. height: 28px;
  234. display: flex;
  235. align-items: center;
  236. justify-content: center;
  237. margin-bottom: 4px;
  238. }
  239. .dot {
  240. width: 10px;
  241. height: 10px;
  242. border-radius: 50%;
  243. background: var(--brand);
  244. box-shadow: 0 0 0 6px rgba(10,159,109,.14);
  245. animation: pulse 1.2s ease-in-out infinite;
  246. }
  247. .dot.sm { width: 8px; height: 8px; box-shadow: 0 0 0 4px rgba(10,159,109,.14); }
  248. .pulse h2, .spin-box h2 { font-size: 15px; font-weight: 700; }
  249. .pulse p, .spin-box p { max-width: 220px; font-size: 12px; color: var(--muted); }
  250. .bars { width: min(220px, 100%); display: grid; gap: 8px; margin-top: 12px; }
  251. .progress {
  252. height: 3px;
  253. background: rgba(255,255,255,.28);
  254. overflow: hidden;
  255. }
  256. .progress i, .sheet-progress i {
  257. display: block;
  258. width: 38%;
  259. height: 100%;
  260. background: #fff;
  261. animation: slide 1.05s ease-in-out infinite;
  262. }
  263. .sheet-progress { height: 3px; background: #e7f3ed; overflow: hidden; }
  264. .sheet-progress i { background: var(--brand); }
  265. .ghost { opacity: .55; }
  266. .spin-box {
  267. flex: 1;
  268. display: flex;
  269. flex-direction: column;
  270. align-items: center;
  271. justify-content: center;
  272. gap: 10px;
  273. min-height: 240px;
  274. text-align: center;
  275. padding: 24px;
  276. }
  277. .ring {
  278. width: 28px;
  279. height: 28px;
  280. border: 3px solid #b7ebce;
  281. border-top-color: var(--brand);
  282. border-radius: 50%;
  283. animation: spin .7s linear infinite;
  284. }
  285. .ring.sm { width: 16px; height: 16px; border-width: 2px; }
  286. .ring.md { width: 22px; height: 22px; }
  287. .scene-sheet { position: relative; background: var(--bg); }
  288. .dim {
  289. position: absolute;
  290. inset: 0;
  291. background: rgba(15, 23, 20, .45);
  292. }
  293. .sheet {
  294. position: absolute;
  295. left: 0;
  296. right: 0;
  297. bottom: 0;
  298. height: 62%;
  299. background: #fff;
  300. border-radius: 18px 18px 0 0;
  301. display: flex;
  302. flex-direction: column;
  303. box-shadow: 0 -8px 24px rgba(0,0,0,.12);
  304. }
  305. .sheet-bar {
  306. height: 48px;
  307. display: flex;
  308. align-items: center;
  309. justify-content: space-between;
  310. padding: 0 16px;
  311. font-weight: 700;
  312. }
  313. .sheet-bar button {
  314. border: 0;
  315. background: transparent;
  316. color: var(--brand);
  317. font-size: 14px;
  318. }
  319. .sheet-body { flex: 1; overflow: auto; padding: 8px 16px 20px; }
  320. .field { margin-bottom: 14px; }
  321. .field label { display: block; margin-bottom: 6px; font-size: 12px; color: var(--muted); }
  322. .fake-input {
  323. height: 36px;
  324. border-radius: 8px;
  325. background: #f3f7f5;
  326. border: 1px solid var(--border);
  327. }
  328. @keyframes shimmer {
  329. 0% { background-position: 100% 0; }
  330. 100% { background-position: 0 0; }
  331. }
  332. @keyframes pulse {
  333. 0%, 100% { transform: scale(1); opacity: 1; }
  334. 50% { transform: scale(.82); opacity: .7; }
  335. }
  336. @keyframes spin { to { transform: rotate(360deg); } }
  337. @keyframes slide {
  338. 0% { transform: translateX(-120%); }
  339. 100% { transform: translateX(320%); }
  340. }
  341. </style>
  342. </head>
  343. <body data-scene="list">
  344. <div class="stage">
  345. <div class="banner">
  346. <strong>通用加载 · 四选一。</strong>
  347. 四种方案共用一条规则:绿头标题始终是真实页面名;整块内容未出用「页面态」,列表已有数据再追加用「追加态」,弹层里等数据用「弹层态」。壳层登录和业务请求用同一种内容区效果,打开页面只出现一次加载。
  348. 色值走三墙 <code>#0a9f6d</code> / <code>#087f57</code>。点下面的场景,四台手机一起切换。
  349. </div>
  350. <div class="switcher" role="tablist" aria-label="加载场景">
  351. <button type="button" data-scene="list" aria-pressed="true">列表首屏</button>
  352. <button type="button" data-scene="more" aria-pressed="false">上拉加载更多</button>
  353. <button type="button" data-scene="detail" aria-pressed="false">详情 / 表单</button>
  354. <button type="button" data-scene="sheet" aria-pressed="false">底部弹层</button>
  355. </div>
  356. <div class="grid">
  357. <section>
  358. <div class="col-label rec-box">
  359. <h2>A · 结构骨架 <span class="rec">推荐</span></h2>
  360. 占位和正式列表、详情、表单同结构。用户能认出即将出现的是卡片还是字段。翻页只在末尾补一张骨架卡。
  361. </div>
  362. <div class="phone" aria-label="方案 A 结构骨架">
  363. <div class="status-bar"><span>9:41</span><span>山峡化工</span></div>
  364. <div class="scene scene-list">
  365. <header class="header">
  366. <div class="header-row"><span class="back">←</span><h1>客户管理</h1></div>
  367. <div class="search">客户名称 / 编号 / 手机号</div>
  368. <div class="filters"><span>客户类型 ▾</span><span>客户级别 ▾</span><span>更多</span></div>
  369. </header>
  370. <div class="body">
  371. <p class="caption">正在加载客户列表</p>
  372. <article class="card"><div class="skel-top"><div style="flex:1"><div class="skel title"></div><div class="skel sub"></div></div><div class="skel tag"></div></div><div class="skel skel-block"></div><div class="skel-actions"><div class="skel btn"></div><div class="skel btn"></div><div class="skel btn"></div></div></article>
  373. <article class="card"><div class="skel-top"><div style="flex:1"><div class="skel title"></div><div class="skel sub"></div></div><div class="skel tag"></div></div><div class="skel skel-block"></div><div class="skel-actions"><div class="skel btn"></div><div class="skel btn"></div><div class="skel btn"></div></div></article>
  374. <article class="card"><div class="skel-top"><div style="flex:1"><div class="skel title"></div><div class="skel sub"></div></div><div class="skel tag"></div></div><div class="skel skel-block"></div><div class="skel-actions"><div class="skel btn"></div><div class="skel btn"></div><div class="skel btn"></div></div></article>
  375. </div>
  376. </div>
  377. <div class="scene scene-more">
  378. <header class="header">
  379. <div class="header-row"><span class="back">←</span><h1>客户管理</h1></div>
  380. <div class="search">客户名称 / 编号 / 手机号</div>
  381. <div class="filters"><span>客户类型 ▾</span><span>客户级别 ▾</span><span>更多</span></div>
  382. </header>
  383. <div class="body">
  384. <article class="card">
  385. <div class="card-top"><div><h3>安庆化轻贸易</h3><div class="meta">KH20261018001 · 经销商</div></div><span class="tag">跟进中</span></div>
  386. <div class="kv"><div><span>负责人</span><span>王敏</span></div><div><span>最近跟进</span><span>昨天 16:20</span></div></div>
  387. </article>
  388. <article class="card"><div class="skel-top"><div style="flex:1"><div class="skel title"></div><div class="skel sub"></div></div><div class="skel tag"></div></div><div class="skel skel-block"></div></article>
  389. <p class="caption">正在加载更多</p>
  390. </div>
  391. </div>
  392. <div class="scene scene-detail">
  393. <header class="header">
  394. <div class="header-row"><span class="back">←</span><h1>客户详情</h1></div>
  395. </header>
  396. <div class="body">
  397. <p class="caption">正在加载客户详情</p>
  398. <article class="card">
  399. <div class="skel title" style="width:46%"></div>
  400. <div class="kv" style="margin-top:16px">
  401. <div class="skel line"></div><div class="skel line mid"></div><div class="skel line"></div><div class="skel line short"></div><div class="skel line"></div><div class="skel line mid"></div>
  402. </div>
  403. </article>
  404. <article class="card">
  405. <div class="skel sub" style="width:28%"></div>
  406. <div class="skel skel-block"></div>
  407. <div class="skel skel-block"></div>
  408. </article>
  409. </div>
  410. </div>
  411. <div class="scene scene-sheet">
  412. <header class="header">
  413. <div class="header-row"><span class="back">←</span><h1>客户管理</h1></div>
  414. <div class="search">客户名称 / 编号 / 手机号</div>
  415. </header>
  416. <div class="dim"></div>
  417. <div class="sheet">
  418. <div class="sheet-bar"><button type="button">关闭</button><span>更多筛选</span><span></span></div>
  419. <div class="sheet-body">
  420. <p class="caption">正在加载筛选项</p>
  421. <div class="field"><div class="skel sub"></div><div class="skel skel-block"></div></div>
  422. <div class="field"><div class="skel sub" style="width:36%"></div><div class="skel skel-block"></div></div>
  423. <div class="field"><div class="skel sub" style="width:24%"></div><div class="skel skel-block"></div></div>
  424. </div>
  425. </div>
  426. </div>
  427. </div>
  428. </section>
  429. <section>
  430. <div class="col-label">
  431. <h2>B · 呼吸点</h2>
  432. 把现在运输计划那套收成唯一组件:绿点、两行字、四条闪烁。列表、详情、弹层都用它,只改文案和尺寸。
  433. </div>
  434. <div class="phone" aria-label="方案 B 呼吸点">
  435. <div class="status-bar"><span>9:41</span><span>山峡化工</span></div>
  436. <div class="scene scene-list">
  437. <header class="header"><div class="header-row"><span class="back">←</span><h1>客户管理</h1></div></header>
  438. <div class="pulse">
  439. <div class="orb"><span class="dot"></span></div>
  440. <h2>正在加载客户列表</h2>
  441. <p>请稍候,正在获取客户数据…</p>
  442. <div class="bars"><div class="skel line"></div><div class="skel line mid"></div><div class="skel line"></div><div class="skel line short"></div></div>
  443. </div>
  444. </div>
  445. <div class="scene scene-more">
  446. <header class="header">
  447. <div class="header-row"><span class="back">←</span><h1>客户管理</h1></div>
  448. <div class="search">客户名称 / 编号 / 手机号</div>
  449. </header>
  450. <div class="body">
  451. <article class="card">
  452. <div class="card-top"><div><h3>安庆化轻贸易</h3><div class="meta">KH20261018001 · 经销商</div></div><span class="tag">跟进中</span></div>
  453. </article>
  454. <p class="foot-hint"><span class="dot sm"></span>正在加载更多</p>
  455. </div>
  456. </div>
  457. <div class="scene scene-detail">
  458. <header class="header"><div class="header-row"><span class="back">←</span><h1>客户详情</h1></div></header>
  459. <div class="pulse">
  460. <div class="orb"><span class="dot"></span></div>
  461. <h2>正在加载客户详情</h2>
  462. <p>请稍候,正在获取客户资料…</p>
  463. <div class="bars"><div class="skel line"></div><div class="skel line mid"></div><div class="skel line"></div><div class="skel line short"></div></div>
  464. </div>
  465. </div>
  466. <div class="scene scene-sheet">
  467. <header class="header"><div class="header-row"><span class="back">←</span><h1>客户管理</h1></div></header>
  468. <div class="dim"></div>
  469. <div class="sheet">
  470. <div class="sheet-bar"><button type="button">关闭</button><span>选择产品</span><span></span></div>
  471. <div class="pulse compact">
  472. <div class="orb"><span class="dot"></span></div>
  473. <h2>正在加载产品</h2>
  474. <p>请稍候…</p>
  475. </div>
  476. </div>
  477. </div>
  478. </div>
  479. </section>
  480. <section>
  481. <div class="col-label">
  482. <h2>C · 顶栏进度</h2>
  483. 绿头底部一条白色不定进度。内容用很淡的骨架,已加载的卡片保持原样。适合觉得整页大加载太重的时候。
  484. </div>
  485. <div class="phone" aria-label="方案 C 顶栏进度">
  486. <div class="status-bar"><span>9:41</span><span>山峡化工</span></div>
  487. <div class="scene scene-list">
  488. <header class="header">
  489. <div class="header-row"><span class="back">←</span><h1>客户管理</h1></div>
  490. <div class="search">客户名称 / 编号 / 手机号</div>
  491. <div class="filters"><span>客户类型 ▾</span><span>客户级别 ▾</span><span>更多</span></div>
  492. </header>
  493. <div class="progress" aria-hidden="true"><i></i></div>
  494. <div class="body ghost">
  495. <article class="card"><div class="skel-top"><div style="flex:1"><div class="skel title"></div><div class="skel sub"></div></div><div class="skel tag"></div></div><div class="skel skel-block"></div></article>
  496. <article class="card"><div class="skel-top"><div style="flex:1"><div class="skel title"></div><div class="skel sub"></div></div><div class="skel tag"></div></div><div class="skel skel-block"></div></article>
  497. </div>
  498. </div>
  499. <div class="scene scene-more">
  500. <header class="header">
  501. <div class="header-row"><span class="back">←</span><h1>客户管理</h1></div>
  502. <div class="search">客户名称 / 编号 / 手机号</div>
  503. </header>
  504. <div class="progress" aria-hidden="true"><i></i></div>
  505. <div class="body">
  506. <article class="card">
  507. <div class="card-top"><div><h3>安庆化轻贸易</h3><div class="meta">KH20261018001 · 经销商</div></div><span class="tag">跟进中</span></div>
  508. </article>
  509. <article class="card">
  510. <div class="card-top"><div><h3>池州新材料</h3><div class="meta">KH20261012018 · 终端</div></div><span class="tag">重点</span></div>
  511. </article>
  512. </div>
  513. </div>
  514. <div class="scene scene-detail">
  515. <header class="header"><div class="header-row"><span class="back">←</span><h1>客户详情</h1></div></header>
  516. <div class="progress" aria-hidden="true"><i></i></div>
  517. <div class="body ghost">
  518. <article class="card"><div class="skel title" style="width:40%"></div><div class="kv" style="margin-top:16px"><div class="skel line"></div><div class="skel line mid"></div><div class="skel line"></div><div class="skel line short"></div></div></article>
  519. </div>
  520. </div>
  521. <div class="scene scene-sheet">
  522. <header class="header"><div class="header-row"><span class="back">←</span><h1>客户管理</h1></div></header>
  523. <div class="dim"></div>
  524. <div class="sheet">
  525. <div class="sheet-bar"><button type="button">关闭</button><span>更多筛选</span><span></span></div>
  526. <div class="sheet-progress" aria-hidden="true"><i></i></div>
  527. <div class="sheet-body ghost">
  528. <div class="field"><label>客户类型</label><div class="fake-input"></div></div>
  529. <div class="field"><label>客户级别</label><div class="fake-input"></div></div>
  530. </div>
  531. </div>
  532. </div>
  533. </div>
  534. </section>
  535. <section>
  536. <div class="col-label">
  537. <h2>D · 单一转圈</h2>
  538. 全站只留一种绿色圆环。页面用 28px 纵向,翻页用 16px 横排,弹层用 22px。文案统一成「正在加载 + 对象名」。
  539. </div>
  540. <div class="phone" aria-label="方案 D 单一转圈">
  541. <div class="status-bar"><span>9:41</span><span>山峡化工</span></div>
  542. <div class="scene scene-list">
  543. <header class="header">
  544. <div class="header-row"><span class="back">←</span><h1>客户管理</h1></div>
  545. <div class="search">客户名称 / 编号 / 手机号</div>
  546. <div class="filters"><span>客户类型 ▾</span><span>客户级别 ▾</span><span>更多</span></div>
  547. </header>
  548. <div class="spin-box">
  549. <span class="ring"></span>
  550. <h2>正在加载客户列表</h2>
  551. </div>
  552. </div>
  553. <div class="scene scene-more">
  554. <header class="header">
  555. <div class="header-row"><span class="back">←</span><h1>客户管理</h1></div>
  556. <div class="search">客户名称 / 编号 / 手机号</div>
  557. </header>
  558. <div class="body">
  559. <article class="card">
  560. <div class="card-top"><div><h3>安庆化轻贸易</h3><div class="meta">KH20261018001 · 经销商</div></div><span class="tag">跟进中</span></div>
  561. </article>
  562. <p class="foot-hint"><span class="ring sm"></span>正在加载更多</p>
  563. </div>
  564. </div>
  565. <div class="scene scene-detail">
  566. <header class="header"><div class="header-row"><span class="back">←</span><h1>编辑客户</h1></div></header>
  567. <div class="spin-box">
  568. <span class="ring"></span>
  569. <h2>正在加载客户资料</h2>
  570. </div>
  571. </div>
  572. <div class="scene scene-sheet">
  573. <header class="header"><div class="header-row"><span class="back">←</span><h1>客户管理</h1></div></header>
  574. <div class="dim"></div>
  575. <div class="sheet">
  576. <div class="sheet-bar"><button type="button">关闭</button><span>选择产品</span><span></span></div>
  577. <div class="spin-box">
  578. <span class="ring md"></span>
  579. <h2>正在加载产品</h2>
  580. </div>
  581. </div>
  582. </div>
  583. </div>
  584. </section>
  585. </div>
  586. </div>
  587. <script>
  588. const buttons = document.querySelectorAll(".switcher button");
  589. buttons.forEach((button) => {
  590. button.addEventListener("click", () => {
  591. const scene = button.dataset.scene;
  592. document.body.dataset.scene = scene;
  593. buttons.forEach((item) => {
  594. item.setAttribute("aria-pressed", item === button ? "true" : "false");
  595. });
  596. });
  597. });
  598. </script>
  599. </body>
  600. </html>