This commit is contained in:
2025-09-12 01:15:09 +08:00
parent c563b2266b
commit e05ad9e223
103 changed files with 20034 additions and 1041 deletions

View File

@@ -468,6 +468,77 @@ func (h *ApiHandler) GetAdminApiCalls(c *gin.Context) {
h.responseBuilder.Success(c, result, "获取API调用记录成功")
}
// ExportAdminApiCalls 导出管理端API调用记录
// @Summary 导出管理端API调用记录
// @Description 管理员导出API调用记录支持Excel和CSV格式
// @Tags API调用管理
// @Accept json
// @Produce application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,text/csv
// @Security Bearer
// @Param user_ids query string false "用户ID列表逗号分隔"
// @Param product_ids query string false "产品ID列表逗号分隔"
// @Param start_time query string false "开始时间" format(date-time)
// @Param end_time query string false "结束时间" format(date-time)
// @Param format query string false "导出格式" Enums(excel, csv) default(excel)
// @Success 200 {file} file "导出文件"
// @Failure 400 {object} map[string]interface{} "请求参数错误"
// @Failure 401 {object} map[string]interface{} "未认证"
// @Failure 500 {object} map[string]interface{} "服务器内部错误"
// @Router /api/v1/admin/api-calls/export [get]
func (h *ApiHandler) ExportAdminApiCalls(c *gin.Context) {
// 解析查询参数
filters := make(map[string]interface{})
// 用户ID筛选
if userIds := c.Query("user_ids"); userIds != "" {
filters["user_ids"] = userIds
}
// 产品ID筛选
if productIds := c.Query("product_ids"); productIds != "" {
filters["product_ids"] = productIds
}
// 时间范围筛选
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
}
}
// 获取导出格式默认为excel
format := c.DefaultQuery("format", "excel")
if format != "excel" && format != "csv" {
h.responseBuilder.BadRequest(c, "不支持的导出格式")
return
}
// 调用应用服务导出数据
fileData, err := h.appService.ExportAdminApiCalls(c.Request.Context(), filters, format)
if err != nil {
h.logger.Error("导出API调用记录失败", zap.Error(err))
h.responseBuilder.BadRequest(c, "导出API调用记录失败")
return
}
// 设置响应头
contentType := "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
filename := "API调用记录.xlsx"
if format == "csv" {
contentType = "text/csv;charset=utf-8"
filename = "API调用记录.csv"
}
c.Header("Content-Type", contentType)
c.Header("Content-Disposition", "attachment; filename="+filename)
c.Data(200, contentType, fileData)
}
// getIntQuery 获取整数查询参数
func (h *ApiHandler) getIntQuery(c *gin.Context, key string, defaultValue int) int {
if value := c.Query(key); value != "" {
@@ -477,3 +548,116 @@ func (h *ApiHandler) getIntQuery(c *gin.Context, key string, defaultValue int) i
}
return defaultValue
}
// GetUserBalanceAlertSettings 获取用户余额预警设置
// @Summary 获取用户余额预警设置
// @Description 获取当前用户的余额预警配置
// @Tags 用户设置
// @Accept json
// @Produce json
// @Success 200 {object} map[string]interface{} "获取成功"
// @Failure 401 {object} map[string]interface{} "未授权"
// @Failure 500 {object} map[string]interface{} "服务器内部错误"
// @Router /api/v1/user/balance-alert/settings [get]
func (h *ApiHandler) GetUserBalanceAlertSettings(c *gin.Context) {
userID := c.GetString("user_id")
if userID == "" {
h.responseBuilder.Unauthorized(c, "用户未登录")
return
}
settings, err := h.appService.GetUserBalanceAlertSettings(c.Request.Context(), userID)
if err != nil {
h.logger.Error("获取用户余额预警设置失败",
zap.String("user_id", userID),
zap.Error(err))
h.responseBuilder.InternalError(c, "获取预警设置失败")
return
}
h.responseBuilder.Success(c, settings, "获取成功")
}
// UpdateUserBalanceAlertSettings 更新用户余额预警设置
// @Summary 更新用户余额预警设置
// @Description 更新当前用户的余额预警配置
// @Tags 用户设置
// @Accept json
// @Produce json
// @Param request body map[string]interface{} true "预警设置"
// @Success 200 {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/user/balance-alert/settings [put]
func (h *ApiHandler) UpdateUserBalanceAlertSettings(c *gin.Context) {
userID := c.GetString("user_id")
if userID == "" {
h.responseBuilder.Unauthorized(c, "用户未登录")
return
}
var request struct {
Enabled bool `json:"enabled" binding:"required"`
Threshold float64 `json:"threshold" binding:"required,min=0"`
AlertPhone string `json:"alert_phone" binding:"required"`
}
if err := c.ShouldBindJSON(&request); err != nil {
h.responseBuilder.BadRequest(c, "请求参数错误: "+err.Error())
return
}
err := h.appService.UpdateUserBalanceAlertSettings(c.Request.Context(), userID, request.Enabled, request.Threshold, request.AlertPhone)
if err != nil {
h.logger.Error("更新用户余额预警设置失败",
zap.String("user_id", userID),
zap.Error(err))
h.responseBuilder.InternalError(c, "更新预警设置失败")
return
}
h.responseBuilder.Success(c, gin.H{}, "更新成功")
}
// TestBalanceAlertSms 测试余额预警短信
// @Summary 测试余额预警短信
// @Description 发送测试预警短信到指定手机号
// @Tags 用户设置
// @Accept json
// @Produce json
// @Param request body map[string]interface{} true "测试参数"
// @Success 200 {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/user/balance-alert/test-sms [post]
func (h *ApiHandler) TestBalanceAlertSms(c *gin.Context) {
userID := c.GetString("user_id")
if userID == "" {
h.responseBuilder.Unauthorized(c, "用户未登录")
return
}
var request struct {
Phone string `json:"phone" binding:"required,len=11"`
Balance float64 `json:"balance" binding:"required"`
AlertType string `json:"alert_type" binding:"required,oneof=low_balance arrears"`
}
if err := c.ShouldBindJSON(&request); err != nil {
h.responseBuilder.BadRequest(c, "请求参数错误: "+err.Error())
return
}
err := h.appService.TestBalanceAlertSms(c.Request.Context(), userID, request.Phone, request.Balance, request.AlertType)
if err != nil {
h.logger.Error("发送测试预警短信失败",
zap.String("user_id", userID),
zap.Error(err))
h.responseBuilder.InternalError(c, "发送测试短信失败")
return
}
h.responseBuilder.Success(c, gin.H{}, "测试短信发送成功")
}

