Commit afe6613aed80af844046e3c03b4bad1322996e0a
1 parent
a0e6eabb
chore(prototype): add erp.html UI prototype
Static HTML mockup used as design reference for the frontend scaffold (layout, color tokens, table/form patterns).
Showing
1 changed file
with
850 additions
and
0 deletions
prototype/erp.html
0 → 100644
| 1 | +<!doctype html> | ||
| 2 | +<html lang="zh-CN"> | ||
| 3 | +<head> | ||
| 4 | +<meta charset="utf-8" /> | ||
| 5 | +<title>ERP - 企业业务能力平台</title> | ||
| 6 | +<meta name="viewport" content="width=device-width, initial-scale=1" /> | ||
| 7 | +<style> | ||
| 8 | + :root { | ||
| 9 | + --bg: #f3f4f6; | ||
| 10 | + --panel: #ffffff; | ||
| 11 | + --topbar: #1f1f23; | ||
| 12 | + --topbar-text: #ffffff; | ||
| 13 | + --primary: #2f7adf; | ||
| 14 | + --primary-strong: #1f6ed4; | ||
| 15 | + --link: #1e84e6; | ||
| 16 | + --text: #333333; | ||
| 17 | + --text-soft: #555; | ||
| 18 | + --text-mute: #888; | ||
| 19 | + --border: #e3e6eb; | ||
| 20 | + --row-alt: #f7f8fa; | ||
| 21 | + --header-bg: #f4f5f7; | ||
| 22 | + --danger: #e34d4d; | ||
| 23 | + --tab-active: #1e84e6; | ||
| 24 | + --toolbar-bg: #2c2f36; | ||
| 25 | + --toolbar-text: #ffffff; | ||
| 26 | + --label: #f04848; | ||
| 27 | + --field-bg: #eaf3fe; | ||
| 28 | + --field-bg-readonly: #f1f3f5; | ||
| 29 | + } | ||
| 30 | + *{box-sizing:border-box} | ||
| 31 | + html,body{margin:0;padding:0;background:var(--bg);color:var(--text);font-family:"Microsoft YaHei","PingFang SC","Helvetica Neue",Helvetica,Arial,"Segoe UI",sans-serif;font-size:13px;} | ||
| 32 | + button{font-family:inherit;cursor:pointer} | ||
| 33 | + a{color:inherit;text-decoration:none} | ||
| 34 | + input,select,textarea{font-family:inherit;font-size:13px} | ||
| 35 | + | ||
| 36 | + /* ======= TOP BAR ======= */ | ||
| 37 | + .topbar{display:flex;align-items:stretch;height:44px;background:var(--topbar);color:var(--topbar-text);position:relative;z-index:30;} | ||
| 38 | + .topbar .logo{width:54px;display:flex;align-items:center;justify-content:center;} | ||
| 39 | + .topbar .logo svg{width:30px;height:30px} | ||
| 40 | + .topbar .nav-btn{display:flex;align-items:center;gap:6px;padding:0 18px;color:#fff;cursor:pointer;font-size:14px;border:none;background:transparent;height:100%;} | ||
| 41 | + .topbar .nav-btn.active{background:var(--primary);} | ||
| 42 | + .topbar .nav-btn:hover{background:#33363d} | ||
| 43 | + .topbar .nav-btn.active:hover{background:var(--primary-strong)} | ||
| 44 | + .topbar .tabs{display:flex;align-items:stretch;flex:1;} | ||
| 45 | + .topbar .tab{display:flex;align-items:center;gap:8px;padding:0 18px;cursor:pointer;color:#cfd2d8;font-size:14px;height:100%;} | ||
| 46 | + .topbar .tab .ic{opacity:.85} | ||
| 47 | + .topbar .tab.active{color:var(--link)} | ||
| 48 | + .topbar .tab .close{margin-left:6px;width:14px;height:14px;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;font-size:11px;color:#9aa0a8} | ||
| 49 | + .topbar .tab .close:hover{background:#3a3d44;color:#fff} | ||
| 50 | + .topbar .right{display:flex;align-items:center;gap:18px;padding-right:14px;} | ||
| 51 | + .topbar .right .ic{width:18px;height:18px;opacity:.9;cursor:pointer} | ||
| 52 | + .topbar .user{display:flex;align-items:center;gap:6px;font-size:14px} | ||
| 53 | + .topbar .more{font-size:18px;letter-spacing:2px;cursor:pointer;padding:0 4px} | ||
| 54 | + | ||
| 55 | + /* ======= APP LAYOUT ======= */ | ||
| 56 | + .app{height:100vh;display:flex;flex-direction:column;overflow:hidden} | ||
| 57 | + .stage{flex:1;position:relative;overflow:hidden;background:var(--bg)} | ||
| 58 | + .screen{position:absolute;inset:0;display:none;overflow:auto} | ||
| 59 | + .screen.active{display:block} | ||
| 60 | + | ||
| 61 | + /* ======= MAIN / DASHBOARD ======= */ | ||
| 62 | + .main-wrap{display:grid;grid-template-columns:1fr 280px;gap:10px;padding:10px;min-height:100%;} | ||
| 63 | + .panel{background:var(--panel);border:1px solid var(--border);border-radius:2px} | ||
| 64 | + .kpi-head{padding:14px 18px;display:flex;align-items:center;gap:24px;flex-wrap:wrap;} | ||
| 65 | + .kpi-head .title{font-size:15px;color:#222;font-weight:500;margin-right:6px} | ||
| 66 | + .kpi-head .stat{color:var(--text-soft)} | ||
| 67 | + .kpi-head .stat b{color:var(--danger);font-weight:500;margin-left:6px;font-size:14px} | ||
| 68 | + .kpi-head .stat.blue b{color:var(--link)} | ||
| 69 | + .kpi-head .sep{color:#cdd0d6} | ||
| 70 | + .kpi-head .ai-btn{margin-left:auto;background:var(--primary);color:#fff;border:none;padding:7px 14px;border-radius:2px;display:inline-flex;align-items:center;gap:6px;font-size:13px;} | ||
| 71 | + .kpi-head .ai-btn:hover{background:var(--primary-strong)} | ||
| 72 | + | ||
| 73 | + .kpi-body{display:grid;grid-template-columns:200px 90px 1fr 1fr 90px 90px 130px;border-top:1px solid var(--border)} | ||
| 74 | + .kpi-body > div{border-right:1px solid var(--border);border-bottom:1px solid var(--border);padding:10px 12px;font-size:13px;min-height:38px;display:flex;align-items:center} | ||
| 75 | + .kpi-body > div:nth-last-child(-n+7){border-bottom:none} | ||
| 76 | + .kpi-body > div:last-child{border-right:none} | ||
| 77 | + .kpi-body .h{background:var(--header-bg);font-weight:500;color:#222;padding:9px 12px} | ||
| 78 | + .kpi-body .row-alt{background:var(--row-alt)} | ||
| 79 | + .kpi-body .link{color:var(--link);cursor:pointer} | ||
| 80 | + .kpi-body .link:hover{text-decoration:underline} | ||
| 81 | + .kpi-body .num-red{color:var(--danger);font-weight:600;justify-content:center} | ||
| 82 | + .kpi-body .num-zero{color:var(--danger);font-weight:600;justify-content:center} | ||
| 83 | + .kpi-body .num{justify-content:center} | ||
| 84 | + .kpi-body .center{justify-content:center} | ||
| 85 | + | ||
| 86 | + .nav-tree{padding:6px 0} | ||
| 87 | + .nav-tree .group{padding:8px 14px;color:#444;font-size:13px;display:flex;align-items:center;gap:6px;cursor:pointer} | ||
| 88 | + .nav-tree .group .arrow{display:inline-block;width:0;height:0;border-left:4px solid #888;border-top:4px solid transparent;border-bottom:4px solid transparent;transform:rotate(90deg);margin-right:2px} | ||
| 89 | + .nav-tree .group .ico{color:#e0b96a} | ||
| 90 | + .nav-tree .item{padding:6px 14px 6px 36px;display:flex;align-items:center;gap:8px;color:#3a3a3a;cursor:pointer;font-size:13px} | ||
| 91 | + .nav-tree .item:hover{background:#eef3fb} | ||
| 92 | + .nav-tree .item.active{background:#d8eaff;color:#1166cc} | ||
| 93 | + .nav-tree .item .ico{color:#e0b96a} | ||
| 94 | + | ||
| 95 | + .three-col{display:grid;grid-template-columns:280px 1fr;height:100%;} | ||
| 96 | + .three-col .left-nav{background:var(--panel);border:1px solid var(--border);overflow:auto} | ||
| 97 | + .three-col .center{display:flex;flex-direction:column;gap:10px;min-width:0} | ||
| 98 | + | ||
| 99 | + .common-ops{padding:14px 18px} | ||
| 100 | + .common-ops .h{font-size:14px;color:#222;margin-bottom:14px;font-weight:500} | ||
| 101 | + .common-ops a{display:block;color:var(--link);padding:8px 0;font-size:13px;border-bottom:1px dashed transparent} | ||
| 102 | + .common-ops a:hover{text-decoration:underline} | ||
| 103 | + | ||
| 104 | + /* table sub-process column */ | ||
| 105 | + .subproc{writing-mode:vertical-rl;text-orientation:upright;color:#222;font-weight:500;justify-content:center;min-width:24px;} | ||
| 106 | + .subproc.estimate{ background:transparent } | ||
| 107 | + | ||
| 108 | + footer.foot{ | ||
| 109 | + background:#f3f4f6;border-top:1px solid var(--border);padding:10px 14px;text-align:center;color:#666;font-size:12px; | ||
| 110 | + } | ||
| 111 | + footer.foot .pipe{margin:0 8px;color:#bbb} | ||
| 112 | + footer.foot .police{display:inline-flex;align-items:center;gap:4px;margin-left:6px} | ||
| 113 | + footer.foot .police svg{width:14px;height:14px} | ||
| 114 | + | ||
| 115 | + /* ======= NAV OVERLAY ======= */ | ||
| 116 | + #nav-overlay{position:absolute;inset:0;background:#2b3137;display:none;z-index:20;color:#cfd3da;} | ||
| 117 | + #nav-overlay.show{display:flex} | ||
| 118 | + #nav-overlay .side{width:200px;background:#2b3137;padding:8px 0;border-right:1px solid #1e2226} | ||
| 119 | + #nav-overlay .side .si{display:flex;align-items:center;gap:10px;padding:11px 18px;font-size:14px;color:#d3d6db;cursor:pointer} | ||
| 120 | + #nav-overlay .side .si:hover{background:#34393f} | ||
| 121 | + #nav-overlay .side .si.active{color:var(--link);background:#34393f} | ||
| 122 | + #nav-overlay .side .si svg{width:16px;height:16px;opacity:.85} | ||
| 123 | + #nav-overlay .grid{flex:1;padding:30px 40px;display:grid;grid-template-columns:repeat(7,1fr);gap:30px 40px;align-content:start} | ||
| 124 | + #nav-overlay .col h3{font-size:15px;color:#e8eaee;font-weight:500;margin:0 0 18px;border-bottom:1px solid #4a4f57;padding-bottom:10px} | ||
| 125 | + #nav-overlay .col a{display:flex;align-items:center;gap:6px;padding:7px 0;color:#cfd3da;font-size:14px;cursor:pointer} | ||
| 126 | + #nav-overlay .col a:hover{color:#fff} | ||
| 127 | + #nav-overlay .col a .star{color:#f3b526} | ||
| 128 | + | ||
| 129 | + /* ======= USER LIST ======= */ | ||
| 130 | + .toolbar{background:var(--toolbar-bg);color:#fff;display:flex;align-items:center;gap:6px;padding:0 8px;height:38px} | ||
| 131 | + .toolbar .tb-btn{display:inline-flex;align-items:center;gap:6px;padding:6px 12px;color:#e6e7ea;cursor:pointer;font-size:13px;border-radius:2px} | ||
| 132 | + .toolbar .tb-btn:hover{background:#3a3d44} | ||
| 133 | + .toolbar .tb-btn .ic{opacity:.9} | ||
| 134 | + .toolbar .spacer{flex:1} | ||
| 135 | + .toolbar .gear{padding:6px 8px;cursor:pointer;color:#cfd2d8} | ||
| 136 | + | ||
| 137 | + .filterbar{display:flex;align-items:center;gap:8px;padding:10px 12px;background:var(--panel);border-bottom:1px solid var(--border)} | ||
| 138 | + .filterbar select, .filterbar input{height:30px;border:1px solid #d5d8de;border-radius:2px;padding:0 28px 0 10px;background:#fff;min-width:140px;appearance:none; | ||
| 139 | + background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 10 10'><path d='M2 3l3 4 3-4z' fill='%23888'/></svg>"); | ||
| 140 | + background-repeat:no-repeat;background-position:right 8px center} | ||
| 141 | + .filterbar input{background-image:none;padding-right:10px} | ||
| 142 | + .filterbar .down{width:34px;height:30px;background:#dfe5ee;border:1px solid #d5d8de;display:flex;align-items:center;justify-content:center;border-radius:2px;cursor:pointer;color:#3776c8} | ||
| 143 | + .filterbar .btn{height:30px;padding:0 14px;border-radius:2px;border:1px solid var(--primary);background:var(--primary);color:#fff;display:inline-flex;align-items:center;gap:5px;font-size:13px;cursor:pointer} | ||
| 144 | + .filterbar .btn.ghost{background:#fff;color:#444;border-color:#cfd3da} | ||
| 145 | + .filterbar .btn:hover{filter:brightness(1.05)} | ||
| 146 | + | ||
| 147 | + .grid-table{width:100%;border-collapse:collapse;background:#fff;font-size:13px;} | ||
| 148 | + .grid-table th, .grid-table td{border:1px solid var(--border);padding:7px 10px;text-align:left;white-space:nowrap} | ||
| 149 | + .grid-table thead th{background:var(--header-bg);font-weight:500;color:#333;position:sticky;top:0;z-index:1} | ||
| 150 | + .grid-table thead th .h-flex{display:flex;align-items:center;gap:6px;justify-content:space-between} | ||
| 151 | + .grid-table thead th .h-flex .ic{display:flex;gap:2px;color:#aaa} | ||
| 152 | + .grid-table tbody tr:nth-child(even){background:var(--row-alt)} | ||
| 153 | + .grid-table tbody tr:hover{background:#eaf3fe} | ||
| 154 | + .grid-table .radio-cell{width:32px;text-align:center} | ||
| 155 | + .radio-dot{width:14px;height:14px;border:1px solid #b8bcc3;border-radius:50%;display:inline-block;vertical-align:middle;background:#fff} | ||
| 156 | + .grid-table input.cb{margin:0} | ||
| 157 | + | ||
| 158 | + .pager{display:flex;align-items:center;gap:8px;padding:10px 14px;background:#fff;border-top:1px solid var(--border);justify-content:flex-end;font-size:13px;color:#555} | ||
| 159 | + .pager .pgbtn{width:28px;height:28px;border:1px solid #d5d8de;background:#fff;border-radius:2px;display:inline-flex;align-items:center;justify-content:center;cursor:pointer;color:#666} | ||
| 160 | + .pager .pgcur{width:28px;height:28px;border:1px solid var(--primary);color:var(--primary);display:inline-flex;align-items:center;justify-content:center;border-radius:2px} | ||
| 161 | + .pager select{height:28px;border:1px solid #d5d8de;border-radius:2px;padding:0 8px;background:#fff} | ||
| 162 | + | ||
| 163 | + /* ======= USER DETAIL ======= */ | ||
| 164 | + .form-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:0;background:#fff;padding:10px 14px;border-bottom:1px solid var(--border)} | ||
| 165 | + .form-cell{display:flex;align-items:center;gap:6px;padding:8px 10px;} | ||
| 166 | + .form-cell .lbl{min-width:88px;color:#333;font-size:13px;text-align:right} | ||
| 167 | + .form-cell .lbl.req::before{content:"*";color:var(--label);margin-right:3px} | ||
| 168 | + .form-cell .lbl.req{color:var(--label)} | ||
| 169 | + .form-cell input[type=text], .form-cell .field{ | ||
| 170 | + flex:1;height:28px;border:1px solid #d5d8de;border-radius:2px;padding:0 24px 0 10px;background:var(--field-bg); | ||
| 171 | + appearance:none; min-width:0; | ||
| 172 | + } | ||
| 173 | + .form-cell .field.readonly{background:var(--field-bg-readonly);color:#444;display:flex;align-items:center} | ||
| 174 | + .form-cell .field.with-caret{background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 10 10'><path d='M2 3l3 4 3-4z' fill='%23888'/></svg>");background-repeat:no-repeat;background-position:right 8px center;background-color:var(--field-bg)} | ||
| 175 | + .form-cell .field.with-cal{background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 16 16' fill='none' stroke='%23888' stroke-width='1.4'><rect x='2' y='3' width='12' height='11' rx='1'/><path d='M2 6h12M5 1v3M11 1v3'/></svg>");background-repeat:no-repeat;background-position:right 8px center;background-color:var(--field-bg-readonly)} | ||
| 176 | + .form-cell .cb{width:14px;height:14px;border:1px solid #b8bcc3;background:#fff;display:inline-block} | ||
| 177 | + | ||
| 178 | + .tabs-row{display:flex;background:#fff;border-bottom:1px solid var(--border);padding:0 6px} | ||
| 179 | + .tabs-row .tb{padding:11px 18px;font-size:14px;color:#444;cursor:pointer;border-bottom:2px solid transparent;margin-right:4px} | ||
| 180 | + .tabs-row .tb.active{color:var(--tab-active);border-bottom-color:var(--tab-active)} | ||
| 181 | + | ||
| 182 | + .perm-list{background:#fff} | ||
| 183 | + .perm-row{display:flex;align-items:center;gap:14px;padding:10px 14px;border-bottom:1px solid var(--border);font-size:13px;color:#333} | ||
| 184 | + .perm-row.head{background:var(--header-bg);font-weight:500;color:#222} | ||
| 185 | + .perm-row .cb{width:14px;height:14px;border:1px solid #b8bcc3;background:#fff;display:inline-block;flex-shrink:0} | ||
| 186 | + .perm-row.head .ic{margin-left:auto;color:#aaa} | ||
| 187 | + | ||
| 188 | + /* ======= LOGIN ======= */ | ||
| 189 | + .login-wrap{position:absolute;inset:0;background:#eaedf2;display:flex;flex-direction:column} | ||
| 190 | + .login-head{display:flex;align-items:center;gap:12px;padding:18px 36px;background:#eaedf2} | ||
| 191 | + .login-head .lg{width:42px;height:42px;display:flex;align-items:center;justify-content:center} | ||
| 192 | + .login-head .name{font-size:24px;font-weight:700;color:#e0a020;letter-spacing:2px} | ||
| 193 | + .login-head .sub{color:#444;font-size:14px;margin-left:6px} | ||
| 194 | + .login-hero{flex:1;position:relative;background: | ||
| 195 | + radial-gradient(ellipse at center, #1a4ea0 0%, #0a1d44 60%, #050d20 100%); | ||
| 196 | + overflow:hidden} | ||
| 197 | + .login-hero::before{ | ||
| 198 | + content:"";position:absolute;inset:0; | ||
| 199 | + background-image: | ||
| 200 | + linear-gradient(rgba(80,160,255,.18) 1px, transparent 1px), | ||
| 201 | + linear-gradient(90deg, rgba(80,160,255,.18) 1px, transparent 1px); | ||
| 202 | + background-size:80px 80px; | ||
| 203 | + transform:perspective(800px) rotateX(55deg) translateY(20%); | ||
| 204 | + transform-origin:center; | ||
| 205 | + opacity:.55; | ||
| 206 | + } | ||
| 207 | + .login-hero::after{ | ||
| 208 | + content:"";position:absolute;inset:0; | ||
| 209 | + background: | ||
| 210 | + radial-gradient(ellipse 800px 300px at 50% 50%, rgba(140,200,255,.35), transparent 60%), | ||
| 211 | + radial-gradient(circle 200px at 30% 40%, rgba(255,255,255,.15), transparent 70%), | ||
| 212 | + radial-gradient(circle 160px at 70% 60%, rgba(255,255,255,.12), transparent 70%); | ||
| 213 | + } | ||
| 214 | + .login-text{position:absolute;left:8%;top:35%;color:#fff;z-index:2} | ||
| 215 | + .login-text .en{font-size:30px;font-weight:300;letter-spacing:1px;color:#cfe1ff;margin-bottom:6px} | ||
| 216 | + .login-text .zh{font-size:54px;font-weight:700;color:#fff;letter-spacing:4px;margin-bottom:4px} | ||
| 217 | + .login-text .erp{font-size:90px;font-weight:800;color:#fff;letter-spacing:8px;line-height:.9} | ||
| 218 | + .login-card{position:absolute;right:8%;top:50%;transform:translateY(-50%);background:#fff;width:380px;padding:36px 32px;border-radius:2px;box-shadow:0 12px 40px rgba(0,0,0,.3);z-index:3} | ||
| 219 | + .login-card h3{margin:0 0 22px;font-size:18px;color:#333;font-weight:500} | ||
| 220 | + .login-card .lf{display:flex;align-items:center;border:1px solid #e1e4e8;border-radius:2px;height:42px;margin-bottom:14px;background:#fff;} | ||
| 221 | + .login-card .lf .ic{width:42px;display:flex;align-items:center;justify-content:center;color:#888} | ||
| 222 | + .login-card .lf .div{width:1px;height:20px;background:#e1e4e8} | ||
| 223 | + .login-card .lf input{flex:1;border:none;outline:none;height:100%;padding:0 12px;background:transparent} | ||
| 224 | + .login-card .lf select{flex:1;border:none;outline:none;height:100%;padding:0 12px;background:transparent;appearance:none} | ||
| 225 | + .login-card .lf.dropdown{position:relative} | ||
| 226 | + .login-card .lf.dropdown::after{content:"";position:absolute;right:14px;top:50%;width:0;height:0;border-left:5px solid transparent;border-right:5px solid transparent;border-top:5px solid #888;transform:translateY(-50%)} | ||
| 227 | + .login-card .lf.dropdown.open .opt{display:block} | ||
| 228 | + .login-card .lf .opt{display:none;position:absolute;left:-1px;right:-1px;top:42px;background:#fff;border:1px solid #e1e4e8;border-top:none;z-index:5} | ||
| 229 | + .login-card .lf .opt .o{padding:10px 14px;color:#333;cursor:pointer;background:#eef5ff} | ||
| 230 | + .login-card .lf .opt .o:hover{background:#dde9fb} | ||
| 231 | + .login-card .submit{width:100%;height:42px;background:var(--primary);color:#fff;border:none;border-radius:2px;font-size:15px;letter-spacing:8px;cursor:pointer;margin-top:6px} | ||
| 232 | + .login-card .submit:hover{background:var(--primary-strong)} | ||
| 233 | + .login-foot{background:#eaedf2;text-align:center;padding:14px 8px;color:#666;font-size:12px;border-top:1px solid #d8dce2} | ||
| 234 | + | ||
| 235 | + /* misc */ | ||
| 236 | + .ic{display:inline-flex;align-items:center;justify-content:center} | ||
| 237 | + .star{color:#f3b526} | ||
| 238 | + .scrollable-y{overflow-y:auto} | ||
| 239 | + .table-shell{background:#fff;flex:1;overflow:auto;border:1px solid var(--border);border-top:none} | ||
| 240 | + | ||
| 241 | + /* Antler logo color */ | ||
| 242 | + .lg-antler{color:#0e1216} | ||
| 243 | +</style> | ||
| 244 | +</head> | ||
| 245 | +<body> | ||
| 246 | +<div class="app"> | ||
| 247 | + | ||
| 248 | + <!-- ======= TOP BAR ======= --> | ||
| 249 | + <div class="topbar" id="topbar"> | ||
| 250 | + <div class="logo" data-go="main" title="主页"> | ||
| 251 | + <!-- antler/deer logo --> | ||
| 252 | + <svg viewBox="0 0 64 64" fill="currentColor" class="lg-antler"> | ||
| 253 | + <path d="M14 10c2 4 1 8-1 11 3-1 7 0 10 3 1-4 4-7 8-7-3 3-4 7-3 11l4 1c-1 3 0 6 3 8-3 0-6 1-8 4-1-3-4-5-8-5 2-3 2-7 0-10-3 1-7 0-10-3 3 0 5-2 6-5l-1-8z"/> | ||
| 254 | + <path d="M48 14c-2 3-2 6-1 9-2-2-5-2-8-1 1 3 1 6-1 9 3 0 5 2 6 5 1-3 4-5 7-5-2-3-2-6 0-9 2 1 5 1 7-1-2 0-4-1-5-3-1-2-3-4-5-4z"/> | ||
| 255 | + <path d="M28 38c2 3 5 5 9 5 1 4 4 7 8 8-3 2-5 5-5 9-3-2-7-3-11-2 1-3 1-7-1-10-3 0-6-1-8-4 3-1 6-3 8-6z"/> | ||
| 256 | + </svg> | ||
| 257 | + </div> | ||
| 258 | + | ||
| 259 | + <div class="tabs" id="tabs"> | ||
| 260 | + <button class="nav-btn" id="nav-toggle"> | ||
| 261 | + <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="4" y1="7" x2="20" y2="7"/><line x1="4" y1="12" x2="20" y2="12"/><line x1="4" y1="17" x2="20" y2="17"/></svg> | ||
| 262 | + 全部导航 | ||
| 263 | + </button> | ||
| 264 | + <div class="tab" data-go="main"> | ||
| 265 | + <span class="ic"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M3 11l9-8 9 8"/><path d="M5 10v10h14V10"/></svg></span> | ||
| 266 | + 主页 | ||
| 267 | + </div> | ||
| 268 | + <div class="tab" id="tab-userlist" data-go="userlist" style="display:none"> | ||
| 269 | + 用户列表 <span class="close" data-close="userlist">✕</span> | ||
| 270 | + </div> | ||
| 271 | + <div class="tab" id="tab-userdetail" data-go="userdetail" style="display:none"> | ||
| 272 | + 用户信息单据 <span class="close" data-close="userdetail">✕</span> | ||
| 273 | + </div> | ||
| 274 | + </div> | ||
| 275 | + | ||
| 276 | + <div class="right"> | ||
| 277 | + <span class="ic" title="搜索"> | ||
| 278 | + <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="7"/><line x1="21" y1="21" x2="16.5" y2="16.5"/></svg> | ||
| 279 | + </span> | ||
| 280 | + <span class="ic" title="通知"> | ||
| 281 | + <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M6 8a6 6 0 0 1 12 0v5l1.5 3h-15L6 13z"/><path d="M10 19a2 2 0 0 0 4 0"/></svg> | ||
| 282 | + </span> | ||
| 283 | + <div class="user"> | ||
| 284 | + <span class="ic"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="5" width="18" height="14" rx="1"/><path d="M3 9h18"/></svg></span> | ||
| 285 | + 朱子纯(超级管理员) <span style="font-size:10px">▾</span> | ||
| 286 | + </div> | ||
| 287 | + <span class="more">⋯</span> | ||
| 288 | + </div> | ||
| 289 | + </div> | ||
| 290 | + | ||
| 291 | + <!-- ======= STAGE ======= --> | ||
| 292 | + <div class="stage" id="stage"> | ||
| 293 | + | ||
| 294 | + <!-- NAV OVERLAY --> | ||
| 295 | + <div id="nav-overlay"> | ||
| 296 | + <div class="side" id="nav-side"></div> | ||
| 297 | + <div class="grid" id="nav-grid"></div> | ||
| 298 | + </div> | ||
| 299 | + | ||
| 300 | + <!-- ===== MAIN ===== --> | ||
| 301 | + <section class="screen active" id="screen-main"> | ||
| 302 | + <div class="main-wrap"> | ||
| 303 | + <div style="display:flex;flex-direction:column;gap:10px;min-height:0"> | ||
| 304 | + <!-- KPI head bar --> | ||
| 305 | + <div class="panel kpi-head"> | ||
| 306 | + <span class="title">KPI监控</span> | ||
| 307 | + <span class="stat">今日未处理:<b>37428</b></span> | ||
| 308 | + <span class="sep">|</span> | ||
| 309 | + <span class="stat blue">未清总数:<b>56433</b></span> | ||
| 310 | + <button class="ai-btn"> | ||
| 311 | + <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 2l2 5 5 2-5 2-2 5-2-5-5-2 5-2z"/></svg> | ||
| 312 | + 小ai同学,请帮我安排今日工作 | ||
| 313 | + </button> | ||
| 314 | + </div> | ||
| 315 | + | ||
| 316 | + <!-- KPI body grid --> | ||
| 317 | + <div class="three-col"> | ||
| 318 | + <!-- Left tree --> | ||
| 319 | + <div class="left-nav nav-tree"> | ||
| 320 | + <div class="group"><span class="arrow"></span><span class="ico">📁</span>按角色</div> | ||
| 321 | + <div class="item active"><span class="ico">📄</span>所有部门 (37428)</div> | ||
| 322 | + <div class="item"><span class="ico">📄</span>核价人员 (17)</div> | ||
| 323 | + <div class="item"><span class="ico">📄</span>销售人员 (0)</div> | ||
| 324 | + <div class="item"><span class="ico">📄</span>印前 (11)</div> | ||
| 325 | + <div class="item"><span class="ico">📄</span>客服部 (30127)</div> | ||
| 326 | + <div class="item"><span class="ico">📄</span>技术研发部 (47)</div> | ||
| 327 | + <div class="item"><span class="ico">📄</span>车间主管 (316)</div> | ||
| 328 | + <div class="item"><span class="ico">📄</span>工艺部 (6)</div> | ||
| 329 | + <div class="item"><span class="ico">📄</span>物控部 (728)</div> | ||
| 330 | + <div class="item"><span class="ico">📄</span>生产计划部 (225)</div> | ||
| 331 | + <div class="item"><span class="ico">📄</span>版房 (120)</div> | ||
| 332 | + <div class="item"><span class="ico">📄</span>生产车间 (596)</div> | ||
| 333 | + <div class="item"><span class="ico">📄</span>工艺技术部 (0)</div> | ||
| 334 | + <div class="item"><span class="ico">📄</span>品质管理部 (589)</div> | ||
| 335 | + <div class="item"><span class="ico">📄</span>储运部 (3496)</div> | ||
| 336 | + <div class="item"><span class="ico">📄</span>通用 (0)</div> | ||
| 337 | + <div class="item"><span class="ico">📄</span>外发组 (867)</div> | ||
| 338 | + <div class="item"><span class="ico">📄</span>材料仓管 (0)</div> | ||
| 339 | + <div class="item"><span class="ico">📄</span>机修组 (42)</div> | ||
| 340 | + <div class="item"><span class="ico">📄</span>应收 (30)</div> | ||
| 341 | + <div class="item"><span class="ico">📄</span>出纳 (211)</div> | ||
| 342 | + <div class="item"><span class="ico">📄</span>应付 (0)</div> | ||
| 343 | + <div class="item"><span class="ico">📄</span>客服 (0)</div> | ||
| 344 | + <div class="group"><span class="arrow"></span><span class="ico">📁</span>按流程</div> | ||
| 345 | + <div class="item"><span class="ico">📄</span>估价管理流程 (17)</div> | ||
| 346 | + <div class="item"><span class="ico">📄</span>设计制作流程 (11)</div> | ||
| 347 | + <div class="item"><span class="ico">📄</span>新品研发流程 (11)</div> | ||
| 348 | + <div class="item"><span class="ico">📄</span>材料测试流程 (51)</div> | ||
| 349 | + <div class="item"><span class="ico">📄</span>订单下达流程 (30118)</div> | ||
| 350 | + </div> | ||
| 351 | + <div class="center"> | ||
| 352 | + <div class="panel" style="overflow:auto"> | ||
| 353 | + <div class="kpi-body" id="kpi-body"></div> | ||
| 354 | + </div> | ||
| 355 | + </div> | ||
| 356 | + </div> | ||
| 357 | + </div> | ||
| 358 | + | ||
| 359 | + <!-- right side common ops --> | ||
| 360 | + <div class="panel common-ops" style="height:fit-content"> | ||
| 361 | + <div class="h">常用操作</div> | ||
| 362 | + <a data-go="userlist">用户列表</a> | ||
| 363 | + <a>系统功能模块设置</a> | ||
| 364 | + </div> | ||
| 365 | + </div> | ||
| 366 | + | ||
| 367 | + <footer class="foot"> | ||
| 368 | + <span style="vertical-align:middle">🛠</span> | ||
| 369 | + ©Copyright Antler Software <span class="pipe">|</span> 印刷智慧工厂 <span class="pipe">|</span> 印刷MES <span class="pipe">|</span> 印刷ERP <span class="pipe">|</span> 印刷电商平台 <span class="pipe">|</span> 文件智能处理 <span class="pipe">|</span> 印前自动化 <span class="pipe">|</span> 400-880-6237 | ||
| 370 | + <span class="police"> | ||
| 371 | + <svg viewBox="0 0 24 24" fill="#3a6cb6"><path d="M12 2l9 4v6c0 5-4 9-9 10-5-1-9-5-9-10V6z"/></svg> | ||
| 372 | + 沪ICP备14034791号-1 | ||
| 373 | + </span> | ||
| 374 | + </footer> | ||
| 375 | + </section> | ||
| 376 | + | ||
| 377 | + <!-- ===== USER LIST ===== --> | ||
| 378 | + <section class="screen" id="screen-userlist"> | ||
| 379 | + <div class="toolbar"> | ||
| 380 | + <span class="tb-btn"><svg class="ic" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 12a9 9 0 1 1-3-6.7"/><path d="M21 4v5h-5"/></svg>刷新</span> | ||
| 381 | + <span class="tb-btn" id="btn-add" data-add-user="1"><svg class="ic" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="9"/><path d="M12 8v8M8 12h8"/></svg>新增</span> | ||
| 382 | + <span class="tb-btn"><svg class="ic" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M4 4h12l4 4v12H4z"/><path d="M16 4v4h4"/><path d="M8 12h8M8 16h8"/></svg>导出Excel</span> | ||
| 383 | + <span class="spacer"></span> | ||
| 384 | + <span class="gear">⚙</span> | ||
| 385 | + </div> | ||
| 386 | + <div class="filterbar"> | ||
| 387 | + <select><option>全部用户</option></select> | ||
| 388 | + <select><option>用户名</option></select> | ||
| 389 | + <select><option>包含</option></select> | ||
| 390 | + <input type="text" /> | ||
| 391 | + <span class="down">▾</span> | ||
| 392 | + <button class="btn"><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="7"/><line x1="21" y1="21" x2="16.5" y2="16.5"/></svg>搜索</button> | ||
| 393 | + <button class="btn ghost">⊗ 清空</button> | ||
| 394 | + </div> | ||
| 395 | + <div class="table-shell"> | ||
| 396 | + <table class="grid-table" id="user-table"> | ||
| 397 | + <thead> | ||
| 398 | + <tr> | ||
| 399 | + <th style="width:36px"></th> | ||
| 400 | + <th style="width:60px">序号</th> | ||
| 401 | + <th>用户名 <span style="color:#aaa">⇅ ⌕</span></th> | ||
| 402 | + <th>员工名 <span style="color:#aaa">⇅ ⌕</span></th> | ||
| 403 | + <th>用户号 <span style="color:#aaa">⇅ ⌕</span></th> | ||
| 404 | + <th>部门 <span style="color:#aaa">⇅ ⌕</span></th> | ||
| 405 | + <th>用户类型 <span style="color:#aaa">⇅ ⌕</span></th> | ||
| 406 | + <th>语言 <span style="color:#aaa">⇅ ⌕</span></th> | ||
| 407 | + <th>作 <span style="color:#aaa">⇅ ⌕</span></th> | ||
| 408 | + <th>登录日期</th> | ||
| 409 | + <th>制单人 <span style="color:#aaa">⇅ ⌕</span></th> | ||
| 410 | + <th>制单日期</th> | ||
| 411 | + </tr> | ||
| 412 | + </thead> | ||
| 413 | + <tbody id="user-tbody"></tbody> | ||
| 414 | + </table> | ||
| 415 | + </div> | ||
| 416 | + <div class="pager"> | ||
| 417 | + <span>当前显示 共37个单据 共37条记录</span> | ||
| 418 | + <span class="pgbtn">‹</span> | ||
| 419 | + <span class="pgcur">1</span> | ||
| 420 | + <span class="pgbtn">›</span> | ||
| 421 | + <select><option>10000 条/页</option></select> | ||
| 422 | + </div> | ||
| 423 | + </section> | ||
| 424 | + | ||
| 425 | + <!-- ===== USER DETAIL ===== --> | ||
| 426 | + <section class="screen" id="screen-userdetail"> | ||
| 427 | + <div class="toolbar"> | ||
| 428 | + <span class="tb-btn"><svg class="ic" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="9"/><path d="M12 8v8M8 12h8"/></svg>新增</span> | ||
| 429 | + <span class="tb-btn"><svg class="ic" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M14 3l7 7-11 11H3v-7z"/></svg>修改</span> | ||
| 430 | + <span class="tb-btn"><svg class="ic" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="9"/><path d="M8 8l8 8M16 8l-8 8"/></svg>删除</span> | ||
| 431 | + <span class="tb-btn"><svg class="ic" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M5 4h11l3 3v13H5z"/><rect x="8" y="4" width="8" height="5"/></svg>保存</span> | ||
| 432 | + <span class="tb-btn"><svg class="ic" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="9"/><path d="M9 9l6 6M15 9l-6 6"/></svg>取消</span> | ||
| 433 | + <span class="tb-btn"><svg class="ic" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="3" width="7" height="7"/><rect x="14" y="3" width="7" height="7"/><rect x="3" y="14" width="7" height="7"/><rect x="14" y="14" width="7" height="7"/></svg>功能</span> | ||
| 434 | + <span class="tb-btn">作废</span> | ||
| 435 | + <span class="tb-btn">重置密码</span> | ||
| 436 | + <span class="tb-btn">取消作废</span> | ||
| 437 | + <span class="spacer"></span> | ||
| 438 | + <span class="gear">⚙</span> | ||
| 439 | + </div> | ||
| 440 | + | ||
| 441 | + <div class="form-grid"> | ||
| 442 | + <div class="form-cell"><span class="lbl">创建时间:</span><div class="field with-cal readonly" id="f-ctime">2023-10-26 17:02:01</div></div> | ||
| 443 | + <div class="form-cell"><span class="lbl">制单人:</span><div class="field readonly" id="f-creator">超级管理员</div></div> | ||
| 444 | + <div class="form-cell"><span class="lbl req">员工名:</span><div class="field with-caret" id="f-empname">管广飞</div></div> | ||
| 445 | + | ||
| 446 | + <div class="form-cell"><span class="lbl req">用户名:</span><input type="text" id="f-username" value="管广飞"/></div> | ||
| 447 | + <div class="form-cell"><span class="lbl req">类型:</span><div class="field with-caret" id="f-type">超级管理员</div></div> | ||
| 448 | + <div class="form-cell"><span class="lbl req">语言:</span><div class="field with-caret" id="f-lang">英文</div></div> | ||
| 449 | + | ||
| 450 | + <div class="form-cell"><span class="lbl req">用户号:</span><input type="text" id="f-userno" value="ggf"/></div> | ||
| 451 | + <div class="form-cell"></div> | ||
| 452 | + <div class="form-cell"><span class="lbl">单据修改权限:</span><span class="cb"></span></div> | ||
| 453 | + </div> | ||
| 454 | + | ||
| 455 | + <div class="tabs-row"> | ||
| 456 | + <div class="tb active">权限组</div> | ||
| 457 | + <div class="tb">客户查看权限</div> | ||
| 458 | + <div class="tb">供应商查看权限</div> | ||
| 459 | + <div class="tb">人员查看权限</div> | ||
| 460 | + <div class="tb">工序查看权限</div> | ||
| 461 | + <div class="tb">司机查看权限</div> | ||
| 462 | + </div> | ||
| 463 | + | ||
| 464 | + <div class="perm-list" id="perm-list"> | ||
| 465 | + <div class="perm-row head"><span class="cb"></span><span>权限分类</span><span class="ic" style="margin-left:auto;color:#aaa">⇅</span></div> | ||
| 466 | + </div> | ||
| 467 | + </section> | ||
| 468 | + | ||
| 469 | + <!-- ===== LOGIN ===== --> | ||
| 470 | + <section class="screen" id="screen-login"> | ||
| 471 | + <div class="login-wrap"> | ||
| 472 | + <div class="login-head"> | ||
| 473 | + <span class="lg"> | ||
| 474 | + <svg viewBox="0 0 64 64" width="42" height="42" fill="#0e1216"> | ||
| 475 | + <path d="M14 10c2 4 1 8-1 11 3-1 7 0 10 3 1-4 4-7 8-7-3 3-4 7-3 11l4 1c-1 3 0 6 3 8-3 0-6 1-8 4-1-3-4-5-8-5 2-3 2-7 0-10-3 1-7 0-10-3 3 0 5-2 6-5l-1-8z"/> | ||
| 476 | + <path d="M48 14c-2 3-2 6-1 9-2-2-5-2-8-1 1 3 1 6-1 9 3 0 5 2 6 5 1-3 4-5 7-5-2-3-2-6 0-9 2 1 5 1 7-1-2 0-4-1-5-3-1-2-3-4-5-4z"/> | ||
| 477 | + <path d="M28 38c2 3 5 5 9 5 1 4 4 7 8 8-3 2-5 5-5 9-3-2-7-3-11-2 1-3 1-7-1-10-3 0-6-1-8-4 3-1 6-3 8-6z"/> | ||
| 478 | + </svg> | ||
| 479 | + </span> | ||
| 480 | + <span class="name">Antler ERP</span> | ||
| 481 | + <span class="sub">欢迎登录EBC平台</span> | ||
| 482 | + </div> | ||
| 483 | + <div class="login-hero"> | ||
| 484 | + <div class="login-text"> | ||
| 485 | + <div class="en">Enterprise Business Capability</div> | ||
| 486 | + <div class="zh">企业业务能力平台</div> | ||
| 487 | + <div class="erp">ERP</div> | ||
| 488 | + </div> | ||
| 489 | + <div class="login-card"> | ||
| 490 | + <h3>用户登录</h3> | ||
| 491 | + <div class="lf"> | ||
| 492 | + <span class="ic"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="8" r="4"/><path d="M4 21c0-4 4-7 8-7s8 3 8 7"/></svg></span> | ||
| 493 | + <span class="div"></span> | ||
| 494 | + <input type="text" placeholder="请输入你的用户名" /> | ||
| 495 | + </div> | ||
| 496 | + <div class="lf"> | ||
| 497 | + <span class="ic"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="4" y="11" width="16" height="10" rx="1"/><path d="M8 11V7a4 4 0 0 1 8 0v4"/></svg></span> | ||
| 498 | + <span class="div"></span> | ||
| 499 | + <input type="password" placeholder="请输入你的密码" /> | ||
| 500 | + </div> | ||
| 501 | + <div class="lf dropdown" id="ver-drop"> | ||
| 502 | + <input type="text" value="标准版" readonly style="cursor:pointer"/> | ||
| 503 | + <div class="opt"> | ||
| 504 | + <div class="o">标准版</div> | ||
| 505 | + </div> | ||
| 506 | + <div class="opt"> | ||
| 507 | + <div class="o">标准版1</div> | ||
| 508 | + </div> | ||
| 509 | + </div> | ||
| 510 | + <button class="submit" data-go="main">登 录</button> | ||
| 511 | + </div> | ||
| 512 | + </div> | ||
| 513 | + <div class="login-foot"> | ||
| 514 | + 🛠 ©Copyright Antler Software | 印刷智慧工厂 | 印刷MES | 印刷ERP | 印刷电商平台 | 文件智能处理 | 印前自动化 | 400-880-6237 | ||
| 515 | + <span style="display:inline-flex;align-items:center;gap:4px;margin-left:6px"> | ||
| 516 | + <svg width="14" height="14" viewBox="0 0 24 24" fill="#3a6cb6"><path d="M12 2l9 4v6c0 5-4 9-9 10-5-1-9-5-9-10V6z"/></svg> | ||
| 517 | + 沪ICP备14034791号-1 | ||
| 518 | + </span> | ||
| 519 | + </div> | ||
| 520 | + </div> | ||
| 521 | + </section> | ||
| 522 | + | ||
| 523 | + </div> | ||
| 524 | +</div> | ||
| 525 | + | ||
| 526 | +<script> | ||
| 527 | +/* ============ KPI ROWS ============ */ | ||
| 528 | +const kpiHeader = ['导航类型','角色','KPI待处理事项(当前行双击进入)','KPI内容描述及处理结果(点击蓝色查看明细)','今日未处理','未清总数','子流程']; | ||
| 529 | +const kpiRows = [ | ||
| 530 | + // [role, item, desc, today, total, sub, navType?, rowSpanRole?, rowSpanSub?] | ||
| 531 | + // group 1: 估价管理流程 — 5 rows, role 核价人员 spans 4, 销售人员 1 | ||
| 532 | + {role:'核价人员', item:'01/04【新增】新报价单', desc:'报价单明细', today:'-', total:'-', sub:'估价管理流程', navTypeFirst:true, roleSpan:4, subSpan:5}, | ||
| 533 | + {role:null, item:'02/04 审核后报价单->客户确认价格', desc:'报价单明细', today:'16', total:'16', red:true}, | ||
| 534 | + {role:null, item:'03/04 客户不认可->二次确认', desc:'报价单明细', today:'-', total:'-'}, | ||
| 535 | + {role:null, item:'04/04 报价单->销售订单', desc:'销售订单明细', today:'1', total:'1', red:true}, | ||
| 536 | + {role:'销售人员', item:'04/04 报价单->销售订单(标签)', desc:'销售订单明细(标签)', today:'0', total:'0', red:true}, | ||
| 537 | + // group 2: 设计制作流程 — 印前 (2 rows), span 2 | ||
| 538 | + {role:'印前', item:'1/2 新增设计申请单', desc:'设计申请明细', today:'-', total:'-', sub:'设计制作流程', roleSpan:2, subSpan:2}, | ||
| 539 | + {role:null, item:'2/2 设计申请->设计制作', desc:'根据设计申请单进行设计制作,当日16:00前审核的为今日任务,16:00后(含)顺延至次日', today:'11', total:'11', red:true}, | ||
| 540 | + // group 3: 新品研发流程 — 客服部, 技术研发部, 客服部, 技术研发部 | ||
| 541 | + {role:'客服部', item:'1/1 研发申请->文件制作', desc:'根据研发申请单,制作电子文件,当日16:00前下达的为今日任务,16:00后(含)顺延至次日', today:'0', total:'12', red:true, sub:'新品研发流程', subSpan:5}, | ||
| 542 | + {role:'客服部', item:'1/5 新增研发申请单', desc:'研发申请明细', today:'-', total:'-'}, | ||
| 543 | + {role:'技术研发部', item:'2/5 研发申请>>研发工单', desc:'及时开立研发工单,当日16:00前审核的为今日任务,16:00后(含)顺延至次日', today:'4', total:'4', red:true, roleSpan:2}, | ||
| 544 | + {role:null, item:'3/5 研发工单>>完工处理', desc:'计划人员在交货日期前确认工单完工', today:'7', total:'7', red:true}, | ||
| 545 | + {role:'客服部', item:'4/5 研发工单->客户确认', desc:'工单完工后需在7天内和客户确认样品', today:'-', total:'2703'}, | ||
| 546 | + // 5/5 技术研发部 | ||
| 547 | + {role:'技术研发部', item:'5/5 客户确认->工艺卡', desc:'根据客户已经确认的研发工单,生成产品工艺卡。当日16:00前确认的为今日任务,16:00后(含)顺延至次日', today:'0', total:'1632', red:true, sub:'', subSpan:0}, | ||
| 548 | + // group 4: 材料测试流程 — 车间主管, 技术研发部, 技术研发部 | ||
| 549 | + {role:'车间主管', item:'1/3 工单(测试部门数)->车间反馈', desc:'车间主管在工单完工前对测试材料进行数据反馈', today:'10', total:'115', red:true, sub:'材料测试流程', subSpan:3}, | ||
| 550 | + {role:null, item:'2/3 车间反馈->车间补充(多部门)', desc:'补充新材料测试信息,车间反馈次日16:00前的为当日任务,16:00后(含)顺延一日', today:'8', total:'8', red:true, roleSpan:2}, | ||
| 551 | + {role:'技术研发部', item:'2/3 车间反馈->工程部反馈(单部门)', desc:'工程部对新材料的测试结果进行反馈,车间反馈次日16:00前的为当日任务,16:00后(含)顺延一日', today:'23', total:'23', red:true}, | ||
| 552 | +]; | ||
| 553 | + | ||
| 554 | +/* Render KPI grid via spans simulated with empty cells (CSS grid) */ | ||
| 555 | +(function renderKpi(){ | ||
| 556 | + const host = document.getElementById('kpi-body'); | ||
| 557 | + const heads = ['导航类型','角色','KPI待处理事项(当前行双击进入)','KPI内容描述及处理结果(点击蓝色查看明细)','今日未处理','未清总数','子流程']; | ||
| 558 | + heads.forEach(h => { const d = document.createElement('div'); d.className='h'; d.textContent=h; host.appendChild(d); }); | ||
| 559 | + | ||
| 560 | + // We'll render 7 columns per row. | ||
| 561 | + // Track active rowspans for col 0(navType), 1(role), 6(sub). | ||
| 562 | + // We model by emitting blank cells for spanned positions (visually merge by removing borders). | ||
| 563 | + // Simpler: emit single tall cells via grid-row span. | ||
| 564 | + let r = 2; // CSS row index (1-based) but auto rows after header row = 1 | ||
| 565 | + // Use explicit grid placement | ||
| 566 | + let line = 2; | ||
| 567 | + // First, emit a single big "按角色" cell for col1 spanning all data rows? Original shows rows have nav type only at start. | ||
| 568 | + // We'll emit "按角色" merged across all rows (24 rows in screenshot share 按角色). Use full span. | ||
| 569 | + // Emit nav cell once | ||
| 570 | + const total = kpiRows.length; | ||
| 571 | + const navCell = document.createElement('div'); | ||
| 572 | + navCell.style.gridColumn = '1'; | ||
| 573 | + navCell.style.gridRow = `2 / span ${total}`; | ||
| 574 | + navCell.className = 'center'; | ||
| 575 | + navCell.textContent = '按角色'; | ||
| 576 | + host.appendChild(navCell); | ||
| 577 | + | ||
| 578 | + let curRow = 2; | ||
| 579 | + let i = 0; | ||
| 580 | + while (i < kpiRows.length) { | ||
| 581 | + const row = kpiRows[i]; | ||
| 582 | + const altClass = (i%2===1)?'row-alt':''; | ||
| 583 | + // role | ||
| 584 | + if (row.role) { | ||
| 585 | + const span = row.roleSpan || 1; | ||
| 586 | + const c = document.createElement('div'); | ||
| 587 | + c.style.gridColumn = '2'; | ||
| 588 | + c.style.gridRow = `${curRow} / span ${span}`; | ||
| 589 | + c.className = 'center ' + altClass; | ||
| 590 | + c.textContent = row.role; | ||
| 591 | + host.appendChild(c); | ||
| 592 | + } | ||
| 593 | + // item | ||
| 594 | + const item = document.createElement('div'); | ||
| 595 | + item.style.gridColumn = '3'; | ||
| 596 | + item.style.gridRow = `${curRow}`; | ||
| 597 | + item.className = 'link ' + altClass; | ||
| 598 | + item.textContent = row.item; | ||
| 599 | + host.appendChild(item); | ||
| 600 | + // desc | ||
| 601 | + const desc = document.createElement('div'); | ||
| 602 | + desc.style.gridColumn = '4'; | ||
| 603 | + desc.style.gridRow = `${curRow}`; | ||
| 604 | + desc.className = 'link ' + altClass; | ||
| 605 | + desc.textContent = row.desc; | ||
| 606 | + host.appendChild(desc); | ||
| 607 | + // today | ||
| 608 | + const today = document.createElement('div'); | ||
| 609 | + today.style.gridColumn = '5'; | ||
| 610 | + today.style.gridRow = `${curRow}`; | ||
| 611 | + today.className = 'num ' + (row.red?'num-red':'') + ' ' + altClass; | ||
| 612 | + today.textContent = row.today; | ||
| 613 | + host.appendChild(today); | ||
| 614 | + // total | ||
| 615 | + const tot = document.createElement('div'); | ||
| 616 | + tot.style.gridColumn = '6'; | ||
| 617 | + tot.style.gridRow = `${curRow}`; | ||
| 618 | + tot.className = 'num ' + (row.red?'num-red':'') + ' ' + altClass; | ||
| 619 | + tot.textContent = row.total; | ||
| 620 | + host.appendChild(tot); | ||
| 621 | + // sub | ||
| 622 | + if (row.sub && row.subSpan) { | ||
| 623 | + const c = document.createElement('div'); | ||
| 624 | + c.style.gridColumn = '7'; | ||
| 625 | + c.style.gridRow = `${curRow} / span ${row.subSpan}`; | ||
| 626 | + c.className = 'subproc'; | ||
| 627 | + c.textContent = row.sub; | ||
| 628 | + host.appendChild(c); | ||
| 629 | + } | ||
| 630 | + curRow++; | ||
| 631 | + i++; | ||
| 632 | + } | ||
| 633 | + host.style.gridTemplateRows = `38px repeat(${total}, minmax(38px, auto))`; | ||
| 634 | +})(); | ||
| 635 | + | ||
| 636 | +/* ============ USER TABLE ============ */ | ||
| 637 | +const users = [ | ||
| 638 | + ['管广飞','管广飞','ggf','工艺技术','超级管理员','英文','','2026-02-27 17:48:11','超级管理员','2023-10-26 17:02:01'], | ||
| 639 | + ['李斌','李斌','lib','印前制作','超级管理员','中文','','2026-01-28 16:53:32','超级管理员','2023-10-26 17:02:58'], | ||
| 640 | + ['系统管理员','','admin','','超级管理员','中文','','2026-05-06 12:28:49','超级管理员','2023-10-26 17:05:58'], | ||
| 641 | + ['朱财喜','朱财喜','zhucx','印刷车间','超级管理员','中文','','2026-03-23 10:08:29','超级管理员','2023-11-20 10:29:09'], | ||
| 642 | + ['ljh','ljh','ljh','机修','超级管理员','中文','','2026-05-06 11:14:04','YFZ','2024-10-08 13:48:59'], | ||
| 643 | + ['wx','汪鑫','wx','工艺技术','超级管理员','中文','','2026-03-23 11:57:13','超级管理员','2023-11-22 13:22:35'], | ||
| 644 | + ['钱豹','钱豹','qianb','物控部','超级管理员','中文','','2026-04-28 16:49:04','超级管理员','2023-11-27 15:30:11'], | ||
| 645 | + ['zyf','张寅飞','zyf','印前制作','超级管理员','中文','','2025-09-11 11:42:12','LJH','2024-11-11 15:59:52'], | ||
| 646 | + ['孟威','孟威','mengw','工艺技术','超级管理员','中文','','2026-05-06 13:56:22','系统管理员','2025-06-03 21:26:07'], | ||
| 647 | + ['杭仁萍','杭仁萍','hangrp','跟单','超级管理员','中文','','2026-04-30 14:18:28','孟威','2025-06-05 11:11:56'], | ||
| 648 | + ['李丹','','李丹','','超级管理员','中文','','2026-04-27 13:47:58','杭仁萍','2025-06-11 10:34:29'], | ||
| 649 | + ['王宽明','王宽明','王宽明','印刷车间','超级管理员','中文','','2026-04-25 16:07:38','李丹','2025-06-11 10:40:22'], | ||
| 650 | + ['潘茹','潘茹','潘茹','工艺技术','超级管理员','中文','','2025-06-17 09:04:46','李丹','2025-06-11 10:41:07'], | ||
| 651 | + ['耿广东','耿广东','耿广东','工艺技术','超级管理员','中文','','2025-07-04 14:40:02','李丹','2025-06-11 10:41:37'], | ||
| 652 | + ['yut','余涛','yut','印刷车间','超级管理员','中文','','2026-04-03 18:39:34','杭仁萍','2025-06-17 14:32:49'], | ||
| 653 | + ['lzj','廖赵军','lzj','财务部','超级管理员','中文','','','杭仁萍','2025-06-26 10:57:28'], | ||
| 654 | + ['caojy','caojy','caojy','物控部','超级管理员','中文','','2026-02-02 13:58:14','李明青','2025-07-28 13:59:21'], | ||
| 655 | + ['陈淑贤','陈淑贤','csx','品质管理部','超级管理员','中文','','2026-04-24 15:05:52','csx','2025-07-29 13:26:58'], | ||
| 656 | + ['张红英','张红英','zhy','模烫车间','超级管理员','中文','','2025-12-24 16:24:52','系统管理员','2025-08-18 09:34:47'], | ||
| 657 | + ['lzy','吕政彦','吕政彦','总经理办公室','超级管理员','中文','','2026-04-16 08:54:24','杭仁萍','2025-08-21 11:16:12'], | ||
| 658 | + ['陈鑫涛','陈鑫涛','cxt','品质管理部','超级管理员','中文','','2026-03-23 10:12:47','陈淑贤','2025-09-01 11:22:00'], | ||
| 659 | + ['陆鑫','陆鑫','luxin','工艺技术','超级管理员','中文','','2026-05-05 17:56:03','张震','2025-09-04 11:48:44'], | ||
| 660 | + ['陆鑫-储运部…','陆鑫','ZY0006','工艺技术','普通用户','中文','','2025-11-19 09:11:27','陆鑫','2025-09-05 11:28:37'], | ||
| 661 | + ['朱咸兵','朱咸兵','zhuxb','工艺技术','超级管理员','中文','','2026-04-27 13:40:15','钱豹','2025-09-08 15:00:29'], | ||
| 662 | + ['孟臻晟','孟臻晟','mengzs','装订车间','超级管理员','中文','','2026-05-07 09:17:57','系统管理员','2025-09-12 16:24:07'], | ||
| 663 | + ['pengm','彭敏','pengm','计划管理','超级管理员','中文','','2026-05-06 11:28:33','彭敏','2025-10-16 13:30:32'], | ||
| 664 | + ['张伟','张伟','zhangw','印刷车间','超级管理员','中文','','2026-03-15 09:22:14','张伟','2025-10-22 10:12:00'], | ||
| 665 | + ['李娜','李娜','lin','质检部','普通用户','中文','','2026-04-02 14:50:33','李丹','2025-11-04 16:08:21'], | ||
| 666 | + ['王军','王军','wangj','装订车间','超级管理员','中文','','2026-04-15 17:10:55','系统管理员','2025-11-15 09:30:11'], | ||
| 667 | + ['赵敏','赵敏','zhaom','财务部','超级管理员','中文','','2026-05-01 08:45:00','赵敏','2025-12-01 11:00:00'], | ||
| 668 | + ['周强','周强','zhouq','物控部','普通用户','中文','','2026-04-20 10:30:21','钱豹','2025-12-08 14:22:33'], | ||
| 669 | + ['吴丽','吴丽','wul','人事部','超级管理员','中文','','2026-04-25 15:18:09','吴丽','2026-01-05 09:15:42'], | ||
| 670 | + ['郑涛','郑涛','zhengt','工艺技术','超级管理员','中文','','2026-05-02 11:40:58','郑涛','2026-01-18 13:55:27'], | ||
| 671 | + ['冯静','冯静','fengj','客服部','超级管理员','中文','','2026-05-04 16:25:17','冯静','2026-02-02 10:08:14'], | ||
| 672 | + ['孙磊','孙磊','sunl','装订车间','普通用户','中文','','2026-05-05 09:55:36','系统管理员','2026-02-20 15:32:48'], | ||
| 673 | + ['马超','马超','mac','机修','超级管理员','中文','','2026-05-06 14:12:25','LJH','2026-03-08 11:48:09'], | ||
| 674 | + ['朱子纯','朱子纯','zhuzc','总经理办公室','超级管理员','中文','','2026-05-07 13:00:00','超级管理员','2026-03-22 09:00:00'], | ||
| 675 | +]; | ||
| 676 | + | ||
| 677 | +(function renderUsers(){ | ||
| 678 | + const tb = document.getElementById('user-tbody'); | ||
| 679 | + users.forEach((u,i)=>{ | ||
| 680 | + const tr = document.createElement('tr'); | ||
| 681 | + tr.innerHTML = ` | ||
| 682 | + <td class="radio-cell"><span class="radio-dot"></span></td> | ||
| 683 | + <td>${i+1}</td> | ||
| 684 | + <td>${u[0]}</td> | ||
| 685 | + <td>${u[1]}</td> | ||
| 686 | + <td>${u[2]}</td> | ||
| 687 | + <td>${u[3]}</td> | ||
| 688 | + <td>${u[4]}</td> | ||
| 689 | + <td>${u[5]}</td> | ||
| 690 | + <td><input class="cb" type="checkbox"></td> | ||
| 691 | + <td>${u[7]}</td> | ||
| 692 | + <td>${u[8]}</td> | ||
| 693 | + <td>${u[9]}</td> | ||
| 694 | + `; | ||
| 695 | + tr.addEventListener('dblclick', ()=> goTo('userdetail')); | ||
| 696 | + tb.appendChild(tr); | ||
| 697 | + }); | ||
| 698 | +})(); | ||
| 699 | + | ||
| 700 | +/* ============ PERM LIST ============ */ | ||
| 701 | +const perms = ['默认显示(必选)','禁止查看价格','客服跟单','报价组员工','物控部员工','供应链PMC','允许查看订单价格','储运部员工','外部供应商','品质部员工','技术中心员工','机修组员工','生产部计划员工','外发组员工','模烫车间','装订车间','后加工车间','品质部管理','精品车间','人事组','统计组','机修主管','样品开发部员工','设计开发','总经办','审核组','结算组','打样车间','制版组','文控组','行政组','成本组','采购组','OA管理员','开发组','API对接','MES管理员','报表组']; | ||
| 702 | +(function(){ | ||
| 703 | + const host = document.getElementById('perm-list'); | ||
| 704 | + perms.forEach(p=>{ | ||
| 705 | + const r = document.createElement('div'); | ||
| 706 | + r.className = 'perm-row'; | ||
| 707 | + r.innerHTML = `<span class="cb"></span><span>${p}</span>`; | ||
| 708 | + host.appendChild(r); | ||
| 709 | + }); | ||
| 710 | +})(); | ||
| 711 | + | ||
| 712 | +/* ============ NAV OVERLAY ============ */ | ||
| 713 | +const navSide = [ | ||
| 714 | + {ico:'sales', label:'销售管理'}, {ico:'dcs', label:'DCS系统'}, {ico:'prod', label:'产品管理'}, | ||
| 715 | + {ico:'ops', label:'生产运营'}, {ico:'exec', label:'生产执行'}, {ico:'mold', label:'模具管理'}, | ||
| 716 | + {ico:'cart', label:'采购管理'}, {ico:'mat', label:'材料库存'}, {ico:'fg', label:'成品库存'}, | ||
| 717 | + {ico:'out', label:'外协管理'}, {ico:'logi', label:'物流管理'}, {ico:'qa', label:'质量管理'}, | ||
| 718 | + {ico:'fin', label:'财务管理'}, {ico:'cost1', label:'成本管理(专)'}, {ico:'cost2', label:'成本管理'}, | ||
| 719 | + {ico:'eq', label:'设备管理'}, {ico:'hr', label:'人事行政'}, {ico:'oa', label:'OA系统'}, | ||
| 720 | + {ico:'base', label:'基础设置'}, {ico:'sys', label:'系统设置', active:true}, | ||
| 721 | +]; | ||
| 722 | +const sideIco = { | ||
| 723 | + sales:'M3 7l3 10h12l3-10M5 7l1-3h12l1 3M9 21a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm8 0a1 1 0 1 0 0-2 1 1 0 0 0 0 2z', | ||
| 724 | + dcs:'M12 2l9 5-9 5-9-5z M3 12l9 5 9-5 M3 17l9 5 9-5', | ||
| 725 | + prod:'M3 7l9-5 9 5v10l-9 5-9-5z', | ||
| 726 | + ops:'M4 4h6v6H4zM14 4h6v6h-6zM4 14h6v6H4zM14 14h6v6h-6z', | ||
| 727 | + exec:'M5 4h14v16H5z M5 9h14 M9 4v5', | ||
| 728 | + mold:'M4 7h16v10H4z M8 7v10 M16 7v10', | ||
| 729 | + cart:'M5 5h2l3 11h10l2-8H8 M9 20a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm9 0a1 1 0 1 0 0-2 1 1 0 0 0 0 2z', | ||
| 730 | + mat:'M4 21V8l8-5 8 5v13z M9 21v-7h6v7', | ||
| 731 | + fg:'M3 21V9l9-6 9 6v12z', | ||
| 732 | + out:'M12 12c2 0 4-1 4-4s-2-4-4-4-4 1-4 4 2 4 4 4z M4 21c0-4 4-7 8-7s8 3 8 7', | ||
| 733 | + logi:'M3 7h11v9H3z M14 10h5l3 3v3h-8z M7 19a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm10 0a1 1 0 1 0 0-2 1 1 0 0 0 0 2z', | ||
| 734 | + qa:'M12 2l8 4v6c0 5-4 8-8 10-4-2-8-5-8-10V6z M9 12l2 2 4-4', | ||
| 735 | + fin:'M12 2v20 M7 6h10 M7 10h10', | ||
| 736 | + cost1:'M4 20V8 M9 20V4 M14 20v-8 M19 20v-6 M2 20h20', | ||
| 737 | + cost2:'M4 20V8 M9 20V4 M14 20v-8 M19 20v-6 M2 20h20', | ||
| 738 | + eq:'M12 8a4 4 0 1 1 0 8 4 4 0 0 1 0-8z M19 12a7 7 0 0 0-.5-2.5l1.5-1.5-2-2-1.5 1.5A7 7 0 0 0 14 7l-.5-2h-3l-.5 2A7 7 0 0 0 7.5 7.5L6 6 4 8l1.5 1.5A7 7 0 0 0 5 12', | ||
| 739 | + hr:'M9 11a4 4 0 1 0 0-8 4 4 0 0 0 0 8z M2 21c0-4 3-7 7-7s7 3 7 7 M17 11a3 3 0 1 0 0-6 3 3 0 0 0 0 6z M22 21c0-3-2-5-5-5', | ||
| 740 | + oa:'M3 7h18v12H3z M3 11h18 M8 7V4h8v3', | ||
| 741 | + base:'M4 6h16 M4 12h16 M4 18h16 M8 6v12 M14 6v12', | ||
| 742 | + sys:'M12 8a4 4 0 1 1 0 8 4 4 0 0 1 0-8z M19 12a7 7 0 0 0-.5-2.5l1.5-1.5-2-2-1.5 1.5A7 7 0 0 0 14 7l-.5-2h-3l-.5 2A7 7 0 0 0 7.5 7.5L6 6 4 8l1.5 1.5A7 7 0 0 0 5 12', | ||
| 743 | +}; | ||
| 744 | +const navSideHost = document.getElementById('nav-side'); | ||
| 745 | +navSide.forEach(s=>{ | ||
| 746 | + const d = document.createElement('div'); | ||
| 747 | + d.className = 'si' + (s.active?' active':''); | ||
| 748 | + d.innerHTML = `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6"><path d="${sideIco[s.ico]||''}"/></svg>${s.label}`; | ||
| 749 | + navSideHost.appendChild(d); | ||
| 750 | +}); | ||
| 751 | + | ||
| 752 | +const navCols = [ | ||
| 753 | + {title:'期初设置', items:['客户期初','供应商期初','材料期初','产品期初','数据导入','离线导出下载']}, | ||
| 754 | + {title:'用户管理', items:[{label:'用户列表',star:true,go:'userlist'},'系统权限','系统权限稽查表','权限组']}, | ||
| 755 | + {title:'系统参数', items:['系统参数','财务结账','系统常量配置']}, | ||
| 756 | + {title:'计算方案', items:['方案列表','计算参数']}, | ||
| 757 | + {title:'日志', items:['个性化模块','操作日志','异常清除KPI任务表','MYSQL监听器']}, | ||
| 758 | + {title:'开发平台', items:['自定义开发范例',{label:'系统功能模块设置',star:true},'EBC流程清单','功能模块界面设置','增删改存业务处理']}, | ||
| 759 | + {title:'API对接管理', items:['调用第三方接口(TOKEN配置)','调用第三方接口(接口定义)','被第三方调用(生成token)','数据同步','被第三方调用(API定义)']}, | ||
| 760 | +]; | ||
| 761 | +const navGridHost = document.getElementById('nav-grid'); | ||
| 762 | +navCols.forEach(c=>{ | ||
| 763 | + const col = document.createElement('div'); | ||
| 764 | + col.className = 'col'; | ||
| 765 | + let html = `<h3>${c.title}</h3>`; | ||
| 766 | + c.items.forEach(it=>{ | ||
| 767 | + if (typeof it === 'string') html += `<a>${it}</a>`; | ||
| 768 | + else html += `<a data-go="${it.go||''}">${it.label}${it.star?' <span class="star">★</span>':''}</a>`; | ||
| 769 | + }); | ||
| 770 | + col.innerHTML = html; | ||
| 771 | + navGridHost.appendChild(col); | ||
| 772 | +}); | ||
| 773 | + | ||
| 774 | +/* ============ NAV / TABS ============ */ | ||
| 775 | +const screens = ['main','userlist','userdetail','login']; | ||
| 776 | +function goTo(name){ | ||
| 777 | + screens.forEach(s=>document.getElementById('screen-'+s).classList.toggle('active', s===name)); | ||
| 778 | + // hide top bar on login | ||
| 779 | + document.getElementById('topbar').style.display = (name==='login') ? 'none' : 'flex'; | ||
| 780 | + // tabs visibility | ||
| 781 | + document.getElementById('tab-userlist').style.display = (['userlist','userdetail'].includes(name) || tabsOpen.userlist) ? 'flex' : 'none'; | ||
| 782 | + document.getElementById('tab-userdetail').style.display = (name==='userdetail' || tabsOpen.userdetail) ? 'flex' : 'none'; | ||
| 783 | + // tab active states | ||
| 784 | + document.querySelectorAll('.topbar .tab').forEach(t=>t.classList.remove('active')); | ||
| 785 | + if (name==='main') document.querySelectorAll('.topbar .tab')[0]?.classList.add('active'); | ||
| 786 | + if (name==='userlist') document.getElementById('tab-userlist').classList.add('active'); | ||
| 787 | + if (name==='userdetail') document.getElementById('tab-userdetail').classList.add('active'); | ||
| 788 | + // nav button active when on main with overlay; clear otherwise | ||
| 789 | + document.getElementById('nav-overlay').classList.remove('show'); | ||
| 790 | + document.getElementById('nav-toggle').classList.remove('active'); | ||
| 791 | + // close login overlay if leaving | ||
| 792 | +} | ||
| 793 | +const tabsOpen = {userlist:false, userdetail:false}; | ||
| 794 | +function openTab(name){ | ||
| 795 | + if (name==='userlist'){ tabsOpen.userlist = true; } | ||
| 796 | + if (name==='userdetail'){ tabsOpen.userlist = true; tabsOpen.userdetail = true; } | ||
| 797 | + goTo(name); | ||
| 798 | +} | ||
| 799 | + | ||
| 800 | +document.body.addEventListener('click', (e)=>{ | ||
| 801 | + const go = e.target.closest('[data-go]'); | ||
| 802 | + if (go){ | ||
| 803 | + const name = go.dataset.go; | ||
| 804 | + if (!name) return; | ||
| 805 | + if (name==='userlist' || name==='userdetail') openTab(name); | ||
| 806 | + else goTo(name); | ||
| 807 | + return; | ||
| 808 | + } | ||
| 809 | + const close = e.target.closest('[data-close]'); | ||
| 810 | + if (close){ | ||
| 811 | + e.stopPropagation(); | ||
| 812 | + const which = close.dataset.close; | ||
| 813 | + tabsOpen[which] = false; | ||
| 814 | + if (which==='userdetail') goTo('userlist'); | ||
| 815 | + else goTo('main'); | ||
| 816 | + if (which==='userlist'){ tabsOpen.userdetail=false; } | ||
| 817 | + return; | ||
| 818 | + } | ||
| 819 | +}); | ||
| 820 | + | ||
| 821 | +document.getElementById('nav-toggle').addEventListener('click', ()=>{ | ||
| 822 | + const ov = document.getElementById('nav-overlay'); | ||
| 823 | + ov.classList.toggle('show'); | ||
| 824 | + document.getElementById('nav-toggle').classList.toggle('active', ov.classList.contains('show')); | ||
| 825 | +}); | ||
| 826 | + | ||
| 827 | +// new-user mode | ||
| 828 | +function setUserDetailMode(mode){ | ||
| 829 | + const isNew = mode === 'new'; | ||
| 830 | + document.getElementById('f-ctime').textContent = isNew ? '' : '2023-10-26 17:02:01'; | ||
| 831 | + document.getElementById('f-creator').textContent = isNew ? '保存后自动生成' : '超级管理员'; | ||
| 832 | + document.getElementById('f-empname').textContent = isNew ? '' : '管广飞'; | ||
| 833 | + document.getElementById('f-type').textContent = isNew ? '' : '超级管理员'; | ||
| 834 | + document.getElementById('f-lang').textContent = isNew ? '' : '英文'; | ||
| 835 | + document.getElementById('f-username').value = isNew ? '' : '管广飞'; | ||
| 836 | + document.getElementById('f-userno').value = isNew ? '' : 'ggf'; | ||
| 837 | + document.querySelectorAll('#perm-list .perm-row:not(.head) .cb').forEach(cb=>{cb.classList.remove('checked')}); | ||
| 838 | +} | ||
| 839 | +document.querySelector('[data-add-user]')?.addEventListener('click', ()=>{ setUserDetailMode('new'); openTab('userdetail'); }); | ||
| 840 | + | ||
| 841 | +// Default initial screen: login | ||
| 842 | +goTo('login'); | ||
| 843 | + | ||
| 844 | +// version dropdown demo | ||
| 845 | +document.getElementById('ver-drop').addEventListener('click', e=>{ | ||
| 846 | + e.currentTarget.classList.toggle('open'); | ||
| 847 | +}); | ||
| 848 | +</script> | ||
| 849 | +</body> | ||
| 850 | +</html> |