dodo hold hace 2 meses
padre
commit
dd9d4a3a5d

+ 3 - 2
molilian.api/Controllers/admin/TaobaoController.cs

@@ -65,8 +65,9 @@ namespace molilian.api.Controllers
             int result;
             switch (name)
             {
-                case "enable_fake_click":
-                case "enable_parse":
+                case "enable_fake_click":
+                case "enable_order_summary_cache":
+                case "enable_parse":
                 case "enable_coupon":
                 case "enable_sync_order":
                 case "enable_promotionQuery":

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 0 - 0
molilian.api/Properties/PublishProfiles/latest.pubxml.user


+ 138 - 134
molilian.core/Core/log/base.cs

@@ -17,8 +17,11 @@ namespace molilian.core
         {
             int flag = RedisHelper.Get<int>("turn:save_dailys_log");
             if (flag == 1) save_dailys_log = true;
-        }
-        private static readonly SemaphoreSlim semaphore = new SemaphoreSlim(10, 10);
+        }
+        private static readonly SemaphoreSlim semaphore = new SemaphoreSlim(10, 10);
+        private const int StatsHourlyExpireSeconds = 7 * 86400;
+        private const int StatsDailyExpireSeconds = 90 * 86400;
+        private const int StatsMonthlyExpireSeconds = 366 * 86400;
 
         public static async Task<int> BatchInsertLogDBAsync(int limit)
         {
@@ -191,51 +194,10 @@ namespace molilian.core
             }
         }
 
-        private static void saveAccountCache(string accountName, bool success, string message, string reason)
-        {
-            RedisHelper.IncrBy($":total:{accountName}:{DateTime.Now:yyyyMM}");
-            RedisHelper.IncrBy($":total:{accountName}:{DateTime.Now:yyyyMMdd}");
-            RedisHelper.IncrBy($":total:{accountName}:{DateTime.Now:yyyyMMddHH}");
-
-
-            string result = success ? "success" : "fail";
-            RedisHelper.IncrBy($":total:{accountName}:{result}:{DateTime.Now:yyyyMM}");
-            RedisHelper.IncrBy($":total:{accountName}:{result}:{DateTime.Now:yyyyMMdd}");
-            RedisHelper.IncrBy($":total:{accountName}:{result}:{DateTime.Now:yyyyMMddHH}");
-
-
-            if (!string.IsNullOrEmpty(message))
-            {
-                RedisHelper.SAdd($":total:{accountName}:message:{DateTime.Now:yyyyMM}", message);
-                RedisHelper.SAdd($":total:{accountName}:message:{DateTime.Now:yyyyMMdd}", message);
-                RedisHelper.SAdd($":total:{accountName}:message:{DateTime.Now:yyyyMMddHH}", message);
-
-                RedisHelper.IncrBy($":total:{accountName}:{message}:{DateTime.Now:yyyyMM}");
-                RedisHelper.IncrBy($":total:{accountName}:{message}:{DateTime.Now:yyyyMMdd}");
-                RedisHelper.IncrBy($":total:{accountName}:{message}:{DateTime.Now:yyyyMMddHH}");
-
-                RedisHelper.IncrBy($":total:{accountName}:message:{message}:{DateTime.Now:yyyyMM}");
-                RedisHelper.IncrBy($":total:{accountName}:message:{message}:{DateTime.Now:yyyyMMdd}");
-                RedisHelper.IncrBy($":total:{accountName}:message:{message}:{DateTime.Now:yyyyMMddHH}");
-            }
-
-            if (!string.IsNullOrEmpty(reason))
-            {
-                RedisHelper.SAdd($":total:{accountName}:reason:{DateTime.Now:yyyyMM}", reason);
-                RedisHelper.SAdd($":total:{accountName}:reason:{DateTime.Now:yyyyMMdd}", reason);
-                RedisHelper.SAdd($":total:{accountName}:reason:{DateTime.Now:yyyyMMddHH}", reason);
-
-                RedisHelper.IncrBy($":total:{accountName}:{reason}:{DateTime.Now:yyyyMM}");
-                RedisHelper.IncrBy($":total:{accountName}:{reason}:{DateTime.Now:yyyyMMdd}");
-                RedisHelper.IncrBy($":total:{accountName}:{reason}:{DateTime.Now:yyyyMMddHH}");
-
-
-                RedisHelper.IncrBy($":total:{accountName}:reason:{reason}:{DateTime.Now:yyyyMM}");
-                RedisHelper.IncrBy($":total:{accountName}:reason:{reason}:{DateTime.Now:yyyyMMdd}");
-                RedisHelper.IncrBy($":total:{accountName}:reason:{reason}:{DateTime.Now:yyyyMMddHH}");
-            }
-
-        }
+        private static void saveAccountCache(string accountName, bool success, string message, string reason)
+        {
+            SaveStatsAccountCache("total", accountName, success, message, reason);
+        }
 
         private static async Task saveUnionCouponParseCacheAsync(TkDataDTO data)
         {
@@ -393,47 +355,11 @@ namespace molilian.core
             }
         }
 
