1.0.0 初始版
This commit is contained in:
211
src/apiClient.ts
Normal file
211
src/apiClient.ts
Normal file
@@ -0,0 +1,211 @@
|
||||
import * as vscode from 'vscode';
|
||||
import * as http from 'http';
|
||||
import * as https from 'https';
|
||||
|
||||
// API 响应接口
|
||||
interface ApiResponse<T> {
|
||||
Data: T;
|
||||
IsError: boolean;
|
||||
Msg: string | null;
|
||||
}
|
||||
|
||||
// 获取文件列表响应
|
||||
interface FileListResponse {
|
||||
Data: string[];
|
||||
IsError: boolean;
|
||||
Msg: string | null;
|
||||
}
|
||||
|
||||
// 获取文件内容响应
|
||||
interface FileContentResponse {
|
||||
Data: {
|
||||
FileContentData: { [key: string]: string };
|
||||
};
|
||||
IsError: boolean;
|
||||
Msg: string | null;
|
||||
}
|
||||
|
||||
export class ApiClient {
|
||||
private baseUrl: string;
|
||||
private port: number;
|
||||
|
||||
constructor(baseUrl: string = 'http://localhost', port: number = 8080) {
|
||||
this.baseUrl = baseUrl;
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
private getFullUrl(endpoint: string): string {
|
||||
return `${this.baseUrl}:${this.port}${endpoint}`;
|
||||
}
|
||||
|
||||
// 通用的 HTTP 请求方法
|
||||
private async request(url: string, method: string = 'GET', body?: string, headers: Record<string, string> = {}): Promise<any> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const urlObj = new URL(url);
|
||||
const isHttps = urlObj.protocol === 'https:';
|
||||
const client = isHttps ? https : http;
|
||||
|
||||
const options: http.RequestOptions = {
|
||||
hostname: urlObj.hostname,
|
||||
port: urlObj.port || (isHttps ? 443 : 80),
|
||||
path: urlObj.pathname + urlObj.search,
|
||||
method: method,
|
||||
headers: {
|
||||
'User-Agent': 'VSCode-Squirrel-NUT-Explorer/1.0',
|
||||
...headers
|
||||
}
|
||||
};
|
||||
|
||||
console.log(`HTTP请求: ${method} ${url}`);
|
||||
console.log(`请求选项:`, options);
|
||||
|
||||
const req = client.request(options, (res) => {
|
||||
let data = '';
|
||||
|
||||
console.log(`响应状态码: ${res.statusCode}`);
|
||||
console.log(`响应头:`, res.headers);
|
||||
|
||||
res.on('data', (chunk) => {
|
||||
data += chunk;
|
||||
});
|
||||
|
||||
res.on('end', () => {
|
||||
console.log(`原始响应数据长度: ${data.length}`);
|
||||
console.log(`原始响应数据: ${data}`);
|
||||
|
||||
if (res.statusCode !== 200) {
|
||||
reject(new Error(`HTTP ${res.statusCode}: ${res.statusMessage}`));
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
if (!data || data.trim() === '') {
|
||||
reject(new Error('响应为空'));
|
||||
return;
|
||||
}
|
||||
const result = JSON.parse(data);
|
||||
resolve(result);
|
||||
} catch (error) {
|
||||
reject(new Error(`解析JSON响应失败: ${error}。原始数据: ${data}`));
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
req.on('error', (error) => {
|
||||
console.error(`请求错误: ${error.message}`);
|
||||
reject(new Error(`请求失败: ${error.message}`));
|
||||
});
|
||||
|
||||
req.setTimeout(10000, () => {
|
||||
console.error('请求超时');
|
||||
req.destroy();
|
||||
reject(new Error('请求超时'));
|
||||
});
|
||||
|
||||
if (body) {
|
||||
console.log(`请求体长度: ${body.length}`);
|
||||
req.write(body);
|
||||
}
|
||||
|
||||
req.end();
|
||||
});
|
||||
}
|
||||
|
||||
// 获取 nut 文件列表
|
||||
async getFileList(dirName: string = 'sqr', fileType: string = 'nut'): Promise<string> {
|
||||
try {
|
||||
const url = this.getFullUrl('/Api/PvfUtiltiy/GetFileList');
|
||||
const params = new URLSearchParams({
|
||||
dirName,
|
||||
returnType: '1',
|
||||
fileType
|
||||
});
|
||||
|
||||
const fullUrl = `${url}?${params}`;
|
||||
console.log(`请求URL: ${fullUrl}`);
|
||||
|
||||
const result = await this.request(fullUrl) as { Data: string; IsError: boolean; Msg: string | null };
|
||||
|
||||
if (result.IsError) {
|
||||
throw new Error(result.Msg || '获取文件列表失败');
|
||||
}
|
||||
|
||||
return result.Data;
|
||||
} catch (error) {
|
||||
vscode.window.showErrorMessage(`获取文件列表失败: ${error}`);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
// 批量获取文件内容
|
||||
async getFileContents(filePaths: string[], encodingType: string | null = null): Promise<{ [key: string]: string }> {
|
||||
try {
|
||||
const url = this.getFullUrl('/Api/PvfUtiltiy/GetFileContents');
|
||||
|
||||
const requestBody = {
|
||||
FileList: filePaths,
|
||||
UseCompatibleDecompiler: false,
|
||||
EncodingType: encodingType
|
||||
};
|
||||
|
||||
const result = await this.request(url, 'POST', JSON.stringify(requestBody), {
|
||||
'Content-Type': 'application/json'
|
||||
}) as FileContentResponse;
|
||||
|
||||
if (result.IsError) {
|
||||
throw new Error(result.Msg || '获取文件内容失败');
|
||||
}
|
||||
|
||||
return result.Data.FileContentData;
|
||||
} catch (error) {
|
||||
vscode.window.showErrorMessage(`获取文件内容失败: ${error}`);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
// 上传文件内容
|
||||
async uploadFileContent(filePath: string, content: string): Promise<boolean> {
|
||||
try {
|
||||
const url = this.getFullUrl(`/Api/PvfUtiltiy/ImportFile?filePath=${encodeURIComponent(filePath)}`);
|
||||
|
||||
const result = await this.request(url, 'POST', content, {
|
||||
'Content-Type': 'text/plain; charset=utf-8',
|
||||
});
|
||||
|
||||
if (result.IsError) {
|
||||
throw new Error(result.Msg || '上传文件失败');
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (error) {
|
||||
vscode.window.showErrorMessage(`上传文件失败: ${error}`);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
// 获取 pvfUtility 版本号
|
||||
async getVersion(): Promise<string> {
|
||||
try {
|
||||
const url = this.getFullUrl('/Api/PvfUtiltiy/getVersion');
|
||||
console.log(`版本检查URL: ${url}`);
|
||||
|
||||
const result = await this.request(url) as { Data: string; IsError: boolean; Msg: string | null };
|
||||
|
||||
if (result.IsError) {
|
||||
throw new Error(result.Msg || '获取版本号失败');
|
||||
}
|
||||
|
||||
return result.Data;
|
||||
} catch (error) {
|
||||
console.error('获取版本号失败:', error);
|
||||
vscode.window.showErrorMessage(`获取 pvfUtility 版本号失败: ${error}`);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
// 更新配置
|
||||
updateConfig(baseUrl: string, port: number) {
|
||||
this.baseUrl = baseUrl;
|
||||
this.port = port;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user