@@ -117,6 +117,11 @@ export class SidebarProvider implements vscode.WebviewViewProvider {
117117 case "getSuggestions" :
118118 await this . _handleGetSuggestions ( msg ) ;
119119 break ;
120+ case "openExternal" :
121+ if ( msg . url && typeof msg . url === 'string' && msg . url . startsWith ( 'https://' ) ) {
122+ vscode . env . openExternal ( vscode . Uri . parse ( msg . url ) ) ;
123+ }
124+ break ;
120125 }
121126 } ) ;
122127
@@ -1624,73 +1629,42 @@ ${commonRules}`;
16241629 .step-num { color: var(--info); min-width: 20px; }
16251630 .step-desc { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
16261631 .step-time { color: var(--info); font-size: 10px; min-width: 36px; text-align: right; }
1627- /* 认证面板 */
1628- .auth-panel {
1629- padding: 16px 12px;
1630- }
1631- .auth-panel h2 {
1632- font-size: 15px; margin: 0 0 12px; text-align: center;
1632+ /* 设置菜单内登录子面板 */
1633+ .sdrop-auth-panel {
1634+ display: none; padding: 8px 12px;
1635+ border-top: 1px solid var(--input-border);
16331636 }
1634- .auth-panel .auth- input {
1637+ .sdrop- auth-panel input {
16351638 width: 100%; box-sizing: border-box;
1636- padding: 7px 10px ; margin-bottom: 8px ;
1639+ padding: 5px 7px ; margin-bottom: 5px ;
16371640 background: var(--input-bg); color: var(--input-fg);
1638- border: 1px solid var(--input-border); border-radius: 4px ;
1639- font-size: 13px ; outline: none;
1641+ border: 1px solid var(--input-border); border-radius: 3px ;
1642+ font-size: 11px ; outline: none;
16401643 }
1641- .auth-panel .auth- input:focus { border-color: var(--btn-bg); }
1642- .auth-panel .auth -btn {
1643- width: 100% ; padding: 8px; margin-top: 4px ;
1644+ .sdrop- auth-panel input:focus { border-color: var(--btn-bg); }
1645+ .sdrop-login -btn {
1646+ flex: 1 ; padding: 5px; font-size: 11px; font-weight: 600 ;
16441647 background: var(--btn-bg); color: var(--btn-fg);
1645- border: none; border-radius: 4px; cursor: pointer;
1646- font-size: 13px; font-weight: 600;
1647- }
1648- .auth-panel .auth-btn:hover { background: var(--btn-hover); }
1649- .auth-panel .auth-toggle {
1650- display: block; text-align: center; margin-top: 12px;
1651- font-size: 12px; color: var(--btn-bg); cursor: pointer;
1652- text-decoration: underline; background: none; border: none;
1653- }
1654- .auth-panel .auth-error {
1655- color: var(--error); font-size: 12px; margin: 6px 0; text-align: center;
1656- display: none;
1657- }
1658- .auth-user-bar {
1659- display: flex; align-items: center; justify-content: space-between;
1660- padding: 6px 12px; font-size: 12px;
1661- border-bottom: 1px solid var(--input-border);
1648+ border: none; border-radius: 3px; cursor: pointer;
1649+ }
1650+ .sdrop-login-btn:hover { background: var(--btn-hover); }
1651+ .sdrop-register-btn {
1652+ padding: 5px 8px; font-size: 11px;
1653+ background: none; color: var(--btn-bg);
1654+ border: 1px solid var(--btn-bg); border-radius: 3px; cursor: pointer;
16621655 }
1663- .auth-user-bar .username { color: var(--success); font-weight: 600; }
1664- .auth-user-bar .logout-btn {
1665- background: none; border: none; color: var(--muted);
1666- cursor: pointer; font-size: 11px; text-decoration: underline;
1656+ .sdrop-register-btn:hover { background: var(--btn-bg); color: var(--btn-fg); }
1657+ .auth-error {
1658+ color: var(--error); font-size: 11px; margin: 0 0 5px; display: none;
1659+ }
1660+ .sdrop-user-row {
1661+ padding: 6px 12px; font-size: 11px;
1662+ border-top: 1px solid var(--input-border);
16671663 }
1668- .auth-user-bar .logout-btn:hover { color: var(--error); }
16691664 </style>
16701665</head>
16711666<body>
1672- <!-- 认证:已登录用户栏 -->
1673- <div id="authUserBar" class="auth-user-bar" style="display:none">
1674- <span>👤 <span class="username" id="authUsername"></span>
1675- <span style="color:var(--muted);font-size:11px" id="authPlan"></span></span>
1676- <span id="authCredits" style="font-size:11px;color:var(--muted);margin-left:4px"></span>
1677- <button class="logout-btn" onclick="doLogout()">退出登录</button>
1678- </div>
1679- <!-- 认证:登录/注册面板 -->
1680- <div id="authPanel" class="auth-panel" style="display:none">
1681- <h2 id="authTitle">登录 TestPilot AI</h2>
1682- <div id="authError" class="auth-error"></div>
1683- <input id="authEmail" class="auth-input" type="text"
1684- placeholder="邮箱" style="display:none" />
1685- <input id="authUser" class="auth-input" type="text"
1686- placeholder="用户名或邮箱" />
1687- <input id="authPass" class="auth-input" type="password"
1688- placeholder="密码" onkeydown="if(event.key==='Enter')doAuth()" />
1689- <button class="auth-btn" onclick="doAuth()">登录</button>
1690- <button class="auth-toggle" onclick="toggleAuthMode()">
1691- 没有账号?注册
1692- </button>
1693- </div>
1667+
16941668 <!-- 引擎状态 -->
16951669 <div class="section">
16961670 <!-- 标题行:引擎字 + 齿轮设置按钮(随页面滚动) -->
@@ -1720,9 +1694,27 @@ ${commonRules}`;
17201694 <span>🔤 字体大小</span>
17211695 <span class="badge-soon">即将推出</span>
17221696 </div>
1723- <div class="sdrop-item disabled">
1724- <span>🔑 账户登录</span>
1725- <span class="badge-soon">即将推出</span>
1697+ <div class="sdrop-divider"></div>
1698+ <div class="sdrop-item" id="settingsAuthRow" onclick="toggleSettingsAuth()">
1699+ <span id="settingsAuthLabel">🔑 账户登录</span>
1700+ <span id="settingsAuthArrow" style="font-size:10px;color:var(--muted)">▾</span>
1701+ </div>
1702+ <div id="settingsAuthPanel" class="sdrop-auth-panel">
1703+ <div id="authError" class="auth-error"></div>
1704+ <input id="authUser" type="text" placeholder="用户名或邮箱" autocomplete="username" />
1705+ <input id="authPass" type="password" placeholder="密码" autocomplete="current-password" onkeydown="if(event.key==='Enter')doAuth()" />
1706+ <div style="display:flex;gap:6px;margin-top:4px">
1707+ <button class="sdrop-login-btn" onclick="doAuth()">登录</button>
1708+ <button class="sdrop-register-btn" onclick="openRegister()">前往注册 ↗</button>
1709+ </div>
1710+ </div>
1711+ <div id="settingsUserRow" class="sdrop-user-row" style="display:none">
1712+ <div style="display:flex;align-items:center;justify-content:space-between">
1713+ <span style="color:var(--success);font-weight:600">👤 <span id="authUsername"></span>
1714+ <span style="color:var(--muted)" id="authPlan"></span></span>
1715+ <button onclick="doLogout()" style="background:none;border:none;color:var(--muted);cursor:pointer;font-size:11px;text-decoration:underline">退出</button>
1716+ </div>
1717+ <div id="authCredits" style="font-size:11px;color:var(--muted);margin-top:2px"></div>
17261718 </div>
17271719 </div>
17281720 </div>
@@ -1928,80 +1920,65 @@ ${commonRules}`;
19281920 <script nonce="${ nonce } ">
19291921 const vscode = acquireVsCodeApi();
19301922
1931- // ── 认证逻辑 ──────────────────────────────
1932- let authMode = 'login'; // 'login' | 'register'
1933- const authPanel = document.getElementById('authPanel');
1934- const authUserBar = document.getElementById('authUserBar');
1935- const authTitle = document.getElementById('authTitle');
1936- const authEmail = document.getElementById('authEmail');
1923+ // ── 认证逻辑(登录UI位于设置菜单内) ──────────────────────────────
19371924 const authUser = document.getElementById('authUser');
19381925 const authPass = document.getElementById('authPass');
19391926 const authError = document.getElementById('authError');
19401927 const authUsername = document.getElementById('authUsername');
19411928 const authPlan = document.getElementById('authPlan');
19421929
19431930 function showAuthError(msg) {
1944- authError.textContent = msg;
1945- authError.style.display = msg ? 'block' : 'none';
1946- }
1947-
1948- function toggleAuthMode() {
1949- authMode = authMode === 'login' ? 'register' : 'login';
1950- if (authMode === 'register') {
1951- authTitle.textContent = '注册 TestPilot AI';
1952- authEmail.style.display = 'block';
1953- authEmail.placeholder = '邮箱';
1954- authUser.placeholder = '用户名';
1955- document.querySelector('.auth-btn').textContent = '注册';
1956- document.querySelector('.auth-toggle').textContent = '已有账号?登录';
1957- } else {
1958- authTitle.textContent = '登录 TestPilot AI';
1959- authEmail.style.display = 'none';
1960- authUser.placeholder = '用户名或邮箱';
1961- document.querySelector('.auth-btn').textContent = '登录';
1962- document.querySelector('.auth-toggle').textContent = '没有账号?注册';
1963- }
1964- showAuthError('');
1931+ if (authError) { authError.textContent = msg; authError.style.display = msg ? 'block' : 'none'; }
1932+ }
1933+
1934+ function toggleSettingsAuth() {
1935+ const panel = document.getElementById('settingsAuthPanel');
1936+ const arrow = document.getElementById('settingsAuthArrow');
1937+ const open = panel && panel.style.display === 'block';
1938+ if (panel) panel.style.display = open ? 'none' : 'block';
1939+ if (arrow) arrow.textContent = open ? '▾' : '▴';
1940+ if (!open) setTimeout(() => authUser && authUser.focus(), 50);
1941+ }
1942+
1943+ function openRegister() {
1944+ vscode.postMessage({ command: 'openExternal', url: 'https://testpilotai.pages.dev/register' });
19651945 }
19661946
19671947 function doAuth() {
19681948 showAuthError('');
1969- if (authMode === 'login') {
1970- const u = authUser.value.trim();
1971- const p = authPass.value;
1972- if (!u || !p) { showAuthError('请填写用户名和密码'); return; }
1973- vscode.postMessage({ command: 'login', emailOrUsername: u, password: p });
1974- } else {
1975- const e = authEmail.value.trim();
1976- const u = authUser.value.trim();
1977- const p = authPass.value;
1978- if (!e || !u || !p) { showAuthError('请填写所有字段'); return; }
1979- if (p.length < 6) { showAuthError('密码至少6位'); return; }
1980- vscode.postMessage({ command: 'register', email: e, username: u, password: p });
1981- }
1949+ const u = authUser.value.trim();
1950+ const p = authPass.value;
1951+ if (!u || !p) { showAuthError('请填写用户名和密码'); return; }
1952+ vscode.postMessage({ command: 'login', emailOrUsername: u, password: p });
19821953 }
19831954
19841955 function doLogout() {
19851956 vscode.postMessage({ command: 'logout' });
19861957 }
19871958
19881959 function setAuthState(loggedIn, user) {
1960+ const authPanel = document.getElementById('settingsAuthPanel');
1961+ const userRow = document.getElementById('settingsUserRow');
1962+ const authLabel = document.getElementById('settingsAuthLabel');
1963+ const authArrow = document.getElementById('settingsAuthArrow');
19891964 if (loggedIn && user) {
1990- authPanel.style.display = 'none';
1991- authUserBar.style.display = 'flex';
1992- authUsername.textContent = user.username || '';
1993- authPlan.textContent = user.plan ? '(' + user.plan + ')' : '';
1994- // 积分显示
1965+ if (authPanel) authPanel.style.display = 'none';
1966+ if (userRow) userRow.style.display = 'block';
1967+ if (authLabel) authLabel.textContent = '👤 ' + (user.username || '');
1968+ if (authArrow) authArrow.style.display = 'none';
1969+ if (authUsername) authUsername.textContent = user.username || '';
1970+ if (authPlan) authPlan.textContent = user.plan ? '(' + user.plan + ')' : '';
19951971 const creditsEl = document.getElementById('authCredits');
19961972 if (creditsEl && user.credits !== undefined) {
19971973 const low = user.credits < 10;
19981974 creditsEl.textContent = '💰 ' + user.credits + '分';
19991975 creditsEl.style.color = low ? 'var(--error)' : 'var(--muted)';
2000- creditsEl.title = '剩余积分:' + user.credits + '(每10步消耗 1 积分)';
20011976 }
20021977 } else {
2003- authPanel.style.display = 'block';
2004- authUserBar.style.display = 'none';
1978+ if (authPanel) authPanel.style.display = 'none';
1979+ if (userRow) userRow.style.display = 'none';
1980+ if (authLabel) authLabel.textContent = '🔑 账户登录';
1981+ if (authArrow) { authArrow.textContent = '▾'; authArrow.style.display = ''; }
20051982 }
20061983 }
20071984
0 commit comments