-        private static async Task SaveParseAccountCacheAsync(string accountName, bool success,
-            string message, string reason)
-        {
-            await RedisKit.IncrByAsync($":parse_total:{accountName}:{DateTime.Now:yyyyMM}");
-            await RedisKit.IncrByAsync($":parse_total:{accountName}:{DateTime.Now:yyyyMMdd}");
-            await RedisKit.IncrByAsync($":parse_total:{accountName}:{DateTime.Now:yyyyMMddHH}");
-
-            string result = success ? "success" : "fail";
-            await RedisKit.IncrByAsync($":parse_total:{accountName}:{result}:{DateTime.Now:yyyyMM}");
-            await RedisKit.IncrByAsync($":parse_total:{accountName}:{result}:{DateTime.Now:yyyyMMdd}");
-            await RedisKit.IncrByAsync($":parse_total:{accountName}:{result}:{DateTime.Now:yyyyMMddHH}");
-
-            if (!string.IsNullOrEmpty(message))
-            {
-                await RedisKit.SAddAsync($":parse_total:{accountName}:message:{DateTime.Now:yyyyMM}", message);
-                await RedisKit.SAddAsync($":parse_total:{accountName}:message:{DateTime.Now:yyyyMMdd}", message);
-                await RedisKit.SAddAsync($":parse_total:{accountName}:message:{DateTime.Now:yyyyMMddHH}", message);
-
-                await RedisKit.IncrByAsync($":parse_total:{accountName}:{message}:{DateTime.Now:yyyyMM}");
-                await RedisKit.IncrByAsync($":parse_total:{accountName}:{message}:{DateTime.Now:yyyyMMdd}");
-                await RedisKit.IncrByAsync($":parse_total:{accountName}:{message}:{DateTime.Now:yyyyMMddHH}");
-                await RedisKit.IncrByAsync($":parse_total:{accountName}:message:{message}:{DateTime.Now:yyyyMM}");
-                await RedisKit.IncrByAsync($":parse_total:{accountName}:message:{message}:{DateTime.Now:yyyyMMdd}");
-                await RedisKit.IncrByAsync($":parse_total:{accountName}:message:{message}:{DateTime.Now:yyyyMMddHH}");
-            }
-
-            if (!string.IsNullOrEmpty(reason))
-            {
-                await RedisKit.SAddAsync($":parse_total:{accountName}:reason:{DateTime.Now:yyyyMM}", reason);
-                await RedisKit.SAddAsync($":parse_total:{accountName}:reason:{DateTime.Now:yyyyMMdd}", reason);
-                await RedisKit.SAddAsync($":parse_total:{accountName}:reason:{DateTime.Now:yyyyMMddHH}", reason);
-
-                await RedisKit.IncrByAsync($":parse_total:{accountName}:{reason}:{DateTime.Now:yyyyMM}");
-                await RedisKit.IncrByAsync($":parse_total:{accountName}:{reason}:{DateTime.Now:yyyyMMdd}");
-                await RedisKit.IncrByAsync($":parse_total:{accountName}:{reason}:{DateTime.Now:yyyyMMddHH}");
-
-                await RedisKit.IncrByAsync($":parse_total:{accountName}:reason:{reason}:{DateTime.Now:yyyyMM}");
-                await RedisKit.IncrByAsync($":parse_total:{accountName}:reason:{reason}:{DateTime.Now:yyyyMMdd}");
-                await RedisKit.IncrByAsync($":parse_total:{accountName}:reason:{reason}:{DateTime.Now:yyyyMMddHH}");
-            }
-        }
+        private static async Task SaveParseAccountCacheAsync(string accountName, bool success,
+            string message, string reason)
+        {
+            await SaveStatsAccountCacheAsync("parse_total", accountName, success, message, reason);
+        }
 
 
 
@@ -469,52 +395,130 @@ namespace molilian.core
                 saveParseAccountCache($"{channel}_{accountId}", success, message, reason);
             }
         }
