diff --git a/build/linux/euler-copilot-web.spec b/build/linux/euler-copilot-web.spec index 19b00ed63ddd673046f1ba6841717b55ff3e33af..de499456f966df2519c89eec7653d15f4468773b 100644 --- a/build/linux/euler-copilot-web.spec +++ b/build/linux/euler-copilot-web.spec @@ -43,6 +43,7 @@ openEuler 智能化解决方案 Web 前端 # Electron 客户端 Group: Applications/Utilities Summary: openEuler 智能化解决方案桌面客户端 +Requires: which Requires: at-spi2-core Requires: gtk3 Requires: libXScrnSaver diff --git a/electron/main/deploy/core/DeploymentService.ts b/electron/main/deploy/core/DeploymentService.ts index fde1c3a1a5b53695e0f0e020a39932a94ec18ff5..d24c8e574e888042fce6f64286d0f3fbb7f50a25 100644 --- a/electron/main/deploy/core/DeploymentService.ts +++ b/electron/main/deploy/core/DeploymentService.ts @@ -1,5 +1,12 @@ // Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. // licensed under the Mulan PSL v2. +// You can use this software according to the terms and conditions of the Mulan PSL v2. +// You may obtain a copy of Mulan PSL v2 at: +// http://license.coscl.org.cn/MulanPSL2 +// THIS SOFTWARE IS PROVIDED ON AN 'AS IS' BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR +// PURPOSE. +// See the Mulan PSL v2 for more details. import * as path from 'path'; import * as fs from 'fs'; @@ -10,7 +17,10 @@ import type { DeploymentParams, DeploymentStatus, } from '../types/deployment.types'; -import { EnvironmentChecker } from './EnvironmentChecker'; +import { + EnvironmentChecker, + type EnvironmentCheckResult, +} from './EnvironmentChecker'; import { ValuesYamlManager } from './ValuesYamlManager'; const execAsync = promisify(exec); @@ -23,10 +33,11 @@ export class DeploymentService { private deploymentPath: string; private environmentChecker: EnvironmentChecker; private valuesYamlManager: ValuesYamlManager; + private environmentCheckResult?: EnvironmentCheckResult; private currentStatus: DeploymentStatus = { status: 'idle', message: '', - progress: 0, + currentStep: 'idle', }; private statusCallback?: (status: DeploymentStatus) => void; @@ -53,7 +64,19 @@ export class DeploymentService { * 更新部署状态 */ private updateStatus(status: Partial) { + // 验证输入状态 + if (!status || typeof status !== 'object') { + console.warn('DeploymentService: 尝试更新无效状态:', status); + return; + } + this.currentStatus = { ...this.currentStatus, ...status }; + + // 确保 currentStep 总是存在 + if (!this.currentStatus.currentStep) { + this.currentStatus.currentStep = 'unknown'; + } + if (this.statusCallback) { this.statusCallback(this.currentStatus); } @@ -75,7 +98,6 @@ export class DeploymentService { this.updateStatus({ status: 'preparing', message: '准备安装环境...', - progress: 0, currentStep: 'preparing-environment', }); @@ -88,13 +110,12 @@ export class DeploymentService { // 3. 配置 values.yaml await this.configureValues(params); - // 4. 执行部署脚本中的工具安装部分 + // 4. 执行部署脚本中的工具安装部分(如果需要) await this.installTools(); // 更新准备环境完成状态 this.updateStatus({ message: '准备安装环境完成', - progress: 25, currentStep: 'environment-ready', }); @@ -104,14 +125,12 @@ export class DeploymentService { this.updateStatus({ status: 'success', message: '部署完成!', - progress: 100, currentStep: 'completed', }); } catch (error) { this.updateStatus({ status: 'error', message: `部署失败: ${error instanceof Error ? error.message : String(error)}`, - progress: 0, currentStep: 'failed', }); throw error; @@ -125,17 +144,42 @@ export class DeploymentService { this.updateStatus({ status: 'preparing', message: '检查系统环境...', - progress: 10, + currentStep: 'preparing-environment', }); + // 检查 root 权限(仅限 Linux) + await this.checkRootPermission(); + const checkResult = await this.environmentChecker.checkAll(); + + // 安装缺失的基础工具 + if (checkResult.needsBasicToolsInstall) { + this.updateStatus({ + message: '安装缺失的基础工具...', + currentStep: 'preparing-environment', + }); + + await this.environmentChecker.installBasicTools( + checkResult.missingBasicTools, + ); + + this.updateStatus({ + message: '基础工具安装完成', + currentStep: 'preparing-environment', + }); + } + + // 检查是否有严重错误 if (!checkResult.success) { throw new Error(`环境检查失败: ${checkResult.errors.join(', ')}`); } + // 存储检查结果,用于后续决定是否需要执行 2-install-tools + this.environmentCheckResult = checkResult; + this.updateStatus({ message: '环境检查通过', - progress: 20, + currentStep: 'preparing-environment', }); } @@ -146,7 +190,7 @@ export class DeploymentService { this.updateStatus({ status: 'cloning', message: '克隆部署仓库...', - progress: 30, + currentStep: 'preparing-environment', }); // 确保部署目录的父目录存在 @@ -162,7 +206,7 @@ export class DeploymentService { await execAsync('git pull origin master', { cwd: this.deploymentPath }); this.updateStatus({ message: '更新部署仓库完成', - progress: 40, + currentStep: 'preparing-environment', }); } else { // 不存在,克隆仓库 @@ -175,7 +219,7 @@ export class DeploymentService { ); this.updateStatus({ message: '克隆部署仓库完成', - progress: 40, + currentStep: 'preparing-environment', }); } } @@ -187,7 +231,7 @@ export class DeploymentService { this.updateStatus({ status: 'configuring', message: '配置部署参数...', - progress: 50, + currentStep: 'preparing-environment', }); const valuesPath = path.join( @@ -198,7 +242,7 @@ export class DeploymentService { this.updateStatus({ message: '配置部署参数完成', - progress: 60, + currentStep: 'preparing-environment', }); } @@ -206,11 +250,19 @@ export class DeploymentService { * 安装工具(准备环境的一部分) */ private async installTools(): Promise { + // 检查是否需要安装 K8s 工具 + if (!this.environmentCheckResult?.needsK8sToolsInstall) { + this.updateStatus({ + message: 'K8s 工具已存在,跳过工具安装', + currentStep: 'preparing-environment', + }); + return; + } + this.updateStatus({ status: 'preparing', - message: '安装必要工具...', - progress: 15, - currentStep: 'installing-tools', + message: '安装 K8s 工具 (kubectl, helm)...', + currentStep: 'preparing-environment', }); const scriptsPath = path.join(this.deploymentPath, 'deploy/scripts'); @@ -221,19 +273,19 @@ export class DeploymentService { // 检查脚本文件是否存在 if (fs.existsSync(toolsScriptPath)) { - // 给脚本添加执行权限并执行 - await execAsync( - `chmod +x "${toolsScriptPath}" && bash "${toolsScriptPath}"`, - { - cwd: scriptsPath, - timeout: 300000, // 5分钟超时 - }, - ); + // 构建需要权限的命令 + const command = this.buildRootCommand(toolsScriptPath); + + // 执行脚本 + await execAsync(command, { + cwd: scriptsPath, + timeout: 300000, // 5分钟超时 + }); } this.updateStatus({ - message: '工具安装完成', - progress: 20, + message: 'K8s 工具安装完成', + currentStep: 'preparing-environment', }); } @@ -250,24 +302,32 @@ export class DeploymentService { path: '6-install-databases/install_databases.sh', displayName: '数据库服务', step: 'install-databases', - progressStart: 30, - progressEnd: 50, + envVars: {}, }, { name: '7-install-authhub', path: '7-install-authhub/install_authhub.sh', displayName: 'AuthHub 服务', step: 'install-authhub', - progressStart: 50, - progressEnd: 75, + envVars: { + // 通过环境变量或输入重定向避免交互 + AUTHHUB_DOMAIN: 'authhub.eulercopilot.local', + }, + useInputRedirection: true, // 标记需要输入重定向 }, { name: '8-install-EulerCopilot', path: '8-install-EulerCopilot/install_eulercopilot.sh', displayName: 'Intelligence 服务', step: 'install-intelligence', - progressStart: 75, - progressEnd: 95, + envVars: { + // install_eulercopilot.sh 已支持这些环境变量 + EULERCOPILOT_DOMAIN: 'www.eulercopilot.local', + AUTHHUB_DOMAIN: 'authhub.eulercopilot.local', + // 设置非交互模式标志 + CI: 'true', + DEBIAN_FRONTEND: 'noninteractive', + }, }, ]; @@ -277,7 +337,6 @@ export class DeploymentService { this.updateStatus({ status: 'deploying', message: `正在安装 ${script.displayName}...`, - progress: script.progressStart, currentStep: script.step, }); @@ -288,20 +347,160 @@ export class DeploymentService { throw new Error(`脚本文件不存在: ${scriptPath}`); } + // 准备环境变量 + const execEnv = { + ...process.env, + ...script.envVars, + }; + + // 构建需要权限的命令 + const command = this.buildRootCommand( + scriptPath, + script.useInputRedirection, + script.useInputRedirection ? 'authhub.eulercopilot.local' : undefined, + ); + // 给脚本添加执行权限并执行 - await execAsync(`chmod +x "${scriptPath}" && bash "${scriptPath}"`, { + await execAsync(command, { cwd: scriptsPath, timeout: 300000, // 5分钟超时 + env: execEnv, }); // 更新完成状态 this.updateStatus({ message: `${script.displayName} 安装完成`, - progress: script.progressEnd, + currentStep: script.step, }); } } + /** + * 检查并确保有 root 权限或 sudo 权限(仅限 Linux 系统) + */ + private async checkRootPermission(): Promise { + // 只在 Linux 系统上检查权限 + if (process.platform !== 'linux') { + return; + } + + try { + // 检查当前用户 ID,0 表示 root + const { stdout } = await execAsync('id -u'); + const uid = parseInt(stdout.trim(), 10); + + // 如果是 root 用户,直接通过 + if (uid === 0) { + return; + } + + // 如果不是 root 用户,检查是否有 sudo 权限 + try { + // 检查用户是否在管理员组中(sudo、wheel、admin) + const { stdout: groupsOutput } = await execAsync('groups'); + const userGroups = groupsOutput.trim().split(/\s+/); + + // 检查常见的管理员组 + const adminGroups = ['sudo', 'wheel', 'admin']; + const hasAdminGroup = adminGroups.some((group) => + userGroups.includes(group), + ); + + if (hasAdminGroup) { + // 用户在管理员组中,具有 sudo 权限 + // 在实际执行时,buildRootCommand 会使用适当的图形化 sudo 工具 + return; + } + + // 如果不在管理员组中,尝试检查是否有无密码 sudo 权限 + try { + await execAsync('sudo -n true', { timeout: 3000 }); + // 如果成功,说明用户有无密码 sudo 权限 + return; + } catch { + // 用户既不在管理员组中,也没有无密码 sudo 权限 + throw new Error( + '部署脚本需要管理员权限才能执行。请确保当前用户具有 sudo 权限。', + ); + } + } catch (error) { + if ( + error instanceof Error && + error.message.includes('部署脚本需要管理员权限') + ) { + throw error; + } + // 无法检查组信息,假设用户可能有权限,在实际执行时再处理 + // 这样避免过于严格的权限检查阻止部署 + return; + } + } catch (error) { + if ( + error instanceof Error && + (error.message.includes('部署脚本需要 root 权限') || + error.message.includes('用户具有管理员权限')) + ) { + throw error; + } + throw new Error('无法检查用户权限'); + } + } + + /** + * 构建需要 root 权限的命令 + */ + private buildRootCommand( + scriptPath: string, + useInputRedirection?: boolean, + inputData?: string, + ): string { + // 在 Linux 系统上,如果不是 root 用户,使用图形化 sudo 工具 + const needsSudo = + process.platform === 'linux' && process.getuid && process.getuid() !== 0; + + // 获取合适的图形化 sudo 工具 + const getSudoCommand = (): string => { + if (!needsSudo) return ''; + + // 构建完整的环境变量,确保 PATH 包含常用的系统路径 + const currentPath = process.env.PATH || ''; + const additionalPaths = [ + '/usr/local/bin', + '/usr/bin', + '/bin', + '/usr/sbin', + '/sbin', + ]; + + // 确保所有常用路径都在 PATH 中 + const pathArray = currentPath.split(':'); + additionalPaths.forEach((path) => { + if (!pathArray.includes(path)) { + pathArray.push(path); + } + }); + const fullPath = pathArray.join(':'); + + // 优先使用 pkexec(现代 Linux 桌面环境的标准) + // 传递必要的环境变量,包括完整的 PATH + return `pkexec env DISPLAY=$DISPLAY XAUTHORITY=$XAUTHORITY PATH="${fullPath}" `; + }; + + const sudoCommand = getSudoCommand(); + + let command = sudoCommand; + command += `chmod +x "${scriptPath}" && `; + command += sudoCommand; + + if (useInputRedirection && inputData) { + command += `bash -c 'echo "${inputData}" | bash "${scriptPath}"'`; + } else { + command += `bash "${scriptPath}"`; + } + + return command; + } + /** * 停止部署 */ @@ -309,7 +508,7 @@ export class DeploymentService { this.updateStatus({ status: 'idle', message: '部署已停止', - progress: 0, + currentStep: 'stopped', }); } @@ -323,7 +522,7 @@ export class DeploymentService { this.updateStatus({ status: 'idle', message: '清理完成', - progress: 0, + currentStep: 'idle', }); } } diff --git a/electron/main/deploy/core/EnvironmentChecker.ts b/electron/main/deploy/core/EnvironmentChecker.ts index 5ee2aaa9e066101aeb2bfff0ff2383a12fa93b48..484981d740985bc8f794204f7cb9a0f441ef53f6 100644 --- a/electron/main/deploy/core/EnvironmentChecker.ts +++ b/electron/main/deploy/core/EnvironmentChecker.ts @@ -1,5 +1,12 @@ // Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. // licensed under the Mulan PSL v2. +// You can use this software according to the terms and conditions of the Mulan PSL v2. +// You may obtain a copy of Mulan PSL v2 at: +// http://license.coscl.org.cn/MulanPSL2 +// THIS SOFTWARE IS PROVIDED ON AN 'AS IS' BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR +// PURPOSE. +// See the Mulan PSL v2 for more details. import * as os from 'os'; import * as fs from 'fs'; @@ -12,6 +19,10 @@ export interface EnvironmentCheckResult { success: boolean; errors: string[]; warnings: string[]; + missingBasicTools: string[]; + missingK8sTools: string[]; + needsBasicToolsInstall: boolean; + needsK8sToolsInstall: boolean; } /** @@ -28,6 +39,10 @@ export class EnvironmentChecker { success: true, errors: [], warnings: [], + missingBasicTools: [], + missingK8sTools: [], + needsBasicToolsInstall: false, + needsK8sToolsInstall: false, }; // 检查主机名 @@ -70,7 +85,22 @@ export class EnvironmentChecker { // 检查必需的系统工具 try { - await this.checkRequiredTools(); + const toolsCheckResult = await this.checkRequiredTools(); + result.missingBasicTools = toolsCheckResult.missingBasicTools; + result.missingK8sTools = toolsCheckResult.missingK8sTools; + result.needsBasicToolsInstall = toolsCheckResult.needsBasicToolsInstall; + result.needsK8sToolsInstall = toolsCheckResult.needsK8sToolsInstall; + + if (toolsCheckResult.missingBasicTools.length > 0) { + result.warnings.push( + `缺少基础工具: ${toolsCheckResult.missingBasicTools.join(', ')},将通过 DNF 自动安装`, + ); + } + if (toolsCheckResult.missingK8sTools.length > 0) { + result.warnings.push( + `缺少 K8s 工具: ${toolsCheckResult.missingK8sTools.join(', ')},将通过 install-tools 脚本安装`, + ); + } } catch (error) { result.errors.push(`系统工具检查: ${error}`); result.success = false; @@ -189,7 +219,7 @@ export class EnvironmentChecker { timeout: 10000, }, ); - } catch (error) { + } catch { throw new Error('无法访问外部网络,请检查网络连接'); } } @@ -197,20 +227,72 @@ export class EnvironmentChecker { /** * 检查必需的系统工具 */ - private async checkRequiredTools(): Promise { - const requiredTools = ['git', 'curl', 'docker', 'kubectl', 'helm']; - const missingTools: string[] = []; + private async checkRequiredTools(): Promise<{ + missingBasicTools: string[]; + missingK8sTools: string[]; + needsBasicToolsInstall: boolean; + needsK8sToolsInstall: boolean; + }> { + // 基础工具:通过 DNF 安装 + const basicTools = ['git', 'curl', 'docker']; + // K8s 工具:通过 2-install-tools 脚本安装 + const k8sTools = ['kubectl', 'helm']; + + const missingBasicTools: string[] = []; + const missingK8sTools: string[] = []; - for (const tool of requiredTools) { + // 检查基础工具 + for (const tool of basicTools) { try { await execAsync(`which ${tool}`); - } catch (error) { - missingTools.push(tool); + } catch { + missingBasicTools.push(tool); } } - if (missingTools.length > 0) { - throw new Error(`缺少必需工具: ${missingTools.join(', ')}`); + // 检查 K8s 工具 + for (const tool of k8sTools) { + try { + await execAsync(`which ${tool}`); + } catch { + missingK8sTools.push(tool); + } + } + + return { + missingBasicTools, + missingK8sTools, + needsBasicToolsInstall: missingBasicTools.length > 0, + needsK8sToolsInstall: missingK8sTools.length > 0, + }; + } + + /** + * 通过 DNF 安装基础工具 + */ + async installBasicTools(missingTools: string[]): Promise { + if (missingTools.length === 0) { + return; + } + + // 构建 DNF 安装命令 + let installCommand = `dnf install -y ${missingTools.join(' ')}`; + + // 在 Linux 系统上,如果不是 root 用户,使用图形化 sudo 工具 + const needsSudo = + process.platform === 'linux' && process.getuid && process.getuid() !== 0; + + if (needsSudo) { + // 使用 pkexec 或 sudo 获取权限 + installCommand = `pkexec env DISPLAY=$DISPLAY XAUTHORITY=$XAUTHORITY ${installCommand}`; + } + + try { + await execAsync(installCommand, { timeout: 300000 }); // 5分钟超时 + } catch (error) { + throw new Error( + `安装基础工具失败: ${error instanceof Error ? error.message : String(error)}`, + ); } } } diff --git a/electron/main/deploy/core/LocalDeployHandler.ts b/electron/main/deploy/core/LocalDeployHandler.ts index f920df845be2b2967c29000ffd0a097dbb42dc2d..53d921ca6fbd977bf6ab5bcb2e5423b11e3c12f3 100644 --- a/electron/main/deploy/core/LocalDeployHandler.ts +++ b/electron/main/deploy/core/LocalDeployHandler.ts @@ -1,5 +1,12 @@ // Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. // licensed under the Mulan PSL v2. +// You can use this software according to the terms and conditions of the Mulan PSL v2. +// You may obtain a copy of Mulan PSL v2 at: +// http://license.coscl.org.cn/MulanPSL2 +// THIS SOFTWARE IS PROVIDED ON AN 'AS IS' BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR +// PURPOSE. +// See the Mulan PSL v2 for more details. import { DeploymentService } from './DeploymentService'; import type { diff --git a/electron/main/deploy/core/ValuesYamlManager.ts b/electron/main/deploy/core/ValuesYamlManager.ts index 571805d8693d8d57e64b54994a1bcb840348a59f..d1190705cb0170589c7b4c3c0ac3128e29d07f6f 100644 --- a/electron/main/deploy/core/ValuesYamlManager.ts +++ b/electron/main/deploy/core/ValuesYamlManager.ts @@ -1,5 +1,12 @@ // Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. // licensed under the Mulan PSL v2. +// You can use this software according to the terms and conditions of the Mulan PSL v2. +// You may obtain a copy of Mulan PSL v2 at: +// http://license.coscl.org.cn/MulanPSL2 +// THIS SOFTWARE IS PROVIDED ON AN 'AS IS' BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR +// PURPOSE. +// See the Mulan PSL v2 for more details. import * as fs from 'fs'; import * as yaml from 'js-yaml'; diff --git a/electron/main/deploy/index.ts b/electron/main/deploy/index.ts index c602ab300cdb4fd05ec4ddb94a3c6adc446ec5b7..aa7820e83a967b81c8d5d6c76fdeae3665da5010 100644 --- a/electron/main/deploy/index.ts +++ b/electron/main/deploy/index.ts @@ -1,5 +1,12 @@ // Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. // licensed under the Mulan PSL v2. +// You can use this software according to the terms and conditions of the Mulan PSL v2. +// You may obtain a copy of Mulan PSL v2 at: +// http://license.coscl.org.cn/MulanPSL2 +// THIS SOFTWARE IS PROVIDED ON AN 'AS IS' BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR +// PURPOSE. +// See the Mulan PSL v2 for more details. import { DeploymentService } from './core/DeploymentService'; import { LocalDeployHandler } from './core/LocalDeployHandler'; diff --git a/electron/main/deploy/main/DeploymentIPCHandler.ts b/electron/main/deploy/main/DeploymentIPCHandler.ts index 17b93f56eac93713f72189edef81c609d48ea0b2..a420cabda13ddd4e33d707f5d31ee5018120dc1a 100644 --- a/electron/main/deploy/main/DeploymentIPCHandler.ts +++ b/electron/main/deploy/main/DeploymentIPCHandler.ts @@ -1,5 +1,12 @@ // Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. // licensed under the Mulan PSL v2. +// You can use this software according to the terms and conditions of the Mulan PSL v2. +// You may obtain a copy of Mulan PSL v2 at: +// http://license.coscl.org.cn/MulanPSL2 +// THIS SOFTWARE IS PROVIDED ON AN 'AS IS' BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR +// PURPOSE. +// See the Mulan PSL v2 for more details. import { ipcMain, BrowserWindow } from 'electron'; import { deploymentService } from '../index'; @@ -27,8 +34,16 @@ export class DeploymentIPCHandler { // 设置状态变化回调 this.localDeployHandler.setStatusCallback((status) => { - if (this.mainWindow && !this.mainWindow.isDestroyed()) { + // 验证状态对象是否有效 + if ( + status && + typeof status === 'object' && + this.mainWindow && + !this.mainWindow.isDestroyed() + ) { this.mainWindow.webContents.send('deployment:statusChanged', status); + } else if (!status) { + console.warn('IPC Handler: 收到无效的状态更新:', status); } }); } diff --git a/electron/main/deploy/preload/deploymentPreload.ts b/electron/main/deploy/preload/deploymentPreload.ts index 4cc335dd769ad4894f808908dabcd92579c39f5f..15b7a2fc63364f389cbc12c6963f7d52b7a7c2a7 100644 --- a/electron/main/deploy/preload/deploymentPreload.ts +++ b/electron/main/deploy/preload/deploymentPreload.ts @@ -1,5 +1,12 @@ // Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. // licensed under the Mulan PSL v2. +// You can use this software according to the terms and conditions of the Mulan PSL v2. +// You may obtain a copy of Mulan PSL v2 at: +// http://license.coscl.org.cn/MulanPSL2 +// THIS SOFTWARE IS PROVIDED ON AN 'AS IS' BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR +// PURPOSE. +// See the Mulan PSL v2 for more details. import { contextBridge, ipcRenderer } from 'electron'; import type { diff --git a/electron/main/deploy/types/deployment.types.ts b/electron/main/deploy/types/deployment.types.ts index 2c918fcc00caa992aed9a8fe9f89657a95648b7a..a293a7d4dfe27802254b05b188a76afb58089738 100644 --- a/electron/main/deploy/types/deployment.types.ts +++ b/electron/main/deploy/types/deployment.types.ts @@ -1,5 +1,12 @@ // Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. // licensed under the Mulan PSL v2. +// You can use this software according to the terms and conditions of the Mulan PSL v2. +// You may obtain a copy of Mulan PSL v2 at: +// http://license.coscl.org.cn/MulanPSL2 +// THIS SOFTWARE IS PROVIDED ON AN 'AS IS' BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR +// PURPOSE. +// See the Mulan PSL v2 for more details. export interface ModelConfig { endpoint: string; @@ -43,7 +50,6 @@ export interface DeploymentStatus { | 'success' | 'error'; message: string; - progress: number; currentStep?: string; estimatedTime?: number; } diff --git a/electron/main/index.ts b/electron/main/index.ts index 81e00dbdeb4c03297a13b040ba7d8f4128b09580..b44c289611d9a206ec519ab8aba82a2a613d6954 100644 --- a/electron/main/index.ts +++ b/electron/main/index.ts @@ -89,6 +89,9 @@ app.on('activate', () => { */ async function onReady() { try { + // 首先注册IPC监听器,确保欢迎窗口也能使用相关功能 + registerIpcListeners(); + // 检查配置文件是否存在,如果不存在则显示欢迎界面 const shouldShowWelcome = checkAndShowWelcomeIfNeeded(); @@ -161,9 +164,6 @@ export async function continueAppStartup() { * 启动应用 */ async function startup() { - // 注册IPC通信监听器 - registerIpcListeners(); - // 创建系统托盘 createTray(); diff --git a/electron/preload/types.d.ts b/electron/preload/types.d.ts index c7f212c478f18aa0c34eb6ecf9b8a3f6077b05f2..9ab635d8a174a818272310dc0408dc8833c1c754 100644 --- a/electron/preload/types.d.ts +++ b/electron/preload/types.d.ts @@ -1,5 +1,12 @@ // Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. // licensed under the Mulan PSL v2. +// You can use this software according to the terms and conditions of the Mulan PSL v2. +// You may obtain a copy of Mulan PSL v2 at: +// http://license.coscl.org.cn/MulanPSL2 +// THIS SOFTWARE IS PROVIDED ON AN 'AS IS' BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR +// PURPOSE. +// See the Mulan PSL v2 for more details. /** * Electron Preload API 类型定义 diff --git a/electron/welcome/deployServiceConnector.js b/electron/welcome/deployServiceConnector.js index 17a385a8598094bc61723265fea39038f12dadbf..b055066e5c9d82c81b034318d855151fe9221108 100644 --- a/electron/welcome/deployServiceConnector.js +++ b/electron/welcome/deployServiceConnector.js @@ -1,3 +1,13 @@ +// Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. +// licensed under the Mulan PSL v2. +// You can use this software according to the terms and conditions of the Mulan PSL v2. +// You may obtain a copy of Mulan PSL v2 at: +// http://license.coscl.org.cn/MulanPSL2 +// THIS SOFTWARE IS PROVIDED ON AN 'AS IS' BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR +// PURPOSE. +// See the Mulan PSL v2 for more details. + /** * 本地部署服务连接器 * 由于不能修改 localDeploy.vue,这个文件作为桥梁连接前端表单和部署服务 diff --git a/electron/welcome/index.vue b/electron/welcome/index.vue index 84be0920d406c27a32660a274236ddbe28aabafc..872633e82a3161353ba7b8827bee052700a97289 100644 --- a/electron/welcome/index.vue +++ b/electron/welcome/index.vue @@ -10,7 +10,11 @@
-
+
{{ $t('welcome.localDeploy') }}
@@ -32,36 +36,28 @@