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
|
{
|
/// <summary>
|
///
|
/// </summary>
|
///
|
[Route("openwize/[controller]/[action]")]
|
[Route(TopConstants.API_ROUTE, Order = 2)]
|
public class TopController : BaseController
|
{
|
/// <summary>
|
/// 短链接口
|
/// </summary>
|
private readonly ILkLinkService _lkLinkService;
|
|
/// <summary>
|
/// 短链访问记录接口
|
/// </summary>
|
private readonly ILkAccessHistoryService _lkAccessHistoryService;
|
|
/// <summary>
|
/// 短链访问统计接口
|
/// </summary>
|
private readonly ILkAccessStatisticService _lkAccessStatisticService;
|
|
/// <summary>
|
/// 映射
|
/// </summary>
|
private readonly IMapper _mapper;
|
|
/// <summary>
|
/// 缓存容器
|
/// </summary>
|
private readonly IEasyCachingProvider _provider;
|
|
/// <summary>
|
/// 构造函数
|
/// </summary>
|
/// <param name="mapper"></param>
|
/// <param name="provider"></param>
|
/// <param name="lkLkinkService"></param>
|
/// <param name="lkAccessHistoryService"></param>
|
/// <param name="lkAccessStatisticService"></param>
|
public TopController(IMapper mapper, IEasyCachingProvider provider, ILkLinkService lkLkinkService, ILkAccessHistoryService lkAccessHistoryService, ILkAccessStatisticService lkAccessStatisticService)
|
{
|
_mapper = mapper;
|
_provider = provider;
|
_lkLinkService = lkLkinkService;
|
_lkAccessHistoryService = lkAccessHistoryService;
|
_lkAccessStatisticService = lkAccessStatisticService;
|
}
|
|
/// <summary>
|
/// 申请生成短链
|
/// </summary>
|
/// <returns></returns>
|
[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<LkLink>().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);
|
}
|
|
/// <summary>
|
/// 申请生成短链-不验证URL
|
/// </summary>
|
/// <returns></returns>
|
[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<LkLink>().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);
|
}
|
|
/// <summary>
|
/// 分页查询访问记录
|
/// </summary>
|
/// <returns></returns>
|
[HttpPost]
|
[ProducesDefaultResponseType(typeof(ListPageGetAccessHistoryResponse))]
|
public IActionResult ListPageGetAccessHistory([FromBody]ListPageGetAccessHistoryRequest request)
|
{
|
var response = new ListPageGetAccessHistoryResponse();
|
var where = ExpressionUtil.Create<LkAccessHistory>().And(j => j.Key == request.Key)
|
.ToExpression();
|
|
int totalCount = 0;
|
response.AccessHistoryList = _lkAccessHistoryService.ListPageGet<AccessHistoryResponse>(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);
|
}
|
|
/// <summary>
|
/// 按创建时间范围查询访问统计
|
/// </summary>
|
/// <returns></returns>
|
[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<LkLink>().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<string>(j => j.Key, linkWhere);
|
|
if (keyList.Count == 0)
|
{
|
return Error("时间范围内未生成短码");
|
}
|
|
var statisticWhere = ExpressionUtil.Create<LkAccessStatistic>().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);
|
}
|
|
/// <summary>
|
/// 指定短码查询访问统计
|
/// </summary>
|
/// <returns></returns>
|
[HttpPost]
|
[ProducesDefaultResponseType(typeof(StatisticResponse))]
|
public IActionResult GetAccessStatistic([FromBody]GetAccessStatisticRequest request)
|
{
|
var result = TryGetInMemory(request.Key, () =>
|
{
|
var statisticWhere = ExpressionUtil.Create<LkAccessStatistic>().And(j => j.Key == request.Key)
|
.ToExpression();
|
return _lkAccessStatisticService.GetFirst(statisticWhere);
|
});
|
|
if (result.IsNull())
|
{
|
return Error("短码不存在");
|
}
|
|
var response = _mapper.Map<LkAccessStatistic, StatisticResponse>(result);
|
|
return Success(response);
|
}
|
|
/// <summary>
|
/// 尝试从内存中获取,若没有则从委托中获取
|
/// </summary>
|
/// <typeparam name="T"></typeparam>
|
/// <param name="t"></param>
|
/// <param name="cacheKey"></param>
|
/// <param name="expireTime"></param>
|
/// <returns></returns>
|
private bool TrySetInMemory<T>(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;
|
}
|
|
/// <summary>
|
/// 尝试从内存中获取,若没有则从委托中获取
|
/// </summary>
|
/// <typeparam name="T"></typeparam>
|
/// <param name="cacheKey"></param>
|
/// <param name="func"></param>
|
/// <returns></returns>
|
private T TryGetInMemory<T>(string cacheKey, Func<T> func)
|
{
|
string key = $"LINK_{cacheKey}";
|
T t = default(T);
|
|
if (!_provider.Exists(key))
|
{
|
t = func.Invoke();
|
|
return t;
|
}
|
|
CacheValue<T> cacheResult = _provider.Get<T>(key);
|
|
if (cacheResult.HasValue && !cacheResult.IsNull)
|
{
|
LogUtil.Trace($"{key}缓存中:{ cacheResult.Value.ObjectToJson()}");
|
return cacheResult.Value;
|
}
|
|
t = func.Invoke();
|
|
return t;
|
}
|
|
/// <summary>
|
/// 根据日期设备统计发送量
|
/// </summary>
|
/// <returns></returns>
|
[HttpPost]
|
[ProducesDefaultResponseType(typeof(List<GetEquipmentStatisticResponse>))]
|
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<dynamic>(sql);
|
|
return Success(st);
|
}
|
|
/// <summary>
|
/// 根据日期设备统计pvuv
|
/// </summary>
|
/// <returns></returns>
|
[HttpPost]
|
[ProducesDefaultResponseType(typeof(List<GetEquipmentStatisticResponse>))]
|
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<dynamic>(pvuvsql);
|
List<GePvUvStatisticResponse> resarr = JSONUtil.JsonToObject<List<GePvUvStatisticResponse>>(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<dynamic>(phonecountsql);
|
res.phoneCount = (JSONUtil.JsonToObject<JArray>(JSONUtil.ObjectToJson(st)))[0]["count"].ToString();
|
return Success(res);
|
}
|
|
/// <summary>
|
/// 根据时间,key统计pvuv
|
/// </summary>
|
/// <returns></returns>
|
[HttpPost]
|
[ProducesDefaultResponseType(typeof(List<GetEquipmentStatisticResponse>))]
|
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<dynamic>(pvuvsql);
|
List<GePvUvByTimeResponse> resarr = JSONUtil.JsonToObject<List<GePvUvByTimeResponse>>(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;
|
}
|
}
|
}
|