-        private static void saveParseAccountCache(string accountName, bool success,
-            string message, string reason)
-        {
-
-            RedisHelper.IncrBy($":parse_total:{accountName}:{DateTime.Now:yyyyMM}");
-            RedisHelper.IncrBy($":parse_total:{accountName}:{DateTime.Now:yyyyMMdd}");
-            RedisHelper.IncrBy($":parse_total:{accountName}:{DateTime.Now:yyyyMMddHH}");
-
-
-            string result = success ? "success" : "fail";
-            RedisHelper.IncrBy($":parse_total:{accountName}:{result}:{DateTime.Now:yyyyMM}");
-            RedisHelper.IncrBy($":parse_total:{accountName}:{result}:{DateTime.Now:yyyyMMdd}");
-            RedisHelper.IncrBy($":parse_total:{accountName}:{result}:{DateTime.Now:yyyyMMddHH}");
-
-
-            if (!string.IsNullOrEmpty(message))
-            {
-                RedisHelper.SAdd($":parse_total:{accountName}:message:{DateTime.Now:yyyyMM}", message);
-                RedisHelper.SAdd($":parse_total:{accountName}:message:{DateTime.Now:yyyyMMdd}", message);
-                RedisHelper.SAdd($":parse_total:{accountName}:message:{DateTime.Now:yyyyMMddHH}", message);
-
-                RedisHelper.IncrBy($":parse_total:{accountName}:{message}:{DateTime.Now:yyyyMM}");
-                RedisHelper.IncrBy($":parse_total:{accountName}:{message}:{DateTime.Now:yyyyMMdd}");
-                RedisHelper.IncrBy($":parse_total:{accountName}:{message}:{DateTime.Now:yyyyMMddHH}");
-                RedisHelper.IncrBy($":parse_total:{accountName}:message:{message}:{DateTime.Now:yyyyMM}");
-                RedisHelper.IncrBy($":parse_total:{accountName}:message:{message}:{DateTime.Now:yyyyMMdd}");
-                RedisHelper.IncrBy($":parse_total:{accountName}:message:{message}:{DateTime.Now:yyyyMMddHH}");
-            }
-
-            if (!string.IsNullOrEmpty(reason))
-            {
-                RedisHelper.SAdd($":parse_total:{accountName}:reason:{DateTime.Now:yyyyMM}", reason);
-                RedisHelper.SAdd($":parse_total:{accountName}:reason:{DateTime.Now:yyyyMMdd}", reason);
-                RedisHelper.SAdd($":parse_total:{accountName}:reason:{DateTime.Now:yyyyMMddHH}", reason);
-
-                RedisHelper.IncrBy($":parse_total:{accountName}:{reason}:{DateTime.Now:yyyyMM}");
-                RedisHelper.IncrBy($":parse_total:{accountName}:{reason}:{DateTime.Now:yyyyMMdd}");
-                RedisHelper.IncrBy($":parse_total:{accountName}:{reason}:{DateTime.Now:yyyyMMddHH}");
-
-                RedisHelper.IncrBy($":parse_total:{accountName}:reason:{reason}:{DateTime.Now:yyyyMM}");
-                RedisHelper.IncrBy($":parse_total:{accountName}:reason:{reason}:{DateTime.Now:yyyyMMdd}");
-                RedisHelper.IncrBy($":parse_total:{accountName}:reason:{reason}:{DateTime.Now:yyyyMMddHH}");
-            }
-        }
-
-        public static async Task<int> GetTotalAsync(string keyname, bool all_node = true)
+        private static void saveParseAccountCache(string accountName, bool success,
+            string message, string reason)
+        {
+            SaveStatsAccountCache("parse_total", accountName, success, message, reason);
+        }
+
+        private static void SaveStatsAccountCache(string prefix, string accountName, bool success,
+            string message, string reason)
+        {
+            var now = DateTime.Now;
+            string month = now.ToString("yyyyMM");
+            string day = now.ToString("yyyyMMdd");
+            string hour = now.ToString("yyyyMMddHH");
+
+            SaveStatsCount(prefix, accountName, month);
+            SaveStatsCount(prefix, accountName, day);
+            SaveStatsCount(prefix, accountName, hour);
+
+            string result = success ? "success" : "fail";
+            SaveStatsCount(prefix, accountName, month, result);
+            SaveStatsCount(prefix, accountName, day, result);
+            SaveStatsCount(prefix, accountName, hour, result);
+
+            SaveStatsDimension(prefix, accountName, "message", message, month);
+            SaveStatsDimension(prefix, accountName, "message", message, day);
+            SaveStatsDimension(prefix, accountName, "message", message, hour);
+
+            SaveStatsDimension(prefix, accountName, "reason", reason, month);
+            SaveStatsDimension(prefix, accountName, "reason", reason, day);
+            SaveStatsDimension(prefix, accountName, "reason", reason, hour);
+        }
+
+        private static async Task SaveStatsAccountCacheAsync(string prefix, string accountName, bool success,
+            string message, string reason)
+        {
+            var now = DateTime.Now;
+            string month = now.ToString("yyyyMM");
+            string day = now.ToString("yyyyMMdd");
+            string hour = now.ToString("yyyyMMddHH");
+
+            await SaveStatsCountAsync(prefix, accountName, month);
+            await SaveStatsCountAsync(prefix, accountName, day);
+            await SaveStatsCountAsync(prefix, accountName, hour);
+
+            string result = success ? "success" : "fail";
+            await SaveStatsCountAsync(prefix, accountName, month, result);
+            await SaveStatsCountAsync(prefix, accountName, day, result);
+            await SaveStatsCountAsync(prefix, accountName, hour, result);
+
+            await SaveStatsDimensionAsync(prefix, accountName, "message", message, month);
+            await SaveStatsDimensionAsync(prefix, accountName, "message", message, day);
+            await SaveStatsDimensionAsync(prefix, accountName, "message", message, hour);
+
+            await SaveStatsDimensionAsync(prefix, accountName, "reason", reason, month);
+            await SaveStatsDimensionAsync(prefix, accountName, "reason", reason, day);
+            await SaveStatsDimensionAsync(prefix, accountName, "reason", reason, hour);
+        }
+
+        private static void SaveStatsCount(string prefix, string accountName, string timeKey, string? dimension = null)
+        {
+            string key = string.IsNullOrEmpty(dimension)
+                ? $":{prefix}:{accountName}:{timeKey}"
+                : $":{prefix}:{accountName}:{dimension}:{timeKey}";
+            RedisHelper.IncrBy(key);
+            RedisHelper.Expire(key, GetStatsExpireSeconds(timeKey));
+        }
+
+        private static async Task SaveStatsCountAsync(string prefix, string accountName, string timeKey, string? dimension = null)
+        {
+            string key = string.IsNullOrEmpty(dimension)
+                ? $":{prefix}:{accountName}:{timeKey}"
+                : $":{prefix}:{accountName}:{dimension}:{timeKey}";
+            await RedisKit.IncrByAsync(key);
+            await RedisKit.ExpireAsync(key, GetStatsExpireSeconds(timeKey));
+        }
+
+        private static void SaveStatsDimension(string prefix, string accountName, string name, string value, string timeKey)
+        {
+            if (string.IsNullOrEmpty(value)) return;
+
+            int expireSeconds = GetStatsExpireSeconds(timeKey);
+            string setKey = $":{prefix}:{accountName}:{name}:{timeKey}";
+            RedisHelper.SAdd(setKey, value);
+            RedisHelper.Expire(setKey, expireSeconds);
+
+            string valueKey = $":{prefix}:{accountName}:{value}:{timeKey}";
+            RedisHelper.IncrBy(valueKey);
+            RedisHelper.Expire(valueKey, expireSeconds);
+
+            string namedValueKey = $":{prefix}:{accountName}:{name}:{value}:{timeKey}";
+            RedisHelper.IncrBy(namedValueKey);
+            RedisHelper.Expire(namedValueKey, expireSeconds);
+        }
+
+        private static async Task SaveStatsDimensionAsync(string prefix, string accountName, string name, string value, string timeKey)
+        {
+            if (string.IsNullOrEmpty(value)) return;
+
+            int expireSeconds = GetStatsExpireSeconds(timeKey);
+            string setKey = $":{prefix}:{accountName}:{name}:{timeKey}";
+            await RedisKit.SAddAsync(setKey, value);
+            await RedisKit.ExpireAsync(setKey, expireSeconds);
+
+            string valueKey = $":{prefix}:{accountName}:{value}:{timeKey}";
+            await RedisKit.IncrByAsync(valueKey);
+            await RedisKit.ExpireAsync(valueKey, expireSeconds);
+
+            string namedValueKey = $":{prefix}:{accountName}:{name}:{value}:{timeKey}";
+            await RedisKit.IncrByAsync(namedValueKey);
+            await RedisKit.ExpireAsync(namedValueKey, expireSeconds);
+        }
+
+        private static int GetStatsExpireSeconds(string timeKey)
+        {
+            return timeKey.Length switch
+            {
+                10 => StatsHourlyExpireSeconds,
+                8 => StatsDailyExpireSeconds,
+                6 => StatsMonthlyExpireSeconds,
+                _ => StatsDailyExpireSeconds,
+            };
+        }
+
+        public static async Task<int> GetTotalAsync(string keyname, bool all_node = true)
         {
             try
             {

+ 4 - 42
molilian.core/Core/log/coupon.cs

@@ -153,48 +153,10 @@ namespace molilian.core
             }
         }
 
