This commit is contained in:
Mrx
2026-05-27 13:00:51 +08:00
parent b7fb2a73c9
commit 5cee8ff035
15 changed files with 569 additions and 146 deletions

View File

@@ -3,6 +3,8 @@ package repositories
import (
"context"
"errors"
"strings"
"tyapi-server/internal/domains/product/entities"
"tyapi-server/internal/domains/product/repositories"
"tyapi-server/internal/domains/product/repositories/queries"
@@ -165,13 +167,33 @@ func (r *GormProductRepository) ListProducts(ctx context.Context, query *queries
// 应用排序
if query.SortBy != "" {
order := query.SortBy
if query.SortOrder == "desc" {
order += " DESC"
// 检查是否是关联表字段排序
if strings.Contains(query.SortBy, ".") {
parts := strings.Split(query.SortBy, ".")
if len(parts) == 2 {
// 关联表字段排序需要JOIN表
joinTable := parts[0]
sortField := parts[1]
dbQuery = dbQuery.Joins("JOIN "+joinTable+" ON products.category_id = "+joinTable+".id")
order := joinTable + "." + sortField
if query.SortOrder == "desc" {
order += " DESC"
} else {
order += " ASC"
}
dbQuery = dbQuery.Order(order)
}
} else {
order += " ASC"
// 本表字段排序
order := query.SortBy
if query.SortOrder == "desc" {
order += " DESC"
} else {
order += " ASC"
}
dbQuery = dbQuery.Order(order)
}
dbQuery = dbQuery.Order(order)
} else {
dbQuery = dbQuery.Order("created_at DESC")
}

View File

@@ -1659,3 +1659,54 @@ func (h *ProductAdminHandler) ExportAdminApiCalls(c *gin.Context) {
c.Header("Content-Disposition", "attachment; filename="+filename)
c.Data(200, contentType, fileData)
}
// ExportProductDictionary 导出产品字典
// @Summary 导出产品字典
// @Description 导出所有启用且可见的产品字典,按分类分组,左侧分类列合并单元格
// @Tags 产品管理
// @Accept json
// @Produce application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,text/csv
// @Security Bearer
// @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/products/export-dictionary [get]
func (h *ProductAdminHandler) ExportProductDictionary(c *gin.Context) {
// 获取导出格式默认为excel
format := c.DefaultQuery("format", "excel")
if format != "excel" && format != "csv" {
h.responseBuilder.BadRequest(c, "不支持的导出格式")
return
}
// 调用应用服务导出数据
fileData, err := h.productAppService.ExportProductDictionary(c.Request.Context(), format)
if err != nil {
h.logger.Error("导出产品字典失败", zap.Error(err))
// 根据错误信息返回具体的提示
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
}
// 设置响应头
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)
}

View File

@@ -60,6 +60,9 @@ func (r *ProductAdminRoutes) Register(router *sharedhttp.GinRouter) {
products.GET("/:id/documentation", r.handler.GetProductDocumentation)
products.POST("/:id/documentation", r.handler.CreateOrUpdateProductDocumentation)
products.DELETE("/:id/documentation", r.handler.DeleteProductDocumentation)
// 产品字典导出
products.GET("/export-dictionary", r.handler.ExportProductDictionary)
}
// 分类管理