This commit is contained in:
@@ -3,6 +3,7 @@ package api
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
"tyapi-server/internal/domains/api/entities"
|
||||
"tyapi-server/internal/domains/api/repositories"
|
||||
@@ -229,6 +230,11 @@ func (r *GormApiCallRepository) CountByUserId(ctx context.Context, userId string
|
||||
return r.CountWhere(ctx, &entities.ApiCall{}, "user_id = ?", userId)
|
||||
}
|
||||
|
||||
// CountByUserIdAndProductId 按用户ID和产品ID统计API调用次数
|
||||
func (r *GormApiCallRepository) CountByUserIdAndProductId(ctx context.Context, userId string, productId string) (int64, error) {
|
||||
return r.CountWhere(ctx, &entities.ApiCall{}, "user_id = ? AND product_id = ?", userId, productId)
|
||||
}
|
||||
|
||||
// CountByUserIdAndDateRange 按用户ID和日期范围统计API调用次数
|
||||
func (r *GormApiCallRepository) CountByUserIdAndDateRange(ctx context.Context, userId string, startDate, endDate time.Time) (int64, error) {
|
||||
return r.CountWhere(ctx, &entities.ApiCall{}, "user_id = ? AND created_at >= ? AND created_at < ?", userId, startDate, endDate)
|
||||
@@ -304,8 +310,29 @@ func (r *GormApiCallRepository) ListWithFiltersAndProductName(ctx context.Contex
|
||||
|
||||
// 应用筛选条件
|
||||
if filters != nil {
|
||||
// 用户ID筛选
|
||||
if userId, ok := filters["user_id"].(string); ok && userId != "" {
|
||||
// 用户ID筛选(支持单个user_id和多个user_ids)
|
||||
// 如果同时存在,优先使用user_ids(批量查询)
|
||||
if userIds, ok := filters["user_ids"].(string); ok && userIds != "" {
|
||||
// 解析逗号分隔的用户ID列表
|
||||
userIdsList := strings.Split(userIds, ",")
|
||||
// 去除空白字符
|
||||
var cleanUserIds []string
|
||||
for _, id := range userIdsList {
|
||||
id = strings.TrimSpace(id)
|
||||
if id != "" {
|
||||
cleanUserIds = append(cleanUserIds, id)
|
||||
}
|
||||
}
|
||||
if len(cleanUserIds) > 0 {
|
||||
placeholders := strings.Repeat("?,", len(cleanUserIds))
|
||||
placeholders = placeholders[:len(placeholders)-1] // 移除最后一个逗号
|
||||
whereCondition += " AND ac.user_id IN (" + placeholders + ")"
|
||||
for _, id := range cleanUserIds {
|
||||
whereArgs = append(whereArgs, id)
|
||||
}
|
||||
}
|
||||
} else if userId, ok := filters["user_id"].(string); ok && userId != "" {
|
||||
// 单个用户ID筛选
|
||||
whereCondition += " AND ac.user_id = ?"
|
||||
whereArgs = append(whereArgs, userId)
|
||||
}
|
||||
|
||||
@@ -89,37 +89,86 @@ func (r *GormRechargeRecordRepository) UpdateStatus(ctx context.Context, id stri
|
||||
|
||||
func (r *GormRechargeRecordRepository) Count(ctx context.Context, options interfaces.CountOptions) (int64, error) {
|
||||
var count int64
|
||||
query := r.GetDB(ctx).Model(&entities.RechargeRecord{})
|
||||
|
||||
// 检查是否有 company_name 筛选,如果有则需要 JOIN 表
|
||||
hasCompanyNameFilter := false
|
||||
if options.Filters != nil {
|
||||
if companyName, ok := options.Filters["company_name"].(string); ok && companyName != "" {
|
||||
hasCompanyNameFilter = true
|
||||
}
|
||||
}
|
||||
|
||||
var query *gorm.DB
|
||||
if hasCompanyNameFilter {
|
||||
// 使用 JOIN 查询以支持企业名称筛选
|
||||
query = r.GetDB(ctx).Table("recharge_records rr").
|
||||
Joins("LEFT JOIN users u ON rr.user_id = u.id").
|
||||
Joins("LEFT JOIN enterprise_infos ei ON u.id = ei.user_id")
|
||||
} else {
|
||||
// 普通查询
|
||||
query = r.GetDB(ctx).Model(&entities.RechargeRecord{})
|
||||
}
|
||||
|
||||
if options.Filters != nil {
|
||||
for key, value := range options.Filters {
|
||||
// 特殊处理时间范围过滤器
|
||||
if key == "start_time" {
|
||||
if startTime, ok := value.(time.Time); ok {
|
||||
query = query.Where("created_at >= ?", startTime)
|
||||
if hasCompanyNameFilter {
|
||||
query = query.Where("rr.created_at >= ?", startTime)
|
||||
} else {
|
||||
query = query.Where("created_at >= ?", startTime)
|
||||
}
|
||||
}
|
||||
} else if key == "end_time" {
|
||||
if endTime, ok := value.(time.Time); ok {
|
||||
query = query.Where("created_at <= ?", endTime)
|
||||
if hasCompanyNameFilter {
|
||||
query = query.Where("rr.created_at <= ?", endTime)
|
||||
} else {
|
||||
query = query.Where("created_at <= ?", endTime)
|
||||
}
|
||||
}
|
||||
} else if key == "company_name" {
|
||||
// 处理企业名称筛选
|
||||
if companyName, ok := value.(string); ok && companyName != "" {
|
||||
query = query.Where("ei.company_name LIKE ?", "%"+companyName+"%")
|
||||
}
|
||||
} else if key == "min_amount" {
|
||||
// 处理最小金额,支持string、int、int64类型
|
||||
if amount, err := r.parseAmount(value); err == nil {
|
||||
query = query.Where("amount >= ?", amount)
|
||||
if hasCompanyNameFilter {
|
||||
query = query.Where("rr.amount >= ?", amount)
|
||||
} else {
|
||||
query = query.Where("amount >= ?", amount)
|
||||
}
|
||||
}
|
||||
} else if key == "max_amount" {
|
||||
// 处理最大金额,支持string、int、int64类型
|
||||
if amount, err := r.parseAmount(value); err == nil {
|
||||
query = query.Where("amount <= ?", amount)
|
||||
if hasCompanyNameFilter {
|
||||
query = query.Where("rr.amount <= ?", amount)
|
||||
} else {
|
||||
query = query.Where("amount <= ?", amount)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 其他过滤器使用等值查询
|
||||
query = query.Where(key+" = ?", value)
|
||||
if hasCompanyNameFilter {
|
||||
query = query.Where("rr."+key+" = ?", value)
|
||||
} else {
|
||||
query = query.Where(key+" = ?", value)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if options.Search != "" {
|
||||
query = query.Where("user_id LIKE ? OR transfer_order_id LIKE ? OR alipay_order_id LIKE ?",
|
||||
"%"+options.Search+"%", "%"+options.Search+"%", "%"+options.Search+"%")
|
||||
if hasCompanyNameFilter {
|
||||
query = query.Where("rr.user_id LIKE ? OR rr.transfer_order_id LIKE ? OR rr.alipay_order_id LIKE ?",
|
||||
"%"+options.Search+"%", "%"+options.Search+"%", "%"+options.Search+"%")
|
||||
} else {
|
||||
query = query.Where("user_id LIKE ? OR transfer_order_id LIKE ? OR alipay_order_id LIKE ?",
|
||||
"%"+options.Search+"%", "%"+options.Search+"%", "%"+options.Search+"%")
|
||||
}
|
||||
}
|
||||
return count, query.Count(&count).Error
|
||||
}
|
||||
@@ -132,45 +181,98 @@ func (r *GormRechargeRecordRepository) Exists(ctx context.Context, id string) (b
|
||||
|
||||
func (r *GormRechargeRecordRepository) List(ctx context.Context, options interfaces.ListOptions) ([]entities.RechargeRecord, error) {
|
||||
var records []entities.RechargeRecord
|
||||
query := r.GetDB(ctx).Model(&entities.RechargeRecord{})
|
||||
|
||||
// 检查是否有 company_name 筛选,如果有则需要 JOIN 表
|
||||
hasCompanyNameFilter := false
|
||||
if options.Filters != nil {
|
||||
if companyName, ok := options.Filters["company_name"].(string); ok && companyName != "" {
|
||||
hasCompanyNameFilter = true
|
||||
}
|
||||
}
|
||||
|
||||
var query *gorm.DB
|
||||
if hasCompanyNameFilter {
|
||||
// 使用 JOIN 查询以支持企业名称筛选
|
||||
query = r.GetDB(ctx).Table("recharge_records rr").
|
||||
Select("rr.*").
|
||||
Joins("LEFT JOIN users u ON rr.user_id = u.id").
|
||||
Joins("LEFT JOIN enterprise_infos ei ON u.id = ei.user_id")
|
||||
} else {
|
||||
// 普通查询
|
||||
query = r.GetDB(ctx).Model(&entities.RechargeRecord{})
|
||||
}
|
||||
|
||||
if options.Filters != nil {
|
||||
for key, value := range options.Filters {
|
||||
// 特殊处理 user_ids 过滤器
|
||||
if key == "user_ids" {
|
||||
if userIds, ok := value.(string); ok && userIds != "" {
|
||||
query = query.Where("user_id IN ?", strings.Split(userIds, ","))
|
||||
if hasCompanyNameFilter {
|
||||
query = query.Where("rr.user_id IN ?", strings.Split(userIds, ","))
|
||||
} else {
|
||||
query = query.Where("user_id IN ?", strings.Split(userIds, ","))
|
||||
}
|
||||
}
|
||||
} else if key == "company_name" {
|
||||
// 处理企业名称筛选
|
||||
if companyName, ok := value.(string); ok && companyName != "" {
|
||||
query = query.Where("ei.company_name LIKE ?", "%"+companyName+"%")
|
||||
}
|
||||
} else if key == "start_time" {
|
||||
// 处理开始时间范围
|
||||
if startTime, ok := value.(time.Time); ok {
|
||||
query = query.Where("created_at >= ?", startTime)
|
||||
if hasCompanyNameFilter {
|
||||
query = query.Where("rr.created_at >= ?", startTime)
|
||||
} else {
|
||||
query = query.Where("created_at >= ?", startTime)
|
||||
}
|
||||
}
|
||||
} else if key == "end_time" {
|
||||
// 处理结束时间范围
|
||||
if endTime, ok := value.(time.Time); ok {
|
||||
query = query.Where("created_at <= ?", endTime)
|
||||
if hasCompanyNameFilter {
|
||||
query = query.Where("rr.created_at <= ?", endTime)
|
||||
} else {
|
||||
query = query.Where("created_at <= ?", endTime)
|
||||
}
|
||||
}
|
||||
} else if key == "min_amount" {
|
||||
// 处理最小金额,支持string、int、int64类型
|
||||
if amount, err := r.parseAmount(value); err == nil {
|
||||
query = query.Where("amount >= ?", amount)
|
||||
if hasCompanyNameFilter {
|
||||
query = query.Where("rr.amount >= ?", amount)
|
||||
} else {
|
||||
query = query.Where("amount >= ?", amount)
|
||||
}
|
||||
}
|
||||
} else if key == "max_amount" {
|
||||
// 处理最大金额,支持string、int、int64类型
|
||||
if amount, err := r.parseAmount(value); err == nil {
|
||||
query = query.Where("amount <= ?", amount)
|
||||
if hasCompanyNameFilter {
|
||||
query = query.Where("rr.amount <= ?", amount)
|
||||
} else {
|
||||
query = query.Where("amount <= ?", amount)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 其他过滤器使用等值查询
|
||||
query = query.Where(key+" = ?", value)
|
||||
if hasCompanyNameFilter {
|
||||
query = query.Where("rr."+key+" = ?", value)
|
||||
} else {
|
||||
query = query.Where(key+" = ?", value)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if options.Search != "" {
|
||||
query = query.Where("user_id LIKE ? OR transfer_order_id LIKE ? OR alipay_order_id LIKE ?",
|
||||
"%"+options.Search+"%", "%"+options.Search+"%", "%"+options.Search+"%")
|
||||
if hasCompanyNameFilter {
|
||||
query = query.Where("rr.user_id LIKE ? OR rr.transfer_order_id LIKE ? OR rr.alipay_order_id LIKE ?",
|
||||
"%"+options.Search+"%", "%"+options.Search+"%", "%"+options.Search+"%")
|
||||
} else {
|
||||
query = query.Where("user_id LIKE ? OR transfer_order_id LIKE ? OR alipay_order_id LIKE ?",
|
||||
"%"+options.Search+"%", "%"+options.Search+"%", "%"+options.Search+"%")
|
||||
}
|
||||
}
|
||||
|
||||
if options.Sort != "" {
|
||||
@@ -178,9 +280,17 @@ func (r *GormRechargeRecordRepository) List(ctx context.Context, options interfa
|
||||
if options.Order == "desc" || options.Order == "DESC" {
|
||||
order = "DESC"
|
||||
}
|
||||
query = query.Order(options.Sort + " " + order)
|
||||
if hasCompanyNameFilter {
|
||||
query = query.Order("rr." + options.Sort + " " + order)
|
||||
} else {
|
||||
query = query.Order(options.Sort + " " + order)
|
||||
}
|
||||
} else {
|
||||
query = query.Order("created_at DESC")
|
||||
if hasCompanyNameFilter {
|
||||
query = query.Order("rr.created_at DESC")
|
||||
} else {
|
||||
query = query.Order("created_at DESC")
|
||||
}
|
||||
}
|
||||
|
||||
if options.Page > 0 && options.PageSize > 0 {
|
||||
|
||||
@@ -382,12 +382,26 @@ func (r *GormWalletTransactionRepository) ListWithFiltersAndProductName(ctx cont
|
||||
|
||||
// 应用筛选条件
|
||||
if filters != nil {
|
||||
// 用户ID筛选
|
||||
if userId, ok := filters["user_id"].(string); ok && userId != "" {
|
||||
// 用户ID筛选(支持单个和多个)
|
||||
if userIds, ok := filters["user_ids"].(string); ok && userIds != "" {
|
||||
// 多个用户ID,逗号分隔
|
||||
userIdsList := strings.Split(userIds, ",")
|
||||
whereCondition += " AND wt.user_id IN ?"
|
||||
whereArgs = append(whereArgs, userIdsList)
|
||||
} else if userId, ok := filters["user_id"].(string); ok && userId != "" {
|
||||
// 单个用户ID
|
||||
whereCondition += " AND wt.user_id = ?"
|
||||
whereArgs = append(whereArgs, userId)
|
||||
}
|
||||
|
||||
// 产品ID筛选(支持多个)
|
||||
if productIds, ok := filters["product_ids"].(string); ok && productIds != "" {
|
||||
// 多个产品ID,逗号分隔
|
||||
productIdsList := strings.Split(productIds, ",")
|
||||
whereCondition += " AND wt.product_id IN ?"
|
||||
whereArgs = append(whereArgs, productIdsList)
|
||||
}
|
||||
|
||||
// 时间范围筛选
|
||||
if startTime, ok := filters["start_time"].(time.Time); ok {
|
||||
whereCondition += " AND wt.created_at >= ?"
|
||||
|
||||
@@ -34,7 +34,7 @@ type ZhichaResp struct {
|
||||
type ZhichaConfig struct {
|
||||
URL string
|
||||
AppID string
|
||||
AppSecret string
|
||||
AppSecret string
|
||||
EncryptKey string
|
||||
}
|
||||
|
||||
@@ -133,14 +133,13 @@ func (z *ZhichaService) CallAPI(ctx context.Context, proID string, params map[st
|
||||
} else if netErr, ok := err.(interface{ Timeout() bool }); ok && netErr.Timeout() {
|
||||
// 检查是否是网络超时错误
|
||||
isTimeout = true
|
||||
} else if errStr := err.Error();
|
||||
errStr == "context deadline exceeded" ||
|
||||
errStr == "timeout" ||
|
||||
errStr == "Client.Timeout exceeded" ||
|
||||
errStr == "net/http: request canceled" {
|
||||
} else if errStr := err.Error(); errStr == "context deadline exceeded" ||
|
||||
errStr == "timeout" ||
|
||||
errStr == "Client.Timeout exceeded" ||
|
||||
errStr == "net/http: request canceled" {
|
||||
isTimeout = true
|
||||
}
|
||||
|
||||
|
||||
if isTimeout {
|
||||
// 超时错误应该返回数据源异常,而不是系统异常
|
||||
err = errors.Join(ErrDatasource, fmt.Errorf("API请求超时: %v", err))
|
||||
|
||||
@@ -2,6 +2,7 @@ package handlers
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
"tyapi-server/internal/application/api"
|
||||
"tyapi-server/internal/application/finance"
|
||||
@@ -1237,13 +1238,27 @@ func (h *ProductAdminHandler) ExportAdminWalletTransactions(c *gin.Context) {
|
||||
|
||||
// 时间范围筛选
|
||||
if startTime := c.Query("start_time"); startTime != "" {
|
||||
// 处理URL编码的+号,转换为空格
|
||||
startTime = strings.ReplaceAll(startTime, "+", " ")
|
||||
if t, err := time.Parse("2006-01-02 15:04:05", startTime); err == nil {
|
||||
filters["start_time"] = t
|
||||
} else {
|
||||
// 尝试其他格式
|
||||
if t, err := time.Parse("2006-01-02T15:04:05", startTime); err == nil {
|
||||
filters["start_time"] = t
|
||||
}
|
||||
}
|
||||
}
|
||||
if endTime := c.Query("end_time"); endTime != "" {
|
||||
// 处理URL编码的+号,转换为空格
|
||||
endTime = strings.ReplaceAll(endTime, "+", " ")
|
||||
if t, err := time.Parse("2006-01-02 15:04:05", endTime); err == nil {
|
||||
filters["end_time"] = t
|
||||
} else {
|
||||
// 尝试其他格式
|
||||
if t, err := time.Parse("2006-01-02T15:04:05", endTime); err == nil {
|
||||
filters["end_time"] = t
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1262,6 +1277,11 @@ func (h *ProductAdminHandler) ExportAdminWalletTransactions(c *gin.Context) {
|
||||
filters["product_ids"] = productIds
|
||||
}
|
||||
|
||||
// 企业名称筛选
|
||||
if companyName := c.Query("company_name"); companyName != "" {
|
||||
filters["company_name"] = companyName
|
||||
}
|
||||
|
||||
// 金额范围筛选
|
||||
if minAmount := c.Query("min_amount"); minAmount != "" {
|
||||
filters["min_amount"] = minAmount
|
||||
@@ -1281,7 +1301,16 @@ func (h *ProductAdminHandler) ExportAdminWalletTransactions(c *gin.Context) {
|
||||
fileData, err := h.financeAppService.ExportAdminWalletTransactions(c.Request.Context(), filters, format)
|
||||
if err != nil {
|
||||
h.logger.Error("导出消费记录失败", zap.Error(err))
|
||||
h.responseBuilder.BadRequest(c, "导出消费记录失败")
|
||||
|
||||
// 根据错误信息返回具体的提示
|
||||
errMsg := err.Error()
|
||||
if strings.Contains(errMsg, "没有找到符合条件的数据") || strings.Contains(errMsg, "没有数据") {
|
||||
h.responseBuilder.NotFound(c, "没有找到符合筛选条件的数据,请调整筛选条件后重试")
|
||||
} else if strings.Contains(errMsg, "参数") || strings.Contains(errMsg, "参数错误") {
|
||||
h.responseBuilder.BadRequest(c, errMsg)
|
||||
} else {
|
||||
h.responseBuilder.BadRequest(c, "导出消费记录失败:"+errMsg)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1364,6 +1393,11 @@ func (h *ProductAdminHandler) GetAdminRechargeRecords(c *gin.Context) {
|
||||
filters["max_amount"] = maxAmount
|
||||
}
|
||||
|
||||
// 企业名称筛选
|
||||
if companyName := c.Query("company_name"); companyName != "" {
|
||||
filters["company_name"] = companyName
|
||||
}
|
||||
|
||||
// 构建分页选项
|
||||
options := interfaces.ListOptions{
|
||||
Page: page,
|
||||
@@ -1442,7 +1476,16 @@ func (h *ProductAdminHandler) ExportAdminRechargeRecords(c *gin.Context) {
|
||||
fileData, err := h.financeAppService.ExportAdminRechargeRecords(c.Request.Context(), filters, format)
|
||||
if err != nil {
|
||||
h.logger.Error("导出充值记录失败", zap.Error(err))
|
||||
h.responseBuilder.BadRequest(c, "导出充值记录失败")
|
||||
|
||||
// 根据错误信息返回具体的提示
|
||||
errMsg := err.Error()
|
||||
if strings.Contains(errMsg, "没有找到符合条件的数据") || strings.Contains(errMsg, "没有数据") {
|
||||
h.responseBuilder.NotFound(c, "没有找到符合筛选条件的充值记录,请调整筛选条件后重试")
|
||||
} else if strings.Contains(errMsg, "参数") || strings.Contains(errMsg, "参数错误") {
|
||||
h.responseBuilder.BadRequest(c, errMsg)
|
||||
} else {
|
||||
h.responseBuilder.BadRequest(c, "导出充值记录失败:"+errMsg)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1468,7 +1511,10 @@ func (h *ProductAdminHandler) GetAdminApiCalls(c *gin.Context) {
|
||||
// 构建筛选条件
|
||||
filters := make(map[string]interface{})
|
||||
|
||||
// 用户ID筛选
|
||||
// 用户ID筛选(支持单个user_id和多个user_ids,根据需求使用)
|
||||
if userId := c.Query("user_id"); userId != "" {
|
||||
filters["user_id"] = userId
|
||||
}
|
||||
if userIds := c.Query("user_ids"); userIds != "" {
|
||||
filters["user_ids"] = userIds
|
||||
}
|
||||
@@ -1566,7 +1612,16 @@ func (h *ProductAdminHandler) ExportAdminApiCalls(c *gin.Context) {
|
||||
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调用记录失败")
|
||||
|
||||
// 根据错误信息返回具体的提示
|
||||
errMsg := err.Error()
|
||||
if strings.Contains(errMsg, "没有找到符合条件的数据") || strings.Contains(errMsg, "没有数据") {
|
||||
h.responseBuilder.NotFound(c, "没有找到符合筛选条件的API调用记录,请调整筛选条件后重试")
|
||||
} else if strings.Contains(errMsg, "参数") || strings.Contains(errMsg, "参数错误") {
|
||||
h.responseBuilder.BadRequest(c, errMsg)
|
||||
} else {
|
||||
h.responseBuilder.BadRequest(c, "导出API调用记录失败:"+errMsg)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user