237 lines
9.3 KiB
Markdown
237 lines
9.3 KiB
Markdown
# 架构设计
|
||
|
||
## 总览
|
||
|
||
```text
|
||
main.go
|
||
├─ Wails application
|
||
├─ embedded frontend/dist
|
||
├─ embedded frontend/src/locales/*.json
|
||
└─ services
|
||
├─ AppService
|
||
├─ AppConfigService
|
||
├─ HotkeyService
|
||
├─ SystemInfo
|
||
├─ OCRService # 当前存量示例
|
||
├─ AuthService # 已实现 provider 边界
|
||
├─ AuditLogService # 已实现审计日志边界
|
||
├─ AppLogService # 已实现运行日志边界
|
||
├─ ImageOptimizationService # 已实现本地模拟任务模型
|
||
└─ MetricsService # 已实现 P0 统计聚合
|
||
|
||
frontend/src
|
||
├─ router
|
||
├─ layouts
|
||
├─ pages
|
||
├─ components
|
||
├─ modules
|
||
├─ utils
|
||
└─ locales
|
||
```
|
||
|
||
前端通过 `frontend/bindings` 调用 Wails 暴露的 Go 服务。后端服务访问本地 SQLite、平台热键、文件系统、真实后端或 AI provider。
|
||
|
||
## 后端边界
|
||
|
||
- `main.go`:只负责应用组装、资源嵌入、服务注册和启动。
|
||
- `internal/models/`:定义数据库和服务返回的结构体。
|
||
- `internal/services/store.go`:负责 SQLite 连接、迁移和基础读写。
|
||
- `internal/services/appservice.go`:负责窗口、托盘、语言资源和应用生命周期。
|
||
- `internal/services/appconfig_service.go`:负责配置读写的 Wails 服务边界。
|
||
- `internal/services/settings_schema.go`:集中定义设置模块 schema、默认值、选项和初始化 SQL。
|
||
- `internal/services/hotkey_service.go`:负责热键读取、更新和重新注册。
|
||
- `internal/services/ocr_service.go`:当前 OCR 存量示例,后续可演进为图片 AI 能力的一部分。
|
||
- `internal/services/image_optimization_service.go`:负责商品图片 AI 优化任务、结果和本地模拟 provider。
|
||
- `internal/services/log_service.go`:负责审计日志和运行日志的记录、查询和共享写入 helper。
|
||
- `internal/services/metrics_service.go`:负责 P0 统计指标和趋势聚合。
|
||
- `platform/`:隔离 Windows / macOS 热键和系统能力差异。
|
||
|
||
已实现边界:
|
||
|
||
- `AuthService`:登录、退出、会话读取;内部通过 `AuthProvider` 接入本地固定账号或真实后端。当前 `LocalAuthProvider` 可用,`RemoteAuthProvider` 保留边界并返回未配置错误。
|
||
- `AppConfigService`:通过统一设置 schema 初始化和校验主题、语言、窗口行为、快捷键展示、数据目录、日志策略和登录配置。
|
||
- `ImageOptimizationService`:商品图片 AI 优化任务模型和本地模拟任务创建已可用,页面已接入任务创建、列表和结果预览。
|
||
- `AuditLogService`:审计日志记录和查询已可用,登录、设置变更和图片任务创建会写审计日志。
|
||
- `AppLogService`:运行日志记录和查询已可用,图片任务创建失败和服务错误会写运行日志。
|
||
- `MetricsService`:P0 统计指标和最近 N 天趋势已可查询,当前直接聚合 `image_tasks` 和 `audit_logs`。
|
||
|
||
服务之间不要互相绕过边界直接操作平台实现。新增平台能力时,优先放在 `platform/`,再由 `internal/services/` 暴露稳定方法。
|
||
|
||
## 前端边界
|
||
|
||
- `frontend/src/router/index.ts`:维护页面路由。
|
||
- `frontend/src/layouts/`:目标目录,放登录布局和主应用布局。
|
||
- `frontend/src/modules/auth/`:目标目录,放登录页面、会话状态和 provider 调用。
|
||
- `frontend/src/modules/settings/`:目标目录,放设置页和设置项。
|
||
- `frontend/src/modules/image-optimizer/`:放已接入的商品图片 AI 优化样例页面。
|
||
- `frontend/src/modules/logs/`:目标目录,放审计日志和运行日志页面。
|
||
- `frontend/src/modules/statistics/`:放统计卡片和趋势图。
|
||
- `frontend/src/modules/components-demo/`:目标目录,放常用组件示例。
|
||
- `frontend/src/components/template/`:放当前模块占位页共享壳。
|
||
- `frontend/src/components/`:通用展示组件和组合控件。
|
||
- `frontend/src/utils/`:国际化、主题、OS、热键等工具函数。
|
||
- `frontend/bindings/`:由 Wails 生成或按 Wails 合约维护,不写业务逻辑。
|
||
|
||
## 登录架构
|
||
|
||
登录已经通过 provider 边界实现:
|
||
|
||
```text
|
||
AuthService
|
||
└─ AuthProvider
|
||
├─ LocalAuthProvider
|
||
└─ RemoteAuthProvider
|
||
```
|
||
|
||
- `LocalAuthProvider`:用于模板演示和离线模式,固定账号密码由后端配置或安全哈希保存,不写死在前端。
|
||
- `RemoteAuthProvider`:用于真实后端,负责请求登录接口并保存 token / session;当前只保留接口边界并返回未配置错误。
|
||
- 前端只关心登录、退出和当前会话,不关心 provider 细节。
|
||
- 默认本地账号由 `appconfig` 初始化,用户名为 `admin`,默认密码为 `admin123`,密码以 salt + SHA-256 hash 形式保存。
|
||
- 登录成功、失败和退出会写入 `audit_logs`。
|
||
|
||
## 日志架构
|
||
|
||
审计日志和运行日志分开:
|
||
|
||
- 审计日志:记录用户可解释动作,支持查询、筛选和导出。
|
||
- 运行日志:记录系统错误和排错信息,支持按时间、级别、模块查看。
|
||
|
||
审计日志用于“责任链”,运行日志用于“故障定位”。不要用一张表混合两种语义。
|
||
|
||
## 数据模型
|
||
|
||
SQLite 数据库位于用户配置目录下的 `cmbone/cmbone.db`,不进入 git。
|
||
|
||
当前核心表:
|
||
|
||
```sql
|
||
hotkeys(
|
||
id INTEGER PRIMARY KEY,
|
||
keycode INTEGER,
|
||
modifiers INTEGER,
|
||
description TEXT,
|
||
target TEXT
|
||
)
|
||
```
|
||
|
||
```sql
|
||
appconfig(
|
||
id INTEGER PRIMARY KEY,
|
||
key TEXT,
|
||
type TEXT,
|
||
value TEXT,
|
||
description TEXT,
|
||
state INTEGER
|
||
)
|
||
```
|
||
|
||
当前 `appconfig` 默认配置由统一设置 schema 生成:
|
||
|
||
- `theme.mode`、`language`
|
||
- `window.start_state`、`window.width`、`window.height`、`window.remember_state`
|
||
- `shortcut.open_second_window`、`shortcut.open_main_window`
|
||
- `data.root_mode`、`data.custom_directory`
|
||
- `logs.level`、`logs.audit_retention_days`、`logs.app_retention_days`
|
||
- `auth.provider`、`auth.local.username`、`auth.local.password_salt`、`auth.local.password_hash`
|
||
|
||
```sql
|
||
auth_sessions(
|
||
id INTEGER PRIMARY KEY,
|
||
user_id TEXT,
|
||
username TEXT,
|
||
provider TEXT,
|
||
token TEXT,
|
||
created_at TEXT,
|
||
expires_at TEXT,
|
||
active INTEGER
|
||
)
|
||
```
|
||
|
||
```sql
|
||
audit_logs(
|
||
id INTEGER PRIMARY KEY,
|
||
actor TEXT,
|
||
action TEXT,
|
||
target_type TEXT,
|
||
target_id TEXT,
|
||
detail TEXT,
|
||
created_at TEXT
|
||
)
|
||
```
|
||
|
||
```sql
|
||
image_tasks(
|
||
id INTEGER PRIMARY KEY,
|
||
source_path TEXT,
|
||
status TEXT,
|
||
operation TEXT,
|
||
duration_ms INTEGER,
|
||
error_message TEXT,
|
||
created_at DATETIME,
|
||
updated_at DATETIME
|
||
)
|
||
```
|
||
|
||
```sql
|
||
image_task_results(
|
||
id INTEGER PRIMARY KEY,
|
||
task_id INTEGER,
|
||
output_path TEXT,
|
||
before_size INTEGER,
|
||
after_size INTEGER,
|
||
created_at DATETIME
|
||
)
|
||
```
|
||
|
||
当前 `image_tasks` 和 `image_task_results` 已由 `T-020` 落地,用于本地模拟图片优化任务和后续统计聚合。
|
||
|
||
```sql
|
||
app_logs(
|
||
id INTEGER PRIMARY KEY,
|
||
level TEXT,
|
||
module TEXT,
|
||
message TEXT,
|
||
detail TEXT,
|
||
created_at DATETIME
|
||
)
|
||
```
|
||
|
||
当前 `audit_logs` 和 `app_logs` 分别用于用户动作审计和运行排错。`MetricsService` 已直接用 SQL 聚合 P0 指标,不急着落 `daily_metrics` 缓存表。数据量变大后再增加缓存表。
|
||
|
||
迁移要求:
|
||
|
||
- 初始化必须幂等。
|
||
- 新字段必须有默认值或迁移逻辑。
|
||
- schema 变化必须同步 `store_test.go`、`api.md` 和 `current-state.md`。
|
||
|
||
## 窗口与页面
|
||
|
||
- 主窗口路由:`/#/` 重定向到 `/#/dashboard`
|
||
- 第二窗口路由:`/#/second`
|
||
- 已实现主应用骨架路由:`/#/login`、`/#/dashboard`、`/#/image-optimizer`、`/#/logs`、`/#/statistics`、`/#/settings`、`/#/components`。
|
||
- 兼容目标文档路由:`/#/business/image-optimizer`、`/#/logs/audit`、`/#/logs/app` 会重定向到当前主入口。
|
||
- 托盘菜单由 `AppService` 配置。
|
||
- 热键触发目标可以是打开主窗口、打开快捷功能或创建快速任务。
|
||
|
||
窗口策略:
|
||
|
||
- 主窗口承载长期业务操作,默认不最大化。
|
||
- 主窗口初始尺寸为 `1280x800`,最小尺寸为 `1024x720`。
|
||
- 主窗口启动时居中,并允许用户调整大小。
|
||
- 主窗口按 `window.width`、`window.height`、`window.start_state` 和 `window.remember_state` 恢复用户上次选择。
|
||
- 前端根容器使用 `width: 100%` 和 `height: 100vh`。
|
||
- 主应用布局内部使用 flex 或 grid 填满窗口。
|
||
- 阅读型内容保留最大宽度,列表、仪表盘、设置页等工作型页面自适应拉伸。
|
||
- 第二窗口保持当前小窗定位,不参与最大化、尺寸恢复和主布局填充逻辑。
|
||
|
||
实现状态:主窗口初始尺寸、居中、可调整大小、根容器和主布局填充已落地;主应用路由骨架已落地;登录 provider 边界已落地;设置模块统一 schema 已落地;主窗口尺寸和最大化状态持久化已落地。
|
||
|
||
## 关键风险
|
||
|
||
- 范围膨胀:模板容易变成“大而全平台”,必须按任务小步交付。
|
||
- Wails v3 仍是 alpha,CLI、Go 模块和 runtime 必须保持匹配。
|
||
- bindings 若与 Go 服务签名不一致,前端会在运行时失败。
|
||
- 登录 provider、AI provider 和日志模块必须有清晰边界,否则后续替换困难。
|
||
- OCR、热键、托盘依赖平台能力,跨平台修改必须分别验证。
|
||
- Vite 构建可能出现 chunk size warning,警告不等于失败,但需要避免无节制增加前端体积。
|