View File

@@ -215,6 +215,86 @@ func (h *CertificationHandler) ApplyContract(c *gin.Context) {
h.response.Success(c, result, "合同申请成功")
}
// RecognizeBusinessLicense OCR识别营业执照
// @Summary OCR识别营业执照
// @Description 上传营业执照图片进行OCR识别自动填充企业信息
// @Tags 认证管理
// @Accept multipart/form-data
// @Produce json
// @Security Bearer
// @Param image formData file true "营业执照图片文件"
// @Success 200 {object} responses.BusinessLicenseResult "营业执照识别成功"
// @Failure 400 {object} map[string]interface{} "请求参数错误"
// @Failure 401 {object} map[string]interface{} "未认证"
// @Failure 500 {object} map[string]interface{} "服务器内部错误"
// @Router /api/v1/certifications/ocr/business-license [post]
func (h *CertificationHandler) RecognizeBusinessLicense(c *gin.Context) {
userID := h.getCurrentUserID(c)
if userID == "" {
h.response.Unauthorized(c, "用户未登录")
return
}
// 获取上传的文件
file, err := c.FormFile("image")
if err != nil {
h.logger.Error("获取上传文件失败", zap.Error(err), zap.String("user_id", userID))
h.response.BadRequest(c, "请选择要上传的营业执照图片")
return
}
// 验证文件类型
allowedTypes := map[string]bool{
"image/jpeg": true,
"image/jpg": true,
"image/png": true,
"image/webp": true,
}
if !allowedTypes[file.Header.Get("Content-Type")] {
h.response.BadRequest(c, "只支持JPG、PNG、WEBP格式的图片")
return
}
// 验证文件大小限制为5MB
if file.Size > 5*1024*1024 {
h.response.BadRequest(c, "图片大小不能超过5MB")
return
}
// 打开文件
src, err := file.Open()
if err != nil {
h.logger.Error("打开上传文件失败", zap.Error(err), zap.String("user_id", userID))
h.response.BadRequest(c, "文件读取失败")
return
}
defer src.Close()
// 读取文件内容
imageBytes, err := io.ReadAll(src)
if err != nil {
h.logger.Error("读取文件内容失败", zap.Error(err), zap.String("user_id", userID))
h.response.BadRequest(c, "文件读取失败")
return
}
// 调用OCR服务识别营业执照
result, err := h.appService.RecognizeBusinessLicense(c.Request.Context(), imageBytes)
if err != nil {
h.logger.Error("营业执照OCR识别失败", zap.Error(err), zap.String("user_id", userID))
h.response.BadRequest(c, "营业执照识别失败:"+err.Error())
return
}
h.logger.Info("营业执照OCR识别成功",
zap.String("user_id", userID),
zap.String("company_name", result.CompanyName),
zap.Float64("confidence", result.Confidence),
)
h.response.Success(c, result, "营业执照识别成功")
}
// ListCertifications 获取认证列表(管理员)
// @Summary 获取认证列表
// @Description 管理员获取认证申请列表

