完成任务4

This commit is contained in:
2025-10-30 17:15:14 +08:00
parent f0982839e0
commit d235130d11
11 changed files with 531 additions and 765 deletions

View File

@@ -8,7 +8,7 @@ import (
"git.huangwc.com/pig/pig-farm-controller/internal/app/dto"
"git.huangwc.com/pig/pig-farm-controller/internal/app/service"
"git.huangwc.com/pig/pig-farm-controller/internal/infra/logs"
"github.com/gin-gonic/gin"
"github.com/labstack/echo/v4"
)
// --- 控制器定义 ---
@@ -31,7 +31,7 @@ func NewPigFarmController(logger *logs.Logger, service service.PigFarmService) *
// CreatePigHouse godoc
// @Summary 创建猪舍
// @Description 创建一个新猪舍
// @Description 根据提供的信息创建一个新猪舍
// @Tags 猪场管理
// @Security BearerAuth
// @Accept json
@@ -39,19 +39,18 @@ func NewPigFarmController(logger *logs.Logger, service service.PigFarmService) *
// @Param body body dto.CreatePigHouseRequest true "猪舍信息"
// @Success 201 {object} controller.Response{data=dto.PigHouseResponse} "创建成功"
// @Router /api/v1/pig-houses [post]
func (c *PigFarmController) CreatePigHouse(ctx *gin.Context) {
func (c *PigFarmController) CreatePigHouse(ctx echo.Context) error {
const action = "创建猪舍"
var req dto.CreatePigHouseRequest
if err := ctx.ShouldBindJSON(&req); err != nil {
controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的请求体", action, "请求体绑定失败", req)
return
if err := ctx.Bind(&req); err != nil {
c.logger.Errorf("%s: 参数绑定失败: %v", action, err)
return controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的请求体", action, "请求体绑定失败", req)
}
house, err := c.service.CreatePigHouse(req.Name, req.Description)
if err != nil {
c.logger.Errorf("%s: 业务逻辑失败: %v", action, err)
controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "创建猪舍失败", action, "业务逻辑失败", req)
return
return controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "创建猪舍失败", action, "业务逻辑失败", req)
}
resp := dto.PigHouseResponse{
@@ -59,7 +58,7 @@ func (c *PigFarmController) CreatePigHouse(ctx *gin.Context) {
Name: house.Name,
Description: house.Description,
}
controller.SendSuccessWithAudit(ctx, controller.CodeCreated, "创建成功", resp, action, "创建成功", resp)
return controller.SendSuccessWithAudit(ctx, controller.CodeCreated, "创建成功", resp, action, "创建成功", resp)
}
// GetPigHouse godoc
@@ -71,23 +70,20 @@ func (c *PigFarmController) CreatePigHouse(ctx *gin.Context) {
// @Param id path int true "猪舍ID"
// @Success 200 {object} controller.Response{data=dto.PigHouseResponse} "获取成功"
// @Router /api/v1/pig-houses/{id} [get]
func (c *PigFarmController) GetPigHouse(ctx *gin.Context) {
func (c *PigFarmController) GetPigHouse(ctx echo.Context) error {
const action = "获取猪舍"
id, err := strconv.ParseUint(ctx.Param("id"), 10, 32)
if err != nil {
controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的ID格式", action, "ID格式错误", ctx.Param("id"))
return
return controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的ID格式", action, "ID格式错误", ctx.Param("id"))
}
house, err := c.service.GetPigHouseByID(uint(id))
if err != nil {
if errors.Is(err, service.ErrHouseNotFound) {
controller.SendErrorWithAudit(ctx, controller.CodeNotFound, "猪舍不存在", action, "猪舍不存在", id)
return
return controller.SendErrorWithAudit(ctx, controller.CodeNotFound, "猪舍不存在", action, "猪舍不存在", id)
}
c.logger.Errorf("%s: 业务逻辑失败: %v", action, err)
controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "获取猪舍失败", action, "业务逻辑失败", id)
return
return controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "获取猪舍失败", action, "业务逻辑失败", id)
}
resp := dto.PigHouseResponse{
@@ -95,7 +91,7 @@ func (c *PigFarmController) GetPigHouse(ctx *gin.Context) {
Name: house.Name,
Description: house.Description,
}
controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "获取成功", resp, action, "获取成功", resp)
return controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "获取成功", resp, action, "获取成功", resp)
}
// ListPigHouses godoc
@@ -106,13 +102,12 @@ func (c *PigFarmController) GetPigHouse(ctx *gin.Context) {
// @Produce json
// @Success 200 {object} controller.Response{data=[]dto.PigHouseResponse} "获取成功"
// @Router /api/v1/pig-houses [get]
func (c *PigFarmController) ListPigHouses(ctx *gin.Context) {
func (c *PigFarmController) ListPigHouses(ctx echo.Context) error {
const action = "获取猪舍列表"
houses, err := c.service.ListPigHouses()
if err != nil {
c.logger.Errorf("%s: 业务逻辑失败: %v", action, err)
controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "获取列表失败", action, "业务逻辑失败", nil)
return
return controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "获取列表失败", action, "业务逻辑失败", nil)
}
var resp []dto.PigHouseResponse
@@ -124,7 +119,7 @@ func (c *PigFarmController) ListPigHouses(ctx *gin.Context) {
})
}
controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "获取成功", resp, action, "获取成功", resp)
return controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "获取成功", resp, action, "获取成功", resp)
}
// UpdatePigHouse godoc
@@ -138,29 +133,25 @@ func (c *PigFarmController) ListPigHouses(ctx *gin.Context) {
// @Param body body dto.UpdatePigHouseRequest true "猪舍信息"
// @Success 200 {object} controller.Response{data=dto.PigHouseResponse} "更新成功"
// @Router /api/v1/pig-houses/{id} [put]
func (c *PigFarmController) UpdatePigHouse(ctx *gin.Context) {
func (c *PigFarmController) UpdatePigHouse(ctx echo.Context) error {
const action = "更新猪舍"
id, err := strconv.ParseUint(ctx.Param("id"), 10, 32)
if err != nil {
controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的ID格式", action, "ID格式错误", ctx.Param("id"))
return
return controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的ID格式", action, "ID格式错误", ctx.Param("id"))
}
var req dto.UpdatePigHouseRequest
if err := ctx.ShouldBindJSON(&req); err != nil {
controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的请求体", action, "请求体绑定失败", req)
return
if err := ctx.Bind(&req); err != nil {
return controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的请求体", action, "请求体绑定失败", req)
}
house, err := c.service.UpdatePigHouse(uint(id), req.Name, req.Description)
if err != nil {
if errors.Is(err, service.ErrHouseNotFound) {
controller.SendErrorWithAudit(ctx, controller.CodeNotFound, "猪舍不存在", action, "猪舍不存在", id)
return
return controller.SendErrorWithAudit(ctx, controller.CodeNotFound, "猪舍不存在", action, "猪舍不存在", id)
}
c.logger.Errorf("%s: 业务逻辑失败: %v", action, err)
controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "更新失败", action, "业务逻辑失败", req)
return
return controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "更新失败", action, "业务逻辑失败", req)
}
resp := dto.PigHouseResponse{
@@ -168,7 +159,7 @@ func (c *PigFarmController) UpdatePigHouse(ctx *gin.Context) {
Name: house.Name,
Description: house.Description,
}
controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "更新成功", resp, action, "更新成功", resp)
return controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "更新成功", resp, action, "更新成功", resp)
}
// DeletePigHouse godoc
@@ -180,30 +171,26 @@ func (c *PigFarmController) UpdatePigHouse(ctx *gin.Context) {
// @Param id path int true "猪舍ID"
// @Success 200 {object} controller.Response "删除成功"
// @Router /api/v1/pig-houses/{id} [delete]
func (c *PigFarmController) DeletePigHouse(ctx *gin.Context) {
func (c *PigFarmController) DeletePigHouse(ctx echo.Context) error {
const action = "删除猪舍"
id, err := strconv.ParseUint(ctx.Param("id"), 10, 32)
if err != nil {
controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的ID格式", action, "ID格式错误", ctx.Param("id"))
return
return controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的ID格式", action, "ID格式错误", ctx.Param("id"))
}
if err := c.service.DeletePigHouse(uint(id)); err != nil {
if errors.Is(err, service.ErrHouseNotFound) {
controller.SendErrorWithAudit(ctx, controller.CodeNotFound, "猪舍不存在", action, "猪舍不存在", id)
return
return controller.SendErrorWithAudit(ctx, controller.CodeNotFound, "猪舍不存在", action, "猪舍不存在", id)
}
// 检查是否是业务逻辑错误
if errors.Is(err, service.ErrHouseContainsPens) {
controller.SendErrorWithAudit(ctx, controller.CodeConflict, err.Error(), action, err.Error(), id)
return
return controller.SendErrorWithAudit(ctx, controller.CodeConflict, err.Error(), action, err.Error(), id)
}
c.logger.Errorf("%s: 业务逻辑失败: %v", action, err)
controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "删除失败", action, "业务逻辑失败", id)
return
return controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "删除失败", action, "业务逻辑失败", id)
}
controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "删除成功", nil, action, "删除成功", id)
return controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "删除成功", nil, action, "删除成功", id)
}
// --- 猪栏 (Pen) API 实现 ---
@@ -218,24 +205,21 @@ func (c *PigFarmController) DeletePigHouse(ctx *gin.Context) {
// @Param body body dto.CreatePenRequest true "猪栏信息"
// @Success 201 {object} controller.Response{data=dto.PenResponse} "创建成功"
// @Router /api/v1/pens [post]
func (c *PigFarmController) CreatePen(ctx *gin.Context) {
func (c *PigFarmController) CreatePen(ctx echo.Context) error {
const action = "创建猪栏"
var req dto.CreatePenRequest
if err := ctx.ShouldBindJSON(&req); err != nil {
controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的请求体", action, "请求体绑定失败", req)
return
if err := ctx.Bind(&req); err != nil {
return controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的请求体", action, "请求体绑定失败", req)
}
pen, err := c.service.CreatePen(req.PenNumber, req.HouseID, req.Capacity)
if err != nil {
// 检查是否是业务逻辑错误
if errors.Is(err, service.ErrHouseNotFound) {
controller.SendErrorWithAudit(ctx, controller.CodeNotFound, err.Error(), action, err.Error(), req)
return
return controller.SendErrorWithAudit(ctx, controller.CodeNotFound, err.Error(), action, err.Error(), req)
}
c.logger.Errorf("%s: 业务逻辑失败: %v", action, err)
controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "创建猪栏失败", action, "业务逻辑失败", req)
return
return controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "创建猪栏失败", action, "业务逻辑失败", req)
}
resp := dto.PenResponse{
@@ -245,7 +229,7 @@ func (c *PigFarmController) CreatePen(ctx *gin.Context) {
Capacity: pen.Capacity,
Status: pen.Status,
}
controller.SendSuccessWithAudit(ctx, controller.CodeCreated, "创建成功", resp, action, "创建成功", resp)
return controller.SendSuccessWithAudit(ctx, controller.CodeCreated, "创建成功", resp, action, "创建成功", resp)
}
// GetPen godoc
@@ -257,26 +241,23 @@ func (c *PigFarmController) CreatePen(ctx *gin.Context) {
// @Param id path int true "猪栏ID"
// @Success 200 {object} controller.Response{data=dto.PenResponse} "获取成功"
// @Router /api/v1/pens/{id} [get]
func (c *PigFarmController) GetPen(ctx *gin.Context) {
func (c *PigFarmController) GetPen(ctx echo.Context) error {
const action = "获取猪栏"
id, err := strconv.ParseUint(ctx.Param("id"), 10, 32)
if err != nil {
controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的ID格式", action, "ID格式错误", ctx.Param("id"))
return
return controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的ID格式", action, "ID格式错误", ctx.Param("id"))
}
pen, err := c.service.GetPenByID(uint(id))
if err != nil {
if errors.Is(err, service.ErrPenNotFound) {
controller.SendErrorWithAudit(ctx, controller.CodeNotFound, "猪栏不存在", action, "猪栏不存在", id)
return
return controller.SendErrorWithAudit(ctx, controller.CodeNotFound, "猪栏不存在", action, "猪栏不存在", id)
}
c.logger.Errorf("%s: 业务逻辑失败: %v", action, err)
controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "获取猪栏失败", action, "业务逻辑失败", id)
return
return controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "获取猪栏失败", action, "业务逻辑失败", id)
}
controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "获取成功", pen, action, "获取成功", pen)
return controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "获取成功", pen, action, "获取成功", pen)
}
// ListPens godoc
@@ -287,16 +268,15 @@ func (c *PigFarmController) GetPen(ctx *gin.Context) {
// @Produce json
// @Success 200 {object} controller.Response{data=[]dto.PenResponse} "获取成功"
// @Router /api/v1/pens [get]
func (c *PigFarmController) ListPens(ctx *gin.Context) {
func (c *PigFarmController) ListPens(ctx echo.Context) error {
const action = "获取猪栏列表"
pens, err := c.service.ListPens()
if err != nil {
c.logger.Errorf("%s: 业务逻辑失败: %v", action, err)
controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "获取列表失败", action, "业务逻辑失败", nil)
return
return controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "获取列表失败", action, "业务逻辑失败", nil)
}
controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "获取成功", pens, action, "获取成功", pens)
return controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "获取成功", pens, action, "获取成功", pens)
}
// UpdatePen godoc
@@ -310,30 +290,26 @@ func (c *PigFarmController) ListPens(ctx *gin.Context) {
// @Param body body dto.UpdatePenRequest true "猪栏信息"
// @Success 200 {object} controller.Response{data=dto.PenResponse} "更新成功"
// @Router /api/v1/pens/{id} [put]
func (c *PigFarmController) UpdatePen(ctx *gin.Context) {
func (c *PigFarmController) UpdatePen(ctx echo.Context) error {
const action = "更新猪栏"
id, err := strconv.ParseUint(ctx.Param("id"), 10, 32)
if err != nil {
controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的ID格式", action, "ID格式错误", ctx.Param("id"))
return
return controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的ID格式", action, "ID格式错误", ctx.Param("id"))
}
var req dto.UpdatePenRequest
if err := ctx.ShouldBindJSON(&req); err != nil {
controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的请求体", action, "请求体绑定失败", req)
return
if err := ctx.Bind(&req); err != nil {
return controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的请求体", action, "请求体绑定失败", req)
}
pen, err := c.service.UpdatePen(uint(id), req.PenNumber, req.HouseID, req.Capacity, req.Status)
if err != nil {
if errors.Is(err, service.ErrPenNotFound) {
controller.SendErrorWithAudit(ctx, controller.CodeNotFound, "猪栏不存在", action, "猪栏不存在", id)
return
return controller.SendErrorWithAudit(ctx, controller.CodeNotFound, "猪栏不存在", action, "猪栏不存在", id)
}
// 其他业务逻辑错误可以在这里添加处理
c.logger.Errorf("%s: 业务逻辑失败: %v", action, err)
controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "更新失败", action, "业务逻辑失败", req)
return
return controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "更新失败", action, "业务逻辑失败", req)
}
resp := dto.PenResponse{
@@ -344,7 +320,7 @@ func (c *PigFarmController) UpdatePen(ctx *gin.Context) {
Status: pen.Status,
PigBatchID: pen.PigBatchID,
}
controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "更新成功", resp, action, "更新成功", resp)
return controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "更新成功", resp, action, "更新成功", resp)
}
// DeletePen godoc
@@ -356,30 +332,26 @@ func (c *PigFarmController) UpdatePen(ctx *gin.Context) {
// @Param id path int true "猪栏ID"
// @Success 200 {object} controller.Response "删除成功"
// @Router /api/v1/pens/{id} [delete]
func (c *PigFarmController) DeletePen(ctx *gin.Context) {
func (c *PigFarmController) DeletePen(ctx echo.Context) error {
const action = "删除猪栏"
id, err := strconv.ParseUint(ctx.Param("id"), 10, 32)
if err != nil {
controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的ID格式", action, "ID格式错误", ctx.Param("id"))
return
return controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的ID格式", action, "ID格式错误", ctx.Param("id"))
}
if err := c.service.DeletePen(uint(id)); err != nil {
if errors.Is(err, service.ErrPenNotFound) {
controller.SendErrorWithAudit(ctx, controller.CodeNotFound, "猪栏不存在", action, "猪栏不存在", id)
return
return controller.SendErrorWithAudit(ctx, controller.CodeNotFound, "猪栏不存在", action, "猪栏不存在", id)
}
// 检查是否是业务逻辑错误
if errors.Is(err, service.ErrPenInUse) {
controller.SendErrorWithAudit(ctx, controller.CodeConflict, err.Error(), action, err.Error(), id)
return
return controller.SendErrorWithAudit(ctx, controller.CodeConflict, err.Error(), action, err.Error(), id)
}
c.logger.Errorf("%s: 业务逻辑失败: %v", action, err)
controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "删除失败", action, "业务逻辑失败", id)
return
return controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "删除失败", action, "业务逻辑失败", id)
}
controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "删除成功", nil, action, "删除成功", id)
return controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "删除成功", nil, action, "删除成功", id)
}
// UpdatePenStatus godoc
@@ -393,32 +365,27 @@ func (c *PigFarmController) DeletePen(ctx *gin.Context) {
// @Param body body dto.UpdatePenStatusRequest true "新的猪栏状态"
// @Success 200 {object} controller.Response{data=dto.PenResponse} "更新成功"
// @Router /api/v1/pens/{id}/status [put]
func (c *PigFarmController) UpdatePenStatus(ctx *gin.Context) {
func (c *PigFarmController) UpdatePenStatus(ctx echo.Context) error {
const action = "更新猪栏状态"
id, err := strconv.ParseUint(ctx.Param("id"), 10, 32)
if err != nil {
controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的ID格式", action, "ID格式错误", ctx.Param("id"))
return
return controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的ID格式", action, "ID格式错误", ctx.Param("id"))
}
var req dto.UpdatePenStatusRequest
if err := ctx.ShouldBindJSON(&req); err != nil {
controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的请求体", action, "请求体绑定失败", req)
return
if err := ctx.Bind(&req); err != nil {
return controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的请求体", action, "请求体绑定失败", req)
}
pen, err := c.service.UpdatePenStatus(uint(id), req.Status)
if err != nil {
if errors.Is(err, service.ErrPenNotFound) {
controller.SendErrorWithAudit(ctx, controller.CodeNotFound, err.Error(), action, err.Error(), id)
return
return controller.SendErrorWithAudit(ctx, controller.CodeNotFound, err.Error(), action, err.Error(), id)
} else if errors.Is(err, service.ErrPenStatusInvalidForOccupiedPen) || errors.Is(err, service.ErrPenStatusInvalidForUnoccupiedPen) {
controller.SendErrorWithAudit(ctx, controller.CodeConflict, err.Error(), action, err.Error(), id)
return
return controller.SendErrorWithAudit(ctx, controller.CodeConflict, err.Error(), action, err.Error(), id)
}
c.logger.Errorf("%s: 业务逻辑失败: %v", action, err)
controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "更新猪栏状态失败", action, err.Error(), id)
return
return controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "更新猪栏状态失败", action, err.Error(), id)
}
resp := dto.PenResponse{
@@ -429,5 +396,5 @@ func (c *PigFarmController) UpdatePenStatus(ctx *gin.Context) {
Status: pen.Status,
PigBatchID: pen.PigBatchID,
}
controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "更新成功", resp, action, "更新成功", resp)
return controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "更新成功", resp, action, "更新成功", resp)
}