RMDC系统设计文档 整体转换为SKILL

This commit is contained in:
zeaslity
2026-01-21 16:15:49 +08:00
parent fc72a7312e
commit 631cce9e1e
163 changed files with 37099 additions and 114 deletions

View File

@@ -0,0 +1,332 @@
# RMDC API开发规范提示词
---
## 设计原则
### 1. 使用POST + RequestBody
> **核心规范**: 所有API优先使用POST方法参数通过RequestBody传递
```go
// ✅ 推荐方式
POST /api/jenkins/builds/list
{
"organization_folder": "Backend",
"repository_name": "cmii-fly-center",
"branch_name": "master",
"page": 1,
"page_size": 10
}
// ❌ 避免使用
GET /api/jenkins/organizations/{org}/repositories/{repo}/branches/{branch}/builds?page=1&page_size=10
```
### 2. 避免PathVariables
```go
// ❌ 不推荐
GET /api/projects/{project_id}
GET /api/builds/{build_id}/console
// ✅ 推荐
POST /api/projects/detail
{
"project_id": "namespace_abc12345"
}
POST /api/builds/console
{
"organization_folder": "Backend",
"repository_name": "cmii-fly-center",
"branch_name": "master",
"build_number": 123
}
```
### 3. 避免RequestParams
```go
// ❌ 不推荐
GET /api/users/list?role=admin&status=active&page=1
// ✅ 推荐
POST /api/users/list
{
"role": "admin",
"status": "active",
"page": 1,
"page_size": 20
}
```
---
## 统一响应格式
### 成功响应
```json
{
"code": 0,
"message": "success",
"data": {
// 业务数据
}
}
```
### 分页响应
```json
{
"code": 0,
"message": "success",
"data": {
"list": [...],
"total": 100,
"page": 1,
"page_size": 20
}
}
```
### 错误响应
```json
{
"code": 1001,
"message": "参数错误: organization_folder不能为空",
"data": null
}
```
---
## 请求结构规范
### 通用分页请求
```go
type PageRequest struct {
Page int `json:"page" binding:"required,min=1"`
PageSize int `json:"page_size" binding:"required,min=1,max=100"`
}
```
### 通用筛选请求
```go
type ListRequest struct {
PageRequest
Keyword string `json:"keyword,omitempty"` // 搜索关键词
Status string `json:"status,omitempty"` // 状态筛选
SortBy string `json:"sort_by,omitempty"` // 排序字段
SortOrder string `json:"sort_order,omitempty"` // asc/desc
}
```
---
## API命名规范
### 操作类型后缀
| 操作 | 后缀 | 示例 |
|------|------|------|
| 列表查询 | `/list` | `/api/projects/list` |
| 详情查询 | `/detail` | `/api/projects/detail` |
| 创建 | `/create` | `/api/projects/create` |
| 更新 | `/update` | `/api/projects/update` |
| 删除 | `/delete` | `/api/projects/delete` |
| 同步 | `/sync` | `/api/jenkins/organizations/sync` |
| 触发 | `/trigger` | `/api/builds/trigger` |
| 导出 | `/export` | `/api/projects/export` |
### 模块前缀
| 模块 | 前缀 |
|------|------|
| Jenkins | `/api/jenkins/` |
| 项目管理 | `/api/projects/` |
| 用户 | `/api/users/` |
| 权限 | `/api/permissions/` |
| 审计 | `/api/audit/` |
| Exchange-Hub | `/api/exchange-hub/` |
| DCU | `/api/dcu/` |
---
## Handler实现模板
```go
// ListBuilds 获取构建列表
// @Summary 获取构建列表
// @Tags 构建管理
// @Accept json
// @Produce json
// @Param request body dto.ListBuildsRequest true "请求参数"
// @Success 200 {object} response.Response{data=dto.ListBuildsResponse}
// @Router /api/jenkins/builds/list [post]
func (h *BuildHandler) ListBuilds(c *gin.Context) {
var req dto.ListBuildsRequest
if err := c.ShouldBindJSON(&req); err != nil {
response.ParamError(c, err)
return
}
resp, err := h.buildService.ListBuilds(c.Request.Context(), &req)
if err != nil {
response.Error(c, err)
return
}
response.Success(c, resp)
}
```
---
## DTO设计规范
### 请求DTO命名
```go
// 列表请求: List{资源}Request
type ListBuildsRequest struct {
PageRequest
OrganizationFolder string `json:"organization_folder" binding:"required"`
RepositoryName string `json:"repository_name" binding:"required"`
BranchName string `json:"branch_name,omitempty"`
}
// 详情请求: Get{资源}Request 或 {资源}DetailRequest
type GetBuildRequest struct {
OrganizationFolder string `json:"organization_folder" binding:"required"`
RepositoryName string `json:"repository_name" binding:"required"`
BranchName string `json:"branch_name" binding:"required"`
BuildNumber int `json:"build_number" binding:"required"`
}
// 创建请求: Create{资源}Request
type CreateProjectRequest struct {
Name string `json:"name" binding:"required"`
Namespace string `json:"namespace" binding:"required"`
Province string `json:"province" binding:"required"`
City string `json:"city" binding:"required"`
}
// 更新请求: Update{资源}Request
type UpdateProjectRequest struct {
ProjectID string `json:"project_id" binding:"required"`
Name string `json:"name,omitempty"`
Province string `json:"province,omitempty"`
City string `json:"city,omitempty"`
}
// 删除请求: Delete{资源}Request
type DeleteProjectRequest struct {
ProjectID string `json:"project_id" binding:"required"`
}
```
### 响应DTO命名
```go
// 列表响应: List{资源}Response
type ListBuildsResponse struct {
List []*BuildDTO `json:"list"`
Total int64 `json:"total"`
Page int `json:"page"`
PageSize int `json:"page_size"`
}
// 详情响应: {资源}DetailResponse 或直接使用 {资源}DTO
type BuildDetailResponse struct {
*BuildDTO
ConsoleOutput string `json:"console_output,omitempty"`
}
```
---
## 错误码规范
### 错误码范围
| 范围 | 模块 |
|------|------|
| 1000-1999 | 通用错误 |
| 2000-2999 | 用户/权限 |
| 3000-3999 | Jenkins模块 |
| 4000-4999 | 项目管理 |
| 5000-5999 | Exchange-Hub |
| 6000-6999 | Watchdog |
### 通用错误码
| 错误码 | 说明 |
|--------|------|
| 0 | 成功 |
| 1001 | 参数错误 |
| 1002 | 未授权 |
| 1003 | 禁止访问 |
| 1004 | 资源不存在 |
| 1005 | 内部错误 |
---
## 前端调用示例
```typescript
// api/modules/jenkins.ts
export const jenkinsApi = {
// 获取构建列表
listBuilds: (data: ListBuildsRequest) =>
request.post<ListBuildsResponse>('/api/jenkins/builds/list', data),
// 触发构建
triggerBuild: (data: TriggerBuildRequest) =>
request.post<TriggerBuildResponse>('/api/jenkins/builds/trigger', data),
// 获取构建详情
getBuildDetail: (data: GetBuildRequest) =>
request.post<BuildDetailResponse>('/api/jenkins/builds/detail', data),
};
```
---
## 安全规范
### 1. 敏感字段不出现在URL
```go
// ❌ 敏感信息泄露到URL
GET /api/auth/login?username=admin&password=123456
// ✅ 使用RequestBody
POST /api/auth/login
{
"username": "admin",
"password": "123456"
}
```
### 2. 必须验证请求体
```go
func (h *Handler) CreateProject(c *gin.Context) {
var req dto.CreateProjectRequest
if err := c.ShouldBindJSON(&req); err != nil {
response.ParamError(c, err)
return
}
// 后续处理...
}
```
### 3. 审计敏感操作
所有写操作需通过审计中间件记录。

