using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using AutoMapper; using CommonUtil; using EasyCaching.Core; using Link.Api.Models; using Link.IService; using Microsoft.AspNetCore.Mvc; using Link.DbModel; using Link.Common; using Newtonsoft.Json.Linq; namespace Link.Api.Controllers { /// /// /// /// [Route("openwize/[controller]/[action]")] [Route(TopConstants.API_ROUTE, Order = 2)] public class TopController : BaseController { /// /// 短链接口 /// private readonly ILkLinkService _lkLinkService; /// /// 短链访问记录接口 /// private readonly ILkAccessHistoryService _lkAccessHistoryService; /// /// 短链访问统计接口 /// private readonly ILkAccessStatisticService _lkAccessStatisticService; /// /// 映射 /// private readonly IMapper _mapper; /// /// 缓存容器 /// private readonly IEasyCachingProvider _provider; /// /// 构造函数 /// /// /// /// /// /// public TopController(IMapper mapper, IEasyCachingProvider provider, ILkLinkService lkLkinkService, ILkAccessHistoryService lkAccessHistoryService, ILkAccessStatisticService lkAccessStatisticService) { _mapper = mapper; _provider = provider; _lkLinkService = lkLkinkService; _lkAccessHistoryService = lkAccessHistoryService; _lkAccessStatisticService = lkAccessStatisticService; } /// /// 申请生成短链 /// /// [HttpPost] [ProducesDefaultResponseType(typeof(TopResponse))] public IActionResult Execute([FromBody]TopRequest request) { TopResponse response = new TopResponse(); string linkKeyName = $"{request.AppName}_{request.Nick}_{request.Url}"; var link = TryGetInMemory(linkKeyName, () => { var existWhere = ExpressionUtil.Create().And(j => j.OriginUrl == request.Url) .And(j => j.AppName == request.AppName) .And(j => j.Nick == request.Nick) .And(j => j.ExpireTime >= DateTime.Now) .And(j => j.IsDelete == 0) .ToExpression(); return _lkLinkService.GetFirst(existWhere); }); if (!link.IsNull() && request.AppName != "mjy") { response.Key = link.Key; response.ShortUrl = link.ShortUrl; response.ExpireTime = link.ExpireTime; return Success(response); } LkLink linkDTO = new LkLink { CreateTime = DateTime.Now, IsDelete = 0, OriginUrl = request.Url, Key = string.Empty, ShortUrl = string.Empty, AppName = request.AppName, Nick = request.Nick, }; DateTime now = DateTime.Now; DateTime expireTime = now.AddMonths(1); var result = _lkLinkService.UseTran(() => { var entity = _lkLinkService.InsertReturnEntity(linkDTO); string key = LinkUtil.MixValueConvertTo64(entity.Id); string shortUrl = ConfigUtil.Configuration["ShortUrl"]; shortUrl += $"/{key}"; LkAccessStatistic statistic = new LkAccessStatistic { CreateTime = DateTime.Now, Key = key, Pv = 0, Uv = 0, }; _lkAccessStatisticService.Insert(statistic); _lkLinkService.Update(j => new LkLink { Key = key, ShortUrl = shortUrl, UpdateTime = now, ExpireTime = expireTime }, j => j.Id == entity.Id); linkDTO.Key = key; linkDTO.ShortUrl = shortUrl; linkDTO.UpdateTime = now; linkDTO.ExpireTime = expireTime; response.Key = key; response.ShortUrl = shortUrl; response.ExpireTime = expireTime; }); if (!result.IsSuccess) { return Error(result.ErrorMessage); } //插入短码缓存 TrySetInMemory(linkDTO, linkDTO.Key, expireTime); //插入长转短记录缓存 TrySetInMemory(linkDTO, linkKeyName, expireTime); return Success(response); } /// /// 申请生成短链-不验证URL /// /// [HttpPost] [ProducesDefaultResponseType(typeof(TopResponse))] public IActionResult SpExecute([FromBody]SpTopRequest request) { TopResponse response = new TopResponse(); string linkKeyName = $"{request.AppName}_{request.Nick}_{request.Url}"; var link = TryGetInMemory(linkKeyName, () => { var existWhere = ExpressionUtil.Create().And(j => j.OriginUrl == request.Url) .And(j => j.AppName == request.AppName) .And(j => j.Nick == request.Nick) .And(j => j.ExpireTime >= DateTime.Now) .And(j => j.IsDelete == 0) .ToExpression(); return _lkLinkService.GetFirst(existWhere); }); if (!link.IsNull() && request.AppName != "mjy") { response.Key = link.Key; response.ShortUrl = link.ShortUrl; response.ExpireTime = link.ExpireTime; return Success(response); } LkLink linkDTO = new LkLink { CreateTime = DateTime.Now, IsDelete = 0, OriginUrl = request.Url, Key = string.Empty, ShortUrl = string.Empty, AppName = request.AppName, Nick = request.Nick, }; DateTime now = DateTime.Now; DateTime expireTime = now.AddMonths(1); var result = _lkLinkService.UseTran(() => { var entity = _lkLinkService.InsertReturnEntity(linkDTO); string key = LinkUtil.MixValueConvertTo64(entity.Id); string shortUrl = ConfigUtil.Configuration["ShortUrl"]; shortUrl += $"/{key}"; LkAccessStatistic statistic = new LkAccessStatistic { CreateTime = DateTime.Now, Key = key, Pv = 0, Uv = 0, }; _lkAccessStatisticService.Insert(statistic); _lkLinkService.Update(j => new LkLink { Key = key, ShortUrl = shortUrl, UpdateTime = now, ExpireTime = expireTime }, j => j.Id == entity.Id); linkDTO.Key = key; linkDTO.ShortUrl = shortUrl; linkDTO.UpdateTime = now; linkDTO.ExpireTime = expireTime; response.Key = key; response.ShortUrl = shortUrl; response.ExpireTime = expireTime; }); if (!result.IsSuccess) { return Error(result.ErrorMessage); } //插入短码缓存 TrySetInMemory(linkDTO, linkDTO.Key, expireTime); //插入长转短记录缓存 TrySetInMemory(linkDTO, linkKeyName, expireTime); return Success(response); } /// /// 分页查询访问记录 /// /// [HttpPost] [ProducesDefaultResponseType(typeof(ListPageGetAccessHistoryResponse))] public IActionResult ListPageGetAccessHistory([FromBody]ListPageGetAccessHistoryRequest request) { var response = new ListPageGetAccessHistoryResponse(); var where = ExpressionUtil.Create().And(j => j.Key == request.Key) .ToExpression(); int totalCount = 0; response.AccessHistoryList = _lkAccessHistoryService.ListPageGet(j => new AccessHistoryResponse { CreateTime = j.CreateTime, Ip = j.Ip, EquipmentCode = j.EquipmentCode, EquipmentName = j.EquipmentName, Nick = j.Nick }, where, j => j.CreateTime, DbEnum.OrderType.Desc, request.CurrentPage, request.PageSize, ref totalCount); return Success(response, request.CurrentPage, request.PageSize, totalCount); } /// /// 按创建时间范围查询访问统计 /// /// [HttpPost] [ProducesDefaultResponseType(typeof(ListGetAccessStatisticRangeResponse))] public IActionResult ListGetAccessStatisticRange([FromBody]ListGetAccessStatisticRangeRequest request) { if (request.MaxCreateTime.HasValue && request.MinCreateTime.HasValue && request.MinCreateTime.Value > request.MaxCreateTime.Value) { return Error("时间范围不正确"); } var response = new ListGetAccessStatisticRangeResponse(); var linkWhere = ExpressionUtil.Create().And(j => j.AppName == request.AppName) .And(j => j.Nick == request.Nick) .And(j => j.IsDelete == 0) .AndIF(request.MinCreateTime.HasValue, j => j.CreateTime >= request.MinCreateTime.Value) .AndIF(request.MaxCreateTime.HasValue, j => j.CreateTime <= request.MaxCreateTime.Value) .ToExpression(); var keyList = _lkLinkService.ListGet(j => j.Key, linkWhere); if (keyList.Count == 0) { return Error("时间范围内未生成短码"); } var statisticWhere = ExpressionUtil.Create().And(j => keyList.Contains(j.Key)) .ToExpression(); response.StatisticList = _lkAccessStatisticService.ListGet(j => new StatisticResponse { Key = j.Key, Pv = j.Pv, Uv = j.Uv }, statisticWhere); return Success(response); } /// /// 指定短码查询访问统计 /// /// [HttpPost] [ProducesDefaultResponseType(typeof(StatisticResponse))] public IActionResult GetAccessStatistic([FromBody]GetAccessStatisticRequest request) { var result = TryGetInMemory(request.Key, () => { var statisticWhere = ExpressionUtil.Create().And(j => j.Key == request.Key) .ToExpression(); return _lkAccessStatisticService.GetFirst(statisticWhere); }); if (result.IsNull()) { return Error("短码不存在"); } var response = _mapper.Map(result); return Success(response); } /// /// 尝试从内存中获取,若没有则从委托中获取 /// /// /// /// /// /// private bool TrySetInMemory(T t, string cacheKey, DateTime expireTime) { string key = $"LINK_{cacheKey}"; TimeSpan expiration = expireTime.Subtract(DateTime.Now); _provider.Remove(key); _provider.Set(key, t, expiration); return true; } /// /// 尝试从内存中获取,若没有则从委托中获取 /// /// /// /// /// private T TryGetInMemory(string cacheKey, Func func) { string key = $"LINK_{cacheKey}"; T t = default(T); if (!_provider.Exists(key)) { t = func.Invoke(); return t; } CacheValue cacheResult = _provider.Get(key); if (cacheResult.HasValue && !cacheResult.IsNull) { LogUtil.Trace($"{key}缓存中:{ cacheResult.Value.ObjectToJson()}"); return cacheResult.Value; } t = func.Invoke(); return t; } /// /// 根据日期设备统计发送量 /// /// [HttpPost] [ProducesDefaultResponseType(typeof(List))] public IActionResult GetEquipmentStatistic([FromBody]GetEquipmentStatisticRequest request) { string sql = $"SELECT count(1) as count,equipment_name from lk_access_history where nick='{request.Nick}'"; sql += GetWhere(request); sql += " GROUP BY equipment_name "; var st = _lkAccessHistoryService.SqlQuery(sql); return Success(st); } /// /// 根据日期设备统计pvuv /// /// [HttpPost] [ProducesDefaultResponseType(typeof(List))] public IActionResult GePvUvStatistic([FromBody]GetEquipmentStatisticRequest request) { string pvuvsql = $"SELECT count(1) as pv,count(DISTINCT(ip)) as uv from lk_access_history where nick='{request.Nick}' { GetWhere(request)} "; var st = _lkAccessHistoryService.SqlQuery(pvuvsql); List resarr = JSONUtil.JsonToObject>(JSONUtil.ObjectToJson(st)); GePvUvStatisticResponse res = resarr[0]; string phonecountsql = $"SELECT count(1) as count from lk_access_history where nick='{request.Nick}' { GetWhere(request)} and equipment_code in ('huawei','samsung','iphone','mi') "; st = _lkAccessHistoryService.SqlQuery(phonecountsql); res.phoneCount = (JSONUtil.JsonToObject(JSONUtil.ObjectToJson(st)))[0]["count"].ToString(); return Success(res); } /// /// 根据时间,key统计pvuv /// /// [HttpPost] [ProducesDefaultResponseType(typeof(List))] public IActionResult GePvUvByKey([FromBody] GePvUvByTimeRequest request) { string pvuvsql = $"SELECT count(1) as pv,count(DISTINCT(ip)) as uv from lk_access_history where `key`='{request.Key}' { GetPvUvWhere(request)} "; var st = _lkAccessHistoryService.SqlQuery(pvuvsql); List resarr = JSONUtil.JsonToObject>(JSONUtil.ObjectToJson(st)); GePvUvByTimeResponse res = resarr.FirstOrDefault(); StatisticResponse statisticResponse = new StatisticResponse() { Key = request.Key, Pv = res.pv.ToLong(), Uv = res.uv.ToLong() }; return Success(statisticResponse); } private string GetWhere(GetEquipmentStatisticRequest request) { string sql = string.Empty; if (!request.MinCreateTime.IsNull()) { sql += $" and create_time>='{((DateTime)request.MinCreateTime).ToString("yyyy-MM-dd HH:mm:ss")}' "; } if (!request.MaxCreateTime.IsNull()) { sql += $" and create_time<='{((DateTime)request.MaxCreateTime).ToString("yyyy-MM-dd HH:mm:ss")}' "; } if (!request.Key.IsNullOrEmpty()) { sql += $" and key='{request.Key}' "; } return sql; } private string GetPvUvWhere(GePvUvByTimeRequest request) { string sql = string.Empty; if (!request.MinCreateTime.IsNull()) { sql += $" and create_time>='{((DateTime)request.MinCreateTime).ToString("yyyy-MM-dd HH:mm:ss")}' "; } if (!request.MaxCreateTime.IsNull()) { sql += $" and create_time<='{((DateTime)request.MaxCreateTime).ToString("yyyy-MM-dd HH:mm:ss")}' "; } if (!request.Nick.IsNullOrEmpty()) { sql += $" and nick='{request.Nick}' "; } return sql; } } }