refactor: 架构整改 - Ticker 逻辑移到 Service 层,DTO 独立
This commit is contained in:
parent
86e073add7
commit
8830dd17ae
@ -1,9 +1,9 @@
|
|||||||
using AssetManager.Data;
|
|
||||||
using AssetManager.Models;
|
using AssetManager.Models;
|
||||||
|
using AssetManager.Models.DTOs;
|
||||||
|
using AssetManager.Services;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using SqlSugar;
|
|
||||||
|
|
||||||
namespace AssetManager.API.Controllers;
|
namespace AssetManager.API.Controllers;
|
||||||
|
|
||||||
@ -16,18 +16,18 @@ namespace AssetManager.API.Controllers;
|
|||||||
public class TickerController : ControllerBase
|
public class TickerController : ControllerBase
|
||||||
{
|
{
|
||||||
private readonly ILogger<TickerController> _logger;
|
private readonly ILogger<TickerController> _logger;
|
||||||
private readonly ISqlSugarClient _db;
|
private readonly ITickerService _tickerService;
|
||||||
|
|
||||||
public TickerController(ILogger<TickerController> logger, ISqlSugarClient db)
|
public TickerController(ILogger<TickerController> logger, ITickerService tickerService)
|
||||||
{
|
{
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_db = db;
|
_tickerService = tickerService;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 模糊搜索股票代码
|
/// 模糊搜索股票代码
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="keyword">搜索关键词(ticker 或 exchange)</param>
|
/// <param name="keyword">搜索关键词(ticker 或 exchange 或 name)</param>
|
||||||
/// <param name="limit">返回数量上限(默认 20)</param>
|
/// <param name="limit">返回数量上限(默认 20)</param>
|
||||||
/// <returns>匹配的股票代码列表</returns>
|
/// <returns>匹配的股票代码列表</returns>
|
||||||
[HttpGet("search")]
|
[HttpGet("search")]
|
||||||
@ -39,30 +39,7 @@ public class TickerController : ControllerBase
|
|||||||
{
|
{
|
||||||
_logger.LogInformation($"Search ticker with keyword: {keyword}, limit: {limit}");
|
_logger.LogInformation($"Search ticker with keyword: {keyword}, limit: {limit}");
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(keyword))
|
var results = await _tickerService.SearchTickerAsync(keyword, limit);
|
||||||
{
|
|
||||||
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>>
|
return Ok(new ApiResponse<List<TickerSearchResult>>
|
||||||
{
|
{
|
||||||
@ -84,15 +61,3 @@ public class TickerController : ControllerBase
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <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; }
|
|
||||||
}
|
|
||||||
|
|||||||
@ -68,6 +68,7 @@ builder.Services.AddScoped<AssetManager.Services.Services.WechatService>();
|
|||||||
builder.Services.AddScoped<AssetManager.Services.Services.JwtService>();
|
builder.Services.AddScoped<AssetManager.Services.Services.JwtService>();
|
||||||
builder.Services.AddScoped<AssetManager.Services.IPortfolioService, AssetManager.Services.PortfolioService>();
|
builder.Services.AddScoped<AssetManager.Services.IPortfolioService, AssetManager.Services.PortfolioService>();
|
||||||
builder.Services.AddScoped<AssetManager.Services.IStrategyService, AssetManager.Services.StrategyService>();
|
builder.Services.AddScoped<AssetManager.Services.IStrategyService, AssetManager.Services.StrategyService>();
|
||||||
|
builder.Services.AddScoped<AssetManager.Services.ITickerService, AssetManager.Services.TickerService>();
|
||||||
|
|
||||||
// 市场数据服务:开发环境用 Mock,生产环境用 Alpaca
|
// 市场数据服务:开发环境用 Mock,生产环境用 Alpaca
|
||||||
if (builder.Environment.IsDevelopment())
|
if (builder.Environment.IsDevelopment())
|
||||||
|
|||||||
13
AssetManager.Models/DTOs/TickerDTO.cs
Normal file
13
AssetManager.Models/DTOs/TickerDTO.cs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
namespace AssetManager.Models.DTOs;
|
||||||
|
|
||||||
|
/// <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; }
|
||||||
|
}
|
||||||
17
AssetManager.Services/ITickerService.cs
Normal file
17
AssetManager.Services/ITickerService.cs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
using AssetManager.Models.DTOs;
|
||||||
|
|
||||||
|
namespace AssetManager.Services;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 股票代码服务接口
|
||||||
|
/// </summary>
|
||||||
|
public interface ITickerService
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 模糊搜索股票代码
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="keyword">搜索关键词</param>
|
||||||
|
/// <param name="limit">返回数量上限</param>
|
||||||
|
/// <returns>匹配的股票代码列表</returns>
|
||||||
|
Task<List<TickerSearchResult>> SearchTickerAsync(string keyword, int limit = 20);
|
||||||
|
}
|
||||||
51
AssetManager.Services/TickerService.cs
Normal file
51
AssetManager.Services/TickerService.cs
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
using AssetManager.Data;
|
||||||
|
using AssetManager.Models.DTOs;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using SqlSugar;
|
||||||
|
|
||||||
|
namespace AssetManager.Services;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 股票代码服务实现
|
||||||
|
/// </summary>
|
||||||
|
public class TickerService : ITickerService
|
||||||
|
{
|
||||||
|
private readonly ILogger<TickerService> _logger;
|
||||||
|
private readonly ISqlSugarClient _db;
|
||||||
|
|
||||||
|
public TickerService(ILogger<TickerService> logger, ISqlSugarClient db)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
_db = db;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 模糊搜索股票代码
|
||||||
|
/// </summary>
|
||||||
|
public async Task<List<TickerSearchResult>> SearchTickerAsync(string keyword, int limit = 20)
|
||||||
|
{
|
||||||
|
_logger.LogInformation($"Search ticker with keyword: {keyword}, limit: {limit}");
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(keyword))
|
||||||
|
{
|
||||||
|
return new List<TickerSearchResult>();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 模糊搜索: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 results;
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user