-        private static void saveAccountCouponCache(string accountName, bool success, string message, string reason)
-        {
-            RedisHelper.IncrBy($":coupon_total:{accountName}:{DateTime.Now:yyyyMM}");
-            RedisHelper.IncrBy($":coupon_total:{accountName}:{DateTime.Now:yyyyMMdd}");
-            RedisHelper.IncrBy($":coupon_total:{accountName}:{DateTime.Now:yyyyMMddHH}");
-
-
-            string result = success ? "success" : "fail";
-            RedisHelper.IncrBy($":coupon_total:{accountName}:{result}:{DateTime.Now:yyyyMM}");
-            RedisHelper.IncrBy($":coupon_total:{accountName}:{result}:{DateTime.Now:yyyyMMdd}");
-            RedisHelper.IncrBy($":coupon_total:{accountName}:{result}:{DateTime.Now:yyyyMMddHH}");
-
-
-            if (!string.IsNullOrEmpty(message))
-            {
-                RedisHelper.SAdd($":coupon_total:{accountName}:message:{DateTime.Now:yyyyMM}", message);
-                RedisHelper.SAdd($":coupon_total:{accountName}:message:{DateTime.Now:yyyyMMdd}", message);
-                RedisHelper.SAdd($":coupon_total:{accountName}:message:{DateTime.Now:yyyyMMddHH}", message);
-
-                RedisHelper.IncrBy($":coupon_total:{accountName}:{message}:{DateTime.Now:yyyyMM}");
-                RedisHelper.IncrBy($":coupon_total:{accountName}:{message}:{DateTime.Now:yyyyMMdd}");
-                RedisHelper.IncrBy($":coupon_total:{accountName}:{message}:{DateTime.Now:yyyyMMddHH}");
-                RedisHelper.IncrBy($":coupon_total:{accountName}:message:{message}:{DateTime.Now:yyyyMM}");
-                RedisHelper.IncrBy($":coupon_total:{accountName}:message:{message}:{DateTime.Now:yyyyMMdd}");
-                RedisHelper.IncrBy($":coupon_total:{accountName}:message:{message}:{DateTime.Now:yyyyMMddHH}");
-            }
-
-            if (!string.IsNullOrEmpty(reason))
-            {
-                RedisHelper.SAdd($":coupon_total:{accountName}:reason:{DateTime.Now:yyyyMM}", reason);
-                RedisHelper.SAdd($":coupon_total:{accountName}:reason:{DateTime.Now:yyyyMMdd}", reason);
-                RedisHelper.SAdd($":coupon_total:{accountName}:reason:{DateTime.Now:yyyyMMddHH}", reason);
-
-                RedisHelper.IncrBy($":coupon_total:{accountName}:{reason}:{DateTime.Now:yyyyMM}");
-                RedisHelper.IncrBy($":coupon_total:{accountName}:{reason}:{DateTime.Now:yyyyMMdd}");
-                RedisHelper.IncrBy($":coupon_total:{accountName}:{reason}:{DateTime.Now:yyyyMMddHH}");
-                RedisHelper.IncrBy($":coupon_total:{accountName}:reason:{reason}:{DateTime.Now:yyyyMM}");
-                RedisHelper.IncrBy($":coupon_total:{accountName}:reason:{reason}:{DateTime.Now:yyyyMMdd}");
-                RedisHelper.IncrBy($":coupon_total:{accountName}:reason:{reason}:{DateTime.Now:yyyyMMddHH}");
-            }
-
-        }
+        private static void saveAccountCouponCache(string accountName, bool success, string message, string reason)
+        {
+            SaveStatsAccountCache("coupon_total", accountName, success, message, reason);
+        }
 
 
 

+ 4 - 42
molilian.core/Core/log/cps.cs

@@ -165,48 +165,10 @@ namespace molilian.core
             }
         }
 
-        private static void saveAccountCpsCache(string flagName, bool success, string message, string reason)
-        {
-            RedisHelper.IncrBy($":cps_total:{flagName}:{DateTime.Now:yyyyMM}");
-            RedisHelper.IncrBy($":cps_total:{flagName}:{DateTime.Now:yyyyMMdd}");
-            RedisHelper.IncrBy($":cps_total:{flagName}:{DateTime.Now:yyyyMMddHH}");
-
-
-            string result = success ? "success" : "fail";
-            RedisHelper.IncrBy($":cps_total:{flagName}:{result}:{DateTime.Now:yyyyMM}");
-            RedisHelper.IncrBy($":cps_total:{flagName}:{result}:{DateTime.Now:yyyyMMdd}");
-            RedisHelper.IncrBy($":cps_total:{flagName}:{result}:{DateTime.Now:yyyyMMddHH}");
-
-
-            if (!string.IsNullOrEmpty(message))
-            {
-                RedisHelper.SAdd($":cps_total:{flagName}:message:{DateTime.Now:yyyyMM}", message);
-                RedisHelper.SAdd($":cps_total:{flagName}:message:{DateTime.Now:yyyyMMdd}", message);
-                RedisHelper.SAdd($":cps_total:{flagName}:message:{DateTime.Now:yyyyMMddHH}", message);
-
-                RedisHelper.IncrBy($":cps_total:{flagName}:{message}:{DateTime.Now:yyyyMM}");
-                RedisHelper.IncrBy($":cps_total:{flagName}:{message}:{DateTime.Now:yyyyMMdd}");
-                RedisHelper.IncrBy($":cps_total:{flagName}:{message}:{DateTime.Now:yyyyMMddHH}");
-                RedisHelper.IncrBy($":cps_total:{flagName}:message:{message}:{DateTime.Now:yyyyMM}");
-                RedisHelper.IncrBy($":cps_total:{flagName}:message:{message}:{DateTime.Now:yyyyMMdd}");
-                RedisHelper.IncrBy($":cps_total:{flagName}:message:{message}:{DateTime.Now:yyyyMMddHH}");
-            }
-
-            if (!string.IsNullOrEmpty(reason))
-            {
-                RedisHelper.SAdd($":cps_total:{flagName}:reason:{DateTime.Now:yyyyMM}", reason);
-                RedisHelper.SAdd($":cps_total:{flagName}:reason:{DateTime.Now:yyyyMMdd}", reason);
-                RedisHelper.SAdd($":cps_total:{flagName}:reason:{DateTime.Now:yyyyMMddHH}", reason);
-
-                RedisHelper.IncrBy($":cps_total:{flagName}:{reason}:{DateTime.Now:yyyyMM}");
-                RedisHelper.IncrBy($":cps_total:{flagName}:{reason}:{DateTime.Now:yyyyMMdd}");
-                RedisHelper.IncrBy($":cps_total:{flagName}:{reason}:{DateTime.Now:yyyyMMddHH}");
-                RedisHelper.IncrBy($":cps_total:{flagName}:reason:{reason}:{DateTime.Now:yyyyMM}");
-                RedisHelper.IncrBy($":cps_total:{flagName}:reason:{reason}:{DateTime.Now:yyyyMMdd}");
-                RedisHelper.IncrBy($":cps_total:{flagName}:reason:{reason}:{DateTime.Now:yyyyMMddHH}");
-            }
-
-        }
+        private static void saveAccountCpsCache(string flagName, bool success, string message, string reason)
+        {
+            SaveStatsAccountCache("cps_total", flagName, success, message, reason);
+        }
 
 
 

+ 8 - 8
molilian.core/Core/log/pdd.cs

@@ -40,10 +40,10 @@ namespace molilian.core
                         daily_table = $"pdd_parse_logs_{data.create_time:yyyyMMdd}";
                         save_pdd_parse_logs(data, daily_table, connection, transaction);
 
-                        if (!data.success)
-                        {
-                            save_pdd_parse_logs(data, "pdd_parse_logs_fail", connection, transaction);
-                        }
+                        //if (!data.success)
+                        //{
+                        //    save_pdd_parse_logs(data, "pdd_parse_logs_fail", connection, transaction);
+                        //}
                     }
                     total++;
                 }
@@ -90,10 +90,10 @@ namespace molilian.core
                             string daily_table = $"pdd_parse_logs_{data.create_time:yyyyMMdd}";
                             save_pdd_parse_logs(data, daily_table, connection, transaction);
                         }
