Skip to content

Latest commit

 

History

History
213 lines (148 loc) · 5.77 KB

File metadata and controls

213 lines (148 loc) · 5.77 KB

开发指南

本文说明在 CloudQue API 中新增或维护功能时应遵循的本地开发流程。项目已有清晰的 Controller、Service、Repository、DTO、Entity 分层,新增能力优先复用现有模块模式。

本地准备

go mod tidy
Copy-Item configs/config.yaml.example configs/config.yaml

修改 configs/config.yaml 后启动:

go run cmd/server/main.go

常用检查:

go test ./...
go fmt ./...
go vet ./...

也可以使用:

make run
make test
make fmt
make vet

新增业务模块流程

1. 定义数据库实体

internal/model/entity 下创建实体,只表达数据库字段和表关系。

package entity

// Example 示例实体
type Example struct {
	BaseEntity
	Name string `gorm:"type:varchar(100);not null" json:"name"`
}

// TableName 返回表名
func (Example) TableName() string {
	return "examples"
}

新增实体后,在 internal/app/app.goinitDatabase 中加入 AutoMigrate

2. 定义 DTO

请求结构放在 internal/model/dto/request,响应结构放在 internal/model/dto/response。Controller 使用 DTO 绑定参数,避免直接暴露 Entity。

package request

// CreateExampleRequest 创建示例请求
type CreateExampleRequest struct {
	Name string `json:"name" binding:"required"`
}

3. 定义 Repository 接口和实现

接口文件命名为 xxx_interface.go,实现文件命名为 xxx_repository.go

type ExampleRepository interface {
	FindByID(id int) (*entity.Example, error)
	Create(example *entity.Example) error
}

Repository 只处理数据访问,不写 HTTP、权限、日志和业务编排逻辑。

4. 定义 Service 接口和实现

Service 负责业务规则、事务、跨 Repository 编排和远程能力调用。

type ExampleService interface {
	Create(req *request.CreateExampleRequest) error
	GetByID(id int) (*entity.Example, error)
}

如果能力需要远程服务器,优先复用 AuthServiceExecServiceFileServiceTerminalServicessh.SessionManager 的现有逻辑。

5. 定义 Controller 和路由

Controller 放在 internal/api/v1/<module>,常见结构是 controller.goroutes.go

func (ctrl *Controller) RegisterRoutes(r *gin.RouterGroup) {
	group := r.Group("/example")
	group.Use(middleware.Auth())
	group.Use(middleware.RequirePermission(ctrl.authService))
	group.Use(middleware.CaptureRawBody())
	group.Use(middleware.GlobalLogManager.UserOperationLogs())
	{
		group.POST("", middleware.WithOperation("创建示例"), ctrl.Create)
	}
}

Controller 只做参数绑定、上下文读取、调用 Service 和返回响应。

6. 接入应用装配

internal/app/app.goinitDependencies 中创建 Repository 和 Service,再传入 api.NewRouter。在 internal/api/router.go 中添加 Controller 字段、构造参数和路由注册。

现有模块维护要点

认证

  • 登录、登出、刷新 Token、验证码、密码重置位于 internal/api/v1/auth
  • 权限判断集中在 AuthServiceRequirePermission 中间件
  • SSH 会话依赖用户登录凭证和远程服务器配置

用户和管理员

  • 普通用户接口位于 /api/v1/user
  • 管理员用户维护位于 /api/v1/admin
  • 用户注册、密码修改、管理员创建用户会涉及远程服务器用户或 SSH 凭证逻辑,修改前要核对 user_service.goauth_service.go

权限、菜单和角色

  • API 权限:/api/v1/permissionManage/API
  • 菜单:/api/v1/permissionManage/menus
  • 角色:/api/v1/permissionManage/roles
  • 权限数据同时影响接口访问和前端菜单展示,修改时要同步检查角色权限聚合逻辑

任务、队列和 GPU

  • 任务接口位于 /api/v1/job
  • 队列接口位于 /api/v1/queue
  • 调度器位于 internal/service/scheduler_service.go
  • 任务执行依赖 ExecService 和 SSH 会话
  • GPU 占用和释放由 GpuService 和调度器协作完成

文件和终端

  • 文件接口位于 /api/v1/files/api/v1/directories
  • 终端接口位于 /api/v1/terminal/ws
  • 两者都依赖远程 SSH/SFTP,修改时优先保持路径解析、root 模式和用户目录隔离逻辑稳定

系统信息和首页

  • 系统实时信息位于 /api/v1/system
  • 首页概览位于 /api/v1/home
  • WebSocket 推送由对应 Service 和 pkg/websocket 连接池管理

操作日志

  • 用户操作日志通过中间件捕获
  • 管理员关机重启日志有独立接口
  • 新增需要记录的写操作时,路由上添加 middleware.WithOperation("中文操作名")

响应和错误

统一使用 pkg/response 返回 JSON:

response.Success(c, data)
response.BizError(c, err)
response.BadRequest(c, "参数错误")

业务错误使用 pkg/errors 中的错误码。新增错误码时同时补充错误消息。

日志规范

业务日志使用 pkg/logger

logger.Info("任务提交成功", zap.Int("job_id", jobID))
logger.Warn("任务取消失败", zap.Error(err))

日志文本保持简洁中文描述。不要在日志中输出密码、Token、私钥、验证码等敏感信息。

配置规范

  • configs/config.yaml.example 只保留示例值
  • configs/config.yaml 保存本地真实配置,不应提交真实敏感信息
  • 新增配置项时同步更新 pkg/config/config.goconfigs/config.yaml.example 和 README 配置说明

文档同步

新增、删除或调整接口时,同步更新:

  • README.md 的模块概览
  • docs/API.md 的接口清单
  • docs/ARCHITECTURE.md 的模块说明
  • 相关协议文档,如 docs/terminal_ws_spec.md

提交前检查

go fmt ./...
go test ./...
go vet ./...

如果只改文档,至少检查 Markdown 文件可读、链接存在、接口路径与路由文件一致。