Files
范智鹏 805737fcfc feat: 设置面板 + Provider 扩展 + 构建脚本
- 设置面板:三步引导 / AI 配置 / API Key / 规则管理 / 连接测试
- Provider 重构:统一 OpenAICompatibleProvider 基类,新增 Gemini/Claude/混元/智谱等
- 审查面板 Webview:三 Tab、统计卡片、问题列表、postMessage 通信
- esbuild 构建脚本 + 生产打包 + PMD 下载
- 保存文件自动静态分析(500ms debounce)
2026-07-16 22:20:30 +08:00

207 lines
5.4 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Step 01 — Phase 1: 基础层
**依赖**: 无
**参考设计**: §3.2, §6.4, §13.2
## 目标
建立公共类型定义和配置管理,为所有上层模块提供基础能力。
## 新建文件
| # | 文件 | 说明 |
|---|------|------|
| 1 | `src/types.ts` | 公共类型定义 |
| 2 | `src/config/ai.ts` | AI 配置 getter |
| 3 | `src/config/linter.ts` | Linter 配置 getter |
| 4 | `src/config/fixer.ts` | 修复器配置 getter |
| 5 | `src/config/secret.ts` | API Key SecretStorage |
| 6 | `src/config/index.ts` | 统一导出 |
---
## 1. `src/types.ts`
```typescript
import * as vscode from 'vscode';
export type Severity = 'error' | 'warning' | 'info';
export type AdapterStatus = 'ok' | 'tool-unavailable' | 'execution-failed';
export interface LinterDiagnostic {
severity: Severity;
ruleId: string;
message: string;
range: vscode.Range;
suggestion?: string;
}
export interface AdapterResult {
diagnostics: LinterDiagnostic[];
status: AdapterStatus;
errorMessage?: string;
}
export interface LinterAdapter {
id: string;
supportedLanguages: string[];
check(document: vscode.TextDocument, workingDir: string): Promise<AdapterResult>;
isAvailable(): boolean;
}
```
---
## 2. `src/config/ai.ts`
```typescript
import * as vscode from 'vscode';
export interface AIConfig {
provider: string;
model: string;
baseUrl: string;
temperature: number;
timeout: number;
outputLanguage: string;
}
export function getAIConfig(): AIConfig {
const config = vscode.workspace.getConfiguration('vscode-code-reviewer');
return {
provider: config.get<string>('ai.provider', 'deepseek'),
model: config.get<string>('ai.model', 'deepseek-chat'),
baseUrl: config.get<string>('ai.baseUrl', 'https://api.deepseek.com/v1'),
temperature: config.get<number>('ai.temperature', 0.2),
timeout: config.get<number>('ai.timeout', 300),
outputLanguage: config.get<string>('ai.outputLanguage', 'zh-CN'),
};
}
```
**配置 Key**(前缀 `vscode-code-reviewer.`:
| Key | 类型 | 默认值 |
|-----|------|--------|
| `ai.provider` | enum | `deepseek` |
| `ai.model` | string | `deepseek-chat` |
| `ai.baseUrl` | string | `https://api.deepseek.com/v1` |
| `ai.temperature` | number | 0.2 |
| `ai.timeout` | number | 300 |
| `ai.outputLanguage` | string | `zh-CN` |
---
## 3. `src/config/linter.ts`
```typescript
import * as vscode from 'vscode';
export interface LinterConfig {
languageMap: Record<string, string>;
pmdJarPath: string;
pmdRulesetPath: string;
pmdJspRulesetPath: string;
sqlLintConfigFile: string;
}
export function getLinterConfig(): LinterConfig {
const config = vscode.workspace.getConfiguration('vscode-code-reviewer');
return {
languageMap: {
javascript: config.get<string>('linters.javascript', 'eslint'),
typescript: config.get<string>('linters.typescript', 'eslint'),
java: config.get<string>('linters.java', 'pmd'),
jsp: config.get<string>('linters.jsp', 'jsp'),
css: config.get<string>('linters.css', 'stylelint'),
sql: config.get<string>('linters.sql', 'sql-lint'),
plsql: config.get<string>('linters.plsql', 'sql-lint'),
},
pmdJarPath: config.get<string>('pmd.jarPath', ''),
pmdRulesetPath: config.get<string>('pmd.rulesetPath', ''),
pmdJspRulesetPath: config.get<string>('pmd.jspRulesetPath', ''),
sqlLintConfigFile: config.get<string>('sql-lint.configFile', ''),
};
}
```
| Key | 类型 | 默认值 | enum |
|-----|------|--------|------|
| `linters.javascript` | enum | `eslint` | `""` / `eslint` |
| `linters.typescript` | enum | `eslint` | `""` / `eslint` |
| `linters.java` | enum | `pmd` | `""` / `pmd` |
| `linters.jsp` | enum | `jsp` | `""` / `jsp` |
| `linters.css` | enum | `stylelint` | `""` / `stylelint` |
| `linters.sql` | enum | `sql-lint` | `""` / `sql-lint` |
| `linters.plsql` | enum | `sql-lint` | `""` / `sql-lint` |
| `pmd.jarPath` | string | `""` | — |
| `pmd.rulesetPath` | string | `""` | — |
| `pmd.jspRulesetPath` | string | `""` | — |
| `sql-lint.configFile` | string | `""` | — |
---
## 4. `src/config/fixer.ts`
```typescript
import * as vscode from 'vscode';
export interface FixerConfig {
contextLines: number;
}
export function getFixerConfig(): FixerConfig {
const config = vscode.workspace.getConfiguration('vscode-code-reviewer');
return {
contextLines: config.get<number>('fixer.contextLines', 5),
};
}
```
---
## 5. `src/config/secret.ts`
```typescript
import * as vscode from 'vscode';
const SECRET_KEY = 'vscode-code-reviewer.apiKey';
export async function getApiKey(context: vscode.ExtensionContext): Promise<string | undefined> {
return context.secrets.get(SECRET_KEY);
}
export async function setApiKey(context: vscode.ExtensionContext, key: string): Promise<void> {
await context.secrets.store(SECRET_KEY, key);
}
export async function deleteApiKey(context: vscode.ExtensionContext): Promise<void> {
await context.secrets.delete(SECRET_KEY);
}
export async function isApiKeyConfigured(context: vscode.ExtensionContext): Promise<boolean> {
const key = await getApiKey(context);
return !!key;
}
```
---
## 6. `src/config/index.ts`
```typescript
export { getAIConfig, AIConfig } from './ai';
export { getLinterConfig, LinterConfig } from './linter';
export { getFixerConfig, FixerConfig } from './fixer';
export { getApiKey, setApiKey, deleteApiKey, isApiKeyConfigured } from './secret';
```
---
## 验收
- [ ] 6 个文件创建完成
- [ ] `npm run compile` 通过
- [ ] `npm run lint` 通过