zkxw-mobile-wechat-notify-menu-demo.html 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772
  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, maximum-scale=1.0, user-scalable=no, viewport-fit=cover" />
  6. <title>中科兴皖 · 微信审批通知菜单 Demo</title>
  7. <style>
  8. :root {
  9. --brand-green: #0a9f6d;
  10. --brand-green-dark: #087f57;
  11. --brand-green-soft: #e9f9f2;
  12. --barley-yellow: #d6a343;
  13. --barley-yellow-soft: #fff7e8;
  14. --bg-page: #f5f8f7;
  15. --surface: #ffffff;
  16. --text-primary: #1f2a26;
  17. --text-muted: #6b7b74;
  18. --border: #dcebe4;
  19. --danger: #d14343;
  20. --warning: #cf8a19;
  21. --success: #189b65;
  22. --radius-card: 14px;
  23. --radius-lg: 20px;
  24. --shadow-soft: 0 4px 16px rgba(8, 127, 87, 0.08);
  25. }
  26. * { box-sizing: border-box; }
  27. html, body {
  28. margin: 0;
  29. padding: 0;
  30. min-height: 100%;
  31. font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Helvetica Neue", sans-serif;
  32. color: var(--text-primary);
  33. background:
  34. radial-gradient(900px 420px at 10% -10%, rgba(10, 159, 109, 0.14), transparent 55%),
  35. radial-gradient(700px 380px at 90% 0%, rgba(214, 163, 67, 0.12), transparent 50%),
  36. linear-gradient(180deg, #eef6f2 0%, #f7faf9 40%, #f3f6f5 100%);
  37. }
  38. body {
  39. display: flex;
  40. justify-content: center;
  41. padding: 24px 16px 40px;
  42. }
  43. #app {
  44. width: 100%;
  45. max-width: 980px;
  46. display: grid;
  47. grid-template-columns: 280px 1fr;
  48. gap: 24px;
  49. align-items: start;
  50. }
  51. @media (max-width: 860px) {
  52. #app { grid-template-columns: 1fr; }
  53. .doc-panel { position: static; }
  54. }
  55. .doc-panel {
  56. position: sticky;
  57. top: 24px;
  58. background: rgba(255, 255, 255, 0.92);
  59. border: 1px solid var(--border);
  60. border-radius: 18px;
  61. padding: 20px 18px;
  62. box-shadow: var(--shadow-soft);
  63. }
  64. .doc-panel h1 {
  65. margin: 0 0 6px;
  66. font-size: 20px;
  67. line-height: 1.3;
  68. color: var(--brand-green-dark);
  69. }
  70. .doc-panel .sub {
  71. margin: 0 0 16px;
  72. font-size: 12px;
  73. color: var(--text-muted);
  74. line-height: 1.5;
  75. }
  76. .section-title {
  77. margin: 16px 0 8px;
  78. font-size: 12px;
  79. font-weight: 600;
  80. color: var(--text-muted);
  81. letter-spacing: 0.04em;
  82. text-transform: uppercase;
  83. }
  84. .screen-nav {
  85. display: flex;
  86. flex-direction: column;
  87. gap: 8px;
  88. }
  89. .screen-nav button {
  90. appearance: none;
  91. border: 1px solid var(--border);
  92. background: #fff;
  93. border-radius: 10px;
  94. padding: 10px 12px;
  95. text-align: left;
  96. font-size: 13px;
  97. color: var(--text-primary);
  98. cursor: pointer;
  99. }
  100. .screen-nav button.is-on {
  101. border-color: var(--brand-green);
  102. background: var(--brand-green-soft);
  103. color: var(--brand-green-dark);
  104. font-weight: 600;
  105. }
  106. .note {
  107. margin-top: 14px;
  108. padding: 10px 12px;
  109. border-radius: 10px;
  110. background: var(--barley-yellow-soft);
  111. border: 1px solid #f0dfb4;
  112. font-size: 12px;
  113. line-height: 1.55;
  114. color: #7a5a12;
  115. }
  116. .stage {
  117. display: flex;
  118. justify-content: center;
  119. }
  120. .phone {
  121. width: 375px;
  122. max-width: 100%;
  123. background: var(--bg-page);
  124. border-radius: 28px;
  125. border: 1px solid var(--border);
  126. box-shadow: var(--shadow-soft);
  127. overflow: hidden;
  128. min-height: 720px;
  129. display: flex;
  130. flex-direction: column;
  131. }
  132. .status-bar {
  133. height: 28px;
  134. background: linear-gradient(180deg, #0a9f6d 0%, #087f57 100%);
  135. }
  136. .screen { display: none; flex: 1; flex-direction: column; }
  137. .screen.is-on { display: flex; }
  138. /* —— 首页 —— */
  139. .home-header {
  140. background: linear-gradient(180deg, #0a9f6d 0%, #087f57 100%);
  141. color: #fff;
  142. padding: 8px 16px 22px;
  143. border-radius: 0 0 22px 22px;
  144. }
  145. .brand { font-size: 13px; opacity: 0.9; }
  146. .hello { margin-top: 10px; font-size: 22px; font-weight: 700; }
  147. .meta {
  148. margin-top: 8px;
  149. display: flex;
  150. justify-content: space-between;
  151. align-items: flex-start;
  152. gap: 12px;
  153. font-size: 12px;
  154. opacity: 0.92;
  155. }
  156. .meta__right {
  157. display: flex;
  158. flex-direction: column;
  159. align-items: flex-end;
  160. gap: 6px;
  161. flex-shrink: 0;
  162. }
  163. .home-logout {
  164. text-decoration: underline;
  165. text-underline-offset: 2px;
  166. cursor: pointer;
  167. opacity: 0.9;
  168. }
  169. .home-mp-legacy {
  170. font-size: 11px;
  171. text-decoration: underline;
  172. opacity: 0.75;
  173. cursor: pointer;
  174. }
  175. .home-mp-legacy.is-hidden { display: none; }
  176. .home-body { padding: 14px 12px 24px; flex: 1; }
  177. .panel {
  178. background: var(--surface);
  179. border-radius: var(--radius-card);
  180. border: 1px solid var(--border);
  181. padding: 14px 12px 8px;
  182. }
  183. .panel-hd {
  184. display: flex;
  185. justify-content: space-between;
  186. align-items: baseline;
  187. margin-bottom: 12px;
  188. padding: 0 4px;
  189. }
  190. .panel-title { font-size: 15px; font-weight: 700; }
  191. .hint { font-size: 12px; color: var(--text-muted); }
  192. .menu-grid {
  193. display: grid;
  194. grid-template-columns: repeat(4, 1fr);
  195. gap: 10px 4px;
  196. }
  197. .menu-item {
  198. display: flex;
  199. flex-direction: column;
  200. align-items: center;
  201. gap: 6px;
  202. padding: 8px 4px;
  203. border: 0;
  204. background: transparent;
  205. cursor: pointer;
  206. border-radius: 10px;
  207. }
  208. .menu-item:hover { background: var(--brand-green-soft); }
  209. .menu-item.is-new .menu-icon {
  210. outline: 2px solid var(--barley-yellow);
  211. outline-offset: 2px;
  212. }
  213. .menu-icon {
  214. width: 44px;
  215. height: 44px;
  216. border-radius: 12px;
  217. display: grid;
  218. place-items: center;
  219. font-size: 18px;
  220. color: #fff;
  221. font-weight: 700;
  222. overflow: hidden;
  223. }
  224. .menu-icon img {
  225. width: 44px;
  226. height: 44px;
  227. object-fit: contain;
  228. display: block;
  229. }
  230. .menu-icon.is-plain {
  231. background: transparent !important;
  232. border-radius: 0;
  233. }
  234. .menu-title {
  235. font-size: 11px;
  236. line-height: 1.3;
  237. text-align: center;
  238. color: var(--text-primary);
  239. }
  240. .c1 { background: #0a9f6d; }
  241. .c2 { background: #2f8f7a; }
  242. .c3 { background: #3d8bb8; }
  243. .c4 { background: #5b7fbf; }
  244. .c5 { background: #7a6bb8; }
  245. .c6 { background: #cf8a19; }
  246. .c7 { background: transparent; }
  247. /* —— 通知设置页 —— */
  248. .nav {
  249. background: linear-gradient(180deg, #0a9f6d 0%, #087f57 100%);
  250. color: #fff;
  251. padding: 10px 12px 14px;
  252. display: flex;
  253. align-items: center;
  254. gap: 8px;
  255. }
  256. .nav__back {
  257. width: 36px;
  258. height: 36px;
  259. border: 0;
  260. background: rgba(255,255,255,0.16);
  261. color: #fff;
  262. border-radius: 10px;
  263. cursor: pointer;
  264. font-size: 18px;
  265. }
  266. .nav__title { font-size: 17px; font-weight: 700; }
  267. .notify-body { padding: 14px 12px 28px; flex: 1; }
  268. .status-banner {
  269. display: none;
  270. }
  271. .step-card {
  272. background: var(--surface);
  273. border: 1px solid var(--border);
  274. border-radius: var(--radius-card);
  275. padding: 14px;
  276. margin-bottom: 10px;
  277. }
  278. .step-card.is-done {
  279. border-color: #b7ebcf;
  280. background: linear-gradient(180deg, #f6fffb 0%, #fff 60%);
  281. }
  282. .step-hd {
  283. display: flex;
  284. align-items: flex-start;
  285. gap: 10px;
  286. }
  287. .step-num {
  288. width: 28px;
  289. height: 28px;
  290. border-radius: 50%;
  291. background: var(--brand-green);
  292. color: #fff;
  293. display: grid;
  294. place-items: center;
  295. font-size: 14px;
  296. font-weight: 700;
  297. flex-shrink: 0;
  298. }
  299. .step-card.is-done .step-num {
  300. background: var(--success);
  301. }
  302. .step-title {
  303. font-size: 15px;
  304. font-weight: 700;
  305. line-height: 1.35;
  306. }
  307. .step-desc {
  308. margin-top: 4px;
  309. font-size: 12px;
  310. color: var(--text-muted);
  311. line-height: 1.5;
  312. }
  313. .step-badge {
  314. margin-left: auto;
  315. font-size: 11px;
  316. padding: 2px 8px;
  317. border-radius: 999px;
  318. background: #eef2f0;
  319. color: var(--text-muted);
  320. flex-shrink: 0;
  321. }
  322. .step-badge.is-done {
  323. background: var(--brand-green-soft);
  324. color: var(--brand-green-dark);
  325. }
  326. .step-actions { margin-top: 12px; padding-left: 38px; }
  327. .btn {
  328. appearance: none;
  329. border: 0;
  330. border-radius: 10px;
  331. padding: 10px 14px;
  332. font-size: 14px;
  333. font-weight: 600;
  334. cursor: pointer;
  335. min-height: 40px;
  336. }
  337. .btn-primary {
  338. background: var(--brand-green);
  339. color: #fff;
  340. width: 100%;
  341. }
  342. .btn-primary:disabled {
  343. background: #a7d7c4;
  344. cursor: default;
  345. }
  346. .btn-ghost {
  347. background: #fff;
  348. color: var(--brand-green-dark);
  349. border: 1px solid var(--border);
  350. width: 100%;
  351. }
  352. .qr-box {
  353. margin-top: 10px;
  354. display: none;
  355. padding: 12px;
  356. border-radius: 12px;
  357. border: 1px dashed #a7f3d0;
  358. background: #f8fffb;
  359. text-align: center;
  360. }
  361. .qr-box.is-on { display: block; }
  362. .qr-fake {
  363. width: 140px;
  364. height: 140px;
  365. margin: 0 auto 8px;
  366. border-radius: 8px;
  367. background:
  368. repeating-linear-gradient(0deg, #1f2a26 0 6px, transparent 6px 12px),
  369. repeating-linear-gradient(90deg, #1f2a26 0 6px, transparent 6px 12px);
  370. opacity: 0.18;
  371. }
  372. .qr-tip { font-size: 12px; color: var(--text-muted); }
  373. /* —— 登录页(对照:入口已移除) —— */
  374. .login-page {
  375. padding: 36px 20px 28px;
  376. flex: 1;
  377. background: linear-gradient(180deg, #e9f9f2 0%, #f5f8f7 42%, #f5f8f7 100%);
  378. }
  379. .login-brand { text-align: center; margin-bottom: 22px; }
  380. .login-logo {
  381. width: 72px;
  382. height: 72px;
  383. margin: 0 auto 10px;
  384. border-radius: 18px;
  385. background: var(--brand-green);
  386. color: #fff;
  387. display: grid;
  388. place-items: center;
  389. font-size: 28px;
  390. font-weight: 800;
  391. }
  392. .login-sub { font-size: 13px; color: var(--text-muted); }
  393. .login-card {
  394. background: #fff;
  395. border-radius: 16px;
  396. border: 1px solid var(--border);
  397. padding: 16px;
  398. box-shadow: var(--shadow-soft);
  399. }
  400. .field { margin-bottom: 12px; }
  401. .field label {
  402. display: block;
  403. font-size: 12px;
  404. color: var(--text-muted);
  405. margin-bottom: 6px;
  406. }
  407. .field .box {
  408. height: 42px;
  409. border: 1px solid var(--border);
  410. border-radius: 10px;
  411. background: #fafcfb;
  412. padding: 0 12px;
  413. display: flex;
  414. align-items: center;
  415. color: #9aaba3;
  416. font-size: 14px;
  417. }
  418. .login-submit {
  419. margin-top: 8px;
  420. height: 44px;
  421. border-radius: 10px;
  422. background: var(--brand-green);
  423. color: #fff;
  424. display: grid;
  425. place-items: center;
  426. font-weight: 700;
  427. }
  428. .login-follow-removed {
  429. margin-top: 16px;
  430. text-align: center;
  431. font-size: 12px;
  432. color: var(--text-muted);
  433. text-decoration: line-through;
  434. opacity: 0.55;
  435. }
  436. .login-follow-note {
  437. margin-top: 6px;
  438. text-align: center;
  439. font-size: 11px;
  440. color: var(--warning);
  441. }
  442. .toast {
  443. position: fixed;
  444. left: 50%;
  445. bottom: 48px;
  446. transform: translateX(-50%);
  447. background: rgba(31, 42, 38, 0.88);
  448. color: #fff;
  449. padding: 10px 16px;
  450. border-radius: 10px;
  451. font-size: 13px;
  452. opacity: 0;
  453. pointer-events: none;
  454. transition: opacity .2s;
  455. z-index: 20;
  456. }
  457. .toast.is-on { opacity: 1; }
  458. </style>
  459. </head>
  460. <body>
  461. <div id="app">
  462. <aside class="doc-panel">
  463. <h1>微信审批通知 · 菜单方案</h1>
  464. <p class="sub">
  465. 在「抄送我的」后新增「开启微信通知」菜单(铃铛图标),
  466. 把「关注服务号」与「账号绑定」合并为步骤 1 / 2。
  467. <strong>登录页「关注服务号」与首页顶栏入口均不展示</strong>,只保留新菜单。
  468. </p>
  469. <div class="section-title">页面</div>
  470. <div class="screen-nav" id="nav">
  471. <button type="button" data-screen="home" class="is-on">① 首页(新菜单)</button>
  472. <button type="button" data-screen="notify">② 开启微信通知(1 / 2)</button>
  473. <button type="button" data-screen="login">③ 登录页(入口移除示意)</button>
  474. </div>
  475. <div class="section-title">模拟状态</div>
  476. <div class="screen-nav">
  477. <button type="button" id="resetState">重置为未开启</button>
  478. <button type="button" id="markFollowed">仅完成步骤 1</button>
  479. <button type="button" id="markBound">完成步骤 1+2</button>
  480. </div>
  481. <div class="note">
  482. 交互说明:首页点「开启微信通知」进入设置页。<br />
  483. 图标:mobile-h5/static/menu-icons/oa-wechat-notify.png<br />
  484. 步骤 1:模拟关注(可弹二维码)。<br />
  485. 步骤 2:未关注时禁用;关注后可点「去绑定」。
  486. </div>
  487. </aside>
  488. <main class="stage">
  489. <div class="phone">
  490. <div class="status-bar"></div>
  491. <!-- 首页 -->
  492. <section class="screen is-on" data-screen="home">
  493. <div class="home-header">
  494. <div class="brand">中科兴皖 · 移动工作台</div>
  495. <div class="hello">您好,张三</div>
  496. <div class="meta">
  497. <div>产品经理 · 研发中心</div>
  498. <div class="meta__right">
  499. <span class="home-mp-legacy is-hidden" id="legacyHomeEntry">开启微信审批通知</span>
  500. <span class="home-logout">退出登录</span>
  501. </div>
  502. </div>
  503. </div>
  504. <div class="home-body">
  505. <div class="panel">
  506. <div class="panel-hd">
  507. <span class="panel-title">功能菜单</span>
  508. <span class="hint" id="menusHint">共 7 项</span>
  509. </div>
  510. <div class="menu-grid" id="menuGrid"></div>
  511. </div>
  512. </div>
  513. </section>
  514. <!-- 通知设置 -->
  515. <section class="screen" data-screen="notify">
  516. <div class="nav">
  517. <button type="button" class="nav__back" id="backHome" aria-label="返回">‹</button>
  518. <div class="nav__title">开启微信通知</div>
  519. </div>
  520. <div class="notify-body">
  521. <div class="step-card" id="step1Card">
  522. <div class="step-hd">
  523. <div class="step-num">1</div>
  524. <div style="flex:1;min-width:0">
  525. <div class="step-title">关注服务号</div>
  526. <div class="step-desc">关注后才能接收微信模板消息。可跳转服务号主页,或长按识别二维码。</div>
  527. </div>
  528. <span class="step-badge" id="step1Badge">未完成</span>
  529. </div>
  530. <div class="step-actions">
  531. <button type="button" class="btn btn-primary" id="btnFollow">去关注</button>
  532. <div class="qr-box" id="qrBox">
  533. <div class="qr-fake" aria-hidden="true"></div>
  534. <div class="qr-tip">长按识别关注(Demo 占位图)</div>
  535. <button type="button" class="btn btn-ghost" id="btnFollowDone" style="margin-top:10px">我已关注</button>
  536. </div>
  537. </div>
  538. </div>
  539. <div class="step-card" id="step2Card">
  540. <div class="step-hd">
  541. <div class="step-num">2</div>
  542. <div style="flex:1;min-width:0">
  543. <div class="step-title">绑定当前账号</div>
  544. <div class="step-desc">将服务号身份与系统账号关联,审批待办 / 抄送才能推送到你。</div>
  545. </div>
  546. <span class="step-badge" id="step2Badge">未完成</span>
  547. </div>
  548. <div class="step-actions">
  549. <button type="button" class="btn btn-primary" id="btnBind">去绑定</button>
  550. </div>
  551. </div>
  552. </div>
  553. </section>
  554. <!-- 登录页对照 -->
  555. <section class="screen" data-screen="login">
  556. <div class="login-page">
  557. <div class="login-brand">
  558. <div class="login-logo">皖</div>
  559. <div class="login-sub">员工工作台登录</div>
  560. </div>
  561. <div class="login-card">
  562. <div class="field">
  563. <label>账号</label>
  564. <div class="box">请输入用户名 / 工号</div>
  565. </div>
  566. <div class="field">
  567. <label>密码</label>
  568. <div class="box">请输入密码</div>
  569. </div>
  570. <div class="login-submit">登录</div>
  571. </div>
  572. <div class="login-follow-note" style="margin-top:16px">登录页不再展示「关注服务号」入口</div>
  573. </div>
  574. </section>
  575. </div>
  576. </main>
  577. </div>
  578. <div class="toast" id="toast"></div>
  579. <script>
  580. const MENUS = [
  581. { title: '发起审批', cls: 'c1', icon: '发' },
  582. { title: '草稿箱', cls: 'c2', icon: '草' },
  583. { title: '待办中心', cls: 'c3', icon: '待' },
  584. { title: '已办中心', cls: 'c4', icon: '已' },
  585. { title: '我发起的', cls: 'c5', icon: '我' },
  586. { title: '抄送我的', cls: 'c6', icon: '抄' },
  587. {
  588. title: '开启微信通知',
  589. cls: 'c7',
  590. iconImg: './oa-wechat-notify.png',
  591. isNew: true,
  592. openNotify: true,
  593. plain: true
  594. }
  595. ]
  596. const state = {
  597. followed: false,
  598. bound: false,
  599. showQr: false
  600. }
  601. const els = {
  602. nav: document.getElementById('nav'),
  603. screens: document.querySelectorAll('.screen'),
  604. menuGrid: document.getElementById('menuGrid'),
  605. menusHint: document.getElementById('menusHint'),
  606. step1Card: document.getElementById('step1Card'),
  607. step2Card: document.getElementById('step2Card'),
  608. step1Badge: document.getElementById('step1Badge'),
  609. step2Badge: document.getElementById('step2Badge'),
  610. btnFollow: document.getElementById('btnFollow'),
  611. btnBind: document.getElementById('btnBind'),
  612. qrBox: document.getElementById('qrBox'),
  613. toast: document.getElementById('toast')
  614. }
  615. function showToast(msg) {
  616. els.toast.textContent = msg
  617. els.toast.classList.add('is-on')
  618. clearTimeout(showToast._t)
  619. showToast._t = setTimeout(() => els.toast.classList.remove('is-on'), 1600)
  620. }
  621. function showScreen(name) {
  622. els.screens.forEach((s) => s.classList.toggle('is-on', s.dataset.screen === name))
  623. els.nav.querySelectorAll('button').forEach((b) => {
  624. b.classList.toggle('is-on', b.dataset.screen === name)
  625. })
  626. }
  627. function renderMenus() {
  628. els.menusHint.textContent = '共 ' + MENUS.length + ' 项'
  629. els.menuGrid.innerHTML = MENUS.map((m) => {
  630. const extra = m.isNew ? ' is-new' : ''
  631. const iconCls = 'menu-icon ' + m.cls + (m.plain ? ' is-plain' : '')
  632. const iconInner = m.iconImg
  633. ? '<img src="' + m.iconImg + '" alt="" />'
  634. : m.icon
  635. return (
  636. '<button type="button" class="menu-item' + extra + '" data-open="' + (m.openNotify ? '1' : '0') + '">' +
  637. '<span class="' + iconCls + '">' + iconInner + '</span>' +
  638. '<span class="menu-title">' + m.title + '</span>' +
  639. '</button>'
  640. )
  641. }).join('')
  642. }
  643. function renderNotify() {
  644. els.step1Card.classList.toggle('is-done', state.followed)
  645. els.step2Card.classList.toggle('is-done', state.bound)
  646. els.step1Badge.textContent = state.followed ? '已完成' : '未完成'
  647. els.step2Badge.textContent = state.bound ? '已完成' : '未完成'
  648. els.step1Badge.classList.toggle('is-done', state.followed)
  649. els.step2Badge.classList.toggle('is-done', state.bound)
  650. els.btnFollow.textContent = state.followed ? '重新打开关注页' : '去关注'
  651. els.qrBox.classList.toggle('is-on', state.showQr && !state.followed)
  652. els.btnBind.disabled = !state.followed || state.bound
  653. els.btnBind.textContent = state.bound ? '已绑定' : (state.followed ? '去绑定' : '请先完成步骤 1')
  654. }
  655. els.nav.addEventListener('click', (e) => {
  656. const btn = e.target.closest('button[data-screen]')
  657. if (!btn) return
  658. showScreen(btn.dataset.screen)
  659. })
  660. document.getElementById('backHome').addEventListener('click', () => showScreen('home'))
  661. els.menuGrid.addEventListener('click', (e) => {
  662. const item = e.target.closest('.menu-item')
  663. if (!item) return
  664. if (item.dataset.open === '1') {
  665. showScreen('notify')
  666. return
  667. }
  668. showToast(item.querySelector('.menu-title').textContent)
  669. })
  670. els.btnFollow.addEventListener('click', () => {
  671. state.showQr = true
  672. renderNotify()
  673. showToast('Demo:打开服务号主页 / 二维码')
  674. })
  675. document.getElementById('btnFollowDone').addEventListener('click', () => {
  676. state.followed = true
  677. state.showQr = false
  678. renderNotify()
  679. showToast('步骤 1 已完成')
  680. })
  681. els.btnBind.addEventListener('click', () => {
  682. if (!state.followed || state.bound) return
  683. state.bound = true
  684. renderNotify()
  685. showToast('步骤 2 已完成 · 通知已开启')
  686. })
  687. document.getElementById('resetState').addEventListener('click', () => {
  688. state.followed = false
  689. state.bound = false
  690. state.showQr = false
  691. renderNotify()
  692. showScreen('notify')
  693. showToast('已重置')
  694. })
  695. document.getElementById('markFollowed').addEventListener('click', () => {
  696. state.followed = true
  697. state.bound = false
  698. state.showQr = false
  699. renderNotify()
  700. showScreen('notify')
  701. })
  702. document.getElementById('markBound').addEventListener('click', () => {
  703. state.followed = true
  704. state.bound = true
  705. state.showQr = false
  706. renderNotify()
  707. showScreen('notify')
  708. })
  709. renderMenus()
  710. renderNotify()
  711. </script>
  712. </body>
  713. </html>