99 lines
3.2 KiB
C#
99 lines
3.2 KiB
C#
using AssetManager.Data;
|
||
using AssetManager.Models;
|
||
using Microsoft.AspNetCore.Authorization;
|
||
using Microsoft.AspNetCore.Mvc;
|
||
using Microsoft.Extensions.Logging;
|
||
using SqlSugar;
|
||
|
||
namespace AssetManager.API.Controllers;
|
||
|
||
/// <summary>
|
||
/// 股票代码查询接口
|
||
/// </summary>
|
||
[ApiController]
|
||
[Route("api/v1/ticker")]
|
||
[Authorize]
|
||
public class TickerController : ControllerBase
|
||
{
|
||
private readonly ILogger<TickerController> _logger;
|
||
private readonly ISqlSugarClient _db;
|
||
|
||
public TickerController(ILogger<TickerController> logger, ISqlSugarClient db)
|
||
{
|
||
_logger = logger;
|
||
_db = db;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 模糊搜索股票代码
|
||
/// </summary>
|
||
/// <param name="keyword">搜索关键词(ticker 或 exchange)</param>
|
||
/// <param name="limit">返回数量上限(默认 20)</param>
|
||
/// <returns>匹配的股票代码列表</returns>
|
||
[HttpGet("search")]
|
||
public async Task<ActionResult<ApiResponse<List<TickerSearchResult>>>> SearchTicker(
|
||
[FromQuery] string keyword,
|
||
[FromQuery] int limit = 20)
|
||
{
|
||
try
|
||
{
|
||
_logger.LogInformation($"Search ticker with keyword: {keyword}, limit: {limit}");
|
||
|
||
if (string.IsNullOrWhiteSpace(keyword))
|
||
{
|
||
return Ok(new ApiResponse<List<TickerSearchResult>>
|
||
{
|
||
code = AssetManager.Models.StatusCodes.Success,
|
||
data = new List<TickerSearchResult>(),
|
||
message = "Keyword is empty"
|
||
});
|
||
}
|
||
|
||
// 模糊搜索:ticker 包含 keyword 或者 exchange 包含 keyword 或者 name 包含 keyword
|
||
var results = await _db.Queryable<TiingoTicker>()
|
||
.Where(t => t.Ticker.Contains(keyword) || t.Exchange.Contains(keyword) || (t.Name != null && t.Name.Contains(keyword)))
|
||
.Take(limit)
|
||
.OrderBy(t => t.Ticker)
|
||
.Select(t => new TickerSearchResult
|
||
{
|
||
Ticker = t.Ticker,
|
||
Name = t.Name,
|
||
Exchange = t.Exchange,
|
||
AssetType = t.AssetType,
|
||
PriceCurrency = t.PriceCurrency
|
||
})
|
||
.ToListAsync();
|
||
|
||
return Ok(new ApiResponse<List<TickerSearchResult>>
|
||
{
|
||
code = AssetManager.Models.StatusCodes.Success,
|
||
data = results,
|
||
message = "Success"
|
||
});
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
_logger.LogError(ex, $"Error searching ticker with keyword: {keyword}");
|
||
|
||
return StatusCode(AssetManager.Models.StatusCodes.InternalServerError, new ApiResponse<List<TickerSearchResult>>
|
||
{
|
||
code = AssetManager.Models.StatusCodes.InternalServerError,
|
||
data = null,
|
||
message = ex.Message
|
||
});
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 股票代码搜索结果
|
||
/// </summary>
|
||
public class TickerSearchResult
|
||
{
|
||
public string? Ticker { get; set; }
|
||
public string? Name { get; set; }
|
||
public string? Exchange { get; set; }
|
||
public string? AssetType { get; set; }
|
||
public string? PriceCurrency { get; set; }
|
||
}
|