diff --git a/src/core/builder/platforms/types/pink.d.ts b/src/core/builder/platforms/types/pink.d.ts index 582a3156b..e8c3c8495 100644 --- a/src/core/builder/platforms/types/pink.d.ts +++ b/src/core/builder/platforms/types/pink.d.ts @@ -1473,4 +1473,11 @@ declare module 'pink' { ): import('vscode').WebviewPanel; } + export namespace builder { + /** + * Gets the preview URL for a built web platform. + */ + export function getPreviewUrl(buildPath: string, platform: string): Thenable; + } + } diff --git a/src/core/builder/platforms/web-mobile/scripts/build-view.js b/src/core/builder/platforms/web-mobile/scripts/build-view.js index f3ebfdc8b..397d2a274 100644 --- a/src/core/builder/platforms/web-mobile/scripts/build-view.js +++ b/src/core/builder/platforms/web-mobile/scripts/build-view.js @@ -29,7 +29,7 @@ const hostOptions = { format: 'cjs', platform: 'node', target: 'node18', - external: ['vscode'], + external: ['vscode', 'pink'], logLevel: 'info', }; diff --git a/src/core/builder/platforms/web-mobile/src/view/build-config-host.ts b/src/core/builder/platforms/web-mobile/src/view/build-config-host.ts index a90d17a50..b47aaf503 100644 --- a/src/core/builder/platforms/web-mobile/src/view/build-config-host.ts +++ b/src/core/builder/platforms/web-mobile/src/view/build-config-host.ts @@ -1,4 +1,5 @@ -import * as fs from 'node:fs'; +import * as pink from 'pink'; +import * as vscode from 'vscode'; import * as path from 'node:path'; type Bundle = Record; @@ -72,16 +73,6 @@ function substitute(text: string, sub?: Record): string { return text.replace(/%?\{(\w+)\}/g, (match, key: string) => (key in sub ? String(sub[key]) : match)); } -async function getActiveProject(): Promise { - try { - const vscode = require('vscode'); - const project = await vscode?.commands.executeCommand('pink.workspace.getActiveProject'); - return project?.path || ''; - } catch { - return ''; - } -} - function runtimeRequire(request: string): T | undefined { try { return module.require(request) as T; @@ -90,32 +81,6 @@ function runtimeRequire(request: string): T | undefined { } } -function resolveBuildPath(buildPath: string, projectPath: string): string { - if (!buildPath || buildPath === 'project://build') { - return path.join(projectPath, 'build'); - } - if (buildPath.startsWith('project://')) { - return path.join(projectPath, buildPath.replace(/^project:\/\//, '')); - } - return buildPath; -} - -function getServerUrl(): string { - const server = runtimeRequire<{ serverService?: { url?: string } }>(path.join(__dirname, '../../../../../../server/server')); - const url = server?.serverService?.url || ''; - return url && !url.includes('未启动') ? url : 'http://localhost:9527'; -} - -function registerBuildOutput(rawPath: string, outputName: string): void { - if (!fs.existsSync(rawPath)) { - return; - } - const middleware = runtimeRequire<{ registerBuildPath?: (platform: string, name: string, dest: string) => void }>( - path.join(__dirname, '../../../../build.middleware'), - ); - middleware?.registerBuildPath?.('web-mobile', outputName, rawPath); -} - async function createQRCodeSrc(url: string): Promise { if (!url) { return ''; @@ -137,15 +102,10 @@ async function createQRCodeSrc(url: string): Promise { } async function getPreviewInfo(request: PreviewRequest = {}): Promise { - const projectPath = await getActiveProject(); const buildPath = request.buildPath || 'project://build'; const outputName = request.outputName || 'web-mobile'; - const buildRoot = resolveBuildPath(buildPath, projectPath); - const rawPath = path.join(buildRoot, outputName); - const serverUrl = getServerUrl(); - const previewUrl = serverUrl ? `${serverUrl}/web-mobile/${outputName}/index.html` : ''; - registerBuildOutput(rawPath, outputName); - + const platform = 'web-mobile'; + const previewUrl = await pink.builder.getPreviewUrl(path.join(buildPath, outputName), platform) || ''; const webGPUTips = request.useWebGPU && previewUrl && !previewUrl.startsWith('https') ? lookup(loadBundle(), 'tips.webGPUServer') || '' : ''; @@ -165,4 +125,9 @@ export function activate(context: HostContext): void { return text === undefined ? key : substitute(text, sub); }); context.registerMethod('getPreviewInfo', (request: PreviewRequest) => getPreviewInfo(request)); + context.registerMethod('openPreviewUrl', async (url: string) => { + if (url) { + await vscode.env.openExternal(vscode.Uri.parse(url)); + } + }); } diff --git a/src/core/builder/platforms/web-mobile/src/view/build-config.tsx b/src/core/builder/platforms/web-mobile/src/view/build-config.tsx index 5d71b7f02..c4bfc3849 100644 --- a/src/core/builder/platforms/web-mobile/src/view/build-config.tsx +++ b/src/core/builder/platforms/web-mobile/src/view/build-config.tsx @@ -79,10 +79,13 @@ export default function WebMobileBuildView({ value, onChange, bridge, commonValu const useWebGPU = boolValue(value.useWebGPU); const outputName = stringValue(commonValue?.outputName) || 'web-mobile'; const buildPath = stringValue(commonValue?.buildPath) || 'project://build'; - const t = (key: string) => translate(bundle, key); const previewRequest = useMemo(() => ({ buildPath, outputName, useWebGPU }), [buildPath, outputName, useWebGPU]); + const openPreviewUrl = (url: string) => { + bridge?.invoke('openPreviewUrl', url).catch(() => {}); + }; + useEffect(() => { if (!bridge) { return; @@ -172,7 +175,14 @@ export default function WebMobileBuildView({ value, onChange, bridge, commonValu