-                        if (!data.success)
-                        {
-                            save_pdd_parse_logs(data, "pdd_parse_logs_fail", connection, transaction);
-                        }
+                        //if (!data.success)
+                        //{
+                        //    save_pdd_parse_logs(data, "pdd_parse_logs_fail", connection, transaction);
+                        //}
                     }
                     total++;
                 }

+ 4 - 41
molilian.core/Core/log/promotion.cs

@@ -151,47 +151,10 @@ namespace molilian.core
             await savePromotionAccountCacheAsync($"{accountId}_{scene}", success, message, reason);
         }
 
-        private static async Task savePromotionAccountCacheAsync(string accountName, bool success, string message, string reason)
-        {
-            await RedisKit.IncrByAsync($":promotion_total:{accountName}:{DateTime.Now:yyyyMM}");
-            await RedisKit.IncrByAsync($":promotion_total:{accountName}:{DateTime.Now:yyyyMMdd}");
-            await RedisKit.IncrByAsync($":promotion_total:{accountName}:{DateTime.Now:yyyyMMddHH}");
-
-
-            string result = success ? "success" : "fail";
-            await RedisKit.IncrByAsync($":promotion_total:{accountName}:{result}:{DateTime.Now:yyyyMM}");
-            await RedisKit.IncrByAsync($":promotion_total:{accountName}:{result}:{DateTime.Now:yyyyMMdd}");
-            await RedisKit.IncrByAsync($":promotion_total:{accountName}:{result}:{DateTime.Now:yyyyMMddHH}");
-
-
-            if (!string.IsNullOrEmpty(message))
-            {
-                await RedisKit.SAddAsync($":promotion_total:{accountName}:message:{DateTime.Now:yyyyMM}", message);
-                await RedisKit.SAddAsync($":promotion_total:{accountName}:message:{DateTime.Now:yyyyMMdd}", message);
-                await RedisKit.SAddAsync($":promotion_total:{accountName}:message:{DateTime.Now:yyyyMMddHH}", message);
-
-                await RedisKit.IncrByAsync($":promotion_total:{accountName}:{message}:{DateTime.Now:yyyyMM}");
-                await RedisKit.IncrByAsync($":promotion_total:{accountName}:{message}:{DateTime.Now:yyyyMMdd}");
-                await RedisKit.IncrByAsync($":promotion_total:{accountName}:{message}:{DateTime.Now:yyyyMMddHH}");
-                await RedisKit.IncrByAsync($":promotion_total:{accountName}:message:{message}:{DateTime.Now:yyyyMM}");
-                await RedisKit.IncrByAsync($":promotion_total:{accountName}:message:{message}:{DateTime.Now:yyyyMMdd}");
-                await RedisKit.IncrByAsync($":promotion_total:{accountName}:message:{message}:{DateTime.Now:yyyyMMddHH}");
-            }
-
-            if (!string.IsNullOrEmpty(reason))
-            {
-                await RedisKit.SAddAsync($":promotion_total:{accountName}:reason:{DateTime.Now:yyyyMM}", reason);
-                await RedisKit.SAddAsync($":promotion_total:{accountName}:reason:{DateTime.Now:yyyyMMdd}", reason);
-                await RedisKit.SAddAsync($":promotion_total:{accountName}:reason:{DateTime.Now:yyyyMMddHH}", reason);
-
-                await RedisKit.IncrByAsync($":promotion_total:{accountName}:{reason}:{DateTime.Now:yyyyMM}");
-                await RedisKit.IncrByAsync($":promotion_total:{accountName}:{reason}:{DateTime.Now:yyyyMMdd}");
-                await RedisKit.IncrByAsync($":promotion_total:{accountName}:{reason}:{DateTime.Now:yyyyMMddHH}");
-                await RedisKit.IncrByAsync($":promotion_total:{accountName}:reason:{reason}:{DateTime.Now:yyyyMM}");
-                await RedisKit.IncrByAsync($":promotion_total:{accountName}:reason:{reason}:{DateTime.Now:yyyyMMdd}");
-                await RedisKit.IncrByAsync($":promotion_total:{accountName}:reason:{reason}:{DateTime.Now:yyyyMMddHH}");
-            }
-        }
+        private static async Task savePromotionAccountCacheAsync(string accountName, bool success, string message, string reason)
+        {
+            await SaveStatsAccountCacheAsync("promotion_total", accountName, success, message, reason);
+        }
 
     }
 

+ 21 - 21
molilian.core/Core/log/taobao.cs

@@ -52,15 +52,15 @@ namespace molilian.core
                             save_tk_parse_logs(data, "tk_parse_logs_test", connection, transaction);
                         }
 
