MarketingSystemDataExportTool/.cursorrules

247 lines
8.3 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# MarketingSystemDataTool 项目规则
## 项目概述
这是一个营销系统和易码通数据工具,提供数据导出、模板管理、元数据查询等功能。
### 技术栈
- **后端**: Go 1.21,使用标准库 `net/http`,不使用第三方 Web 框架
- **前端**: Vue 3 (通过 CDN 引入) + Element Plus
- **数据库**: MySQL支持多数据源Marketing、YMT、Meta
- **导出格式**: CSV、Excel (使用 excelize/v2)
- **配置**: YAML 配置文件 + 环境变量覆盖
## 项目结构
```
server/ # Go 后端代码
├── cmd/server/ # 主程序入口
├── internal/ # 内部包
│ ├── api/ # HTTP 路由和处理器
│ ├── config/ # 配置管理
│ ├── db/ # 数据库连接和池管理
│ ├── exporter/ # 数据导出逻辑
│ ├── logging/ # 日志工具
│ ├── models/ # 数据模型
│ ├── repo/ # 数据仓库层
│ ├── schema/ # 数据库模式定义
│ └── ymtcrypto/ # 加密工具
web/ # 前端静态文件
config/ # 非敏感配置
scripts/ # 开发和运维脚本
```
## Go 代码规范
### 架构模式
1. **Handler 函数模式**: 每个 API 端点使用 `Handler` 函数返回 `http.Handler`
```go
func ExportsHandler(meta, marketing, ymt *sql.DB) http.Handler {
api := &ExportsAPI{meta: meta, marketing: marketing, ymt: ymt}
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// 路由逻辑
})
}
```
2. **中间件链**: 使用函数式中间件,顺序为 `withAccess` -> `withTrace` -> Handler
```go
mux.Handle("/api/exports", withAccess(withTrace(ExportsHandler(...))))
```
3. **Context 传递**: 使用 `context.Context` 传递 trace_id、SQL、请求元数据等
- `TraceIDFrom(r)` - 获取 trace_id
- `WithSQL(r, sql)` - 设置 SQL 到 context
- `SQLFrom(r)` - 从 context 获取 SQL
- `MetaFrom(r)` - 获取请求元数据
### 代码风格
1. **标准库优先**: 优先使用 Go 标准库,避免引入不必要的第三方依赖
2. **包命名**: 使用小写单数形式,如 `api`, `config`, `db`
3. **函数命名**:
- Handler 函数使用 `XxxHandler` 命名
- 中间件函数使用 `withXxx` 命名
- 工具函数使用驼峰命名
4. **错误处理**:
- API 错误使用 `fail(w, r, status, msg)` 返回统一格式
- 成功响应使用 `ok(w, r, data)` 返回统一格式
- 启动错误使用 `log.Fatal()`
5. **数据库操作**:
- 使用 `database/sql` 标准库
- 支持连接池配置(通过环境变量)
- 多数据库实例:`metaDB` (模板/任务), `marketingDB` (营销数据), `ymtDB` (易码通数据)
### 响应格式
统一使用以下 JSON 响应结构:
```go
type resp struct {
Code int `json:"code"` // 0 表示成功,非 0 表示错误
Msg string `json:"msg"` // 消息
Data interface{} `json:"data"` // 数据
TraceID string `json:"trace_id"` // 追踪 ID
}
```
### 日志规范
1. **结构化日志**: 使用 `logging.JSON()` 记录结构化日志
2. **访问日志**: 在 `withAccess` 中间件中自动记录,包含 method、path、status、duration 等
3. **错误日志**: 在 `fail()` 函数中记录错误,包含 trace_id、文件位置、SQL如果有
4. **日志格式**: JSON 格式,包含 level、ts、trace_id、method、path 等字段
## API 设计规范
### 路由规则
1. **RESTful 风格**:
- `GET /api/templates` - 列表
- `POST /api/templates` - 创建
- `GET /api/templates/{id}` - 详情
- `PATCH /api/templates/{id}` - 更新
- `DELETE /api/templates/{id}` - 删除
2. **路径处理**: 使用 `strings.TrimPrefix()` 处理路径前缀,支持带或不带尾部斜杠
3. **CORS 支持**: 所有 API 通过 `withAccess` 中间件自动处理 CORS
### 请求处理
1. **参数解析**:
- GET 请求从 `r.URL.Query()` 获取参数
- POST 请求从 `r.Body` 读取 JSON
- 使用 `json.Decoder` 或 `json.Unmarshal` 解析
2. **用户身份**: 通过 `userId` 查询参数传递(支持 `userId`, `userid`, `user_id`
3. **权限检查**: 在 Handler 内部根据业务逻辑进行权限验证
## 数据库操作规范
### 连接管理
1. **多数据源**:
- `metaDB`: 存储模板和任务元数据
- `marketingDB`: 营销系统数据
- `ymtDB`: 易码通数据
2. **连接池配置**: 通过环境变量配置(`YMT_DB_*`, `MARKETING_DB_*`, `YMT_TEST_DB_*`
3. **DSN 格式**: 使用 `DB.DSN()` 方法生成,包含 `parseTime=True&loc=Local&charset=utf8mb4`
### Schema 抽象
1. **Schema 接口**: 使用 `schema.Schema` 接口抽象不同数据源的差异
2. **字段映射**: 通过 `MapField()` 方法将逻辑字段名映射到物理字段名
3. **表名映射**: 通过 `TableName()` 方法获取实际表名
4. **JOIN 构建**: 通过 `BuildJoins()` 方法构建必要的 JOIN 语句
### SQL 构建
1. **SQL Builder**: 使用 `exporter.BuildSQL()` 构建查询 SQL
2. **白名单机制**: 字段访问需要通过白名单验证
3. **参数化查询**: 使用 `?` 占位符,防止 SQL 注入
4. **时间过滤**: 营销系统的 order 表必须提供 `create_time_between` 过滤条件
## 配置管理规范
### 配置文件
1. **配置文件位置**:
- 优先使用 `server/config.yaml`
- 备选 `config.yaml`
2. **配置结构**:
```yaml
app:
port: "8077"
marketing_db:
host: "..."
port: "..."
user: "..."
password: "..."
name: "..."
ymt_db: {...}
ymt_test_db: {...}
ymt_key_decrypt_key_b64: "..."
```
3. **环境变量覆盖**:
- 支持通过环境变量覆盖配置
- 环境变量优先级高于配置文件
- 支持 `.env.local` 文件(不提交到版本控制)
## 前端代码规范
### Vue 3 使用
1. **CDN 引入**: 使用 CDN 方式引入 Vue 3 和 Element Plus不打包
2. **组合式 API**: 使用 `setup()` 和 `reactive()` 进行状态管理
3. **API 调用**: 使用 `fetch()` 调用后端 APIbase URL 为 `http://localhost:8077`
4. **用户 ID**: 从 URL 查询参数获取 `userId`
### 代码组织
1. **单文件应用**: 主要逻辑在 `web/main.js` 中
2. **样式分离**: 样式在 `web/styles.css` 中
3. **静态资源**: 第三方库在 `web/vendor/` 目录
## 错误处理规范
1. **API 错误**:
- HTTP 状态码400 (Bad Request), 404 (Not Found), 500 (Internal Server Error)
- 响应体:`{code: 1, msg: "错误消息", data: null, trace_id: "..."}`
2. **日志记录**:
- 所有错误都记录到日志,包含 trace_id、文件位置、SQL如果有
- 使用 `failCat()` 记录分类错误
3. **错误消息**: 使用中文错误消息,清晰描述问题
## 导出功能规范
1. **导出格式**: 支持 CSV 和 Excel (xlsx)
2. **流式处理**: 使用 `exporter.Stream()` 进行流式导出,避免内存溢出
3. **文件存储**: 导出文件存储在 `storage/export/` 目录
4. **异步处理**: 导出任务异步执行,通过 job 状态跟踪进度
## 安全规范
1. **访问控制**: 通过 `withAccess` 中间件处理 CORS
2. **SQL 注入防护**: 使用参数化查询,不拼接 SQL 字符串
3. **字段白名单**: 字段访问必须通过白名单验证
4. **敏感信息**: 密码等敏感信息不记录到日志
## 开发建议
1. **新增 API**:
- 在 `internal/api/` 下创建新的 handler 文件
- 在 `router.go` 中注册路由
- 使用统一的响应格式和错误处理
2. **新增数据源**:
- 在 `internal/schema/` 下实现 `Schema` 接口
- 在 `schema.Get()` 中添加路由逻辑
3. **代码审查要点**:
- 是否使用参数化查询
- 是否通过字段白名单验证
- 是否使用统一的响应格式
- 是否记录必要的日志
4. **性能优化**:
- 大数据量导出使用流式处理
- 合理使用数据库连接池
- 避免 N+1 查询问题
## 注意事项
1. **不要使用第三方 Web 框架**: 坚持使用标准库 `net/http`
2. **保持代码简洁**: 避免过度抽象,保持代码可读性
3. **统一错误处理**: 所有错误都通过 `fail()` 函数返回
4. **日志完整性**: 确保关键操作都有日志记录
5. **配置灵活性**: 支持配置文件和环境变量两种方式