package routes import ( "encoding/json" "fmt" "log" "net/http" "os" "runtime" "strconv" "strings" "time" "xianyv/controller" _type "xianyv/type" "xianyv/utils/requestUtil" ) // 简单的全局令牌桶限速器(本地测试用,QPS = 10) const qpsLimit = 10 var tokenBucket chan struct{} func init() { tokenBucket = make(chan struct{}, qpsLimit) // 预先填充令牌 for i := 0; i < qpsLimit; i++ { tokenBucket <- struct{}{} } // 以 QPS 速率补充令牌 go func() { ticker := time.NewTicker(time.Second / time.Duration(qpsLimit)) defer ticker.Stop() for range ticker.C { select { case tokenBucket <- struct{}{}: default: // bucket 已满,跳过 } } }() } type routeHandler struct { cfg *_type.Config } // RegisterRoutes 注册所有路由 func RegisterRoutes(cfg *_type.Config) *http.ServeMux { r := http.NewServeMux() handler := &routeHandler{cfg: cfg} // 注册健康检查路由 r.HandleFunc("GET /health", healthHandler) // 请求类目Id处理器,留作备用 r.HandleFunc("POST /xianyv/getCategoryList", handler.getCategoryListHandler) // 发布处理器 r.HandleFunc("POST /xianyv/creatGoodsBatch", handler.creatGoodsBatchHandler) // 上架处理器 r.HandleFunc("POST /xianyv/publish", publishHandler) // 下架处理器 r.HandleFunc("POST /xianyv/downShelf", downShelfHandler) // 擦亮商品处理器 r.HandleFunc("POST /xianyv/flash", flashHandler) // 改价处理器 r.HandleFunc("POST /xianyv/editPrices", editPricesHandler) // 改库存处理器 r.HandleFunc("POST /xianyv/editStock", editStockHandler) // 查商品处理器 r.HandleFunc("POST /xianyv/getGoodsList", getGoodsListHandler) // 新增:跨页统计 outer_id 的处理器,返回完整统计信息 r.HandleFunc("POST /xianyv/getGoodsListAllStats", getGoodsListAllStatsHandler) // 查店铺处理器 r.HandleFunc("POST /xianyv/getShopList", getShopListHandler) // 查询订单列表处理器 r.HandleFunc("POST /xianyv/getOrderList", getOrderListHandler) // 发布其他类测试(实际不使用) r.HandleFunc("POST /xianyv/onlineTest", handler.onlineTestHandler) // 获取商品详情处理器 r.HandleFunc("POST /xianyv/getGoodsDetail", getGoodsDetailHandler) // 注册默认路由(处理未找到的路由) r.HandleFunc("/", notFoundHandler) return r } // 健康检查处理器 func healthHandler(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") response := map[string]interface{}{ "status": "ok", "timestamp": time.Now().Format(time.RFC3339), "goroutines": runtime.NumGoroutine(), "message": "服务运行正常", } w.WriteHeader(http.StatusOK) if err := json.NewEncoder(w).Encode(response); err != nil { log.Printf("错误的编码响应: %v", err) errorMsg := fmt.Sprintf(`{"error": "错误的编码响应: %v"}`, err) http.Error(w, errorMsg, http.StatusInternalServerError) return } } // 发布处理器 func (h *routeHandler) creatGoodsBatchHandler(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") var body _type.Body // 请求参数处理(计时) paramsStart := time.Now() body, err := requestUtil.RequestParams(r) if err != nil { log.Printf("请求参数处理失败: %v (elapsed=%v)", err, time.Since(paramsStart)) errMsg := fmt.Sprintf(`{"error": "请求参数处理失败: %v"}`, err) http.Error(w, errMsg, http.StatusBadRequest) return } log.Printf("请求参数解析完成 (elapsed=%v)", time.Since(paramsStart)) // 类目处理 goodsController := &controller.GoodsController{ ExcelPath: h.cfg.File.ExcelPath, TxtPath: h.cfg.File.TxtPath, SheetName: h.cfg.File.SheetName, } // 调用业务逻辑(计时) handlerStart := time.Now() createResponse, err := goodsController.GoodsCreatController( body, h.cfg.BatchCreatRequest.Path, h.cfg.App.Domain, false, ) log.Printf("GoodsCreatController 完成 (elapsed=%v)", time.Since(handlerStart)) if err != nil { errorMsg := fmt.Sprintf(`{"error": "请求解析或验证失败: %v"}`, err) http.Error(w, errorMsg, http.StatusBadRequest) return } // 返回Response结果 w.WriteHeader(http.StatusOK) if err = json.NewEncoder(w).Encode(json.RawMessage(createResponse)); err != nil { log.Printf("Failed to encode response: %v", err) errorMsg := fmt.Sprintf(`{"error": "无法对响应进行编码: %v"}`, err) http.Error(w, errorMsg, http.StatusInternalServerError) return } } // 上架处理器 func publishHandler(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") var body _type.ListedProducts body.SpecifyPublishTime = r.FormValue("specify_publish_time") body.NotifyUrl = r.FormValue("notify_url") appIdStr := r.FormValue("appId") body.AppSecret = r.FormValue("appSecret") body.AppId, _ = strconv.Atoi(appIdStr) fmt.Printf("appId: %d", body.AppId) body.NotifyUrl = "http://146.56.192.164:19095/huidiao/goofish/goofishGoods" // 从绝对路径读取txt文件 filePath := "D:/workSpace/batchWorkSpace/josn/product_ids.txt" // 请替换为实际的绝对路径 content, err := os.ReadFile(filePath) if err != nil { log.Printf("读取文件失败: %v", err) errorMsg := fmt.Sprintf(`{"error": "读取文件失败: %v"}`, err) http.Error(w, errorMsg, http.StatusInternalServerError) return } // 按行分割文件内容 lines := strings.Split(strings.TrimSpace(string(content)), "\n") if len(lines) == 0 { errorMsg := `{"error": "文件为空"}` http.Error(w, errorMsg, http.StatusBadRequest) return } // 首先解析表单(只需要解析一次) if err := r.ParseForm(); err != nil { http.Error(w, "Failed to parse form", http.StatusBadRequest) return } var responses []string var hasError bool const qps = 9 const interval = time.Second / time.Duration(qps) // 100ms // 循环处理每个productId for i, line := range lines { line = strings.TrimSpace(line) if line == "" { continue // 跳过空行 } // 添加延时(从第二个请求开始) if i > 0 { time.Sleep(interval) } productIdStr := line body.ProductId, _ = strconv.Atoi(productIdStr) // 获取 user_name 数组 body.UserName = r.Form["user_name[]"] log.Printf("上架测试:%v", body) response, err := controller.Publish(body) if err != nil { log.Printf("上架商品失败 (productId: %s): %v", productIdStr, err) errorResponse := fmt.Sprintf(`{"productId": "%s", "error": "上架商品失败: %v"}`, productIdStr, err) responses = append(responses, errorResponse) hasError = true continue } successResponse := fmt.Sprintf(`{"productId": "%s", "response": %s}`, productIdStr, string(response)) fmt.Printf("successResponse: %v\n", successResponse) } // 构建最终响应 if hasError { w.WriteHeader(http.StatusMultiStatus) // 207 Multi-Status } else { w.WriteHeader(http.StatusOK) } } // 下架处理器 func downShelfHandler(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") var body _type.DownAndFlash productIdStr := r.FormValue("productId") appIdStr := r.FormValue("appId") body.AppSecret = r.FormValue("appSecret") if i, err := strconv.ParseInt(productIdStr, 10, 64); err == nil { body.ProductId = int64(i) } else { body.ProductId = 0 } body.AppId, _ = strconv.Atoi(appIdStr) response, err := controller.DownShelf(body) if err != nil { log.Printf("下架商品失败: %v", err) errorMsg := fmt.Sprintf(`{"error": "下架商品失败: %v"}`, err) http.Error(w, errorMsg, http.StatusInternalServerError) return } w.WriteHeader(http.StatusOK) if err = json.NewEncoder(w).Encode(json.RawMessage(response)); err != nil { log.Printf("Failed to encode response: %v", err) errorMsg := fmt.Sprintf(`{"error": "无法对响应进行编码: %v"}`, err) http.Error(w, errorMsg, http.StatusInternalServerError) return } } // 擦亮商品处理器 func flashHandler(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") var body _type.DownAndFlash productIdStr := r.FormValue("productId") appIdStr := r.FormValue("appId") body.AppSecret = r.FormValue("appSecret") if i, err := strconv.ParseInt(productIdStr, 10, 64); err == nil { body.ProductId = int64(i) } else { body.ProductId = 0 } body.AppId, _ = strconv.Atoi(appIdStr) response, err := controller.Flash(body) if err != nil { log.Printf("擦亮商品失败: %v", err) errorMsg := fmt.Sprintf(`{"error": "擦亮商品失败: %v"}`, err) http.Error(w, errorMsg, http.StatusInternalServerError) return } w.WriteHeader(http.StatusOK) if err = json.NewEncoder(w).Encode(json.RawMessage(response)); err != nil { log.Printf("Failed to encode response: %v", err) errorMsg := fmt.Sprintf(`{"error": "无法对响应进行编码: %v"}`, err) http.Error(w, errorMsg, http.StatusInternalServerError) return } } // 改价处理器 func editPricesHandler(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") var edit _type.EditPrices productIdStr := r.FormValue("productId") pricesStr := r.FormValue("price") originalPriceStr := r.FormValue("originalPrice") appIdStr := r.FormValue("appId") edit.AppSecret = r.FormValue("appSecret") if i, err := strconv.ParseInt(productIdStr, 10, 64); err == nil { edit.ProductId = int64(i) } else { edit.ProductId = 0 } if i, err := strconv.ParseInt(pricesStr, 10, 64); err == nil { edit.Price = int64(i) } else { edit.Price = 0 } if i, err := strconv.ParseInt(originalPriceStr, 10, 64); err == nil { edit.OriginalPrice = int64(i) } else { edit.OriginalPrice = 0 } edit.AppId, _ = strconv.Atoi(appIdStr) fmt.Printf("修改价格参数:%v", edit) response, err := controller.EditPrices(edit) if err != nil { log.Printf("修改价格失败: %v", err) errorMsg := fmt.Sprintf(`{"error": "修改价格失败: %v"}`, err) http.Error(w, errorMsg, http.StatusInternalServerError) return } w.WriteHeader(http.StatusOK) if err = json.NewEncoder(w).Encode(json.RawMessage(response)); err != nil { log.Printf("Failed to encode response: %v", err) errorMsg := fmt.Sprintf(`{"error": "无法对响应进行编码: %v"}`, err) http.Error(w, errorMsg, http.StatusInternalServerError) return } } // 修改库存处理器 func editStockHandler(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") var edit _type.EditStock productIdStr := r.FormValue("productId") stockStr := r.FormValue("stock") appIdStr := r.FormValue("appId") edit.AppSecret = r.FormValue("appSecret") if i, err := strconv.ParseInt(productIdStr, 10, 64); err == nil { edit.ProductId = int64(i) } else { edit.ProductId = 0 } if i, err := strconv.ParseInt(stockStr, 10, 32); err == nil { edit.Stock = int32(i) } else { edit.Stock = 0 } edit.AppId, _ = strconv.Atoi(appIdStr) fmt.Printf("修改库存参数:%v", edit) response, err := controller.EditStock(edit) if err != nil { log.Printf("修改库存失败: %v", err) errorMsg := fmt.Sprintf(`{"error": "修改库存失败: %v"}`, err) http.Error(w, errorMsg, http.StatusInternalServerError) return } w.WriteHeader(http.StatusOK) if err = json.NewEncoder(w).Encode(json.RawMessage(response)); err != nil { log.Printf("Failed to encode response: %v", err) errorMsg := fmt.Sprintf(`{"error": "无法对响应进行编码: %v"}`, err) http.Error(w, errorMsg, http.StatusInternalServerError) return } } // 获取商品列表处理器 func getGoodsListHandler(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") // 检查是否有online_time字段 onlineTimeStr := r.FormValue("online_time") var response []byte var err error if onlineTimeStr != "" { var selectGoodsList _type.SelectGoodsListWithTime timeStrs := strings.Split(onlineTimeStr, ",") var onlineTime []int64 for _, timeStr := range timeStrs { if t, err := strconv.ParseInt(strings.TrimSpace(timeStr), 10, 64); err == nil { onlineTime = append(onlineTime, t) } } selectGoodsList.OfflineTime = onlineTime productStatusStr := r.FormValue("productStatus") appIdStr := r.FormValue("appId") selectGoodsList.AppSecret = r.FormValue("appSecret") pageNoStr := r.FormValue("pageNo") pageSizeStr := r.FormValue("pageSize") if i, err := strconv.ParseInt(productStatusStr, 10, 32); err == nil { selectGoodsList.ProductStatus = int32(i) } if i, err := strconv.Atoi(appIdStr); err == nil { selectGoodsList.AppId = i } if i, err := strconv.ParseInt(pageNoStr, 10, 32); err == nil { selectGoodsList.PageNo = int32(i) } if i, err := strconv.ParseInt(pageSizeStr, 10, 32); err == nil { selectGoodsList.PageSize = int32(i) } response, err = controller.SelectGoodsListWithTime(selectGoodsList) } else { var selectGoodsList _type.SelectGoodsListWithoutTime productStatusStr := r.FormValue("productStatus") appIdStr := r.FormValue("appId") selectGoodsList.AppSecret = r.FormValue("appSecret") pageNoStr := r.FormValue("pageNo") pageSizeStr := r.FormValue("pageSize") if i, err := strconv.ParseInt(productStatusStr, 10, 32); err == nil { selectGoodsList.ProductStatus = int32(i) } if i, err := strconv.Atoi(appIdStr); err == nil { selectGoodsList.AppId = i } if i, err := strconv.ParseInt(pageNoStr, 10, 32); err == nil { selectGoodsList.PageNo = int32(i) } if i, err := strconv.ParseInt(pageSizeStr, 10, 32); err == nil { selectGoodsList.PageSize = int32(i) } response, err = controller.SelectGoodsListWithoutTime(selectGoodsList) } if err != nil { log.Printf("查询商品失败: %v", err) errorMsg := fmt.Sprintf(`{"error": "查询商品失败: %v"}`, err) http.Error(w, errorMsg, http.StatusInternalServerError) return } // 添加统计功能 responseWithStats, err := addOuterIDStatsToResponse(response) if err != nil { log.Printf("统计outer_id失败,返回原始数据: %v", err) // 统计失败时返回原始数据 responseWithStats = response } else { log.Printf("成功添加outer_id统计信息") } w.WriteHeader(http.StatusOK) if err = json.NewEncoder(w).Encode(json.RawMessage(responseWithStats)); err != nil { log.Printf("Failed to encode response: %v", err) errorMsg := fmt.Sprintf(`{"error": "无法对响应进行编码: %v"}`, err) http.Error(w, errorMsg, http.StatusInternalServerError) return } } // getGoodsListAllStatsHandler - 在 getGoodsList 的基础上做跨页拉取并统计所有页的 outer_id 分布, // 返回原始分页响应并在 data.outer_id_stats 中附加总体统计信息 func getGoodsListAllStatsHandler(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") // 检查是否有online_time字段 onlineTimeStr := r.FormValue("online_time") var response []byte var err error // 通用变量 var initialPageNo int32 = 1 var pageSize int32 = 100 var combinedList []map[string]interface{} if onlineTimeStr != "" { var selectGoodsList _type.SelectGoodsListWithTime timeStrs := strings.Split(onlineTimeStr, ",") var onlineTime []int64 for _, timeStr := range timeStrs { if t, err := strconv.ParseInt(strings.TrimSpace(timeStr), 10, 64); err == nil { onlineTime = append(onlineTime, t) } } selectGoodsList.OfflineTime = onlineTime productStatusStr := r.FormValue("productStatus") appIdStr := r.FormValue("appId") selectGoodsList.AppSecret = r.FormValue("appSecret") pageNoStr := r.FormValue("pageNo") pageSizeStr := r.FormValue("pageSize") if i, err := strconv.ParseInt(productStatusStr, 10, 32); err == nil { selectGoodsList.ProductStatus = int32(i) } if i, err := strconv.Atoi(appIdStr); err == nil { selectGoodsList.AppId = i } if i, err := strconv.ParseInt(pageNoStr, 10, 32); err == nil { selectGoodsList.PageNo = int32(i) } if i, err := strconv.ParseInt(pageSizeStr, 10, 32); err == nil { selectGoodsList.PageSize = int32(i) } initialPageNo = selectGoodsList.PageNo if selectGoodsList.PageSize > 0 { pageSize = selectGoodsList.PageSize } // 第一次请求 response, err = controller.SelectGoodsListWithTime(selectGoodsList) if err != nil { log.Printf("查询商品失败: %v", err) errorMsg := fmt.Sprintf(`{"error": "查询商品失败: %v"}`, err) http.Error(w, errorMsg, http.StatusInternalServerError) return } var resp struct { Code int `json:"code"` Msg string `json:"msg"` Data struct { Count int `json:"count"` List []map[string]interface{} `json:"list"` PageNo int `json:"page_no"` PageSize int `json:"page_size"` } `json:"data"` } if err := json.Unmarshal(response, &resp); err != nil { // 无法解析则返回原始响应 w.WriteHeader(http.StatusOK) if err = json.NewEncoder(w).Encode(json.RawMessage(response)); err != nil { log.Printf("Failed to encode response: %v", err) } return } combinedList = append(combinedList, resp.Data.List...) totalCount := resp.Data.Count if resp.Data.PageSize > 0 { pageSize = int32(resp.Data.PageSize) } totalPages := 1 if pageSize > 0 { totalPages = (totalCount + int(pageSize) - 1) / int(pageSize) } for p := 1; p <= totalPages; p++ { if int32(p) == initialPageNo { continue } selectGoodsList.PageNo = int32(p) pageResp, pageErr := controller.SelectGoodsListWithTime(selectGoodsList) if pageErr != nil { log.Printf("Warning: 获取第 %d 页失败: %v", p, pageErr) continue } var pageParsed struct { Data struct { List []map[string]interface{} `json:"list"` } `json:"data"` } if perr := json.Unmarshal(pageResp, &pageParsed); perr != nil { log.Printf("Warning: 解析第 %d 页响应失败: %v", p, perr) continue } combinedList = append(combinedList, pageParsed.Data.List...) } // 构造最终响应:在原始 response 的 data 中注入 outer_id_stats finalRespMap := make(map[string]interface{}) if err := json.Unmarshal(response, &finalRespMap); err != nil { w.WriteHeader(http.StatusOK) if err = json.NewEncoder(w).Encode(json.RawMessage(response)); err != nil { log.Printf("Failed to encode response: %v", err) } return } // 计算统计 outerCount := make(map[string]int) for _, item := range combinedList { if v, ok := item["outer_id"].(string); ok { if v == "" { outerCount["(空)"]++ } else { outerCount[v]++ } } } stats := map[string]interface{}{ "total_count": len(combinedList), "distribution": outerCount, } if dataMap, ok := finalRespMap["data"].(map[string]interface{}); ok { dataMap["outer_id_stats"] = stats finalRespMap["data"] = dataMap } bts, merr := json.Marshal(finalRespMap) if merr != nil { w.WriteHeader(http.StatusOK) if err = json.NewEncoder(w).Encode(json.RawMessage(response)); err != nil { log.Printf("Failed to encode response: %v", err) } return } w.WriteHeader(http.StatusOK) if err = json.NewEncoder(w).Encode(json.RawMessage(bts)); err != nil { log.Printf("Failed to encode response: %v", err) errorMsg := fmt.Sprintf(`{"error": "无法对响应进行编码: %v"}`, err) http.Error(w, errorMsg, http.StatusInternalServerError) return } return } else { // 无 time 字段的情况 var selectGoodsList _type.SelectGoodsListWithoutTime productStatusStr := r.FormValue("productStatus") appIdStr := r.FormValue("appId") selectGoodsList.AppSecret = r.FormValue("appSecret") pageNoStr := r.FormValue("pageNo") pageSizeStr := r.FormValue("pageSize") if i, err := strconv.ParseInt(productStatusStr, 10, 32); err == nil { selectGoodsList.ProductStatus = int32(i) } if i, err := strconv.Atoi(appIdStr); err == nil { selectGoodsList.AppId = i } if i, err := strconv.ParseInt(pageNoStr, 10, 32); err == nil { selectGoodsList.PageNo = int32(i) } if i, err := strconv.ParseInt(pageSizeStr, 10, 32); err == nil { selectGoodsList.PageSize = int32(i) } initialPageNo = selectGoodsList.PageNo if selectGoodsList.PageSize > 0 { pageSize = selectGoodsList.PageSize } response, err = controller.SelectGoodsListWithoutTime(selectGoodsList) if err != nil { log.Printf("查询商品失败: %v", err) errorMsg := fmt.Sprintf(`{"error": "查询商品失败: %v"}`, err) http.Error(w, errorMsg, http.StatusInternalServerError) return } var resp struct { Code int `json:"code"` Msg string `json:"msg"` Data struct { Count int `json:"count"` List []map[string]interface{} `json:"list"` PageNo int `json:"page_no"` PageSize int `json:"page_size"` } `json:"data"` } if err := json.Unmarshal(response, &resp); err != nil { w.WriteHeader(http.StatusOK) if err = json.NewEncoder(w).Encode(json.RawMessage(response)); err != nil { log.Printf("Failed to encode response: %v", err) } return } combinedList = append(combinedList, resp.Data.List...) totalCount := resp.Data.Count if resp.Data.PageSize > 0 { pageSize = int32(resp.Data.PageSize) } totalPages := 1 if pageSize > 0 { totalPages = (totalCount + int(pageSize) - 1) / int(pageSize) } for p := 1; p <= totalPages; p++ { if int32(p) == initialPageNo { continue } selectGoodsList.PageNo = int32(p) pageResp, pageErr := controller.SelectGoodsListWithoutTime(selectGoodsList) if pageErr != nil { log.Printf("Warning: 获取第 %d 页失败: %v", p, pageErr) continue } var pageParsed struct { Data struct { List []map[string]interface{} `json:"list"` } `json:"data"` } if perr := json.Unmarshal(pageResp, &pageParsed); perr != nil { log.Printf("Warning: 解析第 %d 页响应失败: %v", p, perr) continue } combinedList = append(combinedList, pageParsed.Data.List...) } finalRespMap := make(map[string]interface{}) if err := json.Unmarshal(response, &finalRespMap); err != nil { w.WriteHeader(http.StatusOK) if err = json.NewEncoder(w).Encode(json.RawMessage(response)); err != nil { log.Printf("Failed to encode response: %v", err) } return } outerCount := make(map[string]int) for _, item := range combinedList { if v, ok := item["outer_id"].(string); ok { if v == "" { outerCount["(空)"]++ } else { outerCount[v]++ } } } stats := map[string]interface{}{ "total_count": len(combinedList), "distribution": outerCount, } if dataMap, ok := finalRespMap["data"].(map[string]interface{}); ok { dataMap["outer_id_stats"] = stats finalRespMap["data"] = dataMap } bts, merr := json.Marshal(finalRespMap) if merr != nil { w.WriteHeader(http.StatusOK) if err = json.NewEncoder(w).Encode(json.RawMessage(response)); err != nil { log.Printf("Failed to encode response: %v", err) } return } w.WriteHeader(http.StatusOK) if err = json.NewEncoder(w).Encode(json.RawMessage(bts)); err != nil { log.Printf("Failed to encode response: %v", err) errorMsg := fmt.Sprintf(`{"error": "无法对响应进行编码: %v"}`, err) http.Error(w, errorMsg, http.StatusInternalServerError) return } return } } // 获取店铺列表处理器 func getShopListHandler(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") var body _type.GetShopList appIdStr := r.FormValue("appId") body.AppSecret = r.FormValue("appSecret") body.AppId, _ = strconv.Atoi(appIdStr) response, err := controller.GetShopList(body) if err != nil { log.Printf("获取店铺列表失败: %v", err) errorMsg := fmt.Sprintf(`{"error": "获取店铺列表失败: %v"}`, err) http.Error(w, errorMsg, http.StatusInternalServerError) return } w.WriteHeader(http.StatusOK) if err = json.NewEncoder(w).Encode(json.RawMessage(response)); err != nil { log.Printf("Failed to encode response: %v", err) errorMsg := fmt.Sprintf(`{"error": "无法对响应进行编码: %v"}`, err) http.Error(w, errorMsg, http.StatusInternalServerError) return } } // 获取订单列表处理器 func getOrderListHandler(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") var body _type.GetShopList appIdStr := r.FormValue("appId") body.AppSecret = r.FormValue("appSecret") body.AppId, _ = strconv.Atoi(appIdStr) response, err := controller.GetOrderList(body) if err != nil { log.Printf("获取店铺列表失败: %v", err) errorMsg := fmt.Sprintf(`{"error": "获取店铺列表失败: %v"}`, err) http.Error(w, errorMsg, http.StatusInternalServerError) return } w.WriteHeader(http.StatusOK) if err = json.NewEncoder(w).Encode(json.RawMessage(response)); err != nil { log.Printf("Failed to encode response: %v", err) errorMsg := fmt.Sprintf(`{"error": "无法对响应进行编码: %v"}`, err) http.Error(w, errorMsg, http.StatusInternalServerError) return } } // 发布处理器 func (h *routeHandler) onlineTestHandler(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") var body _type.Body // 请求参数处理 body, err := requestUtil.RequestParams(r) if err != nil { log.Printf("请求参数处理失败: %v", err) errMsg := fmt.Sprintf(`{"error": "请求参数处理失败: %v"}`, err) http.Error(w, errMsg, http.StatusBadRequest) return } // 类目处理 goodsController := &controller.GoodsController{ ExcelPath: h.cfg.File.ExcelPath, TxtPath: h.cfg.File.TxtPath, SheetName: h.cfg.File.SheetName, } createResponse, err := goodsController.GoodsCreatController( body, h.cfg.BatchCreatRequest.Path, h.cfg.App.Domain, true, ) if err != nil { errorMsg := fmt.Sprintf(`{"error": "请求解析或验证失败: %v"}`, err) http.Error(w, errorMsg, http.StatusBadRequest) return } // 返回Response结果 w.WriteHeader(http.StatusOK) if err = json.NewEncoder(w).Encode(json.RawMessage(createResponse)); err != nil { log.Printf("Failed to encode response: %v", err) errorMsg := fmt.Sprintf(`{"error": "无法对响应进行编码: %v"}`, err) http.Error(w, errorMsg, http.StatusInternalServerError) return } } // 获取商品详情处理器 func getGoodsDetailHandler(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") var body _type.GetGoosDetail productIdStr := r.FormValue("productId") appIdStr := r.FormValue("appId") body.AppSecret = r.FormValue("appSecret") if i, err := strconv.ParseInt(productIdStr, 10, 64); err == nil { body.ProductId = int64(i) } else { body.ProductId = 0 } body.AppId, _ = strconv.Atoi(appIdStr) response, err := controller.GetGoosDetail(body) if err != nil { log.Printf("获取商品详情失败: %v", err) errorMsg := fmt.Sprintf(`{"error": "获取商品详情失败: %v"}`, err) http.Error(w, errorMsg, http.StatusInternalServerError) return } w.WriteHeader(http.StatusOK) if err = json.NewEncoder(w).Encode(json.RawMessage(response)); err != nil { log.Printf("Failed to encode response: %v", err) errorMsg := fmt.Sprintf(`{"error": "无法对响应进行编码: %v"}`, err) http.Error(w, errorMsg, http.StatusInternalServerError) return } } // 404 处理器 func notFoundHandler(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusNotFound) response := map[string]interface{}{ "error": "未找到路由", "path": r.URL.Path, "method": r.Method, "code": 404, "message": "请求的资源不存在", } if err := json.NewEncoder(w).Encode(response); err != nil { log.Printf("错误的编码响应: %v", err) errorMsg := fmt.Sprintf(`{"error": "错误的编码响应: %v"}`, err) http.Error(w, errorMsg, http.StatusInternalServerError) return } } // 请求类目Id处理器 func (h *routeHandler) getCategoryListHandler(w http.ResponseWriter, r *http.Request) { fmt.Println("开始请求商品分类列表") // 创建或打开txt文件 file, err := os.OpenFile("category_list.txt", os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644) if err != nil { log.Printf("创建文件失败: %v", err) return } defer file.Close() // 请求商品分类列表 fmt.Println("正在获取商品分类列表...") categoryPath := h.cfg.CategoryListRequest.Path categoryRequest := _type.CategoryListRequest{ ItemBizType: h.cfg.CategoryListRequest.ItemBizType, // 普通商品类型 SpBizType: h.cfg.CategoryListRequest.SpBizType, // 潮品行业类型(可选) } categoryResponseBody, err := requestUtil.MakeAPIRequest(h.cfg.App.AppId, h.cfg.App.AppSecret, h.cfg.App.Domain, categoryPath, categoryRequest) if err != nil { log.Printf("获取商品分类列表失败: %v", err) } else { fmt.Println("商品分类列表响应:") fmt.Println(string(categoryResponseBody)) // 解析响应以获取分类信息 var categoryResponse _type.CategoryListResponse if err := json.Unmarshal(categoryResponseBody, &categoryResponse); err != nil { log.Printf("解析分类响应失败: %v", err) } else if categoryResponse.Code == 0 { fmt.Println("成功获取商品分类:") // 遍历分类列表,同时打印和写入文件 for _, item := range categoryResponse.Data.List { // 控制台打印 fmt.Printf("行业: %s, 类目: %s (ID: %s)\n", item.SpBizName, item.ChannelCatName, item.ChannelCatId) // 写入文件 line := fmt.Sprintf("行业: %s, 类目: %s (ID: %s)\n", item.SpBizName, item.ChannelCatName, item.ChannelCatId) if _, err := file.WriteString(line); err != nil { log.Printf("写入文件失败: %v", err) } } fmt.Printf("共获取 %d 个分类,已保存到 category_list.txt\n", len(categoryResponse.Data.List)) } else { errorMsg := fmt.Sprintf("获取分类失败: %s (代码: %d)\n", categoryResponse.Msg, categoryResponse.Code) fmt.Printf(errorMsg) file.WriteString(errorMsg) } } if err != nil { log.Printf("获取商品分类列表失败: %v", err) } fmt.Println("商品分类列表获取结束") } // 将统计结果添加到响应中的辅助函数 func addOuterIDStatsToResponse(originalResponse []byte) ([]byte, error) { var responseMap map[string]interface{} if err := json.Unmarshal(originalResponse, &responseMap); err != nil { return nil, fmt.Errorf("解析响应JSON失败: %v", err) } // 获取统计结果 stats := getOuterIDStats(originalResponse) // 将统计结果添加到response的data中 if data, exists := responseMap["data"].(map[string]interface{}); exists { data["outer_id_stats"] = stats responseMap["data"] = data } return json.Marshal(responseMap) } // 获取outer_id统计 func getOuterIDStats(responseData []byte) map[string]interface{} { stats := make(map[string]interface{}) var data struct { Data struct { List []struct { OuterID string `json:"outer_id"` } `json:"list"` } `json:"data"` } if err := json.Unmarshal(responseData, &data); err != nil { return stats } outerIDCount := make(map[string]int) totalCount := len(data.Data.List) for _, item := range data.Data.List { outerID := item.OuterID if outerID == "" { outerID = "(空)" } outerIDCount[outerID]++ } stats["total_count"] = totalCount stats["distribution"] = outerIDCount return stats }