bindbox-game/docs/开发规范/APP端开发统一规范.md
邹方成 1ab39d2f5a
Some checks failed
Build docker and publish / linux (1.24.5) (push) Failing after 25s
refactor: 重构项目结构并重命名模块
feat(admin): 新增工会管理功能
feat(activity): 添加活动管理相关服务
feat(user): 实现用户道具卡和积分管理
feat(guild): 新增工会成员管理功能

fix: 修复数据库连接配置
fix: 修正jwtoken导入路径
fix: 解决端口冲突问题

style: 统一代码格式和注释风格
style: 更新项目常量命名

docs: 添加项目框架和开发规范文档
docs: 更新接口文档注释

chore: 移除无用代码和文件
chore: 更新Makefile和配置文件
chore: 清理日志文件

test: 添加道具卡测试脚本
2025-11-14 21:10:00 +08:00

147 lines
5.0 KiB
Markdown
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.

# APP 端开发统一规范
## 1. 目标
统一 APP 端接口的目录结构、编码范式、错误处理与文档注释确保与管理端admin 模块)保持一致的风格与契约。
## 2. 目录结构
- 模块放置:`internal/api/activity/`
- 每个端点单文件:
- `activity_create.go`
- `activity_issue_add.go`
- `activity_list.go`
- `activity_detail.go`
- `activity_issues_list.go`
- `issue_rewards_list.go`
## 3. Handler 初始化
- 在模块根定义 `handler``New(logger, db)`,注入 `writeDB`/`readDB`
- 路由绑定示例:`appHandler := app.New(logger, db)`,方法统一返回 `core.HandlerFunc`
## 4. 请求/响应范式
- 所有接口必须定义 `Request``Response` 结构体
- 成功统一:`ctx.Payload(res)``res.Message` 使用统一文案 `操作成功`
## 5. 参数绑定与校验
- JSON`ctx.ShouldBindJSON(req)`
- 表单/查询:`ctx.ShouldBindForm(req)`
- 绑定错误:`ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err)))`
## 6. 业务错误处理
- 统一:`ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ServerError, err.Error()))`
- 业务码:在 `internal/code/` 中约定并使用具体业务码
## 7. 分页与过滤规范
- 分页:`page` 默认 1、`page_size` 默认 20、最大 100超过返回参数错误
- 过滤:字符串使用 `Like("%xxx%")`,数值/枚举使用 `Eq(...)``is_boss` 仅允许 `0/1`
## 8. 路径参数规范
- 使用 `strconv.Atoi` 并校验 `> 0`,非法返回 `ParamBindError`
## 9. 时间规范
- 入参解析:`timeutil.ParseCSTInLocation`
- 响应时间:`FriendlyTime` 或固定格式化 `2006-01-02 15:04`
## 10. Swagger 注释规范
- 标签APP 端统一使用 `@Tags APP端.活动`(或模块名)
- 必填注释:`@Summary/@Description/@Accept/@Produce/@Param/@Success/@Failure/@Router`
## 11. 统一 Handler 模板(示例)
以下示例来自 `internal/api/activity/activity_issues_list.go:46-127`,作为 APP 端列表接口标准参考:
```go
// ListActivityIssues 活动期列表
// @Summary 活动期列表
// @Description 获取指定活动的期列表,支持分页
// @Tags APP端.活动
// @Accept json
// @Produce json
// @Param activity_id path int true "活动ID"
// @Param page query int true "页码" default(1)
// @Param page_size query int true "每页数量最多100" default(20)
// @Success 200 {object} listIssuesResponse
// @Failure 400 {object} code.Failure
// @Router /api/app/activities/{activity_id}/issues [get]
func (h *handler) ListActivityIssues() core.HandlerFunc {
return func(ctx core.Context) {
idStr := ctx.Param("activity_id")
id, err := strconv.Atoi(idStr)
if err != nil || id <= 0 {
ctx.AbortWithError(core.Error(
http.StatusBadRequest,
code.ParamBindError,
"活动ID无效"),
)
return
}
req := new(listIssuesRequest)
res := new(listIssuesResponse)
if err := ctx.ShouldBindForm(req); err != nil {
ctx.AbortWithError(core.Error(
http.StatusBadRequest,
code.ParamBindError,
validation.Error(err)),
)
return
}
if req.Page == 0 { req.Page = 1 }
if req.PageSize == 0 { req.PageSize = 20 }
if req.PageSize > 100 {
ctx.AbortWithError(core.Error(
http.StatusBadRequest,
code.ParamBindError,
"每页最多100条"),
)
return
}
query := h.readDB.ActivityIssues.WithContext(ctx.RequestContext()).
Where(h.readDB.ActivityIssues.ActivityID.Eq(int64(id)))
listQuery := query
countQuery := query
issues, err := listQuery.Order(h.readDB.ActivityIssues.ID.Desc()).
Limit(req.PageSize).Offset((req.Page-1)*req.PageSize).Find()
if err != nil {
ctx.AbortWithError(core.Error(
http.StatusBadRequest,
code.ServerError,
err.Error()),
)
return
}
total, err := countQuery.Count()
if err != nil {
ctx.AbortWithError(core.Error(
http.StatusBadRequest,
code.ServerError,
err.Error()),
)
return
}
res.Page = req.Page
res.PageSize = req.PageSize
res.Total = total
res.List = make([]issueListItem, len(issues))
for i, v := range issues {
res.List[i] = issueListItem{
ID: v.ID,
IssueNumber: v.IssueNumber,
Status: v.Status,
Sort: v.Sort,
CreatedAt: timeutil.FriendlyTime(v.CreatedAt),
UpdatedAt: timeutil.FriendlyTime(v.UpdatedAt),
}
}
ctx.Payload(res)
}
}
```
## 12. 文档生成与预览
- 生成:`make gen-swagger`
- 预览:`make serve-swagger`(默认端口 `36666`,访问 `http://localhost:36666/docs`