-                        if (data.reason.Contains("初步筛选2") && !data.rawContent.Contains("I:/kWqN5t623Hx"))
-                        {
-                            save_tk_parse_logs(data, "tk_parse_logs_test2", connection, transaction);
-                        }
-
-                        if (data.reason.Contains("初步筛选1.5"))
-                        {
-                            save_tk_parse_logs(data, "tk_parse_logs_multi_token", connection, transaction);
-                        }
+                        //if (data.reason.Contains("初步筛选2") && !data.rawContent.Contains("I:/kWqN5t623Hx"))
+                        //{
+                        //    save_tk_parse_logs(data, "tk_parse_logs_test2", connection, transaction);
+                        //}
+
+                        //if (data.reason.Contains("初步筛选1.5"))
+                        //{
+                        //    save_tk_parse_logs(data, "tk_parse_logs_multi_token", connection, transaction);
+                        //}
                         if (data.reason.Contains("霸下验证码"))
                         {
                             save_tk_parse_logs(data, "tk_parse_logs_captcha", connection, transaction);
@@ -111,18 +111,18 @@ namespace molilian.core
                 {
                     _ = saveUnionCouponParseCacheAsync(response);
                 }
-                if (!TestParseCore.InWhitelist(response.ip, response.oaid))
-                {
-                    await SaveParseCacheAsync(response.channel.ToString(), response.accountId,
-                        response.accountName, response.success, response.message, response.reason,
-                        response.deeplink_url);
-                }
-                if (!string.IsNullOrEmpty(response.itemId)) TkOrderTrackingCore.SaveLinkSummary(response);
-
-
-                var account = await TkPoolCore.ALLGetOneAsync(response.accountId);
-                bool is_hide = false;
-                if (account != null) is_hide = account.is_hide;
+                if (!TestParseCore.InWhitelist(response.ip, response.oaid))
+                {
+                    await SaveParseCacheAsync(response.channel.ToString(), response.accountId,
+                        response.accountName, response.success, response.message, response.reason,
+                        response.deeplink_url);
+                }
+
+                var account = await TkPoolCore.ALLGetOneAsync(response.accountId);
+                if (!string.IsNullOrEmpty(response.itemId)) TkOrderTrackingCore.SaveLinkSummary(response, account);
+
+                bool is_hide = false;
+                if (account != null) is_hide = account.is_hide;
 
                 if (!response.success && "nologin".Equals(response.message))
                 {

+ 4 - 39
molilian.core/Core/log/tkActivity.cs

@@ -137,45 +137,10 @@ namespace molilian.core
                 .Create(DBContext.InsertType.NORMAL, transaction);
         }
 
-        private static void saveAccountActivityCache(string accountName, bool success, string message, string reason)
-        {
-            RedisHelper.IncrBy($":activity_total:{accountName}:{DateTime.Now:yyyyMM}");
-            RedisHelper.IncrBy($":activity_total:{accountName}:{DateTime.Now:yyyyMMdd}");
-            RedisHelper.IncrBy($":activity_total:{accountName}:{DateTime.Now:yyyyMMddHH}");
-
-            string result = success ? "success" : "fail";
-            RedisHelper.IncrBy($":activity_total:{accountName}:{result}:{DateTime.Now:yyyyMM}");
-            RedisHelper.IncrBy($":activity_total:{accountName}:{result}:{DateTime.Now:yyyyMMdd}");
-            RedisHelper.IncrBy($":activity_total:{accountName}:{result}:{DateTime.Now:yyyyMMddHH}");
-
-            if (!string.IsNullOrEmpty(message))
-            {
-                RedisHelper.SAdd($":activity_total:{accountName}:message:{DateTime.Now:yyyyMM}", message);
-                RedisHelper.SAdd($":activity_total:{accountName}:message:{DateTime.Now:yyyyMMdd}", message);
-                RedisHelper.SAdd($":activity_total:{accountName}:message:{DateTime.Now:yyyyMMddHH}", message);
-
-                RedisHelper.IncrBy($":activity_total:{accountName}:{message}:{DateTime.Now:yyyyMM}");
-                RedisHelper.IncrBy($":activity_total:{accountName}:{message}:{DateTime.Now:yyyyMMdd}");
-                RedisHelper.IncrBy($":activity_total:{accountName}:{message}:{DateTime.Now:yyyyMMddHH}");
-                RedisHelper.IncrBy($":activity_total:{accountName}:message:{message}:{DateTime.Now:yyyyMM}");
-                RedisHelper.IncrBy($":activity_total:{accountName}:message:{message}:{DateTime.Now:yyyyMMdd}");
-                RedisHelper.IncrBy($":activity_total:{accountName}:message:{message}:{DateTime.Now:yyyyMMddHH}");
-            }
-
-            if (!string.IsNullOrEmpty(reason))
-            {
-                RedisHelper.SAdd($":activity_total:{accountName}:reason:{DateTime.Now:yyyyMM}", reason);
-                RedisHelper.SAdd($":activity_total:{accountName}:reason:{DateTime.Now:yyyyMMdd}", reason);
-                RedisHelper.SAdd($":activity_total:{accountName}:reason:{DateTime.Now:yyyyMMddHH}", reason);
-
-                RedisHelper.IncrBy($":activity_total:{accountName}:{reason}:{DateTime.Now:yyyyMM}");
-                RedisHelper.IncrBy($":activity_total:{accountName}:{reason}:{DateTime.Now:yyyyMMdd}");
-                RedisHelper.IncrBy($":activity_total:{accountName}:{reason}:{DateTime.Now:yyyyMMddHH}");
-                RedisHelper.IncrBy($":activity_total:{accountName}:reason:{reason}:{DateTime.Now:yyyyMM}");
-                RedisHelper.IncrBy($":activity_total:{accountName}:reason:{reason}:{DateTime.Now:yyyyMMdd}");
-                RedisHelper.IncrBy($":activity_total:{accountName}:reason:{reason}:{DateTime.Now:yyyyMMddHH}");
-            }
-        }
+        private static void saveAccountActivityCache(string accountName, bool success, string message, string reason)
+        {
+            SaveStatsAccountCache("activity_total", accountName, success, message, reason);
+        }
 
 
     }

+ 208 - 71
molilian.core/Core/taoke/OrderTrackingCore.cs

