add f
This commit is contained in:
@@ -116,7 +116,7 @@ func (r *GormComponentReportRepository) GetUserDownloadedProductCodes(ctx contex
|
||||
|
||||
func (r *GormComponentReportRepository) GetDownloadByPaymentOrderID(ctx context.Context, orderID string) (*entities.ComponentReportDownload, error) {
|
||||
var download entities.ComponentReportDownload
|
||||
err := r.GetDB(ctx).Where("order_number = ?", orderID).First(&download).Error
|
||||
err := r.GetDB(ctx).Where("order_id = ?", orderID).First(&download).Error
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, gorm.ErrRecordNotFound
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
package repositories
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"tyapi-server/internal/domains/product/entities"
|
||||
"tyapi-server/internal/domains/product/repositories"
|
||||
"tyapi-server/internal/shared/database"
|
||||
|
||||
"go.uber.org/zap"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
const (
|
||||
ProductSubCategoriesTable = "product_sub_categories"
|
||||
)
|
||||
|
||||
type GormProductSubCategoryRepository struct {
|
||||
*database.CachedBaseRepositoryImpl
|
||||
}
|
||||
|
||||
var _ repositories.ProductSubCategoryRepository = (*GormProductSubCategoryRepository)(nil)
|
||||
|
||||
func NewGormProductSubCategoryRepository(db *gorm.DB, logger *zap.Logger) repositories.ProductSubCategoryRepository {
|
||||
return &GormProductSubCategoryRepository{
|
||||
CachedBaseRepositoryImpl: database.NewCachedBaseRepositoryImpl(db, logger, ProductSubCategoriesTable),
|
||||
}
|
||||
}
|
||||
|
||||
// Create 创建二级分类
|
||||
func (r *GormProductSubCategoryRepository) Create(ctx context.Context, category entities.ProductSubCategory) (*entities.ProductSubCategory, error) {
|
||||
err := r.CreateEntity(ctx, &category)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &category, nil
|
||||
}
|
||||
|
||||
// GetByID 根据ID获取二级分类
|
||||
func (r *GormProductSubCategoryRepository) GetByID(ctx context.Context, id string) (*entities.ProductSubCategory, error) {
|
||||
var entity entities.ProductSubCategory
|
||||
err := r.SmartGetByID(ctx, id, &entity)
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, gorm.ErrRecordNotFound
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return &entity, nil
|
||||
}
|
||||
|
||||
// Update 更新二级分类
|
||||
func (r *GormProductSubCategoryRepository) Update(ctx context.Context, category entities.ProductSubCategory) error {
|
||||
return r.UpdateEntity(ctx, &category)
|
||||
}
|
||||
|
||||
// Delete 删除二级分类
|
||||
func (r *GormProductSubCategoryRepository) Delete(ctx context.Context, id string) error {
|
||||
return r.DeleteEntity(ctx, id, &entities.ProductSubCategory{})
|
||||
}
|
||||
|
||||
// List 获取所有二级分类
|
||||
func (r *GormProductSubCategoryRepository) List(ctx context.Context) ([]*entities.ProductSubCategory, error) {
|
||||
var categories []entities.ProductSubCategory
|
||||
err := r.GetDB(ctx).Order("sort ASC, created_at DESC").Find(&categories).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 转换为指针切片
|
||||
result := make([]*entities.ProductSubCategory, len(categories))
|
||||
for i := range categories {
|
||||
result[i] = &categories[i]
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// FindByCode 根据编号查找二级分类
|
||||
func (r *GormProductSubCategoryRepository) FindByCode(ctx context.Context, code string) (*entities.ProductSubCategory, error) {
|
||||
var entity entities.ProductSubCategory
|
||||
err := r.GetDB(ctx).Where("code = ?", code).First(&entity).Error
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, gorm.ErrRecordNotFound
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return &entity, nil
|
||||
}
|
||||
|
||||
// FindByCategoryID 根据一级分类ID查找二级分类
|
||||
func (r *GormProductSubCategoryRepository) FindByCategoryID(ctx context.Context, categoryID string) ([]*entities.ProductSubCategory, error) {
|
||||
var categories []entities.ProductSubCategory
|
||||
err := r.GetDB(ctx).Where("category_id = ?", categoryID).Order("sort ASC, created_at DESC").Find(&categories).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 转换为指针切片
|
||||
result := make([]*entities.ProductSubCategory, len(categories))
|
||||
for i := range categories {
|
||||
result[i] = &categories[i]
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// FindVisible 查找可见的二级分类
|
||||
func (r *GormProductSubCategoryRepository) FindVisible(ctx context.Context) ([]*entities.ProductSubCategory, error) {
|
||||
var categories []entities.ProductSubCategory
|
||||
err := r.GetDB(ctx).Where("is_visible = ? AND is_enabled = ?", true, true).Order("sort ASC, created_at DESC").Find(&categories).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 转换为指针切片
|
||||
result := make([]*entities.ProductSubCategory, len(categories))
|
||||
for i := range categories {
|
||||
result[i] = &categories[i]
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// FindEnabled 查找启用的二级分类
|
||||
func (r *GormProductSubCategoryRepository) FindEnabled(ctx context.Context) ([]*entities.ProductSubCategory, error) {
|
||||
var categories []entities.ProductSubCategory
|
||||
err := r.GetDB(ctx).Where("is_enabled = ?", true).Order("sort ASC, created_at DESC").Find(&categories).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 转换为指针切片
|
||||
result := make([]*entities.ProductSubCategory, len(categories))
|
||||
for i := range categories {
|
||||
result[i] = &categories[i]
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
229
internal/infrastructure/http/handlers/sub_category_handler.go
Normal file
229
internal/infrastructure/http/handlers/sub_category_handler.go
Normal file
@@ -0,0 +1,229 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"tyapi-server/internal/application/product"
|
||||
"tyapi-server/internal/application/product/dto/commands"
|
||||
"tyapi-server/internal/application/product/dto/queries"
|
||||
"tyapi-server/internal/shared/interfaces"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
// SubCategoryHandler 二级分类HTTP处理器
|
||||
type SubCategoryHandler struct {
|
||||
subCategoryAppService product.SubCategoryApplicationService
|
||||
responseBuilder interfaces.ResponseBuilder
|
||||
validator interfaces.RequestValidator
|
||||
logger *zap.Logger
|
||||
}
|
||||
|
||||
// NewSubCategoryHandler 创建二级分类HTTP处理器
|
||||
func NewSubCategoryHandler(
|
||||
subCategoryAppService product.SubCategoryApplicationService,
|
||||
responseBuilder interfaces.ResponseBuilder,
|
||||
validator interfaces.RequestValidator,
|
||||
logger *zap.Logger,
|
||||
) *SubCategoryHandler {
|
||||
return &SubCategoryHandler{
|
||||
subCategoryAppService: subCategoryAppService,
|
||||
responseBuilder: responseBuilder,
|
||||
validator: validator,
|
||||
logger: logger,
|
||||
}
|
||||
}
|
||||
|
||||
// CreateSubCategory 创建二级分类
|
||||
// @Summary 创建二级分类
|
||||
// @Description 管理员创建新二级分类
|
||||
// @Tags 二级分类管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security Bearer
|
||||
// @Param request body commands.CreateSubCategoryCommand true "创建二级分类请求"
|
||||
// @Success 201 {object} map[string]interface{} "二级分类创建成功"
|
||||
// @Failure 400 {object} map[string]interface{} "请求参数错误"
|
||||
// @Failure 401 {object} map[string]interface{} "未认证"
|
||||
// @Failure 500 {object} map[string]interface{} "服务器内部错误"
|
||||
// @Router /api/v1/admin/sub-categories [post]
|
||||
func (h *SubCategoryHandler) CreateSubCategory(c *gin.Context) {
|
||||
var cmd commands.CreateSubCategoryCommand
|
||||
if err := h.validator.BindAndValidate(c, &cmd); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.subCategoryAppService.CreateSubCategory(c.Request.Context(), &cmd); err != nil {
|
||||
h.logger.Error("创建二级分类失败", zap.Error(err))
|
||||
h.responseBuilder.BadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
h.responseBuilder.Created(c, nil, "二级分类创建成功")
|
||||
}
|
||||
|
||||
// UpdateSubCategory 更新二级分类
|
||||
// @Summary 更新二级分类
|
||||
// @Description 管理员更新二级分类信息
|
||||
// @Tags 二级分类管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security Bearer
|
||||
// @Param id path string true "二级分类ID"
|
||||
// @Param request body commands.UpdateSubCategoryCommand true "更新二级分类请求"
|
||||
// @Success 200 {object} map[string]interface{} "二级分类更新成功"
|
||||
// @Failure 400 {object} map[string]interface{} "请求参数错误"
|
||||
// @Failure 401 {object} map[string]interface{} "未认证"
|
||||
// @Failure 404 {object} map[string]interface{} "二级分类不存在"
|
||||
// @Failure 500 {object} map[string]interface{} "服务器内部错误"
|
||||
// @Router /api/v1/admin/sub-categories/{id} [put]
|
||||
func (h *SubCategoryHandler) UpdateSubCategory(c *gin.Context) {
|
||||
var cmd commands.UpdateSubCategoryCommand
|
||||
cmd.ID = c.Param("id")
|
||||
if cmd.ID == "" {
|
||||
h.responseBuilder.BadRequest(c, "二级分类ID不能为空")
|
||||
return
|
||||
}
|
||||
if err := h.validator.BindAndValidate(c, &cmd); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.subCategoryAppService.UpdateSubCategory(c.Request.Context(), &cmd); err != nil {
|
||||
h.logger.Error("更新二级分类失败", zap.Error(err))
|
||||
h.responseBuilder.BadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
h.responseBuilder.Success(c, nil, "二级分类更新成功")
|
||||
}
|
||||
|
||||
// DeleteSubCategory 删除二级分类
|
||||
// @Summary 删除二级分类
|
||||
// @Description 管理员删除二级分类
|
||||
// @Tags 二级分类管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security Bearer
|
||||
// @Param id path string true "二级分类ID"
|
||||
// @Success 200 {object} map[string]interface{} "二级分类删除成功"
|
||||
// @Failure 400 {object} map[string]interface{} "请求参数错误"
|
||||
// @Failure 401 {object} map[string]interface{} "未认证"
|
||||
// @Failure 404 {object} map[string]interface{} "二级分类不存在"
|
||||
// @Failure 500 {object} map[string]interface{} "服务器内部错误"
|
||||
// @Router /api/v1/admin/sub-categories/{id} [delete]
|
||||
func (h *SubCategoryHandler) DeleteSubCategory(c *gin.Context) {
|
||||
cmd := commands.DeleteSubCategoryCommand{ID: c.Param("id")}
|
||||
if err := h.validator.ValidateParam(c, &cmd); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.subCategoryAppService.DeleteSubCategory(c.Request.Context(), &cmd); err != nil {
|
||||
h.logger.Error("删除二级分类失败", zap.Error(err))
|
||||
h.responseBuilder.BadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
h.responseBuilder.Success(c, nil, "二级分类删除成功")
|
||||
}
|
||||
|
||||
// GetSubCategory 获取二级分类详情
|
||||
// @Summary 获取二级分类详情
|
||||
// @Description 获取指定二级分类的详细信息
|
||||
// @Tags 二级分类管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security Bearer
|
||||
// @Param id path string true "二级分类ID"
|
||||
// @Success 200 {object} responses.SubCategoryInfoResponse "二级分类信息"
|
||||
// @Failure 400 {object} map[string]interface{} "请求参数错误"
|
||||
// @Failure 401 {object} map[string]interface{} "未认证"
|
||||
// @Failure 404 {object} map[string]interface{} "二级分类不存在"
|
||||
// @Failure 500 {object} map[string]interface{} "服务器内部错误"
|
||||
// @Router /api/v1/admin/sub-categories/{id} [get]
|
||||
func (h *SubCategoryHandler) GetSubCategory(c *gin.Context) {
|
||||
query := &queries.GetSubCategoryQuery{ID: c.Param("id")}
|
||||
if err := h.validator.ValidateParam(c, query); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
result, err := h.subCategoryAppService.GetSubCategoryByID(c.Request.Context(), query)
|
||||
if err != nil {
|
||||
h.logger.Error("获取二级分类失败", zap.Error(err))
|
||||
h.responseBuilder.NotFound(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
h.responseBuilder.Success(c, result, "获取二级分类成功")
|
||||
}
|
||||
|
||||
// ListSubCategories 获取二级分类列表
|
||||
// @Summary 获取二级分类列表
|
||||
// @Description 获取二级分类列表,支持筛选和分页
|
||||
// @Tags 二级分类管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security Bearer
|
||||
// @Param category_id query string false "一级分类ID"
|
||||
// @Param page query int false "页码"
|
||||
// @Param page_size query int false "每页数量"
|
||||
// @Param is_enabled query bool false "是否启用"
|
||||
// @Param is_visible query bool false "是否展示"
|
||||
// @Param sort_by query string false "排序字段"
|
||||
// @Param sort_order query string false "排序方向"
|
||||
// @Success 200 {object} responses.SubCategoryListResponse "二级分类列表"
|
||||
// @Failure 400 {object} map[string]interface{} "请求参数错误"
|
||||
// @Failure 401 {object} map[string]interface{} "未认证"
|
||||
// @Failure 500 {object} map[string]interface{} "服务器内部错误"
|
||||
// @Router /api/v1/admin/sub-categories [get]
|
||||
func (h *SubCategoryHandler) ListSubCategories(c *gin.Context) {
|
||||
query := &queries.ListSubCategoriesQuery{}
|
||||
if err := h.validator.ValidateQuery(c, query); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// 设置默认分页参数
|
||||
if query.Page == 0 {
|
||||
query.Page = 1
|
||||
}
|
||||
if query.PageSize == 0 {
|
||||
query.PageSize = 20
|
||||
}
|
||||
|
||||
result, err := h.subCategoryAppService.ListSubCategories(c.Request.Context(), query)
|
||||
if err != nil {
|
||||
h.logger.Error("获取二级分类列表失败", zap.Error(err))
|
||||
h.responseBuilder.BadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
h.responseBuilder.Success(c, result, "获取二级分类列表成功")
|
||||
}
|
||||
|
||||
// ListSubCategoriesByCategory 根据一级分类ID获取二级分类列表(级联选择用)
|
||||
// @Summary 根据一级分类获取二级分类列表
|
||||
// @Description 根据一级分类ID获取二级分类简单列表,用于级联选择
|
||||
// @Tags 二级分类管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security Bearer
|
||||
// @Param id path string true "一级分类ID"
|
||||
// @Success 200 {object} []responses.SubCategorySimpleResponse "二级分类简单列表"
|
||||
// @Failure 400 {object} map[string]interface{} "请求参数错误"
|
||||
// @Failure 401 {object} map[string]interface{} "未认证"
|
||||
// @Failure 500 {object} map[string]interface{} "服务器内部错误"
|
||||
// @Router /api/v1/admin/categories/{id}/sub-categories [get]
|
||||
func (h *SubCategoryHandler) ListSubCategoriesByCategory(c *gin.Context) {
|
||||
categoryID := c.Param("id")
|
||||
if categoryID == "" {
|
||||
h.responseBuilder.BadRequest(c, "一级分类ID不能为空")
|
||||
return
|
||||
}
|
||||
|
||||
result, err := h.subCategoryAppService.ListSubCategoriesByCategoryID(c.Request.Context(), categoryID)
|
||||
if err != nil {
|
||||
h.logger.Error("获取二级分类列表失败", zap.Error(err))
|
||||
h.responseBuilder.BadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
h.responseBuilder.Success(c, result, "获取二级分类列表成功")
|
||||
}
|
||||
52
internal/infrastructure/http/routes/sub_category_routes.go
Normal file
52
internal/infrastructure/http/routes/sub_category_routes.go
Normal file
@@ -0,0 +1,52 @@
|
||||
package routes
|
||||
|
||||
import (
|
||||
"tyapi-server/internal/infrastructure/http/handlers"
|
||||
sharedhttp "tyapi-server/internal/shared/http"
|
||||
"tyapi-server/internal/shared/middleware"
|
||||
)
|
||||
|
||||
// SubCategoryRoutes 二级分类路由
|
||||
type SubCategoryRoutes struct {
|
||||
handler *handlers.SubCategoryHandler
|
||||
auth *middleware.JWTAuthMiddleware
|
||||
admin *middleware.AdminAuthMiddleware
|
||||
}
|
||||
|
||||
// NewSubCategoryRoutes 创建二级分类路由
|
||||
func NewSubCategoryRoutes(
|
||||
handler *handlers.SubCategoryHandler,
|
||||
auth *middleware.JWTAuthMiddleware,
|
||||
admin *middleware.AdminAuthMiddleware,
|
||||
) *SubCategoryRoutes {
|
||||
return &SubCategoryRoutes{
|
||||
handler: handler,
|
||||
auth: auth,
|
||||
admin: admin,
|
||||
}
|
||||
}
|
||||
|
||||
// Register 注册路由
|
||||
func (r *SubCategoryRoutes) Register(router *sharedhttp.GinRouter) {
|
||||
engine := router.GetEngine()
|
||||
adminGroup := engine.Group("/api/v1/admin")
|
||||
adminGroup.Use(r.auth.Handle())
|
||||
adminGroup.Use(r.admin.Handle())
|
||||
{
|
||||
// 二级分类管理
|
||||
subCategories := adminGroup.Group("/sub-categories")
|
||||
{
|
||||
subCategories.POST("", r.handler.CreateSubCategory) // 创建二级分类
|
||||
subCategories.PUT("/:id", r.handler.UpdateSubCategory) // 更新二级分类
|
||||
subCategories.DELETE("/:id", r.handler.DeleteSubCategory) // 删除二级分类
|
||||
subCategories.GET("/:id", r.handler.GetSubCategory) // 获取二级分类详情
|
||||
subCategories.GET("", r.handler.ListSubCategories) // 获取二级分类列表
|
||||
}
|
||||
|
||||
// 一级分类下的二级分类路由(级联选择)
|
||||
categoryAdmin := adminGroup.Group("/product-categories")
|
||||
{
|
||||
categoryAdmin.GET("/:id/sub-categories", r.handler.ListSubCategoriesByCategory) // 根据一级分类获取二级分类列表
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user