diff --git a/qimingclaw/crates/agent-electron-client/package.json b/qimingclaw/crates/agent-electron-client/package.json index 7e9ba2c3..046a00a9 100644 --- a/qimingclaw/crates/agent-electron-client/package.json +++ b/qimingclaw/crates/agent-electron-client/package.json @@ -1,7 +1,7 @@ { "name": "@qiming-ai/qimingclaw", "version": "0.9.7", - "description": "启明数字员工", + "description": "陇电数字员工", "main": "dist/main/main.js", "author": "Qiming Team", "license": "MIT", @@ -128,7 +128,7 @@ }, "build": { "appId": "com.qiming.qimingclaw", - "productName": "启明数字员工", + "productName": "陇电数字员工", "afterSign": "scripts/build/after-sign.js", "electronLanguages": [ "en", @@ -297,8 +297,8 @@ "hardenedRuntime": true, "extendInfo": { "CFBundleIdentifier": "com.qiming.agent", - "CFBundleName": "启明数字员工", - "CFBundleDisplayName": "启明数字员工", + "CFBundleName": "陇电数字员工", + "CFBundleDisplayName": "陇电数字员工", "NSDesktopFolderUsageDescription": "需要访问桌面文件夹以支持文件操作", "NSDocumentsFolderUsageDescription": "需要访问文档文件夹以支持文件操作", "NSDownloadsFolderUsageDescription": "需要访问下载文件夹以支持文件操作" diff --git a/qimingclaw/crates/agent-electron-client/public/128x128.png b/qimingclaw/crates/agent-electron-client/public/128x128.png index 18a3a7ff..f5e6493f 100644 Binary files a/qimingclaw/crates/agent-electron-client/public/128x128.png and b/qimingclaw/crates/agent-electron-client/public/128x128.png differ diff --git a/qimingclaw/crates/agent-electron-client/public/128x128@2x.png b/qimingclaw/crates/agent-electron-client/public/128x128@2x.png index 7e1e3346..8190688e 100644 Binary files a/qimingclaw/crates/agent-electron-client/public/128x128@2x.png and b/qimingclaw/crates/agent-electron-client/public/128x128@2x.png differ diff --git a/qimingclaw/crates/agent-electron-client/public/32x32.png b/qimingclaw/crates/agent-electron-client/public/32x32.png index 79330a2e..822b9cae 100644 Binary files a/qimingclaw/crates/agent-electron-client/public/32x32.png and b/qimingclaw/crates/agent-electron-client/public/32x32.png differ diff --git a/qimingclaw/crates/agent-electron-client/public/64x64.png b/qimingclaw/crates/agent-electron-client/public/64x64.png index e91ce863..d692052b 100644 Binary files a/qimingclaw/crates/agent-electron-client/public/64x64.png and b/qimingclaw/crates/agent-electron-client/public/64x64.png differ diff --git a/qimingclaw/crates/agent-electron-client/public/icon-dock.png b/qimingclaw/crates/agent-electron-client/public/icon-dock.png index 1cfe6f49..0bf5f9f0 100644 Binary files a/qimingclaw/crates/agent-electron-client/public/icon-dock.png and b/qimingclaw/crates/agent-electron-client/public/icon-dock.png differ diff --git a/qimingclaw/crates/agent-electron-client/public/icon.icns b/qimingclaw/crates/agent-electron-client/public/icon.icns index 3ba8d8b0..d55903ec 100644 Binary files a/qimingclaw/crates/agent-electron-client/public/icon.icns and b/qimingclaw/crates/agent-electron-client/public/icon.icns differ diff --git a/qimingclaw/crates/agent-electron-client/public/icon.ico b/qimingclaw/crates/agent-electron-client/public/icon.ico index 0a39930d..f9479484 100644 Binary files a/qimingclaw/crates/agent-electron-client/public/icon.ico and b/qimingclaw/crates/agent-electron-client/public/icon.ico differ diff --git a/qimingclaw/crates/agent-electron-client/public/icon.png b/qimingclaw/crates/agent-electron-client/public/icon.png index 723b3967..1ea0031a 100644 Binary files a/qimingclaw/crates/agent-electron-client/public/icon.png and b/qimingclaw/crates/agent-electron-client/public/icon.png differ diff --git a/qimingclaw/crates/agent-electron-client/src/renderer/App.tsx b/qimingclaw/crates/agent-electron-client/src/renderer/App.tsx index c1aacc0e..b2fb83fa 100644 --- a/qimingclaw/crates/agent-electron-client/src/renderer/App.tsx +++ b/qimingclaw/crates/agent-electron-client/src/renderer/App.tsx @@ -39,6 +39,7 @@ import { syncConfigToServer, normalizeServerHost, loginAndRegister, + isLoggedIn as checkIsLoggedIn, } from "./services/core/auth"; import { APP_DISPLAY_NAME, @@ -49,6 +50,7 @@ import type { QuickInitConfig } from "@shared/types/quickInit"; import type { UpdateState } from "@shared/types/updateTypes"; import { t, getCurrentLang } from "./services/core/i18n"; import SetupWizard from "./components/setup/SetupWizard"; +import LoginPage from "./components/setup/LoginPage"; import SetupDependencies from "./components/setup/SetupDependencies"; import ClientPage from "./components/pages/ClientPage"; import SettingsPage from "./components/pages/SettingsPage"; @@ -187,6 +189,9 @@ function App() { // 初始化向导状态 // ============================================ const [isSetupComplete, setIsSetupComplete] = useState(null); + const [isLoggedIn, setIsLoggedIn] = useState(null); + const [loginStep1Config, setLoginStep1Config] = + useState(DEFAULT_STEP1_CONFIG); const setupJustCompleted = useRef(false); // 内存变量:标记服务是否由登录流程启动(不持久化) const loginStartedRef = useRef(false); @@ -392,6 +397,10 @@ function App() { const checkSetup = async () => { try { const completed = await setupService.isSetupCompleted(); + const step1 = await setupService.getStep1Config(); + setLoginStep1Config(step1); + const loggedIn = await checkIsLoggedIn(); + setIsLoggedIn(loggedIn); // 每次启动优先读取 quick init 配置 if (completed) { @@ -411,6 +420,7 @@ function App() { } catch (error) { log.error("Failed to check setup status:", error); setIsSetupComplete(true); + setIsLoggedIn(false); } }; checkSetup(); @@ -445,6 +455,8 @@ function App() { // ============================================ const handleAuthChange = useCallback(async () => { const user = await authService.getAuthUser(); + const loggedIn = await checkIsLoggedIn(); + setIsLoggedIn(loggedIn); if (user) { setUsername( user.displayName || user.username || t("Claw.App.defaultUsername"), @@ -459,6 +471,29 @@ function App() { loginStartedRef.current = true; }, []); + const ensureDefaultLoginConfig = useCallback(async () => { + const currentConfig = await setupService.getStep1Config(); + const nextConfig: Step1Config = { + ...DEFAULT_STEP1_CONFIG, + ...currentConfig, + serverHost: currentConfig.serverHost || DEFAULT_STEP1_CONFIG.serverHost, + workspaceDir: + currentConfig.workspaceDir || DEFAULT_STEP1_CONFIG.workspaceDir, + }; + await setupService.saveStep1Config(nextConfig); + setLoginStep1Config(nextConfig); + return nextConfig; + }, []); + + const handleFullscreenLoginSuccess = useCallback(async () => { + await setupService.completeStep2(); + await setupService.completeSetup(); + setupJustCompleted.current = true; + setIsSetupComplete(true); + await handleAuthChange(); + setAuthRefreshTrigger((v) => v + 1); + }, [handleAuthChange]); + // ============================================ // 主界面下必需依赖检查:仅当存在「未安装」或「错误」时进入依赖安装 // 版本以当前真实安装为准,outdated 不触发(用户可在依赖 Tab 手动升级) @@ -1106,7 +1141,8 @@ function App() { // ============================================ if ( isSetupComplete === null || - (isSetupComplete && needsRequiredDepsReinstall === null) + isLoggedIn === null || + (isLoggedIn && isSetupComplete && needsRequiredDepsReinstall === null) ) { return ( @@ -1120,6 +1156,20 @@ function App() { ); } + if (!isLoggedIn) { + return ( + + + + + + ); + } + // ============================================ // 渲染:初始化向导 // ============================================ diff --git a/qimingclaw/crates/agent-electron-client/src/renderer/components/setup/LoginPage.module.css b/qimingclaw/crates/agent-electron-client/src/renderer/components/setup/LoginPage.module.css new file mode 100644 index 00000000..cb1f9b06 --- /dev/null +++ b/qimingclaw/crates/agent-electron-client/src/renderer/components/setup/LoginPage.module.css @@ -0,0 +1,306 @@ +.page { + min-height: 100vh; + width: 100%; + display: grid; + grid-template-columns: minmax(360px, 36.1vw) 1fr; + overflow: hidden; + background: #f4f4f1; + color: #171412; +} + +.brandPanel { + min-height: 100vh; + display: flex; + align-items: center; + justify-content: center; + background: #1a1714; + color: #ffffff; +} + +.brandContent { + width: 280px; + margin-top: 10px; + text-align: center; +} + +.brandIcon { + position: relative; + width: 72px; + height: 72px; + margin: 0 auto 24px; + border-radius: 16px; + background: linear-gradient(135deg, #00a960 0%, #007d73 100%); +} + +.brandIconHead { + position: absolute; + top: 25px; + left: 32px; + width: 8px; + height: 8px; + border: 2px solid #ffffff; + border-radius: 50%; +} + +.brandIconBody { + position: absolute; + top: 38px; + left: 24px; + width: 24px; + height: 18px; + border: 2px solid #ffffff; + border-bottom: 0; + border-radius: 14px 14px 0 0; +} + +.brandTitle { + margin-top: 0; + color: #ffffff; + font-size: 29px; + line-height: 40px; + font-weight: 700; + letter-spacing: 0; +} + +.brandSubtitle { + margin-top: 20px; + color: rgba(255, 255, 255, 0.55); + font-size: 14px; + line-height: 20px; + letter-spacing: 8px; + text-indent: 8px; +} + +.brandSlogan { + margin-top: 24px; + color: rgba(255, 255, 255, 0.74); + font-size: 15px; + line-height: 22px; + letter-spacing: 0; +} + +.brandCopyright { + margin-top: 24px; + color: rgba(255, 255, 255, 0.38); + font-size: 12px; + line-height: 18px; + letter-spacing: 0; +} + +.loginPanel { + min-height: 100vh; + display: flex; + align-items: center; + justify-content: center; + padding: 48px; +} + +.card { + position: relative; + width: 420px; + height: 636px; + display: flex; + flex-direction: column; + background: #ffffff; + border: 1px solid #ededeb; + border-radius: 16px; + box-shadow: 0 18px 40px rgba(26, 23, 20, 0.08); + padding: 46px 48px 46px; +} + +.header { + margin-bottom: 24px; +} + +.title { + margin: 0; + color: #171412; + font-size: 28px; + line-height: 40px; + font-weight: 700; + letter-spacing: 0; +} + +.subtitle { + margin: 20px 0 0; + color: #8c8883; + font-size: 14px; + line-height: 20px; + letter-spacing: 0; +} + +.form { + display: flex; + flex-direction: column; + gap: 22px; +} + +.field { + display: flex; + flex-direction: column; + gap: 8px; +} + +.label { + color: #171412; + font-size: 14px; + line-height: 20px; + letter-spacing: 0; +} + +.input, +.input:global(.ant-input-affix-wrapper) { + width: 100%; +} + +.input:global(.ant-input-affix-wrapper) { + height: 48px; + padding: 0 13px; + border: 1px solid #d7d3ce; + border-radius: 8px; + background: #fdfdfb; + box-shadow: none; +} + +.input:global(.ant-input-affix-wrapper) :global(.ant-input) { + height: 46px; + color: #171412; + background: transparent; + font-size: 14px; + line-height: 46px; +} + +.input:global(.ant-input-affix-wrapper) :global(.ant-input-prefix) { + margin-inline-end: 13px; + color: #8c8883; + font-size: 16px; +} + +.input:global(.ant-input-affix-wrapper) :global(.ant-input-suffix) { + color: #8c8883; + font-size: 15px; +} + +.input:global(.ant-input-affix-wrapper) :global(.ant-input-clear-icon) { + color: #c8c5bf; + font-size: 12px; +} + +.input:global(.ant-input-affix-wrapper) :global(.ant-input::placeholder), +.input:global(.ant-input-affix-wrapper) + :global(.ant-input-password input::placeholder) { + color: #b7b3ad; + font-size: 14px; +} + +.input:global(.ant-input-affix-wrapper-focused), +.input:global(.ant-input-affix-wrapper:hover) { + border-color: #00846d; + box-shadow: none; +} + +.error { + height: 0; + margin-top: -16px; + color: #dc2626; + font-size: 12px; + line-height: 16px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.loginButton { + width: 100%; + height: 48px; + margin-top: 2px; + border: 0; + border-radius: 8px; + background: linear-gradient(90deg, #00a455 0%, #007d73 100%); + color: #ffffff; + font-size: 16px; + font-weight: 600; + letter-spacing: 0; + box-shadow: 0 9px 16px rgba(0, 160, 88, 0.24); +} + +.loginButton:hover, +.loginButton:focus { + background: linear-gradient(90deg, #00ae5d 0%, #00887c 100%) !important; + color: #ffffff !important; +} + +.loginButton:active { + background: linear-gradient(90deg, #00964e 0%, #006e66 100%) !important; +} + +.hint { + width: 100%; + margin: 24px 0 0; + color: #006f68; + font-size: 14px; + line-height: 20px; + font-weight: 600; + letter-spacing: 0; + display: inline-flex; + align-items: center; + justify-content: center; + gap: 7px; +} + +.hintIcon { + width: 11px; + height: 11px; + border: 1.5px solid currentColor; + border-radius: 2px; +} + +.hintArrow { + font-size: 18px; + line-height: 16px; +} + +.divider { + width: 100%; + height: 1px; + margin-top: 25px; + background: #e7e1dc; +} + +.footer { + display: flex; + align-items: center; + justify-content: space-between; + gap: 16px; + margin-top: 25px; + color: #aaa5a0; + font-size: 12px; + line-height: 18px; +} + +@media (max-width: 900px) { + .page { + grid-template-columns: 1fr; + } + + .brandPanel { + display: none; + } + + .loginPanel { + padding: 24px; + } +} + +@media (max-height: 720px), (max-width: 520px) { + .loginPanel { + align-items: flex-start; + overflow: auto; + } + + .card { + width: min(420px, calc(100vw - 48px)); + height: auto; + min-height: 636px; + } +} diff --git a/qimingclaw/crates/agent-electron-client/src/renderer/components/setup/LoginPage.tsx b/qimingclaw/crates/agent-electron-client/src/renderer/components/setup/LoginPage.tsx new file mode 100644 index 00000000..5940a6f8 --- /dev/null +++ b/qimingclaw/crates/agent-electron-client/src/renderer/components/setup/LoginPage.tsx @@ -0,0 +1,185 @@ +import React, { useEffect, useMemo, useState } from "react"; +import { Button, Input, message } from "antd"; +import { + GlobalOutlined, + LockOutlined, + UserOutlined, +} from "@ant-design/icons"; +import type { Step1Config } from "../../services/core/setup"; +import { + getAuthErrorMessage, + loginAndRegister, +} from "../../services/core/auth"; +import { t } from "../../services/core/i18n"; +import styles from "./LoginPage.module.css"; + +interface LoginPageProps { + step1Config: Step1Config; + initialUsername?: string; + onLoginStart?: () => Promise; + onLoginSuccess: () => Promise; +} + +function LoginPage({ + step1Config, + initialUsername = "", + onLoginStart, + onLoginSuccess, +}: LoginPageProps) { + const [domain, setDomain] = useState(step1Config.serverHost || ""); + const [username, setUsername] = useState(initialUsername); + const [password, setPassword] = useState(""); + const [loading, setLoading] = useState(false); + const [error, setError] = useState(""); + const [retryCooldown, setRetryCooldown] = useState(0); + + useEffect(() => { + setDomain(step1Config.serverHost || ""); + }, [step1Config.serverHost]); + + useEffect(() => { + setUsername(initialUsername); + }, [initialUsername]); + + useEffect(() => { + if (retryCooldown <= 0) return; + const timer = window.setInterval(() => { + setRetryCooldown((prev) => Math.max(0, prev - 1)); + }, 1000); + return () => window.clearInterval(timer); + }, [retryCooldown]); + + const loginButtonText = useMemo(() => { + if (retryCooldown > 0) { + return t("Claw.Setup.login.pleaseWait", { seconds: retryCooldown }); + } + return t("Claw.Setup.login.loginButton"); + }, [retryCooldown]); + + const handleLogin = async () => { + const normalizedDomain = domain.trim(); + const normalizedUsername = username.trim(); + if (!normalizedUsername || !password) { + message.warning(t("Claw.Setup.login.accountAndCodeRequired")); + return; + } + if (!normalizedDomain) { + message.warning(t("Claw.Setup.login.domainRequired")); + return; + } + + setLoading(true); + setError(""); + try { + await onLoginStart?.(); + await loginAndRegister(normalizedUsername, password, { + suppressToast: true, + domain: normalizedDomain, + }); + await onLoginSuccess(); + } catch (loginError: any) { + const errorMessage = getAuthErrorMessage(loginError); + message.error(errorMessage); + setError(errorMessage); + setPassword(""); + setRetryCooldown(3); + } finally { + setLoading(false); + } + }; + + return ( +
+ + +
+
+
+

欢迎登录

+

请输入您的认证信息以继续

+
+ +
+ + + + + + +
{error}
+ + +
+ +
+ + 统一权限登录 + +
+ +
+ +
+ 需要帮助? + v2.0.1 +
+
+
+
+ ); +} + +export default LoginPage; diff --git a/qimingclaw/crates/agent-electron-client/src/renderer/components/setup/SetupWizard.tsx b/qimingclaw/crates/agent-electron-client/src/renderer/components/setup/SetupWizard.tsx index ebda4213..b21d240f 100644 --- a/qimingclaw/crates/agent-electron-client/src/renderer/components/setup/SetupWizard.tsx +++ b/qimingclaw/crates/agent-electron-client/src/renderer/components/setup/SetupWizard.tsx @@ -33,10 +33,7 @@ import { SettingOutlined, UserOutlined, CheckCircleOutlined, - RobotOutlined, FolderOpenOutlined, - LockOutlined, - GlobalOutlined, } from "@ant-design/icons"; import { setupService, @@ -46,9 +43,7 @@ import { import { loginAndRegister, normalizeServerHost, - isLoggedIn as checkIsLoggedIn, getCurrentAuth, - getAuthErrorMessage, logout, } from "../../services/core/auth"; import { AUTH_KEYS } from "@shared/constants"; @@ -56,6 +51,7 @@ import type { QuickInitConfig } from "@shared/types/quickInit"; import SetupDependencies, { type MockDependenciesApi, } from "./SetupDependencies"; +import LoginPage from "./LoginPage"; const { Text } = Typography; @@ -94,19 +90,15 @@ function SetupWizard({ const [dependenciesReady, setDependenciesReady] = useState( null, ); - const [currentStep, setCurrentStep] = useState(1); + const [currentStep, setCurrentStep] = useState(2); const [loading, setLoading] = useState(true); const [step1Config, setStep1Config] = useState(DEFAULT_STEP1_CONFIG); const [username, setUsername] = useState(""); - const [password, setPassword] = useState(""); const [completed, setCompleted] = useState(false); const [domain, setDomain] = useState(""); - const [loginLoading, setLoginLoading] = useState(false); - const [loginError, setLoginError] = useState(""); - const [retryCooldown, setRetryCooldown] = useState(0); const [isAlreadyLoggedIn, setIsAlreadyLoggedIn] = useState(false); - const [checkingAuth, setCheckingAuth] = useState(false); + const [checkingAuth, setCheckingAuth] = useState(true); const [quickIniting, setQuickIniting] = useState(false); const quickInitAttempted = useRef(false); @@ -117,14 +109,14 @@ function SetupWizard({ if (skipDependencyCheck) { setDependenciesReady(true); const state = await setupService.getSetupState(); - if (state.completed) { - setCompleted(true); - onCompleteRef.current(); - } else { - setCurrentStep(state.step1Completed ? 2 : 1); - } const config = await setupService.getStep1Config(); setStep1Config(config); + if (state.completed) { + setCompleted(true); + onComplete(); + } else { + setCurrentStep(2); + } setLoading(false); return; } @@ -173,7 +165,7 @@ function SetupWizard({ ); } } - setCurrentStep(state.step1Completed ? 2 : 1); + setCurrentStep(2); } } else { // 有依赖缺失,进入安装流程 @@ -203,6 +195,7 @@ function SetupWizard({ try { // 1. 保存 step1 配置 const step1: Step1Config = { + ...DEFAULT_STEP1_CONFIG, serverHost: normalizeServerHost(config.serverHost), agentPort: config.agentPort, fileServerPort: config.fileServerPort, @@ -247,9 +240,7 @@ function SetupWizard({ error, ); setQuickIniting(false); - // step1 可能已保存,从 step1 或 step2 继续 - const state = await setupService.getSetupState(); - setCurrentStep(state.step1Completed ? 2 : 1); + setCurrentStep(2); } }, [onComplete], @@ -272,9 +263,23 @@ function SetupWizard({ } } - setCurrentStep(1); + setCurrentStep(2); }, [performQuickInit]); + const ensureDefaultStep1Config = useCallback(async () => { + const currentConfig = await setupService.getStep1Config(); + const nextConfig: Step1Config = { + ...DEFAULT_STEP1_CONFIG, + ...currentConfig, + serverHost: currentConfig.serverHost || DEFAULT_STEP1_CONFIG.serverHost, + workspaceDir: + currentConfig.workspaceDir || DEFAULT_STEP1_CONFIG.workspaceDir, + }; + await setupService.saveStep1Config(nextConfig); + setStep1Config(nextConfig); + return nextConfig; + }, []); + // Check login status when entering step 2 const checkLoginStatus = useCallback(async () => { setCheckingAuth(true); @@ -300,15 +305,6 @@ function SetupWizard({ } }, [currentStep, checkLoginStatus]); - // Retry cooldown timer - useEffect(() => { - if (retryCooldown <= 0) return; - const timer = setInterval(() => { - setRetryCooldown((prev) => Math.max(0, prev - 1)); - }, 1000); - return () => clearInterval(timer); - }, [retryCooldown]); - const handleStep1Submit = async () => { if (!step1Config.fileServerPort) { message.warning(t("Claw.Setup.basicConfig.fileServerPortRequired")); @@ -327,49 +323,13 @@ function SetupWizard({ await setupService.saveStep1Config(step1Config); setCurrentStep(2); message.success(t("Claw.Setup.basicConfig.saved")); - } catch (error) { + } catch { message.error(t("Claw.Setup.basicConfig.saveFailed")); } finally { setLoading(false); } }; - const handleLogin = async () => { - if (!username || !password) { - message.warning(t("Claw.Setup.login.accountAndCodeRequired")); - return; - } - - const loginDomain = domain || step1Config.serverHost; - if (!loginDomain) { - message.warning(t("Claw.Setup.login.domainRequired")); - return; - } - - setLoginLoading(true); - setLoginError(""); - try { - await loginAndRegister(username, password, { - suppressToast: true, - domain: loginDomain, - }); - setLoginError(""); - await setupService.completeStep2(); - await setupService.completeSetup(); - setCompleted(true); - message.success(t("Claw.Setup.login.success")); - setTimeout(() => onComplete(), 2000); - } catch (error: any) { - const errorMessage = getAuthErrorMessage(error); - message.error(errorMessage); - setLoginError(errorMessage); - setPassword(""); - setRetryCooldown(3); - } finally { - setLoginLoading(false); - } - }; - const handleContinueLoggedIn = async () => { try { await setupService.completeStep2(); @@ -381,6 +341,15 @@ function SetupWizard({ } }; + const handleLoginSuccess = async () => { + await ensureDefaultStep1Config(); + await setupService.completeStep2(); + await setupService.completeSetup(); + setCompleted(true); + message.success(t("Claw.Setup.login.success")); + setTimeout(() => onComplete(), 2000); + }; + const handleLogout = async () => { try { await logout(); @@ -551,85 +520,11 @@ function SetupWizard({ } return ( -
- {loginError && ( - - {loginError} - - } - type="error" - showIcon - style={{ marginBottom: 12 }} - /> - )} - - - } - value={domain || step1Config.serverHost} - onChange={(e) => setDomain(e.target.value)} - placeholder={t("Claw.Setup.login.domainPlaceholder")} - autoComplete="off" - spellCheck={false} - /> - - - - } - value={username} - onChange={(e) => setUsername(e.target.value)} - placeholder={t("Claw.Setup.login.accountPlaceholder")} - autoComplete="username" - /> - - - - } - value={password} - onChange={(e) => setPassword(e.target.value)} - placeholder={t("Claw.Setup.login.codePlaceholder")} - autoComplete="current-password" - /> - - - - - - - -
- - {t("Claw.Setup.login.supportMultipleAccountTypes")} - -
-
- + ); default: @@ -709,6 +604,22 @@ function SetupWizard({ ); } + if ( + dependenciesReady && + currentStep === 2 && + !completed && + !checkingAuth && + !isAlreadyLoggedIn + ) { + return ( + + ); + } + // 阶段 2-4: 配置步骤 return (
diff --git a/qimingclaw/crates/agent-electron-client/src/renderer/index.html b/qimingclaw/crates/agent-electron-client/src/renderer/index.html index 7a2cb171..8d9d5b3d 100644 --- a/qimingclaw/crates/agent-electron-client/src/renderer/index.html +++ b/qimingclaw/crates/agent-electron-client/src/renderer/index.html @@ -6,7 +6,7 @@ - 启明 + 陇电数字员工
diff --git a/qimingclaw/crates/agent-electron-client/src/shared/constants.test.ts b/qimingclaw/crates/agent-electron-client/src/shared/constants.test.ts index 6e370a60..d17cf522 100644 --- a/qimingclaw/crates/agent-electron-client/src/shared/constants.test.ts +++ b/qimingclaw/crates/agent-electron-client/src/shared/constants.test.ts @@ -49,7 +49,7 @@ import { describe("Constants", () => { describe("App Identity", () => { it("should have consistent app name", () => { - expect(APP_DISPLAY_NAME).toBe("启明数字员工"); + expect(APP_DISPLAY_NAME).toBe("陇电数字员工"); expect(APP_NAME_IDENTIFIER).toBe("qimingclaw"); }); diff --git a/qimingclaw/crates/agent-electron-client/src/shared/constants.ts b/qimingclaw/crates/agent-electron-client/src/shared/constants.ts index a51097ed..05731b19 100644 --- a/qimingclaw/crates/agent-electron-client/src/shared/constants.ts +++ b/qimingclaw/crates/agent-electron-client/src/shared/constants.ts @@ -10,7 +10,7 @@ import type { AgentEngineType } from "@shared/types/electron"; // ==================== 应用名称 ==================== /** 应用对外显示名称(窗口标题、关于、安装包名称等),与 package.json build.productName 保持一致 */ -export const APP_DISPLAY_NAME = "启明数字员工"; +export const APP_DISPLAY_NAME = "陇电数字员工"; /** 应用技术标识(进程名、目录名等,小写字母),与 appId 等保持一致 */ export const APP_NAME_IDENTIFIER = "qimingclaw";