245 lines
5.1 KiB
Markdown
245 lines
5.1 KiB
Markdown
## 1.Architecture design
|
||
```mermaid
|
||
graph TD
|
||
U["User Browser"] --> F["Vue Frontend Application"]
|
||
F --> S["Backend API Service"]
|
||
S --> M["MySQL 8 Database"]
|
||
S --> P["SQLite (Metadata)"]
|
||
|
||
subgraph "Frontend Layer"
|
||
F
|
||
end
|
||
|
||
subgraph "Backend Layer"
|
||
S
|
||
end
|
||
|
||
subgraph "Data Layer"
|
||
M
|
||
end
|
||
|
||
subgraph "Service Layer (Provided by Supabase)"
|
||
P
|
||
end
|
||
```
|
||
|
||
## 2.Technology Description
|
||
- Frontend: Vue3 + Vite + TailwindCSS
|
||
- Backend: Go + Gin
|
||
- Auth: JWT(后端签发与校验)
|
||
- Metadata: SQLite(用户、题目、进度、用户数据库列表等)
|
||
- SQL Execution Engine: MySQL 8(用于模拟库与用户导入库的执行环境)
|
||
|
||
## 3.Route definitions
|
||
| Route | Purpose |
|
||
|-------|---------|
|
||
| /login | 登录/注册页 |
|
||
| / | 首页:题目分级列表、新手引导、继续练习 |
|
||
| /practice/:id | 练习页:SQL 编辑、运行、结果与校验 |
|
||
| /databases | 数据库管理:选择模拟库、导入自定义库、激活当前库 |
|
||
|
||
## 4.API definitions (If it includes backend services)
|
||
### 4.1 Core Types (TypeScript)
|
||
```ts
|
||
export type Level = 'beginner' | 'normal' | 'advanced'
|
||
|
||
export type ModuleKey = 'shop' | 'hr'
|
||
|
||
export type ActiveDatabase = {
|
||
id: string
|
||
name: string
|
||
source: 'mock' | 'imported'
|
||
schemaName: string
|
||
}
|
||
|
||
export type ExerciseSummary = {
|
||
id: string
|
||
title: string
|
||
level: Level
|
||
isSolved: boolean
|
||
}
|
||
|
||
export type ExecuteSqlRequest = {
|
||
exerciseId: string
|
||
sql: string
|
||
}
|
||
|
||
export type ExecuteSqlResponse = {
|
||
ok: boolean
|
||
durationMs: number
|
||
columns?: string[]
|
||
rows?: Array<Record<string, unknown>>
|
||
errorMessage?: string
|
||
verdict?: 'pass' | 'fail'
|
||
hint?: string
|
||
}
|
||
|
||
export type ImportDatabaseRequest = {
|
||
name: string
|
||
initSqlFileUrl: string
|
||
}
|
||
|
||
export type UserDatabase = {
|
||
id: string
|
||
name: string
|
||
source: 'mock' | 'imported'
|
||
createdAt: string
|
||
}
|
||
```
|
||
|
||
### 4.2 Core API
|
||
- 获取题目列表
|
||
```
|
||
GET /api/exercises?level=beginner|normal|advanced&query=...
|
||
```
|
||
|
||
- 获取题目详情(含描述与校验配置)
|
||
```
|
||
GET /api/exercises/:id
|
||
```
|
||
|
||
- 执行 SQL + 返回结果 + 判题
|
||
```
|
||
POST /api/sql/execute
|
||
```
|
||
Request: ExecuteSqlRequest
|
||
|
||
- 保存/更新进度(草稿 SQL、是否通过)
|
||
```
|
||
POST /api/progress/upsert
|
||
```
|
||
|
||
- 获取/切换当前激活数据库
|
||
```
|
||
GET /api/user-databases
|
||
POST /api/user-databases/activate
|
||
```
|
||
|
||
- 导入自定义数据库(先上传文件到 Storage,再触发导入)
|
||
```
|
||
POST /api/user-databases/import
|
||
```
|
||
Request: ImportDatabaseRequest
|
||
|
||
- 新手引导状态(是否已完成/已跳过)
|
||
```
|
||
GET /api/onboarding
|
||
POST /api/onboarding/complete
|
||
```
|
||
|
||
## 5.Server architecture diagram (If it includes backend services)
|
||
```mermaid
|
||
graph TD
|
||
A["Client / Frontend"] --> B["API Controller"]
|
||
B --> C["Practice Service (Execute + Judge)"]
|
||
B --> D["Exercise Service"]
|
||
B --> E["Database Import Service"]
|
||
C --> F["MySQL Repository"]
|
||
D --> G["SQLite Repository (Metadata)"]
|
||
E --> F
|
||
|
||
subgraph "Server"
|
||
B
|
||
C
|
||
D
|
||
E
|
||
F
|
||
G
|
||
end
|
||
```
|
||
|
||
## 6.Data model(if applicable)
|
||
### 6.1 Data model definition
|
||
(SQLite 用于题目/进度/用户库元数据;MySQL 用于实际运行 SQL 的数据面。)
|
||
|
||
```mermaid
|
||
erDiagram
|
||
PROFILE {
|
||
uuid id
|
||
text email
|
||
timestamptz created_at
|
||
}
|
||
EXERCISE {
|
||
uuid id
|
||
text title
|
||
text level
|
||
text prompt
|
||
text answer_sql
|
||
}
|
||
USER_PROGRESS {
|
||
uuid id
|
||
uuid user_id
|
||
uuid exercise_id
|
||
text draft_sql
|
||
bool is_solved
|
||
timestamptz updated_at
|
||
}
|
||
USER_DATABASE {
|
||
uuid id
|
||
uuid user_id
|
||
text name
|
||
text source
|
||
text mysql_schema_name
|
||
bool is_active
|
||
timestamptz created_at
|
||
}
|
||
```
|
||
|
||
### 6.2 Data Definition Language
|
||
Profile Table (profiles)
|
||
```
|
||
CREATE TABLE profiles (
|
||
id UUID PRIMARY KEY,
|
||
email TEXT,
|
||
created_at TIMESTAMPTZ DEFAULT NOW()
|
||
);
|
||
GRANT SELECT ON profiles TO anon;
|
||
GRANT ALL PRIVILEGES ON profiles TO authenticated;
|
||
```
|
||
|
||
Exercise Table (exercises)
|
||
```
|
||
CREATE TABLE exercises (
|
||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
title TEXT NOT NULL,
|
||
level TEXT NOT NULL CHECK (level IN ('beginner','normal','advanced')),
|
||
prompt TEXT NOT NULL,
|
||
answer_sql TEXT NOT NULL,
|
||
created_at TIMESTAMPTZ DEFAULT NOW()
|
||
);
|
||
GRANT SELECT ON exercises TO anon;
|
||
GRANT ALL PRIVILEGES ON exercises TO authenticated;
|
||
```
|
||
|
||
User Progress Table (user_progress)
|
||
```
|
||
CREATE TABLE user_progress (
|
||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
user_id UUID NOT NULL,
|
||
exercise_id UUID NOT NULL,
|
||
draft_sql TEXT,
|
||
is_solved BOOLEAN DEFAULT FALSE,
|
||
updated_at TIMESTAMPTZ DEFAULT NOW()
|
||
);
|
||
CREATE INDEX idx_user_progress_user_id ON user_progress(user_id);
|
||
CREATE INDEX idx_user_progress_exercise_id ON user_progress(exercise_id);
|
||
GRANT SELECT ON user_progress TO anon;
|
||
GRANT ALL PRIVILEGES ON user_progress TO authenticated;
|
||
```
|
||
|
||
User Database Table (user_databases)
|
||
```
|
||
CREATE TABLE user_databases (
|
||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
user_id UUID NOT NULL,
|
||
name TEXT NOT NULL,
|
||
source TEXT NOT NULL CHECK (source IN ('mock','imported')),
|
||
mysql_schema_name TEXT NOT NULL,
|
||
is_active BOOLEAN DEFAULT FALSE,
|
||
created_at TIMESTAMPTZ DEFAULT NOW()
|
||
);
|
||
CREATE INDEX idx_user_databases_user_id ON user_databases(user_id);
|
||
GRANT SELECT ON user_databases TO anon
|
||
```
|
||
|