TaobaoController.cs 46 KB

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