View File

@@ -1199,6 +1199,102 @@ func (h *ProductAdminHandler) GetAdminWalletTransactions(c *gin.Context) {
h.responseBuilder.Success(c, result, "获取消费记录成功")
}
// ExportAdminWalletTransactions 导出管理端消费记录
// @Summary 导出管理端消费记录
// @Description 管理员导出消费记录支持Excel和CSV格式
// @Tags 财务管理
// @Accept json
// @Produce application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,text/csv
// @Security Bearer
// @Param user_ids query string false "用户ID列表逗号分隔"
// @Param user_id query string false "单个用户ID"
// @Param transaction_id query string false "交易ID"
// @Param product_name query string false "产品名称"
// @Param product_ids query string false "产品ID列表逗号分隔"
// @Param min_amount query string false "最小金额"
// @Param max_amount query string false "最大金额"
// @Param start_time query string false "开始时间" format(date-time)
// @Param end_time query string false "结束时间" format(date-time)
// @Param format query string false "导出格式" Enums(excel, csv) default(excel)
// @Success 200 {file} file "导出文件"
// @Failure 400 {object} map[string]interface{} "请求参数错误"
// @Failure 401 {object} map[string]interface{} "未认证"
// @Failure 500 {object} map[string]interface{} "服务器内部错误"
// @Router /api/v1/admin/wallet-transactions/export [get]
func (h *ProductAdminHandler) ExportAdminWalletTransactions(c *gin.Context) {
// 构建筛选条件
filters := make(map[string]interface{})
// 用户ID筛选
if userIds := c.Query("user_ids"); userIds != "" {
filters["user_ids"] = userIds
} else 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
}
// 产品ID列表筛选
if productIds := c.Query("product_ids"); productIds != "" {
filters["product_ids"] = productIds
}
// 金额范围筛选
if minAmount := c.Query("min_amount"); minAmount != "" {
filters["min_amount"] = minAmount
}
if maxAmount := c.Query("max_amount"); maxAmount != "" {
filters["max_amount"] = maxAmount
}
// 获取导出格式
format := c.DefaultQuery("format", "excel")
if format != "excel" && format != "csv" {
h.responseBuilder.BadRequest(c, "不支持的导出格式")
return
}
// 调用导出服务
fileData, err := h.financeAppService.ExportAdminWalletTransactions(c.Request.Context(), filters, format)
if err != nil {
h.logger.Error("导出消费记录失败", zap.Error(err))
h.responseBuilder.BadRequest(c, "导出消费记录失败")
return
}
// 设置响应头
contentType := "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
filename := "消费记录.xlsx"
if format == "csv" {
contentType = "text/csv;charset=utf-8"
filename = "消费记录.csv"
}
c.Header("Content-Type", contentType)
c.Header("Content-Disposition", "attachment; filename="+filename)
c.Data(200, contentType, fileData)
}
// GetAdminRechargeRecords 获取管理端充值记录
// @Summary 获取管理端充值记录
// @Description 管理员获取充值记录,支持筛选和分页
@@ -1282,3 +1378,184 @@ func (h *ProductAdminHandler) GetAdminRechargeRecords(c *gin.Context) {
h.responseBuilder.Success(c, result, "获取充值记录成功")
}
// ExportAdminRechargeRecords 导出管理端充值记录
// @Summary 导出管理端充值记录
// @Description 管理员导出充值记录支持Excel和CSV格式
// @Tags 财务管理
// @Accept json
// @Produce application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,text/csv
// @Security Bearer
// @Param user_ids query string false "用户ID列表逗号分隔"
// @Param recharge_type query string false "充值类型" Enums(alipay, transfer, gift)
// @Param status query string false "状态" Enums(pending, success, failed)
// @Param start_time query string false "开始时间" format(date-time)
// @Param end_time query string false "结束时间" format(date-time)
// @Param format query string false "导出格式" Enums(excel, csv) default(excel)
// @Success 200 {file} file "导出文件"
// @Failure 400 {object} map[string]interface{} "请求参数错误"
// @Failure 401 {object} map[string]interface{} "未认证"
// @Failure 500 {object} map[string]interface{} "服务器内部错误"
// @Router /api/v1/admin/recharge-records/export [get]
func (h *ProductAdminHandler) ExportAdminRechargeRecords(c *gin.Context) {
// 解析查询参数
filters := make(map[string]interface{})
// 用户ID筛选
if userIds := c.Query("user_ids"); userIds != "" {
filters["user_ids"] = userIds
}
// 充值类型筛选
if rechargeType := c.Query("recharge_type"); rechargeType != "" {
filters["recharge_type"] = rechargeType
}
// 状态筛选
if status := c.Query("status"); status != "" {
filters["status"] = status
}
// 时间范围筛选
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
}
}
// 获取导出格式默认为excel
format := c.DefaultQuery("format", "excel")
if format != "excel" && format != "csv" {
h.responseBuilder.BadRequest(c, "不支持的导出格式")
return
}
// 调用应用服务导出数据
fileData, err := h.financeAppService.ExportAdminRechargeRecords(c.Request.Context(), filters, format)
if err != nil {
h.logger.Error("导出充值记录失败", zap.Error(err))
h.responseBuilder.BadRequest(c, "导出充值记录失败")
return
}
// 设置响应头
contentType := "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
filename := "充值记录.xlsx"
if format == "csv" {
contentType = "text/csv;charset=utf-8"
filename = "充值记录.csv"
}
c.Header("Content-Type", contentType)
c.Header("Content-Disposition", "attachment; filename="+filename)
c.Data(200, contentType, fileData)
}
// GetAdminApiCalls 获取管理端API调用记录
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 userIds := c.Query("user_ids"); userIds != "" {
filters["user_ids"] = userIds
}
// 产品ID筛选
if productIds := c.Query("product_ids"); productIds != "" {
filters["product_ids"] = productIds
}
// 时间范围筛选
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
}
}
// 构建分页选项
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调用记录成功")
}
// ExportAdminApiCalls 导出管理端API调用记录
func (h *ProductAdminHandler) ExportAdminApiCalls(c *gin.Context) {
// 解析查询参数
filters := make(map[string]interface{})
// 用户ID筛选
if userIds := c.Query("user_ids"); userIds != "" {
filters["user_ids"] = userIds
}
// 产品ID筛选
if productIds := c.Query("product_ids"); productIds != "" {
filters["product_ids"] = productIds
}
// 时间范围筛选
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
}
}
// 获取导出格式默认为excel
format := c.DefaultQuery("format", "excel")
if format != "excel" && format != "csv" {
h.responseBuilder.BadRequest(c, "不支持的导出格式")
return
}
// 调用应用服务导出数据
fileData, err := h.apiAppService.ExportAdminApiCalls(c.Request.Context(), filters, format)
if err != nil {
h.logger.Error("导出API调用记录失败", zap.Error(err))
h.responseBuilder.BadRequest(c, "导出API调用记录失败")
return
}
// 设置响应头
contentType := "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
filename := "API调用记录.xlsx"
if format == "csv" {
contentType = "text/csv;charset=utf-8"
filename = "API调用记录.csv"
}
c.Header("Content-Type", contentType)
c.Header("Content-Disposition", "attachment; filename="+filename)
c.Data(200, contentType, fileData)
}

