Skip to content

Commit 96126e3

Browse files
author
lhy
committed
通过web view反馈验证结果
1 parent a3093d7 commit 96126e3

5 files changed

Lines changed: 213 additions & 72 deletions

File tree

src/PawSQLSidebarProvider.ts

Lines changed: 143 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,7 @@ export class PawSQLTreeProvider
342342
}
343343
public async validateConfiguration(hideMessage?: boolean): Promise<void> {
344344
const config = vscode.workspace.getConfiguration("pawsql");
345+
345346
const apiKey = config.get<string>("apiKey");
346347
const frontendUrl = config.get<string>("frontendUrl");
347348
const backendUrl = config.get<string>("backendUrl");
@@ -350,8 +351,6 @@ export class PawSQLTreeProvider
350351
// Reset all validation states first
351352
this.isConfigValid = false;
352353

353-
// Validate backend connectivity
354-
355354
const backendResult = await validateBackend(backendUrl ?? "");
356355

357356
const isBackendConnected = backendResult.isAvailable;
@@ -366,20 +365,20 @@ export class PawSQLTreeProvider
366365
return;
367366
}
368367

369-
// Validate frontend connectivity
370-
const frontendReuslt = await validateFrontend(frontendUrl ?? "");
368+
// // Validate frontend connectivity
369+
// const frontendReuslt = await validateFrontend(frontendUrl ?? "");
371370

372-
const isFrontendConnected = frontendReuslt.isAvailable;
371+
// const isFrontendConnected = frontendReuslt.isAvailable;
373372

374-
if (!isFrontendConnected) {
375-
!hideMessage &&
376-
vscode.window.showErrorMessage(
377-
`${LanguageService.getMessage(
378-
"error.config.validate.failed"
379-
)}: ${LanguageService.getMessage("error.frontendUrl.invalid")}`
380-
);
381-
return;
382-
}
373+
// if (!isFrontendConnected) {
374+
// !hideMessage &&
375+
// vscode.window.showErrorMessage(
376+
// `${LanguageService.getMessage(
377+
// "error.config.validate.failed"
378+
// )}: ${LanguageService.getMessage("error.frontendUrl.invalid")}`
379+
// );
380+
// return;
381+
// }
383382

384383
// Validate API key
385384
const isApikeyValid = await ApiService.validateUserKey(apiKey ?? "");
@@ -426,6 +425,69 @@ export class PawSQLTreeProvider
426425
);
427426
}
428427
}
428+
public async validatePawSQLConfig(): Promise<boolean> {
429+
const pawsqlConfig = vscode.workspace.getConfiguration("pawsql");
430+
431+
const apiKey = pawsqlConfig.get<string>("apiKey");
432+
const frontendUrl = pawsqlConfig.get<string>("frontendUrl");
433+
const backendUrl = pawsqlConfig.get<string>("backendUrl");
434+
435+
try {
436+
// Reset all validation states first
437+
this.isConfigValid = false;
438+
439+
if (!backendUrl || !frontendUrl || !apiKey) {
440+
this.isConfigValid = false;
441+
vscode.commands.executeCommand("setContext", "isConfigured", false);
442+
this.workspaces = [];
443+
return false;
444+
}
445+
446+
const backendResult = await validateBackend(backendUrl);
447+
const isBackendConnected = backendResult.isAvailable;
448+
449+
if (!isBackendConnected) {
450+
this.isConfigValid = false;
451+
vscode.commands.executeCommand("setContext", "isConfigured", false);
452+
this.workspaces = [];
453+
return false;
454+
}
455+
456+
const frontendReuslt = await validateFrontend(frontendUrl);
457+
const isFrontendConnected = frontendReuslt.isAvailable;
458+
459+
if (!isFrontendConnected) {
460+
this.isConfigValid = false;
461+
vscode.commands.executeCommand("setContext", "isConfigured", false);
462+
463+
this.workspaces = [];
464+
return false;
465+
}
466+
467+
const isApikeyValid = await ApiService.validateUserKey(apiKey);
468+
469+
if (!isApikeyValid) {
470+
this.isConfigValid = false;
471+
vscode.commands.executeCommand("setContext", "isConfigured", false);
472+
473+
this.workspaces = [];
474+
return false;
475+
}
476+
477+
this.isConfigValid = true;
478+
vscode.commands.executeCommand("setContext", "isConfigured", true);
479+
480+
await this.loadWorkspaceData();
481+
return true;
482+
} catch (error: any) {
483+
console.error(error);
484+
this.isConfigValid = false;
485+
vscode.commands.executeCommand("setContext", "isConfigured", false);
486+
487+
this.workspaces = [];
488+
return false;
489+
}
490+
}
429491

