From b512ee992fb2e5ad9827bba08f9770f8d6bc7ff9 Mon Sep 17 00:00:00 2001 From: chfei Date: Mon, 24 Aug 2026 18:14:31 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E8=AE=A2=E5=8D=95API?= =?UTF-8?q?=E4=B8=8B=E7=9A=84Task=20=E5=A2=9E=E5=8A=A0=E7=A4=BC=E7=89=A9?= =?UTF-8?q?=E7=9A=84Task=E6=98=BE=E7=A4=BA=20=E4=BF=AE=E6=94=B9=E8=BD=AC?= =?UTF-8?q?=E6=8D=A2=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../KJD_WebService/BLL/WXXD/WXOrderManage.cs | 263 ++++++++++++++++-- .../WxModel/user_operate_task_status_info.cs | 68 ++++- .../Utils/Extension/Extension.Convert.cs | 57 ++-- 3 files changed, 340 insertions(+), 48 deletions(-) diff --git a/KJDService/KJD_WebService/BLL/WXXD/WXOrderManage.cs b/KJDService/KJD_WebService/BLL/WXXD/WXOrderManage.cs index 92e3651..d121c16 100644 --- a/KJDService/KJD_WebService/BLL/WXXD/WXOrderManage.cs +++ b/KJDService/KJD_WebService/BLL/WXXD/WXOrderManage.cs @@ -713,10 +713,6 @@ namespace KJD_Web.BLL.WXXD string conn = System.Configuration.ConfigurationManager.ConnectionStrings["ConnKJD"].ConnectionString; MysqlUtils mySql = new MysqlUtils(conn); - if (orderNo.Contains("3738552208766960384")) - { - - } string sql = ""; count = -1; @@ -2177,18 +2173,81 @@ namespace KJD_Web.BLL.WXXD if (!WXUserManage.GetSign(inputData)) return "{\"code\":999,\"msg\":\"签名校验失败\"}"; var user_name = RegexUtils.GetStringQuery(ref inputData, "user_name"); + + string shop_ids = RegexUtils.GetStringQuery(ref inputData, "shop_ids")?.Replace("'", "");//所有店铺信息 + if (string.IsNullOrEmpty(shop_ids)) + throw new ArgumentException("请选择店铺"); + List shopIdLst = shop_ids.Split(',').ToList(); + if (shopIdLst.Count > 0) + shop_ids = "'" + string.Join("','", shopIdLst) + "'"; + + string start_Time = RegexUtils.GetStringQuery(ref inputData, "start_time")?.Replace("'", ""); + string end_Time = RegexUtils.GetStringQuery(ref inputData, "end_time")?.Replace("'", ""); + DateTime startTime = DateTime.Now.AddDays(-7); + DateTime endTime = DateTime.Now; + if (!string.IsNullOrEmpty(start_Time)) + startTime = TimeUtils.StampMillisecondsToDateTime(start_Time.ParseToLong()); + if (!string.IsNullOrEmpty(end_Time)) + endTime = TimeUtils.StampMillisecondsToDateTime(end_Time.ParseToLong()); + if (endTime <= startTime) + throw new ArgumentException("结束时间必须大于开始时间"); + //if (endTime > startTime.AddDays(10)) + // throw new ArgumentException("时间范围不能超过10天"); + int startTimestamp = TimeUtils.DateTimeToTimestampSeconds(startTime); + int endTimestamp = TimeUtils.DateTimeToTimestampSeconds(endTime); + var timeCalc = DateTime.Now; string conn = System.Configuration.ConfigurationManager.ConnectionStrings["ConnKJD"].ConnectionString; MysqlUtils mySql = new MysqlUtils(conn); // ---------- 1. 查主任务 ---------- - string taskSql = $"SELECT A.id, A.task_type, A.task_describe, A.shop_ids, B.`name` as shop_name, A.object_ids, A.sub_task_num, A.success_task_num, A.fail_task_num, A.`status`, A.create_by, A.update_by, A.remark, A.task_fail_reason, A.create_time, A.update_time FROM erp.o_user_operate_task AS A INNER JOIN erp.o_shop AS B ON A.shop_ids = B.id WHERE task_type in(25,31) AND A.create_by = '{user_name}' ORDER BY create_time DESC, id DESC; "; + StringBuilder sbTask = new StringBuilder(); + + sbTask.Append("SELECT "); + sbTask.Append("A.id, "); + sbTask.Append("A.task_type, "); + sbTask.Append("A.task_describe, "); + sbTask.Append("A.shop_ids, "); + sbTask.Append("C.name AS shop_name, "); + sbTask.Append("A.object_ids, "); + sbTask.Append("A.sub_task_num, "); + sbTask.Append("A.success_task_num, "); + sbTask.Append("A.fail_task_num, "); + sbTask.Append("A.status, "); + sbTask.Append("A.create_by, "); + sbTask.Append("A.update_by, "); + sbTask.Append("A.remark, "); + sbTask.Append("A.task_fail_reason, "); + sbTask.Append("A.create_time, "); + sbTask.Append("A.update_time "); + sbTask.Append("FROM erp.o_user_operate_task AS A "); + sbTask.Append("INNER JOIN erp.o_shop AS C ON A.shop_ids = C.id "); + sbTask.Append("WHERE A.task_type IN (25, 31, 36) "); + + // 时间条件 + { + sbTask.Append("AND A.create_time BETWEEN '"); + sbTask.Append(startTime); + sbTask.Append("' AND '"); + sbTask.Append(endTime); + sbTask.Append("' "); + } + + // 店铺条件 + if (!string.IsNullOrEmpty(shop_ids)) + { + sbTask.Append("AND A.shop_ids IN ("); + sbTask.Append(shop_ids); + sbTask.Append(") "); + } + + sbTask.Append("ORDER BY A.create_time DESC, A.id DESC;"); DataTable taskDt = null; try { - taskDt = mySql.ExecuteDataTable(taskSql); + taskDt = mySql.ExecuteDataTable(sbTask.ToString()); } catch (Exception ex) { @@ -2221,30 +2280,180 @@ namespace KJD_Web.BLL.WXXD task_fail_reason = row["task_fail_reason"].ParseToNullableString(), create_time = row["create_time"].ParseToString().ParseToDateTimeNullable(), update_time = row["update_time"].ParseToString().ParseToDateTimeNullable(), + sub_tasks = new List() // 初始化子任务列表 }; orderList.Add(g); } - JsonSerializerSettings jsonSetting = new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore }; - var data = JsonUtils.SerializeObjectToString(orderList.Select(a => new { - id = a.id, - taskType = a.task_type, - taskDescribe = a.task_describe, - ShopId = a.shop_ids, - shopName = a.shop_name, - ObjectIds = a.object_ids, - subTaskNum = a.sub_task_num, - successTaskNum = a.success_task_num, - failTaskNum = a.fail_task_num, - status = a.status, - createBy = a.create_by, - updateBy = a.update_by, - remark = a.remark, - taskFailReason = a.task_fail_reason, - createTime = a.create_time, - updateTime = a.update_time - }), jsonSetting); - var seconds = (DateTime.Now - timeCalc).TotalSeconds.ToString("0.000"); - return "{\"code\":200,\"msg\":\"success\",\"data\":" + data + "}"; + + + + + List taskIdList = orderList.Select(x => x.id).ToList(); + if (taskIdList.Count > 0) + { + StringBuilder sbSubTask = new StringBuilder(); + + sbSubTask.Append("SELECT "); + sbSubTask.Append("id, "); + sbSubTask.Append("task_id, "); + sbSubTask.Append("platform_code, "); + sbSubTask.Append("shop_id, "); + sbSubTask.Append("platform_object_id, "); + sbSubTask.Append("object_id, "); + sbSubTask.Append("platform_resp_code, "); + sbSubTask.Append("platform_resp_msg, "); + sbSubTask.Append("platform_resp_data, "); + sbSubTask.Append("sys_msg, "); + sbSubTask.Append("CAST(`status` AS SIGNED) AS `status`, "); + sbSubTask.Append("audit_result, "); + sbSubTask.Append("audit_reason, "); + sbSubTask.Append("create_time, "); + sbSubTask.Append("create_by, "); + sbSubTask.Append("update_time, "); + sbSubTask.Append("update_by "); + sbSubTask.Append("FROM erp.o_user_operate_sub_task "); + sbSubTask.Append("WHERE task_id IN ("); + + for (int i = 0; i < taskIdList.Count; i++) + { + if (i > 0) + { + sbSubTask.Append(", "); + } + sbSubTask.Append(taskIdList[i]); + } + sbSubTask.Append(") "); + sbSubTask.Append("ORDER BY task_id, create_time DESC;"); + + DataTable subTaskDt = null; + try + { + subTaskDt = mySql.ExecuteDataTable(sbSubTask.ToString()); + } + catch (Exception ex) + { + return "{\"code\":500,\"msg\":\"" + ex.Message + "\",\"data\":[],\"count\":" + 0 + "}"; + } + + // 按task_id分组存储子任务 + Dictionary> subTaskDict = new Dictionary>(); + + if (subTaskDt != null) + { + foreach (DataRow row in subTaskDt.Rows) + { + var subTask = new user_operate_sub_task_info + { + id = row["id"].ParseToLong(), + task_id = row["task_id"].ParseToLong(), + platform_code = row["platform_code"].ParseToNullableString(), + shop_id = row["shop_id"].ParseToLong(), + platform_object_id = row["platform_object_id"].ParseToNullableString(), + object_id = row["object_id"].ParseToNullableString(), + platform_resp_code = row["platform_resp_code"].ParseToNullableString(), + platform_resp_msg = row["platform_resp_msg"].ParseToNullableString(), + platform_resp_data = row["platform_resp_data"].ParseToNullableString(), + sys_msg = row["sys_msg"].ParseToNullableString(), + status = row["status"].ParseToInt(), + audit_result = row["audit_result"].ParseToNullableInt(), + audit_reason = row["audit_reason"].ParseToNullableString(), + create_time = row["create_time"].ParseToString().ParseToDateTimeNullable(), + create_by = row["create_by"].ParseToNullableString(), + update_time = row["update_time"].ParseToString().ParseToDateTimeNullable(), + update_by = row["update_by"].ParseToNullableString() + }; + + long taskId = subTask.task_id; + if (!subTaskDict.ContainsKey(taskId)) + { + subTaskDict[taskId] = new List(); + } + subTaskDict[taskId].Add(subTask); + } + // 将子任务列表赋值给对应的主任务 + foreach (var task in orderList) + { + if (subTaskDict.ContainsKey(task.id)) + { + task.sub_tasks = subTaskDict[task.id]; + } + } + } + + // ---------- 3. 合并错误信息到主任务 ---------- + foreach (var task in orderList) + { + List errorList = new List(); + + // 主任务错误 + if (!string.IsNullOrEmpty(task.task_fail_reason)) + { + errorList.Add(task.task_fail_reason); + } + + // 获取该任务的子任务列表 + if (subTaskDict.ContainsKey(task.id)) + { + var subTasks = subTaskDict[task.id]; + + // 对于36类型,子任务可能有更详细的错误 + if (task.task_type == 36) + { + foreach (var subTask in subTasks) + { + // 子任务失败的错误信息 + if (subTask.status == 2 && !string.IsNullOrEmpty(subTask.sys_msg)) + { + errorList.Add(subTask.sys_msg); + } + // 审核不通过的原因 + if (subTask.audit_result == 2 && !string.IsNullOrEmpty(subTask.audit_reason)) + { + errorList.Add("审核不通过:" + subTask.audit_reason); + } + } + } + else + { + // 25、31类型,如果主任务没有错误,但子任务有错误,也收集 + foreach (var subTask in subTasks) + { + if (subTask.status == 2 && !string.IsNullOrEmpty(subTask.sys_msg)) + { + errorList.Add(subTask.sys_msg); + } + } + } + } + + // 合并错误信息(去重) + task.task_fail_reason = errorList + .Where(x => !string.IsNullOrEmpty(x)) + .Distinct() + .ToList() + .Count > 0 ? string.Join("; ", errorList.Distinct()) : null; + } + } + + JsonSerializerSettings jsonSetting = new JsonSerializerSettings + { + NullValueHandling = NullValueHandling.Ignore, + ContractResolver = new DefaultContractResolver + { + // 核心:设置命名策略为 SnakeCaseNamingStrategy + // 这样序列化时,ProjectId 会变成 "project_id"; + // 反序列化时,"project_id" 也能正确映射回 ProjectId + NamingStrategy = new SnakeCaseNamingStrategy() + } + }; + string jsonResult = JsonConvert.SerializeObject(new + { + code = 200, + msg = "success", + data = orderList, + count = orderList.Count + }, jsonSetting); + return jsonResult; } diff --git a/KJDService/KJD_WebService/Model/WxModel/user_operate_task_status_info.cs b/KJDService/KJD_WebService/Model/WxModel/user_operate_task_status_info.cs index de34202..fe380c9 100644 --- a/KJDService/KJD_WebService/Model/WxModel/user_operate_task_status_info.cs +++ b/KJDService/KJD_WebService/Model/WxModel/user_operate_task_status_info.cs @@ -1,4 +1,5 @@ -using System; +using Newtonsoft.Json; +using System; using System.Collections.Generic; using System.Linq; using System.Web; @@ -11,13 +12,13 @@ namespace KJD_Web.Model.WxModel public class user_operate_task_info { /// 主键id - public long id; + [JsonIgnore] public long id; /// 任务类型,25:微信订单拉取任务 public int? task_type; /// 任务描述,描述任务设置的相关规则 - public string task_describe; + [JsonIgnore] public string task_describe; /// 平台编码 public string task_platform_code; @@ -35,7 +36,7 @@ namespace KJD_Web.Model.WxModel public string shop_ids; public string shop_name; /// 任务对象id列表,多个,分割 - public string object_ids; + [JsonIgnore] public string object_ids; /// 子任务总数 public int? sub_task_num; @@ -53,9 +54,11 @@ namespace KJD_Web.Model.WxModel public int status; /// 创建人 + [JsonIgnore] public string create_by; /// 更新人 + [JsonIgnore] public string update_by; /// 备注 @@ -69,5 +72,62 @@ namespace KJD_Web.Model.WxModel /// 更新时间 public DateTime? update_time; + public List sub_tasks; + } + + + public class user_operate_sub_task_info + { + /// 子任务主键id + [JsonIgnore] public long id; + + /// 主任务id,对应o_user_operate_task主键id + [JsonIgnore] + public long task_id; + + /// 平台编码。"淘宝天猫:TMALL","京东POP:JD-POP"),"京东自营:JD-VC","拼多多:PDD","抖店:DOUDIAN","微信小店:WEISHOP","其他渠道:OFFLINE + public string platform_code; + + /// 门店id + [JsonIgnore] public long shop_id; + + /// 平台任务对象id,对应平台商品id + public string platform_object_id; + + /// 任务对象id。例如:商品上传中的商品id,同步订单的订单id + public string object_id; + + /// 平台返回状态码 + [JsonIgnore] public string platform_resp_code; + + /// 平台返回信息 + [JsonIgnore] public string platform_resp_msg; + + /// 平台返回数据 + [JsonIgnore] public string platform_resp_data; + + /// 系统异常信息 + public string sys_msg; + + /// 子任务状态:0:待执行,1:成功,2:失败,3:人为终止 + public int status; + + /// 审核结果:2:审核不通过;3:审核通过 + [JsonIgnore] public int? audit_result; + + /// 审核不通过原因 + [JsonIgnore] public string audit_reason; + + /// 创建时间 + [JsonIgnore] public DateTime? create_time; + + /// 创建人 + [JsonIgnore] public string create_by; + + /// 更新时间 + public DateTime? update_time; + + /// 更新人 + [JsonIgnore] public string update_by; } } diff --git a/KJDService/KJD_WebService/Utils/Extension/Extension.Convert.cs b/KJDService/KJD_WebService/Utils/Extension/Extension.Convert.cs index 1999a32..84f1f2b 100644 --- a/KJDService/KJD_WebService/Utils/Extension/Extension.Convert.cs +++ b/KJDService/KJD_WebService/Utils/Extension/Extension.Convert.cs @@ -1,13 +1,14 @@ -using System; +using NaiBa.Util.Helper; +using Newtonsoft.Json; +using System; using System.Collections; using System.Collections.Generic; +using System.Globalization; using System.IO; using System.Linq; using System.Runtime.Serialization.Formatters.Binary; using System.Text; using System.Threading.Tasks; -using NaiBa.Util.Helper; -using Newtonsoft.Json; namespace NaiBa.Util.Extension { @@ -102,22 +103,44 @@ namespace NaiBa.Util.Extension } } - public static int? ParseToNullableInt(this object str) - { - if (str == null) - return null; + public static int? ParseToNullableInt(this object str) + { + // 1. 快速判断:如果为 null 或 DBNull,直接返回 + if (str == null || str == DBNull.Value) + return null; - try - { - return Convert.ToInt32(str); - } - catch - { - return null; - } - } + // 2. 尝试直接转换类型(处理 int, short, long 等) + if (str is int intVal) + return intVal; + if (str is long longVal && longVal >= int.MinValue && longVal <= int.MaxValue) + return (int)longVal; - public static int DecimalPointParseToInt(this object str) + // 3. 针对字符串进行处理(支持空格、空字符串) + if (str is string strVal) + { + // 如果字符串为 null 或空白,视为 null + if (string.IsNullOrWhiteSpace(strVal)) + return null; + + if (int.TryParse(strVal, NumberStyles.Integer, CultureInfo.InvariantCulture, out int result)) + return result; + + return null; + } + + // 4. 其他类型(如 bool, DateTime)统一返回 null,保持严格 + try + { + return Convert.ToInt32(str); + } + catch + { + return null; + } + return null; + } + + public static int DecimalPointParseToInt(this object str) { try {