Files
xiaocai/docs/class-diagram.mermaid
wangxiaogang 61f9b33f8c feat(iter-v2): T01 partial - TOKEN_SECRET check, SQL param, export credential, docs
- S2: logs.ts LIMIT/OFFSET SQL parameterization (? placeholders)
- S3: checkTokenSecret() startup validation, JWT_SECRET→TOKEN_SECRET in backup.ts
- S3: Access Token expiry shortened to 2h (from 30d)
- S4: Export download uses HMAC signed short-term token (/prepare endpoint)
- S4: Frontend export.ts adapted for prepare-then-download flow
- .env.example reorganized with security notes
- Added PRD and architecture docs for iteration v2
2026-06-11 08:58:24 +08:00

213 lines
5.3 KiB
Plaintext

classDiagram
direction TB
class TokenConfig {
+TOKEN_SECRET: string
+ACCESS_TOKEN_EXPIRY: number
+REFRESH_TOKEN_EXPIRY: number
}
class AuthMiddleware {
+authMiddleware(req, res, next): void
-verifyHmacToken(token): userId
-isTokenExpired(timestamp): boolean
}
class AuthRoute {
+POST /login: LoginResult
+POST /demo-login: LoginResult
+POST /refresh: RefreshResult
-signToken(userId): string
-generateRefreshToken(userId): string
-hashToken(token): string
-autoSetAdmin(userId): void
}
class LoginResult {
+accessToken: string
+refreshToken: string
+expiresIn: number
+userId: number
+nickname: string
+avatar_url: string
+role: string
}
class RefreshResult {
+accessToken: string
+refreshToken: string
+expiresIn: number
}
class RefreshTokenRow {
+id: number
+user_id: number
+token_hash: string
+expires_at: Date
+revoked_at: Date|null
+created_at: Date
}
class DownloadTokenRow {
+id: number
+token: string
+user_id: number
+resource_type: string
+resource_id: string
+expires_at: Date
+used_at: Date|null
+created_at: Date
}
class DownloadTokenRoute {
+POST /download-tokens: GenerateDownloadToken
+GET /download/:token: FileStream
-validateToken(token): DownloadTokenRow
-markUsed(tokenId): void
-cleanupExpired(): void
}
class AdminRoute {
+GET /dashboard: DashboardData
+GET /users: UserList
+PUT /users/:id/status: void
+DELETE /users/:id: void~~软删除
+POST /users/:id/restore: void~~恢复
}
class UserRow {
+id: number
+openid: string
+nickname: string
+avatar_url: string
+role: string
+deleted_at: Date|null
+created_at: Date
}
class ManageListComponent {
+items: T[]
+displayField: string
+colorField: string
+showDrag: boolean
+showEdit: boolean
+showDelete: boolean
+emptyText: string
+emit_add(): void
+emit_edit(item): void
+emit_delete(item): void
+emit_sort(ids): void
}
class ColorPickerComponent {
+modelValue: string
+colors: string[]
+emit_update:modelValue(color): void
}
class EditModalComponent {
+visible: boolean
+title: string
+fields: EditField[]
+emit_confirm(data): void
}
class SnackbarComponent {
+message: string
+actionText: string
+duration: number
+visible: boolean
+emit_action(): void
+show(msg, action): void
+hide(): void
}
class OfflineQueue {
-pendingOps: PendingOp[]
-isProcessing: boolean
+enqueue(op): void
+dequeue(id): void
+processPendingOps(): Promise~void~
+isOnline(): boolean
+startNetworkListener(): void
}
class PendingOp {
+id: string
+type: string
+data: object
+createdAt: number
+status: string
}
class SchedulerService {
+start(): void
+stop(): void
-weeklyReportCron(): void
-monthlyReportCron(): void
-dailyBudgetScanCron(): void
}
class ReportService {
+generateWeeklyReport(userId): WeeklyReport
+generateMonthlyReport(userId): MonthlyReport
-queryPeriodData(userId, start, end): PeriodData
}
class BudgetAlertService {
+checkBudgetAlert(userId, month): void
-calculateUsageRatio(userId, month): number
-sendNotification(userId, level): void
-sendWechatMessage(userId, level): void
-hasAlerted(userId, month, level): boolean
}
class WechatSubscribeService {
+sendMessage(userId, templateId, data): void
-getAccessToken(): string
}
class BudgetAlertRow {
+id: number
+user_id: number
+month: string
+level: string
+group_id: number|null
+created_at: Date
}
class UserSettings {
+user_id: number
+report_push_enabled: boolean
+updated_at: Date
}
class StatsRoute {
+GET /overview: Overview
+GET /category: CategoryStat[]
+GET /trend: TrendPoint[]
+GET /dashboard: DashboardData
-buildWhereClause(userId, groupId): WhereResult
}
class DashboardData {
+overview: Overview
+category: CategoryStat[]
+trend: TrendPoint[]
}
TokenConfig <-- AuthMiddleware : uses
TokenConfig <-- AuthRoute : uses
AuthRoute --> LoginResult : returns
AuthRoute --> RefreshResult : returns
AuthRoute --> RefreshTokenRow : creates/revokes
DownloadTokenRoute --> DownloadTokenRow : creates/validates
AdminRoute --> UserRow : soft deletes
SchedulerService --> ReportService : triggers
SchedulerService --> BudgetAlertService : triggers
ReportService --> WechatSubscribeService : uses
BudgetAlertService --> WechatSubscribeService : uses
BudgetAlertService --> BudgetAlertRow : creates
BudgetAlertService --> UserSettings : checks
StatsRoute --> DashboardData : returns