zkxw-mobile-oa-drafts-beautify-demos.html 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678
  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, maximum-scale=1" />
  6. <title>草稿箱 · 模式 A 美化 Demo(管理位 + 卡片 + 勾选对齐)</title>
  7. <style>
  8. :root {
  9. --brand: #0a9f6d;
  10. --brand-dark: #087f57;
  11. --brand-soft: #e9f9f2;
  12. --warn: #d97706;
  13. --warn-soft: #fff7e8;
  14. --danger: #ef4444;
  15. --text: #1f2a26;
  16. --text-muted: #6b7b74;
  17. --border: #dcebe4;
  18. --page-bg: #f5f8f7;
  19. --surface: #fff;
  20. }
  21. * { box-sizing: border-box; }
  22. body {
  23. margin: 0;
  24. min-height: 100vh;
  25. font-family: "PingFang SC", "Hiragino Sans GB", "Noto Sans SC", -apple-system, system-ui, sans-serif;
  26. color: var(--text);
  27. background:
  28. radial-gradient(900px 420px at 8% -8%, rgba(10, 159, 109, 0.14), transparent 55%),
  29. radial-gradient(700px 380px at 92% 0%, rgba(214, 163, 67, 0.1), transparent 50%),
  30. linear-gradient(180deg, #f8fffc 0%, #f4f7fb 45%, #f7f8fa 100%);
  31. line-height: 1.45;
  32. }
  33. .stage { max-width: 1320px; margin: 0 auto; padding: 28px 16px 64px; }
  34. .hero h1 { margin: 0 0 8px; font-size: 24px; font-weight: 720; letter-spacing: -0.02em; }
  35. .hero p { margin: 0; max-width: 820px; color: #64748b; font-size: 14px; }
  36. .hero .note {
  37. margin-top: 12px; display: inline-block; padding: 8px 12px;
  38. border-radius: 10px; background: #fff; border: 1px solid #e2e8f0;
  39. font-size: 12px; color: #64748b;
  40. }
  41. .hero .note strong { color: #0f766e; }
  42. .pain {
  43. margin: 18px 0 0;
  44. display: grid;
  45. grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  46. gap: 10px;
  47. }
  48. .pain-item {
  49. background: #fff;
  50. border: 1px solid #fecaca;
  51. border-radius: 12px;
  52. padding: 10px 12px;
  53. font-size: 12px;
  54. color: #7f1d1d;
  55. }
  56. .pain-item b { color: #b91c1c; }
  57. .tabs {
  58. display: flex; flex-wrap: wrap; gap: 10px; margin: 22px 0 18px;
  59. }
  60. .tab {
  61. appearance: none; border: 1px solid #e2e8f0; background: #fff;
  62. border-radius: 999px; padding: 10px 16px; font-size: 13px;
  63. font-weight: 600; color: #475569; cursor: pointer;
  64. transition: .15s border-color, .15s box-shadow, .15s color, .15s background;
  65. }
  66. .tab:hover { border-color: #94a3b8; }
  67. .tab.is-active {
  68. color: var(--brand-dark); border-color: var(--brand);
  69. background: var(--brand-soft);
  70. box-shadow: 0 0 0 3px rgba(10, 159, 109, 0.18);
  71. }
  72. .tab .badge {
  73. margin-left: 6px; font-size: 10px; font-weight: 700;
  74. padding: 2px 6px; border-radius: 999px;
  75. background: #ecfdf5; color: #047857;
  76. }
  77. .layout {
  78. display: grid;
  79. grid-template-columns: minmax(260px, 340px) 1fr;
  80. gap: 22px;
  81. align-items: start;
  82. }
  83. @media (max-width: 960px) { .layout { grid-template-columns: 1fr; } }
  84. .panel {
  85. background: rgba(255,255,255,.92);
  86. border: 1px solid #e2e8f0;
  87. border-radius: 18px;
  88. padding: 18px;
  89. box-shadow: 0 10px 30px rgba(15, 23, 42, 0.05);
  90. }
  91. .panel h2 { margin: 0 0 4px; font-size: 16px; }
  92. .panel .sub { margin: 0 0 12px; font-size: 12px; color: #64748b; }
  93. .panel ul { margin: 0; padding-left: 18px; font-size: 13px; color: #475569; }
  94. .panel li { margin: 6px 0; }
  95. .panel .pick {
  96. margin-top: 14px; padding: 12px; border-radius: 12px;
  97. background: var(--brand-soft); border: 1px solid #c6f0dc;
  98. font-size: 12px; color: #166534;
  99. }
  100. .phones {
  101. display: flex; flex-wrap: wrap; gap: 20px; justify-content: center;
  102. }
  103. .phone {
  104. width: 375px; background: #fff; border-radius: 28px;
  105. box-shadow: 0 0 0 1px rgb(15 23 42 / 6%), 0 18px 40px rgb(15 23 42 / 12%);
  106. overflow: hidden;
  107. }
  108. .phone-bar {
  109. height: 44px; display: flex; align-items: center; justify-content: center;
  110. background: linear-gradient(135deg, #0a9f6d, #087f57);
  111. color: #fff; font-size: 16px; font-weight: 600;
  112. }
  113. .phone-cap {
  114. padding: 8px 14px; font-size: 11px; font-weight: 650;
  115. color: #64748b; background: #f8fafc; border-bottom: 1px solid #eef2f0;
  116. text-align: center;
  117. }
  118. .page { background: var(--page-bg); min-height: 620px; padding-bottom: 18px; }
  119. .style-block { display: none; }
  120. .style-block.is-active { display: block; }
  121. /* ========== 共用搜索 ========== */
  122. .search {
  123. height: 36px; display: flex; align-items: center; gap: 8px;
  124. padding: 0 12px; border-radius: 10px; border: 1px solid #e8eaed;
  125. background: #fafafa; font-size: 13px; color: #94a3b8; width: 100%;
  126. }
  127. .search::before {
  128. content: ""; width: 12px; height: 12px; border: 1.5px solid #94a3b8;
  129. border-radius: 50%; flex-shrink: 0;
  130. }
  131. /* ========== 共用卡片(美化后的模式 A) ========== */
  132. .card {
  133. width: 100%;
  134. background: var(--surface);
  135. border: 1px solid #e2ebe6;
  136. border-radius: 14px;
  137. overflow: hidden;
  138. box-shadow: 0 6px 18px rgba(15, 23, 42, 0.05);
  139. }
  140. .card-body { padding: 14px 14px 12px; }
  141. .card-top {
  142. display: flex; align-items: flex-start; justify-content: space-between; gap: 10px;
  143. }
  144. .card-title {
  145. font-size: 15px; font-weight: 700; color: #1f2a26; line-height: 1.35;
  146. min-width: 0; flex: 1;
  147. }
  148. .card-status {
  149. flex-shrink: 0; font-size: 11px; font-weight: 700;
  150. padding: 3px 9px; border-radius: 999px;
  151. background: var(--warn-soft); color: var(--warn);
  152. }
  153. .card-meta { margin-top: 10px; display: flex; flex-direction: column; gap: 6px; }
  154. .card-meta-line {
  155. display: flex; gap: 10px; font-size: 12px; line-height: 1.4;
  156. }
  157. .card-meta-line .lab { color: #94a3b8; min-width: 56px; flex-shrink: 0; }
  158. .card-meta-line .val { color: #475569; min-width: 0; }
  159. .card-footer {
  160. display: flex; gap: 8px; padding: 10px 12px 12px;
  161. border-top: 1px dashed rgba(140, 170, 155, 0.28);
  162. }
  163. .card-footer button {
  164. flex: 1; min-width: 0; height: 34px; border-radius: 10px;
  165. border: 1px solid #d8e3de; background: #fff;
  166. font-size: 12px; font-weight: 650; color: #334155; cursor: pointer;
  167. }
  168. .card-footer .p {
  169. background: var(--brand); border-color: var(--brand); color: #fff;
  170. }
  171. .card-footer .d {
  172. color: var(--danger); border-color: rgba(239,68,68,.35);
  173. background: rgba(239,68,68,.06);
  174. }
  175. .list { padding: 10px 12px 0; display: flex; flex-direction: column; gap: 10px; }
  176. .end { text-align: center; padding: 14px 0 6px; font-size: 12px; color: #94a3b8; }
  177. /* —— 卡片变体:更精致 —— */
  178. .card.v-soft {
  179. border-color: transparent;
  180. box-shadow: 0 8px 24px rgba(15, 23, 42, 0.06);
  181. }
  182. .card.v-accent {
  183. border-color: #e8eeeb;
  184. box-shadow: 0 4px 14px rgba(15, 23, 42, 0.04);
  185. position: relative;
  186. }
  187. .card.v-accent::before {
  188. content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 3px;
  189. background: linear-gradient(180deg, #f59e0b, #d6a343);
  190. }
  191. .card.v-accent .card-body { padding-left: 16px; }
  192. .card.v-flat {
  193. border: 0;
  194. background: #fff;
  195. box-shadow: none;
  196. border-radius: 12px;
  197. outline: 1px solid #e8eeeb;
  198. }
  199. .card.v-meta-inline .card-meta {
  200. flex-direction: row; flex-wrap: wrap; gap: 4px 12px;
  201. }
  202. .card.v-meta-inline .card-meta-line .lab { min-width: 0; }
  203. .card.v-meta-inline .card-meta-line .lab::after { content: " "; }
  204. .card.v-meta-inline .sep {
  205. color: #cbd5e1; font-size: 12px;
  206. }
  207. /* ========== A0 现状对照 ========== */
  208. .a0-toolbar {
  209. display: flex; align-items: center; gap: 10px;
  210. padding: 10px 12px; background: #fff; border-bottom: 1px solid #f1f5f9;
  211. }
  212. .a0-manage {
  213. flex-shrink: 0; font-size: 14px; font-weight: 600; color: #166534;
  214. padding: 0 2px; white-space: nowrap;
  215. }
  216. .a0-row {
  217. display: flex; align-items: flex-start; gap: 8px; width: 100%;
  218. }
  219. .a0-check {
  220. padding-top: 20px; flex-shrink: 0;
  221. }
  222. .a0-check span {
  223. display: flex; width: 20px; height: 20px; border-radius: 50%;
  224. border: 1.5px solid #cbd5e1; background: #fff;
  225. align-items: center; justify-content: center;
  226. font-size: 11px; color: #fff; font-weight: 700;
  227. }
  228. .a0-check span.on { background: #22c55e; border-color: #22c55e; }
  229. .a0-row .card { flex: 1; min-width: 0; }
  230. /* ========== 方案 1:搜索独占 + 列表头「共N条 | 管理」 ========== */
  231. .s1-toolbar { padding: 10px 12px 8px; background: #fff; border-bottom: 1px solid #f1f5f9; }
  232. .s1-head {
  233. display: flex; align-items: center; justify-content: space-between;
  234. padding: 10px 14px 2px;
  235. }
  236. .s1-count { font-size: 12px; color: var(--text-muted); }
  237. .s1-count strong { color: var(--brand-dark); font-weight: 700; }
  238. .s1-link {
  239. font-size: 13px; font-weight: 650; color: var(--brand-dark);
  240. padding: 4px 2px; cursor: pointer; user-select: none;
  241. }
  242. .s1-link.is-done { color: #64748b; }
  243. /* ========== 方案 2:顶栏右侧胶囊「管理」 ========== */
  244. .s2-toolbar {
  245. display: flex; align-items: center; gap: 8px;
  246. padding: 10px 12px; background: #fff; border-bottom: 1px solid #f1f5f9;
  247. }
  248. .s2-chip {
  249. flex-shrink: 0; height: 36px; padding: 0 14px;
  250. border-radius: 999px; border: 1px solid #d8e3de;
  251. background: #fff; font-size: 13px; font-weight: 650;
  252. color: var(--brand-dark); cursor: pointer;
  253. display: inline-flex; align-items: center; gap: 4px;
  254. }
  255. .s2-chip.is-on {
  256. background: #f1f5f9; border-color: #e2e8f0; color: #64748b;
  257. }
  258. .s2-chip svg { width: 14px; height: 14px; }
  259. /* ========== 方案 3:搜索下方次级工具条 ========== */
  260. .s3-toolbar { padding: 10px 12px 0; background: #fff; border-bottom: 1px solid #f1f5f9; }
  261. .s3-sub {
  262. display: flex; align-items: center; justify-content: space-between;
  263. margin-top: 10px; padding: 8px 2px 10px;
  264. }
  265. .s3-hint { font-size: 12px; color: #94a3b8; }
  266. .s3-btn {
  267. height: 28px; padding: 0 12px; border-radius: 8px;
  268. border: 1px solid #c6f0dc; background: var(--brand-soft);
  269. color: var(--brand-dark); font-size: 12px; font-weight: 650; cursor: pointer;
  270. }
  271. .s3-btn.is-on {
  272. background: #f1f5f9; border-color: #e2e8f0; color: #64748b;
  273. }
  274. /* ========== 方案 4:底栏管理(列表干净) ========== */
  275. .s4-page { position: relative; padding-bottom: 64px; }
  276. .s4-toolbar { padding: 10px 12px; background: #fff; border-bottom: 1px solid #f1f5f9; }
  277. .s4-dock {
  278. position: absolute; left: 0; right: 0; bottom: 0;
  279. padding: 10px 14px calc(10px + env(safe-area-inset-bottom, 0px));
  280. background: rgba(255,255,255,.96);
  281. border-top: 1px solid #e8eeeb;
  282. display: flex; align-items: center; justify-content: space-between;
  283. backdrop-filter: blur(8px);
  284. }
  285. .s4-dock .hint { font-size: 12px; color: var(--text-muted); }
  286. .s4-dock .btn {
  287. height: 36px; padding: 0 18px; border-radius: 10px;
  288. border: 0; background: var(--brand); color: #fff;
  289. font-size: 13px; font-weight: 700; cursor: pointer;
  290. }
  291. .s4-dock.is-manage .btn {
  292. background: #f1f5f9; color: #64748b;
  293. }
  294. .s4-dock .danger {
  295. height: 36px; padding: 0 16px; border-radius: 10px;
  296. border: 1px solid rgba(239,68,68,.35);
  297. background: rgba(239,68,68,.06); color: var(--danger);
  298. font-size: 13px; font-weight: 650; cursor: pointer;
  299. }
  300. /* ========== 管理态:勾选垂直居中 ========== */
  301. .row {
  302. display: flex; align-items: center; gap: 10px; width: 100%;
  303. }
  304. .row .card { flex: 1; min-width: 0; margin: 0; }
  305. .check {
  306. flex-shrink: 0; width: 22px; height: 22px;
  307. display: flex; align-items: center; justify-content: center;
  308. }
  309. .check span {
  310. display: flex; width: 20px; height: 20px; border-radius: 50%;
  311. border: 1.5px solid #cbd5e1; background: #fff;
  312. align-items: center; justify-content: center;
  313. font-size: 11px; color: #fff; font-weight: 700;
  314. }
  315. .check span.on { background: #22c55e; border-color: #22c55e; }
  316. .row.is-on .card {
  317. border-color: rgba(34, 197, 94, 0.45);
  318. box-shadow: 0 8px 20px rgba(22, 163, 74, 0.12);
  319. }
  320. .batch {
  321. margin: 10px 12px 0; padding: 10px 12px; border-radius: 12px;
  322. background: #fff; border: 1px solid #c6f0dc;
  323. display: flex; align-items: center; justify-content: space-between;
  324. font-size: 13px; color: #166534;
  325. }
  326. .batch button {
  327. height: 30px; padding: 0 12px; border-radius: 8px;
  328. border: 1px solid rgba(239,68,68,.35);
  329. background: rgba(239,68,68,.06); color: var(--danger);
  330. font-size: 12px; font-weight: 650; cursor: pointer;
  331. }
  332. /* 内嵌勾选(方案变体) */
  333. .card-check-in {
  334. display: flex; gap: 10px; align-items: flex-start;
  335. }
  336. .card-check-in .check { margin-top: 2px; }
  337. .meta-inline {
  338. margin-top: 8px; font-size: 12px; color: #64748b;
  339. }
  340. .meta-inline .dot { margin: 0 6px; color: #cbd5e1; }
  341. </style>
  342. </head>
  343. <body>
  344. <div class="stage">
  345. <div class="hero">
  346. <h1>草稿箱 · 模式 A 美化选型</h1>
  347. <p>
  348. 保留现有信息结构(标题 / 草稿态 / 最近保存 / 版本 / 编辑·提交·删除),针对你反馈的三点做方案对比:
  349. <strong>管理入口不突兀</strong>、<strong>勾选与卡片垂直居中</strong>、<strong>卡片更好看</strong>。
  350. </p>
  351. <div class="note">请选 <strong>S1 / S2 / S3 / S4</strong>(卡片可再指定 soft / accent / flat)。选好后我落到 <code>mobile-h5</code>。</div>
  352. <div class="pain">
  353. <div class="pain-item"><b>痛点 1</b> 「管理」挤在搜索框右侧,突兀</div>
  354. <div class="pain-item"><b>痛点 2</b> 管理态勾选与卡片未垂直居中</div>
  355. <div class="pain-item"><b>痛点 3</b> 卡片观感偏平、不好看</div>
  356. </div>
  357. </div>
  358. <div class="tabs" id="tabs">
  359. <button class="tab is-active" data-k="a0">A0 现状对照</button>
  360. <button class="tab" data-k="s1">S1 列表头管理<span class="badge">推荐</span></button>
  361. <button class="tab" data-k="s2">S2 胶囊按钮</button>
  362. <button class="tab" data-k="s3">S3 次级工具条</button>
  363. <button class="tab" data-k="s4">S4 底栏管理</button>
  364. <button class="tab" data-k="cards">卡片三款</button>
  365. </div>
  366. <div class="layout">
  367. <div class="panel" id="desc"></div>
  368. <div class="phones" id="phones"></div>
  369. </div>
  370. </div>
  371. <script>
  372. const ICON_GEAR = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 15a3 3 0 1 0 0-6 3 3 0 0 0 0 6Z"/><path d="M19.4 15a1.7 1.7 0 0 0 .3 1.8l.1.1a2 2 0 1 1-2.8 2.8l-.1-.1a1.7 1.7 0 0 0-1.8-.3 1.7 1.7 0 0 0-1 1.5V21a2 2 0 1 1-4 0v-.1a1.7 1.7 0 0 0-1-1.5 1.7 1.7 0 0 0-1.8.3l-.1.1a2 2 0 1 1-2.8-2.8l.1-.1a1.7 1.7 0 0 0 .3-1.8 1.7 1.7 0 0 0-1.5-1H3a2 2 0 1 1 0-4h.1a1.7 1.7 0 0 0 1.5-1 1.7 1.7 0 0 0-.3-1.8l-.1-.1a2 2 0 1 1 2.8-2.8l.1.1a1.7 1.7 0 0 0 1.8.3H9a1.7 1.7 0 0 0 1-1.5V3a2 2 0 1 1 4 0v.1a1.7 1.7 0 0 0 1 1.5 1.7 1.7 0 0 0 1.8-.3l.1-.1a2 2 0 1 1 2.8 2.8l-.1.1a1.7 1.7 0 0 0-.3 1.8V9a1.7 1.7 0 0 0 1.5 1H21a2 2 0 1 1 0 4h-.1a1.7 1.7 0 0 0-1.5 1Z"/></svg>';
  373. function cardHtml(title, time, ver, opts) {
  374. opts = opts || {};
  375. var cls = "card" + (opts.variant ? " " + opts.variant : "");
  376. var footer = opts.noActions ? "" : (
  377. '<div class="card-footer">' +
  378. '<button class="p">编辑</button>' +
  379. '<button>提交审批</button>' +
  380. '<button class="d">删除</button>' +
  381. '</div>'
  382. );
  383. var meta = opts.inlineMeta
  384. ? ('<div class="meta-inline">' + time + '<span class="dot">·</span>版本 ' + ver + '</div>')
  385. : (
  386. '<div class="card-meta">' +
  387. '<div class="card-meta-line"><span class="lab">最近保存</span><span class="val">' + time + '</span></div>' +
  388. '<div class="card-meta-line"><span class="lab">版本</span><span class="val">' + ver + '</span></div>' +
  389. '</div>'
  390. );
  391. return (
  392. '<div class="' + cls + '">' +
  393. '<div class="card-body">' +
  394. '<div class="card-top">' +
  395. '<div class="card-title">' + title + '</div>' +
  396. '<div class="card-status">草稿</div>' +
  397. '</div>' +
  398. meta +
  399. '</div>' +
  400. footer +
  401. '</div>'
  402. );
  403. }
  404. const ROWS = [
  405. ["入帐单", "2026-08-12 17:03:42", "v5"],
  406. ["出差申请", "2026-08-11 09:18:00", "v3"],
  407. ["采购报销", "2026-08-10 17:05:11", "v2"]
  408. ];
  409. function phone(cap, bodyHtml) {
  410. return (
  411. '<div class="phone">' +
  412. '<div class="phone-bar">草稿箱</div>' +
  413. (cap ? '<div class="phone-cap">' + cap + '</div>' : '') +
  414. '<div class="page">' + bodyHtml + '</div>' +
  415. '</div>'
  416. );
  417. }
  418. const DESCS = {
  419. a0: {
  420. title: "A0 · 现状对照",
  421. sub: "复现当前问题,方便并排对比。",
  422. items: [
  423. "「管理」文字直接贴在搜索框右侧,视觉突兀",
  424. "管理态勾选 padding-top 硬对齐,无法跟卡片垂直居中",
  425. "卡片可用,但边框/按钮节奏偏旧"
  426. ],
  427. pick: "仅作对照,不建议落地。"
  428. },
  429. s1: {
  430. title: "S1 · 列表头管理(推荐)",
  431. sub: "搜索独占一行;「共 N 条」与「管理」放在列表上方次级行。",
  432. items: [
  433. "搜索框不再被挤窄,输入更舒适",
  434. "管理入口与列表语义绑定,不再像外挂按钮",
  435. "管理态:勾选与卡片 align-items:center 垂直居中",
  436. "卡片:轻阴影 + 等分按钮(现状结构保留)"
  437. ],
  438. pick: "最推荐:改动小、符合列表页习惯(微信/钉钉类)。"
  439. },
  440. s2: {
  441. title: "S2 · 搜索旁胶囊按钮",
  442. sub: "仍在顶栏,但「管理」做成等高胶囊,降低突兀感。",
  443. items: [
  444. "与搜索同高的描边胶囊,比纯文字更规整",
  445. "可选左侧小图标强化「管理模式」",
  446. "勾选垂直居中;完成态胶囊变灰"
  447. ],
  448. pick: "想少改布局、只润色顶栏时选 S2。"
  449. },
  450. s3: {
  451. title: "S3 · 搜索下次级工具条",
  452. sub: "搜索下方增加一行提示 + 浅绿小按钮。",
  453. items: [
  454. "主搜索区干净,管理降为次级操作",
  455. "可用文案提示「可批量删除草稿」",
  456. "管理态同样垂直居中勾选"
  457. ],
  458. pick: "需要教育用户「可批量管理」时选 S3。"
  459. },
  460. s4: {
  461. title: "S4 · 底栏管理",
  462. sub: "列表区完全干净;管理/批量删除沉到底部固定栏。",
  463. items: [
  464. "顶栏只留搜索,最清爽",
  465. "进入管理后底栏切换为「已选 N · 批量删除 · 完成」",
  466. "适合单手操作、强调批量删除场景"
  467. ],
  468. pick: "草稿常需批量清理时选 S4;会占一点底部空间。"
  469. },
  470. cards: {
  471. title: "卡片三款细调",
  472. sub: "同一信息结构,只换卡片「皮」;可与 S1–S4 任意组合。",
  473. items: [
  474. "Soft:无描边、更柔阴影",
  475. "Accent:左侧琥珀竖条强调草稿",
  476. "Flat:细线扁平,信息更密(元信息可一行)"
  477. ],
  478. pick: "建议:S1 布局 + Soft 或 Accent 卡片。"
  479. }
  480. };
  481. function renderA0() {
  482. var normal = phone("普通态 · 管理突兀",
  483. '<div class="a0-toolbar"><div class="search" style="flex:1">搜索流程名称</div><div class="a0-manage">管理</div></div>' +
  484. '<div class="list">' +
  485. ROWS.map(function (r) { return cardHtml(r[0], r[1], r[2]); }).join("") +
  486. '<div class="end">已经到底了</div></div>'
  487. );
  488. var manage = phone("管理态 · 勾选未居中",
  489. '<div class="a0-toolbar"><div class="search" style="flex:1">搜索流程名称</div><div class="a0-manage" style="color:#64748b">完成</div></div>' +
  490. '<div class="batch"><span>已选 1 项</span><button>批量删除</button></div>' +
  491. '<div class="list">' +
  492. '<div class="a0-row"><div class="a0-check"><span class="on">✓</span></div>' + cardHtml(ROWS[0][0], ROWS[0][1], ROWS[0][2], { noActions: true }) + '</div>' +
  493. '<div class="a0-row"><div class="a0-check"><span></span></div>' + cardHtml(ROWS[1][0], ROWS[1][1], ROWS[1][2], { noActions: true }) + '</div>' +
  494. '<div class="a0-row"><div class="a0-check"><span></span></div>' + cardHtml(ROWS[2][0], ROWS[2][1], ROWS[2][2], { noActions: true }) + '</div>' +
  495. '</div>'
  496. );
  497. return normal + manage;
  498. }
  499. function renderS1() {
  500. var normal = phone("普通态",
  501. '<div class="s1-toolbar"><div class="search">搜索流程名称</div></div>' +
  502. '<div class="s1-head"><div class="s1-count">共 <strong>3</strong> 条草稿</div><div class="s1-link">管理</div></div>' +
  503. '<div class="list">' +
  504. ROWS.map(function (r) { return cardHtml(r[0], r[1], r[2], { variant: "v-soft" }); }).join("") +
  505. '<div class="end">已经到底了</div></div>'
  506. );
  507. var manage = phone("管理态 · 勾选居中",
  508. '<div class="s1-toolbar"><div class="search">搜索流程名称</div></div>' +
  509. '<div class="s1-head"><div class="s1-count">已选 <strong>1</strong> / 3</div><div class="s1-link is-done">完成</div></div>' +
  510. '<div class="batch"><span>已选 1 项</span><button>批量删除</button></div>' +
  511. '<div class="list">' +
  512. '<div class="row is-on"><div class="check"><span class="on">✓</span></div>' + cardHtml(ROWS[0][0], ROWS[0][1], ROWS[0][2], { noActions: true, variant: "v-soft" }) + '</div>' +
  513. '<div class="row"><div class="check"><span></span></div>' + cardHtml(ROWS[1][0], ROWS[1][1], ROWS[1][2], { noActions: true, variant: "v-soft" }) + '</div>' +
  514. '<div class="row"><div class="check"><span></span></div>' + cardHtml(ROWS[2][0], ROWS[2][1], ROWS[2][2], { noActions: true, variant: "v-soft" }) + '</div>' +
  515. '</div>'
  516. );
  517. return normal + manage;
  518. }
  519. function renderS2() {
  520. var normal = phone("普通态 · 胶囊",
  521. '<div class="s2-toolbar"><div class="search" style="flex:1">搜索流程名称</div>' +
  522. '<button class="s2-chip">' + ICON_GEAR + '管理</button></div>' +
  523. '<div class="list">' +
  524. ROWS.map(function (r) { return cardHtml(r[0], r[1], r[2], { variant: "v-accent" }); }).join("") +
  525. '<div class="end">已经到底了</div></div>'
  526. );
  527. var manage = phone("管理态 · 勾选居中",
  528. '<div class="s2-toolbar"><div class="search" style="flex:1">搜索流程名称</div>' +
  529. '<button class="s2-chip is-on">完成</button></div>' +
  530. '<div class="batch"><span>已选 1 项</span><button>批量删除</button></div>' +
  531. '<div class="list">' +
  532. '<div class="row is-on"><div class="check"><span class="on">✓</span></div>' + cardHtml(ROWS[0][0], ROWS[0][1], ROWS[0][2], { noActions: true, variant: "v-accent" }) + '</div>' +
  533. '<div class="row"><div class="check"><span></span></div>' + cardHtml(ROWS[1][0], ROWS[1][1], ROWS[1][2], { noActions: true, variant: "v-accent" }) + '</div>' +
  534. '<div class="row"><div class="check"><span></span></div>' + cardHtml(ROWS[2][0], ROWS[2][1], ROWS[2][2], { noActions: true, variant: "v-accent" }) + '</div>' +
  535. '</div>'
  536. );
  537. return normal + manage;
  538. }
  539. function renderS3() {
  540. var normal = phone("普通态 · 次级条",
  541. '<div class="s3-toolbar"><div class="search">搜索流程名称</div>' +
  542. '<div class="s3-sub"><span class="s3-hint">可批量删除不用的草稿</span><button class="s3-btn">管理</button></div></div>' +
  543. '<div class="list">' +
  544. ROWS.map(function (r) { return cardHtml(r[0], r[1], r[2]); }).join("") +
  545. '<div class="end">已经到底了</div></div>'
  546. );
  547. var manage = phone("管理态 · 勾选居中",
  548. '<div class="s3-toolbar"><div class="search">搜索流程名称</div>' +
  549. '<div class="s3-sub"><span class="s3-hint">点选草稿后可批量删除</span><button class="s3-btn is-on">完成</button></div></div>' +
  550. '<div class="batch"><span>已选 1 项</span><button>批量删除</button></div>' +
  551. '<div class="list">' +
  552. '<div class="row is-on"><div class="check"><span class="on">✓</span></div>' + cardHtml(ROWS[0][0], ROWS[0][1], ROWS[0][2], { noActions: true }) + '</div>' +
  553. '<div class="row"><div class="check"><span></span></div>' + cardHtml(ROWS[1][0], ROWS[1][1], ROWS[1][2], { noActions: true }) + '</div>' +
  554. '<div class="row"><div class="check"><span></span></div>' + cardHtml(ROWS[2][0], ROWS[2][1], ROWS[2][2], { noActions: true }) + '</div>' +
  555. '</div>'
  556. );
  557. return normal + manage;
  558. }
  559. function renderS4() {
  560. var normal = phone("普通态 · 底栏",
  561. '<div class="s4-page">' +
  562. '<div class="s4-toolbar"><div class="search">搜索流程名称</div></div>' +
  563. '<div class="list">' +
  564. ROWS.map(function (r) { return cardHtml(r[0], r[1], r[2], { variant: "v-soft", inlineMeta: true }); }).join("") +
  565. '<div class="end">已经到底了</div></div>' +
  566. '<div class="s4-dock"><span class="hint">共 3 条草稿</span><button class="btn">管理</button></div>' +
  567. '</div>'
  568. );
  569. var manage = phone("管理态 · 底栏批量",
  570. '<div class="s4-page">' +
  571. '<div class="s4-toolbar"><div class="search">搜索流程名称</div></div>' +
  572. '<div class="list">' +
  573. '<div class="row is-on"><div class="check"><span class="on">✓</span></div>' + cardHtml(ROWS[0][0], ROWS[0][1], ROWS[0][2], { noActions: true, variant: "v-soft", inlineMeta: true }) + '</div>' +
  574. '<div class="row"><div class="check"><span></span></div>' + cardHtml(ROWS[1][0], ROWS[1][1], ROWS[1][2], { noActions: true, variant: "v-soft", inlineMeta: true }) + '</div>' +
  575. '<div class="row"><div class="check"><span></span></div>' + cardHtml(ROWS[2][0], ROWS[2][1], ROWS[2][2], { noActions: true, variant: "v-soft", inlineMeta: true }) + '</div>' +
  576. '</div>' +
  577. '<div class="s4-dock is-manage">' +
  578. '<span class="hint">已选 1 项</span>' +
  579. '<div style="display:flex;gap:8px">' +
  580. '<button class="danger">批量删除</button>' +
  581. '<button class="btn">完成</button>' +
  582. '</div>' +
  583. '</div>' +
  584. '</div>'
  585. );
  586. return normal + manage;
  587. }
  588. function renderCards() {
  589. return (
  590. phone("Soft · 柔阴影",
  591. '<div class="s1-toolbar"><div class="search">搜索流程名称</div></div>' +
  592. '<div class="s1-head"><div class="s1-count">共 <strong>3</strong> 条</div><div class="s1-link">管理</div></div>' +
  593. '<div class="list">' + ROWS.map(function (r) { return cardHtml(r[0], r[1], r[2], { variant: "v-soft" }); }).join("") + '</div>'
  594. ) +
  595. phone("Accent · 左色条",
  596. '<div class="s1-toolbar"><div class="search">搜索流程名称</div></div>' +
  597. '<div class="s1-head"><div class="s1-count">共 <strong>3</strong> 条</div><div class="s1-link">管理</div></div>' +
  598. '<div class="list">' + ROWS.map(function (r) { return cardHtml(r[0], r[1], r[2], { variant: "v-accent" }); }).join("") + '</div>'
  599. ) +
  600. phone("Flat · 扁平一行元信息",
  601. '<div class="s1-toolbar"><div class="search">搜索流程名称</div></div>' +
  602. '<div class="s1-head"><div class="s1-count">共 <strong>3</strong> 条</div><div class="s1-link">管理</div></div>' +
  603. '<div class="list">' + ROWS.map(function (r) { return cardHtml(r[0], r[1], r[2], { variant: "v-flat", inlineMeta: true }); }).join("") + '</div>'
  604. )
  605. );
  606. }
  607. const RENDER = {
  608. a0: renderA0,
  609. s1: renderS1,
  610. s2: renderS2,
  611. s3: renderS3,
  612. s4: renderS4,
  613. cards: renderCards
  614. };
  615. const descEl = document.getElementById("desc");
  616. const phonesEl = document.getElementById("phones");
  617. const tabs = document.getElementById("tabs");
  618. function show(key) {
  619. var d = DESCS[key];
  620. descEl.innerHTML =
  621. "<h2>" + d.title + "</h2>" +
  622. '<p class="sub">' + d.sub + "</p>" +
  623. "<ul>" + d.items.map(function (i) { return "<li>" + i + "</li>"; }).join("") + "</ul>" +
  624. '<div class="pick">' + d.pick + "</div>";
  625. phonesEl.innerHTML = RENDER[key]();
  626. }
  627. tabs.addEventListener("click", function (e) {
  628. var btn = e.target.closest(".tab");
  629. if (!btn) return;
  630. tabs.querySelectorAll(".tab").forEach(function (t) {
  631. t.classList.toggle("is-active", t === btn);
  632. });
  633. show(btn.getAttribute("data-k"));
  634. });
  635. show("a0");
  636. </script>
  637. </body>
  638. </html>