File diff suppressed because it is too large Load Diff

View File

@@ -274,7 +274,6 @@ func (h *UserHandler) ListUsers(c *gin.Context) {
return
}
// 构建查询参数
query := &queries.ListUsersQuery{
Page: 1,
@@ -289,7 +288,7 @@ func (h *UserHandler) ListUsers(c *gin.Context) {
}
if pageSize := c.Query("page_size"); pageSize != "" {
if size, err := strconv.Atoi(pageSize); err == nil && size > 0 && size <= 100 {
if size, err := strconv.Atoi(pageSize); err == nil && size > 0 && size <= 1000 {
query.PageSize = size
}
}

View File

@@ -38,6 +38,7 @@ func (r *ApiRoutes) Register(router *sharedhttp.GinRouter) {
apiGroup := engine.Group("/api/v1")
{
// API调用接口 - 不受频率限制(业务核心接口)
apiGroup.POST("/:api_name", r.domainAuthMiddleware.Handle(""), r.apiHandler.HandleApiCall)
// Console专用接口 - 使用JWT认证不需要域名认证
@@ -62,6 +63,11 @@ func (r *ApiRoutes) Register(router *sharedhttp.GinRouter) {
// API调用记录接口
apiGroup.GET("/my/api-calls", r.authMiddleware.Handle(), r.apiHandler.GetUserApiCalls)
// 余额预警设置接口
apiGroup.GET("/user/balance-alert/settings", r.authMiddleware.Handle(), r.apiHandler.GetUserBalanceAlertSettings)
apiGroup.PUT("/user/balance-alert/settings", r.authMiddleware.Handle(), r.apiHandler.UpdateUserBalanceAlertSettings)
apiGroup.POST("/user/balance-alert/test-sms", r.authMiddleware.Handle(), r.apiHandler.TestBalanceAlertSms)
}
r.logger.Info("API路由注册完成")

View File

@@ -54,6 +54,9 @@ func (r *CertificationRoutes) Register(router *http.GinRouter) {
// 2. 提交企业信息(应用每日限流)
authGroup.POST("/enterprise-info", r.dailyRateLimit.Handle(), r.handler.SubmitEnterpriseInfo)
// OCR营业执照识别接口
authGroup.POST("/ocr/business-license", r.handler.RecognizeBusinessLicense)
// 3. 申请合同签署
authGroup.POST("/apply-contract", r.handler.ApplyContract)
@@ -84,6 +87,7 @@ func (r *CertificationRoutes) GetRoutes() []RouteInfo {
{Method: "GET", Path: "/api/v1/certifications", Handler: "ListCertifications", Auth: true},
{Method: "GET", Path: "/api/v1/certifications/statistics", Handler: "GetCertificationStatistics", Auth: true},
{Method: "POST", Path: "/api/v1/certifications/:id/enterprise-info", Handler: "SubmitEnterpriseInfo", Auth: true},
{Method: "POST", Path: "/api/v1/certifications/ocr/business-license", Handler: "RecognizeBusinessLicense", Auth: true},
{Method: "POST", Path: "/api/v1/certifications/apply-contract", Handler: "ApplyContract", Auth: true},
{Method: "POST", Path: "/api/v1/certifications/retry", Handler: "RetryOperation", Auth: true},
{Method: "POST", Path: "/api/v1/certifications/force-transition", Handler: "ForceTransitionStatus", Auth: true},

View File

@@ -87,12 +87,21 @@ func (r *ProductAdminRoutes) Register(router *sharedhttp.GinRouter) {
walletTransactions := adminGroup.Group("/wallet-transactions")
{
walletTransactions.GET("", r.handler.GetAdminWalletTransactions)
walletTransactions.GET("/export", r.handler.ExportAdminWalletTransactions)
}
// API调用记录管理
apiCalls := adminGroup.Group("/api-calls")
{
apiCalls.GET("", r.handler.GetAdminApiCalls)
apiCalls.GET("/export", r.handler.ExportAdminApiCalls)
}
// 充值记录管理
rechargeRecords := adminGroup.Group("/recharge-records")
{
rechargeRecords.GET("", r.handler.GetAdminRechargeRecords)
rechargeRecords.GET("/export", r.handler.ExportAdminRechargeRecords)
}
}
}

View File

@@ -0,0 +1,165 @@
package routes
import (
"tyapi-server/internal/infrastructure/http/handlers"
sharedhttp "tyapi-server/internal/shared/http"
"tyapi-server/internal/shared/middleware"
"go.uber.org/zap"
)
// StatisticsRoutes 统计路由
type StatisticsRoutes struct {
statisticsHandler *handlers.StatisticsHandler
auth *middleware.JWTAuthMiddleware
optionalAuth *middleware.OptionalAuthMiddleware
admin *middleware.AdminAuthMiddleware
logger *zap.Logger
}
// NewStatisticsRoutes 创建统计路由
func NewStatisticsRoutes(
statisticsHandler *handlers.StatisticsHandler,
auth *middleware.JWTAuthMiddleware,
optionalAuth *middleware.OptionalAuthMiddleware,
admin *middleware.AdminAuthMiddleware,
logger *zap.Logger,
) *StatisticsRoutes {
return &StatisticsRoutes{
statisticsHandler: statisticsHandler,
auth: auth,
optionalAuth: optionalAuth,
admin: admin,
logger: logger,
}
}
// Register 注册统计相关路由
func (r *StatisticsRoutes) Register(router *sharedhttp.GinRouter) {
engine := router.GetEngine()
// ================ 用户端统计路由 ================
// 统计公开接口
statistics := engine.Group("/api/v1/statistics")
{
// 获取公开统计信息
statistics.GET("/public", r.statisticsHandler.GetPublicStatistics)
}
// 用户统计接口 - 需要认证
userStats := engine.Group("/api/v1/statistics", r.auth.Handle())
{
// 获取用户统计信息
userStats.GET("/user", r.statisticsHandler.GetUserStatistics)
// 独立统计接口(用户只能查询自己的数据)
userStats.GET("/api-calls", r.statisticsHandler.GetApiCallsStatistics)
userStats.GET("/consumption", r.statisticsHandler.GetConsumptionStatistics)
userStats.GET("/recharge", r.statisticsHandler.GetRechargeStatistics)
// 获取最新产品推荐
userStats.GET("/latest-products", r.statisticsHandler.GetLatestProducts)
// 获取指标列表
userStats.GET("/metrics", r.statisticsHandler.GetMetrics)
// 获取指标详情
userStats.GET("/metrics/:id", r.statisticsHandler.GetMetricDetail)
// 获取仪表板列表
userStats.GET("/dashboards", r.statisticsHandler.GetDashboards)
// 获取仪表板详情
userStats.GET("/dashboards/:id", r.statisticsHandler.GetDashboardDetail)
// 获取仪表板数据
userStats.GET("/dashboards/:id/data", r.statisticsHandler.GetDashboardData)
// 获取报告列表
userStats.GET("/reports", r.statisticsHandler.GetReports)
// 获取报告详情
userStats.GET("/reports/:id", r.statisticsHandler.GetReportDetail)
// 创建报告
userStats.POST("/reports", r.statisticsHandler.CreateReport)
}
// ================ 管理员统计路由 ================
// 管理员路由组
adminGroup := engine.Group("/api/v1/admin")
adminGroup.Use(r.admin.Handle()) // 管理员权限验证
{
// 统计指标管理
metrics := adminGroup.Group("/statistics/metrics")
{
metrics.GET("", r.statisticsHandler.AdminGetMetrics)
metrics.POST("", r.statisticsHandler.AdminCreateMetric)
metrics.PUT("/:id", r.statisticsHandler.AdminUpdateMetric)
metrics.DELETE("/:id", r.statisticsHandler.AdminDeleteMetric)
}
// 仪表板管理
dashboards := adminGroup.Group("/statistics/dashboards")
{
dashboards.GET("", r.statisticsHandler.AdminGetDashboards)
dashboards.POST("", r.statisticsHandler.AdminCreateDashboard)
dashboards.PUT("/:id", r.statisticsHandler.AdminUpdateDashboard)
dashboards.DELETE("/:id", r.statisticsHandler.AdminDeleteDashboard)
}
// 报告管理
reports := adminGroup.Group("/statistics/reports")
{
reports.GET("", r.statisticsHandler.AdminGetReports)
}
// 系统统计
system := adminGroup.Group("/statistics/system")
{
system.GET("", r.statisticsHandler.AdminGetSystemStatistics)
}
// 独立域统计接口
domainStats := adminGroup.Group("/statistics")
{
domainStats.GET("/user-domain", r.statisticsHandler.AdminGetUserDomainStatistics)
domainStats.GET("/api-domain", r.statisticsHandler.AdminGetApiDomainStatistics)
domainStats.GET("/consumption-domain", r.statisticsHandler.AdminGetConsumptionDomainStatistics)
domainStats.GET("/recharge-domain", r.statisticsHandler.AdminGetRechargeDomainStatistics)
}
// 排行榜接口
rankings := adminGroup.Group("/statistics")
{
rankings.GET("/user-call-ranking", r.statisticsHandler.AdminGetUserCallRanking)
rankings.GET("/recharge-ranking", r.statisticsHandler.AdminGetRechargeRanking)
rankings.GET("/api-popularity-ranking", r.statisticsHandler.AdminGetApiPopularityRanking)
rankings.GET("/today-certified-enterprises", r.statisticsHandler.AdminGetTodayCertifiedEnterprises)
}
// 用户统计
userStats := adminGroup.Group("/statistics/users")
{
userStats.GET("/:user_id", r.statisticsHandler.AdminGetUserStatistics)
}
// 独立统计接口(管理员可查询任意用户)
independentStats := adminGroup.Group("/statistics")
{
independentStats.GET("/api-calls", r.statisticsHandler.GetApiCallsStatistics)
independentStats.GET("/consumption", r.statisticsHandler.GetConsumptionStatistics)
independentStats.GET("/recharge", r.statisticsHandler.GetRechargeStatistics)
}
// 数据聚合
aggregation := adminGroup.Group("/statistics/aggregation")
{
aggregation.POST("/trigger", r.statisticsHandler.AdminTriggerAggregation)
}
}
r.logger.Info("统计路由注册完成")
}