/* v22 part1: DOM dump + header login btn */ (function () { 'use strict'; if (window.__mobV22) return; window.__mobV22 = true; function $(id) { return document.getElementById(id); } var API = 'https://api-gateway.duoweiying.cn'; var GUEST = 'v20_guest'; function logged() { try { return !!localStorage.getItem('user_token') || localStorage.getItem(GUEST) === '1'; } catch (e) { return false; } } /* ---- console 输出当前真实 DOM 结构(供精准修复样式) ---- */ function dumpDOM() { try { var lines = []; function info(el, tag) { if (!el) return; lines.push(tag + ' tag=' + el.tagName + ' id=' + (el.id || '-') + ' cls=' + (el.className && String(el.className).slice(0, 90) || '-')); } info(document.querySelector('.mobile-header'), 'HEADER'); info(document.querySelector('.mobile-header h1'), 'H1'); var fn = $('function-nav'); if (fn) { info(fn, 'FN-NAV'); var b0 = fn.querySelector('button'); if (b0) { info(b0, 'FN-BTN0'); lines.push('FN-BTN0 style=' + (b0.getAttribute('style') || '').slice(0, 160)); } } info($('chat-container'), 'CHAT'); info($('ai-chat-wrapper'), 'WRAP'); var w = $('ai-chat-wrapper'); if (w) { var m = w.querySelector('.message-bubble'); if (m) info(m, 'BUBBLE'); } info($('chat-input'), 'INPUT'); var sb = document.querySelector('button.send-btn, [id*="send"]'); if (sb) { info(sb, 'SEND'); lines.push('SEND style=' + (sb.getAttribute('style') || '').slice(0, 200)); } var nav = document.querySelector('.bottom-nav'); if (nav) { info(nav, 'BNAV'); var nb = nav.querySelectorAll('button'); lines.push('BNAV buttons=' + nb.length); for (var i = 0; i < nb.length && i < 6; i++) info(nb[i], 'NAV' + i); } var loginEl = $('login-form-container'); if (loginEl) lines.push('LOGIN-FORM-C display=' + loginEl.style.display + ' (default css class present)'); lines.push('guest=' + (localStorage.getItem(GUEST) || '0') + ' token=' + (localStorage.getItem('user_token') ? 'yes' : 'no')); lines.forEach(function (l) { console.log('[V22-DOM] ' + l); }); } catch (e) { console.log('[V22-DOM] err ' + e.message); } } window.__mobV22Dump = dumpDOM; /* v22 part2: self login layer + topbar login btn */ /* ---- 自建顶部登录按钮 ---- */ function topLoginBtn() { try { if ($('v22LoginBtn')) return; var bar = document.createElement('div'); bar.style.cssText = 'position:absolute;right:6px;top:50%;transform:translateY(-50%);z-index:5;'; var a = document.createElement('span'); a.id = 'v22LoginBtn'; a.style.cssText = 'font-size:12px;color:#475569;border:1px solid #cbd5e1;border-radius:13px;padding:3px 11px;cursor:pointer;background:#fff;'; a.textContent = '登录'; a.onclick = function () { openLoginLayer(); }; bar.appendChild(a); var hd = document.querySelector('.mobile-header'); if (hd) { hd.style.position = 'relative'; hd.appendChild(bar); } } catch (e) {} } /* ---- 自建登录层(独立 DOM,不依赖任何旧登录 UI) ---- */ function openLoginLayer() { try { if ($('v22Login')) return; var ov = document.createElement('div'); ov.id = 'v22Login'; ov.style.cssText = 'position:fixed;inset:0;z-index:40000;background:rgba(15,23,42,.55);display:flex;align-items:center;justify-content:center;'; ov.innerHTML = '
' + '
多维鹰 · 账号登录' + '×
' + '
登录后余额/订阅/素材/任务与桌面、公众号互通
' + '
' + '' + '
' + '
' + '' + '' + '
' + '' + '
' + '
👀 游客预览(免登录)
'; document.body.appendChild(ov); var X = $('v22X'); if (X) X.onclick = function () { ov.remove(); }; ov.addEventListener('click', function (e) { if (e.target === ov) ov.remove(); }); $('v22TLogin').onclick = function () { showF('login'); }; $('v22TReg').onclick = function () { showF('reg'); }; $('v22Go').onclick = function () { doAuth('login'); }; $('v22RGo').onclick = function () { doAuth('register'); }; $('v22Guest').onclick = function () { ov.remove(); try { localStorage.setItem(GUEST, '1'); } catch (e) {} location.reload(); }; function showF(k) { $('v22LoginForm').style.display = k === 'login' ? 'block' : 'none'; $('v22RegForm').style.display = k === 'reg' ? 'block' : 'none'; $('v22TLogin').style.background = k === 'login' ? '#334155' : '#fff'; $('v22TLogin').style.color = k === 'login' ? '#fff' : '#475569'; $('v22TReg').style.background = k === 'reg' ? '#334155' : '#fff'; $('v22TReg').style.color = k === 'reg' ? '#fff' : '#475569'; } } catch (e) {} } function msg22(t) { var m = $('v22Msg'); if (m) m.textContent = t; } /* v22 part3: auth + boot */ function doAuth(kind) { var u, p, e, agree; if (kind === 'login') { u = ($('v22U') || {}).value || ''; p = ($('v22P') || {}).value || ''; if (!u || !p) { msg22('请输入用户名与密码'); return; } msg22('登录中…'); fetch(API + '/api/auth/login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ username: u, password: p }) }) .then(function (r) { return r.json(); }) .then(function (d) { /* WR-550: 兼容 access_token / data.token,避免登录成功却不落 user_token */ var _tk = (d && (d.token || d.access_token)) || (d && d.data && (d.data.token || d.data.access_token)) || ''; var _u2 = (d && (d.user || d.data)) || {}; if (_tk) { try { localStorage.setItem('user_token', _tk); localStorage.setItem('user_info', JSON.stringify({ id: _u2.id || u, username: _u2.username || _u2.nickname || u })); localStorage.setItem('user_id', _u2.id || u); } catch (e2) {} location.reload(); } else { msg22('登录失败:' + ((d && (d.message || d.detail || d.msg)) || '用户名或密码错误')); } }).catch(function () { msg22('网络错误,请重试'); }); } else { u = ($('v22RU') || {}).value || ''; e = ($('v22RE') || {}).value || ''; p = ($('v22RP') || {}).value || ''; agree = $('v22Agree'); if (!u || !p) { msg22('请填写用户名与密码'); return; } if (p.length < 6) { msg22('密码至少 6 位'); return; } if (agree && !agree.checked) { msg22('请先勾选同意《用户协议与隐私政策》'); return; } msg22('注册中…'); var body = { username: u, password: p }; if (e) body.email = e; fetch(API + '/api/auth/register', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body) }) .then(function (r) { return r.json(); }) .then(function (d) { if (d && (d.user || d.success || d.id)) { msg22('✅ 注册成功,正在自动登录…'); fetch(API + '/api/auth/login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ username: u, password: p }) }) .then(function (r2) { return r2.json(); }) .then(function (d2) { var _tk2 = (d2 && (d2.token || d2.access_token)) || (d2 && d2.data && (d2.data.token || d2.data.access_token)) || ''; var _u3 = (d2 && (d2.user || d2.data)) || {}; if (_tk2) { try { localStorage.setItem('user_token', _tk2); localStorage.setItem('user_info', JSON.stringify({ id: _u3.id || u, username: _u3.username || _u3.nickname || u })); localStorage.setItem('user_id', _u3.id || u); } catch (e3) {} location.reload(); } else { location.reload(); } }).catch(function () { location.reload(); }); } else { msg22('注册失败:' + ((d && d.message) || '用户名可能已存在')); } }).catch(function () { msg22('网络错误,请重试'); }); } } function topUserChip() { try { if ($('v22UserChip')) return; var u = null; try { u = JSON.parse(localStorage.getItem('user_info') || '{}'); } catch (e) {} var nm = (u && (u.nickname || u.username)) || '已登录'; var chip = document.createElement('div'); chip.id = 'v22UserChip'; chip.style.cssText = 'position:absolute;right:6px;top:50%;transform:translateY(-50%);z-index:5;display:flex;align-items:center;gap:5px;font-size:12px;color:#334155;border:1px solid #cbd5e1;border-radius:13px;padding:3px 11px;cursor:pointer;background:#fff;max-width:44%;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;'; chip.innerHTML = '👤' + String(nm).replace(/[<>&"]/g, function (c) { return { '<': '<', '>': '>', '&': '&', '"': '"' }[c]; }) + ''; chip.onclick = function () { try { if (typeof window.switchTab === 'function') window.switchTab('profile'); else if (typeof window.mobGo === 'function') window.mobGo('profile'); } catch (e) {} }; var hd = document.querySelector('.mobile-header'); if (hd) { hd.style.position = 'relative'; hd.appendChild(chip); } } catch (e) {} } function bootV22() { try { dumpDOM(); var lg = logged(); if (!lg) { topLoginBtn(); } else if (localStorage.getItem(GUEST) === '1') { topLoginBtn(); } else { topUserChip(); } console.log('[MobV22] ready token=' + (localStorage.getItem('user_token') ? 'yes' : 'no') + ' guest=' + (localStorage.getItem(GUEST) || '0')); } catch (e) { console.log('[MobV22] boot err ' + e.message); } } window.__mobV22ShowLogin = openLoginLayer; if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', bootV22); else bootV22(); setTimeout(bootV22, 1200); setTimeout(bootV22, 3000); })();