add article
This commit is contained in:
		| @@ -145,6 +145,18 @@ func (h *ApiHandler) AddWhiteListIP(c *gin.Context) { | ||||
| } | ||||
|  | ||||
| // DeleteWhiteListIP 删除白名单IP | ||||
| // @Summary 删除白名单IP | ||||
| // @Description 从当前用户的白名单中删除指定IP地址 | ||||
| // @Tags API管理 | ||||
| // @Accept json | ||||
| // @Produce json | ||||
| // @Security Bearer | ||||
| // @Param ip path string true "IP地址" | ||||
| // @Success 200 {object} map[string]interface{} "删除白名单IP成功" | ||||
| // @Failure 400 {object} map[string]interface{} "请求参数错误" | ||||
| // @Failure 401 {object} map[string]interface{} "未认证" | ||||
| // @Failure 500 {object} map[string]interface{} "服务器内部错误" | ||||
| // @Router /api/v1/my/whitelist/{ip} [delete] | ||||
| func (h *ApiHandler) DeleteWhiteListIP(c *gin.Context) { | ||||
| 	userID := h.getCurrentUserID(c) | ||||
| 	if userID == "" { | ||||
|   | ||||
							
								
								
									
										650
									
								
								internal/infrastructure/http/handlers/article_handler.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										650
									
								
								internal/infrastructure/http/handlers/article_handler.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,650 @@ | ||||
| //nolint:unused | ||||
| package handlers | ||||
|  | ||||
| import ( | ||||
| 	"tyapi-server/internal/application/article" | ||||
| 	"tyapi-server/internal/application/article/dto/commands" | ||||
| 	appQueries "tyapi-server/internal/application/article/dto/queries" | ||||
| 	_ "tyapi-server/internal/application/article/dto/responses" | ||||
| 	"tyapi-server/internal/shared/interfaces" | ||||
|  | ||||
| 	"github.com/gin-gonic/gin" | ||||
| 	"go.uber.org/zap" | ||||
| ) | ||||
|  | ||||
| // ArticleHandler 文章HTTP处理器 | ||||
| type ArticleHandler struct { | ||||
| 	appService      article.ArticleApplicationService | ||||
| 	responseBuilder interfaces.ResponseBuilder | ||||
| 	validator       interfaces.RequestValidator | ||||
| 	logger          *zap.Logger | ||||
| } | ||||
|  | ||||
| // NewArticleHandler 创建文章HTTP处理器 | ||||
| func NewArticleHandler( | ||||
| 	appService article.ArticleApplicationService, | ||||
| 	responseBuilder interfaces.ResponseBuilder, | ||||
| 	validator interfaces.RequestValidator, | ||||
| 	logger *zap.Logger, | ||||
| ) *ArticleHandler { | ||||
| 	return &ArticleHandler{ | ||||
| 		appService:      appService, | ||||
| 		responseBuilder: responseBuilder, | ||||
| 		validator:       validator, | ||||
| 		logger:          logger, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // CreateArticle 创建文章 | ||||
| // @Summary 创建文章 | ||||
| // @Description 创建新的文章 | ||||
| // @Tags 文章管理 | ||||
| // @Accept json | ||||
| // @Produce json | ||||
| // @Security Bearer | ||||
| // @Param request body commands.CreateArticleCommand 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/articles [post] | ||||
| func (h *ArticleHandler) CreateArticle(c *gin.Context) { | ||||
| 	var cmd commands.CreateArticleCommand | ||||
| 	if err := h.validator.BindAndValidate(c, &cmd); err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	 | ||||
| 	// 验证用户是否已登录 | ||||
| 	if _, exists := c.Get("user_id"); !exists { | ||||
| 		h.responseBuilder.Unauthorized(c, "用户未登录") | ||||
| 		return | ||||
| 	} | ||||
| 	 | ||||
| 	if err := h.appService.CreateArticle(c.Request.Context(), &cmd); err != nil { | ||||
| 		h.logger.Error("创建文章失败", zap.Error(err)) | ||||
| 		h.responseBuilder.BadRequest(c, err.Error()) | ||||
| 		return | ||||
| 	} | ||||
| 	 | ||||
| 	h.responseBuilder.Created(c, nil, "文章创建成功") | ||||
| } | ||||
|  | ||||
| // GetArticleByID 获取文章详情 | ||||
| // @Summary 获取文章详情 | ||||
| // @Description 根据ID获取文章详情 | ||||
| // @Tags 文章管理 | ||||
| // @Accept json | ||||
| // @Produce json | ||||
| // @Security Bearer | ||||
| // @Param id path string true "文章ID" | ||||
| // @Success 200 {object} responses.ArticleInfoResponse "获取文章详情成功" | ||||
| // @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/articles/{id} [get] | ||||
| func (h *ArticleHandler) GetArticleByID(c *gin.Context) { | ||||
| 	var query appQueries.GetArticleQuery | ||||
| 	query.ID = c.Param("id") | ||||
| 	if query.ID == "" { | ||||
| 		h.responseBuilder.BadRequest(c, "文章ID不能为空") | ||||
| 		return | ||||
| 	} | ||||
| 	 | ||||
| 	response, err := h.appService.GetArticleByID(c.Request.Context(), &query) | ||||
| 	if err != nil { | ||||
| 		h.logger.Error("获取文章详情失败", zap.Error(err)) | ||||
| 		h.responseBuilder.NotFound(c, "文章不存在") | ||||
| 		return | ||||
| 	} | ||||
| 	 | ||||
| 	h.responseBuilder.Success(c, response, "获取文章详情成功") | ||||
| } | ||||
|  | ||||
| // ListArticles 获取文章列表 | ||||
| // @Summary 获取文章列表 | ||||
| // @Description 分页获取文章列表,支持多种筛选条件 | ||||
| // @Tags 文章管理 | ||||
| // @Accept json | ||||
| // @Produce json | ||||
| // @Param page query int false "页码" default(1) | ||||
| // @Param page_size query int false "每页数量" default(10) | ||||
| // @Param status query string false "文章状态" | ||||
| // @Param category_id query string false "分类ID" | ||||
| // @Param tag_id query string false "标签ID" | ||||
| // @Param title query string false "标题关键词" | ||||
| // @Param summary query string false "摘要关键词" | ||||
| // @Param is_featured query bool false "是否推荐" | ||||
| // @Param order_by query string false "排序字段" | ||||
| // @Param order_dir query string false "排序方向" | ||||
| // @Success 200 {object} responses.ArticleListResponse "获取文章列表成功" | ||||
| // @Failure 400 {object} map[string]interface{} "请求参数错误" | ||||
| // @Failure 500 {object} map[string]interface{} "服务器内部错误" | ||||
| // @Router /api/v1/articles [get] | ||||
| func (h *ArticleHandler) ListArticles(c *gin.Context) { | ||||
| 	var query appQueries.ListArticleQuery | ||||
| 	if err := h.validator.ValidateQuery(c, &query); err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	 | ||||
| 	// 设置默认值 | ||||
| 	if query.Page <= 0 { | ||||
| 		query.Page = 1 | ||||
| 	} | ||||
| 	if query.PageSize <= 0 { | ||||
| 		query.PageSize = 10 | ||||
| 	} | ||||
| 	if query.PageSize > 100 { | ||||
| 		query.PageSize = 100 | ||||
| 	} | ||||
| 	 | ||||
| 	response, err := h.appService.ListArticles(c.Request.Context(), &query) | ||||
| 	if err != nil { | ||||
| 		h.logger.Error("获取文章列表失败", zap.Error(err)) | ||||
| 		h.responseBuilder.InternalError(c, "获取文章列表失败") | ||||
| 		return | ||||
| 	} | ||||
| 	 | ||||
| 	h.responseBuilder.Success(c, response, "获取文章列表成功") | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| // UpdateArticle 更新文章 | ||||
| // @Summary 更新文章 | ||||
| // @Description 更新文章信息 | ||||
| // @Tags 文章管理 | ||||
| // @Accept json | ||||
| // @Produce json | ||||
| // @Security Bearer | ||||
| // @Param id path string true "文章ID" | ||||
| // @Param request body commands.UpdateArticleCommand 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/articles/{id} [put] | ||||
| func (h *ArticleHandler) UpdateArticle(c *gin.Context) { | ||||
| 	var cmd commands.UpdateArticleCommand | ||||
| 	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.appService.UpdateArticle(c.Request.Context(), &cmd); err != nil { | ||||
| 		h.logger.Error("更新文章失败", zap.Error(err)) | ||||
| 		h.responseBuilder.BadRequest(c, err.Error()) | ||||
| 		return | ||||
| 	} | ||||
| 	 | ||||
| 	h.responseBuilder.Success(c, nil, "文章更新成功") | ||||
| } | ||||
|  | ||||
| // DeleteArticle 删除文章 | ||||
| // @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/articles/{id} [delete] | ||||
| func (h *ArticleHandler) DeleteArticle(c *gin.Context) { | ||||
| 	var cmd commands.DeleteArticleCommand | ||||
| 	if err := h.validator.ValidateParam(c, &cmd); err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	 | ||||
| 	if err := h.appService.DeleteArticle(c.Request.Context(), &cmd); err != nil { | ||||
| 		h.logger.Error("删除文章失败", zap.Error(err)) | ||||
| 		h.responseBuilder.BadRequest(c, err.Error()) | ||||
| 		return | ||||
| 	} | ||||
| 	 | ||||
| 	h.responseBuilder.Success(c, nil, "文章删除成功") | ||||
| } | ||||
|  | ||||
| // PublishArticle 发布文章 | ||||
| // @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/articles/{id}/publish [post] | ||||
| func (h *ArticleHandler) PublishArticle(c *gin.Context) { | ||||
| 	var cmd commands.PublishArticleCommand | ||||
| 	if err := h.validator.ValidateParam(c, &cmd); err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	 | ||||
| 	if err := h.appService.PublishArticle(c.Request.Context(), &cmd); err != nil { | ||||
| 		h.logger.Error("发布文章失败", zap.Error(err)) | ||||
| 		h.responseBuilder.BadRequest(c, err.Error()) | ||||
| 		return | ||||
| 	} | ||||
| 	 | ||||
| 	h.responseBuilder.Success(c, nil, "文章发布成功") | ||||
| } | ||||
|  | ||||
| // SchedulePublishArticle 定时发布文章 | ||||
| // @Summary 定时发布文章 | ||||
| // @Description 设置文章的定时发布时间 | ||||
| // @Tags 文章管理 | ||||
| // @Accept json | ||||
| // @Produce json | ||||
| // @Security Bearer | ||||
| // @Param id path string true "文章ID" | ||||
| // @Param request body commands.SchedulePublishCommand 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/articles/{id}/schedule-publish [post] | ||||
| func (h *ArticleHandler) SchedulePublishArticle(c *gin.Context) { | ||||
| 	var cmd commands.SchedulePublishCommand | ||||
| 	if err := h.validator.ValidateParam(c, &cmd); err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	if err := h.validator.BindAndValidate(c, &cmd); err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	 | ||||
| 	if err := h.appService.SchedulePublishArticle(c.Request.Context(), &cmd); err != nil { | ||||
| 		h.logger.Error("设置定时发布失败", zap.Error(err)) | ||||
| 		h.responseBuilder.BadRequest(c, err.Error()) | ||||
| 		return | ||||
| 	} | ||||
| 	 | ||||
| 	h.responseBuilder.Success(c, nil, "定时发布设置成功") | ||||
| } | ||||
|  | ||||
| // ArchiveArticle 归档文章 | ||||
| // @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/articles/{id}/archive [post] | ||||
| func (h *ArticleHandler) ArchiveArticle(c *gin.Context) { | ||||
| 	var cmd commands.ArchiveArticleCommand | ||||
| 	if err := h.validator.ValidateParam(c, &cmd); err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	 | ||||
| 	if err := h.appService.ArchiveArticle(c.Request.Context(), &cmd); err != nil { | ||||
| 		h.logger.Error("归档文章失败", zap.Error(err)) | ||||
| 		h.responseBuilder.BadRequest(c, err.Error()) | ||||
| 		return | ||||
| 	} | ||||
| 	 | ||||
| 	h.responseBuilder.Success(c, nil, "文章归档成功") | ||||
| } | ||||
|  | ||||
| // SetFeatured 设置推荐状态 | ||||
| // @Summary 设置推荐状态 | ||||
| // @Description 设置文章的推荐状态 | ||||
| // @Tags 文章管理 | ||||
| // @Accept json | ||||
| // @Produce json | ||||
| // @Security Bearer | ||||
| // @Param id path string true "文章ID" | ||||
| // @Param request body commands.SetFeaturedCommand 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/articles/{id}/featured [put] | ||||
| func (h *ArticleHandler) SetFeatured(c *gin.Context) { | ||||
| 	var cmd commands.SetFeaturedCommand | ||||
| 	if err := h.validator.ValidateParam(c, &cmd); err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	if err := h.validator.BindAndValidate(c, &cmd); err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	 | ||||
| 	if err := h.appService.SetFeatured(c.Request.Context(), &cmd); err != nil { | ||||
| 		h.logger.Error("设置推荐状态失败", zap.Error(err)) | ||||
| 		h.responseBuilder.BadRequest(c, err.Error()) | ||||
| 		return | ||||
| 	} | ||||
| 	 | ||||
| 	h.responseBuilder.Success(c, nil, "设置推荐状态成功") | ||||
| } | ||||
|  | ||||
| // GetArticleStats 获取文章统计 | ||||
| // @Summary 获取文章统计 | ||||
| // @Description 获取文章相关统计数据 | ||||
| // @Tags 文章管理 | ||||
| // @Accept json | ||||
| // @Produce json | ||||
| // @Security Bearer | ||||
| // @Success 200 {object} responses.ArticleStatsResponse "获取统计成功" | ||||
| // @Failure 401 {object} map[string]interface{} "未认证" | ||||
| // @Failure 500 {object} map[string]interface{} "服务器内部错误" | ||||
| // @Router /api/v1/admin/articles/stats [get] | ||||
| func (h *ArticleHandler) GetArticleStats(c *gin.Context) { | ||||
| 	response, err := h.appService.GetArticleStats(c.Request.Context()) | ||||
| 	if err != nil { | ||||
| 		h.logger.Error("获取文章统计失败", zap.Error(err)) | ||||
| 		h.responseBuilder.InternalError(c, "获取文章统计失败") | ||||
| 		return | ||||
| 	} | ||||
| 	 | ||||
| 	h.responseBuilder.Success(c, response, "获取统计成功") | ||||
| } | ||||
|  | ||||
|  | ||||
| // ==================== 分类相关方法 ==================== | ||||
|  | ||||
| // ListCategories 获取分类列表 | ||||
| // @Summary 获取分类列表 | ||||
| // @Description 获取所有文章分类 | ||||
| // @Tags 文章分类 | ||||
| // @Accept json | ||||
| // @Produce json | ||||
| // @Success 200 {object} responses.CategoryListResponse "获取分类列表成功" | ||||
| // @Failure 500 {object} map[string]interface{} "服务器内部错误" | ||||
| // @Router /api/v1/article-categories [get] | ||||
| func (h *ArticleHandler) ListCategories(c *gin.Context) { | ||||
| 	response, err := h.appService.ListCategories(c.Request.Context()) | ||||
| 	if err != nil { | ||||
| 		h.logger.Error("获取分类列表失败", zap.Error(err)) | ||||
| 		h.responseBuilder.InternalError(c, "获取分类列表失败") | ||||
| 		return | ||||
| 	} | ||||
| 	 | ||||
| 	h.responseBuilder.Success(c, response, "获取分类列表成功") | ||||
| } | ||||
|  | ||||
| // GetCategoryByID 获取分类详情 | ||||
| // @Summary 获取分类详情 | ||||
| // @Description 根据ID获取分类详情 | ||||
| // @Tags 文章分类 | ||||
| // @Accept json | ||||
| // @Produce json | ||||
| // @Param id path string true "分类ID" | ||||
| // @Success 200 {object} responses.CategoryInfoResponse "获取分类详情成功" | ||||
| // @Failure 400 {object} map[string]interface{} "请求参数错误" | ||||
| // @Failure 404 {object} map[string]interface{} "分类不存在" | ||||
| // @Failure 500 {object} map[string]interface{} "服务器内部错误" | ||||
| // @Router /api/v1/article-categories/{id} [get] | ||||
| func (h *ArticleHandler) GetCategoryByID(c *gin.Context) { | ||||
| 	var query appQueries.GetCategoryQuery | ||||
| 	query.ID = c.Param("id") | ||||
| 	if query.ID == "" { | ||||
| 		h.responseBuilder.BadRequest(c, "分类ID不能为空") | ||||
| 		return | ||||
| 	} | ||||
| 	 | ||||
| 	response, err := h.appService.GetCategoryByID(c.Request.Context(), &query) | ||||
| 	if err != nil { | ||||
| 		h.logger.Error("获取分类详情失败", zap.Error(err)) | ||||
| 		h.responseBuilder.NotFound(c, "分类不存在") | ||||
| 		return | ||||
| 	} | ||||
| 	 | ||||
| 	h.responseBuilder.Success(c, response, "获取分类详情成功") | ||||
| } | ||||
|  | ||||
| // CreateCategory 创建分类 | ||||
| // @Summary 创建分类 | ||||
| // @Description 创建新的文章分类 | ||||
| // @Tags 文章分类管理 | ||||
| // @Accept json | ||||
| // @Produce json | ||||
| // @Security Bearer | ||||
| // @Param request body commands.CreateCategoryCommand 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/article-categories [post] | ||||
| func (h *ArticleHandler) CreateCategory(c *gin.Context) { | ||||
| 	var cmd commands.CreateCategoryCommand | ||||
| 	if err := h.validator.BindAndValidate(c, &cmd); err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	 | ||||
| 	if err := h.appService.CreateCategory(c.Request.Context(), &cmd); err != nil { | ||||
| 		h.logger.Error("创建分类失败", zap.Error(err)) | ||||
| 		h.responseBuilder.BadRequest(c, err.Error()) | ||||
| 		return | ||||
| 	} | ||||
| 	 | ||||
| 	h.responseBuilder.Created(c, nil, "分类创建成功") | ||||
| } | ||||
|  | ||||
| // UpdateCategory 更新分类 | ||||
| // @Summary 更新分类 | ||||
| // @Description 更新分类信息 | ||||
| // @Tags 文章分类管理 | ||||
| // @Accept json | ||||
| // @Produce json | ||||
| // @Security Bearer | ||||
| // @Param id path string true "分类ID" | ||||
| // @Param request body commands.UpdateCategoryCommand 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/article-categories/{id} [put] | ||||
| func (h *ArticleHandler) UpdateCategory(c *gin.Context) { | ||||
| 	var cmd commands.UpdateCategoryCommand | ||||
| 	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.appService.UpdateCategory(c.Request.Context(), &cmd); err != nil { | ||||
| 		h.logger.Error("更新分类失败", zap.Error(err)) | ||||
| 		h.responseBuilder.BadRequest(c, err.Error()) | ||||
| 		return | ||||
| 	} | ||||
| 	 | ||||
| 	h.responseBuilder.Success(c, nil, "分类更新成功") | ||||
| } | ||||
|  | ||||
| // DeleteCategory 删除分类 | ||||
| // @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/article-categories/{id} [delete] | ||||
| func (h *ArticleHandler) DeleteCategory(c *gin.Context) { | ||||
| 	var cmd commands.DeleteCategoryCommand | ||||
| 	if err := h.validator.ValidateParam(c, &cmd); err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	 | ||||
| 	if err := h.appService.DeleteCategory(c.Request.Context(), &cmd); err != nil { | ||||
| 		h.logger.Error("删除分类失败", zap.Error(err)) | ||||
| 		h.responseBuilder.BadRequest(c, err.Error()) | ||||
| 		return | ||||
| 	} | ||||
| 	 | ||||
| 	h.responseBuilder.Success(c, nil, "分类删除成功") | ||||
| } | ||||
|  | ||||
| // ==================== 标签相关方法 ==================== | ||||
|  | ||||
| // ListTags 获取标签列表 | ||||
| // @Summary 获取标签列表 | ||||
| // @Description 获取所有文章标签 | ||||
| // @Tags 文章标签 | ||||
| // @Accept json | ||||
| // @Produce json | ||||
| // @Success 200 {object} responses.TagListResponse "获取标签列表成功" | ||||
| // @Failure 500 {object} map[string]interface{} "服务器内部错误" | ||||
| // @Router /api/v1/article-tags [get] | ||||
| func (h *ArticleHandler) ListTags(c *gin.Context) { | ||||
| 	response, err := h.appService.ListTags(c.Request.Context()) | ||||
| 	if err != nil { | ||||
| 		h.logger.Error("获取标签列表失败", zap.Error(err)) | ||||
| 		h.responseBuilder.InternalError(c, "获取标签列表失败") | ||||
| 		return | ||||
| 	} | ||||
| 	 | ||||
| 	h.responseBuilder.Success(c, response, "获取标签列表成功") | ||||
| } | ||||
|  | ||||
| // GetTagByID 获取标签详情 | ||||
| // @Summary 获取标签详情 | ||||
| // @Description 根据ID获取标签详情 | ||||
| // @Tags 文章标签 | ||||
| // @Accept json | ||||
| // @Produce json | ||||
| // @Param id path string true "标签ID" | ||||
| // @Success 200 {object} responses.TagInfoResponse "获取标签详情成功" | ||||
| // @Failure 400 {object} map[string]interface{} "请求参数错误" | ||||
| // @Failure 404 {object} map[string]interface{} "标签不存在" | ||||
| // @Failure 500 {object} map[string]interface{} "服务器内部错误" | ||||
| // @Router /api/v1/article-tags/{id} [get] | ||||
| func (h *ArticleHandler) GetTagByID(c *gin.Context) { | ||||
| 	var query appQueries.GetTagQuery | ||||
| 	query.ID = c.Param("id") | ||||
| 	if query.ID == "" { | ||||
| 		h.responseBuilder.BadRequest(c, "标签ID不能为空") | ||||
| 		return | ||||
| 	} | ||||
| 	 | ||||
| 	response, err := h.appService.GetTagByID(c.Request.Context(), &query) | ||||
| 	if err != nil { | ||||
| 		h.logger.Error("获取标签详情失败", zap.Error(err)) | ||||
| 		h.responseBuilder.NotFound(c, "标签不存在") | ||||
| 		return | ||||
| 	} | ||||
| 	 | ||||
| 	h.responseBuilder.Success(c, response, "获取标签详情成功") | ||||
| } | ||||
|  | ||||
| // CreateTag 创建标签 | ||||
| // @Summary 创建标签 | ||||
| // @Description 创建新的文章标签 | ||||
| // @Tags 文章标签管理 | ||||
| // @Accept json | ||||
| // @Produce json | ||||
| // @Security Bearer | ||||
| // @Param request body commands.CreateTagCommand 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/article-tags [post] | ||||
| func (h *ArticleHandler) CreateTag(c *gin.Context) { | ||||
| 	var cmd commands.CreateTagCommand | ||||
| 	if err := h.validator.BindAndValidate(c, &cmd); err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	 | ||||
| 	if err := h.appService.CreateTag(c.Request.Context(), &cmd); err != nil { | ||||
| 		h.logger.Error("创建标签失败", zap.Error(err)) | ||||
| 		h.responseBuilder.BadRequest(c, err.Error()) | ||||
| 		return | ||||
| 	} | ||||
| 	 | ||||
| 	h.responseBuilder.Created(c, nil, "标签创建成功") | ||||
| } | ||||
|  | ||||
| // UpdateTag 更新标签 | ||||
| // @Summary 更新标签 | ||||
| // @Description 更新标签信息 | ||||
| // @Tags 文章标签管理 | ||||
| // @Accept json | ||||
| // @Produce json | ||||
| // @Security Bearer | ||||
| // @Param id path string true "标签ID" | ||||
| // @Param request body commands.UpdateTagCommand 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/article-tags/{id} [put] | ||||
| func (h *ArticleHandler) UpdateTag(c *gin.Context) { | ||||
| 	var cmd commands.UpdateTagCommand | ||||
| 	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.appService.UpdateTag(c.Request.Context(), &cmd); err != nil { | ||||
| 		h.logger.Error("更新标签失败", zap.Error(err)) | ||||
| 		h.responseBuilder.BadRequest(c, err.Error()) | ||||
| 		return | ||||
| 	} | ||||
| 	 | ||||
| 	h.responseBuilder.Success(c, nil, "标签更新成功") | ||||
| } | ||||
|  | ||||
| // DeleteTag 删除标签 | ||||
| // @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/article-tags/{id} [delete] | ||||
| func (h *ArticleHandler) DeleteTag(c *gin.Context) { | ||||
| 	var cmd commands.DeleteTagCommand | ||||
| 	if err := h.validator.ValidateParam(c, &cmd); err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	 | ||||
| 	if err := h.appService.DeleteTag(c.Request.Context(), &cmd); err != nil { | ||||
| 		h.logger.Error("删除标签失败", zap.Error(err)) | ||||
| 		h.responseBuilder.BadRequest(c, err.Error()) | ||||
| 		return | ||||
| 	} | ||||
| 	 | ||||
| 	h.responseBuilder.Success(c, nil, "标签删除成功") | ||||
| } | ||||
| @@ -1,3 +1,4 @@ | ||||
| //nolint:unused | ||||
| package handlers | ||||
|  | ||||
| import ( | ||||
| @@ -12,6 +13,7 @@ import ( | ||||
| 	"tyapi-server/internal/application/certification" | ||||
| 	"tyapi-server/internal/application/certification/dto/commands" | ||||
| 	"tyapi-server/internal/application/certification/dto/queries" | ||||
| 	_ "tyapi-server/internal/application/certification/dto/responses" | ||||
| 	"tyapi-server/internal/shared/interfaces" | ||||
| 	"tyapi-server/internal/shared/middleware" | ||||
| ) | ||||
| @@ -123,8 +125,8 @@ func (h *CertificationHandler) SubmitEnterpriseInfo(c *gin.Context) { | ||||
| // @Accept json | ||||
| // @Produce json | ||||
| // @Security Bearer | ||||
| // @Param request body commands.ConfirmAuthCommand true "确认状态请求" | ||||
| // @Success 200 {object} responses.ConfirmStatusResponse "状态确认成功" | ||||
| // @Param request body queries.ConfirmAuthCommand true "确认状态请求" | ||||
| // @Success 200 {object} responses.ConfirmAuthResponse "状态确认成功" | ||||
| // @Failure 400 {object} map[string]interface{} "请求参数错误" | ||||
| // @Failure 401 {object} map[string]interface{} "未认证" | ||||
| // @Failure 404 {object} map[string]interface{} "认证记录不存在" | ||||
| @@ -155,8 +157,8 @@ func (h *CertificationHandler) ConfirmAuth(c *gin.Context) { | ||||
| // @Accept json | ||||
| // @Produce json | ||||
| // @Security Bearer | ||||
| // @Param request body commands.ConfirmSignCommand true "确认状态请求" | ||||
| // @Success 200 {object} responses.ConfirmStatusResponse "状态确认成功" | ||||
| // @Param request body queries.ConfirmSignCommand true "确认状态请求" | ||||
| // @Success 200 {object} responses.ConfirmSignResponse "状态确认成功" | ||||
| // @Failure 400 {object} map[string]interface{} "请求参数错误" | ||||
| // @Failure 401 {object} map[string]interface{} "未认证" | ||||
| // @Failure 404 {object} map[string]interface{} "认证记录不存在" | ||||
| @@ -260,15 +262,13 @@ func (h *CertificationHandler) ListCertifications(c *gin.Context) { | ||||
|  | ||||
| // HandleEsignCallback 处理e签宝回调 | ||||
| // @Summary 处理e签宝回调 | ||||
| // @Description 处理e签宝的企业认证和合同签署回调 | ||||
| // @Description 处理e签宝的异步回调通知 | ||||
| // @Tags 认证管理 | ||||
| // @Accept json | ||||
| // @Produce json | ||||
| // @Param request body commands.EsignCallbackCommand true "e签宝回调数据" | ||||
| // @Success 200 {object} responses.CallbackResponse "回调处理成功" | ||||
| // @Failure 400 {object} map[string]interface{} "请求参数错误" | ||||
| // @Failure 500 {object} map[string]interface{} "服务器内部错误" | ||||
| // @Router /api/v1/certifications/callbacks/esign [post] | ||||
| // @Accept application/json | ||||
| // @Produce text/plain | ||||
| // @Success 200 {string} string "success" | ||||
| // @Failure 400 {string} string "fail" | ||||
| // @Router /api/v1/certifications/esign/callback [post] | ||||
| func (h *CertificationHandler) HandleEsignCallback(c *gin.Context) { | ||||
| 	// 记录请求基本信息 | ||||
| 	h.logger.Info("收到e签宝回调请求", | ||||
|   | ||||
| @@ -1,3 +1,4 @@ | ||||
| //nolint:unused | ||||
| package handlers | ||||
|  | ||||
| import ( | ||||
| @@ -12,6 +13,7 @@ import ( | ||||
| 	"tyapi-server/internal/application/finance" | ||||
| 	"tyapi-server/internal/application/finance/dto/commands" | ||||
| 	"tyapi-server/internal/application/finance/dto/queries" | ||||
| 	_ "tyapi-server/internal/application/finance/dto/responses" | ||||
| 	"tyapi-server/internal/shared/interfaces" | ||||
| ) | ||||
|  | ||||
| @@ -570,9 +572,9 @@ func (h *FinanceHandler) GetAlipayOrderStatus(c *gin.Context) { | ||||
| // @Accept json | ||||
| // @Produce json | ||||
| // @Param request body finance.ApplyInvoiceRequest true "申请开票请求" | ||||
| // @Success 200 {object} response.Response{data=finance.InvoiceApplicationResponse} | ||||
| // @Failure 400 {object} response.Response | ||||
| // @Failure 500 {object} response.Response | ||||
| // @Success 200 {object} interfaces.APIResponse{data=dto.InvoiceApplicationResponse} | ||||
| // @Failure 400 {object} interfaces.APIResponse | ||||
| // @Failure 500 {object} interfaces.APIResponse | ||||
| // @Router /api/v1/invoices/apply [post] | ||||
| func (h *FinanceHandler) ApplyInvoice(c *gin.Context) { | ||||
| 	var req finance.ApplyInvoiceRequest | ||||
| @@ -601,9 +603,9 @@ func (h *FinanceHandler) ApplyInvoice(c *gin.Context) { | ||||
| // @Description 获取用户的发票信息 | ||||
| // @Tags 发票管理 | ||||
| // @Produce json | ||||
| // @Success 200 {object} response.Response{data=finance.InvoiceInfoResponse} | ||||
| // @Failure 400 {object} response.Response | ||||
| // @Failure 500 {object} response.Response | ||||
| // @Success 200 {object} interfaces.APIResponse{data=dto.InvoiceInfoResponse} | ||||
| // @Failure 400 {object} interfaces.APIResponse | ||||
| // @Failure 500 {object} interfaces.APIResponse | ||||
| // @Router /api/v1/invoices/info [get] | ||||
| func (h *FinanceHandler) GetUserInvoiceInfo(c *gin.Context) { | ||||
| 	userID := c.GetString("user_id") | ||||
| @@ -628,9 +630,9 @@ func (h *FinanceHandler) GetUserInvoiceInfo(c *gin.Context) { | ||||
| // @Accept json | ||||
| // @Produce json | ||||
| // @Param request body finance.UpdateInvoiceInfoRequest true "更新发票信息请求" | ||||
| // @Success 200 {object} response.Response | ||||
| // @Failure 400 {object} response.Response | ||||
| // @Failure 500 {object} response.Response | ||||
| // @Success 200 {object} interfaces.APIResponse | ||||
| // @Failure 400 {object} interfaces.APIResponse | ||||
| // @Failure 500 {object} interfaces.APIResponse | ||||
| // @Router /api/v1/invoices/info [put] | ||||
| func (h *FinanceHandler) UpdateUserInvoiceInfo(c *gin.Context) { | ||||
| 	var req finance.UpdateInvoiceInfoRequest | ||||
| @@ -662,9 +664,9 @@ func (h *FinanceHandler) UpdateUserInvoiceInfo(c *gin.Context) { | ||||
| // @Param page query int false "页码" default(1) | ||||
| // @Param page_size query int false "每页数量" default(10) | ||||
| // @Param status query string false "状态筛选" | ||||
| // @Success 200 {object} response.Response{data=finance.InvoiceRecordsResponse} | ||||
| // @Failure 400 {object} response.Response | ||||
| // @Failure 500 {object} response.Response | ||||
| // @Success 200 {object} interfaces.APIResponse{data=dto.InvoiceRecordsResponse} | ||||
| // @Failure 400 {object} interfaces.APIResponse | ||||
| // @Failure 500 {object} interfaces.APIResponse | ||||
| // @Router /api/v1/invoices/records [get] | ||||
| func (h *FinanceHandler) GetUserInvoiceRecords(c *gin.Context) { | ||||
| 	userID := c.GetString("user_id") | ||||
| @@ -703,8 +705,8 @@ func (h *FinanceHandler) GetUserInvoiceRecords(c *gin.Context) { | ||||
| // @Produce application/octet-stream | ||||
| // @Param application_id path string true "申请ID" | ||||
| // @Success 200 {file} file | ||||
| // @Failure 400 {object} response.Response | ||||
| // @Failure 500 {object} response.Response | ||||
| // @Failure 400 {object} interfaces.APIResponse | ||||
| // @Failure 500 {object} interfaces.APIResponse | ||||
| // @Router /api/v1/invoices/{application_id}/download [get] | ||||
| func (h *FinanceHandler) DownloadInvoiceFile(c *gin.Context) { | ||||
| 	userID := c.GetString("user_id") | ||||
| @@ -739,9 +741,9 @@ func (h *FinanceHandler) DownloadInvoiceFile(c *gin.Context) { | ||||
| // @Description 获取用户当前可开票的金额 | ||||
| // @Tags 发票管理 | ||||
| // @Produce json | ||||
| // @Success 200 {object} response.Response{data=finance.AvailableAmountResponse} | ||||
| // @Failure 400 {object} response.Response | ||||
| // @Failure 500 {object} response.Response | ||||
| // @Success 200 {object} interfaces.APIResponse{data=dto.AvailableAmountResponse} | ||||
| // @Failure 400 {object} interfaces.APIResponse | ||||
| // @Failure 500 {object} interfaces.APIResponse | ||||
| // @Router /api/v1/invoices/available-amount [get] | ||||
| func (h *FinanceHandler) GetAvailableAmount(c *gin.Context) { | ||||
| 	userID := c.GetString("user_id") | ||||
| @@ -771,9 +773,9 @@ func (h *FinanceHandler) GetAvailableAmount(c *gin.Context) { | ||||
| // @Param status query string false "状态筛选:pending/completed/rejected" | ||||
| // @Param start_time query string false "开始时间 (格式: 2006-01-02 15:04:05)" | ||||
| // @Param end_time query string false "结束时间 (格式: 2006-01-02 15:04:05)" | ||||
| // @Success 200 {object} response.Response{data=finance.PendingApplicationsResponse} | ||||
| // @Failure 400 {object} response.Response | ||||
| // @Failure 500 {object} response.Response | ||||
| // @Success 200 {object} interfaces.APIResponse{data=dto.PendingApplicationsResponse} | ||||
| // @Failure 400 {object} interfaces.APIResponse | ||||
| // @Failure 500 {object} interfaces.APIResponse | ||||
| // @Router /api/v1/admin/invoices/pending [get] | ||||
| func (h *FinanceHandler) GetPendingApplications(c *gin.Context) { | ||||
| 	page, _ := strconv.Atoi(c.DefaultQuery("page", "1")) | ||||
| @@ -808,9 +810,9 @@ func (h *FinanceHandler) GetPendingApplications(c *gin.Context) { | ||||
| // @Param application_id path string true "申请ID" | ||||
| // @Param file formData file true "发票文件" | ||||
| // @Param admin_notes formData string false "管理员备注" | ||||
| // @Success 200 {object} response.Response | ||||
| // @Failure 400 {object} response.Response | ||||
| // @Failure 500 {object} response.Response | ||||
| // @Success 200 {object} interfaces.APIResponse | ||||
| // @Failure 400 {object} interfaces.APIResponse | ||||
| // @Failure 500 {object} interfaces.APIResponse | ||||
| // @Router /api/v1/admin/invoices/{application_id}/approve [post] | ||||
| func (h *FinanceHandler) ApproveInvoiceApplication(c *gin.Context) { | ||||
| 	applicationID := c.Param("application_id") | ||||
| @@ -860,9 +862,9 @@ func (h *FinanceHandler) ApproveInvoiceApplication(c *gin.Context) { | ||||
| // @Produce json | ||||
| // @Param application_id path string true "申请ID" | ||||
| // @Param request body finance.RejectInvoiceRequest true "拒绝申请请求" | ||||
| // @Success 200 {object} response.Response | ||||
| // @Failure 400 {object} response.Response | ||||
| // @Failure 500 {object} response.Response | ||||
| // @Success 200 {object} interfaces.APIResponse | ||||
| // @Failure 400 {object} interfaces.APIResponse | ||||
| // @Failure 500 {object} interfaces.APIResponse | ||||
| // @Router /api/v1/admin/invoices/{application_id}/reject [post] | ||||
| func (h *FinanceHandler) RejectInvoiceApplication(c *gin.Context) { | ||||
| 	applicationID := c.Param("application_id") | ||||
| @@ -893,8 +895,8 @@ func (h *FinanceHandler) RejectInvoiceApplication(c *gin.Context) { | ||||
| // @Produce application/octet-stream | ||||
| // @Param application_id path string true "申请ID" | ||||
| // @Success 200 {file} file | ||||
| // @Failure 400 {object} response.Response | ||||
| // @Failure 500 {object} response.Response | ||||
| // @Failure 400 {object} interfaces.APIResponse | ||||
| // @Failure 500 {object} interfaces.APIResponse | ||||
| // @Router /api/v1/admin/invoices/{application_id}/download [get] | ||||
| func (h *FinanceHandler) AdminDownloadInvoiceFile(c *gin.Context) { | ||||
| 	applicationID := c.Param("application_id") | ||||
| @@ -918,13 +920,16 @@ func (h *FinanceHandler) AdminDownloadInvoiceFile(c *gin.Context) { | ||||
| 	c.Data(http.StatusOK, "application/pdf", result.FileContent) | ||||
| } | ||||
|  | ||||
| // DebugEventSystem 调试事件系统状态 | ||||
| // @Summary 调试事件系统状态 | ||||
| // @Description 获取事件系统的调试信息 | ||||
| // @Tags 调试 | ||||
| // DebugEventSystem 调试事件系统 | ||||
| // @Summary 调试事件系统 | ||||
| // @Description 调试事件系统,用于测试事件触发和处理 | ||||
| // @Tags 系统调试 | ||||
| // @Accept json | ||||
| // @Produce json | ||||
| // @Success 200 {object} map[string]interface{} | ||||
| // @Router /api/v1/debug/events [get] | ||||
| // @Security Bearer | ||||
| // @Success 200 {object} map[string]interface{} "调试成功" | ||||
| // @Failure 500 {object} map[string]interface{} "服务器内部错误" | ||||
| // @Router /api/v1/debug/event-system [post] | ||||
| func (h *FinanceHandler) DebugEventSystem(c *gin.Context) { | ||||
| 	h.logger.Info("🔍 请求事件系统调试信息") | ||||
| 	 | ||||
|   | ||||
| @@ -1113,85 +1113,7 @@ func (h *ProductAdminHandler) DeleteProductDocumentation(c *gin.Context) { | ||||
| 	h.responseBuilder.Success(c, nil, "文档删除成功") | ||||
| } | ||||
|  | ||||
| // GetAdminApiCalls 获取管理端API调用记录 | ||||
| // @Summary 获取管理端API调用记录 | ||||
| // @Description 管理员获取API调用记录,支持筛选和分页 | ||||
| // @Tags API管理 | ||||
| // @Accept json | ||||
| // @Produce json | ||||
| // @Security Bearer | ||||
| // @Param page query int false "页码" default(1) | ||||
| // @Param page_size query int false "每页数量" default(10) | ||||
| // @Param user_id query string false "用户ID" | ||||
| // @Param transaction_id query string false "交易ID" | ||||
| // @Param product_name query string false "产品名称" | ||||
| // @Param status query string false "状态" | ||||
| // @Param start_time query string false "开始时间" format(date-time) | ||||
| // @Param end_time query string false "结束时间" format(date-time) | ||||
| // @Param sort_by query string false "排序字段" | ||||
| // @Param sort_order query string false "排序方向" Enums(asc, desc) | ||||
| // @Success 200 {object} dto.ApiCallListResponse "获取API调用记录成功" | ||||
| // @Failure 400 {object} map[string]interface{} "请求参数错误" | ||||
| // @Failure 401 {object} map[string]interface{} "未认证" | ||||
| // @Failure 500 {object} map[string]interface{} "服务器内部错误" | ||||
| // @Router /api/v1/admin/api-calls [get] | ||||
| func (h *ProductAdminHandler) GetAdminApiCalls(c *gin.Context) { | ||||
| 	// 解析查询参数 | ||||
| 	page := h.getIntQuery(c, "page", 1) | ||||
| 	pageSize := h.getIntQuery(c, "page_size", 10) | ||||
|  | ||||
| 	// 构建筛选条件 | ||||
| 	filters := make(map[string]interface{}) | ||||
|  | ||||
| 	// 用户ID筛选 | ||||
| 	if userId := c.Query("user_id"); userId != "" { | ||||
| 		filters["user_id"] = userId | ||||
| 	} | ||||
|  | ||||
| 	// 时间范围筛选 | ||||
| 	if startTime := c.Query("start_time"); startTime != "" { | ||||
| 		if t, err := time.Parse("2006-01-02 15:04:05", startTime); err == nil { | ||||
| 			filters["start_time"] = t | ||||
| 		} | ||||
| 	} | ||||
| 	if endTime := c.Query("end_time"); endTime != "" { | ||||
| 		if t, err := time.Parse("2006-01-02 15:04:05", endTime); err == nil { | ||||
| 			filters["end_time"] = t | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// 交易ID筛选 | ||||
| 	if transactionId := c.Query("transaction_id"); transactionId != "" { | ||||
| 		filters["transaction_id"] = transactionId | ||||
| 	} | ||||
|  | ||||
| 	// 产品名称筛选 | ||||
| 	if productName := c.Query("product_name"); productName != "" { | ||||
| 		filters["product_name"] = productName | ||||
| 	} | ||||
|  | ||||
| 	// 状态筛选 | ||||
| 	if status := c.Query("status"); status != "" { | ||||
| 		filters["status"] = status | ||||
| 	} | ||||
|  | ||||
| 	// 构建分页选项 | ||||
| 	options := interfaces.ListOptions{ | ||||
| 		Page:     page, | ||||
| 		PageSize: pageSize, | ||||
| 		Sort:     "created_at", | ||||
| 		Order:    "desc", | ||||
| 	} | ||||
|  | ||||
| 	result, err := h.apiAppService.GetAdminApiCalls(c.Request.Context(), filters, options) | ||||
| 	if err != nil { | ||||
| 		h.logger.Error("获取管理端API调用记录失败", zap.Error(err)) | ||||
| 		h.responseBuilder.BadRequest(c, "获取API调用记录失败") | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	h.responseBuilder.Success(c, result, "获取API调用记录成功") | ||||
| } | ||||
|  | ||||
| // GetAdminWalletTransactions 获取管理端消费记录 | ||||
| // @Summary 获取管理端消费记录 | ||||
| @@ -1211,7 +1133,7 @@ func (h *ProductAdminHandler) GetAdminApiCalls(c *gin.Context) { | ||||
| // @Param end_time query string false "结束时间" format(date-time) | ||||
| // @Param sort_by query string false "排序字段" | ||||
| // @Param sort_order query string false "排序方向" Enums(asc, desc) | ||||
| // @Success 200 {object} dto.WalletTransactionListResponse "获取消费记录成功" | ||||
| // @Success 200 {object} responses.WalletTransactionListResponse "获取消费记录成功" | ||||
| // @Failure 400 {object} map[string]interface{} "请求参数错误" | ||||
| // @Failure 401 {object} map[string]interface{} "未认证" | ||||
| // @Failure 500 {object} map[string]interface{} "服务器内部错误" | ||||
| @@ -1295,7 +1217,7 @@ func (h *ProductAdminHandler) GetAdminWalletTransactions(c *gin.Context) { | ||||
| // @Param end_time query string false "结束时间" format(date-time) | ||||
| // @Param sort_by query string false "排序字段" | ||||
| // @Param sort_order query string false "排序方向" Enums(asc, desc) | ||||
| // @Success 200 {object} dto.RechargeRecordListResponse "获取充值记录成功" | ||||
| // @Success 200 {object} responses.RechargeRecordListResponse "获取充值记录成功" | ||||
| // @Failure 400 {object} map[string]interface{} "请求参数错误" | ||||
| // @Failure 401 {object} map[string]interface{} "未认证" | ||||
| // @Failure 500 {object} map[string]interface{} "服务器内部错误" | ||||
|   | ||||
| @@ -1,3 +1,4 @@ | ||||
| //nolint:unused | ||||
| package handlers | ||||
|  | ||||
| import ( | ||||
| @@ -5,6 +6,7 @@ import ( | ||||
| 	"tyapi-server/internal/application/product" | ||||
| 	"tyapi-server/internal/application/product/dto/commands" | ||||
| 	"tyapi-server/internal/application/product/dto/queries" | ||||
| 	_ "tyapi-server/internal/application/product/dto/responses" | ||||
| 	"tyapi-server/internal/shared/interfaces" | ||||
|  | ||||
| 	"github.com/gin-gonic/gin" | ||||
| @@ -607,9 +609,9 @@ func (h *ProductHandler) GetMySubscriptionUsage(c *gin.Context) { | ||||
| // @Accept json | ||||
| // @Produce json | ||||
| // @Param id path string true "产品ID" | ||||
| // @Success 200 {object} responses.DocumentationResponse "获取文档成功" | ||||
| // @Success 200 {object} responses.DocumentationResponse "获取产品文档成功" | ||||
| // @Failure 400 {object} map[string]interface{} "请求参数错误" | ||||
| // @Failure 404 {object} map[string]interface{} "产品或文档不存在" | ||||
| // @Failure 404 {object} map[string]interface{} "产品不存在" | ||||
| // @Failure 500 {object} map[string]interface{} "服务器内部错误" | ||||
| // @Router /api/v1/products/{id}/documentation [get] | ||||
| func (h *ProductHandler) GetProductDocumentation(c *gin.Context) { | ||||
|   | ||||
| @@ -1,3 +1,4 @@ | ||||
| //nolint:unused | ||||
| package handlers | ||||
|  | ||||
| import ( | ||||
| @@ -9,6 +10,7 @@ import ( | ||||
| 	"tyapi-server/internal/application/user" | ||||
| 	"tyapi-server/internal/application/user/dto/commands" | ||||
| 	"tyapi-server/internal/application/user/dto/queries" | ||||
| 	_ "tyapi-server/internal/application/user/dto/responses" | ||||
| 	"tyapi-server/internal/shared/interfaces" | ||||
| 	"tyapi-server/internal/shared/middleware" | ||||
| ) | ||||
| @@ -362,9 +364,9 @@ func (h *UserHandler) GetUserDetail(c *gin.Context) { | ||||
| 	h.response.Success(c, resp, "获取用户详情成功") | ||||
| } | ||||
|  | ||||
| // GetUserStats 管理员获取用户统计信息 | ||||
| // @Summary 管理员获取用户统计信息 | ||||
| // @Description 管理员获取用户统计信息,包括总用户数、活跃用户数、已认证用户数 | ||||
| // GetUserStats 获取用户统计信息 | ||||
| // @Summary 获取用户统计信息 | ||||
| // @Description 管理员获取用户相关的统计信息 | ||||
| // @Tags 用户管理 | ||||
| // @Accept json | ||||
| // @Produce json | ||||
|   | ||||
							
								
								
									
										104
									
								
								internal/infrastructure/http/routes/article_routes.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										104
									
								
								internal/infrastructure/http/routes/article_routes.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,104 @@ | ||||
| package routes | ||||
|  | ||||
| import ( | ||||
| 	"tyapi-server/internal/infrastructure/http/handlers" | ||||
| 	sharedhttp "tyapi-server/internal/shared/http" | ||||
| 	"tyapi-server/internal/shared/middleware" | ||||
|  | ||||
| 	"go.uber.org/zap" | ||||
| ) | ||||
|  | ||||
| // ArticleRoutes 文章路由 | ||||
| type ArticleRoutes struct { | ||||
| 	handler *handlers.ArticleHandler | ||||
| 	auth    *middleware.JWTAuthMiddleware | ||||
| 	admin   *middleware.AdminAuthMiddleware | ||||
| 	logger  *zap.Logger | ||||
| } | ||||
|  | ||||
| // NewArticleRoutes 创建文章路由 | ||||
| func NewArticleRoutes( | ||||
| 	handler *handlers.ArticleHandler, | ||||
| 	auth *middleware.JWTAuthMiddleware, | ||||
| 	admin *middleware.AdminAuthMiddleware, | ||||
| 	logger *zap.Logger, | ||||
| ) *ArticleRoutes { | ||||
| 	return &ArticleRoutes{ | ||||
| 		handler: handler, | ||||
| 		auth:    auth, | ||||
| 		admin:   admin, | ||||
| 		logger:  logger, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Register 注册路由 | ||||
| func (r *ArticleRoutes) Register(router *sharedhttp.GinRouter) { | ||||
| 	engine := router.GetEngine() | ||||
|  | ||||
| 	// ==================== 用户端路由 ==================== | ||||
| 	// 文章相关路由 - 用户端 | ||||
| 	articleGroup := engine.Group("/api/v1/articles") | ||||
| 	{ | ||||
| 		// 公开路由 - 不需要认证 | ||||
| 		articleGroup.GET("/:id", r.handler.GetArticleByID) // 获取文章详情 | ||||
| 		articleGroup.GET("", r.handler.ListArticles)       // 获取文章列表(支持筛选:标题、分类、摘要、标签、推荐状态) | ||||
| 	} | ||||
|  | ||||
| 	// 分类相关路由 - 用户端 | ||||
| 	categoryGroup := engine.Group("/api/v1/article-categories") | ||||
| 	{ | ||||
| 		// 公开路由 - 不需要认证 | ||||
| 		categoryGroup.GET("", r.handler.ListCategories)      // 获取分类列表 | ||||
| 		categoryGroup.GET("/:id", r.handler.GetCategoryByID) // 获取分类详情 | ||||
| 	} | ||||
|  | ||||
| 	// 标签相关路由 - 用户端 | ||||
| 	tagGroup := engine.Group("/api/v1/article-tags") | ||||
| 	{ | ||||
| 		// 公开路由 - 不需要认证 | ||||
| 		tagGroup.GET("", r.handler.ListTags)       // 获取标签列表 | ||||
| 		tagGroup.GET("/:id", r.handler.GetTagByID) // 获取标签详情 | ||||
| 	} | ||||
|  | ||||
| 	// ==================== 管理员端路由 ==================== | ||||
| 	// 管理员文章管理路由 | ||||
| 	adminArticleGroup := engine.Group("/api/v1/admin/articles") | ||||
| 	adminArticleGroup.Use(r.admin.Handle()) | ||||
| 	{ | ||||
| 		// 统计信息 | ||||
| 		adminArticleGroup.GET("/stats", r.handler.GetArticleStats)               // 获取文章统计 | ||||
| 		 | ||||
| 		// 文章管理 | ||||
| 		adminArticleGroup.POST("", r.handler.CreateArticle)       // 创建文章 | ||||
| 		adminArticleGroup.PUT("/:id", r.handler.UpdateArticle)    // 更新文章 | ||||
| 		adminArticleGroup.DELETE("/:id", r.handler.DeleteArticle) // 删除文章 | ||||
|  | ||||
| 		// 文章状态管理 | ||||
| 		adminArticleGroup.POST("/:id/publish", r.handler.PublishArticle)                  // 发布文章 | ||||
| 		adminArticleGroup.POST("/:id/schedule-publish", r.handler.SchedulePublishArticle) // 定时发布文章 | ||||
| 		adminArticleGroup.POST("/:id/archive", r.handler.ArchiveArticle)                  // 归档文章 | ||||
| 		adminArticleGroup.PUT("/:id/featured", r.handler.SetFeatured)                     // 设置推荐状态 | ||||
| 	} | ||||
|  | ||||
| 	// 管理员分类管理路由 | ||||
| 	adminCategoryGroup := engine.Group("/api/v1/admin/article-categories") | ||||
| 	adminCategoryGroup.Use(r.admin.Handle()) | ||||
| 	{ | ||||
| 		// 分类管理 | ||||
| 		adminCategoryGroup.POST("", r.handler.CreateCategory)       // 创建分类 | ||||
| 		adminCategoryGroup.PUT("/:id", r.handler.UpdateCategory)    // 更新分类 | ||||
| 		adminCategoryGroup.DELETE("/:id", r.handler.DeleteCategory) // 删除分类 | ||||
| 	} | ||||
|  | ||||
| 	// 管理员标签管理路由 | ||||
| 	adminTagGroup := engine.Group("/api/v1/admin/article-tags") | ||||
| 	adminTagGroup.Use(r.admin.Handle()) | ||||
| 	{ | ||||
| 		// 标签管理 | ||||
| 		adminTagGroup.POST("", r.handler.CreateTag)       // 创建标签 | ||||
| 		adminTagGroup.PUT("/:id", r.handler.UpdateTag)    // 更新标签 | ||||
| 		adminTagGroup.DELETE("/:id", r.handler.DeleteTag) // 删除标签 | ||||
| 	} | ||||
|  | ||||
| 	r.logger.Info("文章路由注册完成") | ||||
| } | ||||
| @@ -81,11 +81,7 @@ func (r *ProductAdminRoutes) Register(router *sharedhttp.GinRouter) { | ||||
| 			subscriptions.POST("/batch-update-prices", r.handler.BatchUpdateSubscriptionPrices) | ||||
| 		} | ||||
|  | ||||
| 		// API调用记录管理 | ||||
| 		apiCalls := adminGroup.Group("/api-calls") | ||||
| 		{ | ||||
| 			apiCalls.GET("", r.handler.GetAdminApiCalls) | ||||
| 		} | ||||
|  | ||||
|  | ||||
| 		// 消费记录管理 | ||||
| 		walletTransactions := adminGroup.Group("/wallet-transactions") | ||||
|   | ||||
		Reference in New Issue
	
	Block a user