Compare commits
	
		
			2 Commits
		
	
	
		
			b0ce191aff
			...
			69bdc50b3e
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 69bdc50b3e | |||
| b3322fe367 | 
@@ -2,7 +2,6 @@ package device
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"errors"
 | 
						"errors"
 | 
				
			||||||
	"net/http"
 | 
					 | 
				
			||||||
	"strconv"
 | 
						"strconv"
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
@@ -112,7 +111,7 @@ func (c *Controller) CreateDevice(ctx *gin.Context) {
 | 
				
			|||||||
	var req CreateDeviceRequest
 | 
						var req CreateDeviceRequest
 | 
				
			||||||
	if err := ctx.ShouldBindJSON(&req); err != nil {
 | 
						if err := ctx.ShouldBindJSON(&req); err != nil {
 | 
				
			||||||
		c.logger.Errorf("创建设备: 参数绑定失败: %v", err)
 | 
							c.logger.Errorf("创建设备: 参数绑定失败: %v", err)
 | 
				
			||||||
		controller.SendErrorResponse(ctx, http.StatusBadRequest, err.Error())
 | 
							controller.SendErrorResponse(ctx, controller.CodeBadRequest, err.Error())
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -127,11 +126,11 @@ func (c *Controller) CreateDevice(ctx *gin.Context) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	if err := c.repo.Create(device); err != nil {
 | 
						if err := c.repo.Create(device); err != nil {
 | 
				
			||||||
		c.logger.Errorf("创建设备: 数据库操作失败: %v", err)
 | 
							c.logger.Errorf("创建设备: 数据库操作失败: %v", err)
 | 
				
			||||||
		controller.SendErrorResponse(ctx, http.StatusInternalServerError, "创建设备失败")
 | 
							controller.SendErrorResponse(ctx, controller.CodeInternalError, "创建设备失败")
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	controller.SendResponse(ctx, http.StatusCreated, "设备创建成功", newDeviceResponse(device))
 | 
						controller.SendResponse(ctx, controller.CodeCreated, "设备创建成功", newDeviceResponse(device))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetDevice godoc
 | 
					// GetDevice godoc
 | 
				
			||||||
@@ -149,19 +148,19 @@ func (c *Controller) GetDevice(ctx *gin.Context) {
 | 
				
			|||||||
	device, err := c.repo.FindByIDString(deviceID)
 | 
						device, err := c.repo.FindByIDString(deviceID)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		if errors.Is(err, gorm.ErrRecordNotFound) {
 | 
							if errors.Is(err, gorm.ErrRecordNotFound) {
 | 
				
			||||||
			controller.SendErrorResponse(ctx, http.StatusNotFound, "设备未找到")
 | 
								controller.SendErrorResponse(ctx, controller.CodeNotFound, "设备未找到")
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if strings.Contains(err.Error(), "无效的设备ID格式") {
 | 
							if strings.Contains(err.Error(), "无效的设备ID格式") {
 | 
				
			||||||
			controller.SendErrorResponse(ctx, http.StatusBadRequest, err.Error())
 | 
								controller.SendErrorResponse(ctx, controller.CodeBadRequest, err.Error())
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		c.logger.Errorf("获取设备: 数据库操作失败: %v", err)
 | 
							c.logger.Errorf("获取设备: 数据库操作失败: %v", err)
 | 
				
			||||||
		controller.SendErrorResponse(ctx, http.StatusInternalServerError, "获取设备信息失败")
 | 
							controller.SendErrorResponse(ctx, controller.CodeInternalError, "获取设备信息失败")
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	controller.SendResponse(ctx, http.StatusOK, "获取设备信息成功", newDeviceResponse(device))
 | 
						controller.SendResponse(ctx, controller.CodeSuccess, "获取设备信息成功", newDeviceResponse(device))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ListDevices godoc
 | 
					// ListDevices godoc
 | 
				
			||||||
@@ -176,11 +175,11 @@ func (c *Controller) ListDevices(ctx *gin.Context) {
 | 
				
			|||||||
	devices, err := c.repo.ListAll()
 | 
						devices, err := c.repo.ListAll()
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		c.logger.Errorf("获取设备列表: 数据库操作失败: %v", err)
 | 
							c.logger.Errorf("获取设备列表: 数据库操作失败: %v", err)
 | 
				
			||||||
		controller.SendErrorResponse(ctx, http.StatusInternalServerError, "获取设备列表失败")
 | 
							controller.SendErrorResponse(ctx, controller.CodeInternalError, "获取设备列表失败")
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	controller.SendResponse(ctx, http.StatusOK, "获取设备列表成功", newListDeviceResponse(devices))
 | 
						controller.SendResponse(ctx, controller.CodeSuccess, "获取设备列表成功", newListDeviceResponse(devices))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// UpdateDevice godoc
 | 
					// UpdateDevice godoc
 | 
				
			||||||
@@ -201,15 +200,15 @@ func (c *Controller) UpdateDevice(ctx *gin.Context) {
 | 
				
			|||||||
	existingDevice, err := c.repo.FindByIDString(deviceID)
 | 
						existingDevice, err := c.repo.FindByIDString(deviceID)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		if errors.Is(err, gorm.ErrRecordNotFound) {
 | 
							if errors.Is(err, gorm.ErrRecordNotFound) {
 | 
				
			||||||
			controller.SendErrorResponse(ctx, http.StatusNotFound, "设备未找到")
 | 
								controller.SendErrorResponse(ctx, controller.CodeNotFound, "设备未找到")
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if strings.Contains(err.Error(), "无效的设备ID格式") {
 | 
							if strings.Contains(err.Error(), "无效的设备ID格式") {
 | 
				
			||||||
			controller.SendErrorResponse(ctx, http.StatusBadRequest, err.Error())
 | 
								controller.SendErrorResponse(ctx, controller.CodeBadRequest, err.Error())
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		c.logger.Errorf("更新设备: 查找设备失败: %v", err)
 | 
							c.logger.Errorf("更新设备: 查找设备失败: %v", err)
 | 
				
			||||||
		controller.SendErrorResponse(ctx, http.StatusInternalServerError, "更新设备失败")
 | 
							controller.SendErrorResponse(ctx, controller.CodeInternalError, "更新设备失败")
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -217,7 +216,7 @@ func (c *Controller) UpdateDevice(ctx *gin.Context) {
 | 
				
			|||||||
	var req UpdateDeviceRequest
 | 
						var req UpdateDeviceRequest
 | 
				
			||||||
	if err := ctx.ShouldBindJSON(&req); err != nil {
 | 
						if err := ctx.ShouldBindJSON(&req); err != nil {
 | 
				
			||||||
		c.logger.Errorf("更新设备: 参数绑定失败: %v", err)
 | 
							c.logger.Errorf("更新设备: 参数绑定失败: %v", err)
 | 
				
			||||||
		controller.SendErrorResponse(ctx, http.StatusBadRequest, err.Error())
 | 
							controller.SendErrorResponse(ctx, controller.CodeBadRequest, err.Error())
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -232,11 +231,11 @@ func (c *Controller) UpdateDevice(ctx *gin.Context) {
 | 
				
			|||||||
	// 4. 将修改后的 existingDevice 对象保存回数据库
 | 
						// 4. 将修改后的 existingDevice 对象保存回数据库
 | 
				
			||||||
	if err := c.repo.Update(existingDevice); err != nil {
 | 
						if err := c.repo.Update(existingDevice); err != nil {
 | 
				
			||||||
		c.logger.Errorf("更新设备: 数据库操作失败: %v", err)
 | 
							c.logger.Errorf("更新设备: 数据库操作失败: %v", err)
 | 
				
			||||||
		controller.SendErrorResponse(ctx, http.StatusInternalServerError, "更新设备失败")
 | 
							controller.SendErrorResponse(ctx, controller.CodeInternalError, "更新设备失败")
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	controller.SendResponse(ctx, http.StatusOK, "设备更新成功", newDeviceResponse(existingDevice))
 | 
						controller.SendResponse(ctx, controller.CodeSuccess, "设备更新成功", newDeviceResponse(existingDevice))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// DeleteDevice godoc
 | 
					// DeleteDevice godoc
 | 
				
			||||||
@@ -254,15 +253,15 @@ func (c *Controller) DeleteDevice(ctx *gin.Context) {
 | 
				
			|||||||
	// 我们需要先将字符串ID转换为uint,因为Delete方法需要uint类型
 | 
						// 我们需要先将字符串ID转换为uint,因为Delete方法需要uint类型
 | 
				
			||||||
	idUint, err := strconv.ParseUint(deviceID, 10, 64)
 | 
						idUint, err := strconv.ParseUint(deviceID, 10, 64)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		controller.SendErrorResponse(ctx, http.StatusBadRequest, "无效的设备ID格式")
 | 
							controller.SendErrorResponse(ctx, controller.CodeBadRequest, "无效的设备ID格式")
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := c.repo.Delete(uint(idUint)); err != nil {
 | 
						if err := c.repo.Delete(uint(idUint)); err != nil {
 | 
				
			||||||
		c.logger.Errorf("删除设备: 数据库操作失败: %v", err)
 | 
							c.logger.Errorf("删除设备: 数据库操作失败: %v", err)
 | 
				
			||||||
		controller.SendErrorResponse(ctx, http.StatusInternalServerError, "删除设备失败")
 | 
							controller.SendErrorResponse(ctx, controller.CodeInternalError, "删除设备失败")
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	controller.SendResponse(ctx, http.StatusOK, "设备删除成功", nil)
 | 
						controller.SendResponse(ctx, controller.CodeSuccess, "设备删除成功", nil)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -203,7 +203,7 @@ func TestCreateDevice(t *testing.T) {
 | 
				
			|||||||
				}).Once()
 | 
									}).Once()
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			expectedStatus:  http.StatusOK,
 | 
								expectedStatus:  http.StatusOK,
 | 
				
			||||||
			expectedCode:    http.StatusCreated,
 | 
								expectedCode:    controller.CodeCreated,
 | 
				
			||||||
			expectedMessage: "设备创建成功",
 | 
								expectedMessage: "设备创建成功",
 | 
				
			||||||
			expectedDataFunc: func(data interface{}) bool {
 | 
								expectedDataFunc: func(data interface{}) bool {
 | 
				
			||||||
				dataMap, ok := data.(map[string]interface{})
 | 
									dataMap, ok := data.(map[string]interface{})
 | 
				
			||||||
@@ -236,7 +236,7 @@ func TestCreateDevice(t *testing.T) {
 | 
				
			|||||||
				}).Once()
 | 
									}).Once()
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			expectedStatus:  http.StatusOK,
 | 
								expectedStatus:  http.StatusOK,
 | 
				
			||||||
			expectedCode:    http.StatusCreated,
 | 
								expectedCode:    controller.CodeCreated,
 | 
				
			||||||
			expectedMessage: "设备创建成功",
 | 
								expectedMessage: "设备创建成功",
 | 
				
			||||||
			expectedDataFunc: func(data interface{}) bool {
 | 
								expectedDataFunc: func(data interface{}) bool {
 | 
				
			||||||
				dataMap, ok := data.(map[string]interface{})
 | 
									dataMap, ok := data.(map[string]interface{})
 | 
				
			||||||
@@ -260,7 +260,7 @@ func TestCreateDevice(t *testing.T) {
 | 
				
			|||||||
			},
 | 
								},
 | 
				
			||||||
			mockRepoSetup:    func(m *MockDeviceRepository) {},
 | 
								mockRepoSetup:    func(m *MockDeviceRepository) {},
 | 
				
			||||||
			expectedStatus:   http.StatusOK,
 | 
								expectedStatus:   http.StatusOK,
 | 
				
			||||||
			expectedCode:     http.StatusBadRequest,
 | 
								expectedCode:     controller.CodeBadRequest,
 | 
				
			||||||
			expectedMessage:  "Key: 'CreateDeviceRequest.Name' Error:Field validation for 'Name' failed on the 'required' tag",
 | 
								expectedMessage:  "Key: 'CreateDeviceRequest.Name' Error:Field validation for 'Name' failed on the 'required' tag",
 | 
				
			||||||
			expectedDataFunc: func(data interface{}) bool { return data == nil },
 | 
								expectedDataFunc: func(data interface{}) bool { return data == nil },
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
@@ -275,7 +275,7 @@ func TestCreateDevice(t *testing.T) {
 | 
				
			|||||||
				m.On("Create", mock.Anything).Return(errors.New("db error")).Once()
 | 
									m.On("Create", mock.Anything).Return(errors.New("db error")).Once()
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			expectedStatus:   http.StatusOK,
 | 
								expectedStatus:   http.StatusOK,
 | 
				
			||||||
			expectedCode:     http.StatusInternalServerError,
 | 
								expectedCode:     controller.CodeInternalError,
 | 
				
			||||||
			expectedMessage:  "创建设备失败",
 | 
								expectedMessage:  "创建设备失败",
 | 
				
			||||||
			expectedDataFunc: func(data interface{}) bool { return data == nil },
 | 
								expectedDataFunc: func(data interface{}) bool { return data == nil },
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
@@ -300,7 +300,7 @@ func TestCreateDevice(t *testing.T) {
 | 
				
			|||||||
				}).Once()
 | 
									}).Once()
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			expectedStatus:   http.StatusOK,                // HTTP status is 200 OK for business errors
 | 
								expectedStatus:   http.StatusOK,                // HTTP status is 200 OK for business errors
 | 
				
			||||||
			expectedCode:     http.StatusInternalServerError, // Business code for internal server error
 | 
								expectedCode:     controller.CodeInternalError, // Business code for internal server error
 | 
				
			||||||
			expectedMessage:  "创建设备失败",                     // The message returned by the controller
 | 
								expectedMessage:  "创建设备失败",                     // The message returned by the controller
 | 
				
			||||||
			expectedDataFunc: func(data interface{}) bool { return data == nil },
 | 
								expectedDataFunc: func(data interface{}) bool { return data == nil },
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
@@ -338,7 +338,7 @@ func TestGetDevice(t *testing.T) {
 | 
				
			|||||||
				}, nil).Once()
 | 
									}, nil).Once()
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			expectedStatus:  http.StatusOK,
 | 
								expectedStatus:  http.StatusOK,
 | 
				
			||||||
			expectedCode:    http.StatusOK,
 | 
								expectedCode:    controller.CodeSuccess,
 | 
				
			||||||
			expectedMessage: "获取设备信息成功",
 | 
								expectedMessage: "获取设备信息成功",
 | 
				
			||||||
			expectedDataFunc: func(data interface{}) bool {
 | 
								expectedDataFunc: func(data interface{}) bool {
 | 
				
			||||||
				dataMap, ok := data.(map[string]interface{})
 | 
									dataMap, ok := data.(map[string]interface{})
 | 
				
			||||||
@@ -359,7 +359,7 @@ func TestGetDevice(t *testing.T) {
 | 
				
			|||||||
				m.On("FindByIDString", "999").Return(nil, gorm.ErrRecordNotFound).Once()
 | 
									m.On("FindByIDString", "999").Return(nil, gorm.ErrRecordNotFound).Once()
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			expectedStatus:   http.StatusOK,
 | 
								expectedStatus:   http.StatusOK,
 | 
				
			||||||
			expectedCode:     http.StatusNotFound,
 | 
								expectedCode:     controller.CodeNotFound,
 | 
				
			||||||
			expectedMessage:  "设备未找到",
 | 
								expectedMessage:  "设备未找到",
 | 
				
			||||||
			expectedDataFunc: func(data interface{}) bool { return data == nil },
 | 
								expectedDataFunc: func(data interface{}) bool { return data == nil },
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
@@ -372,7 +372,7 @@ func TestGetDevice(t *testing.T) {
 | 
				
			|||||||
				m.On("FindByIDString", "abc").Return(nil, errors.New("无效的设备ID格式")).Once()
 | 
									m.On("FindByIDString", "abc").Return(nil, errors.New("无效的设备ID格式")).Once()
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			expectedStatus:   http.StatusOK,
 | 
								expectedStatus:   http.StatusOK,
 | 
				
			||||||
			expectedCode:     http.StatusBadRequest,
 | 
								expectedCode:     controller.CodeBadRequest,
 | 
				
			||||||
			expectedMessage:  "无效的设备ID格式",
 | 
								expectedMessage:  "无效的设备ID格式",
 | 
				
			||||||
			expectedDataFunc: func(data interface{}) bool { return data == nil },
 | 
								expectedDataFunc: func(data interface{}) bool { return data == nil },
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
@@ -385,7 +385,7 @@ func TestGetDevice(t *testing.T) {
 | 
				
			|||||||
				m.On("FindByIDString", "1").Return(nil, errors.New("db error")).Once()
 | 
									m.On("FindByIDString", "1").Return(nil, errors.New("db error")).Once()
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			expectedStatus:   http.StatusOK,
 | 
								expectedStatus:   http.StatusOK,
 | 
				
			||||||
			expectedCode:     http.StatusInternalServerError,
 | 
								expectedCode:     controller.CodeInternalError,
 | 
				
			||||||
			expectedMessage:  "获取设备信息失败",
 | 
								expectedMessage:  "获取设备信息失败",
 | 
				
			||||||
			expectedDataFunc: func(data interface{}) bool { return data == nil },
 | 
								expectedDataFunc: func(data interface{}) bool { return data == nil },
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
@@ -413,7 +413,7 @@ func TestListDevices(t *testing.T) {
 | 
				
			|||||||
				m.On("ListAll").Return([]*models.Device{}, nil).Once()
 | 
									m.On("ListAll").Return([]*models.Device{}, nil).Once()
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			expectedStatus:  http.StatusOK,
 | 
								expectedStatus:  http.StatusOK,
 | 
				
			||||||
			expectedCode:    http.StatusOK,
 | 
								expectedCode:    controller.CodeSuccess,
 | 
				
			||||||
			expectedMessage: "获取设备列表成功",
 | 
								expectedMessage: "获取设备列表成功",
 | 
				
			||||||
			expectedDataFunc: func(data interface{}) bool {
 | 
								expectedDataFunc: func(data interface{}) bool {
 | 
				
			||||||
				s, ok := data.([]interface{})
 | 
									s, ok := data.([]interface{})
 | 
				
			||||||
@@ -450,7 +450,7 @@ func TestListDevices(t *testing.T) {
 | 
				
			|||||||
				}, nil).Once()
 | 
									}, nil).Once()
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			expectedStatus:  http.StatusOK,
 | 
								expectedStatus:  http.StatusOK,
 | 
				
			||||||
			expectedCode:    http.StatusOK,
 | 
								expectedCode:    controller.CodeSuccess,
 | 
				
			||||||
			expectedMessage: "获取设备列表成功",
 | 
								expectedMessage: "获取设备列表成功",
 | 
				
			||||||
			expectedDataFunc: func(data interface{}) bool {
 | 
								expectedDataFunc: func(data interface{}) bool {
 | 
				
			||||||
				dataList, ok := data.([]interface{})
 | 
									dataList, ok := data.([]interface{})
 | 
				
			||||||
@@ -483,7 +483,7 @@ func TestListDevices(t *testing.T) {
 | 
				
			|||||||
				m.On("ListAll").Return(nil, errors.New("db error")).Once()
 | 
									m.On("ListAll").Return(nil, errors.New("db error")).Once()
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			expectedStatus:   http.StatusOK,
 | 
								expectedStatus:   http.StatusOK,
 | 
				
			||||||
			expectedCode:     http.StatusInternalServerError,
 | 
								expectedCode:     controller.CodeInternalError,
 | 
				
			||||||
			expectedMessage:  "获取设备列表失败",
 | 
								expectedMessage:  "获取设备列表失败",
 | 
				
			||||||
			expectedDataFunc: func(data interface{}) bool { return data == nil },
 | 
								expectedDataFunc: func(data interface{}) bool { return data == nil },
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
@@ -529,7 +529,7 @@ func TestUpdateDevice(t *testing.T) {
 | 
				
			|||||||
				m.On("Update", mock.AnythingOfType("*models.Device")).Return(nil).Once()
 | 
									m.On("Update", mock.AnythingOfType("*models.Device")).Return(nil).Once()
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			expectedStatus:  http.StatusOK,
 | 
								expectedStatus:  http.StatusOK,
 | 
				
			||||||
			expectedCode:    http.StatusOK,
 | 
								expectedCode:    controller.CodeSuccess,
 | 
				
			||||||
			expectedMessage: "设备更新成功",
 | 
								expectedMessage: "设备更新成功",
 | 
				
			||||||
			expectedDataFunc: func(data interface{}) bool {
 | 
								expectedDataFunc: func(data interface{}) bool {
 | 
				
			||||||
				dataMap, ok := data.(map[string]interface{})
 | 
									dataMap, ok := data.(map[string]interface{})
 | 
				
			||||||
@@ -555,7 +555,7 @@ func TestUpdateDevice(t *testing.T) {
 | 
				
			|||||||
				m.On("FindByIDString", "1").Return(&models.Device{Model: gorm.Model{ID: 1}}, nil).Once()
 | 
									m.On("FindByIDString", "1").Return(&models.Device{Model: gorm.Model{ID: 1}}, nil).Once()
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			expectedStatus:   http.StatusOK,
 | 
								expectedStatus:   http.StatusOK,
 | 
				
			||||||
			expectedCode:     http.StatusBadRequest,
 | 
								expectedCode:     controller.CodeBadRequest,
 | 
				
			||||||
			expectedMessage:  "Key: 'UpdateDeviceRequest.Name' Error:Field validation for 'Name' failed on the 'required' tag",
 | 
								expectedMessage:  "Key: 'UpdateDeviceRequest.Name' Error:Field validation for 'Name' failed on the 'required' tag",
 | 
				
			||||||
			expectedDataFunc: func(data interface{}) bool { return data == nil },
 | 
								expectedDataFunc: func(data interface{}) bool { return data == nil },
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
@@ -570,7 +570,7 @@ func TestUpdateDevice(t *testing.T) {
 | 
				
			|||||||
				m.On("FindByIDString", "999").Return(nil, gorm.ErrRecordNotFound).Once()
 | 
									m.On("FindByIDString", "999").Return(nil, gorm.ErrRecordNotFound).Once()
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			expectedStatus:   http.StatusOK,
 | 
								expectedStatus:   http.StatusOK,
 | 
				
			||||||
			expectedCode:     http.StatusNotFound,
 | 
								expectedCode:     controller.CodeNotFound,
 | 
				
			||||||
			expectedMessage:  "设备未找到",
 | 
								expectedMessage:  "设备未找到",
 | 
				
			||||||
			expectedDataFunc: func(data interface{}) bool { return data == nil },
 | 
								expectedDataFunc: func(data interface{}) bool { return data == nil },
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
@@ -585,7 +585,7 @@ func TestUpdateDevice(t *testing.T) {
 | 
				
			|||||||
				m.On("FindByIDString", "abc").Return(nil, errors.New("无效的设备ID格式")).Once()
 | 
									m.On("FindByIDString", "abc").Return(nil, errors.New("无效的设备ID格式")).Once()
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			expectedStatus:   http.StatusOK,
 | 
								expectedStatus:   http.StatusOK,
 | 
				
			||||||
			expectedCode:     http.StatusBadRequest,
 | 
								expectedCode:     controller.CodeBadRequest,
 | 
				
			||||||
			expectedMessage:  "无效的设备ID格式",
 | 
								expectedMessage:  "无效的设备ID格式",
 | 
				
			||||||
			expectedDataFunc: func(data interface{}) bool { return data == nil },
 | 
								expectedDataFunc: func(data interface{}) bool { return data == nil },
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
@@ -601,7 +601,7 @@ func TestUpdateDevice(t *testing.T) {
 | 
				
			|||||||
				m.On("Update", mock.AnythingOfType("*models.Device")).Return(errors.New("db error")).Once()
 | 
									m.On("Update", mock.AnythingOfType("*models.Device")).Return(errors.New("db error")).Once()
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			expectedStatus:   http.StatusOK,
 | 
								expectedStatus:   http.StatusOK,
 | 
				
			||||||
			expectedCode:     http.StatusInternalServerError,
 | 
								expectedCode:     controller.CodeInternalError,
 | 
				
			||||||
			expectedMessage:  "更新设备失败",
 | 
								expectedMessage:  "更新设备失败",
 | 
				
			||||||
			expectedDataFunc: func(data interface{}) bool { return data == nil },
 | 
								expectedDataFunc: func(data interface{}) bool { return data == nil },
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
@@ -628,7 +628,7 @@ func TestUpdateDevice(t *testing.T) {
 | 
				
			|||||||
				}).Once()
 | 
									}).Once()
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			expectedStatus:   http.StatusOK,
 | 
								expectedStatus:   http.StatusOK,
 | 
				
			||||||
			expectedCode:     http.StatusInternalServerError, // Expected to be internal server error due to DB error
 | 
								expectedCode:     controller.CodeInternalError, // Expected to be internal server error due to DB error
 | 
				
			||||||
			expectedMessage:  "更新设备失败",                     // The message returned by the controller
 | 
								expectedMessage:  "更新设备失败",                     // The message returned by the controller
 | 
				
			||||||
			expectedDataFunc: func(data interface{}) bool { return data == nil },
 | 
								expectedDataFunc: func(data interface{}) bool { return data == nil },
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
@@ -664,7 +664,7 @@ func TestUpdateDevice(t *testing.T) {
 | 
				
			|||||||
				})).Return(nil).Once()
 | 
									})).Return(nil).Once()
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			expectedStatus:  http.StatusOK,
 | 
								expectedStatus:  http.StatusOK,
 | 
				
			||||||
			expectedCode:    http.StatusOK,
 | 
								expectedCode:    controller.CodeSuccess,
 | 
				
			||||||
			expectedMessage: "设备更新成功",
 | 
								expectedMessage: "设备更新成功",
 | 
				
			||||||
			expectedDataFunc: func(data interface{}) bool {
 | 
								expectedDataFunc: func(data interface{}) bool {
 | 
				
			||||||
				dataMap, ok := data.(map[string]interface{})
 | 
									dataMap, ok := data.(map[string]interface{})
 | 
				
			||||||
@@ -700,7 +700,7 @@ func TestDeleteDevice(t *testing.T) {
 | 
				
			|||||||
				m.On("Delete", uint(1)).Return(nil).Once()
 | 
									m.On("Delete", uint(1)).Return(nil).Once()
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			expectedStatus:   http.StatusOK,
 | 
								expectedStatus:   http.StatusOK,
 | 
				
			||||||
			expectedCode:     http.StatusOK,
 | 
								expectedCode:     controller.CodeSuccess,
 | 
				
			||||||
			expectedMessage:  "设备删除成功",
 | 
								expectedMessage:  "设备删除成功",
 | 
				
			||||||
			expectedDataFunc: func(data interface{}) bool { return data == nil },
 | 
								expectedDataFunc: func(data interface{}) bool { return data == nil },
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
@@ -711,7 +711,7 @@ func TestDeleteDevice(t *testing.T) {
 | 
				
			|||||||
			paramID:          "abc",
 | 
								paramID:          "abc",
 | 
				
			||||||
			mockRepoSetup:    func(m *MockDeviceRepository) {},
 | 
								mockRepoSetup:    func(m *MockDeviceRepository) {},
 | 
				
			||||||
			expectedStatus:   http.StatusOK,
 | 
								expectedStatus:   http.StatusOK,
 | 
				
			||||||
			expectedCode:     http.StatusBadRequest,
 | 
								expectedCode:     controller.CodeBadRequest,
 | 
				
			||||||
			expectedMessage:  "无效的设备ID格式",
 | 
								expectedMessage:  "无效的设备ID格式",
 | 
				
			||||||
			expectedDataFunc: func(data interface{}) bool { return data == nil },
 | 
								expectedDataFunc: func(data interface{}) bool { return data == nil },
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
@@ -724,7 +724,7 @@ func TestDeleteDevice(t *testing.T) {
 | 
				
			|||||||
				m.On("Delete", uint(1)).Return(errors.New("db error")).Once()
 | 
									m.On("Delete", uint(1)).Return(errors.New("db error")).Once()
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			expectedStatus:   http.StatusOK,
 | 
								expectedStatus:   http.StatusOK,
 | 
				
			||||||
			expectedCode:     http.StatusInternalServerError,
 | 
								expectedCode:     controller.CodeInternalError,
 | 
				
			||||||
			expectedMessage:  "删除设备失败",
 | 
								expectedMessage:  "删除设备失败",
 | 
				
			||||||
			expectedDataFunc: func(data interface{}) bool { return data == nil },
 | 
								expectedDataFunc: func(data interface{}) bool { return data == nil },
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
@@ -738,7 +738,7 @@ func TestDeleteDevice(t *testing.T) {
 | 
				
			|||||||
				m.On("Delete", uint(999)).Return(gorm.ErrRecordNotFound).Once()
 | 
									m.On("Delete", uint(999)).Return(gorm.ErrRecordNotFound).Once()
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			expectedStatus:   http.StatusOK,
 | 
								expectedStatus:   http.StatusOK,
 | 
				
			||||||
			expectedCode:     http.StatusInternalServerError, // 当前控制器逻辑会将 ErrRecordNotFound 视为内部错误
 | 
								expectedCode:     controller.CodeInternalError, // 当前控制器逻辑会将 ErrRecordNotFound 视为内部错误
 | 
				
			||||||
			expectedMessage:  "删除设备失败",
 | 
								expectedMessage:  "删除设备失败",
 | 
				
			||||||
			expectedDataFunc: func(data interface{}) bool { return data == nil },
 | 
								expectedDataFunc: func(data interface{}) bool { return data == nil },
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,8 +1,6 @@
 | 
				
			|||||||
package plan
 | 
					package plan
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"net/http"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	"git.huangwc.com/pig/pig-farm-controller/internal/app/controller"
 | 
						"git.huangwc.com/pig/pig-farm-controller/internal/app/controller"
 | 
				
			||||||
	"git.huangwc.com/pig/pig-farm-controller/internal/infra/logs"
 | 
						"git.huangwc.com/pig/pig-farm-controller/internal/infra/logs"
 | 
				
			||||||
	"git.huangwc.com/pig/pig-farm-controller/internal/infra/repository"
 | 
						"git.huangwc.com/pig/pig-farm-controller/internal/infra/repository"
 | 
				
			||||||
@@ -72,7 +70,7 @@ func NewController(logger *logs.Logger, planRepo repository.PlanRepository) *Con
 | 
				
			|||||||
func (pc *Controller) CreatePlan(c *gin.Context) {
 | 
					func (pc *Controller) CreatePlan(c *gin.Context) {
 | 
				
			||||||
	// 占位符:此处应调用服务层或仓库层来创建计划
 | 
						// 占位符:此处应调用服务层或仓库层来创建计划
 | 
				
			||||||
	pc.logger.Infof("收到创建计划请求 (占位符)")
 | 
						pc.logger.Infof("收到创建计划请求 (占位符)")
 | 
				
			||||||
	controller.SendResponse(c, http.StatusCreated, "创建计划接口占位符", PlanResponse{ID: 0, Name: "占位计划"})
 | 
						controller.SendResponse(c, controller.CodeCreated, "创建计划接口占位符", PlanResponse{ID: 0, Name: "占位计划"})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetPlan godoc
 | 
					// GetPlan godoc
 | 
				
			||||||
@@ -87,7 +85,7 @@ func (pc *Controller) CreatePlan(c *gin.Context) {
 | 
				
			|||||||
func (pc *Controller) GetPlan(c *gin.Context) {
 | 
					func (pc *Controller) GetPlan(c *gin.Context) {
 | 
				
			||||||
	// 占位符:此处应调用服务层或仓库层来获取计划
 | 
						// 占位符:此处应调用服务层或仓库层来获取计划
 | 
				
			||||||
	pc.logger.Infof("收到获取计划 (占位符)")
 | 
						pc.logger.Infof("收到获取计划 (占位符)")
 | 
				
			||||||
	controller.SendResponse(c, http.StatusOK, "获取计划接口占位符", ListPlansResponse{Plans: []PlanResponse{}, Total: 0})
 | 
						controller.SendResponse(c, controller.CodeSuccess, "获取计划接口占位符", ListPlansResponse{Plans: []PlanResponse{}, Total: 0})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -102,7 +100,7 @@ func (pc *Controller) GetPlan(c *gin.Context) {
 | 
				
			|||||||
func (pc *Controller) ListPlans(c *gin.Context) {
 | 
					func (pc *Controller) ListPlans(c *gin.Context) {
 | 
				
			||||||
	// 占位符:此处应调用服务层或仓库层来获取计划列表
 | 
						// 占位符:此处应调用服务层或仓库层来获取计划列表
 | 
				
			||||||
	pc.logger.Infof("收到获取计划列表请求 (占位符)")
 | 
						pc.logger.Infof("收到获取计划列表请求 (占位符)")
 | 
				
			||||||
	controller.SendResponse(c, http.StatusOK, "获取计划列表接口占位符", ListPlansResponse{Plans: []PlanResponse{}, Total: 0})
 | 
						controller.SendResponse(c, controller.CodeSuccess, "获取计划列表接口占位符", ListPlansResponse{Plans: []PlanResponse{}, Total: 0})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// UpdatePlan godoc
 | 
					// UpdatePlan godoc
 | 
				
			||||||
@@ -119,7 +117,7 @@ func (pc *Controller) ListPlans(c *gin.Context) {
 | 
				
			|||||||
func (pc *Controller) UpdatePlan(c *gin.Context) {
 | 
					func (pc *Controller) UpdatePlan(c *gin.Context) {
 | 
				
			||||||
	// 占位符:此处应调用服务层或仓库层来更新计划
 | 
						// 占位符:此处应调用服务层或仓库层来更新计划
 | 
				
			||||||
	pc.logger.Infof("收到更新计划请求 (占位符)")
 | 
						pc.logger.Infof("收到更新计划请求 (占位符)")
 | 
				
			||||||
	controller.SendResponse(c, http.StatusOK, "更新计划接口占位符", PlanResponse{ID: 0, Name: "占位计划"})
 | 
						controller.SendResponse(c, controller.CodeSuccess, "更新计划接口占位符", PlanResponse{ID: 0, Name: "占位计划"})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// DeletePlan godoc
 | 
					// DeletePlan godoc
 | 
				
			||||||
@@ -134,7 +132,7 @@ func (pc *Controller) UpdatePlan(c *gin.Context) {
 | 
				
			|||||||
func (pc *Controller) DeletePlan(c *gin.Context) {
 | 
					func (pc *Controller) DeletePlan(c *gin.Context) {
 | 
				
			||||||
	// 占位符:此处应调用服务层或仓库层来删除计划
 | 
						// 占位符:此处应调用服务层或仓库层来删除计划
 | 
				
			||||||
	pc.logger.Infof("收到删除计划请求 (占位符)")
 | 
						pc.logger.Infof("收到删除计划请求 (占位符)")
 | 
				
			||||||
	controller.SendResponse(c, http.StatusOK, "删除计划接口占位符", nil)
 | 
						controller.SendResponse(c, controller.CodeSuccess, "删除计划接口占位符", nil)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// StartPlan godoc
 | 
					// StartPlan godoc
 | 
				
			||||||
@@ -149,7 +147,7 @@ func (pc *Controller) DeletePlan(c *gin.Context) {
 | 
				
			|||||||
func (pc *Controller) StartPlan(c *gin.Context) {
 | 
					func (pc *Controller) StartPlan(c *gin.Context) {
 | 
				
			||||||
	// 占位符:此处应调用服务层或仓库层来启动计划
 | 
						// 占位符:此处应调用服务层或仓库层来启动计划
 | 
				
			||||||
	pc.logger.Infof("收到启动计划请求 (占位符)")
 | 
						pc.logger.Infof("收到启动计划请求 (占位符)")
 | 
				
			||||||
	controller.SendResponse(c, http.StatusOK, "启动计划接口占位符", nil)
 | 
						controller.SendResponse(c, controller.CodeSuccess, "启动计划接口占位符", nil)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// StopPlan godoc
 | 
					// StopPlan godoc
 | 
				
			||||||
@@ -164,5 +162,5 @@ func (pc *Controller) StartPlan(c *gin.Context) {
 | 
				
			|||||||
func (pc *Controller) StopPlan(c *gin.Context) {
 | 
					func (pc *Controller) StopPlan(c *gin.Context) {
 | 
				
			||||||
	// 占位符:此处应调用服务层或仓库层来停止计划
 | 
						// 占位符:此处应调用服务层或仓库层来停止计划
 | 
				
			||||||
	pc.logger.Infof("收到停止计划请求 (占位符)")
 | 
						pc.logger.Infof("收到停止计划请求 (占位符)")
 | 
				
			||||||
	controller.SendResponse(c, http.StatusOK, "停止计划接口占位符", nil)
 | 
						controller.SendResponse(c, controller.CodeSuccess, "停止计划接口占位符", nil)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,6 +7,23 @@ import (
 | 
				
			|||||||
	"github.com/gin-gonic/gin"
 | 
						"github.com/gin-gonic/gin"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// --- 业务状态码 ---
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						// 成功状态码 (2000-2999)
 | 
				
			||||||
 | 
						CodeSuccess = 2000 // 操作成功
 | 
				
			||||||
 | 
						CodeCreated = 2001 // 创建成功
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 客户端错误状态码 (4000-4999)
 | 
				
			||||||
 | 
						CodeBadRequest   = 4000 // 请求参数错误
 | 
				
			||||||
 | 
						CodeUnauthorized = 4001 // 未授权
 | 
				
			||||||
 | 
						CodeNotFound     = 4004 // 资源未找到
 | 
				
			||||||
 | 
						CodeConflict     = 4009 // 资源冲突
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 服务器错误状态码 (5000-5999)
 | 
				
			||||||
 | 
						CodeInternalError      = 5000 // 服务器内部错误
 | 
				
			||||||
 | 
						CodeServiceUnavailable = 5003 // 服务不可用
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// --- 通用响应结构 ---
 | 
					// --- 通用响应结构 ---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Response 定义统一的API响应结构体
 | 
					// Response 定义统一的API响应结构体
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,8 +1,6 @@
 | 
				
			|||||||
package user
 | 
					package user
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"net/http"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	"git.huangwc.com/pig/pig-farm-controller/internal/app/controller"
 | 
						"git.huangwc.com/pig/pig-farm-controller/internal/app/controller"
 | 
				
			||||||
	"git.huangwc.com/pig/pig-farm-controller/internal/app/service/token"
 | 
						"git.huangwc.com/pig/pig-farm-controller/internal/app/service/token"
 | 
				
			||||||
	"git.huangwc.com/pig/pig-farm-controller/internal/infra/logs"
 | 
						"git.huangwc.com/pig/pig-farm-controller/internal/infra/logs"
 | 
				
			||||||
@@ -67,7 +65,7 @@ func (c *Controller) CreateUser(ctx *gin.Context) {
 | 
				
			|||||||
	var req CreateUserRequest
 | 
						var req CreateUserRequest
 | 
				
			||||||
	if err := ctx.ShouldBindJSON(&req); err != nil {
 | 
						if err := ctx.ShouldBindJSON(&req); err != nil {
 | 
				
			||||||
		c.logger.Errorf("创建用户: 参数绑定失败: %v", err)
 | 
							c.logger.Errorf("创建用户: 参数绑定失败: %v", err)
 | 
				
			||||||
		controller.SendErrorResponse(ctx, http.StatusBadRequest, err.Error())
 | 
							controller.SendErrorResponse(ctx, controller.CodeBadRequest, err.Error())
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -82,16 +80,16 @@ func (c *Controller) CreateUser(ctx *gin.Context) {
 | 
				
			|||||||
		// 尝试查询用户,以判断是否是用户名重复导致的错误
 | 
							// 尝试查询用户,以判断是否是用户名重复导致的错误
 | 
				
			||||||
		_, findErr := c.userRepo.FindByUsername(req.Username)
 | 
							_, findErr := c.userRepo.FindByUsername(req.Username)
 | 
				
			||||||
		if findErr == nil { // 如果能找到用户,说明是用户名重复
 | 
							if findErr == nil { // 如果能找到用户,说明是用户名重复
 | 
				
			||||||
			controller.SendErrorResponse(ctx, http.StatusConflict, "用户名已存在")
 | 
								controller.SendErrorResponse(ctx, controller.CodeConflict, "用户名已存在")
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// 其他创建失败的情况
 | 
							// 其他创建失败的情况
 | 
				
			||||||
		controller.SendErrorResponse(ctx, http.StatusInternalServerError, "创建用户失败")
 | 
							controller.SendErrorResponse(ctx, controller.CodeInternalError, "创建用户失败")
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	controller.SendResponse(ctx, http.StatusCreated, "用户创建成功", CreateUserResponse{
 | 
						controller.SendResponse(ctx, controller.CodeCreated, "用户创建成功", CreateUserResponse{
 | 
				
			||||||
		Username: user.Username,
 | 
							Username: user.Username,
 | 
				
			||||||
		ID:       user.ID,
 | 
							ID:       user.ID,
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
@@ -111,23 +109,23 @@ func (c *Controller) Login(ctx *gin.Context) {
 | 
				
			|||||||
	var req LoginRequest
 | 
						var req LoginRequest
 | 
				
			||||||
	if err := ctx.ShouldBindJSON(&req); err != nil {
 | 
						if err := ctx.ShouldBindJSON(&req); err != nil {
 | 
				
			||||||
		c.logger.Errorf("登录: 参数绑定失败: %v", err)
 | 
							c.logger.Errorf("登录: 参数绑定失败: %v", err)
 | 
				
			||||||
		controller.SendErrorResponse(ctx, http.StatusBadRequest, err.Error())
 | 
							controller.SendErrorResponse(ctx, controller.CodeBadRequest, err.Error())
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	user, err := c.userRepo.FindByUsername(req.Username)
 | 
						user, err := c.userRepo.FindByUsername(req.Username)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		if err == gorm.ErrRecordNotFound {
 | 
							if err == gorm.ErrRecordNotFound {
 | 
				
			||||||
			controller.SendErrorResponse(ctx, http.StatusUnauthorized, "用户名或密码不正确")
 | 
								controller.SendErrorResponse(ctx, controller.CodeUnauthorized, "用户名或密码不正确")
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		c.logger.Errorf("登录: 查询用户失败: %v", err)
 | 
							c.logger.Errorf("登录: 查询用户失败: %v", err)
 | 
				
			||||||
		controller.SendErrorResponse(ctx, http.StatusInternalServerError, "登录失败")
 | 
							controller.SendErrorResponse(ctx, controller.CodeInternalError, "登录失败")
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if !user.CheckPassword(req.Password) {
 | 
						if !user.CheckPassword(req.Password) {
 | 
				
			||||||
		controller.SendErrorResponse(ctx, http.StatusUnauthorized, "用户名或密码不正确")
 | 
							controller.SendErrorResponse(ctx, controller.CodeUnauthorized, "用户名或密码不正确")
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -135,11 +133,11 @@ func (c *Controller) Login(ctx *gin.Context) {
 | 
				
			|||||||
	tokenString, err := c.tokenService.GenerateToken(user.ID)
 | 
						tokenString, err := c.tokenService.GenerateToken(user.ID)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		c.logger.Errorf("登录: 生成令牌失败: %v", err)
 | 
							c.logger.Errorf("登录: 生成令牌失败: %v", err)
 | 
				
			||||||
		controller.SendErrorResponse(ctx, http.StatusInternalServerError, "登录失败,无法生成认证信息")
 | 
							controller.SendErrorResponse(ctx, controller.CodeInternalError, "登录失败,无法生成认证信息")
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	controller.SendResponse(ctx, http.StatusOK, "登录成功", LoginResponse{
 | 
						controller.SendResponse(ctx, controller.CodeSuccess, "登录成功", LoginResponse{
 | 
				
			||||||
		Username: user.Username,
 | 
							Username: user.Username,
 | 
				
			||||||
		ID:       user.ID,
 | 
							ID:       user.ID,
 | 
				
			||||||
		Token:    tokenString,
 | 
							Token:    tokenString,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,6 +9,7 @@ import (
 | 
				
			|||||||
	"net/http/httptest"
 | 
						"net/http/httptest"
 | 
				
			||||||
	"testing"
 | 
						"testing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"git.huangwc.com/pig/pig-farm-controller/internal/app/controller"
 | 
				
			||||||
	"git.huangwc.com/pig/pig-farm-controller/internal/app/controller/user"
 | 
						"git.huangwc.com/pig/pig-farm-controller/internal/app/controller/user"
 | 
				
			||||||
	"git.huangwc.com/pig/pig-farm-controller/internal/app/service/token"
 | 
						"git.huangwc.com/pig/pig-farm-controller/internal/app/service/token"
 | 
				
			||||||
	"git.huangwc.com/pig/pig-farm-controller/internal/infra/logs"
 | 
						"git.huangwc.com/pig/pig-farm-controller/internal/infra/logs"
 | 
				
			||||||
@@ -106,7 +107,7 @@ func TestCreateUser(t *testing.T) {
 | 
				
			|||||||
				// 在成功创建用户的路径下,FindByUsername 不会被调用,因此这里不需要设置其期望
 | 
									// 在成功创建用户的路径下,FindByUsername 不会被调用,因此这里不需要设置其期望
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			expectedResponse: map[string]interface{}{
 | 
								expectedResponse: map[string]interface{}{
 | 
				
			||||||
				"code":    float64(http.StatusCreated), // 修改这里:从 http.StatusOK 改为 http.StatusCreated
 | 
									"code":    float64(controller.CodeCreated), // 修改这里:使用自定义状态码
 | 
				
			||||||
				"message": "用户创建成功",
 | 
									"message": "用户创建成功",
 | 
				
			||||||
				"data": map[string]interface{}{
 | 
									"data": map[string]interface{}{
 | 
				
			||||||
					"username": "testuser",
 | 
										"username": "testuser",
 | 
				
			||||||
@@ -124,7 +125,7 @@ func TestCreateUser(t *testing.T) {
 | 
				
			|||||||
				// 不会调用 Create 或 FindByUsername
 | 
									// 不会调用 Create 或 FindByUsername
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			expectedResponse: map[string]interface{}{
 | 
								expectedResponse: map[string]interface{}{
 | 
				
			||||||
				"code":    float64(http.StatusBadRequest),
 | 
									"code":    float64(controller.CodeBadRequest),
 | 
				
			||||||
				"message": "Key: 'CreateUserRequest.Password' Error:Field validation for 'Password' failed on the 'min' tag",
 | 
									"message": "Key: 'CreateUserRequest.Password' Error:Field validation for 'Password' failed on the 'min' tag",
 | 
				
			||||||
				"data":    nil,
 | 
									"data":    nil,
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
@@ -138,7 +139,7 @@ func TestCreateUser(t *testing.T) {
 | 
				
			|||||||
				// 不会调用 Create 或 FindByUsername
 | 
									// 不会调用 Create 或 FindByUsername
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			expectedResponse: map[string]interface{}{
 | 
								expectedResponse: map[string]interface{}{
 | 
				
			||||||
				"code":    float64(http.StatusBadRequest),
 | 
									"code":    float64(controller.CodeBadRequest),
 | 
				
			||||||
				"message": "Key: 'CreateUserRequest.Username' Error:Field validation for 'Username' failed on the 'required' tag",
 | 
									"message": "Key: 'CreateUserRequest.Username' Error:Field validation for 'Username' failed on the 'required' tag",
 | 
				
			||||||
				"data":    nil,
 | 
									"data":    nil,
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
@@ -156,7 +157,7 @@ func TestCreateUser(t *testing.T) {
 | 
				
			|||||||
				m.On("FindByUsername", "existinguser").Return(&models.User{Username: "existinguser"}, nil).Once()
 | 
									m.On("FindByUsername", "existinguser").Return(&models.User{Username: "existinguser"}, nil).Once()
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			expectedResponse: map[string]interface{}{
 | 
								expectedResponse: map[string]interface{}{
 | 
				
			||||||
				"code":    float64(http.StatusConflict),
 | 
									"code":    float64(controller.CodeConflict),
 | 
				
			||||||
				"message": "用户名已存在",
 | 
									"message": "用户名已存在",
 | 
				
			||||||
				"data":    nil,
 | 
									"data":    nil,
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
@@ -174,7 +175,7 @@ func TestCreateUser(t *testing.T) {
 | 
				
			|||||||
				m.On("FindByUsername", "db_error_user").Return(nil, gorm.ErrRecordNotFound).Once()
 | 
									m.On("FindByUsername", "db_error_user").Return(nil, gorm.ErrRecordNotFound).Once()
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			expectedResponse: map[string]interface{}{
 | 
								expectedResponse: map[string]interface{}{
 | 
				
			||||||
				"code":    float64(http.StatusInternalServerError),
 | 
									"code":    float64(controller.CodeInternalError),
 | 
				
			||||||
				"message": "创建用户失败",
 | 
									"message": "创建用户失败",
 | 
				
			||||||
				"data":    nil,
 | 
									"data":    nil,
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
@@ -200,10 +201,10 @@ func TestCreateUser(t *testing.T) {
 | 
				
			|||||||
			tt.mockRepoSetup(mockRepo)
 | 
								tt.mockRepoSetup(mockRepo)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// 创建控制器实例,使用静默日志器
 | 
								// 创建控制器实例,使用静默日志器
 | 
				
			||||||
			controller := user.NewController(mockRepo, silentLogger, nil) // tokenService 在 CreateUser 中未使用,设为 nil
 | 
								userController := user.NewController(mockRepo, silentLogger, nil) // tokenService 在 CreateUser 中未使用,设为 nil
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// 调用被测试的方法
 | 
								// 调用被测试的方法
 | 
				
			||||||
			controller.CreateUser(ctx)
 | 
								userController.CreateUser(ctx)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// 解析响应体
 | 
								// 解析响应体
 | 
				
			||||||
			var responseBody map[string]interface{}
 | 
								var responseBody map[string]interface{}
 | 
				
			||||||
@@ -214,7 +215,7 @@ func TestCreateUser(t *testing.T) {
 | 
				
			|||||||
			assert.Equal(t, tt.expectedResponse["code"], responseBody["code"])
 | 
								assert.Equal(t, tt.expectedResponse["code"], responseBody["code"])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// 断言响应内容 (除了 code 字段)
 | 
								// 断言响应内容 (除了 code 字段)
 | 
				
			||||||
			if tt.expectedResponse["code"] == float64(http.StatusCreated) { // 修改这里:从 http.StatusOK 改为 http.StatusCreated
 | 
								if tt.expectedResponse["code"] == float64(controller.CodeCreated) {
 | 
				
			||||||
				// 确保 data 字段存在且是 map[string]interface{} 类型
 | 
									// 确保 data 字段存在且是 map[string]interface{} 类型
 | 
				
			||||||
				data, ok := responseBody["data"].(map[string]interface{})
 | 
									data, ok := responseBody["data"].(map[string]interface{})
 | 
				
			||||||
				assert.True(t, ok, "响应体中的 data 字段应为 map[string]interface{}")
 | 
									assert.True(t, ok, "响应体中的 data 字段应为 map[string]interface{}")
 | 
				
			||||||
@@ -282,7 +283,7 @@ func TestLogin(t *testing.T) {
 | 
				
			|||||||
				m.On("GenerateToken", uint(1)).Return("mocked_token", nil).Once()
 | 
									m.On("GenerateToken", uint(1)).Return("mocked_token", nil).Once()
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			expectedResponse: map[string]interface{}{
 | 
								expectedResponse: map[string]interface{}{
 | 
				
			||||||
				"code":    float64(http.StatusOK),
 | 
									"code":    float64(controller.CodeSuccess),
 | 
				
			||||||
				"message": "登录成功",
 | 
									"message": "登录成功",
 | 
				
			||||||
				"data": map[string]interface{}{
 | 
									"data": map[string]interface{}{
 | 
				
			||||||
					"username": "loginuser",
 | 
										"username": "loginuser",
 | 
				
			||||||
@@ -300,7 +301,7 @@ func TestLogin(t *testing.T) {
 | 
				
			|||||||
			mockRepoSetup:         func(m *MockUserRepository) {},
 | 
								mockRepoSetup:         func(m *MockUserRepository) {},
 | 
				
			||||||
			mockTokenServiceSetup: func(m *MockTokenService) {},
 | 
								mockTokenServiceSetup: func(m *MockTokenService) {},
 | 
				
			||||||
			expectedResponse: map[string]interface{}{
 | 
								expectedResponse: map[string]interface{}{
 | 
				
			||||||
				"code":    float64(http.StatusBadRequest),
 | 
									"code":    float64(controller.CodeBadRequest),
 | 
				
			||||||
				"message": "Key: 'LoginRequest.Username' Error:Field validation for 'Username' failed on the 'required' tag",
 | 
									"message": "Key: 'LoginRequest.Username' Error:Field validation for 'Username' failed on the 'required' tag",
 | 
				
			||||||
				"data":    nil,
 | 
									"data":    nil,
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
@@ -314,7 +315,7 @@ func TestLogin(t *testing.T) {
 | 
				
			|||||||
			mockRepoSetup:         func(m *MockUserRepository) {},
 | 
								mockRepoSetup:         func(m *MockUserRepository) {},
 | 
				
			||||||
			mockTokenServiceSetup: func(m *MockTokenService) {},
 | 
								mockTokenServiceSetup: func(m *MockTokenService) {},
 | 
				
			||||||
			expectedResponse: map[string]interface{}{
 | 
								expectedResponse: map[string]interface{}{
 | 
				
			||||||
				"code":    float64(http.StatusBadRequest),
 | 
									"code":    float64(controller.CodeBadRequest),
 | 
				
			||||||
				"message": "Key: 'LoginRequest.Password' Error:Field validation for 'Password' failed on the 'required' tag",
 | 
									"message": "Key: 'LoginRequest.Password' Error:Field validation for 'Password' failed on the 'required' tag",
 | 
				
			||||||
				"data":    nil,
 | 
									"data":    nil,
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
@@ -330,7 +331,7 @@ func TestLogin(t *testing.T) {
 | 
				
			|||||||
			},
 | 
								},
 | 
				
			||||||
			mockTokenServiceSetup: func(m *MockTokenService) {},
 | 
								mockTokenServiceSetup: func(m *MockTokenService) {},
 | 
				
			||||||
			expectedResponse: map[string]interface{}{
 | 
								expectedResponse: map[string]interface{}{
 | 
				
			||||||
				"code":    float64(http.StatusUnauthorized),
 | 
									"code":    float64(controller.CodeUnauthorized),
 | 
				
			||||||
				"message": "用户名或密码不正确",
 | 
									"message": "用户名或密码不正确",
 | 
				
			||||||
				"data":    nil,
 | 
									"data":    nil,
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
@@ -345,7 +346,7 @@ func TestLogin(t *testing.T) {
 | 
				
			|||||||
				m.On("FindByUsername", "dberroruser").Return(nil, errors.New("database connection error")).Once()
 | 
									m.On("FindByUsername", "dberroruser").Return(nil, errors.New("database connection error")).Once()
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			mockTokenServiceSetup: func(m *MockTokenService) {}, expectedResponse: map[string]interface{}{
 | 
								mockTokenServiceSetup: func(m *MockTokenService) {}, expectedResponse: map[string]interface{}{
 | 
				
			||||||
				"code":    float64(http.StatusInternalServerError),
 | 
									"code":    float64(controller.CodeInternalError),
 | 
				
			||||||
				"message": "登录失败",
 | 
									"message": "登录失败",
 | 
				
			||||||
				"data":    nil,
 | 
									"data":    nil,
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
@@ -368,7 +369,7 @@ func TestLogin(t *testing.T) {
 | 
				
			|||||||
			},
 | 
								},
 | 
				
			||||||
			mockTokenServiceSetup: func(m *MockTokenService) {},
 | 
								mockTokenServiceSetup: func(m *MockTokenService) {},
 | 
				
			||||||
			expectedResponse: map[string]interface{}{
 | 
								expectedResponse: map[string]interface{}{
 | 
				
			||||||
				"code":    float64(http.StatusUnauthorized),
 | 
									"code":    float64(controller.CodeUnauthorized),
 | 
				
			||||||
				"message": "用户名或密码不正确",
 | 
									"message": "用户名或密码不正确",
 | 
				
			||||||
				"data":    nil,
 | 
									"data":    nil,
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
@@ -393,7 +394,7 @@ func TestLogin(t *testing.T) {
 | 
				
			|||||||
				m.On("GenerateToken", uint(1)).Return("", errors.New("jwt error")).Once()
 | 
									m.On("GenerateToken", uint(1)).Return("", errors.New("jwt error")).Once()
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			expectedResponse: map[string]interface{}{
 | 
								expectedResponse: map[string]interface{}{
 | 
				
			||||||
				"code":    float64(http.StatusInternalServerError),
 | 
									"code":    float64(controller.CodeInternalError),
 | 
				
			||||||
				"message": "登录失败,无法生成认证信息",
 | 
									"message": "登录失败,无法生成认证信息",
 | 
				
			||||||
				"data":    nil,
 | 
									"data":    nil,
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
@@ -421,10 +422,10 @@ func TestLogin(t *testing.T) {
 | 
				
			|||||||
			tt.mockTokenServiceSetup(mockTokenService)
 | 
								tt.mockTokenServiceSetup(mockTokenService)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// 创建控制器实例
 | 
								// 创建控制器实例
 | 
				
			||||||
			controller := user.NewController(mockRepo, silentLogger, mockTokenService)
 | 
								userController := user.NewController(mockRepo, silentLogger, mockTokenService)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// 调用被测试的方法
 | 
								// 调用被测试的方法
 | 
				
			||||||
			controller.Login(ctx)
 | 
								userController.Login(ctx)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// 解析响应体
 | 
								// 解析响应体
 | 
				
			||||||
			var responseBody map[string]interface{}
 | 
								var responseBody map[string]interface{}
 | 
				
			||||||
@@ -435,9 +436,15 @@ func TestLogin(t *testing.T) {
 | 
				
			|||||||
			assert.Equal(t, tt.expectedResponse["code"], responseBody["code"])
 | 
								assert.Equal(t, tt.expectedResponse["code"], responseBody["code"])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// 断言响应内容 (除了 code 字段)
 | 
								// 断言响应内容 (除了 code 字段)
 | 
				
			||||||
			if tt.expectedResponse["code"] == float64(http.StatusOK) {
 | 
								if tt.expectedResponse["code"] == float64(controller.CodeSuccess) {
 | 
				
			||||||
				assert.NotNil(t, responseBody["data"].(map[string]interface{})["id"])
 | 
									// 确保 data 字段存在且是 map[string]interface{} 类型
 | 
				
			||||||
				assert.NotNil(t, responseBody["data"].(map[string]interface{})["token"])
 | 
									data, ok := responseBody["data"].(map[string]interface{})
 | 
				
			||||||
 | 
									assert.True(t, ok, "响应体中的 data 字段应为 map[string]interface{}")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									// 验证 id 和 token 存在
 | 
				
			||||||
 | 
									assert.NotNil(t, data["id"])
 | 
				
			||||||
 | 
									assert.NotNil(t, data["token"])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				// 移除 ID 和 Token 字段以便进行通用断言
 | 
									// 移除 ID 和 Token 字段以便进行通用断言
 | 
				
			||||||
				delete(responseBody["data"].(map[string]interface{}), "id")
 | 
									delete(responseBody["data"].(map[string]interface{}), "id")
 | 
				
			||||||
				delete(tt.expectedResponse["data"].(map[string]interface{}), "id")
 | 
									delete(tt.expectedResponse["data"].(map[string]interface{}), "id")
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user