using AllBase; using AllBase.Helper; using AllBase.Model.Result; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Work.Services { /// /// 云商品数据服务 /// public class CloudGoodsService { private static string ServerUrl = "http://103.90.155.78:9001"; static CloudGoodsService() { if (EnvironmentHelper.IsDevelopment) { ServerUrl = "http://localhost:14312"; } } public static async Task> GetGoods(GoodsSearchRequest request) { var html = await GetHtml.PostJsonAsync(ServerUrl + "/api/CloudGoods/SearchGoods", request); var ret = JsonConvert.DeserializeObject>>(html); if (ret.Code != 200) { throw new Exception(ret.Msg); } return ret.Data; } public static string GetGoodsDetail(long goodsId) { var html = GetHtml.PostJson(ServerUrl + $"/api/CloudGoods/GetGoodsRawData?goodsId={goodsId}", ""); var ret = JsonConvert.DeserializeObject>(html); if (ret.Code != 200) { throw new Exception(ret.Msg); } return ret.Data; } /// /// 在后台解析微信处罚 JSON 并上报;无商品或处理失败时返回空列表,异常在内部记录。 /// public static void ReportViolationsFromJson(string json) { try { Task.Run(() => ReportViolationsFromJsonCore(json)).ConfigureAwait(false); } catch (Exception ex) { try { LogSave.AddFile("解析并上报违规商品失败:" + ex.Message); } catch { // 日志失败也不能影响调用方。 } } } private static async Task> ReportViolationsFromJsonCore(string json) { if (string.IsNullOrWhiteSpace(json)) { throw new ArgumentException("处罚 JSON 文本不能为空。", nameof(json)); } JObject root; try { root = JObject.Parse(json); } catch (JsonException ex) { throw new ArgumentException("处罚 JSON 格式不正确。", nameof(json), ex); } var record = root["record"] as JObject; if (root["code"]?.ToString() != "0" || record?["code"]?.ToString() != "0") { throw new ArgumentException("处罚数据的 code 或 record.code 不为 0,或缺少 record。", nameof(json)); } if (!(record["items"] is JArray records)) { throw new ArgumentException("处罚数据缺少 record.items 数组。", nameof(json)); } var items = new List(); foreach (var token in records) { if (!(token is JObject punishment)) { throw new ArgumentException("record.items 中的处罚记录必须是对象。", nameof(json)); } var objects = punishment["punishObject"]; if (objects == null || objects.Type == JTokenType.Null) { continue; } if (!(objects is JArray products)) { throw new ArgumentException("punishObject 必须是数组。", nameof(json)); } foreach (var product in products) { if (!(product is JObject target)) { throw new ArgumentException("punishObject 中的处罚对象必须是对象。", nameof(json)); } var id = target["productId"]; // 订单等非商品处罚对象不包含 productId。 if (id == null) { continue; } if ((id.Type != JTokenType.String && id.Type != JTokenType.Integer) || !long.TryParse(id.ToString(), out var goodsId) || goodsId <= 0) { throw new ArgumentException("商品 productId 必须是有效的正整数编号。", nameof(json)); } var reason = punishment["punishReason"]; if (reason?.Type != JTokenType.String || string.IsNullOrWhiteSpace((string)reason)) { throw new ArgumentException($"商品 {goodsId} 缺少有效的 punishReason。", nameof(json)); } items.Add(new ReportGoodsViolationItem { GoodsId = goodsId, Reasons = ((string)reason).Trim() }); } } var reports = items.GroupBy(item => item.GoodsId).Select(group => new ReportGoodsViolationItem { GoodsId = group.Key, Reasons = string.Join(";", group.Select(item => item.Reasons).Distinct()) }).ToList(); return reports.Count == 0 ? new List() : await ReportViolations(reports); } /// /// 批量上报违规商品。 /// public static async Task> ReportViolations(List items) { if (items == null) { throw new ArgumentNullException(nameof(items)); } if (items.Any(item => item == null)) { throw new ArgumentException("违规商品列表不能包含空项。", nameof(items)); } var html = await GetHtml.PostJsonAsync(ServerUrl + "/api/CloudGoods/ReportViolations", items); var ret = JsonConvert.DeserializeObject>>(html); if (ret == null) { throw new Exception("批量上报违规商品返回为空。"); } if (ret.Code != 200) { throw new Exception(ret.Msg); } return ret.Data ?? throw new Exception("批量上报违规商品返回数据为空。"); } /// /// 批量查询商品违规状态。 /// public static async Task> GetViolationStatus(List goodsIds) { if (goodsIds == null) { throw new ArgumentNullException(nameof(goodsIds)); } var html = await GetHtml.PostJsonAsync(ServerUrl + "/api/CloudGoods/GetViolationStatus", goodsIds); var ret = JsonConvert.DeserializeObject>>(html); if (ret == null) { throw new Exception("批量查询商品违规状态返回为空。"); } if (ret.Code != 200) { throw new Exception(ret.Msg); } return ret.Data ?? throw new Exception("批量查询商品违规状态返回数据为空。"); } #region user /// /// 搜索收藏 /// /// /// /// public static async Task> SearchFavorites(UserFavoritesGoodsSearchRequest request) { request.UserName = GetUserName(); var html = await GetHtml.PostJsonAsync(ServerUrl + "/api/CloudGoods/SearchFavorites", request); var ret = JsonConvert.DeserializeObject>>(html); if (ret.Code != 200) { throw new Exception(ret.Msg); } return ret.Data; } /// /// 收藏 /// /// /// /// public static async Task Favorite(List goodsIds) { var html = await GetHtml.PostJsonAsync(ServerUrl + $"/api/CloudGoods/AddFavorite", new { UserName = GetUserName(), GoodsIds = goodsIds, }); var ret = JsonConvert.DeserializeObject>(html); if (ret.Code != 200) { throw new Exception(ret.Msg); } return ret.Data; } /// /// 取消收藏 /// /// /// /// public static async Task RemoveFavorites(List goodsIds) { var html = await GetHtml.PostJsonAsync(ServerUrl + $"/api/CloudGoods/RemoveFavorites", new { UserName = GetUserName(), GoodsIds = goodsIds, }); var ret = JsonConvert.DeserializeObject>(html); if (ret.Code != 200) { throw new Exception(ret.Msg); } return ret.Data; } #endregion public static string GetUserName() { return string.IsNullOrEmpty(BaseClass.ParentUserName) ? BaseClass.UserName : BaseClass.ParentUserName; } } /// /// 违规商品上报项。 /// public class ReportGoodsViolationItem { [JsonProperty("goodsId")] public long GoodsId { get; set; } [JsonProperty("reasons")] public string Reasons { get; set; } = string.Empty; } /// /// 单个商品的违规上报结果。 /// public class ReportGoodsViolationResult { [JsonProperty("goodsId")] public long GoodsId { get; set; } [JsonProperty("isOffShelf")] public bool IsOffShelf { get; set; } } /// /// 商品违规状态。 /// public class GoodsViolationStatus { [JsonProperty("goodsId")] public long GoodsId { get; set; } [JsonProperty("isViolation")] public bool IsViolation { get; set; } } /// /// 商品搜索请求 /// public class GoodsSearchRequest { /// /// 标题(模糊搜索) /// public string Title { get; set; } = string.Empty; /// /// 最低价格(元) /// public long? MinPrice { get; set; } /// /// 最高价格(元) /// public long? MaxPrice { get; set; } /// /// 一级类目ID /// public int? CatId1 { get; set; } /// /// 二级类目ID /// public int? CatId2 { get; set; } /// /// 三级类目ID /// public int? CatId3 { get; set; } /// /// 四级类目ID /// public int? CatId4 { get; set; } /// /// 最低销量 /// public int? MinSoldQuantity { get; set; } /// /// 最高销量 /// public int? MaxSoldQuantity { get; set; } /// /// 平台类型 /// public PlatformType Platform { get; set; } /// /// 页码(默认1) /// public int PageIndex { get; set; } = 1; /// /// 每页数量(默认20) /// public int PageSize { get; set; } = 20; } public class UserFavoritesGoodsSearchRequest : GoodsSearchRequest { public string UserName { get; set; } } /// /// 商品搜索返回结果 /// public class GoodsSearchResponse { /// /// 商品列表 /// [JsonProperty("list")] public List List { get; set; } = new List(); /// /// 总记录数 /// [JsonProperty("total")] public int Total { get; set; } /// /// 当前页码 /// [JsonProperty("pageIndex")] public int PageIndex { get; set; } /// /// 每页数量 /// [JsonProperty("pageSize")] public int PageSize { get; set; } /// /// 总页数 /// [JsonProperty("totalPages")] public int TotalPages { get; set; } } public class CloudGoods : BindableBase { public bool IsSelected { get => GetValue(); set => SetValue(value); } /// /// 自增ID /// public long Id { get; set; } /// /// 平台类型 /// public byte Platform { get; set; } /// /// 商品编号 /// public long GoodsId { get; set; } /// /// 标题 /// public string Title { get; set; } = string.Empty; /// /// 描述 /// public string? Description { get; set; } /// /// 缩略图 /// public string? ThumbUrl { get; set; } /// /// 一级类目ID /// public int? CatId1 { get; set; } /// /// 二级类目ID /// public int? CatId2 { get; set; } /// /// 三级类目ID /// public int? CatId3 { get; set; } /// /// 四级类目ID /// public int? CatId4 { get; set; } /// /// 最低价快照(元),导入时计算 /// public decimal MinPrice { get; set; } /// /// 最高价快照(元),导入时计算 /// public decimal MaxPrice { get; set; } public string Price => $"{MinPrice / 100m:N2}"; /// /// 销量 /// public int SoldQuantity { get; set; } /// /// 状态:0正常 1已删除 /// public byte Status { get; set; } /// /// 创建时间 /// public DateTime CreatedTime { get; set; } /// /// 更新时间(自动更新) /// public DateTime UpdatedTime { get; set; } /// /// 索引同步状态:0未同步 1已同步 /// public byte IndexStatus { get; set; } } }