430492
private async registerProviders(): Promise<void> {
431493
// 1. 创建树视图(如果不存在)
@@ -444,16 +506,12 @@ export class PawSQLTreeProvider
444506
private registerConfigurationChangeListener(): void {
445507
vscode.workspace.onDidChangeConfiguration(async (event) => {
446508
if (this.isApiConfigChanged(event)) {
447-
await this.registerProviders();
509+
await this.refresh(true);
448510
}
449511
});
450512
}
451513
public isApiConfigChanged(e: vscode.ConfigurationChangeEvent): boolean {
452-
return (
453-
e.affectsConfiguration("pawsql.apiKey") ||
454-
e.affectsConfiguration("pawsql.frontendUrl") ||
455-
e.affectsConfiguration("pawsql.backendUrl")
456-
);
514+
return e.affectsConfiguration("pawsql.apiKey");
457515
}
458516
public async validateConfig(): Promise<boolean> {
459517
const config = vscode.workspace.getConfiguration("pawsql");
@@ -650,6 +708,62 @@ export class PawSQLTreeProvider
650708
}
651709
}
652710

711+
// Rest of the methods remain unchanged...
712+
private async loadWorkspaceData(): Promise<void> {
713+
this.isWorkspaceLoading = true;
714+
this._onDidChangeTreeData.fire(undefined);
715+
716+
const apiKey = vscode.workspace
717+
.getConfiguration("pawsql")
718+
.get<string>("apiKey");
719+
720+
if (!apiKey) {
721+
vscode.window.showErrorMessage(
722+
`${LanguageService.getMessage(
723+
"error.config.validate.failed"
724+
)}: ${LanguageService.getMessage("license.code.not.valid")}`
725+
);
726+
return;
727+
}
728+
729+
try {
730+
const [workspacesResponse] = await Promise.all([
731+
ApiService.getWorkspaces(apiKey),
732+
]);
733+
734+
this.workspaces = workspacesResponse.data.records.map(
735+
(workspace) =>
736+
new WorkspaceItem(
737+
workspace.workspaceName,
738+
workspace.workspaceId,
739+
workspace.workspaceName,
740+
workspace.workspaceDefinitionId,
741+
workspace.dbType,
742+
workspace.dbHost,
743+
workspace.dbPort,
744+
vscode.TreeItemCollapsibleState.Collapsed
745+
)
746+
);
747+
vscode.commands.executeCommand(
748+
"setContext",
749+
"hasNoWorkspace",
750+
this.workspaces.length === 0
751+
);
752+
} catch (error: any) {
753+
console.log(error);
754+
this.isConfigValid = false;
755+
vscode.commands.executeCommand(
756+
"setContext",
757+
"isConfigured",
758+
this.isConfigValid
759+
);
760+
this.workspaces = [];
761+
} finally {
762+
this.isWorkspaceLoading = false;
763+
this._onDidChangeTreeData.fire(undefined);
764+
}
765+
}
766+
653767
private async getAnalysisItems(
654768
workspace: WorkspaceItem
655769
): Promise<AnalysisItem[] | EmptyItem[]> {
@@ -843,7 +957,15 @@ export class PawSQLTreeProvider
843957
}) {
844958
const result = await ApiService.getUserKey(config.email, config.password);
845959
if (!result) {
846-
throw Error("error.login.invalidCredentials");
960+
await vscode.workspace
961+
.getConfiguration("pawsql")
962+
.update("frontendUrl", "", true);
963+
964+
await vscode.workspace
965+
.getConfiguration("pawsql")
966+
.update("apiKey", "", true);
967+
968+
return;
847969
}
848970
const { apikey, frontendUrl } = result;
849971

src/i18n/zh-cn.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,8 @@
4545
"codelens.optimize.sql.with.default.workspace": "⚡Optimize",
4646
"codelens.optimize.sql.with.selected.workspace": "⚡Optimize in ...",
4747
"webview.anlysis.result.title": "SQL优化结果",
48-
"webview.settings.save.config.success": "保存成功",
49-
"webview.settings.save.config.failed": "保存配置失败",
48+
"webview.settings.save.config.success": "验证成功",
49+
"webview.settings.save.config.failed": "验证失败",
5050
"form.config.title": "PawSQL 配置",
5151
"form.config.email.label": "PawSQL 账号",
5252
"form.config.password.label": "密码",

src/webview/components/ConfigForm.tsx

Lines changed: 33 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React from "react";
1+
import React, { useEffect } from "react";
22
import {
33
TextField,
44
Button,
@@ -27,17 +27,22 @@ interface ConfigFormProps {
2727
getState: () => any;
2828
};
2929
initialConfig: Config;
30+
validateResult: boolean;
3031
onSubmit: (config: Config) => void;
32+
refresh: boolean;
3133
}
3234

3335
const ConfigForm: React.FC<ConfigFormProps> = ({
3436
vscode,
3537
initialConfig,
3638
onSubmit,
39+
validateResult,
40+
refresh,
3741
}) => {
3842
const defaultConfig = {
3943
...initialConfig,
4044
};
45+
const [initFlag, setInitFlag] = React.useState(false);
4146

4247
const [formState, setFormState] = React.useState<Config>(defaultConfig);
4348
const [snackbarOpen, setSnackbarOpen] = React.useState(false);
@@ -55,16 +60,16 @@ const ConfigForm: React.FC<ConfigFormProps> = ({
5560
vscode.postMessage({ command: "openLink", url });
5661
};
5762

58-
const handleSubmit = (event: React.FormEvent) => {
63+
const handleSubmit = async (event: React.FormEvent) => {
5964
event.preventDefault();
60-
61-
onSubmit(formState);
62-
setSnackbarMessage(
63-
formatMessage({ id: "webview.settings.save.config.success" })
64-
);
65-
setSnackbarSeverity("success");
66-
setSnackbarOpen(true);
65+
setInitFlag(true);
66+
await onSubmit(formState);
6767
};
68+
useEffect(() => {
69+
if (initFlag) {
70+
setSnackbarOpen(true);
71+
}
72+
}, [refresh]);
6873

6974
const handleInputChange = (event: React.ChangeEvent<HTMLInputElement>) => {
7075
const { name, value } = event.target;
@@ -217,23 +222,27 @@ const ConfigForm: React.FC<ConfigFormProps> = ({
217222
<FormattedMessage id="form.config.joinPawSQL" />
218223
</Button>
219224
</form>
220-
<Snackbar
221-
open={snackbarOpen}
222-
autoHideDuration={6000}
223-
onClose={() => setSnackbarOpen(false)}
224-
anchorOrigin={{ vertical: "bottom", horizontal: "center" }}
225-
>
226-
<Alert
225+
{snackbarOpen && (
226+
<Snackbar
227+
open={snackbarOpen}
228+
autoHideDuration={6000}
227229
onClose={() => setSnackbarOpen(false)}
228-
severity={snackbarSeverity}
229-
sx={{
230-
width: "100%",
231-
boxShadow: "0 2px 8px rgba(0, 0, 0, 0.15)",
232-
}}
230+
anchorOrigin={{ vertical: "bottom", horizontal: "center" }}
233231
>
234-
{snackbarMessage}
235-
</Alert>
236-
</Snackbar>
232+
<Alert
233+
onClose={() => setSnackbarOpen(false)}
234+
severity={validateResult ? "success" : "error"}
235+
sx={{
236+
width: "100%",
237+
boxShadow: "0 2px 8px rgba(0, 0, 0, 0.15)",
238+
}}
239+
>
240+
{validateResult
241+
? formatMessage({ id: "webview.settings.save.config.success" })
242+
: formatMessage({ id: "webview.settings.save.config.failed" })}
243+
</Alert>
244+
</Snackbar>
245+
)}
237246
</Container>
238247
);
239248
};

src/webview/index.tsx

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -29,22 +29,26 @@ const App: React.FC = () => {
2929
});
3030

3131
const [locale, setLocale] = React.useState<"en" | "zh-cn">("en"); // 使用字面量类型
32+
const [validateResult, setValidateResult] = React.useState<boolean>(false); // 使用字面量类型
33+
const [refresh, setRefresh] = React.useState(false);
3234

3335
const vscode = React.useMemo(() => {
3436
return window.acquireVsCodeApi();
3537
}, []);
3638

37-
const handleConfigSubmit = React.useCallback(
38-
(newConfig: Config) => {
39-
vscode.postMessage({
40-
command: "saveConfig",
41-
config: newConfig,
42-
});
43-
},
44-
[vscode]
45-
);
39+
const handleConfigSubmit = (newConfig: Config) => {
40+
vscode.postMessage({
41+
command: "saveConfig",
42+
config: newConfig,
43+
});
44+
};
4645

4746
React.useEffect(() => {
47+
// Request initial config
48+
console.log("Requesting initial config");
49+
vscode.postMessage({ command: "getConfig" });
50+
vscode.postMessage({ command: "getLanguage" });
51+
4852
const messageHandler = (event: MessageEvent) => {
4953
const message = event.data;
5054
console.log("Received message:", message);
@@ -58,6 +62,10 @@ const App: React.FC = () => {
5862
console.log("Updating config:", newConfig);
5963
setConfig(newConfig);
6064
}
65+
if (message.command === "validateConfig") {
66+
setRefresh((pre) => !pre);
67+
setValidateResult(message.validateResult as boolean);
68+
}
6169

6270
if (message.command === "languageResponse") {
6371
setLocale(message.locale);
@@ -66,11 +74,6 @@ const App: React.FC = () => {
6674

6775
window.addEventListener("message", messageHandler);
6876

69-
// Request initial config
70-
console.log("Requesting initial config");
71-
vscode.postMessage({ command: "getConfig" });
72-
vscode.postMessage({ command: "getLanguage" });
73-
7477
return () => {
7578
window.removeEventListener("message", messageHandler);
7679
};
@@ -80,8 +83,10 @@ const App: React.FC = () => {
8083
<IntlProvider locale={locale} messages={messages[locale]}>
8184
<div>
8285
<ConfigForm
86+
refresh={refresh}
8387
vscode={vscode}
8488
initialConfig={config}
89+
validateResult={validateResult}
8590
onSubmit={handleConfigSubmit}
8691
/>
8792
</div>

0 commit comments

Comments
 (0)