|
|
@@ -0,0 +1,772 @@
|
|
|
+<!DOCTYPE html>
|
|
|
+<html lang="zh-CN">
|
|
|
+<head>
|
|
|
+ <meta charset="UTF-8" />
|
|
|
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover" />
|
|
|
+ <title>中科兴皖 · 微信审批通知菜单 Demo</title>
|
|
|
+ <style>
|
|
|
+ :root {
|
|
|
+ --brand-green: #0a9f6d;
|
|
|
+ --brand-green-dark: #087f57;
|
|
|
+ --brand-green-soft: #e9f9f2;
|
|
|
+ --barley-yellow: #d6a343;
|
|
|
+ --barley-yellow-soft: #fff7e8;
|
|
|
+ --bg-page: #f5f8f7;
|
|
|
+ --surface: #ffffff;
|
|
|
+ --text-primary: #1f2a26;
|
|
|
+ --text-muted: #6b7b74;
|
|
|
+ --border: #dcebe4;
|
|
|
+ --danger: #d14343;
|
|
|
+ --warning: #cf8a19;
|
|
|
+ --success: #189b65;
|
|
|
+ --radius-card: 14px;
|
|
|
+ --radius-lg: 20px;
|
|
|
+ --shadow-soft: 0 4px 16px rgba(8, 127, 87, 0.08);
|
|
|
+ }
|
|
|
+
|
|
|
+ * { box-sizing: border-box; }
|
|
|
+ html, body {
|
|
|
+ margin: 0;
|
|
|
+ padding: 0;
|
|
|
+ min-height: 100%;
|
|
|
+ font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Helvetica Neue", sans-serif;
|
|
|
+ color: var(--text-primary);
|
|
|
+ background:
|
|
|
+ radial-gradient(900px 420px at 10% -10%, rgba(10, 159, 109, 0.14), transparent 55%),
|
|
|
+ radial-gradient(700px 380px at 90% 0%, rgba(214, 163, 67, 0.12), transparent 50%),
|
|
|
+ linear-gradient(180deg, #eef6f2 0%, #f7faf9 40%, #f3f6f5 100%);
|
|
|
+ }
|
|
|
+
|
|
|
+ body {
|
|
|
+ display: flex;
|
|
|
+ justify-content: center;
|
|
|
+ padding: 24px 16px 40px;
|
|
|
+ }
|
|
|
+
|
|
|
+ #app {
|
|
|
+ width: 100%;
|
|
|
+ max-width: 980px;
|
|
|
+ display: grid;
|
|
|
+ grid-template-columns: 280px 1fr;
|
|
|
+ gap: 24px;
|
|
|
+ align-items: start;
|
|
|
+ }
|
|
|
+
|
|
|
+ @media (max-width: 860px) {
|
|
|
+ #app { grid-template-columns: 1fr; }
|
|
|
+ .doc-panel { position: static; }
|
|
|
+ }
|
|
|
+
|
|
|
+ .doc-panel {
|
|
|
+ position: sticky;
|
|
|
+ top: 24px;
|
|
|
+ background: rgba(255, 255, 255, 0.92);
|
|
|
+ border: 1px solid var(--border);
|
|
|
+ border-radius: 18px;
|
|
|
+ padding: 20px 18px;
|
|
|
+ box-shadow: var(--shadow-soft);
|
|
|
+ }
|
|
|
+
|
|
|
+ .doc-panel h1 {
|
|
|
+ margin: 0 0 6px;
|
|
|
+ font-size: 20px;
|
|
|
+ line-height: 1.3;
|
|
|
+ color: var(--brand-green-dark);
|
|
|
+ }
|
|
|
+
|
|
|
+ .doc-panel .sub {
|
|
|
+ margin: 0 0 16px;
|
|
|
+ font-size: 12px;
|
|
|
+ color: var(--text-muted);
|
|
|
+ line-height: 1.5;
|
|
|
+ }
|
|
|
+
|
|
|
+ .section-title {
|
|
|
+ margin: 16px 0 8px;
|
|
|
+ font-size: 12px;
|
|
|
+ font-weight: 600;
|
|
|
+ color: var(--text-muted);
|
|
|
+ letter-spacing: 0.04em;
|
|
|
+ text-transform: uppercase;
|
|
|
+ }
|
|
|
+
|
|
|
+ .screen-nav {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ gap: 8px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .screen-nav button {
|
|
|
+ appearance: none;
|
|
|
+ border: 1px solid var(--border);
|
|
|
+ background: #fff;
|
|
|
+ border-radius: 10px;
|
|
|
+ padding: 10px 12px;
|
|
|
+ text-align: left;
|
|
|
+ font-size: 13px;
|
|
|
+ color: var(--text-primary);
|
|
|
+ cursor: pointer;
|
|
|
+ }
|
|
|
+
|
|
|
+ .screen-nav button.is-on {
|
|
|
+ border-color: var(--brand-green);
|
|
|
+ background: var(--brand-green-soft);
|
|
|
+ color: var(--brand-green-dark);
|
|
|
+ font-weight: 600;
|
|
|
+ }
|
|
|
+
|
|
|
+ .note {
|
|
|
+ margin-top: 14px;
|
|
|
+ padding: 10px 12px;
|
|
|
+ border-radius: 10px;
|
|
|
+ background: var(--barley-yellow-soft);
|
|
|
+ border: 1px solid #f0dfb4;
|
|
|
+ font-size: 12px;
|
|
|
+ line-height: 1.55;
|
|
|
+ color: #7a5a12;
|
|
|
+ }
|
|
|
+
|
|
|
+ .stage {
|
|
|
+ display: flex;
|
|
|
+ justify-content: center;
|
|
|
+ }
|
|
|
+
|
|
|
+ .phone {
|
|
|
+ width: 375px;
|
|
|
+ max-width: 100%;
|
|
|
+ background: var(--bg-page);
|
|
|
+ border-radius: 28px;
|
|
|
+ border: 1px solid var(--border);
|
|
|
+ box-shadow: var(--shadow-soft);
|
|
|
+ overflow: hidden;
|
|
|
+ min-height: 720px;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ }
|
|
|
+
|
|
|
+ .status-bar {
|
|
|
+ height: 28px;
|
|
|
+ background: linear-gradient(180deg, #0a9f6d 0%, #087f57 100%);
|
|
|
+ }
|
|
|
+
|
|
|
+ .screen { display: none; flex: 1; flex-direction: column; }
|
|
|
+ .screen.is-on { display: flex; }
|
|
|
+
|
|
|
+ /* —— 首页 —— */
|
|
|
+ .home-header {
|
|
|
+ background: linear-gradient(180deg, #0a9f6d 0%, #087f57 100%);
|
|
|
+ color: #fff;
|
|
|
+ padding: 8px 16px 22px;
|
|
|
+ border-radius: 0 0 22px 22px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .brand { font-size: 13px; opacity: 0.9; }
|
|
|
+ .hello { margin-top: 10px; font-size: 22px; font-weight: 700; }
|
|
|
+ .meta {
|
|
|
+ margin-top: 8px;
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ align-items: flex-start;
|
|
|
+ gap: 12px;
|
|
|
+ font-size: 12px;
|
|
|
+ opacity: 0.92;
|
|
|
+ }
|
|
|
+ .meta__right {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ align-items: flex-end;
|
|
|
+ gap: 6px;
|
|
|
+ flex-shrink: 0;
|
|
|
+ }
|
|
|
+ .home-logout {
|
|
|
+ text-decoration: underline;
|
|
|
+ text-underline-offset: 2px;
|
|
|
+ cursor: pointer;
|
|
|
+ opacity: 0.9;
|
|
|
+ }
|
|
|
+ .home-mp-legacy {
|
|
|
+ font-size: 11px;
|
|
|
+ text-decoration: underline;
|
|
|
+ opacity: 0.75;
|
|
|
+ cursor: pointer;
|
|
|
+ }
|
|
|
+ .home-mp-legacy.is-hidden { display: none; }
|
|
|
+
|
|
|
+ .home-body { padding: 14px 12px 24px; flex: 1; }
|
|
|
+ .panel {
|
|
|
+ background: var(--surface);
|
|
|
+ border-radius: var(--radius-card);
|
|
|
+ border: 1px solid var(--border);
|
|
|
+ padding: 14px 12px 8px;
|
|
|
+ }
|
|
|
+ .panel-hd {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ align-items: baseline;
|
|
|
+ margin-bottom: 12px;
|
|
|
+ padding: 0 4px;
|
|
|
+ }
|
|
|
+ .panel-title { font-size: 15px; font-weight: 700; }
|
|
|
+ .hint { font-size: 12px; color: var(--text-muted); }
|
|
|
+
|
|
|
+ .menu-grid {
|
|
|
+ display: grid;
|
|
|
+ grid-template-columns: repeat(4, 1fr);
|
|
|
+ gap: 10px 4px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .menu-item {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ align-items: center;
|
|
|
+ gap: 6px;
|
|
|
+ padding: 8px 4px;
|
|
|
+ border: 0;
|
|
|
+ background: transparent;
|
|
|
+ cursor: pointer;
|
|
|
+ border-radius: 10px;
|
|
|
+ }
|
|
|
+ .menu-item:hover { background: var(--brand-green-soft); }
|
|
|
+ .menu-item.is-new .menu-icon {
|
|
|
+ outline: 2px solid var(--barley-yellow);
|
|
|
+ outline-offset: 2px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .menu-icon {
|
|
|
+ width: 44px;
|
|
|
+ height: 44px;
|
|
|
+ border-radius: 12px;
|
|
|
+ display: grid;
|
|
|
+ place-items: center;
|
|
|
+ font-size: 18px;
|
|
|
+ color: #fff;
|
|
|
+ font-weight: 700;
|
|
|
+ overflow: hidden;
|
|
|
+ }
|
|
|
+ .menu-icon img {
|
|
|
+ width: 44px;
|
|
|
+ height: 44px;
|
|
|
+ object-fit: contain;
|
|
|
+ display: block;
|
|
|
+ }
|
|
|
+ .menu-icon.is-plain {
|
|
|
+ background: transparent !important;
|
|
|
+ border-radius: 0;
|
|
|
+ }
|
|
|
+ .menu-title {
|
|
|
+ font-size: 11px;
|
|
|
+ line-height: 1.3;
|
|
|
+ text-align: center;
|
|
|
+ color: var(--text-primary);
|
|
|
+ }
|
|
|
+
|
|
|
+ .c1 { background: #0a9f6d; }
|
|
|
+ .c2 { background: #2f8f7a; }
|
|
|
+ .c3 { background: #3d8bb8; }
|
|
|
+ .c4 { background: #5b7fbf; }
|
|
|
+ .c5 { background: #7a6bb8; }
|
|
|
+ .c6 { background: #cf8a19; }
|
|
|
+ .c7 { background: transparent; }
|
|
|
+
|
|
|
+ /* —— 通知设置页 —— */
|
|
|
+ .nav {
|
|
|
+ background: linear-gradient(180deg, #0a9f6d 0%, #087f57 100%);
|
|
|
+ color: #fff;
|
|
|
+ padding: 10px 12px 14px;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 8px;
|
|
|
+ }
|
|
|
+ .nav__back {
|
|
|
+ width: 36px;
|
|
|
+ height: 36px;
|
|
|
+ border: 0;
|
|
|
+ background: rgba(255,255,255,0.16);
|
|
|
+ color: #fff;
|
|
|
+ border-radius: 10px;
|
|
|
+ cursor: pointer;
|
|
|
+ font-size: 18px;
|
|
|
+ }
|
|
|
+ .nav__title { font-size: 17px; font-weight: 700; }
|
|
|
+
|
|
|
+ .notify-body { padding: 14px 12px 28px; flex: 1; }
|
|
|
+
|
|
|
+ .status-banner {
|
|
|
+ display: none;
|
|
|
+ }
|
|
|
+
|
|
|
+ .step-card {
|
|
|
+ background: var(--surface);
|
|
|
+ border: 1px solid var(--border);
|
|
|
+ border-radius: var(--radius-card);
|
|
|
+ padding: 14px;
|
|
|
+ margin-bottom: 10px;
|
|
|
+ }
|
|
|
+ .step-card.is-done {
|
|
|
+ border-color: #b7ebcf;
|
|
|
+ background: linear-gradient(180deg, #f6fffb 0%, #fff 60%);
|
|
|
+ }
|
|
|
+ .step-hd {
|
|
|
+ display: flex;
|
|
|
+ align-items: flex-start;
|
|
|
+ gap: 10px;
|
|
|
+ }
|
|
|
+ .step-num {
|
|
|
+ width: 28px;
|
|
|
+ height: 28px;
|
|
|
+ border-radius: 50%;
|
|
|
+ background: var(--brand-green);
|
|
|
+ color: #fff;
|
|
|
+ display: grid;
|
|
|
+ place-items: center;
|
|
|
+ font-size: 14px;
|
|
|
+ font-weight: 700;
|
|
|
+ flex-shrink: 0;
|
|
|
+ }
|
|
|
+ .step-card.is-done .step-num {
|
|
|
+ background: var(--success);
|
|
|
+ }
|
|
|
+ .step-title {
|
|
|
+ font-size: 15px;
|
|
|
+ font-weight: 700;
|
|
|
+ line-height: 1.35;
|
|
|
+ }
|
|
|
+ .step-desc {
|
|
|
+ margin-top: 4px;
|
|
|
+ font-size: 12px;
|
|
|
+ color: var(--text-muted);
|
|
|
+ line-height: 1.5;
|
|
|
+ }
|
|
|
+ .step-badge {
|
|
|
+ margin-left: auto;
|
|
|
+ font-size: 11px;
|
|
|
+ padding: 2px 8px;
|
|
|
+ border-radius: 999px;
|
|
|
+ background: #eef2f0;
|
|
|
+ color: var(--text-muted);
|
|
|
+ flex-shrink: 0;
|
|
|
+ }
|
|
|
+ .step-badge.is-done {
|
|
|
+ background: var(--brand-green-soft);
|
|
|
+ color: var(--brand-green-dark);
|
|
|
+ }
|
|
|
+
|
|
|
+ .step-actions { margin-top: 12px; padding-left: 38px; }
|
|
|
+ .btn {
|
|
|
+ appearance: none;
|
|
|
+ border: 0;
|
|
|
+ border-radius: 10px;
|
|
|
+ padding: 10px 14px;
|
|
|
+ font-size: 14px;
|
|
|
+ font-weight: 600;
|
|
|
+ cursor: pointer;
|
|
|
+ min-height: 40px;
|
|
|
+ }
|
|
|
+ .btn-primary {
|
|
|
+ background: var(--brand-green);
|
|
|
+ color: #fff;
|
|
|
+ width: 100%;
|
|
|
+ }
|
|
|
+ .btn-primary:disabled {
|
|
|
+ background: #a7d7c4;
|
|
|
+ cursor: default;
|
|
|
+ }
|
|
|
+ .btn-ghost {
|
|
|
+ background: #fff;
|
|
|
+ color: var(--brand-green-dark);
|
|
|
+ border: 1px solid var(--border);
|
|
|
+ width: 100%;
|
|
|
+ }
|
|
|
+
|
|
|
+ .qr-box {
|
|
|
+ margin-top: 10px;
|
|
|
+ display: none;
|
|
|
+ padding: 12px;
|
|
|
+ border-radius: 12px;
|
|
|
+ border: 1px dashed #a7f3d0;
|
|
|
+ background: #f8fffb;
|
|
|
+ text-align: center;
|
|
|
+ }
|
|
|
+ .qr-box.is-on { display: block; }
|
|
|
+ .qr-fake {
|
|
|
+ width: 140px;
|
|
|
+ height: 140px;
|
|
|
+ margin: 0 auto 8px;
|
|
|
+ border-radius: 8px;
|
|
|
+ background:
|
|
|
+ repeating-linear-gradient(0deg, #1f2a26 0 6px, transparent 6px 12px),
|
|
|
+ repeating-linear-gradient(90deg, #1f2a26 0 6px, transparent 6px 12px);
|
|
|
+ opacity: 0.18;
|
|
|
+ }
|
|
|
+ .qr-tip { font-size: 12px; color: var(--text-muted); }
|
|
|
+
|
|
|
+ /* —— 登录页(对照:入口已移除) —— */
|
|
|
+ .login-page {
|
|
|
+ padding: 36px 20px 28px;
|
|
|
+ flex: 1;
|
|
|
+ background: linear-gradient(180deg, #e9f9f2 0%, #f5f8f7 42%, #f5f8f7 100%);
|
|
|
+ }
|
|
|
+ .login-brand { text-align: center; margin-bottom: 22px; }
|
|
|
+ .login-logo {
|
|
|
+ width: 72px;
|
|
|
+ height: 72px;
|
|
|
+ margin: 0 auto 10px;
|
|
|
+ border-radius: 18px;
|
|
|
+ background: var(--brand-green);
|
|
|
+ color: #fff;
|
|
|
+ display: grid;
|
|
|
+ place-items: center;
|
|
|
+ font-size: 28px;
|
|
|
+ font-weight: 800;
|
|
|
+ }
|
|
|
+ .login-sub { font-size: 13px; color: var(--text-muted); }
|
|
|
+ .login-card {
|
|
|
+ background: #fff;
|
|
|
+ border-radius: 16px;
|
|
|
+ border: 1px solid var(--border);
|
|
|
+ padding: 16px;
|
|
|
+ box-shadow: var(--shadow-soft);
|
|
|
+ }
|
|
|
+ .field { margin-bottom: 12px; }
|
|
|
+ .field label {
|
|
|
+ display: block;
|
|
|
+ font-size: 12px;
|
|
|
+ color: var(--text-muted);
|
|
|
+ margin-bottom: 6px;
|
|
|
+ }
|
|
|
+ .field .box {
|
|
|
+ height: 42px;
|
|
|
+ border: 1px solid var(--border);
|
|
|
+ border-radius: 10px;
|
|
|
+ background: #fafcfb;
|
|
|
+ padding: 0 12px;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ color: #9aaba3;
|
|
|
+ font-size: 14px;
|
|
|
+ }
|
|
|
+ .login-submit {
|
|
|
+ margin-top: 8px;
|
|
|
+ height: 44px;
|
|
|
+ border-radius: 10px;
|
|
|
+ background: var(--brand-green);
|
|
|
+ color: #fff;
|
|
|
+ display: grid;
|
|
|
+ place-items: center;
|
|
|
+ font-weight: 700;
|
|
|
+ }
|
|
|
+ .login-follow-removed {
|
|
|
+ margin-top: 16px;
|
|
|
+ text-align: center;
|
|
|
+ font-size: 12px;
|
|
|
+ color: var(--text-muted);
|
|
|
+ text-decoration: line-through;
|
|
|
+ opacity: 0.55;
|
|
|
+ }
|
|
|
+ .login-follow-note {
|
|
|
+ margin-top: 6px;
|
|
|
+ text-align: center;
|
|
|
+ font-size: 11px;
|
|
|
+ color: var(--warning);
|
|
|
+ }
|
|
|
+
|
|
|
+ .toast {
|
|
|
+ position: fixed;
|
|
|
+ left: 50%;
|
|
|
+ bottom: 48px;
|
|
|
+ transform: translateX(-50%);
|
|
|
+ background: rgba(31, 42, 38, 0.88);
|
|
|
+ color: #fff;
|
|
|
+ padding: 10px 16px;
|
|
|
+ border-radius: 10px;
|
|
|
+ font-size: 13px;
|
|
|
+ opacity: 0;
|
|
|
+ pointer-events: none;
|
|
|
+ transition: opacity .2s;
|
|
|
+ z-index: 20;
|
|
|
+ }
|
|
|
+ .toast.is-on { opacity: 1; }
|
|
|
+ </style>
|
|
|
+</head>
|
|
|
+<body>
|
|
|
+ <div id="app">
|
|
|
+ <aside class="doc-panel">
|
|
|
+ <h1>微信审批通知 · 菜单方案</h1>
|
|
|
+ <p class="sub">
|
|
|
+ 在「抄送我的」后新增「开启微信通知」菜单(铃铛图标),
|
|
|
+ 把「关注服务号」与「账号绑定」合并为步骤 1 / 2。
|
|
|
+ <strong>登录页「关注服务号」与首页顶栏入口均不展示</strong>,只保留新菜单。
|
|
|
+ </p>
|
|
|
+
|
|
|
+ <div class="section-title">页面</div>
|
|
|
+ <div class="screen-nav" id="nav">
|
|
|
+ <button type="button" data-screen="home" class="is-on">① 首页(新菜单)</button>
|
|
|
+ <button type="button" data-screen="notify">② 开启微信通知(1 / 2)</button>
|
|
|
+ <button type="button" data-screen="login">③ 登录页(入口移除示意)</button>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="section-title">模拟状态</div>
|
|
|
+ <div class="screen-nav">
|
|
|
+ <button type="button" id="resetState">重置为未开启</button>
|
|
|
+ <button type="button" id="markFollowed">仅完成步骤 1</button>
|
|
|
+ <button type="button" id="markBound">完成步骤 1+2</button>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="note">
|
|
|
+ 交互说明:首页点「开启微信通知」进入设置页。<br />
|
|
|
+ 图标:mobile-h5/static/menu-icons/oa-wechat-notify.png<br />
|
|
|
+ 步骤 1:模拟关注(可弹二维码)。<br />
|
|
|
+ 步骤 2:未关注时禁用;关注后可点「去绑定」。
|
|
|
+ </div>
|
|
|
+ </aside>
|
|
|
+
|
|
|
+ <main class="stage">
|
|
|
+ <div class="phone">
|
|
|
+ <div class="status-bar"></div>
|
|
|
+
|
|
|
+ <!-- 首页 -->
|
|
|
+ <section class="screen is-on" data-screen="home">
|
|
|
+ <div class="home-header">
|
|
|
+ <div class="brand">中科兴皖 · 移动工作台</div>
|
|
|
+ <div class="hello">您好,张三</div>
|
|
|
+ <div class="meta">
|
|
|
+ <div>产品经理 · 研发中心</div>
|
|
|
+ <div class="meta__right">
|
|
|
+ <span class="home-mp-legacy is-hidden" id="legacyHomeEntry">开启微信审批通知</span>
|
|
|
+ <span class="home-logout">退出登录</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="home-body">
|
|
|
+ <div class="panel">
|
|
|
+ <div class="panel-hd">
|
|
|
+ <span class="panel-title">功能菜单</span>
|
|
|
+ <span class="hint" id="menusHint">共 7 项</span>
|
|
|
+ </div>
|
|
|
+ <div class="menu-grid" id="menuGrid"></div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </section>
|
|
|
+
|
|
|
+ <!-- 通知设置 -->
|
|
|
+ <section class="screen" data-screen="notify">
|
|
|
+ <div class="nav">
|
|
|
+ <button type="button" class="nav__back" id="backHome" aria-label="返回">‹</button>
|
|
|
+ <div class="nav__title">开启微信通知</div>
|
|
|
+ </div>
|
|
|
+ <div class="notify-body">
|
|
|
+ <div class="step-card" id="step1Card">
|
|
|
+ <div class="step-hd">
|
|
|
+ <div class="step-num">1</div>
|
|
|
+ <div style="flex:1;min-width:0">
|
|
|
+ <div class="step-title">关注服务号</div>
|
|
|
+ <div class="step-desc">关注后才能接收微信模板消息。可跳转服务号主页,或长按识别二维码。</div>
|
|
|
+ </div>
|
|
|
+ <span class="step-badge" id="step1Badge">未完成</span>
|
|
|
+ </div>
|
|
|
+ <div class="step-actions">
|
|
|
+ <button type="button" class="btn btn-primary" id="btnFollow">去关注</button>
|
|
|
+ <div class="qr-box" id="qrBox">
|
|
|
+ <div class="qr-fake" aria-hidden="true"></div>
|
|
|
+ <div class="qr-tip">长按识别关注(Demo 占位图)</div>
|
|
|
+ <button type="button" class="btn btn-ghost" id="btnFollowDone" style="margin-top:10px">我已关注</button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="step-card" id="step2Card">
|
|
|
+ <div class="step-hd">
|
|
|
+ <div class="step-num">2</div>
|
|
|
+ <div style="flex:1;min-width:0">
|
|
|
+ <div class="step-title">绑定当前账号</div>
|
|
|
+ <div class="step-desc">将服务号身份与系统账号关联,审批待办 / 抄送才能推送到你。</div>
|
|
|
+ </div>
|
|
|
+ <span class="step-badge" id="step2Badge">未完成</span>
|
|
|
+ </div>
|
|
|
+ <div class="step-actions">
|
|
|
+ <button type="button" class="btn btn-primary" id="btnBind">去绑定</button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </section>
|
|
|
+
|
|
|
+ <!-- 登录页对照 -->
|
|
|
+ <section class="screen" data-screen="login">
|
|
|
+ <div class="login-page">
|
|
|
+ <div class="login-brand">
|
|
|
+ <div class="login-logo">皖</div>
|
|
|
+ <div class="login-sub">员工工作台登录</div>
|
|
|
+ </div>
|
|
|
+ <div class="login-card">
|
|
|
+ <div class="field">
|
|
|
+ <label>账号</label>
|
|
|
+ <div class="box">请输入用户名 / 工号</div>
|
|
|
+ </div>
|
|
|
+ <div class="field">
|
|
|
+ <label>密码</label>
|
|
|
+ <div class="box">请输入密码</div>
|
|
|
+ </div>
|
|
|
+ <div class="login-submit">登录</div>
|
|
|
+ </div>
|
|
|
+ <div class="login-follow-note" style="margin-top:16px">登录页不再展示「关注服务号」入口</div>
|
|
|
+ </div>
|
|
|
+ </section>
|
|
|
+ </div>
|
|
|
+ </main>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="toast" id="toast"></div>
|
|
|
+
|
|
|
+ <script>
|
|
|
+ const MENUS = [
|
|
|
+ { title: '发起审批', cls: 'c1', icon: '发' },
|
|
|
+ { title: '草稿箱', cls: 'c2', icon: '草' },
|
|
|
+ { title: '待办中心', cls: 'c3', icon: '待' },
|
|
|
+ { title: '已办中心', cls: 'c4', icon: '已' },
|
|
|
+ { title: '我发起的', cls: 'c5', icon: '我' },
|
|
|
+ { title: '抄送我的', cls: 'c6', icon: '抄' },
|
|
|
+ {
|
|
|
+ title: '开启微信通知',
|
|
|
+ cls: 'c7',
|
|
|
+ iconImg: './oa-wechat-notify.png',
|
|
|
+ isNew: true,
|
|
|
+ openNotify: true,
|
|
|
+ plain: true
|
|
|
+ }
|
|
|
+ ]
|
|
|
+
|
|
|
+ const state = {
|
|
|
+ followed: false,
|
|
|
+ bound: false,
|
|
|
+ showQr: false
|
|
|
+ }
|
|
|
+
|
|
|
+ const els = {
|
|
|
+ nav: document.getElementById('nav'),
|
|
|
+ screens: document.querySelectorAll('.screen'),
|
|
|
+ menuGrid: document.getElementById('menuGrid'),
|
|
|
+ menusHint: document.getElementById('menusHint'),
|
|
|
+ step1Card: document.getElementById('step1Card'),
|
|
|
+ step2Card: document.getElementById('step2Card'),
|
|
|
+ step1Badge: document.getElementById('step1Badge'),
|
|
|
+ step2Badge: document.getElementById('step2Badge'),
|
|
|
+ btnFollow: document.getElementById('btnFollow'),
|
|
|
+ btnBind: document.getElementById('btnBind'),
|
|
|
+ qrBox: document.getElementById('qrBox'),
|
|
|
+ toast: document.getElementById('toast')
|
|
|
+ }
|
|
|
+
|
|
|
+ function showToast(msg) {
|
|
|
+ els.toast.textContent = msg
|
|
|
+ els.toast.classList.add('is-on')
|
|
|
+ clearTimeout(showToast._t)
|
|
|
+ showToast._t = setTimeout(() => els.toast.classList.remove('is-on'), 1600)
|
|
|
+ }
|
|
|
+
|
|
|
+ function showScreen(name) {
|
|
|
+ els.screens.forEach((s) => s.classList.toggle('is-on', s.dataset.screen === name))
|
|
|
+ els.nav.querySelectorAll('button').forEach((b) => {
|
|
|
+ b.classList.toggle('is-on', b.dataset.screen === name)
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ function renderMenus() {
|
|
|
+ els.menusHint.textContent = '共 ' + MENUS.length + ' 项'
|
|
|
+ els.menuGrid.innerHTML = MENUS.map((m) => {
|
|
|
+ const extra = m.isNew ? ' is-new' : ''
|
|
|
+ const iconCls = 'menu-icon ' + m.cls + (m.plain ? ' is-plain' : '')
|
|
|
+ const iconInner = m.iconImg
|
|
|
+ ? '<img src="' + m.iconImg + '" alt="" />'
|
|
|
+ : m.icon
|
|
|
+ return (
|
|
|
+ '<button type="button" class="menu-item' + extra + '" data-open="' + (m.openNotify ? '1' : '0') + '">' +
|
|
|
+ '<span class="' + iconCls + '">' + iconInner + '</span>' +
|
|
|
+ '<span class="menu-title">' + m.title + '</span>' +
|
|
|
+ '</button>'
|
|
|
+ )
|
|
|
+ }).join('')
|
|
|
+ }
|
|
|
+
|
|
|
+ function renderNotify() {
|
|
|
+ els.step1Card.classList.toggle('is-done', state.followed)
|
|
|
+ els.step2Card.classList.toggle('is-done', state.bound)
|
|
|
+ els.step1Badge.textContent = state.followed ? '已完成' : '未完成'
|
|
|
+ els.step2Badge.textContent = state.bound ? '已完成' : '未完成'
|
|
|
+ els.step1Badge.classList.toggle('is-done', state.followed)
|
|
|
+ els.step2Badge.classList.toggle('is-done', state.bound)
|
|
|
+
|
|
|
+ els.btnFollow.textContent = state.followed ? '重新打开关注页' : '去关注'
|
|
|
+ els.qrBox.classList.toggle('is-on', state.showQr && !state.followed)
|
|
|
+
|
|
|
+ els.btnBind.disabled = !state.followed || state.bound
|
|
|
+ els.btnBind.textContent = state.bound ? '已绑定' : (state.followed ? '去绑定' : '请先完成步骤 1')
|
|
|
+ }
|
|
|
+
|
|
|
+ els.nav.addEventListener('click', (e) => {
|
|
|
+ const btn = e.target.closest('button[data-screen]')
|
|
|
+ if (!btn) return
|
|
|
+ showScreen(btn.dataset.screen)
|
|
|
+ })
|
|
|
+
|
|
|
+ document.getElementById('backHome').addEventListener('click', () => showScreen('home'))
|
|
|
+
|
|
|
+ els.menuGrid.addEventListener('click', (e) => {
|
|
|
+ const item = e.target.closest('.menu-item')
|
|
|
+ if (!item) return
|
|
|
+ if (item.dataset.open === '1') {
|
|
|
+ showScreen('notify')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ showToast(item.querySelector('.menu-title').textContent)
|
|
|
+ })
|
|
|
+
|
|
|
+ els.btnFollow.addEventListener('click', () => {
|
|
|
+ state.showQr = true
|
|
|
+ renderNotify()
|
|
|
+ showToast('Demo:打开服务号主页 / 二维码')
|
|
|
+ })
|
|
|
+
|
|
|
+ document.getElementById('btnFollowDone').addEventListener('click', () => {
|
|
|
+ state.followed = true
|
|
|
+ state.showQr = false
|
|
|
+ renderNotify()
|
|
|
+ showToast('步骤 1 已完成')
|
|
|
+ })
|
|
|
+
|
|
|
+ els.btnBind.addEventListener('click', () => {
|
|
|
+ if (!state.followed || state.bound) return
|
|
|
+ state.bound = true
|
|
|
+ renderNotify()
|
|
|
+ showToast('步骤 2 已完成 · 通知已开启')
|
|
|
+ })
|
|
|
+
|
|
|
+ document.getElementById('resetState').addEventListener('click', () => {
|
|
|
+ state.followed = false
|
|
|
+ state.bound = false
|
|
|
+ state.showQr = false
|
|
|
+ renderNotify()
|
|
|
+ showScreen('notify')
|
|
|
+ showToast('已重置')
|
|
|
+ })
|
|
|
+
|
|
|
+ document.getElementById('markFollowed').addEventListener('click', () => {
|
|
|
+ state.followed = true
|
|
|
+ state.bound = false
|
|
|
+ state.showQr = false
|
|
|
+ renderNotify()
|
|
|
+ showScreen('notify')
|
|
|
+ })
|
|
|
+
|
|
|
+ document.getElementById('markBound').addEventListener('click', () => {
|
|
|
+ state.followed = true
|
|
|
+ state.bound = true
|
|
|
+ state.showQr = false
|
|
|
+ renderNotify()
|
|
|
+ showScreen('notify')
|
|
|
+ })
|
|
|
+
|
|
|
+ renderMenus()
|
|
|
+ renderNotify()
|
|
|
+ </script>
|
|
|
+</body>
|
|
|
+</html>
|