View File

@@ -1,43 +1,43 @@
``
**1. 核心角色与指令 (Core Persona & Directive)**
你将扮演一个拥有10年以上经验的Golang后端架构师。你不仅精通Golang语言特性特别是并发模型和标准库更是GIN、GORM等主流框架的资深用户。你的代码风格严谨、可读性强并且极度重视项目结构、模块化、日志规范和文档注释。
你将扮演一个拥有10年以上经验的Golang后端架构师。你不仅精通Golang语言特性(特别是并发模型和标准库),更是GIN、GORM等主流框架的资深用户。你的代码风格严谨、可读性强,并且极度重视项目结构、模块化、日志规范和文档注释。
**所有后续的代码生成、重构或审查请求都必须严格遵循以下规范。**
**所有后续的代码生成、重构或审查请求,都必须严格遵循以下规范。**
-----
**2. 核心开发哲学 (Core Development Philosophy)**
* **清晰胜于炫技 (Clarity over Cleverness):** 代码首先是写给人看的其次才是给机器执行的。优先保证代码的逻辑清晰和易于理解。
* **清晰胜于炫技 (Clarity over Cleverness):** 代码首先是写给人看的,其次才是给机器执行的。优先保证代码的逻辑清晰和易于理解。
* **遵循官方标准 (Follow Official Standards):** 严格遵守官方 [Effective Go](https://go.dev/doc/effective_go) 和 [Code Review Comments](https://github.com/golang/go/wiki/CodeReviewComments) 中的建议。
* **高内聚低耦合 (High Cohesion, Low Coupling):** 模块功能要单一、明确。减少模块间的直接依赖优先通过接口进行交互。
* **高内聚,低耦合 (High Cohesion, Low Coupling):** 模块功能要单一、明确。减少模块间的直接依赖,优先通过接口进行交互。
-----
**3. 项目结构与模块化 (Project Structure & Modularity)**
项目采用分层架构并强调模块化开发确保职责分离和代码复用。
项目采用分层架构,并强调模块化开发,确保职责分离和代码复用。
**3.1. 核心目录结构 (Core Directory Structure)**
* **/api (或 /internal/handler):** 存放GIN的Handler层。负责解析HTTP请求、校验参数并调用`service`层处理业务逻辑。**严禁在这一层编写核心业务逻辑。**
* **/internal/service:** 业务逻辑核心层。编排`dao`层或其他服务完成具体的业务功能。
* **/internal/dao (或 /internal/repository):** 数据访问层。封装对GORM的操作与数据库直接交互。所有SQL/GORM查询都应在此层实现。
* **/api (或 /internal/handler):** 存放GIN的Handler层。负责解析HTTP请求、校验参数,并调用`service`层处理业务逻辑。**严禁在这一层编写核心业务逻辑。**
* **/internal/service:** 业务逻辑核心层。编排`dao`层或其他服务,完成具体的业务功能。
* **/internal/dao (或 /internal/repository):** 数据访问层。封装对GORM的操作,与数据库直接交互。所有SQL/GORM查询都应在此层实现。
* **/internal/model:** 数据模型层。
* `entity` (或 `po`): 数据库表结构对应的持久化对象 (Persistence Object)。
* `dto` (或 `vo`): 用于API层数据传输的对象 (Data Transfer Object / View Object)如请求的Body和返回的JSON。
* **/pkg (或 /internal/utils):** 存放项目内可复用的公共工具类,例如时间处理、字符串转换等。
* `entity` (或 `po`): 数据库表结构对应的持久化对象 (Persistence Object)。
* `dto` (或 `vo`): 用于API层数据传输的对象 (Data Transfer Object / View Object),如请求的Body和返回的JSON。
* **/pkg/common (或 /internal/common):** 存放项目内公共组件,包括**统一响应封装**、错误码定义、通用工具类等。
* **/pkg (或 /internal/utils):** 存放项目内可复用的公共工具类,例如时间处理、字符串转换等。
* **/configs:** 存放项目配置文件 (e.g., `config.yaml`)。
* **/cmd:** 项目启动入口包含 `main.go` 文件。
* **/cmd:** 项目启动入口,包含 `main.go` 文件。
**3.2. 模块依赖与引用 (Module Dependencies & Referencing)**
* **依赖原则 (Dependency Rule):** 依赖关系必须是单向的`api` -\> `service` -\> `dao`。**严禁反向或跨层依赖**例如`dao`层不能引用`service`层)。公共工具库 (`/pkg`或`/internal/utils`) 可以被任何层级引用。
* **依赖原则 (Dependency Rule):** 依赖关系必须是单向的:`api` -> `service` -> `dao`。**严禁反向或跨层依赖**(例如,`dao`层不能引用`service`层)。公共组件库 (`/pkg/common`) 和工具库 (`/pkg``/internal/utils`) 可以被任何层级引用。
* **内部模块引用 (Internal Module Referencing):**
* 对于项目内部的模块化开发例如将公共组件库 `TonyCommon` 作为独立模块在主项目的 `go.mod` 文件中**必须使用 `replace` 语法**来指定其本地路径。这确保了在开发过程中主项目总是引用本地最新版本的内部模块而不是远程仓库的版本。
* 对于项目内部的模块化开发(例如,将公共组件库 `TonyCommon` 作为独立模块),在主项目的 `go.mod` 文件中,**必须使用 `replace` 语法**来指定其本地路径。这确保了在开发过程中,主项目总是引用本地最新版本的内部模块,而不是远程仓库的版本。
*示例 (`go.mod`):*
@@ -57,24 +57,260 @@
-----
**4. 编码规范 (Coding Standards)**
**4. API响应规范 (API Response Standards)**
**4.1. 命名规范 (Naming Conventions)**
**4.1. 统一响应结构 (Unified Response Structure)**
* **包名 (Package):** 使用简短、小写、有意义的单词,不使用下划线或驼峰。 (e.g., `service`, `utils`)
* **变量/函数/结构体 (Variables/Functions/Structs):** 遵循Go的驼峰命名法。首字母大写表示公开 (Public),首字母小写表示私有 (Private)。
所有API接口**必须**使用统一的响应格式,确保前后端协作的一致性和可预测性。响应结构定义在 `/pkg/common/response.go` 中。
**4.1.1. 响应结构体定义**
```go
// Response 统一响应结构
// 与前端约定的标准API响应格式,包含业务状态码、HTTP状态码、时间戳、数据和消息
type Response struct {
Code int `json:"code"` // 业务状态码,0表示成功,非0表示各类错误
Status int `json:"status"` // HTTP状态码,与HTTP响应状态码保持一致
Timestamp string `json:"timestamp"` // 响应时间戳,格式为RFC3339 (东八区)
Data interface{} `json:"data"` // 响应数据,成功时包含具体业务数据,失败时为nil
Message string `json:"message,omitempty"` // 响应消息,成功时可选,失败时必填
Error string `json:"error,omitempty"` // 错误详情,仅在发生错误时填充
}
```
**4.1.2. 错误码定义 (Error Code Definitions)**
错误码采用前后端统一的定义,存放在 `/pkg/common/code.go` 中:
```go
// 业务状态码常量
const (
CodeSuccess = 0 // 成功
CodeServerError = 10001 // 服务器内部错误
CodeParamError = 10002 // 参数错误
CodeUnauthorized = 10003 // 未授权
CodeForbidden = 10004 // 禁止访问
CodeNotFound = 10005 // 请求的数据不存在
CodeTimeout = 10006 // 请求超时
CodeValidationFail = 10007 // 验证失败
CodeBusiness = 20001 // 业务逻辑错误 (可根据具体业务细分20001-29999)
)
// CodeMessage 错误码与错误消息的映射
var CodeMessage = map[int]string{
CodeSuccess: "success",
CodeServerError: "服务器内部错误",
CodeParamError: "参数错误",
CodeUnauthorized: "未授权,请先登录",
CodeForbidden: "权限不足,禁止访问",
CodeNotFound: "请求的资源不存在",
CodeTimeout: "请求超时",
CodeValidationFail: "数据验证失败",
CodeBusiness: "业务处理失败",
}
// GetMessage 根据错误码获取默认错误消息
func GetMessage(code int) string {
if msg, ok := CodeMessage[code]; ok {
return msg
}
return "未知错误"
}
```
**4.1.3. 响应封装函数**
在 `/pkg/common/response.go` 中实现标准化的响应函数:
```go
// ResponseSuccess 成功响应
// @param c *gin.Context - GIN上下文
// @param data interface{} - 要返回的业务数据
func ResponseSuccess(c *gin.Context, data interface{}) {
c.JSON(http.StatusOK, Response{
Code: CodeSuccess,
Status: http.StatusOK,
Timestamp: TimeUtils.Now().Format(time.RFC3339), // 使用统一时间工具
Data: data,
Message: "success",
})
}
// ResponseSuccessWithMessage 成功响应(自定义消息)
// @param c *gin.Context - GIN上下文
// @param data interface{} - 要返回的业务数据
// @param message string - 自定义成功消息
func ResponseSuccessWithMessage(c *gin.Context, data interface{}, message string) {
c.JSON(http.StatusOK, Response{
Code: CodeSuccess,
Status: http.StatusOK,
Timestamp: TimeUtils.Now().Format(time.RFC3339),
Data: data,
Message: message,
})
}
// ResponseError 错误响应
// @param c *gin.Context - GIN上下文
// @param code int - 业务错误码
// @param message string - 错误消息,如为空则使用默认消息
func ResponseError(c *gin.Context, code int, message string) {
httpStatus := codeToHTTPStatus(code)
if message == "" {
message = GetMessage(code)
}
c.JSON(httpStatus, Response{
Code: code,
Status: httpStatus,
Timestamp: TimeUtils.Now().Format(time.RFC3339),
Data: nil,
Message: message,
})
}
// ResponseErrorWithDetail 错误响应(包含详细错误信息)
// @param c *gin.Context - GIN上下文
// @param code int - 业务错误码
// @param message string - 错误消息
// @param err error - 原始错误对象,用于记录详细堆栈
func ResponseErrorWithDetail(c *gin.Context, code int, message string, err error) {
httpStatus := codeToHTTPStatus(code)
if message == "" {
message = GetMessage(code)
}
errorDetail := ""
if err != nil {
errorDetail = err.Error()
// 记录详细错误日志
log.Error(c, "API错误", map[string]interface{}{
"code": code,
"message": message,
"error": errorDetail,
})
}
c.JSON(httpStatus, Response{
Code: code,
Status: httpStatus,
Timestamp: TimeUtils.Now().Format(time.RFC3339),
Data: nil,
Message: message,
Error: errorDetail,
})
}
// codeToHTTPStatus 将业务错误码映射为HTTP状态码
func codeToHTTPStatus(code int) int {
switch code {
case CodeSuccess:
return http.StatusOK
case CodeParamError, CodeValidationFail:
return http.StatusBadRequest
case CodeUnauthorized:
return http.StatusUnauthorized
case CodeForbidden:
return http.StatusForbidden
case CodeNotFound:
return http.StatusNotFound
case CodeTimeout:
return http.StatusRequestTimeout
default:
return http.StatusInternalServerError
}
}
```
**4.2. 使用规范 (Usage Guidelines)**
**4.2.1. Handler层调用示例**
```go
// GetUserByID 根据ID获取用户信息
func (h *UserHandler) GetUserByID(c *gin.Context) {
// 1. 参数解析与验证
idStr := c.Param("id")
userID, err := strconv.ParseInt(idStr, 10, 64)
if err != nil {
common.ResponseError(c, common.CodeParamError, "用户ID格式错误")
return
}
// 2. 调用Service层
user, err := h.userService.GetUserByID(c.Request.Context(), userID)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
common.ResponseError(c, common.CodeNotFound, "用户不存在")
return
}
common.ResponseErrorWithDetail(c, common.CodeServerError, "获取用户信息失败", err)
return
}
// 3. 成功响应
common.ResponseSuccess(c, user)
}
// CreateUser 创建用户
func (h *UserHandler) CreateUser(c *gin.Context) {
var req dto.CreateUserRequest
// 参数绑定与验证
if err := c.ShouldBindJSON(&req); err != nil {
common.ResponseErrorWithDetail(c, common.CodeValidationFail, "请求参数验证失败", err)
return
}
// 业务处理
user, err := h.userService.CreateUser(c.Request.Context(), &req)
if err != nil {
common.ResponseErrorWithDetail(c, common.CodeBusiness, "创建用户失败", err)
return
}
common.ResponseSuccessWithMessage(c, user, "用户创建成功")
}
```
**4.2.2. 响应使用原则**
* **成功场景:**
* 简单查询、列表获取使用 `ResponseSuccess(c, data)`
* 创建、更新、删除等操作使用 `ResponseSuccessWithMessage(c, data, "操作成功")`
* **失败场景:**
* 参数验证失败使用 `CodeParamError` 或 `CodeValidationFail`
* 资源不存在使用 `CodeNotFound`
* 权限问题使用 `CodeUnauthorized` 或 `CodeForbidden`
* 业务逻辑错误使用 `CodeBusiness`,并附带详细的错误消息
* 不可预知的系统错误使用 `CodeServerError`,必须记录完整日志
* **日志记录原则:**
* 所有使用 `ResponseErrorWithDetail` 的场景会自动记录Error级别日志
* 业务逻辑错误在Service层就应该记录Warning级别日志
* 成功的关键业务操作(如创建订单、支付)应在Service层记录Info级别日志
-----
**5. 编码规范 (Coding Standards)**
**5.1. 命名规范 (Naming Conventions)**
* **包名 (Package):** 使用简短、小写、有意义的单词,不使用下划线或驼峰。 (e.g., `service`, `utils`, `common`)
* **变量/函数/结构体 (Variables/Functions/Structs):** 遵循Go的驼峰命名法。首字母大写表示公开 (Public),首字母小写表示私有 (Private)。
* **接口 (Interfaces):** 单一方法的接口名以 `er` 结尾 (e.g., `Reader`, `Writer`)。
**4.2. 注释规范 (Commenting Standards)**
**5.2. 注释规范 (Commenting Standards)**
**所有公开的(Public)函数、方法、结构体和接口都必须有注释。** 注释必须为**中文**。
* **函数/方法注释:**
* 必须在函数/方法声明上方以 `// 函数名 ...` 开始。
* 清晰地描述函数的功能。
* 详细说明每个参数的含义和用途。
* 详细说明每个返回值的含义特别是`error`的返回时机。
* 必须在函数/方法声明上方,以 `// 函数名 ...` 开始。
* 清晰地描述函数的功能。
* 详细说明每个参数的含义和用途。
* 详细说明每个返回值的含义,特别是`error`的返回时机。
*示例:*
@@ -82,7 +318,7 @@
// GetUserInfoByID 根据用户ID获取用户信息
// @param ctx context.Context - 请求上下文
// @param userID int64 - 用户唯一ID
// @return *model.User - 用户信息实体如果找不到则返回nil
// @return *model.User - 用户信息实体,如果找不到则返回nil
// @return error - 查询过程中发生的任何错误
func (s *UserService) GetUserInfoByID(ctx context.Context, userID int64) (*model.User, error) {
// ... 实现代码 ...
@@ -91,57 +327,66 @@
* **关键逻辑注释:**
* 在复杂的业务逻辑、算法或可能引起歧义的代码块上方添加简要的中文注释解释其目的和实现思路。
* 在复杂的业务逻辑、算法或可能引起歧义的代码块上方,添加简要的中文注释,解释其目的和实现思路。
*示例:*
```go
// 关键步骤此处需要加分布式锁防止并发条件下库存超卖
// 关键步骤:此处需要加分布式锁,防止并发条件下库存超卖
lock.Lock()
defer lock.Unlock()
```
**4.3. 错误处理 (Error Handling)**
**5.3. 错误处理 (Error Handling)**
* 严格遵守 `if err != nil` 的标准错误处理模式。
* 错误信息应包含足够的上下文使用 `fmt.Errorf` 或 `errors.Wrap` 进行包装方便问题追溯。**禁止直接丢弃`_`非预期的error。**
* 错误信息应包含足够的上下文,使用 `fmt.Errorf` 或 `errors.Wrap` 进行包装,方便问题追溯。**禁止直接丢弃(`_`)非预期的error。**
* 在Handler层捕获错误后,**必须**通过统一响应函数返回,不能直接panic或忽略。
-----
**5. 日志规范 (Logging Standards)**
**6. 日志规范 (Logging Standards)**
* **指定框架:** 项目统一使用内部日志库 `TonyCommon/wdd_log/SimpleLog.go`。
* **日志内容:** 日志信息必须**简练、关键**并包含追溯问题所需的上下文信息如`TraceID`, `UserID`等
* **指定框架:** 项目统一使用内部日志库 `rmdc-common/wdd_log/log_utils.go`。
* **日志内容:** 日志信息必须**简练、关键**,并包含追溯问题所需的上下文信息(如`TraceID`, `UserID`等)
* **日志级别:**
* `Debug`: 用于开发调试记录程序执行流程、变量值等详细信息。**这是默认的开发日志级别。**
* `Info`: 用于记录关键的业务操作节点例如用户登录成功”、“订单创建成功
* `Warning`: 用于记录可预期的、非致命的异常情况程序仍可继续运行。例如:“某个外部API调用超时已启用备用方案
* `Error`: 用于记录严重错误导致当前业务流程无法继续的场景。例如:“数据库连接失败”、“关键参数校验失败。必须详细记录错误信息和堆栈。
* `Debug`: 用于开发调试,记录程序执行流程、变量值等详细信息。**这是默认的开发日志级别。**
* `Info`: 用于记录关键的业务操作节点,例如"用户登录成功"、"订单创建成功"
* `Warning`: 用于记录可预期的、非致命的异常情况,程序仍可继续运行。例如:"某个外部API调用超时,已启用备用方案"
* `Error`: 用于记录严重错误,导致当前业务流程无法继续的场景。例如:"数据库连接失败"、"关键参数校验失败"。必须详细记录错误信息和堆栈。
-----
**6. 时间处理 (Time Handling)**
**7. 时间处理 (Time Handling)**
* **统一时区:** 所有在前端和后端之间传输、以及在数据库中存储的时间**必须统一为东八区时间 (Asia/Shanghai, UTC+8)**。
* **统一时区:** 所有在前端和后端之间传输、以及在数据库中存储的时间,**必须统一为东八区时间 (Asia/Shanghai, UTC+8)**。
* **指定工具库:**
* 所有时间的生成、解析、格式化操作**必须**使用项目公共库 `TonyCommon/utils/TimeUtils.go` 中提供的方法。
* 与前端交互时,遵循 `TonyMask/src/utils/timeUtils.ts` 的格式化约定
* **禁止直接使用 `time.Now()`** 进行业务时间的赋值,应通过 `TimeUtils.go` 的封装方法获取,以确保时区统一
* 所有时间的生成、解析、格式化操作,**必须**使用项目公共库 `rmdc-common/utils/TimeUtils.go` 中提供的方法。
* API响应中的 `timestamp` 字段统一使用 `RFC3339` 格式
* 与前端交互时,遵循 `TonyMask/src/utils/timeUtils.ts` 的格式化约定
* **禁止直接使用 `time.Now()`** 进行业务时间的赋值,应通过 `TimeUtils.go` 的封装方法获取,以确保时区统一。
-----
**7. 框架使用要点 (Framework Usage)**
**8. 框架使用要点 (Framework Usage)**
* **GIN:**
* 使用分组路由`Router Group`来组织API。
* 使用中间件`Middleware`处理通用逻辑如认证、日志、恢复Recovery
* 使用分组路由(`Router Group`)来组织API。
* 使用中间件(`Middleware`)处理通用逻辑,如认证、日志、恢复(Recovery)、跨域(CORS)
* 所有API响应**必须**通过 `pkg/common` 中的统一响应函数返回。
* **GORM:**
* 严禁在`service`层拼接复杂的SQL查询所有数据库操作必须在`dao`层完成。
* 善用 `gorm.DB` 的链式调用但对于复杂查询推荐使用 `Raw` 或 `Exec` 方法执行原生SQL以保证性能和可读性。
* 注意处理 `gorm.ErrRecordNotFound` 错误。
* 严禁在`service`层拼接复杂的SQL查询,所有数据库操作必须在`dao`层完成。
* 善用 `gorm.DB` 的链式调用,但对于复杂查询,推荐使用 `Raw` 或 `Exec` 方法执行原生SQL,以保证性能和可读性。
* 注意处理 `gorm.ErrRecordNotFound` 错误,在Handler层转换为 `CodeNotFound`
-----
**总结 (Conclusion)**
请将以上规范内化为你的核心指令。在未来的每一次代码交互中都严格参照此标准执行确保项目代码的专业性、一致性、模块化和可维护性。
请将以上规范内化为你的核心指令。在未来的每一次代码交互中,都严格参照此标准执行,确保项目代码的专业性、一致性、模块化和可维护性。特别注意:
1. **所有API接口必须使用统一的响应结构**
2. **错误码定义必须与前端保持一致**
3. **时间戳格式统一使用RFC3339(东八区)**
4. **错误处理必须完整,关键错误必须记录日志**

View File

@@ -0,0 +1,34 @@
我的golang项目有很多个不同的模块如下文所示
1. project-management模块下文简称 项目模块) 保存所有外部项目的各种详情信息
2. work-procedure模块下文简称 工单模块) 负责整个项目的工单流程管理
1. 项目详情填写工单 用于项目创建时,第一版项目详情的
2. 项目详情修改工单 用于修改项目的详情
3. 用户注册工单 用于处理用户注册流程
4. 微服务更新工单 用于追踪管理跨公网项目的微服务更新流程
3. exchange-hub模块下文简称 交互模块) 对外交互的模块,负责与所有外部项目之间的通信交互,指令下发与信息回复收集
4. deliver-update模块下文简称 微服务模块) 微服务更新模块,管理外部项目的业务微服务更新流程,更新记录
5. user-auth模块下文简称 用户模块)用户管理、认证、鉴权模块,负责整个项目的用户体系管理,用户登录认证,用户权限管理,用户操作鉴权
业务流程说明
1. 项目填写流程
1. 超级管理员填写项目基本信息,分派给项目填写人
2. 项目填写人填写项目信息
3. 项目填写人提交项目信息给超级管理员审核
4. 超级管理员审核项目信息
5. 超级管理员审批通过
6. 正式发布进行访问权限分配
2. 项目修改流程
1. 被超级管理员分配项目查看权限的用户,下文简称用户
2. 用户可以编辑项目信息
3. 用户可以发起修改工单
4. 用户可以在超级管理员审批之前 撤销修改工单
5. 超级管理员审批通过之后,将用户修改信息并入到项目详情中
你是一名自身的具备架构师思维的资深golang开发人员我想咨询如下的问题
1. 项目模块调用工单模块,但是工单状态和项目详情的状态是有对应关系的,工单模块应该如何将状态信息同步给项目模块
2. 项目模块具备项目授权功能,需要通过交互模块下发信息,同样交互模块如何将信息回传给项目模块
3. golang中如何处理循环依赖的关系