# 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()` 调用后端 API,base 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. **配置灵活性**: 支持配置文件和环境变量两种方式