docs: initialize harness coding docs
This commit is contained in:
@@ -0,0 +1,185 @@
|
||||
# 架构设计
|
||||
|
||||
> 本文讲系统结构、职责划分、数据模型、技术难点、开发顺序。具体技术选型见 [技术栈](03-tech-stack.md)。
|
||||
|
||||
## 一、系统结构
|
||||
|
||||
```text
|
||||
浏览器
|
||||
|
|
||||
| GET /, /static/*
|
||||
| fetch /api/*
|
||||
v
|
||||
Go + Gin 单体服务
|
||||
| |
|
||||
| +-- 托管 web/ 静态前端文件
|
||||
|
|
||||
+-- REST handlers
|
||||
+-- services: 钉钉 API、同步、导出
|
||||
+-- repositories: SQLite 读写
|
||||
| |
|
||||
| +-- SQLite 数据库
|
||||
|
|
||||
+-- 钉钉 OpenAPI
|
||||
```
|
||||
|
||||
## 二、职责划分
|
||||
|
||||
**原生前端**
|
||||
|
||||
- 渲染站点选择、同步状态、部门树、人员表格、筛选表单。
|
||||
- 使用 `fetch` 调用同源 `/api/*`。
|
||||
- 只保存当前页面交互状态,不保存密钥和 token。
|
||||
- 不直接访问钉钉 OpenAPI。
|
||||
|
||||
**Gin 后端**
|
||||
|
||||
- 托管 `web/` 静态文件。
|
||||
- 提供 REST API。
|
||||
- 负责请求参数校验、错误响应、分页与导出。
|
||||
- 封装钉钉 OpenAPI 调用、token 获取与复用。
|
||||
- 执行同步流程并记录同步日志。
|
||||
|
||||
**SQLite / repository**
|
||||
|
||||
- 持久化站点配置、access token、部门、人员、同步日志。
|
||||
- 保存钉钉返回的关键字段和必要原始 JSON 字段。
|
||||
- 提供按站点、部门、关键词、状态分页查询。
|
||||
|
||||
## 三、数据模型
|
||||
|
||||
### 3.1 站点与 token
|
||||
|
||||
```sql
|
||||
CREATE TABLE sites (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
code TEXT NOT NULL UNIQUE,
|
||||
name TEXT NOT NULL,
|
||||
app_key TEXT NOT NULL,
|
||||
app_secret TEXT NOT NULL,
|
||||
created_at TEXT NOT NULL,
|
||||
updated_at TEXT NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE access_tokens (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
site_id INTEGER NOT NULL REFERENCES sites(id) ON DELETE CASCADE,
|
||||
token TEXT NOT NULL,
|
||||
expires_in INTEGER NOT NULL,
|
||||
fetched_at INTEGER NOT NULL,
|
||||
created_at TEXT NOT NULL
|
||||
);
|
||||
```
|
||||
|
||||
### 3.2 部门
|
||||
|
||||
```sql
|
||||
CREATE TABLE departments (
|
||||
site_id INTEGER NOT NULL REFERENCES sites(id) ON DELETE CASCADE,
|
||||
dept_id INTEGER NOT NULL,
|
||||
parent_id INTEGER NOT NULL,
|
||||
name TEXT NOT NULL,
|
||||
raw_json TEXT,
|
||||
updated_at TEXT NOT NULL,
|
||||
PRIMARY KEY (site_id, dept_id)
|
||||
);
|
||||
|
||||
CREATE INDEX idx_departments_site_parent ON departments(site_id, parent_id);
|
||||
```
|
||||
|
||||
### 3.3 人员
|
||||
|
||||
```sql
|
||||
CREATE TABLE users (
|
||||
site_id INTEGER NOT NULL REFERENCES sites(id) ON DELETE CASCADE,
|
||||
userid TEXT NOT NULL,
|
||||
name TEXT,
|
||||
mobile TEXT,
|
||||
title TEXT,
|
||||
job_number TEXT,
|
||||
active INTEGER,
|
||||
avatar TEXT,
|
||||
unionid TEXT,
|
||||
dept_id INTEGER,
|
||||
dept_id_list TEXT,
|
||||
dept_name TEXT,
|
||||
hired_date INTEGER,
|
||||
raw_json TEXT,
|
||||
updated_at TEXT NOT NULL,
|
||||
PRIMARY KEY (site_id, userid)
|
||||
);
|
||||
|
||||
CREATE INDEX idx_users_site_name ON users(site_id, name);
|
||||
CREATE INDEX idx_users_site_mobile ON users(site_id, mobile);
|
||||
CREATE INDEX idx_users_site_job_number ON users(site_id, job_number);
|
||||
CREATE INDEX idx_users_site_dept ON users(site_id, dept_id);
|
||||
```
|
||||
|
||||
### 3.4 同步日志
|
||||
|
||||
```sql
|
||||
CREATE TABLE sync_logs (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
site_id INTEGER REFERENCES sites(id) ON DELETE SET NULL,
|
||||
sync_type TEXT NOT NULL,
|
||||
status TEXT NOT NULL,
|
||||
message TEXT,
|
||||
started_at TEXT NOT NULL,
|
||||
finished_at TEXT
|
||||
);
|
||||
```
|
||||
|
||||
## 四、关键技术难点
|
||||
|
||||
| 难点 | 说明 | 应对 |
|
||||
| --- | --- | --- |
|
||||
| token 过期 | access_token 有有效期,接口失败可能由 token 过期导致 | 按需获取;过期前刷新;失败日志可见 |
|
||||
| 部门递归 | 需要从根部门 `dept_id=1` 拉完整树 | 先实现 BFS/队列同步,并测试重复和空子部门 |
|
||||
| 用户多部门 | 用户可能属于多个部门,单 `dept_id` 不足 | 保留 `dept_id_list` 原始 JSON,MVP 用主部门筛选 |
|
||||
| 密钥安全 | app_secret 需要存储但不能泄露 | 列表和日志不返回密钥;导出不包含密钥 |
|
||||
| 静态前端复杂度 | 原生 JS 容易膨胀 | 按页面拆分 `web/assets/*.js`,保持小模块 |
|
||||
|
||||
## 五、推荐开发顺序
|
||||
|
||||
1. 初始化 Go module、Gin、健康检查、静态文件托管。
|
||||
2. 建立 SQLite 连接、迁移和基础 repository。
|
||||
3. 实现站点 CRUD API。
|
||||
4. 实现钉钉 token、部门、用户 API client。
|
||||
5. 实现全量同步入库和同步日志。
|
||||
6. 实现部门、用户、导出 API。
|
||||
7. 实现原生前端页面。
|
||||
8. 完整验收和运行文档。
|
||||
|
||||
## 六、项目结构建议
|
||||
|
||||
```text
|
||||
dingding_hrm/
|
||||
├── docs/
|
||||
├── main.go
|
||||
├── go.mod
|
||||
├── internal/
|
||||
│ ├── config/
|
||||
│ ├── db/
|
||||
│ ├── dingtalk/
|
||||
│ ├── handler/
|
||||
│ ├── model/
|
||||
│ ├── repository/
|
||||
│ └── service/
|
||||
├── web/
|
||||
│ ├── index.html
|
||||
│ └── assets/
|
||||
│ ├── app.js
|
||||
│ └── style.css
|
||||
├── data/
|
||||
│ └── dingding_hrm.db
|
||||
├── AGENTS.md
|
||||
└── CLAUDE.md
|
||||
```
|
||||
|
||||
## 七、架构纪律
|
||||
|
||||
- `handler` 不直接拼 SQL,不直接调用钉钉 OpenAPI。
|
||||
- `service` 编排业务流程,但不处理 HTTP 细节。
|
||||
- `repository` 只负责 SQLite 读写和事务。
|
||||
- `dingtalk` 包只负责 OpenAPI 请求、响应解析和错误归一。
|
||||
- 前端只调用 `/api/*`,不保存密钥、token 或业务缓存文件。
|
||||
Reference in New Issue
Block a user