feat: initial commit - Phase 1 & 2 core features

This commit is contained in:
hiderfong
2026-04-22 17:07:33 +08:00
commit 1773bda06b
25005 changed files with 6252106 additions and 0 deletions
+3
View File
@@ -0,0 +1,3 @@
from app.schemas.auth import Token, TokenRefresh, LoginRequest
from app.schemas.user import UserCreate, UserUpdate, UserOut, RoleOut, DeptOut, DeptTree
from app.schemas.common import ResponseModel, ListResponse, PageParams
+17
View File
@@ -0,0 +1,17 @@
from pydantic import BaseModel
class LoginRequest(BaseModel):
username: str
password: str
class Token(BaseModel):
access_token: str
refresh_token: str
token_type: str = "bearer"
expires_in: int
class TokenRefresh(BaseModel):
refresh_token: str
+102
View File
@@ -0,0 +1,102 @@
from typing import Optional, List
from pydantic import BaseModel, Field
from datetime import datetime
class CategoryBase(BaseModel):
parent_id: Optional[int] = None
level: int = 1
code: str = Field(..., max_length=50)
name: str = Field(..., max_length=100)
description: Optional[str] = None
sort_order: int = 0
class CategoryCreate(CategoryBase):
pass
class CategoryUpdate(BaseModel):
parent_id: Optional[int] = None
code: Optional[str] = Field(None, max_length=50)
name: Optional[str] = Field(None, max_length=100)
description: Optional[str] = None
sort_order: Optional[int] = None
class CategoryOut(CategoryBase):
id: int
created_at: datetime
class Config:
from_attributes = True
class CategoryTree(CategoryOut):
children: List["CategoryTree"] = []
class DataLevelOut(BaseModel):
id: int
code: str
name: str
description: Optional[str] = None
color: str
control_requirements: Optional[dict] = None
sort_order: int
class Config:
from_attributes = True
class RecognitionRuleBase(BaseModel):
template_id: int
category_id: Optional[int] = None
level_id: Optional[int] = None
rule_type: str = Field(..., max_length=20) # regex, keyword, enum
rule_name: Optional[str] = Field(None, max_length=100)
rule_content: str
target_field: str = Field(default="column_name", max_length=20)
priority: int = 100
is_active: bool = True
class RecognitionRuleCreate(RecognitionRuleBase):
pass
class RecognitionRuleUpdate(BaseModel):
category_id: Optional[int] = None
level_id: Optional[int] = None
rule_type: Optional[str] = Field(None, max_length=20)
rule_name: Optional[str] = Field(None, max_length=100)
rule_content: Optional[str] = None
target_field: Optional[str] = Field(None, max_length=20)
priority: Optional[int] = None
is_active: Optional[bool] = None
class RecognitionRuleOut(RecognitionRuleBase):
id: int
hit_count: int
created_at: datetime
category_name: Optional[str] = None
level_name: Optional[str] = None
level_color: Optional[str] = None
class Config:
from_attributes = True
class TemplateOut(BaseModel):
id: int
name: str
industry_type: str
version: str
description: Optional[str] = None
is_builtin: bool
is_active: bool
created_at: datetime
class Config:
from_attributes = True
+25
View File
@@ -0,0 +1,25 @@
from typing import Generic, TypeVar, Optional, List
from pydantic import BaseModel, Field
T = TypeVar("T")
class ResponseModel(BaseModel, Generic[T]):
code: int = 200
message: str = "success"
data: Optional[T] = None
class ListResponse(BaseModel, Generic[T]):
code: int = 200
message: str = "success"
data: List[T] = []
total: int = 0
page: int = 1
page_size: int = 20
class PageParams(BaseModel):
page: int = Field(1, ge=1)
page_size: int = Field(20, ge=1, le=500)
keyword: Optional[str] = None
+51
View File
@@ -0,0 +1,51 @@
from typing import Optional
from pydantic import BaseModel, Field
from datetime import datetime
class DataSourceBase(BaseModel):
name: str = Field(..., max_length=100)
source_type: str = Field(..., max_length=50)
host: Optional[str] = Field(None, max_length=200)
port: Optional[int] = None
database_name: Optional[str] = Field(None, max_length=100)
username: Optional[str] = Field(None, max_length=100)
extra_params: Optional[str] = None
status: Optional[str] = "active"
dept_id: Optional[int] = None
class DataSourceCreate(DataSourceBase):
password: Optional[str] = None
class DataSourceUpdate(BaseModel):
name: Optional[str] = Field(None, max_length=100)
source_type: Optional[str] = Field(None, max_length=50)
host: Optional[str] = Field(None, max_length=200)
port: Optional[int] = None
database_name: Optional[str] = Field(None, max_length=100)
username: Optional[str] = Field(None, max_length=100)
password: Optional[str] = None
extra_params: Optional[str] = None
dept_id: Optional[int] = None
class DataSourceOut(DataSourceBase):
id: int
created_by: Optional[int] = None
created_at: datetime
updated_at: datetime
class Config:
from_attributes = True
class DataSourceTest(BaseModel):
source_type: str
host: Optional[str] = None
port: Optional[int] = None
database_name: Optional[str] = None
username: Optional[str] = None
password: Optional[str] = None
extra_params: Optional[str] = None
+51
View File
@@ -0,0 +1,51 @@
from typing import Optional, List
from pydantic import BaseModel
from datetime import datetime
class DatabaseOut(BaseModel):
id: int
source_id: int
name: str
charset: Optional[str] = None
table_count: int = 0
created_at: datetime
class Config:
from_attributes = True
class DataTableOut(BaseModel):
id: int
database_id: int
name: str
comment: Optional[str] = None
row_count: int = 0
column_count: int = 0
created_at: datetime
class Config:
from_attributes = True
class DataColumnOut(BaseModel):
id: int
table_id: int
name: str
data_type: Optional[str] = None
length: Optional[int] = None
comment: Optional[str] = None
is_nullable: bool = True
sample_data: Optional[str] = None
created_at: datetime
class Config:
from_attributes = True
class MetadataTreeNode(BaseModel):
id: int
name: str
type: str # source, database, table, column
children: Optional[List["MetadataTreeNode"]] = None
meta: Optional[dict] = None
+61
View File
@@ -0,0 +1,61 @@
from typing import Optional, List
from pydantic import BaseModel, EmailStr
from datetime import datetime
class RoleOut(BaseModel):
id: int
name: str
code: str
description: Optional[str] = None
class Config:
from_attributes = True
class DeptOut(BaseModel):
id: int
name: str
parent_id: Optional[int] = None
sort_order: int = 0
class Config:
from_attributes = True
class DeptTree(DeptOut):
children: List["DeptTree"] = []
class UserBase(BaseModel):
username: str
email: Optional[str] = None
real_name: Optional[str] = None
phone: Optional[str] = None
dept_id: Optional[int] = None
is_active: bool = True
class UserCreate(UserBase):
password: str
role_ids: List[int] = []
class UserUpdate(BaseModel):
email: Optional[str] = None
real_name: Optional[str] = None
phone: Optional[str] = None
dept_id: Optional[int] = None
is_active: Optional[bool] = None
role_ids: Optional[List[int]] = None
class UserOut(UserBase):
id: int
is_superuser: bool
created_at: datetime
dept: Optional[DeptOut] = None
roles: List[RoleOut] = []
class Config:
from_attributes = True