1
0

AdvertisementController.cs 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. using AutoMapper.QueryableExtensions;
  2. using Masuit.MyBlogs.Core.Common;
  3. using Masuit.MyBlogs.Core.Extensions;
  4. using Masuit.MyBlogs.Core.Infrastructure.Services.Interface;
  5. using Masuit.MyBlogs.Core.Models.DTO;
  6. using Masuit.MyBlogs.Core.Models.Entity;
  7. using Masuit.MyBlogs.Core.Models.Enum;
  8. using Masuit.MyBlogs.Core.Models.ViewModel;
  9. using Masuit.Tools.Core.Net;
  10. using Masuit.Tools.Linq;
  11. using Masuit.Tools.Models;
  12. using Microsoft.AspNetCore.Mvc;
  13. using Microsoft.EntityFrameworkCore;
  14. using Microsoft.Net.Http.Headers;
  15. using System.ComponentModel.DataAnnotations;
  16. using System.Linq.Expressions;
  17. using System.Net;
  18. using System.Text.RegularExpressions;
  19. using EFCoreSecondLevelCacheInterceptor;
  20. namespace Masuit.MyBlogs.Core.Controllers
  21. {
  22. [Route("partner/[action]")]
  23. public class AdvertisementController : BaseController
  24. {
  25. public IAdvertisementClickRecordService ClickRecordService { get; set; }
  26. /// <summary>
  27. /// 前往
  28. /// </summary>
  29. /// <param name="id">广告id</param>
  30. /// <returns></returns>
  31. [HttpGet("/p{id:int}"), HttpGet("{id:int}", Order = 1), ResponseCache(Duration = 3600)]
  32. public async Task<IActionResult> Redirect(int id)
  33. {
  34. var ad = await AdsService.GetByIdAsync(id) ?? throw new NotFoundException("推广链接不存在");
  35. if (!Request.IsRobot() && string.IsNullOrEmpty(HttpContext.Session.Get<string>("ads" + id)))
  36. {
  37. HttpContext.Session.Set("ads" + id, id.ToString());
  38. ad.ClickRecords.Add(new AdvertisementClickRecord()
  39. {
  40. IP = ClientIP,
  41. Location = ClientIP.GetIPLocation(),
  42. Referer = Request.Headers[HeaderNames.Referer].ToString(),
  43. Time = DateTime.Now
  44. });
  45. await AdsService.SaveChangesAsync();
  46. var start = DateTime.Today.AddMonths(-1);
  47. await ClickRecordService.GetQuery(a => a.Time < start).DeleteFromQueryAsync();
  48. }
  49. return Redirect(ad.Url);
  50. }
  51. /// <summary>
  52. /// 获取分页
  53. /// </summary>
  54. /// <returns></returns>
  55. [MyAuthorize]
  56. public async Task<ActionResult> GetPageData([FromServices] ICategoryService categoryService, [Range(1, int.MaxValue, ErrorMessage = "页数必须大于0")] int page = 1, [Range(1, int.MaxValue, ErrorMessage = "页大小必须大于0")] int size = 10, string kw = "")
  57. {
  58. Expression<Func<Advertisement, bool>> where = p => true;
  59. if (!string.IsNullOrEmpty(kw))
  60. {
  61. where = where.And(p => p.Title.Contains(kw) || p.Description.Contains(kw) || p.Url.Contains(kw));
  62. }
  63. var list = AdsService.GetQuery(where).OrderByDescending(p => p.Status == Status.Available).ThenByDescending(a => a.Price).ProjectTo<AdvertisementViewModel>(MapperConfig).NotCacheable().ToPagedList(page, size);
  64. var cids = list.Data.Where(m => !string.IsNullOrEmpty(m.CategoryIds)).SelectMany(m => m.CategoryIds.Split(",", StringSplitOptions.RemoveEmptyEntries).Select(int.Parse)).Distinct().ToArray();
  65. var dic = await categoryService.GetQuery(c => cids.Contains(c.Id)).ToDictionaryAsync(c => c.Id + "", c => c.Name);
  66. foreach (var ad in list.Data.Where(ad => !string.IsNullOrEmpty(ad.CategoryIds)))
  67. {
  68. ad.CategoryNames = JiebaNet.Segmenter.Common.Extensions.Join(ad.CategoryIds.Split(",").Select(c => dic.GetValueOrDefault(c)), ",");
  69. }
  70. return Ok(list);
  71. }
  72. /// <summary>
  73. /// 保存广告
  74. /// </summary>
  75. /// <param name="model"></param>
  76. /// <returns></returns>
  77. [HttpPost, MyAuthorize]
  78. public async Task<IActionResult> Save(AdvertisementDto model)
  79. {
  80. var entity = AdsService[model.Id] ?? new Advertisement();
  81. model.CategoryIds = model.CategoryIds?.Replace("null", "");
  82. model.Regions = Regex.Replace(model.Regions ?? "", @"(\p{P}|\p{Z}|\p{S})+", "|");
  83. if (model.RegionMode == RegionLimitMode.All)
  84. {
  85. model.Regions = null;
  86. }
  87. if (model.Types.Contains(AdvertiseType.Banner.ToString("D")) && string.IsNullOrEmpty(model.ImageUrl))
  88. {
  89. return ResultData(null, false, "宣传大图不能为空");
  90. }
  91. if (model.Types.Length > 3 && string.IsNullOrEmpty(model.ThumbImgUrl))
  92. {
  93. return ResultData(null, false, "宣传小图不能为空");
  94. }
  95. Mapper.Map(model, entity);
  96. var b = await AdsService.AddOrUpdateSavedAsync(a => a.Id, entity) > 0;
  97. return ResultData(null, b, b ? "保存成功" : "保存失败");
  98. }
  99. /// <summary>
  100. /// 删除广告
  101. /// </summary>
  102. /// <param name="id"></param>
  103. /// <returns></returns>
  104. [HttpPost("{id}"), HttpGet("{id}"), MyAuthorize]
  105. public async Task<IActionResult> Delete(int id)
  106. {
  107. bool b = await AdsService.DeleteByIdAsync(id) > 0;
  108. return ResultData(null, b, b ? "删除成功" : "删除失败");
  109. }
  110. /// <summary>
  111. /// 广告上下架
  112. /// </summary>
  113. /// <param name="id">文章id</param>
  114. /// <returns></returns>
  115. [MyAuthorize, HttpPost("{id}")]
  116. public async Task<ActionResult> ChangeState(int id)
  117. {
  118. var ad = await AdsService.GetByIdAsync(id) ?? throw new NotFoundException("广告不存在!");
  119. ad.Status = ad.Status == Status.Available ? Status.Unavailable : Status.Available;
  120. return ResultData(null, await AdsService.SaveChangesAsync() > 0, ad.Status == Status.Available ? $"【{ad.Title}】已上架!" : $"【{ad.Title}】已下架!");
  121. }
  122. /// <summary>
  123. /// 随机前往一个广告
  124. /// </summary>
  125. /// <returns></returns>
  126. [HttpGet("/partner-random")]
  127. public async Task<ActionResult> RandomGo()
  128. {
  129. var ad = AdsService.GetByWeightedPrice((AdvertiseType)new Random().Next(1, 4), Request.Location());
  130. if (!Request.IsRobot() && string.IsNullOrEmpty(HttpContext.Session.Get<string>("ads" + ad.Id)))
  131. {
  132. HttpContext.Session.Set("ads" + ad.Id, ad.Id.ToString());
  133. ad.ClickRecords.Add(new AdvertisementClickRecord()
  134. {
  135. IP = ClientIP,
  136. Location = ClientIP.GetIPLocation(),
  137. Referer = Request.Headers[HeaderNames.Referer].ToString(),
  138. Time = DateTime.Now
  139. });
  140. await AdsService.SaveChangesAsync();
  141. var start = DateTime.Today.AddMonths(-1);
  142. await ClickRecordService.GetQuery(a => a.Time < start).DeleteFromQueryAsync();
  143. }
  144. return Redirect(ad.Url);
  145. }
  146. /// <summary>
  147. /// 广告访问记录
  148. /// </summary>
  149. /// <param name="id"></param>
  150. /// <param name="page"></param>
  151. /// <param name="size"></param>
  152. /// <returns></returns>
  153. [HttpGet("/partner/{id}/records"), MyAuthorize]
  154. public async Task<IActionResult> ClickRecords(int id, int page = 1, int size = 15, string kw = "")
  155. {
  156. Expression<Func<AdvertisementClickRecord, bool>> where = e => e.AdvertisementId == id;
  157. if (!string.IsNullOrEmpty(kw))
  158. {
  159. kw = Regex.Escape(kw);
  160. where = where.And(e => Regex.IsMatch(e.IP + e.Location + e.Referer, kw));
  161. }
  162. var pages = await ClickRecordService.GetPagesAsync<DateTime, AdvertisementClickRecordViewModel>(page, size, where, e => e.Time, false);
  163. return Ok(pages);
  164. }
  165. /// <summary>
  166. /// 广告访问记录图表
  167. /// </summary>
  168. /// <param name="id"></param>
  169. /// <param name="cancellationToken"></param>
  170. /// <returns></returns>
  171. [HttpGet("/partner/{id}/records-chart"), MyAuthorize]
  172. [ProducesResponseType((int)HttpStatusCode.OK)]
  173. public async Task<IActionResult> ClickRecordsChart(int id, CancellationToken cancellationToken)
  174. {
  175. var list = await ClickRecordService.GetQuery(e => e.AdvertisementId == id, e => e.Time).Select(e => e.Time).GroupBy(t => t.Date).Select(g => new
  176. {
  177. Date = g.Key,
  178. Count = g.Count()
  179. }).ToListAsync(cancellationToken);
  180. return Ok(list);
  181. }
  182. /// <summary>
  183. /// 广告访问记录分析
  184. /// </summary>
  185. /// <param name="id"></param>
  186. /// <returns></returns>
  187. [HttpGet("/partner/{id}/insight"), MyAuthorize]
  188. public IActionResult ClickRecordsInsight(int id)
  189. {
  190. return View(AdsService[id]);
  191. }
  192. }
  193. }