TaobaoController.cs 45 KB

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