@@ -20,51 +20,169 @@ using System.IO;
 
 namespace molilian.core
 {
-    public partial class TkOrderTrackingCore
-    {
-        public static void SaveLinkSummary(TkDataDTO item)
-        {
-            //清洗数据
-            item.content = null;
-            item.rawContent = null;
-            item.rawContent2 = null;
-
-            TkDataDTO newData = new()
-            {
-                channel = item.channel,
-                ip = item.ip,
-                oaid = item.oaid,
+    public partial class TkOrderTrackingCore
+    {
+        private const int DefaultLinkSummaryTtlSeconds = 24 * 3600;
+        private const int MaxLinkSummaryTtlSeconds = 7 * 24 * 3600;
+        private const string LinkSummaryCacheVersion = "v2";
+
+        public class TkOrderLinkSummaryDTO
+        {
+            public TkChannelEnum channel { get; set; }
+            public int accountId { get; set; } = 0;
+            public string ip { get; set; } = string.Empty;
+            public string oaid { get; set; } = string.Empty;
+            public string mktId { get; set; } = string.Empty;
+            public string itemId { get; set; } = string.Empty;
+            public string itemName { get; set; } = string.Empty;
+            public string taoToken { get; set; } = string.Empty;
+            public string shortLinkurl { get; set; } = string.Empty;
+            public string deeplink_url { get; set; } = string.Empty;
+            public string item_url { get; set; } = string.Empty;
+            public string item_deeplink_url { get; set; } = string.Empty;
+            public DateTime create_time { get; set; } = DateTime.Now;
+        }
+
+        public static void SaveLinkSummary(TkDataDTO item, TkPoolDTO? account = null)
+        {
+            if (!ShouldSaveLinkSummary(item, account)) return;
+
+            TkOrderLinkSummaryDTO newData = new()
+            {
+                accountId = item.accountId,
+                channel = item.channel,
+                ip = item.ip,
+                oaid = item.oaid,
                 mktId = item.mktId,
                 itemId = item.itemId,
                 itemName = item.itemName,
-                taoToken = item.taoToken,
-                shortLinkurl = item.shortLinkurl,
-                deeplink_url = item.deeplink_url,
-                create_time = item.create_time,
-            };
-
-            var config = TkConfigCore.Get();
-            var ttl = config.fake_click_ttl * 3600;
-            string cacheKey = $":cache:order_summary:{item.accountId}:{item.itemId}";
-            RedisHelper.Set(cacheKey, newData, ttl);
-
-            string mktId = item.mktId;
-            if (!string.IsNullOrEmpty(mktId) && mktId.Contains('-'))
-            {
-                mktId = mktId.Split('-')[^1];
-                cacheKey = $":cache:order_summary:{item.accountId}:mktId:{mktId}";
-                RedisHelper.Set(cacheKey, newData, ttl);
-            }
-
-            cacheKey = $":cache:order_summary:{item.accountId}:{item.itemName}";
-            RedisHelper.Set(cacheKey, newData, ttl);
-        }
-
-
-        public static async Task<(int, TkDataDTO)> GetLinkSummaryAsync(TkPoolDTO account, string itemId, string mktId, string itemTitle)
-        {
-            try
-            {
+                taoToken = item.taoToken,
+                shortLinkurl = item.shortLinkurl,
+                deeplink_url = item.deeplink_url,
+                item_url = item.item_url,
+                item_deeplink_url = item.item_deeplink_url,
+                create_time = item.create_time,
+            };
+
+            var config = TkConfigCore.Get();
+            int ttl = GetLinkSummaryTtlSeconds(config);
+            string cacheKey = BuildItemSummaryKey(item.accountId, item.itemId);
+            if (!string.IsNullOrEmpty(cacheKey)) RedisHelper.Set(cacheKey, newData, ttl);
+
+            string mktId = item.mktId;
+            if (!string.IsNullOrEmpty(mktId) && mktId.Contains('-'))
+            {
+                mktId = mktId.Split('-')[^1];
+                cacheKey = BuildMktSummaryKey(item.accountId, mktId);
+                RedisHelper.Set(cacheKey, newData, ttl);
+            }
+
+            cacheKey = BuildTitleSummaryKey(item.accountId, item.itemName);
+            if (!string.IsNullOrEmpty(cacheKey)) RedisHelper.Set(cacheKey, newData, ttl);
+        }
+
+        private static bool ShouldSaveLinkSummary(TkDataDTO item, TkPoolDTO? account)
+        {
+            if (item == null || item.accountId <= 0) return false;
+            if (!item.success) return false;
+            if (string.IsNullOrEmpty(item.itemId)) return false;
+
+            bool hasLink = !string.IsNullOrEmpty(item.shortLinkurl) ||
+                           !string.IsNullOrEmpty(item.deeplink_url) ||
+                           !string.IsNullOrEmpty(item.item_url) ||
+                           !string.IsNullOrEmpty(item.item_deeplink_url);
+            if (!hasLink) return false;
+
+            account ??= GetCachedAccount(item.accountId);
+            return account?.enable_order_summary_cache ?? true;
+        }
+
+        private static TkPoolDTO? GetCachedAccount(int accountId)
+        {
+            try
+            {
+                var list = TkPoolCore.GetCachedAccounts();
+                return list?.FirstOrDefault(e => e.id == accountId);
+            }
+            catch
+            {
+                return null;
+            }
+        }
+
+        private static int GetLinkSummaryTtlSeconds(TkConfigDTO config)
+        {
+            long configuredHours = config?.fake_click_ttl ?? 0;
+            long ttl = configuredHours > 0 ? configuredHours * 3600 : DefaultLinkSummaryTtlSeconds;
+            return (int)Math.Clamp(ttl, 3600, MaxLinkSummaryTtlSeconds);
+        }
+
+        private static string BuildItemSummaryKey(int accountId, string itemId)
+        {
+            if (accountId <= 0 || string.IsNullOrEmpty(itemId)) return string.Empty;
+            return $":cache:order_summary:{LinkSummaryCacheVersion}:{accountId}:item:{itemId}";
+        }
+
+        private static string BuildMktSummaryKey(int accountId, string mktId)
+        {
+            if (accountId <= 0 || string.IsNullOrEmpty(mktId)) return string.Empty;
+            return $":cache:order_summary:{LinkSummaryCacheVersion}:{accountId}:mktId:{mktId}";
+        }
+
+        private static string BuildTitleSummaryKey(int accountId, string itemTitle)
+        {
+            if (accountId <= 0 || string.IsNullOrEmpty(itemTitle)) return string.Empty;
+            return $":cache:order_summary:{LinkSummaryCacheVersion}:{accountId}:title:{Sha256Hex(itemTitle)}";
+        }
+
+        private static string BuildLegacyItemSummaryKey(int accountId, string itemId)
+        {
+            if (accountId <= 0 || string.IsNullOrEmpty(itemId)) return string.Empty;
+            return $":cache:order_summary:{accountId}:{itemId}";
+        }
+
+        private static string BuildLegacyMktSummaryKey(int accountId, string mktId)
+        {
+            if (accountId <= 0 || string.IsNullOrEmpty(mktId)) return string.Empty;
+            return $":cache:order_summary:{accountId}:mktId:{mktId}";
+        }
+
+        private static string BuildLegacyTitleSummaryKey(int accountId, string itemTitle)
+        {
+            if (accountId <= 0 || string.IsNullOrEmpty(itemTitle)) return string.Empty;
+            return $":cache:order_summary:{accountId}:{itemTitle}";
+        }
+
+        private static string Sha256Hex(string value)
+        {
+            byte[] hash = SHA256.HashData(Encoding.UTF8.GetBytes(value));
+            return Convert.ToHexString(hash).ToLowerInvariant();
+        }
+
+        private static async Task<TkOrderLinkSummaryDTO?> GetFirstSummaryAsync(YunhuiKit.RedisClient redis, IEnumerable<string> keys)
+        {
+            foreach (var key in keys.Where(e => !string.IsNullOrEmpty(e)))
+            {
+                var result = await redis.GetAsync<TkOrderLinkSummaryDTO>(key);
+                if (IsUsableOrderSummary(result)) return result;
+            }
+            return null;
+        }
+
+
+        private static bool IsUsableOrderSummary(TkOrderLinkSummaryDTO? summary)
+        {
+            if (summary == null) return false;
+            return !string.IsNullOrEmpty(summary.shortLinkurl) ||
+                   !string.IsNullOrEmpty(summary.deeplink_url) ||
+                   !string.IsNullOrEmpty(summary.item_url) ||
+                   !string.IsNullOrEmpty(summary.item_deeplink_url);
+        }
+
+        public static async Task<(int, TkOrderLinkSummaryDTO)> GetLinkSummaryAsync(TkPoolDTO account, string itemId, string mktId, string itemTitle)
+        {
+            try
+            {
                 int accountId = account.id;
                 mktId = !string.IsNullOrEmpty(mktId) && mktId.Contains('-')
                     ? mktId.Split('-')[^1]
@@ -95,30 +213,42 @@ namespace molilian.core
                             var redis = scope.Client;
 
                             // 按优先级依次查询不同的缓存key
-                            TkDataDTO result = null;
+                            TkOrderLinkSummaryDTO result = null;
 
 
                             // 遍历所有关联账户ID
                             foreach (var relatedId in relatedAccountIds)
                             {
-                                if (!string.IsNullOrEmpty(mktId))
-                                {
-                                    result = await redis.GetAsync<TkDataDTO>($":cache:order_summary:{relatedId}:mktId:{mktId}");
-                                    if (result != null) return (1, result);
-                                }
-
-                                if (!string.IsNullOrEmpty(itemId))
-                                {
-                                    result = await redis.GetAsync<TkDataDTO>($":cache:order_summary:{relatedId}:{itemId}");
-                                    if (result != null) return (2, result);
-
-                                    if (!string.IsNullOrEmpty(itemTitle))
-                                    {
-                                        result = await redis.GetAsync<TkDataDTO>($":cache:order_summary:{relatedId}:{itemTitle}");
-                                        if (result != null) return (3, result);
-                                    }
-                                }
-                            }
+                                if (!string.IsNullOrEmpty(mktId))
+                                {
+                                    result = await GetFirstSummaryAsync(redis, new[]
+                                    {
+                                        BuildMktSummaryKey(relatedId, mktId),
+                                        BuildLegacyMktSummaryKey(relatedId, mktId)
+                                    });
+                                    if (IsUsableOrderSummary(result)) return (1, result);
+                                }
+
+                                if (!string.IsNullOrEmpty(itemId))
+                                {
+                                    result = await GetFirstSummaryAsync(redis, new[]
+                                    {
+                                        BuildItemSummaryKey(relatedId, itemId),
+                                        BuildLegacyItemSummaryKey(relatedId, itemId)
+                                    });
+                                    if (IsUsableOrderSummary(result)) return (2, result);
+
+                                    if (!string.IsNullOrEmpty(itemTitle))
+                                    {
+                                        result = await GetFirstSummaryAsync(redis, new[]
+                                        {
+                                            BuildTitleSummaryKey(relatedId, itemTitle),
+                                            BuildLegacyTitleSummaryKey(relatedId, itemTitle)
+                                        });
+                                        if (IsUsableOrderSummary(result)) return (3, result);
+                                    }
+                                }
+                            }
                         }
                         catch (Exception ex)
                         {
@@ -127,10 +257,10 @@ namespace molilian.core
                     });
 
                 var results = await Task.WhenAll(tasks);
-                return results.FirstOrDefault(r => r != (0, null));
-            }
-            catch (Exception)
-            {
+                return results.FirstOrDefault(r => r != (0, null));
+            }
+            catch (Exception)
+            {
                 // TODO: 添加日志记录
                 return (0, null);
             }
@@ -153,12 +283,19 @@ namespace molilian.core
                             using var scope = await RedisClientFactory.CreateScopeAsync(redisServer);
                             var redis = scope.Client;
 
-                            var keys = new[]
-                            {
-                                $":cache:order_summary:{accountId}:{itemId}",
-                                $":cache:order_summary:{accountId}:mktId:{mktId}",
-                                $":cache:order_summary:{accountId}:{itemTitle}"
-                            }.Where(k => !string.IsNullOrEmpty(k));
+                            mktId = !string.IsNullOrEmpty(mktId) && mktId.Contains('-')
+                                ? mktId.Split('-')[^1]
+                                : mktId;
+
+                            var keys = new[]
+                            {
+                                BuildItemSummaryKey(accountId, itemId),
+                                BuildLegacyItemSummaryKey(accountId, itemId),
+                                BuildMktSummaryKey(accountId, mktId),
+                                BuildLegacyMktSummaryKey(accountId, mktId),
+                                BuildTitleSummaryKey(accountId, itemTitle),
+                                BuildLegacyTitleSummaryKey(accountId, itemTitle)
+                            }.Where(k => !string.IsNullOrEmpty(k));
 
                             // 批量删除所有相关缓存
                             await redis.DelAsync(keys.ToArray());

+ 11 - 6
molilian.core/Core/taoke/TkPoolCore.cs

@@ -24,12 +24,17 @@ namespace molilian.core
 
         private static SemaphoreSlim _semaphore = new SemaphoreSlim(1, 1);
 
-        private static IEnumerable<TkPoolDTO> _cached;
-        private static IEnumerable<TkPoolDTO> _all_cached;
-
-        public static async Task<TkPoolDTO> GetOneAsync(int id)
-        {
-            var list = await ListAsync();
+        private static IEnumerable<TkPoolDTO> _cached;
+        private static IEnumerable<TkPoolDTO> _all_cached;
+
+        public static IEnumerable<TkPoolDTO> GetCachedAccounts()
+        {
+            return _all_cached ?? _cached ?? Enumerable.Empty<TkPoolDTO>();
+        }
+
+        public static async Task<TkPoolDTO> GetOneAsync(int id)
+        {
+            var list = await ListAsync();
             if (!list.Any()) return null;
             return list.Where(e => e.id == id).FirstOrDefault();
         }

+ 3 - 2
molilian.core/DTO/alimama/TkPoolDTO.cs

@@ -42,8 +42,9 @@
         public string api { get; set; } = string.Empty;
         public int api_id { get; set; } = 0;
         public string end_point { get; set; } = string.Empty;
-        public bool enable_fake_click { get; set; } = false;
-        public FakeClickLinkType fake_click_link_type { get; set; } = 0;
+        public bool enable_fake_click { get; set; } = false;
+        public bool enable_order_summary_cache { get; set; } = true;
+        public FakeClickLinkType fake_click_link_type { get; set; } = 0;
         public int fake_click_max { get; set; } = 0;
         public int fake_click_min { get; set; } = 0;
         public bool enable_parse { get; set; } = false;

+ 17 - 0
sql/20260619_add_tk_pool_order_summary_switch.sql

@@ -0,0 +1,17 @@
+SET @column_exists := (
+    SELECT COUNT(*)
+    FROM information_schema.columns
+    WHERE table_schema = DATABASE()
+      AND table_name = 'tk_pool'
+      AND column_name = 'enable_order_summary_cache'
+);
+
+SET @sql := IF(
+    @column_exists = 0,
+    'ALTER TABLE tk_pool ADD COLUMN enable_order_summary_cache TINYINT(1) NOT NULL DEFAULT 1 COMMENT ''是否记录淘宝转链订单匹配缓存''',
+    'SELECT 1'
+);
+
+PREPARE stmt FROM @sql;
+EXECUTE stmt;
+DEALLOCATE PREPARE stmt;

Algunos archivos no se mostraron porque demasiados archivos cambiaron en este cambio