package controllers import ( "net/http" "strconv" "strings" "github.com/gin-gonic/gin" "git.beifan.cn/trace-system/backend-go/models" "git.beifan.cn/trace-system/backend-go/services" ) // SerialsController 序列号控制器 type SerialsController struct { serialsService services.SerialsService } // NewSerialsController 创建序列号控制器实例 func NewSerialsController() *SerialsController { return &SerialsController{ serialsService: services.SerialsService{}, } } // Generate 生成序列号 // @Summary 生成序列号 // @Description 生成指定数量的序列号 // @Tags 序列号管理 // @Accept json // @Produce json // @Security BearerAuth // @Param generateData body models.GenerateSerialDTO true "生成数据" // @Success 200 {object} models.DataResponse // @Failure 400 {object} models.ErrorResponse // @Failure 401 {object} models.ErrorResponse // @Failure 500 {object} models.ErrorResponse // @Router /serials/generate [post] func (c *SerialsController) Generate(ctx *gin.Context) { userModel, ok := GetCurrentUser(ctx) if !ok { return } var generateData models.GenerateSerialDTO if !BindJSON(ctx, &generateData) { return } serials, err := c.serialsService.Generate( generateData.CompanyName, generateData.Quantity, generateData.ValidDays, userModel.ID, ) if err != nil { ErrorResponse(ctx, http.StatusInternalServerError, err.Error()) return } items := make([]gin.H, 0, len(serials)) for _, serial := range serials { items = append(items, gin.H{ "serialNumber": serial.SerialNumber, "companyName": serial.CompanyName, "validUntil": serial.ValidUntil, "isActive": serial.IsActive, "createdAt": serial.CreatedAt, "createdBy": userModel.Name, }) } SuccessResponse(ctx, "成功生成"+strconv.Itoa(len(serials))+"个序列号", gin.H{ "serials": items, }) } // GenerateWithPrefix 带前缀生成序列号 // @Summary 带前缀生成序列号 // @Description 生成带有指定前缀的序列号 // @Tags 序列号管理 // @Accept json // @Produce json // @Security BearerAuth // @Param generateData body models.GenerateWithPrefixDTO true "生成数据" // @Success 200 {object} models.DataResponse // @Failure 400 {object} models.ErrorResponse // @Failure 401 {object} models.ErrorResponse // @Failure 500 {object} models.ErrorResponse // @Router /serials/generate-with-prefix [post] func (c *SerialsController) GenerateWithPrefix(ctx *gin.Context) { userModel, ok := GetCurrentUser(ctx) if !ok { return } var generateData models.GenerateWithPrefixDTO if !BindJSON(ctx, &generateData) { return } serials, err := c.serialsService.Generate( generateData.CompanyName, generateData.Quantity, generateData.ValidDays, userModel.ID, generateData.SerialPrefix, ) if err != nil { ErrorResponse(ctx, http.StatusInternalServerError, err.Error()) return } items := make([]gin.H, 0, len(serials)) for _, serial := range serials { items = append(items, gin.H{ "serialNumber": serial.SerialNumber, "companyName": serial.CompanyName, "validUntil": serial.ValidUntil, "isActive": serial.IsActive, "createdAt": serial.CreatedAt, "createdBy": userModel.Name, }) } SuccessResponse(ctx, "成功生成"+strconv.Itoa(len(serials))+"个序列号", gin.H{ "serials": items, }) } // GenerateQRCode 生成二维码 // @Summary 生成二维码 // @Description 为指定序列号生成查询二维码 // @Tags 序列号管理 // @Accept json // @Produce json // @Security BearerAuth // @Param serialNumber path string true "序列号" // @Param qrCodeData body models.QRCodeDTO false "二维码数据" // @Success 200 {object} models.QRCodeResponse // @Failure 400 {object} models.ErrorResponse // @Failure 401 {object} models.ErrorResponse // @Failure 404 {object} models.ErrorResponse // @Failure 500 {object} models.ErrorResponse // @Router /serials/{serialNumber}/qrcode [post] func (c *SerialsController) GenerateQRCode(ctx *gin.Context) { serialNumber := ctx.Param("serialNumber") var qrCodeData models.QRCodeDTO if !BindJSON(ctx, &qrCodeData) { return } protocol := "http" if ctx.Request.TLS != nil { protocol = "https" } qrCodeBase64, queryUrl, err := c.serialsService.GenerateQRCode( serialNumber, qrCodeData.BaseUrl, ctx.Request.Host, protocol, ) if err != nil { ErrorResponse(ctx, http.StatusBadRequest, err.Error()) return } SuccessResponse(ctx, "二维码生成成功", gin.H{ "qrCodeData": qrCodeBase64, "queryUrl": queryUrl, }) } // Query 查询序列号信息 // @Summary 查询序列号信息 // @Description 查询指定序列号的详细信息 // @Tags 序列号查询 // @Produce json // @Param serialNumber path string true "序列号" // @Success 200 {object} models.DataResponse // @Failure 400 {object} models.ErrorResponse // @Failure 404 {object} models.ErrorResponse // @Failure 500 {object} models.ErrorResponse // @Router /serials/{serialNumber}/query [get] func (c *SerialsController) Query(ctx *gin.Context) { serialNumber := ctx.Param("serialNumber") serial, err := c.serialsService.Query(serialNumber) if err != nil { ErrorResponse(ctx, http.StatusBadRequest, err.Error()) return } createdBy := "" if serial.User != nil { createdBy = serial.User.Name } status := "active" if !serial.IsActive { status = "disabled" } SuccessResponse(ctx, "查询成功", gin.H{ "serial": gin.H{ "serialNumber": serial.SerialNumber, "companyName": serial.CompanyName, "validUntil": serial.ValidUntil, "status": status, "isActive": serial.IsActive, "createdAt": serial.CreatedAt, "createdBy": createdBy, }, }) } // FindAll 获取序列号列表 // @Summary 获取序列号列表 // @Description 获取序列号列表,支持分页和搜索 // @Tags 序列号管理 // @Produce json // @Security BearerAuth // @Param page query int false "页码" // @Param limit query int false " "每页数量" // @Param search query string false "搜索关键词" // @Success 200 {object} models.PaginationResponse // @Failure 401 {object} models.ErrorResponse // @Failure 500 {object} models.ErrorResponse // @Router /serials [get] func (c *SerialsController) FindAll(ctx *gin.Context) { page, _ := strconv.Atoi(ctx.DefaultQuery("page", "1")) limit, _ := strconv.Atoi(ctx.DefaultQuery("limit", "20")) search := ctx.DefaultQuery("search", "") serials, total, totalPages, err := c.serialsService.FindAll(page, limit, search) if err != nil { ErrorResponse(ctx, http.StatusInternalServerError, err.Error()) return } items := make([]gin.H, 0, len(serials)) for _, serial := range serials { createdBy := "" if serial.User != nil { createdBy = serial.User.Name } items = append(items, gin.H{ "serialNumber": serial.SerialNumber, "companyName": serial.CompanyName, "validUntil": serial.ValidUntil, "isActive": serial.IsActive, "createdAt": serial.CreatedAt, "createdBy": createdBy, }) } SuccessResponse(ctx, "获取序列号列表成功", gin.H{ "data": items, "pagination": gin.H{ "page": page, "limit": limit, "total": total, "totalPages": totalPages, }, }) } // Update 更新序列号信息 // @Summary 更新序列号信息 // @Description 更新指定序列号的信息 // @Tags 序列号管理 // @Accept json // @Produce json // @Security BearerAuth // @Param serialNumber path string true "序列号" // @Param updateData body models.UpdateSerialDTO true "更新数据" // @Success 200 {object} models.DataResponse // @Failure 400 {object} models.ErrorResponse // @Failure 401 {object} models.ErrorResponse // @Failure 404 {object} models.ErrorResponse // @Failure 500 {object} models.ErrorResponse // @Router /serials/{serialNumber} [put] func (c *SerialsController) Update(ctx *gin.Context) { serialNumber := ctx.Param("serialNumber") var updateData models.UpdateSerialDTO if !BindJSON(ctx, &updateData) { return } serial, err := c.serialsService.Update(serialNumber, updateData) if err != nil { ErrorResponse(ctx, http.StatusInternalServerError, err.Error()) return } createdBy := "" if serial.User != nil { createdBy = serial.User.Name } SuccessResponse(ctx, "序列号更新成功", gin.H{ "serial": gin.H{ "serialNumber": serial.SerialNumber, "companyName": serial.CompanyName, "validUntil": serial.ValidUntil, "isActive": serial.IsActive, "createdAt": serial.CreatedAt, "updatedAt": serial.UpdatedAt, "createdBy": createdBy, }, }) } // Revoke 吊销序列号 // @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 /serials/{serialNumber}/revoke [post] func (c *SerialsController) Revoke(ctx *gin.Context) { serialNumber := ctx.Param("serialNumber") err := c.serialsService.Revoke(serialNumber) if err != nil { ErrorResponse(ctx, http.StatusBadRequest, err.Error()) return } SuccessResponse(ctx, "序列号已吊销", gin.H{ "data": gin.H{ "serialNumber": strings.ToUpper(serialNumber), }, }) }