TaobaoController.cs 47 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006
  1. using molilian.core;
  2. using dodohold.core;
  3. using Microsoft.AspNetCore.Mvc;
  4. using System.Text.Json;
  5. using System.Net;
  6. using static QRCoder.PayloadGenerator;
  7. using MySqlX.XDevAPI;
  8. using OfficeOpenXml.FormulaParsing.LexicalAnalysis;
  9. using StackExchange.Redis;
  10. namespace molilian.api.Controllers
  11. {
  12. [ApiController]
  13. [MyAuthorize("admin")]
  14. [Route("api/[controller]/[action]")]
  15. [Route("coupon_api/[controller]/[action]")]
  16. public class TaobaoController : ControllerBase
  17. {
  18. readonly IAuthorizationProvider provider = new AdminProvider();
  19. protected IHttpContextAccessor _accessor;
  20. public TaobaoController(IHttpContextAccessor accessor)
  21. {
  22. _accessor = accessor;
  23. }
  24. [HttpPost]
  25. public async Task<ActionResult> updateCookies([FromBody] JsonElement form)
  26. {
  27. var clientIp = _accessor.HttpContext.GetUserIp();
  28. var token = provider.Get(_accessor.HttpContext);
  29. string user_agent = _accessor.HttpContext.Request.UserAgent();
  30. string cookie = form.Read<string>("cookie", string.Empty);
  31. var accountId = await TkPoolCore.UpdateCookies(cookie, user_agent);
  32. bool success = accountId > 0;
  33. if (success)
  34. {
  35. //string desc = ObjectComparer.PrintCompareToString(old, form).Trim();
  36. OperationLogCore.LogOperation(token.AccessKey, clientIp, $"tk_pool:{accountId}:cookie", string.Empty, cookie);
  37. }
  38. return new APIResult(new
  39. {
  40. data = new { success, msg = success ? "更新成功" : "更新失败,请检查输入的cookie" },
  41. });
  42. }
  43. [HttpPost]
  44. public async Task<ActionResult> update([FromBody] JsonElement form)
  45. {
  46. var clientIp = _accessor.HttpContext.GetUserIp();
  47. var token = provider.Get(_accessor.HttpContext);
  48. int id = form.Read<int>("id", 0);
  49. string name = form.Read<string>("name", string.Empty);
  50. string val = form.Read<string>("val", string.Empty);
  51. if (id == 0)
  52. {
  53. return new APIResult(new { data = new { success = false, msg = "更新失败,请检查输入的cookie" } });
  54. }
  55. int result;
  56. switch (name)
  57. {
  58. case "enable_fake_click":
  59. case "enable_order_summary_cache":
  60. case "enable_parse":
  61. case "enable_coupon":
  62. case "enable_sync_order":
  63. case "enable_promotionQuery":
  64. case "enable_deep_url":
  65. case "status":
  66. bool bVal = val.Equals("True");
  67. result = new DBContext.Table("tk_pool")
  68. .Add(name, bVal)
  69. .Add("last_time", DateTime.Now)
  70. .Where("id=@id", new { id })
  71. .Update();
  72. break;
  73. case "check_status":
  74. //检查状态
  75. var arr = EndPointCore.NotifyCheckDeepUrl(id);
  76. string suspended_endpoint = string.Empty;
  77. var log = new LoggerLibrary("check_suspended_endpoint");
  78. foreach ((string node, string message) in arr)
  79. {
  80. log.Info(node, message);
  81. if (message.Contains("霸下验证码"))
  82. {
  83. suspended_endpoint += $"{node},";
  84. }
  85. }
  86. result = new DBContext.Table("tk_pool")
  87. .Add("suspended_endpoint", suspended_endpoint)
  88. .Add("last_time", DateTime.Now)
  89. .Where("id=@id", new { id })
  90. .Update();
  91. log.SaveAsync();
  92. break;
  93. case "time_range":
  94. int.TryParse(val, out int iVal);
  95. result = new DBContext.Table("tk_pool")
  96. .Add(name, iVal)
  97. .Add("last_time", DateTime.Now)
  98. .Where("id=@id", new { id })
  99. .Update();
  100. break;
  101. default:
  102. return new APIResult(new { data = new { success = false, msg = "更新失败,未授权操作" } });
  103. }
  104. bool success = result > 0;
  105. if (success)
  106. {
  107. //string desc = ObjectComparer.PrintCompareToString(old, form).Trim();
  108. OperationLogCore.LogOperation(token.AccessKey, clientIp, $"tk_pool:{id}:{name}", string.Empty, val);
  109. await EndPointCore.NotifyReload(true);
  110. }
  111. return new APIResult(new
  112. {
  113. data = new { success, msg = success ? "更新成功" : "更新失败,请检查输入信息" },
  114. });
  115. }
  116. /// <summary>
  117. /// 账号列表
  118. /// </summary>
  119. /// <param name="form"></param>
  120. /// <returns></returns>
  121. [HttpPost]
  122. public async Task<ActionResult> list([FromBody] JsonElement form)
  123. {
  124. var token = provider.Get(_accessor.HttpContext);
  125. int page = form.Read("current", 1);
  126. int size = form.Read("pageSize", 10);
  127. string keyword = form.Read("name", string.Empty);
  128. bool getTotal = form.Read("getTotal", true);
  129. string _status = form.Read("status", string.Empty);
  130. int status = _status switch
  131. {
  132. "online" => 1,
  133. "offline" => 0,
  134. _ => -1,
  135. };
  136. var lastTime = form.PathReadArray<string>("lastTime[]");
  137. string sort = form.Read<string>("sort");
  138. string order = form.Read<string>("order");
  139. bool show_hide = form.Read("show_hide", false);
  140. string filter = string.Empty;
  141. if (!show_hide) filter = "is_hide=0";
  142. if (!string.IsNullOrEmpty(keyword))
  143. {
  144. filter += $" AND (`name` LIKE @keyword OR `description` LIKE @keyword)";
  145. keyword = $"%{keyword}%";
  146. }
  147. DateTime stime = DateTime.MinValue, etime = DateTime.MinValue;
  148. if (lastTime.Count == 2)
  149. {
  150. if (DateTime.TryParse(lastTime[0], out stime) && DateTime.TryParse(lastTime[1], out etime))
  151. {
  152. etime = etime.AddDays(1).AddSeconds(-1);
  153. filter += $" AND last_time BETWEEN @stime AND @etime";
  154. }
  155. }
  156. if (status != -1)
  157. {
  158. filter += $" AND status=@status";
  159. }
  160. filter = filter.StringTrimStart(" AND ");
  161. //排序
  162. string orderBy = "id DESC";
  163. if (!string.IsNullOrEmpty(order))
  164. {
  165. order = "descending".Equals(order) ? "DESC" : "ASC";
  166. orderBy = sort switch
  167. {
  168. //"num" => $"num {order}",
  169. _ => $"{sort} {order},ID DESC",
  170. };
  171. }
  172. using var conn = DBContext.GetOpenConnection();
  173. var result = new DBContext.Table(conn, "tk_pool")
  174. .Where(filter, new { keyword, status, stime, etime })
  175. .Page(size, page)
  176. .Order(orderBy)
  177. .PageList<TkPoolDTO>(getTotal);
  178. var proxyNodes = (ProxyNodesCore.AllList() ?? Array.Empty<ProxyNodesDTO>())
  179. .ToList();
  180. foreach (var item in result.List)
  181. {
  182. item.current_amt = Math.Round(RiskControlCore.GetIncomeAmt(TkChannelEnum.tb, $"{item.id}"), 2);
  183. item.cookies = string.Empty;
  184. //await RiskControlCore.SetRiskCookie($"tb:{item.id}", "TEST");
  185. item.riskCookie = RiskControlCore.GetRiskCookie($"tb:{item.id}");
  186. item.proxyStatus = proxyNodes
  187. .FirstOrDefault(proxyNode =>
  188. ProxyNodesCore.IsMatchNode(proxyNode, item.nodeName))
  189. ?.status;
  190. }
  191. return new APIResult(new { data = result });
  192. }
  193. [HttpPost]
  194. public async Task<ActionResult> report_dailys([FromBody] JsonElement form)
  195. {
  196. int page = form.Read("current", 1);
  197. int size = form.Read("pageSize", 10);
  198. bool getTotal = form.Read("getTotal", true);
  199. string sort = form.Read<string>("sort");
  200. string order = form.Read<string>("order");
  201. var report_date = form.PathReadArray<string>("query_date[]");
  202. string dailys_accountName = "all";
  203. int dailys_accountId = 0;
  204. string filter = string.Empty;
  205. DateTime stime = DateTime.MinValue, etime = DateTime.MinValue;
  206. if (report_date.Count == 2)
  207. {
  208. if (DateTime.TryParse(report_date[0], out stime) && DateTime.TryParse(report_date[1], out etime))
  209. {
  210. etime = etime.AddDays(1).AddSeconds(-1);
  211. filter += $" AND A.report_date BETWEEN @stime AND @etime";
  212. }
  213. }
  214. filter = filter.StringTrimStart(" AND ");
  215. //排序
  216. string orderBy = "A.report_date DESC";
  217. if (!string.IsNullOrEmpty(order))
  218. {
  219. order = "descending".Equals(order) ? "DESC" : "ASC";
  220. orderBy = sort switch
  221. {
  222. _ => $"A.{sort} {order}",
  223. };
  224. }
  225. var result = new DBContext.Table("v_tk_report_dailys")
  226. .LeftJoin("daily_logs",
  227. "B.log_date = A.report_date AND B.channel=0 AND B.accountId=@dailys_accountId",
  228. "total_count, B.abandon_count, B.success_count, B.abandon_percentage, B.success_percentage," +
  229. "B.parse_total_count, B.parse_abandon_count, B.parse_success_count, B.parse_abandon_percentage, B.parse_success_percentage," +
  230. "B.coupon_total_count, B.coupon_abandon_count, B.coupon_success_count, B.coupon_abandon_percentage, B.coupon_success_percentage," +
  231. "B.tool_total_count, B.tool_abandon_count, B.tool_success_count, B.tool_abandon_percentage, B.tool_success_percentage")
  232. .Where(filter, new { dailys_accountId, dailys_accountName, stime, etime })
  233. .Page(size, page)
  234. .Order(orderBy)
  235. .PageList<TkReportDTO>(getTotal);
  236. foreach (var item in result.List)
  237. {
  238. if (item.report_date.Date < DateTime.Now.Date) continue;
  239. if (item.total_count == 0)
  240. {
  241. item.total_count = await TkLogCore.GetTotalAsync($":total:tb:{item.report_date:yyyyMMdd}");
  242. if (item.total_count > 0)
  243. {
  244. item.success_count = await TkLogCore.GetTotalAsync($":total:tb:success:{item.report_date:yyyyMMdd}");
  245. item.abandon_count = await TkLogCore.GetTotalAsync($":total:tb:放弃转链:{item.report_date:yyyyMMdd}");
  246. if (item.total_count > 0)
  247. {
  248. item.success_percentage = $"{item.success_count / (double)item.total_count * 100:f2}%";
  249. item.abandon_percentage = $"{item.abandon_count / (double)item.total_count * 100:f2}%";
  250. }
  251. }
  252. }
  253. if (item.parse_total_count == 0)
  254. {
  255. item.parse_total_count = await TkLogCore.GetTotalAsync($":parse_total:tb:{item.report_date:yyyyMMdd}");
  256. if (item.parse_total_count > 0)
  257. {
  258. item.parse_success_count = await TkLogCore.GetTotalAsync($":parse_total:tb:success:{item.report_date:yyyyMMdd}");
  259. item.parse_abandon_count = await TkLogCore.GetTotalAsync($":parse_total:tb:放弃转链:{item.report_date:yyyyMMdd}");
  260. if (item.parse_total_count > 0)
  261. {
  262. item.parse_success_percentage = $"{item.parse_success_count / (double)item.parse_total_count * 100:f2}%";
  263. item.parse_abandon_percentage = $"{item.parse_abandon_count / (double)item.parse_total_count * 100:f2}%";
  264. }
  265. }
  266. }
  267. if (item.coupon_total_count == 0)
  268. {
  269. item.coupon_total_count = await TkLogCore.GetTotalAsync($":coupon_total:tb:{item.report_date:yyyyMMdd}", false);
  270. if (item.coupon_total_count > 0)
  271. {
  272. item.coupon_success_count = await TkLogCore.GetTotalAsync($":coupon_total:tb:success:{item.report_date:yyyyMMdd}", false);
  273. item.coupon_abandon_count = await TkLogCore.GetTotalAsync($":coupon_total:tb:放弃转链:{item.report_date:yyyyMMdd}", false);
  274. if (item.coupon_total_count > 0)
  275. {
  276. item.coupon_success_percentage = $"{item.coupon_success_count / (double)item.coupon_total_count * 100:f2}%";
  277. item.coupon_abandon_percentage = $"{item.coupon_abandon_count / (double)item.coupon_total_count * 100:f2}%";
  278. }
  279. }
  280. }
  281. if (item.tool_total_count == 0)
  282. {
  283. item.tool_total_count = await TkLogCore.GetTotalAsync($":parse_total:tool:{item.report_date:yyyyMMdd}");
  284. if (item.tool_total_count > 0)
  285. {
  286. item.tool_success_count = await TkLogCore.GetTotalAsync($":parse_total:tool:success:{item.report_date:yyyyMMdd}");
  287. item.tool_abandon_count = await TkLogCore.GetTotalAsync($":parse_total:tool:放弃转链:{item.report_date:yyyyMMdd}");
  288. if (item.tool_total_count > 0)
  289. {
  290. item.tool_success_percentage = $"{item.tool_success_count / (double)item.tool_total_count * 100:f2}%";
  291. item.tool_abandon_percentage = $"{item.tool_abandon_count / (double)item.tool_total_count * 100:f2}%";
  292. }
  293. }
  294. }
  295. }
  296. return new APIResult(new
  297. {
  298. data = result
  299. });
  300. }
  301. [HttpPost]
  302. public async Task<ActionResult> report_hourlys([FromBody] JsonElement form)
  303. {
  304. int page = form.Read("current", 1);
  305. int size = form.Read("pageSize", 10);
  306. bool getTotal = form.Read("getTotal", true);
  307. string sort = form.Read<string>("sort");
  308. string order = form.Read<string>("order");
  309. var report_date = form.PathReadArray<string>("query_date[]");
  310. var filterHours = form.Read<int?>("filterHours", null);
  311. string dailys_accountName = "all";
  312. int dailys_accountId = 0;
  313. string filter = string.Empty;
  314. DateTime stime = DateTime.MinValue, etime = DateTime.MinValue;
  315. if (report_date.Count == 2)
  316. {
  317. if (DateTime.TryParse(report_date[0], out stime) && DateTime.TryParse(report_date[1], out etime))
  318. {
  319. etime = etime.AddDays(1).AddSeconds(-1);
  320. filter += $" AND A.report_date BETWEEN @stime AND @etime";
  321. }
  322. }
  323. if (filterHours != null)
  324. {
  325. filterHours--;
  326. filter += $" AND HOUR(report_date) = @filterHours";
  327. }
  328. filter = filter.StringTrimStart(" AND ");
  329. //排序
  330. string orderBy = "A.report_date DESC";
  331. if (!string.IsNullOrEmpty(order))
  332. {
  333. order = "descending".Equals(order) ? "DESC" : "ASC";
  334. orderBy = sort switch
  335. {
  336. _ => $"A.{sort} {order}",
  337. };
  338. }
  339. var result = new DBContext.Table("v_tk_report_hourlys")
  340. .LeftJoin("daily_logs",
  341. "B.log_date = A.report_date AND B.channel=0 AND B.accountId=@dailys_accountId",
  342. "total_count, B.abandon_count, B.success_count, B.abandon_percentage, B.success_percentage," +
  343. "B.parse_total_count, B.parse_abandon_count, B.parse_success_count, B.parse_abandon_percentage, B.parse_success_percentage," +
  344. "B.coupon_total_count, B.coupon_abandon_count, B.coupon_success_count, B.coupon_abandon_percentage, B.coupon_success_percentage," +
  345. "B.tool_total_count, B.tool_abandon_count, B.tool_success_count, B.tool_abandon_percentage, B.tool_success_percentage")
  346. .Where(filter, new { dailys_accountId, dailys_accountName, filterHours, stime, etime })
  347. .Page(size, page)
  348. .Order(orderBy)
  349. .PageList<TkReportDTO>(getTotal);
  350. foreach (var item in result.List)
  351. {
  352. if (item.total_count == 0)
  353. {
  354. item.total_count = await TkLogCore.GetTotalAsync($":total:tb:{item.report_date:yyyyMMddHH}");
  355. if (item.total_count > 0)
  356. {
  357. item.success_count = await TkLogCore.GetTotalAsync($":total:tb:success:{item.report_date:yyyyMMddHH}");
  358. item.abandon_count = await TkLogCore.GetTotalAsync($":total:tb:放弃转链:{item.report_date:yyyyMMddHH}");
  359. if (item.total_count > 0)
  360. {
  361. item.success_percentage = $"{item.success_count / (double)item.total_count * 100:f2}%";
  362. item.abandon_percentage = $"{item.abandon_count / (double)item.total_count * 100:f2}%";
  363. }
  364. }
  365. }
  366. if (item.parse_total_count == 0)
  367. {
  368. item.parse_total_count = await TkLogCore.GetTotalAsync($":parse_total:tb:{item.report_date:yyyyMMddHH}");
  369. if (item.parse_total_count > 0)
  370. {
  371. item.parse_success_count = await TkLogCore.GetTotalAsync($":parse_total:tb:success:{item.report_date:yyyyMMddHH}");
  372. item.parse_abandon_count = await TkLogCore.GetTotalAsync($":parse_total:tb:放弃转链:{item.report_date:yyyyMMddHH}");
  373. if (item.parse_total_count > 0)
  374. {
  375. item.parse_success_percentage = $"{item.parse_success_count / (double)item.parse_total_count * 100:f2}%";
  376. item.parse_abandon_percentage = $"{item.parse_abandon_count / (double)item.parse_total_count * 100:f2}%";
  377. }
  378. }
  379. }
  380. if (item.coupon_total_count == 0)
  381. {
  382. item.coupon_total_count = await TkLogCore.GetTotalAsync($":coupon_total:tb:{item.report_date:yyyyMMddHH}", false);
  383. if (item.coupon_total_count > 0)
  384. {
  385. item.coupon_success_count = await TkLogCore.GetTotalAsync($":coupon_total:tb:success:{item.report_date:yyyyMMddHH}", false);
  386. item.coupon_abandon_count = await TkLogCore.GetTotalAsync($":coupon_total:tb:放弃转链:{item.report_date:yyyyMMddHH}", false);
  387. if (item.coupon_total_count > 0)
  388. {
  389. item.coupon_success_percentage = $"{item.coupon_success_count / (double)item.coupon_total_count * 100:f2}%";
  390. item.coupon_abandon_percentage = $"{item.coupon_abandon_count / (double)item.coupon_total_count * 100:f2}%";
  391. }
  392. }
  393. }
  394. if (item.tool_total_count == 0)
  395. {
  396. item.tool_total_count = await TkLogCore.GetTotalAsync($":parse_total:tool:{item.report_date:yyyyMMddHH}");
  397. if (item.tool_total_count > 0)
  398. {
  399. item.tool_success_count = await TkLogCore.GetTotalAsync($":parse_total:tool:success:{item.report_date:yyyyMMddHH}");
  400. item.tool_abandon_count = await TkLogCore.GetTotalAsync($":parse_total:tool:放弃转链:{item.report_date:yyyyMMddHH}");
  401. if (item.tool_total_count > 0)
  402. {
  403. item.tool_success_percentage = $"{item.tool_success_count / (double)item.tool_total_count * 100:f2}%";
  404. item.tool_abandon_percentage = $"{item.tool_abandon_count / (double)item.tool_total_count * 100:f2}%";
  405. }
  406. }
  407. }
  408. }
  409. return new APIResult(new
  410. {
  411. data = result
  412. });
  413. }
  414. [HttpPost]
  415. public async Task<ActionResult> report_list([FromBody] JsonElement form)
  416. {
  417. int page = form.Read("current", 1);
  418. int size = form.Read("pageSize", 10);
  419. bool getTotal = form.Read("getTotal", true);
  420. string sort = form.Read<string>("sort");
  421. string order = form.Read<string>("order");
  422. var report_date = form.PathReadArray<string>("query_date[]");
  423. string accountName = form.Read<string>("accountName");
  424. string filter = string.Empty;
  425. if (!string.IsNullOrEmpty(accountName))
  426. {
  427. filter += $" AND accountName=@accountName";
  428. }
  429. DateTime stime = DateTime.MinValue, etime = DateTime.MinValue;
  430. if (report_date.Count == 2)
  431. {
  432. if (DateTime.TryParse(report_date[0], out stime) && DateTime.TryParse(report_date[1], out etime))
  433. {
  434. etime = etime.AddDays(1).AddSeconds(-1);
  435. filter += $" AND report_date BETWEEN @stime AND @etime";
  436. }
  437. }
  438. filter = filter.StringTrimStart(" AND ");
  439. //排序
  440. string orderBy = "id DESC";
  441. if (!string.IsNullOrEmpty(order))
  442. {
  443. order = "descending".Equals(order) ? "DESC" : "ASC";
  444. orderBy = sort switch
  445. {
  446. _ => $"{sort} {order}",
  447. };
  448. }
  449. var result = new DBContext.Table("tk_report")
  450. .Where(filter, new { accountName, stime, etime })
  451. .Page(size, page)
  452. .Order(orderBy)
  453. .PageList<TkReportDTO>(getTotal);
  454. var tb_accounts = await TkPoolCore.AllListAsync();
  455. var tb_hide_ids = tb_accounts.Where(e => e.is_hide).Select(e => e.id).ToList();
  456. result.List = result.List.Where(e => !tb_hide_ids.Contains(e.accountId));
  457. foreach (var item in result.List)
  458. {
  459. #if DEBUG
  460. #else
  461. if (item.report_date.Date < DateTime.Now.Date) continue;
  462. #endif
  463. //var tk = TkPoolCore.GetOne(item.accountId);
  464. //if (tk != null) item.accountName = tk.company;
  465. string redisAccountName = $"{TkChannelEnum.tb}_{item.accountId}";
  466. if (item.total_count == 0)
  467. {
  468. string totalAccountName = redisAccountName;
  469. item.total_count = await TkLogCore.GetTotalAsync($":total:{totalAccountName}:{item.report_date:yyyyMMdd}");
  470. if (item.total_count == 0 && !string.Equals(item.accountName, totalAccountName, StringComparison.Ordinal))
  471. {
  472. //todo 过度用, 0613 跑两天就可以删掉
  473. totalAccountName = item.accountName;
  474. item.total_count = await TkLogCore.GetTotalAsync($":total:{totalAccountName}:{item.report_date:yyyyMMdd}");
  475. }
  476. if (item.total_count > 0)
  477. {
  478. item.success_count = await TkLogCore.GetTotalAsync($":total:{totalAccountName}:success:{item.report_date:yyyyMMdd}");
  479. item.abandon_count = await TkLogCore.GetTotalAsync($":total:{totalAccountName}:放弃转链:{item.report_date:yyyyMMdd}");
  480. if (item.total_count > 0)
  481. {
  482. item.success_percentage = $"{item.success_count / (double)item.total_count * 100:f2}%";
  483. item.abandon_percentage = $"{item.abandon_count / (double)item.total_count * 100:f2}%";
  484. }
  485. }
  486. }
  487. string parseAccountName = redisAccountName;
  488. int parseTotalCount = await TkLogCore.GetTotalAsync($":parse_total:{parseAccountName}:{item.report_date:yyyyMMdd}");
  489. if (parseTotalCount == 0 && !string.Equals(item.accountName, parseAccountName, StringComparison.Ordinal))
  490. {
  491. parseAccountName = item.accountName;
  492. parseTotalCount = await TkLogCore.GetTotalAsync($":parse_total:{parseAccountName}:{item.report_date:yyyyMMdd}");
  493. }
  494. // Today's DB row may be an earlier snapshot. Prefer the live Redis values
  495. // whenever they exist instead of only filling an initially-zero total.
  496. if (parseTotalCount > 0)
  497. {
  498. item.parse_total_count = parseTotalCount;
  499. item.parse_success_count = await TkLogCore.GetTotalAsync($":parse_total:{parseAccountName}:success:{item.report_date:yyyyMMdd}");
  500. item.parse_abandon_count = await TkLogCore.GetTotalAsync($":parse_total:{parseAccountName}:放弃转链:{item.report_date:yyyyMMdd}");
  501. item.parse_success_percentage = $"{item.parse_success_count / (double)item.parse_total_count * 100:f2}%";
  502. item.parse_abandon_percentage = $"{item.parse_abandon_count / (double)item.parse_total_count * 100:f2}%";
  503. }
  504. if (item.coupon_total_count == 0)
  505. {
  506. item.coupon_total_count = await TkLogCore.GetTotalAsync($":coupon_total:{redisAccountName}:{item.report_date:yyyyMMdd}", false);
  507. if (item.coupon_total_count > 0)
  508. {
  509. item.coupon_success_count = await TkLogCore.GetTotalAsync($":coupon_total:{redisAccountName}:success:{item.report_date:yyyyMMdd}", false);
  510. item.coupon_abandon_count = await TkLogCore.GetTotalAsync($":coupon_total:{redisAccountName}:放弃转链:{item.report_date:yyyyMMdd}", false);
  511. if (item.coupon_total_count > 0)
  512. {
  513. item.coupon_success_percentage = $"{item.coupon_success_count / (double)item.coupon_total_count * 100:f2}%";
  514. item.coupon_abandon_percentage = $"{item.coupon_abandon_count / (double)item.coupon_total_count * 100:f2}%";
  515. }
  516. }
  517. }
  518. if (item.tool_total_count == 0)
  519. {
  520. item.tool_total_count = await TkLogCore.GetTotalAsync($":parse_total:tool:{item.report_date:yyyyMMdd}");
  521. if (item.tool_total_count > 0)
  522. {
  523. item.tool_success_count = await TkLogCore.GetTotalAsync($":parse_total:tool:success:{item.report_date:yyyyMMdd}");
  524. item.tool_abandon_count = await TkLogCore.GetTotalAsync($":parse_total:tool:放弃转链:{item.report_date:yyyyMMdd}");
  525. if (item.tool_total_count > 0)
  526. {
  527. item.tool_success_percentage = $"{item.tool_success_count / (double)item.tool_total_count * 100:f2}%";
  528. item.tool_abandon_percentage = $"{item.tool_abandon_count / (double)item.tool_total_count * 100:f2}%";
  529. }
  530. }
  531. }
  532. }
  533. return new APIResult(new { data = result });
  534. }
  535. [HttpPost]
  536. public async Task<ActionResult> report_hourtrend([FromBody] JsonElement form)
  537. {
  538. int page = form.Read("current", 1);
  539. int size = form.Read("pageSize", 10);
  540. bool getTotal = form.Read("getTotal", true);
  541. string sort = form.Read<string>("sort");
  542. string order = form.Read<string>("order");
  543. var filterHours = form.Read<int?>("filterHours", null);
  544. string accountName = form.Read<string>("accountName");
  545. var report_date = form.PathReadArray<string>("query_date[]");
  546. int accountId = form.Read("accountId", 0);
  547. string filter = string.Empty;
  548. if (!string.IsNullOrEmpty(accountName))
  549. {
  550. filter += $" AND accountName=@accountName";
  551. }
  552. if (accountId != 0)
  553. {
  554. filter += $" AND accountId=@accountId";
  555. }
  556. DateTime stime = DateTime.MinValue, etime = DateTime.MinValue;
  557. if (report_date.Count == 2)
  558. {
  559. if (DateTime.TryParse(report_date[0], out stime) && DateTime.TryParse(report_date[1], out etime))
  560. {
  561. etime = etime.AddDays(1).AddSeconds(-1);
  562. if (etime > DateTime.Now) etime = DateTime.Now;
  563. filter += $" AND report_date BETWEEN @stime AND @etime";
  564. }
  565. }
  566. if (filterHours != null)
  567. {
  568. filterHours--;
  569. filter += $" AND HOUR(report_date) = @filterHours";
  570. }
  571. filter = filter.StringTrimStart(" AND ");
  572. //排序
  573. string orderBy = "id ASC";
  574. if (!string.IsNullOrEmpty(order))
  575. {
  576. order = "descending".Equals(order) ? "DESC" : "ASC";
  577. orderBy = sort switch
  578. {
  579. _ => $"{sort} {order}",
  580. };
  581. }
  582. using var conn = DBContext.GetOpenConnection();
  583. var result = new DBContext.Table(conn, "tk_report_hourtrend")
  584. .Where(filter, new { accountId, stime, etime, accountName, filterHours })
  585. .Page(size, page)
  586. .Order(orderBy)
  587. .PageList<TkReportDTO>(getTotal);
  588. foreach (var item in result.List)
  589. {
  590. #if DEBUG
  591. #else
  592. if (item.report_date.Date < DateTime.Now.Date) continue;
  593. #endif
  594. accountName = $"{TkChannelEnum.tb}_{item.accountId}";
  595. if (item.total_count == 0)
  596. {
  597. item.total_count = await TkLogCore.GetTotalAsync($":total:{accountName}:{item.report_date:yyyyMMddHH}");
  598. if (item.total_count == 0)
  599. {
  600. //todo 过度用, 0613 跑两天就可以删掉
  601. accountName = item.accountName;
  602. item.total_count = await TkLogCore.GetTotalAsync($":total:{accountName}:{item.report_date:yyyyMMddHH}");
  603. }
  604. if (item.total_count == 0) continue;
  605. item.success_count = await TkLogCore.GetTotalAsync($":total:{item.accountName}:success:{item.report_date:yyyyMMddHH}");
  606. item.abandon_count = await TkLogCore.GetTotalAsync($":total:{item.accountName}:放弃转链:{item.report_date:yyyyMMddHH}");
  607. if (item.total_count > 0)
  608. {
  609. item.success_percentage = $"{item.success_count / (double)item.total_count * 100:f2}%";
  610. item.abandon_percentage = $"{item.abandon_count / (double)item.total_count * 100:f2}%";
  611. }
  612. }
  613. if (item.parse_total_count == 0)
  614. {
  615. item.parse_total_count = await TkLogCore.GetTotalAsync($":parse_total:{accountName}:{item.report_date:yyyyMMddHH}");
  616. if (item.parse_total_count > 0)
  617. {
  618. item.parse_success_count = await TkLogCore.GetTotalAsync($":parse_total:{item.accountName}:success:{item.report_date:yyyyMMddHH}");
  619. item.parse_abandon_count = await TkLogCore.GetTotalAsync($":parse_total:{item.accountName}:放弃转链:{item.report_date:yyyyMMddHH}");
  620. if (item.parse_total_count > 0)
  621. {
  622. item.parse_success_percentage = $"{item.parse_success_count / (double)item.parse_total_count * 100:f2}%";
  623. item.parse_abandon_percentage = $"{item.parse_abandon_count / (double)item.parse_total_count * 100:f2}%";
  624. }
  625. }
  626. }
  627. if (item.coupon_total_count == 0)
  628. {
  629. item.coupon_total_count = await TkLogCore.GetTotalAsync($":coupon_total:{accountName}:{item.report_date:yyyyMMddHH}", false);
  630. if (item.coupon_total_count > 0)
  631. {
  632. item.coupon_success_count = await TkLogCore.GetTotalAsync($":coupon_total:{item.accountName}:success:{item.report_date:yyyyMMddHH}", false);
  633. item.coupon_abandon_count = await TkLogCore.GetTotalAsync($":coupon_total:{item.accountName}:放弃转链:{item.report_date:yyyyMMddHH}", false);
  634. if (item.coupon_total_count > 0)
  635. {
  636. item.coupon_success_percentage = $"{item.coupon_success_count / (double)item.coupon_total_count * 100:f2}%";
  637. item.coupon_abandon_percentage = $"{item.coupon_abandon_count / (double)item.coupon_total_count * 100:f2}%";
  638. }
  639. }
  640. }
  641. if (item.tool_total_count == 0)
  642. {
  643. item.tool_total_count = await TkLogCore.GetTotalAsync($":tool_total:{accountName}:{item.report_date:yyyyMMddHH}");
  644. if (item.tool_total_count > 0)
  645. {
  646. item.tool_success_count = await TkLogCore.GetTotalAsync($":tool_total:{item.accountName}:success:{item.report_date:yyyyMMddHH}");
  647. item.tool_abandon_count = await TkLogCore.GetTotalAsync($":tool_total:{item.accountName}:放弃转链:{item.report_date:yyyyMMddHH}");
  648. if (item.tool_total_count > 0)
  649. {
  650. item.tool_success_percentage = $"{item.tool_success_count / (double)item.tool_total_count * 100:f2}%";
  651. item.tool_abandon_percentage = $"{item.tool_abandon_count / (double)item.tool_total_count * 100:f2}%";
  652. }
  653. }
  654. }
  655. }
  656. return new APIResult(new { data = result });
  657. }
  658. [HttpPost]
  659. public async Task<ActionResult> chartData([FromBody] JsonElement form)
  660. {
  661. var result = new List<dynamic>();
  662. var reason_result = new List<dynamic>();
  663. var report_date = form.PathReadArray<string>("query_date[]");
  664. var accountName = form.Read("accountName", string.Empty);
  665. var isHourtrend = form.Read<bool>("isLeaf", false);
  666. var total_key = form.Read("total_key", "total");
  667. DateTime stime = DateTime.MinValue;
  668. if (!DateTime.TryParse(report_date[0], out stime)) return new APIResult(new { data = result, data2 = reason_result });
  669. string _report_date = stime.ToString("yyyyMMdd");
  670. if (isHourtrend) _report_date = stime.ToString("yyyyMMddHH");
  671. if (string.IsNullOrEmpty(accountName)) accountName = "tb";
  672. if (total_key == "tool_total")
  673. {
  674. accountName = "tool";
  675. total_key = "parse_total";
  676. string cacheKey = $":{total_key}:{accountName}:{_report_date}";
  677. double total = await TkLogCore.GetTotalAsync(cacheKey);
  678. if (total > 0)
  679. {
  680. string[] keys = ["bdpan", "wemeet"];
  681. foreach (var keyname in keys)
  682. {
  683. // string[] keys = ["bdpan:success", "bdpan:fail", "wemeet:success", "wemeet:fail"];
  684. cacheKey = $":{total_key}:{keyname}:{_report_date}";
  685. total = await TkLogCore.GetTotalAsync(cacheKey);
  686. cacheKey = $":{total_key}:{keyname}:success:{_report_date}";
  687. int value = await TkLogCore.GetTotalAsync(cacheKey);
  688. if (value == 0) continue;
  689. result.Add(new { name = $"{keyname}-成功", value, increases = Math.Round(value / total * 100, 2) });
  690. cacheKey = $":{total_key}:{keyname}:fail:{_report_date}";
  691. value = await TkLogCore.GetTotalAsync(cacheKey);
  692. if (value == 0) continue;
  693. result.Add(new { name = $"{keyname}-失败", value, increases = Math.Round(value / total * 100, 2) });
  694. }
  695. cacheKey = $":{total_key}:{accountName}:reason:{_report_date}";
  696. string[] reason_keys = await TkLogCore.GetTotalKeysAsync(cacheKey);
  697. foreach (var keyname in reason_keys)
  698. {
  699. cacheKey = $":{total_key}:{accountName}:{keyname}:{_report_date}";
  700. int value = await TkLogCore.GetTotalAsync(cacheKey);
  701. if (value == 0) continue;
  702. reason_result.Add(new { name = keyname, value, increases = Math.Round(value / total * 100, 2) });
  703. }
  704. reason_result = reason_result.OrderByDescending(item => item.value).ToList();
  705. }
  706. return new APIResult(new { total, data = result, data2 = reason_result });
  707. }
  708. else
  709. {
  710. string cacheKey = $":{total_key}:{accountName}:{_report_date}";
  711. double total = await TkLogCore.GetTotalAsync(cacheKey, false);
  712. if (total > 0)
  713. {
  714. string[] keys = ["success"];
  715. cacheKey = $":{total_key}:{accountName}:message:{_report_date}";
  716. string[] message_keys = await TkLogCore.GetTotalKeysAsync(cacheKey, false);
  717. var combinedKeys = keys.Union(message_keys).ToList();
  718. combinedKeys.RemoveAll(item => item == "fail");
  719. combinedKeys.RemoveAll(item => item == "OK");
  720. foreach (var keyname in combinedKeys)
  721. {
  722. cacheKey = $":{total_key}:{accountName}:{keyname}:{_report_date}";
  723. int value = await TkLogCore.GetTotalAsync(cacheKey, false);
  724. if (value == 0) continue;
  725. result.Add(new { name = keyname, value, increases = Math.Round(value / total * 100, 2) });
  726. }
  727. result = result.OrderByDescending(item => item.value).ToList();
  728. cacheKey = $":{total_key}:{accountName}:reason:{_report_date}";
  729. string[] reason_keys = await TkLogCore.GetTotalKeysAsync(cacheKey, false);
  730. foreach (var keyname in reason_keys)
  731. {
  732. if ("没有优惠券".Equals(keyname)) continue;
  733. cacheKey = $":{total_key}:{accountName}:{keyname}:{_report_date}";
  734. int value = await TkLogCore.GetTotalAsync(cacheKey, false);
  735. if (value < 50) continue;
  736. reason_result.Add(new { name = keyname, value, increases = Math.Round(value / total * 100, 2) });
  737. }
  738. reason_result = reason_result.OrderByDescending(item => item.value).ToList();
  739. }
  740. return new APIResult(new { total, data = result, data2 = reason_result });
  741. }
  742. }
  743. [HttpPost]
  744. public async Task<ActionResult> chartData2([FromBody] JsonElement form)
  745. {
  746. var result = new List<dynamic>();
  747. var reason_result = new List<dynamic>();
  748. var report_date = form.PathReadArray<string>("query_date[]");
  749. var accountName = form.Read("accountName", string.Empty);
  750. var isHourtrend = form.Read<bool>("isLeaf", false);
  751. var total_key = form.Read("total_key", "total");
  752. if (string.IsNullOrEmpty(accountName)) accountName = "tb";
  753. DateTime stime = DateTime.MinValue;
  754. if (!DateTime.TryParse(report_date[0], out stime)) return new APIResult(new { data = result, data2 = reason_result });
  755. string _report_date = stime.ToString("yyyyMMdd");
  756. if (isHourtrend) _report_date = stime.ToString("yyyyMMddHH");
  757. string cacheKey = $":{total_key}:{accountName}:{_report_date}";
  758. double total = await TkLogCore.GetTotalAsync(cacheKey);
  759. if (total > 0)
  760. {
  761. string[] keys = ["success"];
  762. cacheKey = $":{total_key}:{accountName}:message:{_report_date}";
  763. string[] message_keys = await TkLogCore.GetTotalKeysAsync(cacheKey);
  764. var combinedKeys = keys.Union(message_keys).ToList();
  765. combinedKeys.RemoveAll(item => item == "fail");
  766. combinedKeys.RemoveAll(item => item == "OK");
  767. foreach (var keyname in combinedKeys)
  768. {
  769. cacheKey = $":{total_key}:{accountName}:{keyname}:{_report_date}";
  770. int value = await TkLogCore.GetTotalAsync(cacheKey);
  771. if (value == 0) continue;
  772. result.Add(new { name = keyname, value, increases = Math.Round(value / total * 100, 2) });
  773. }
  774. result = result.OrderByDescending(item => item.value).ToList();
  775. cacheKey = $":{total_key}:{accountName}:reason:{_report_date}";
  776. string[] reason_keys = await TkLogCore.GetTotalKeysAsync(cacheKey);
  777. foreach (var keyname in reason_keys)
  778. {
  779. if ("没有优惠券".Equals(keyname)) continue;
  780. cacheKey = $":{total_key}:{accountName}:{keyname}:{_report_date}";
  781. int value = await TkLogCore.GetTotalAsync(cacheKey);
  782. if (value == 0) continue;
  783. reason_result.Add(new { name = keyname, value, increases = Math.Round(value / total * 100, 2) });
  784. }
  785. reason_result = reason_result.OrderByDescending(item => item.value).ToList();
  786. }
  787. return new APIResult(new { total, data = result, data2 = reason_result });
  788. }
  789. [HttpPost]
  790. public ActionResult settle_bills_total([FromBody] JsonElement form)
  791. {
  792. int page = form.Read("current", 1);
  793. int size = form.Read("pageSize", 10);
  794. bool getTotal = form.Read("getTotal", true);
  795. string sort = form.Read<string>("sort");
  796. string order = form.Read<string>("order");
  797. var belongTime = form.PathReadArray<string>("query_date[]");
  798. string filter = string.Empty;
  799. DateTime stime = DateTime.MinValue, etime = DateTime.MinValue;
  800. if (belongTime.Count == 2)
  801. {
  802. if (DateTime.TryParse(belongTime[0], out stime) && DateTime.TryParse(belongTime[1], out etime))
  803. {
  804. etime = etime.AddDays(1).AddSeconds(-1);
  805. filter += $" AND belongTime BETWEEN @stime AND @etime";
  806. }
  807. }
  808. filter = filter.StringTrimStart(" AND ");
  809. //排序
  810. string orderBy = "belongTime DESC";
  811. if (!string.IsNullOrEmpty(order))
  812. {
  813. order = "descending".Equals(order) ? "DESC" : "ASC";
  814. orderBy = sort switch
  815. {
  816. _ => $"{sort} {order}",
  817. };
  818. }
  819. var result = new DBContext.Table("v_tk_report_bills")
  820. .Where(filter, new { stime, etime })
  821. .Page(size, page)
  822. .Order(orderBy)
  823. .PageList<TkSettleBillDTO>(getTotal);
  824. return new APIResult(new { data = result });
  825. }
  826. [HttpPost]
  827. public ActionResult settle_bills([FromBody] JsonElement form)
  828. {
  829. int page = form.Read("current", 1);
  830. int size = form.Read("pageSize", 10);
  831. bool getTotal = form.Read("getTotal", true);
  832. string sort = form.Read<string>("sort");
  833. string order = form.Read<string>("order");
  834. string name = form.Read<string>("keyword");
  835. var belongTime = form.PathReadArray<string>("query_date[]");
  836. string filter = string.Empty;
  837. if (!string.IsNullOrEmpty(name))
  838. {
  839. filter += $" AND accountId IN (SELECT ID FROM tk_pool WHERE company=@name)";
  840. }
  841. DateTime stime = DateTime.MinValue, etime = DateTime.MinValue;
  842. if (belongTime.Count == 2)
  843. {
  844. if (DateTime.TryParse(belongTime[0], out stime) && DateTime.TryParse(belongTime[1], out etime))
  845. {
  846. etime = etime.AddDays(1).AddSeconds(-1);
  847. filter += $" AND belongTime BETWEEN @stime AND @etime";
  848. }
  849. }
  850. filter = filter.StringTrimStart(" AND ");
  851. //排序
  852. string orderBy = "belongTime DESC";
  853. if (!string.IsNullOrEmpty(order))
  854. {
  855. order = "descending".Equals(order) ? "DESC" : "ASC";
  856. orderBy = sort switch
  857. {
  858. _ => $"{sort} {order}",
  859. };
  860. }
  861. var result = new DBContext.Table("tk_settle_bill")
  862. .Where(filter, new { name, stime, etime })
  863. .Page(size, page)
  864. .Order(orderBy)
  865. .PageList<TkSettleBillDTO>(getTotal);
  866. //foreach (var item in result.List)
  867. //{
  868. // if (string.IsNullOrEmpty(name))
  869. // {
  870. // item.accountName = "-";
  871. // }
  872. //}
  873. return new APIResult(new { data = result });
  874. }
  875. }
  876. }