Re-migrate code
This commit is contained in:
@@ -125,7 +125,7 @@ func (s *AuthService) ValidateUser(username, password string) (models.User, erro
|
||||
var user models.User
|
||||
err := database.DB.Where("username = ?", username).First(&user).Error
|
||||
if err != nil {
|
||||
return models.User{}, errors.New("用户名或密码错误")
|
||||
return models.User{}, errors.New("用户名或密码不正确")
|
||||
}
|
||||
return user, nil
|
||||
}
|
||||
@@ -149,6 +149,9 @@ func (c *AuthController) Login(ctx *gin.Context) {
|
||||
}
|
||||
```
|
||||
|
||||
- Use `ErrorResponse` for API errors so messages are user-friendly and consistent.
|
||||
- Do not leak raw DB/stack errors to clients; log internal details and return safe messages.
|
||||
|
||||
### Response Format
|
||||
**Success response**:
|
||||
```json
|
||||
@@ -158,6 +161,8 @@ func (c *AuthController) Login(ctx *gin.Context) {
|
||||
}
|
||||
```
|
||||
|
||||
Some endpoints also return Node-compatible top-level keys (e.g. `serial`, `serials`, `pagination`) to preserve frontend compatibility.
|
||||
|
||||
**Error response**:
|
||||
```json
|
||||
{
|
||||
|
||||
@@ -240,6 +240,8 @@ swag init -g main.go
|
||||
| PUT | `/api/auth/profile` | 更新用户信息 | 是 |
|
||||
| POST | `/api/auth/change-password` | 修改密码 | 是 |
|
||||
|
||||
> 错误提示已做用户友好化,例如登录失败统一返回:`用户名或密码不正确`。
|
||||
|
||||
### 序列号管理
|
||||
|
||||
| 方法 | 路径 | 描述 | 需要认证 | 角色 |
|
||||
@@ -279,6 +281,12 @@ swag init -g main.go
|
||||
| PUT | `/api/employee-serials/:serialNumber` | 更新员工序列号信息 | 是 | 管理员 |
|
||||
| POST | `/api/employee-serials/:serialNumber/revoke` | 吊销员工序列号 | 是 | 管理员 |
|
||||
|
||||
### Node 对齐说明
|
||||
|
||||
- Go 版路由已与 `backend-node` 对齐(含 `PATCH` 更新接口、企业详情、企业吊销、删除企业下单个序列号)。
|
||||
- 企业统计与企业详情接口统一返回 `{ message, data }` 结构。
|
||||
- 序列号相关返回字段已对齐前端使用(如 `serialNumber`、`validUntil`、`createdBy`、`status`)。
|
||||
|
||||
**员工序列号特点**:
|
||||
- 无有效期限制(与企业赋码不同)
|
||||
- 包含部门(department)和员工姓名(employeeName)信息
|
||||
|
||||
@@ -52,6 +52,7 @@ func (c *EmployeeSerialsController) Generate(ctx *gin.Context) {
|
||||
generateData.EmployeeName,
|
||||
generateData.Quantity,
|
||||
userModel.ID,
|
||||
generateData.SerialPrefix,
|
||||
)
|
||||
if err != nil {
|
||||
ErrorResponse(ctx, http.StatusInternalServerError, err.Error())
|
||||
@@ -226,3 +227,28 @@ func (c *EmployeeSerialsController) Revoke(ctx *gin.Context) {
|
||||
|
||||
SuccessResponse(ctx, "员工序列号吊销成功")
|
||||
}
|
||||
|
||||
// Delete 删除员工序列号
|
||||
// @Summary 删除员工序列号
|
||||
// @Description 删除指定员工序列号(物理删除)
|
||||
// @Tags 员工赋码管理
|
||||
// @Produce json
|
||||
// @Security BearerAuth
|
||||
// @Param serialNumber path string true "序列号"
|
||||
// @Success 200 {object} models.BaseResponse
|
||||
// @Failure 400 {object} models.ErrorResponse
|
||||
// @Failure 401 {object} models.ErrorResponse
|
||||
// @Failure 404 {object} models.ErrorResponse
|
||||
// @Failure 500 {object} models.ErrorResponse
|
||||
// @Router /employee-serials/{serialNumber} [delete]
|
||||
func (c *EmployeeSerialsController) Delete(ctx *gin.Context) {
|
||||
serialNumber := ctx.Param("serialNumber")
|
||||
|
||||
err := c.employeeSerialsService.Delete(serialNumber)
|
||||
if err != nil {
|
||||
ErrorResponse(ctx, http.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
SuccessResponse(ctx, "员工序列号删除成功")
|
||||
}
|
||||
|
||||
@@ -199,6 +199,7 @@ type GenerateEmployeeSerialDTO struct {
|
||||
Department string `json:"department" validate:"required"`
|
||||
EmployeeName string `json:"employeeName" validate:"required"`
|
||||
Quantity int `json:"quantity" validate:"min=1,max=1000"`
|
||||
SerialPrefix string `json:"serialPrefix,omitempty"`
|
||||
}
|
||||
|
||||
// UpdateEmployeeSerialDTO 员工序列号更新请求数据
|
||||
|
||||
@@ -71,5 +71,6 @@ func SetupAPIRoutes(r *gin.RouterGroup) {
|
||||
employeeSerialsRoutes.GET("/", middleware.JWTAuthMiddleware(), employeeSerialsController.FindAll)
|
||||
employeeSerialsRoutes.PUT("/:serialNumber", middleware.JWTAuthMiddleware(), middleware.AdminMiddleware(), employeeSerialsController.Update)
|
||||
employeeSerialsRoutes.POST("/:serialNumber/revoke", middleware.JWTAuthMiddleware(), middleware.AdminMiddleware(), employeeSerialsController.Revoke)
|
||||
employeeSerialsRoutes.DELETE("/:serialNumber", middleware.JWTAuthMiddleware(), middleware.AdminMiddleware(), employeeSerialsController.Delete)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package services
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
"gorm.io/gorm"
|
||||
@@ -311,8 +312,14 @@ func (s *CompaniesService) GetStats() (map[string]any, error) {
|
||||
return nil, errors.New("查询序列号统计失败")
|
||||
}
|
||||
|
||||
var employeeSerials []models.EmployeeSerial
|
||||
if err := database.DB.Order("created_at DESC").Find(&employeeSerials).Error; err != nil {
|
||||
return nil, errors.New("查询员工序列号统计失败")
|
||||
}
|
||||
|
||||
companyCount := len(companies)
|
||||
serialCount := len(serials)
|
||||
employeeSerialCount := len(employeeSerials)
|
||||
activeCount := 0
|
||||
for _, serial := range serials {
|
||||
if serial.IsActive && (serial.ValidUntil == nil || serial.ValidUntil.After(now)) {
|
||||
@@ -355,22 +362,41 @@ func (s *CompaniesService) GetStats() (map[string]any, error) {
|
||||
}
|
||||
|
||||
recentSerials := make([]map[string]any, 0)
|
||||
for i, serial := range serials {
|
||||
if i >= 10 {
|
||||
break
|
||||
}
|
||||
// 添加企业序列号
|
||||
for _, serial := range serials {
|
||||
recentSerials = append(recentSerials, map[string]any{
|
||||
"serialNumber": serial.SerialNumber,
|
||||
"companyName": serial.CompanyName,
|
||||
"isActive": serial.IsActive,
|
||||
"createdAt": serial.CreatedAt,
|
||||
"type": "company",
|
||||
})
|
||||
}
|
||||
// 添加员工序列号
|
||||
for _, serial := range employeeSerials {
|
||||
recentSerials = append(recentSerials, map[string]any{
|
||||
"serialNumber": serial.SerialNumber,
|
||||
"companyName": serial.CompanyName,
|
||||
"isActive": serial.IsActive,
|
||||
"createdAt": serial.CreatedAt,
|
||||
"type": "employee",
|
||||
"department": serial.Department,
|
||||
"employeeName": serial.EmployeeName,
|
||||
})
|
||||
}
|
||||
// 按创建时间排序,保留最新的10条
|
||||
sort.Slice(recentSerials, func(i, j int) bool {
|
||||
return recentSerials[i]["createdAt"].(time.Time).After(recentSerials[j]["createdAt"].(time.Time))
|
||||
})
|
||||
if len(recentSerials) > 10 {
|
||||
recentSerials = recentSerials[:10]
|
||||
}
|
||||
|
||||
return map[string]any{
|
||||
"overview": map[string]any{
|
||||
"totalCompanies": companyCount,
|
||||
"totalSerials": serialCount,
|
||||
"totalEmployeeSerials": employeeSerialCount,
|
||||
"activeSerials": activeCount,
|
||||
"inactiveSerials": inactiveCount,
|
||||
},
|
||||
|
||||
@@ -28,6 +28,7 @@ func (s *EmployeeSerialsService) Generate(
|
||||
employeeName string,
|
||||
quantity int,
|
||||
userId uint,
|
||||
serialPrefix string,
|
||||
) ([]models.EmployeeSerial, error) {
|
||||
var serials []models.EmployeeSerial
|
||||
|
||||
@@ -45,8 +46,12 @@ func (s *EmployeeSerialsService) Generate(
|
||||
}
|
||||
}
|
||||
|
||||
// 生成序列号前缀 (EMP + 年份后两位)
|
||||
serialPrefix := fmt.Sprintf("EMP%d", time.Now().Year()%100)
|
||||
// 生成序列号前缀
|
||||
if serialPrefix == "" {
|
||||
serialPrefix = fmt.Sprintf("EMP%d", time.Now().Year()%100)
|
||||
}
|
||||
// 标准化前缀(转大写,去除空格)
|
||||
serialPrefix = strings.ToUpper(strings.TrimSpace(serialPrefix))
|
||||
|
||||
// 预生成所有序列号
|
||||
serialNumbers := make(map[string]bool)
|
||||
@@ -199,6 +204,22 @@ func (s *EmployeeSerialsService) Revoke(serialNumber string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Delete 删除员工序列号(物理删除)
|
||||
func (s *EmployeeSerialsService) Delete(serialNumber string) error {
|
||||
var serial models.EmployeeSerial
|
||||
result := database.DB.Where("serial_number = ?", strings.ToUpper(serialNumber)).First(&serial)
|
||||
if result.Error != nil {
|
||||
return fmt.Errorf("查询员工序列号失败: %w", errors.New("序列号不存在"))
|
||||
}
|
||||
|
||||
result = database.DB.Delete(&serial)
|
||||
if result.Error != nil {
|
||||
return fmt.Errorf("删除员工序列号失败: %w", result.Error)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GenerateQRCode 生成员工二维码
|
||||
func (s *EmployeeSerialsService) GenerateQRCode(
|
||||
serialNumber string,
|
||||
|
||||
Reference in New Issue
Block a user