From 287634cf99ad4fffd33969080fdf6c1c16dad011 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=A9=99=E5=AD=90?= <454313500@qq.com> Date: Sun, 2 Mar 2025 01:54:12 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9Eai-stock=E6=A8=A1?= =?UTF-8?q?=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Yi.Abp.Net8/Yi.Abp.sln | 12 +- .../Dtos/StockHolding/StockHoldingDto.cs | 66 ++++++++ .../StockHoldingGetListInputDto.cs | 21 +++ .../Dtos/StockMarket/StockMarketDto.cs | 36 +++++ .../StockMarket/StockMarketGetListInputDto.cs | 26 ++++ .../Dtos/StockNews/StockNewsDto.cs | 41 +++++ .../StockNews/StockNewsGetListInputDto.cs | 37 +++++ .../Dtos/StockPrice/StockPriceRecordDto.cs | 42 ++++++ .../StockPriceRecordGetListInputDto.cs | 32 ++++ .../StockTransaction/StockTransactionDto.cs | 62 ++++++++ .../StockTransactionGetListInputDto.cs | 37 +++++ .../IServices/IStockHoldingService.cs | 29 ++++ .../IServices/IStockMarketService.cs | 29 ++++ .../IServices/IStockNewsService.cs | 20 +++ ...amework.Stock.Application.Contracts.csproj | 0 ...rameworkStockApplicationContractsModule.cs | 0 .../Services/StockHoldingService.cs | 106 +++++++++++++ .../Services/StockMarketService.cs | 95 ++++++++++++ .../Services/StockNewsService.cs | 65 ++++++++ .../Yi.Framework.Stock.Application.csproj | 0 .../YiFrameworkStockApplicationModule.cs | 0 .../Enums/PeriodTypeEnum.cs | 41 +++++ .../Enums/TransactionTypeEnum.cs | 18 +++ .../Yi.Framework.Stock.Domain.Shared.csproj | 0 .../YiFrameworkStockDomainSharedModule.cs | 0 .../Entities/StockHoldingAggregateRoot.cs | 141 ++++++++++++++++++ .../Entities/StockMarketAggregateRoot.cs | 81 ++++++++++ .../Entities/StockNewsAggregateRoot.cs | 81 ++++++++++ .../Entities/StockPriceRecordEntity.cs | 72 +++++++++ .../Entities/StockTransactionEntity.cs | 121 +++++++++++++++ .../Yi.Framework.Stock.Domain.csproj | 1 - .../YiFrameworkStockDomainModule.cs | 0 .../Yi.Framework.Stock.SqlSugarCore.csproj | 0 .../YiFrameworkStockSqlSugarCoreModule.cs | 0 .../Services/TestService.cs | 15 -- .../Yi.Abp.Application.csproj | 2 +- .../Yi.Abp.SqlSugarCore.csproj | 2 +- Yi.Abp.Net8/src/Yi.Abp.Web/YiAbpWebModule.cs | 2 +- 38 files changed, 1308 insertions(+), 25 deletions(-) create mode 100644 Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Application.Contracts/Dtos/StockHolding/StockHoldingDto.cs create mode 100644 Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Application.Contracts/Dtos/StockHolding/StockHoldingGetListInputDto.cs create mode 100644 Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Application.Contracts/Dtos/StockMarket/StockMarketDto.cs create mode 100644 Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Application.Contracts/Dtos/StockMarket/StockMarketGetListInputDto.cs create mode 100644 Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Application.Contracts/Dtos/StockNews/StockNewsDto.cs create mode 100644 Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Application.Contracts/Dtos/StockNews/StockNewsGetListInputDto.cs create mode 100644 Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Application.Contracts/Dtos/StockPrice/StockPriceRecordDto.cs create mode 100644 Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Application.Contracts/Dtos/StockPrice/StockPriceRecordGetListInputDto.cs create mode 100644 Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Application.Contracts/Dtos/StockTransaction/StockTransactionDto.cs create mode 100644 Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Application.Contracts/Dtos/StockTransaction/StockTransactionGetListInputDto.cs create mode 100644 Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Application.Contracts/IServices/IStockHoldingService.cs create mode 100644 Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Application.Contracts/IServices/IStockMarketService.cs create mode 100644 Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Application.Contracts/IServices/IStockNewsService.cs rename Yi.Abp.Net8/module/{stock => ai-stock}/Yi.Framework.Stock.Application.Contracts/Yi.Framework.Stock.Application.Contracts.csproj (100%) rename Yi.Abp.Net8/module/{stock => ai-stock}/Yi.Framework.Stock.Application.Contracts/YiFrameworkStockApplicationContractsModule.cs (100%) create mode 100644 Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Application/Services/StockHoldingService.cs create mode 100644 Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Application/Services/StockMarketService.cs create mode 100644 Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Application/Services/StockNewsService.cs rename Yi.Abp.Net8/module/{stock => ai-stock}/Yi.Framework.Stock.Application/Yi.Framework.Stock.Application.csproj (100%) rename Yi.Abp.Net8/module/{stock => ai-stock}/Yi.Framework.Stock.Application/YiFrameworkStockApplicationModule.cs (100%) create mode 100644 Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Domain.Shared/Enums/PeriodTypeEnum.cs create mode 100644 Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Domain.Shared/Enums/TransactionTypeEnum.cs rename Yi.Abp.Net8/module/{stock => ai-stock}/Yi.Framework.Stock.Domain.Shared/Yi.Framework.Stock.Domain.Shared.csproj (100%) rename Yi.Abp.Net8/module/{stock => ai-stock}/Yi.Framework.Stock.Domain.Shared/YiFrameworkStockDomainSharedModule.cs (100%) create mode 100644 Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Domain/Entities/StockHoldingAggregateRoot.cs create mode 100644 Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Domain/Entities/StockMarketAggregateRoot.cs create mode 100644 Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Domain/Entities/StockNewsAggregateRoot.cs create mode 100644 Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Domain/Entities/StockPriceRecordEntity.cs create mode 100644 Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Domain/Entities/StockTransactionEntity.cs rename Yi.Abp.Net8/module/{stock => ai-stock}/Yi.Framework.Stock.Domain/Yi.Framework.Stock.Domain.csproj (95%) rename Yi.Abp.Net8/module/{stock => ai-stock}/Yi.Framework.Stock.Domain/YiFrameworkStockDomainModule.cs (100%) rename Yi.Abp.Net8/module/{stock => ai-stock}/Yi.Framework.Stock.SqlSugarCore/Yi.Framework.Stock.SqlSugarCore.csproj (100%) rename Yi.Abp.Net8/module/{stock => ai-stock}/Yi.Framework.Stock.SqlSugarCore/YiFrameworkStockSqlSugarCoreModule.cs (100%) delete mode 100644 Yi.Abp.Net8/module/stock/Yi.Framework.Stock.Application/Services/TestService.cs diff --git a/Yi.Abp.Net8/Yi.Abp.sln b/Yi.Abp.Net8/Yi.Abp.sln index dcf482a4..d4e242fa 100644 --- a/Yi.Abp.Net8/Yi.Abp.sln +++ b/Yi.Abp.Net8/Yi.Abp.sln @@ -174,17 +174,17 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Yi.Framework.WeChat.MiniPro EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Yi.Framework.BackgroundWorkers.Hangfire", "framework\Yi.Framework.BackgroundWorkers.Hangfire\Yi.Framework.BackgroundWorkers.Hangfire.csproj", "{862CA181-BEE6-4870-82D2-B662E527ED8C}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "stock", "stock", "{DB46873F-981A-43D8-91B0-D464CCB65943}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ai-stock", "ai-stock", "{DB46873F-981A-43D8-91B0-D464CCB65943}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Yi.Framework.Stock.Application", "module\stock\Yi.Framework.Stock.Application\Yi.Framework.Stock.Application.csproj", "{B79CE23C-10F8-48A5-A039-5940A188CF5A}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Yi.Framework.Stock.Application", "module\ai-stock\Yi.Framework.Stock.Application\Yi.Framework.Stock.Application.csproj", "{B79CE23C-10F8-48A5-A039-5940A188CF5A}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Yi.Framework.Stock.Application.Contracts", "module\stock\Yi.Framework.Stock.Application.Contracts\Yi.Framework.Stock.Application.Contracts.csproj", "{846B781A-B77E-4F86-A31F-0B5B57AB0775}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Yi.Framework.Stock.Application.Contracts", "module\ai-stock\Yi.Framework.Stock.Application.Contracts\Yi.Framework.Stock.Application.Contracts.csproj", "{846B781A-B77E-4F86-A31F-0B5B57AB0775}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Yi.Framework.Stock.Domain", "module\stock\Yi.Framework.Stock.Domain\Yi.Framework.Stock.Domain.csproj", "{162821E4-8FE0-4A68-B3C0-49BD6596446F}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Yi.Framework.Stock.Domain", "module\ai-stock\Yi.Framework.Stock.Domain\Yi.Framework.Stock.Domain.csproj", "{162821E4-8FE0-4A68-B3C0-49BD6596446F}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Yi.Framework.Stock.Domain.Shared", "module\stock\Yi.Framework.Stock.Domain.Shared\Yi.Framework.Stock.Domain.Shared.csproj", "{10273544-715D-4BB3-893C-6F010D947BDD}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Yi.Framework.Stock.Domain.Shared", "module\ai-stock\Yi.Framework.Stock.Domain.Shared\Yi.Framework.Stock.Domain.Shared.csproj", "{10273544-715D-4BB3-893C-6F010D947BDD}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Yi.Framework.Stock.SqlSugarCore", "module\stock\Yi.Framework.Stock.SqlSugarCore\Yi.Framework.Stock.SqlSugarCore.csproj", "{5F49318F-E6C7-4194-BAE0-83D4FB8D1983}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Yi.Framework.Stock.SqlSugarCore", "module\ai-stock\Yi.Framework.Stock.SqlSugarCore\Yi.Framework.Stock.SqlSugarCore.csproj", "{5F49318F-E6C7-4194-BAE0-83D4FB8D1983}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Application.Contracts/Dtos/StockHolding/StockHoldingDto.cs b/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Application.Contracts/Dtos/StockHolding/StockHoldingDto.cs new file mode 100644 index 00000000..19dafdfe --- /dev/null +++ b/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Application.Contracts/Dtos/StockHolding/StockHoldingDto.cs @@ -0,0 +1,66 @@ +using System; +using Volo.Abp.Application.Dtos; + +namespace Yi.Framework.Stock.Application.Contracts.Dtos.StockHolding +{ + /// + /// 用户股票持仓DTO + /// + public class StockHoldingDto : EntityDto + { + /// + /// 用户ID + /// + public Guid UserId { get; set; } + + /// + /// 股票ID + /// + public Guid StockId { get; set; } + + /// + /// 股票代码 + /// + public string StockCode { get; set; } + + /// + /// 股票名称 + /// + public string StockName { get; set; } + + /// + /// 持有数量 + /// + public int Quantity { get; set; } + + /// + /// 持仓成本 + /// + public decimal CostPrice { get; set; } + + /// + /// 当前价格 + /// + public decimal CurrentPrice { get; set; } + + /// + /// 持仓市值 + /// + public decimal MarketValue { get; set; } + + /// + /// 盈亏金额 + /// + public decimal ProfitLoss { get; set; } + + /// + /// 盈亏百分比 + /// + public decimal ProfitLossPercentage { get; set; } + + /// + /// 创建时间 + /// + public DateTime CreationTime { get; set; } + } +} \ No newline at end of file diff --git a/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Application.Contracts/Dtos/StockHolding/StockHoldingGetListInputDto.cs b/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Application.Contracts/Dtos/StockHolding/StockHoldingGetListInputDto.cs new file mode 100644 index 00000000..8447c357 --- /dev/null +++ b/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Application.Contracts/Dtos/StockHolding/StockHoldingGetListInputDto.cs @@ -0,0 +1,21 @@ +using System; +using Volo.Abp.Application.Dtos; + +namespace Yi.Framework.Stock.Application.Contracts.Dtos.StockHolding +{ + /// + /// 获取用户持仓列表的输入DTO + /// + public class StockHoldingGetListInputDto : PagedAndSortedResultRequestDto + { + /// + /// 股票代码 + /// + public string? StockCode { get; set; } + + /// + /// 股票名称 + /// + public string? StockName { get; set; } + } +} \ No newline at end of file diff --git a/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Application.Contracts/Dtos/StockMarket/StockMarketDto.cs b/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Application.Contracts/Dtos/StockMarket/StockMarketDto.cs new file mode 100644 index 00000000..19659159 --- /dev/null +++ b/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Application.Contracts/Dtos/StockMarket/StockMarketDto.cs @@ -0,0 +1,36 @@ +using System; +using Volo.Abp.Application.Dtos; + +namespace Yi.Framework.Stock.Application.Contracts.Dtos.StockMarket +{ + /// + /// 股市信息DTO + /// + public class StockMarketDto : EntityDto + { + /// + /// 股市代码 + /// + public string MarketCode { get; set; } + + /// + /// 股市名称 + /// + public string MarketName { get; set; } + + /// + /// 股市描述 + /// + public string Description { get; set; } + + /// + /// 状态 + /// + public bool State { get; set; } + + /// + /// 创建时间 + /// + public DateTime CreationTime { get; set; } + } +} \ No newline at end of file diff --git a/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Application.Contracts/Dtos/StockMarket/StockMarketGetListInputDto.cs b/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Application.Contracts/Dtos/StockMarket/StockMarketGetListInputDto.cs new file mode 100644 index 00000000..38cf5faa --- /dev/null +++ b/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Application.Contracts/Dtos/StockMarket/StockMarketGetListInputDto.cs @@ -0,0 +1,26 @@ +using System; +using Volo.Abp.Application.Dtos; + +namespace Yi.Framework.Stock.Application.Contracts.Dtos.StockMarket +{ + /// + /// 获取股市列表的输入DTO + /// + public class StockMarketGetListInputDto : PagedAndSortedResultRequestDto + { + /// + /// 股市代码 + /// + public string? MarketCode { get; set; } + + /// + /// 股市名称 + /// + public string? MarketName { get; set; } + + /// + /// 状态 + /// + public bool? State { get; set; } + } +} \ No newline at end of file diff --git a/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Application.Contracts/Dtos/StockNews/StockNewsDto.cs b/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Application.Contracts/Dtos/StockNews/StockNewsDto.cs new file mode 100644 index 00000000..6a4150b2 --- /dev/null +++ b/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Application.Contracts/Dtos/StockNews/StockNewsDto.cs @@ -0,0 +1,41 @@ +using System; +using Volo.Abp.Application.Dtos; + +namespace Yi.Framework.Stock.Application.Contracts.Dtos.StockNews +{ + /// + /// 股市新闻DTO + /// + public class StockNewsDto : EntityDto + { + /// + /// 新闻标题 + /// + public string Title { get; set; } + + /// + /// 新闻内容 + /// + public string Content { get; set; } + + /// + /// 发布时间 + /// + public DateTime PublishTime { get; set; } + + /// + /// 新闻来源 + /// + public string Source { get; set; } + + /// + /// 创建时间 + /// + public DateTime CreationTime { get; set; } + + /// + /// 排序号 + /// + public int OrderNum { get; set; } + } +} \ No newline at end of file diff --git a/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Application.Contracts/Dtos/StockNews/StockNewsGetListInputDto.cs b/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Application.Contracts/Dtos/StockNews/StockNewsGetListInputDto.cs new file mode 100644 index 00000000..4a934fcd --- /dev/null +++ b/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Application.Contracts/Dtos/StockNews/StockNewsGetListInputDto.cs @@ -0,0 +1,37 @@ +using System; +using Volo.Abp.Application.Dtos; + +namespace Yi.Framework.Stock.Application.Contracts.Dtos.StockNews +{ + /// + /// 获取股市新闻列表的输入DTO + /// + public class StockNewsGetListInputDto : PagedAndSortedResultRequestDto + { + /// + /// 新闻标题关键词 + /// + public string? Title { get; set; } + + /// + /// 新闻来源 + /// + public string? Source { get; set; } + + /// + /// 开始时间 + /// + public DateTime? StartTime { get; set; } + + /// + /// 结束时间 + /// + public DateTime? EndTime { get; set; } + + /// + /// 是否只显示最近10天的新闻 + /// + /// 默认为true,查询最近10天的新闻 + public bool IsRecent { get; set; } = true; + } +} \ No newline at end of file diff --git a/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Application.Contracts/Dtos/StockPrice/StockPriceRecordDto.cs b/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Application.Contracts/Dtos/StockPrice/StockPriceRecordDto.cs new file mode 100644 index 00000000..8c10c801 --- /dev/null +++ b/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Application.Contracts/Dtos/StockPrice/StockPriceRecordDto.cs @@ -0,0 +1,42 @@ +using System; +using Volo.Abp.Application.Dtos; +using Yi.Framework.Stock.Domain.Shared; + +namespace Yi.Framework.Stock.Application.Contracts.Dtos.StockPrice +{ + /// + /// 股市价格记录DTO + /// + public class StockPriceRecordDto : EntityDto + { + /// + /// 股票ID + /// + public Guid StockId { get; set; } + + /// + /// 记录时间 + /// + public DateTime CreationTime { get; set; } + + /// + /// 当前价 + /// + public decimal CurrentPrice { get; set; } + + /// + /// 交易量 + /// + public long Volume { get; set; } + + /// + /// 交易额 + /// + public decimal Turnover { get; set; } + + /// + /// 时间周期类型 + /// + public PeriodTypeEnum PeriodType { get; set; } + } +} \ No newline at end of file diff --git a/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Application.Contracts/Dtos/StockPrice/StockPriceRecordGetListInputDto.cs b/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Application.Contracts/Dtos/StockPrice/StockPriceRecordGetListInputDto.cs new file mode 100644 index 00000000..84fcf6e1 --- /dev/null +++ b/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Application.Contracts/Dtos/StockPrice/StockPriceRecordGetListInputDto.cs @@ -0,0 +1,32 @@ +using System; +using Volo.Abp.Application.Dtos; +using Yi.Framework.Stock.Domain.Shared; + +namespace Yi.Framework.Stock.Application.Contracts.Dtos.StockPrice +{ + /// + /// 获取股市价格记录的输入DTO + /// + public class StockPriceRecordGetListInputDto : PagedAndSortedResultRequestDto + { + /// + /// 股票ID + /// + public Guid? StockId { get; set; } + + /// + /// 开始时间 + /// + public DateTime? StartTime { get; set; } + + /// + /// 结束时间 + /// + public DateTime? EndTime { get; set; } + + /// + /// 时间周期类型 + /// + public PeriodTypeEnum? PeriodType { get; set; } + } +} \ No newline at end of file diff --git a/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Application.Contracts/Dtos/StockTransaction/StockTransactionDto.cs b/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Application.Contracts/Dtos/StockTransaction/StockTransactionDto.cs new file mode 100644 index 00000000..955af11d --- /dev/null +++ b/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Application.Contracts/Dtos/StockTransaction/StockTransactionDto.cs @@ -0,0 +1,62 @@ +using System; +using Volo.Abp.Application.Dtos; +using Yi.Framework.Stock.Domain.Shared; + +namespace Yi.Framework.Stock.Application.Contracts.Dtos.StockTransaction +{ + /// + /// 股票交易记录DTO + /// + public class StockTransactionDto : EntityDto + { + /// + /// 用户ID + /// + public Guid UserId { get; set; } + + /// + /// 股票ID + /// + public Guid StockId { get; set; } + + /// + /// 股票代码 + /// + public string StockCode { get; set; } + + /// + /// 股票名称 + /// + public string StockName { get; set; } + + /// + /// 交易类型 + /// + public TransactionTypeEnum TransactionType { get; set; } + + /// + /// 交易价格 + /// + public decimal Price { get; set; } + + /// + /// 交易数量 + /// + public int Quantity { get; set; } + + /// + /// 交易总额 + /// + public decimal TotalAmount { get; set; } + + /// + /// 交易费用 + /// + public decimal Fee { get; set; } + + /// + /// 交易时间 + /// + public DateTime CreationTime { get; set; } + } +} \ No newline at end of file diff --git a/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Application.Contracts/Dtos/StockTransaction/StockTransactionGetListInputDto.cs b/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Application.Contracts/Dtos/StockTransaction/StockTransactionGetListInputDto.cs new file mode 100644 index 00000000..f8464c45 --- /dev/null +++ b/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Application.Contracts/Dtos/StockTransaction/StockTransactionGetListInputDto.cs @@ -0,0 +1,37 @@ +using System; +using Volo.Abp.Application.Dtos; +using Yi.Framework.Stock.Domain.Shared; + +namespace Yi.Framework.Stock.Application.Contracts.Dtos.StockTransaction +{ + /// + /// 获取交易记录的输入DTO + /// + public class StockTransactionGetListInputDto : PagedAndSortedResultRequestDto + { + /// + /// 股票代码 + /// + public string StockCode { get; set; } + + /// + /// 股票名称 + /// + public string StockName { get; set; } + + /// + /// 交易类型 + /// + public TransactionTypeEnum? TransactionType { get; set; } + + /// + /// 开始时间 + /// + public DateTime? StartTime { get; set; } + + /// + /// 结束时间 + /// + public DateTime? EndTime { get; set; } + } +} \ No newline at end of file diff --git a/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Application.Contracts/IServices/IStockHoldingService.cs b/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Application.Contracts/IServices/IStockHoldingService.cs new file mode 100644 index 00000000..1f4cdd09 --- /dev/null +++ b/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Application.Contracts/IServices/IStockHoldingService.cs @@ -0,0 +1,29 @@ +using System; +using System.Threading.Tasks; +using Volo.Abp.Application.Dtos; +using Volo.Abp.Application.Services; +using Yi.Framework.Stock.Application.Contracts.Dtos.StockHolding; +using Yi.Framework.Stock.Application.Contracts.Dtos.StockTransaction; + +namespace Yi.Framework.Stock.Application.Contracts.IServices +{ + /// + /// 用户持仓服务接口 + /// + public interface IStockHoldingService : IApplicationService + { + /// + /// 获取当前用户的持仓列表 + /// + /// 查询条件 + /// 持仓列表 + Task> GetUserHoldingsAsync(StockHoldingGetListInputDto input); + + /// + /// 获取当前用户的交易记录 + /// + /// 查询条件 + /// 交易记录列表 + Task> GetUserTransactionsAsync(StockTransactionGetListInputDto input); + } +} \ No newline at end of file diff --git a/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Application.Contracts/IServices/IStockMarketService.cs b/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Application.Contracts/IServices/IStockMarketService.cs new file mode 100644 index 00000000..9426870a --- /dev/null +++ b/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Application.Contracts/IServices/IStockMarketService.cs @@ -0,0 +1,29 @@ +using System; +using System.Threading.Tasks; +using Volo.Abp.Application.Dtos; +using Volo.Abp.Application.Services; +using Yi.Framework.Stock.Application.Contracts.Dtos.StockMarket; +using Yi.Framework.Stock.Application.Contracts.Dtos.StockPrice; + +namespace Yi.Framework.Stock.Application.Contracts.IServices +{ + /// + /// 股市服务接口 + /// + public interface IStockMarketService : IApplicationService + { + /// + /// 获取股市列表 + /// + /// 查询条件 + /// 股市列表 + Task> GetStockMarketListAsync(StockMarketGetListInputDto input); + + /// + /// 获取股市价格记录看板 + /// + /// 查询条件 + /// 股价记录列表 + Task> GetStockPriceRecordListAsync(StockPriceRecordGetListInputDto input); + } +} \ No newline at end of file diff --git a/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Application.Contracts/IServices/IStockNewsService.cs b/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Application.Contracts/IServices/IStockNewsService.cs new file mode 100644 index 00000000..5689682c --- /dev/null +++ b/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Application.Contracts/IServices/IStockNewsService.cs @@ -0,0 +1,20 @@ +using System.Threading.Tasks; +using Volo.Abp.Application.Dtos; +using Volo.Abp.Application.Services; +using Yi.Framework.Stock.Application.Contracts.Dtos.StockNews; + +namespace Yi.Framework.Stock.Application.Contracts.IServices +{ + /// + /// 股市新闻服务接口 + /// + public interface IStockNewsService : IApplicationService + { + /// + /// 获取股市新闻列表 + /// + /// 查询条件 + /// 新闻列表 + Task> GetStockNewsListAsync(StockNewsGetListInputDto input); + } +} \ No newline at end of file diff --git a/Yi.Abp.Net8/module/stock/Yi.Framework.Stock.Application.Contracts/Yi.Framework.Stock.Application.Contracts.csproj b/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Application.Contracts/Yi.Framework.Stock.Application.Contracts.csproj similarity index 100% rename from Yi.Abp.Net8/module/stock/Yi.Framework.Stock.Application.Contracts/Yi.Framework.Stock.Application.Contracts.csproj rename to Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Application.Contracts/Yi.Framework.Stock.Application.Contracts.csproj diff --git a/Yi.Abp.Net8/module/stock/Yi.Framework.Stock.Application.Contracts/YiFrameworkStockApplicationContractsModule.cs b/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Application.Contracts/YiFrameworkStockApplicationContractsModule.cs similarity index 100% rename from Yi.Abp.Net8/module/stock/Yi.Framework.Stock.Application.Contracts/YiFrameworkStockApplicationContractsModule.cs rename to Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Application.Contracts/YiFrameworkStockApplicationContractsModule.cs diff --git a/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Application/Services/StockHoldingService.cs b/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Application/Services/StockHoldingService.cs new file mode 100644 index 00000000..ff692258 --- /dev/null +++ b/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Application/Services/StockHoldingService.cs @@ -0,0 +1,106 @@ +using System; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using SqlSugar; +using Volo.Abp.Application.Dtos; +using Volo.Abp.Application.Services; +using Yi.Framework.Stock.Application.Contracts.Dtos.StockHolding; +using Yi.Framework.Stock.Application.Contracts.Dtos.StockTransaction; +using Yi.Framework.Stock.Application.Contracts.IServices; +using Yi.Framework.Stock.Domain.Entities; +using Yi.Framework.SqlSugarCore.Abstractions; +using Volo.Abp.Users; + +namespace Yi.Framework.Stock.Application.Services +{ + /// + /// 用户持仓服务实现 + /// + [Authorize] + public class StockHoldingService : ApplicationService, IStockHoldingService + { + private readonly ISqlSugarRepository _stockHoldingRepository; + private readonly ISqlSugarRepository _stockTransactionRepository; + + public StockHoldingService( + ISqlSugarRepository stockHoldingRepository, + ISqlSugarRepository stockTransactionRepository) + { + _stockHoldingRepository = stockHoldingRepository; + _stockTransactionRepository = stockTransactionRepository; + } + + /// + /// 获取当前用户的持仓列表 + /// + [Authorize] + [HttpGet("stock/user-holdings")] + public async Task> GetUserHoldingsAsync(StockHoldingGetListInputDto input) + { + Guid userId = CurrentUser.GetId(); + RefAsync total = 0; + + var query = _stockHoldingRepository._DbQueryable + .Where(h => h.UserId == userId) + .WhereIF(!string.IsNullOrEmpty(input.StockCode), h => h.StockCode.Contains(input.StockCode)) + .WhereIF(!string.IsNullOrEmpty(input.StockName), h => h.StockName.Contains(input.StockName)) + .OrderByIF(!string.IsNullOrEmpty(input.Sorting),input.Sorting) + .OrderByIF(string.IsNullOrEmpty(input.Sorting),t=>t.CreationTime,OrderByType.Desc); + + var list = await query + .Select(h => new StockHoldingDto + { + Id = h.Id, + UserId = h.UserId, + StockId = h.StockId, + StockCode = h.StockCode, + StockName = h.StockName, + CreationTime = h.CreationTime + }) + .ToPageListAsync(input.SkipCount, input.MaxResultCount, total); + + return new PagedResultDto(total, list); + } + + /// + /// 获取当前用户的交易记录 + /// + [Authorize] + [HttpGet("stock/user-transactions")] + public async Task> GetUserTransactionsAsync(StockTransactionGetListInputDto input) + { + Guid userId = CurrentUser.GetId(); + RefAsync total = 0; + + var query = _stockTransactionRepository._DbQueryable + .Where(t => t.UserId == userId) + .WhereIF(!string.IsNullOrEmpty(input.StockCode), t => t.StockCode.Contains(input.StockCode)) + .WhereIF(!string.IsNullOrEmpty(input.StockName), t => t.StockName.Contains(input.StockName)) + .WhereIF(input.TransactionType.HasValue, t => t.TransactionType == input.TransactionType.Value) + .WhereIF(input.StartTime.HasValue, t => t.CreationTime >= input.StartTime.Value) + .WhereIF(input.EndTime.HasValue, t => t.CreationTime <= input.EndTime.Value) + .OrderByIF(!string.IsNullOrEmpty(input.Sorting),input.Sorting) + .OrderByIF(string.IsNullOrEmpty(input.Sorting),t=>t.CreationTime,OrderByType.Desc); + + var list = await query + .Select(t => new StockTransactionDto + { + Id = t.Id, + UserId = t.UserId, + StockId = t.StockId, + StockCode = t.StockCode, + StockName = t.StockName, + TransactionType = t.TransactionType, + Price = t.Price, + Quantity = t.Quantity, + TotalAmount = t.TotalAmount, + Fee = t.Fee, + CreationTime = t.CreationTime + }) + .ToPageListAsync(input.SkipCount, input.MaxResultCount, total); + + return new PagedResultDto(total, list); + } + } +} \ No newline at end of file diff --git a/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Application/Services/StockMarketService.cs b/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Application/Services/StockMarketService.cs new file mode 100644 index 00000000..44b0b349 --- /dev/null +++ b/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Application/Services/StockMarketService.cs @@ -0,0 +1,95 @@ +using System; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using SqlSugar; +using Volo.Abp.Application.Dtos; +using Volo.Abp.Application.Services; +using Yi.Framework.Stock.Application.Contracts.Dtos.StockMarket; +using Yi.Framework.Stock.Application.Contracts.Dtos.StockPrice; +using Yi.Framework.Stock.Application.Contracts.IServices; +using Yi.Framework.Stock.Domain.Entities; +using Yi.Framework.SqlSugarCore.Abstractions; + +namespace Yi.Framework.Stock.Application.Services +{ + /// + /// 股市服务实现 + /// + public class StockMarketService : ApplicationService, IStockMarketService + { + private readonly ISqlSugarRepository _stockMarketRepository; + private readonly ISqlSugarRepository _stockPriceRecordRepository; + + public StockMarketService( + ISqlSugarRepository stockMarketRepository, + ISqlSugarRepository stockPriceRecordRepository) + { + _stockMarketRepository = stockMarketRepository; + _stockPriceRecordRepository = stockPriceRecordRepository; + } + + /// + /// 获取股市列表 + /// + [HttpGet("stock/markets")] + public async Task> GetStockMarketListAsync(StockMarketGetListInputDto input) + { + RefAsync total = 0; + + var query = _stockMarketRepository._DbQueryable + .WhereIF(!string.IsNullOrEmpty(input.MarketCode), m => m.MarketCode.Contains(input.MarketCode)) + .WhereIF(!string.IsNullOrEmpty(input.MarketName), m => m.MarketName.Contains(input.MarketName)) + .WhereIF(input.State.HasValue, m => m.State == input.State.Value) + .OrderByIF(!string.IsNullOrEmpty(input.Sorting),input.Sorting) + .OrderByIF(string.IsNullOrEmpty(input.Sorting),m=>m.OrderNum,OrderByType.Asc) + .OrderByIF(string.IsNullOrEmpty(input.Sorting),m=>m.CreationTime,OrderByType.Desc); + + var list = await query + .Select(m => new StockMarketDto + { + Id = m.Id, + MarketCode = m.MarketCode, + MarketName = m.MarketName, + Description = m.Description, + State = m.State, + CreationTime = m.CreationTime + }) + .ToPageListAsync(input.SkipCount, input.MaxResultCount, total); + + return new PagedResultDto(total, list); + } + + /// + /// 获取股市价格记录看板 + /// + [HttpGet("stock/price-records")] + public async Task> GetStockPriceRecordListAsync(StockPriceRecordGetListInputDto input) + { + RefAsync total = 0; + + var query = _stockPriceRecordRepository._DbQueryable + .WhereIF(input.StockId.HasValue, p => p.StockId == input.StockId.Value) + .WhereIF(input.StartTime.HasValue, p => p.CreationTime >= input.StartTime.Value) + .WhereIF(input.EndTime.HasValue, p => p.CreationTime <= input.EndTime.Value) + .WhereIF(input.PeriodType.HasValue, p => p.PeriodType == input.PeriodType.Value) + .OrderByIF(!string.IsNullOrEmpty(input.Sorting),input.Sorting) + .OrderByIF(string.IsNullOrEmpty(input.Sorting),p=>p.CreationTime,OrderByType.Desc); + + var list = await query + .Select(p => new StockPriceRecordDto + { + Id = p.Id, + StockId = p.StockId, + CreationTime = p.CreationTime, + CurrentPrice = p.CurrentPrice, + Volume = p.Volume, + Turnover = p.Turnover, + PeriodType = p.PeriodType + }) + .ToPageListAsync(input.SkipCount, input.MaxResultCount, total); + + return new PagedResultDto(total, list); + } + } +} \ No newline at end of file diff --git a/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Application/Services/StockNewsService.cs b/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Application/Services/StockNewsService.cs new file mode 100644 index 00000000..a5a92d9b --- /dev/null +++ b/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Application/Services/StockNewsService.cs @@ -0,0 +1,65 @@ +using System; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; +using SqlSugar; +using Volo.Abp.Application.Dtos; +using Volo.Abp.Application.Services; +using Yi.Framework.Stock.Application.Contracts.Dtos.StockNews; +using Yi.Framework.Stock.Application.Contracts.IServices; +using Yi.Framework.Stock.Domain.Entities; +using Yi.Framework.SqlSugarCore.Abstractions; + +namespace Yi.Framework.Stock.Application.Services +{ + /// + /// 股市新闻服务实现 + /// + public class StockNewsService : ApplicationService, IStockNewsService + { + private readonly ISqlSugarRepository _stockNewsRepository; + + public StockNewsService(ISqlSugarRepository stockNewsRepository) + { + _stockNewsRepository = stockNewsRepository; + } + + /// + /// 获取股市新闻列表 + /// + [HttpGet("/api/stock/news")] + public async Task> GetStockNewsListAsync(StockNewsGetListInputDto input) + { + RefAsync total = 0; + + // 计算10天前的日期 + DateTime tenDaysAgo = DateTime.Now.AddDays(-10); + + var query = _stockNewsRepository._DbQueryable + .WhereIF(!string.IsNullOrEmpty(input.Title), n => n.Title.Contains(input.Title)) + .WhereIF(!string.IsNullOrEmpty(input.Source), n => n.Source.Contains(input.Source)) + .WhereIF(input.StartTime.HasValue, n => n.PublishTime >= input.StartTime.Value) + .WhereIF(input.EndTime.HasValue, n => n.PublishTime <= input.EndTime.Value) + // 如果IsRecent为true,则只查询最近10天的新闻 + .WhereIF(input.IsRecent, n => n.PublishTime >= tenDaysAgo) + .OrderByIF(!string.IsNullOrEmpty(input.Sorting),input.Sorting) + .OrderByIF(string.IsNullOrEmpty(input.Sorting),n=>n.OrderNum,OrderByType.Asc) + .OrderByIF(string.IsNullOrEmpty(input.Sorting),n=>n.PublishTime,OrderByType.Desc) ; + + + var list = await query + .Select(n => new StockNewsDto + { + Id = n.Id, + Title = n.Title, + Content = n.Content, + PublishTime = n.PublishTime, + Source = n.Source, + CreationTime = n.CreationTime, + OrderNum = n.OrderNum + }) + .ToPageListAsync(input.SkipCount, input.MaxResultCount, total); + + return new PagedResultDto(total, list); + } + } +} \ No newline at end of file diff --git a/Yi.Abp.Net8/module/stock/Yi.Framework.Stock.Application/Yi.Framework.Stock.Application.csproj b/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Application/Yi.Framework.Stock.Application.csproj similarity index 100% rename from Yi.Abp.Net8/module/stock/Yi.Framework.Stock.Application/Yi.Framework.Stock.Application.csproj rename to Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Application/Yi.Framework.Stock.Application.csproj diff --git a/Yi.Abp.Net8/module/stock/Yi.Framework.Stock.Application/YiFrameworkStockApplicationModule.cs b/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Application/YiFrameworkStockApplicationModule.cs similarity index 100% rename from Yi.Abp.Net8/module/stock/Yi.Framework.Stock.Application/YiFrameworkStockApplicationModule.cs rename to Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Application/YiFrameworkStockApplicationModule.cs diff --git a/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Domain.Shared/Enums/PeriodTypeEnum.cs b/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Domain.Shared/Enums/PeriodTypeEnum.cs new file mode 100644 index 00000000..4ca57fa4 --- /dev/null +++ b/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Domain.Shared/Enums/PeriodTypeEnum.cs @@ -0,0 +1,41 @@ +namespace Yi.Framework.Stock.Domain.Shared +{ + /// + /// 时间周期类型枚举 + /// + /// + /// 用于定义股票价格记录的时间周期类型 + /// + public enum PeriodTypeEnum + { + /// + /// 分钟 + /// + Minute = 0, + + /// + /// 小时 + /// + Hour = 1, + + /// + /// 天 + /// + Day = 2, + + /// + /// 周 + /// + Week = 3, + + /// + /// 月 + /// + Month = 4, + + /// + /// 年 + /// + Year = 5 + } +} \ No newline at end of file diff --git a/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Domain.Shared/Enums/TransactionTypeEnum.cs b/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Domain.Shared/Enums/TransactionTypeEnum.cs new file mode 100644 index 00000000..b8e0d6d3 --- /dev/null +++ b/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Domain.Shared/Enums/TransactionTypeEnum.cs @@ -0,0 +1,18 @@ +namespace Yi.Framework.Stock.Domain.Shared +{ + /// + /// 交易类型枚举 + /// + public enum TransactionTypeEnum + { + /// + /// 买入 + /// + Buy = 0, + + /// + /// 卖出 + /// + Sell = 1 + } +} \ No newline at end of file diff --git a/Yi.Abp.Net8/module/stock/Yi.Framework.Stock.Domain.Shared/Yi.Framework.Stock.Domain.Shared.csproj b/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Domain.Shared/Yi.Framework.Stock.Domain.Shared.csproj similarity index 100% rename from Yi.Abp.Net8/module/stock/Yi.Framework.Stock.Domain.Shared/Yi.Framework.Stock.Domain.Shared.csproj rename to Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Domain.Shared/Yi.Framework.Stock.Domain.Shared.csproj diff --git a/Yi.Abp.Net8/module/stock/Yi.Framework.Stock.Domain.Shared/YiFrameworkStockDomainSharedModule.cs b/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Domain.Shared/YiFrameworkStockDomainSharedModule.cs similarity index 100% rename from Yi.Abp.Net8/module/stock/Yi.Framework.Stock.Domain.Shared/YiFrameworkStockDomainSharedModule.cs rename to Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Domain.Shared/YiFrameworkStockDomainSharedModule.cs diff --git a/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Domain/Entities/StockHoldingAggregateRoot.cs b/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Domain/Entities/StockHoldingAggregateRoot.cs new file mode 100644 index 00000000..4d815593 --- /dev/null +++ b/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Domain/Entities/StockHoldingAggregateRoot.cs @@ -0,0 +1,141 @@ +using SqlSugar; +using Volo.Abp.Auditing; +using Volo.Abp.Domain.Entities; +using Yi.Framework.Core.Data; + +namespace Yi.Framework.Stock.Domain.Entities +{ + /// + /// 用户股票持仓聚合根 + /// + /// + /// 记录用户持有的股票数量和相关信息 + /// + [SugarTable("Stock_Holding")] + public class StockHoldingAggregateRoot : AggregateRoot, ISoftDelete, IAuditedObject + { + + /// + /// 逻辑删除 + /// + public bool IsDeleted { get; set; } + + /// + /// 创建时间 + /// + public DateTime CreationTime { get; set; } = DateTime.Now; + + /// + /// 创建者 + /// + public Guid? CreatorId { get; set; } + + /// + /// 最后修改者 + /// + public Guid? LastModifierId { get; set; } + + /// + /// 最后修改时间 + /// + public DateTime? LastModificationTime { get; set; } + + /// + /// 用户ID + /// + /// 关联到持有股票的用户 + public Guid UserId { get; set; } + + /// + /// 股票ID + /// + /// 关联到具体的股票 + public Guid StockId { get; set; } + + /// + /// 股票代码 + /// + /// 冗余字段,方便查询 + public string StockCode { get; set; } = string.Empty; + + /// + /// 股票名称 + /// + /// 冗余字段,方便查询 + public string StockName { get; set; } = string.Empty; + + /// + /// 持有数量 + /// + /// 用户持有的股票数量 + public int Quantity { get; set; } + + /// + /// 平均成本价 + /// + /// 用户购买这些股票的平均成本价 + public decimal AverageCostPrice { get; set; } + + /// + /// 持仓成本 + /// + /// 总投入成本 = 平均成本价 * 持有数量 + [SugarColumn(IsIgnore = true)] + public decimal TotalCost => AverageCostPrice * Quantity; + + public StockHoldingAggregateRoot() { } + + public StockHoldingAggregateRoot( + Guid userId, + Guid stockId, + string stockCode, + string stockName, + int quantity, + decimal averageCostPrice) + { + UserId = userId; + StockId = stockId; + StockCode = stockCode; + StockName = stockName; + Quantity = quantity; + AverageCostPrice = averageCostPrice; + } + + /// + /// 增加持仓数量 + /// + /// 增加的数量 + /// 本次购买价格 + public void AddQuantity(int quantity, decimal price) + { + if (quantity <= 0) + throw new ArgumentException("增加的数量必须大于0"); + + // 计算新的平均成本价 + decimal totalCost = AverageCostPrice * Quantity + price * quantity; + Quantity += quantity; + AverageCostPrice = totalCost / Quantity; + } + + /// + /// 减少持仓数量 + /// + /// 减少的数量 + public void ReduceQuantity(int quantity) + { + if (quantity <= 0) + throw new ArgumentException("减少的数量必须大于0"); + + if (quantity > Quantity) + throw new ArgumentException("减少的数量不能大于持有数量"); + + Quantity -= quantity; + + // 如果数量为0,标记为删除 + if (Quantity == 0) + { + IsDeleted = true; + } + } + } +} \ No newline at end of file diff --git a/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Domain/Entities/StockMarketAggregateRoot.cs b/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Domain/Entities/StockMarketAggregateRoot.cs new file mode 100644 index 00000000..ba9d2741 --- /dev/null +++ b/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Domain/Entities/StockMarketAggregateRoot.cs @@ -0,0 +1,81 @@ +using SqlSugar; +using Volo.Abp.Auditing; +using Volo.Abp.Domain.Entities; +using Yi.Framework.Core.Data; + +namespace Yi.Framework.Stock.Domain.Entities +{ + /// + /// 股市聚合根实体 + /// + /// + /// 用于定义有哪些公司上架的股市 + /// + [SugarTable("Stock_Market")] + public class StockMarketAggregateRoot : AggregateRoot, ISoftDelete, IAuditedObject, IOrderNum, IState + { + /// + /// 逻辑删除 + /// + public bool IsDeleted { get; set; } + + /// + /// 创建时间 + /// + public DateTime CreationTime { get; set; } = DateTime.Now; + + /// + /// 创建者 + /// + public Guid? CreatorId { get; set; } + + /// + /// 最后修改者 + /// + public Guid? LastModifierId { get; set; } + + /// + /// 最后修改时间 + /// + public DateTime? LastModificationTime { get; set; } + + /// + /// 排序 + /// + public int OrderNum { get; set; } = 0; + + /// + /// 状态 + /// + public bool State { get; set; } = true; + + /// + /// 股市代码 + /// + /// 如:SH、SZ、HK等 + public string MarketCode { get; set; } = string.Empty; + + /// + /// 股市名称 + /// + /// 如:上海证券交易所、深圳证券交易所等 + public string MarketName { get; set; } = string.Empty; + + /// + /// 股市描述 + /// + public string Description { get; set; } = string.Empty; + + public StockMarketAggregateRoot() { } + + public StockMarketAggregateRoot( + string marketCode, + string marketName, + string description = "") + { + MarketCode = marketCode; + MarketName = marketName; + Description = description; + } + } +} \ No newline at end of file diff --git a/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Domain/Entities/StockNewsAggregateRoot.cs b/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Domain/Entities/StockNewsAggregateRoot.cs new file mode 100644 index 00000000..f1062336 --- /dev/null +++ b/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Domain/Entities/StockNewsAggregateRoot.cs @@ -0,0 +1,81 @@ +using SqlSugar; +using Volo.Abp.Auditing; +using Volo.Abp.Domain.Entities; +using Yi.Framework.Core.Data; + +namespace Yi.Framework.Stock.Domain.Entities +{ + /// + /// 股市新闻聚合根实体 + /// + /// + /// 用于记录影响股市波动的新闻事件 + /// + [SugarTable("Stock_News")] + public class StockNewsAggregateRoot : AggregateRoot, ISoftDelete, IAuditedObject, IOrderNum + { + /// + /// 逻辑删除 + /// + public bool IsDeleted { get; set; } + + /// + /// 创建时间 + /// + public DateTime CreationTime { get; set; } = DateTime.Now; + + /// + /// 创建者ID + /// + public Guid? CreatorId { get; set; } + + /// + /// 最后修改时间 + /// + public DateTime? LastModificationTime { get; set; } + + /// + /// 最后修改者ID + /// + public Guid? LastModifierId { get; set; } + + /// + /// 排序号 + /// + public int OrderNum { get; set; } = 0; + + /// + /// 新闻标题 + /// + public string Title { get; set; } = string.Empty; + + /// + /// 新闻内容 + /// + public string Content { get; set; } = string.Empty; + + /// + /// 发布时间 + /// + public DateTime PublishTime { get; set; } = DateTime.Now; + + /// + /// 新闻来源 + /// + public string Source { get; set; } = string.Empty; + + public StockNewsAggregateRoot() { } + + public StockNewsAggregateRoot( + string title, + string content, + string source = "") + { + Title = title; + Content = content; + Source = source; + PublishTime = DateTime.Now; + } + + } +} \ No newline at end of file diff --git a/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Domain/Entities/StockPriceRecordEntity.cs b/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Domain/Entities/StockPriceRecordEntity.cs new file mode 100644 index 00000000..26479c14 --- /dev/null +++ b/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Domain/Entities/StockPriceRecordEntity.cs @@ -0,0 +1,72 @@ +using SqlSugar; +using Volo.Abp.Domain.Entities; +using Volo.Abp.Auditing; +using Yi.Framework.Stock.Domain.Shared; + +namespace Yi.Framework.Stock.Domain.Entities +{ + /// + /// 股票价格记录实体 + /// + /// + /// 用于记录每支股票在不同时间点的价格数据,支持趋势分析和图表展示 + /// + [SugarTable("Stock_PriceRecord")] + public class StockPriceRecordEntity : Entity, IHasCreationTime + { + + /// + /// 股票ID + /// + /// 关联到具体的股票 + public Guid StockId { get; set; } + + /// + /// 记录时间 + /// + /// 价格记录的时间点 + public DateTime CreationTime { get; set; } + + /// + /// 当前价 + /// + public decimal CurrentPrice { get; set; } + + /// + /// 交易量 + /// + /// 该时间段内的交易股数 + public long Volume { get; set; } + + /// + /// 交易额 + /// + /// 该时间段内的交易金额 + public decimal Turnover { get; set; } + + /// + /// 时间周期类型 + /// + /// + /// 记录的时间周期类型:分钟、小时、日、周、月等 + /// + public PeriodTypeEnum PeriodType { get; set; } + + public StockPriceRecordEntity() { } + + public StockPriceRecordEntity( + Guid stockId, + decimal currentPrice, + long volume = 0, + decimal turnover = 0, + PeriodTypeEnum periodType = PeriodTypeEnum.Day) + { + StockId = stockId; + CreationTime = DateTime.Now; + CurrentPrice = currentPrice; + Volume = volume; + Turnover = turnover; + PeriodType = periodType; + } + } +} \ No newline at end of file diff --git a/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Domain/Entities/StockTransactionEntity.cs b/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Domain/Entities/StockTransactionEntity.cs new file mode 100644 index 00000000..389a60e4 --- /dev/null +++ b/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Domain/Entities/StockTransactionEntity.cs @@ -0,0 +1,121 @@ +using SqlSugar; +using Volo.Abp.Domain.Entities; +using Volo.Abp.Auditing; +using Yi.Framework.Stock.Domain.Shared; + +namespace Yi.Framework.Stock.Domain.Entities +{ + /// + /// 股票交易记录实体 + /// + /// + /// 用于记录用户买入或卖出股票的交易历史 + /// + [SugarTable("Stock_Transaction")] + public class StockTransactionEntity : Entity, IAuditedObject + { + /// + /// 用户ID + /// + /// 进行交易的用户 + public Guid UserId { get; set; } + + /// + /// 股票ID + /// + /// 交易的股票 + public Guid StockId { get; set; } + + /// + /// 股票代码 + /// + /// 冗余字段,方便查询 + public string StockCode { get; set; } = string.Empty; + + /// + /// 股票名称 + /// + /// 冗余字段,方便查询 + public string StockName { get; set; } = string.Empty; + + /// + /// 交易类型 + /// + public TransactionTypeEnum TransactionType { get; set; } + + /// + /// 交易价格 + /// + /// 股票的单价 + public decimal Price { get; set; } + + /// + /// 交易数量 + /// + /// 买入或卖出的股票数量 + public int Quantity { get; set; } + + /// + /// 交易总额 + /// + /// 价格 × 数量 + public decimal TotalAmount { get; set; } + + /// + /// 交易费用 + /// + /// 手续费、佣金等 + public decimal Fee { get; set; } + + /// + /// 创建时间 + /// + /// 交易发生时间 + public DateTime CreationTime { get; set; } + + /// + /// 创建者ID + /// + public Guid? CreatorId { get; set; } + + /// + /// 最后修改时间 + /// + public DateTime? LastModificationTime { get; set; } + + /// + /// 最后修改者ID + /// + public Guid? LastModifierId { get; set; } + + /// + /// 备注 + /// + public string Remark { get; set; } = string.Empty; + + public StockTransactionEntity() { } + + public StockTransactionEntity( + Guid userId, + Guid stockId, + string stockCode, + string stockName, + TransactionTypeEnum transactionType, + decimal price, + int quantity, + decimal fee = 0) + { + Id = Guid.NewGuid(); + UserId = userId; + StockId = stockId; + StockCode = stockCode; + StockName = stockName; + TransactionType = transactionType; + Price = price; + Quantity = quantity; + TotalAmount = price * quantity; + Fee = fee; + CreationTime = DateTime.Now; + } + } +} \ No newline at end of file diff --git a/Yi.Abp.Net8/module/stock/Yi.Framework.Stock.Domain/Yi.Framework.Stock.Domain.csproj b/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Domain/Yi.Framework.Stock.Domain.csproj similarity index 95% rename from Yi.Abp.Net8/module/stock/Yi.Framework.Stock.Domain/Yi.Framework.Stock.Domain.csproj rename to Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Domain/Yi.Framework.Stock.Domain.csproj index 67c7f81e..e65240f4 100644 --- a/Yi.Abp.Net8/module/stock/Yi.Framework.Stock.Domain/Yi.Framework.Stock.Domain.csproj +++ b/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Domain/Yi.Framework.Stock.Domain.csproj @@ -14,7 +14,6 @@ - diff --git a/Yi.Abp.Net8/module/stock/Yi.Framework.Stock.Domain/YiFrameworkStockDomainModule.cs b/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Domain/YiFrameworkStockDomainModule.cs similarity index 100% rename from Yi.Abp.Net8/module/stock/Yi.Framework.Stock.Domain/YiFrameworkStockDomainModule.cs rename to Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.Domain/YiFrameworkStockDomainModule.cs diff --git a/Yi.Abp.Net8/module/stock/Yi.Framework.Stock.SqlSugarCore/Yi.Framework.Stock.SqlSugarCore.csproj b/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.SqlSugarCore/Yi.Framework.Stock.SqlSugarCore.csproj similarity index 100% rename from Yi.Abp.Net8/module/stock/Yi.Framework.Stock.SqlSugarCore/Yi.Framework.Stock.SqlSugarCore.csproj rename to Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.SqlSugarCore/Yi.Framework.Stock.SqlSugarCore.csproj diff --git a/Yi.Abp.Net8/module/stock/Yi.Framework.Stock.SqlSugarCore/YiFrameworkStockSqlSugarCoreModule.cs b/Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.SqlSugarCore/YiFrameworkStockSqlSugarCoreModule.cs similarity index 100% rename from Yi.Abp.Net8/module/stock/Yi.Framework.Stock.SqlSugarCore/YiFrameworkStockSqlSugarCoreModule.cs rename to Yi.Abp.Net8/module/ai-stock/Yi.Framework.Stock.SqlSugarCore/YiFrameworkStockSqlSugarCoreModule.cs diff --git a/Yi.Abp.Net8/module/stock/Yi.Framework.Stock.Application/Services/TestService.cs b/Yi.Abp.Net8/module/stock/Yi.Framework.Stock.Application/Services/TestService.cs deleted file mode 100644 index c78b7006..00000000 --- a/Yi.Abp.Net8/module/stock/Yi.Framework.Stock.Application/Services/TestService.cs +++ /dev/null @@ -1,15 +0,0 @@ -using Volo.Abp.Application.Services; - -namespace Yi.Framework.Stock.Application.Services -{ - /// - /// 常用魔改及扩展示例 - /// - public class TestService : ApplicationService - { - public string TTT() - { - return "你好"; - } - } -} diff --git a/Yi.Abp.Net8/src/Yi.Abp.Application/Yi.Abp.Application.csproj b/Yi.Abp.Net8/src/Yi.Abp.Application/Yi.Abp.Application.csproj index 4d6a10cf..97b45b8c 100644 --- a/Yi.Abp.Net8/src/Yi.Abp.Application/Yi.Abp.Application.csproj +++ b/Yi.Abp.Net8/src/Yi.Abp.Application/Yi.Abp.Application.csproj @@ -10,7 +10,7 @@ - + diff --git a/Yi.Abp.Net8/src/Yi.Abp.SqlSugarCore/Yi.Abp.SqlSugarCore.csproj b/Yi.Abp.Net8/src/Yi.Abp.SqlSugarCore/Yi.Abp.SqlSugarCore.csproj index 28f8e04b..d6aec39f 100644 --- a/Yi.Abp.Net8/src/Yi.Abp.SqlSugarCore/Yi.Abp.SqlSugarCore.csproj +++ b/Yi.Abp.Net8/src/Yi.Abp.SqlSugarCore/Yi.Abp.SqlSugarCore.csproj @@ -11,7 +11,7 @@ - + diff --git a/Yi.Abp.Net8/src/Yi.Abp.Web/YiAbpWebModule.cs b/Yi.Abp.Net8/src/Yi.Abp.Web/YiAbpWebModule.cs index e2a8b421..fdb307af 100644 --- a/Yi.Abp.Net8/src/Yi.Abp.Web/YiAbpWebModule.cs +++ b/Yi.Abp.Net8/src/Yi.Abp.Web/YiAbpWebModule.cs @@ -94,7 +94,7 @@ namespace Yi.Abp.Web options.ConventionalControllers.Create(typeof(YiFrameworkDigitalCollectiblesApplicationModule).Assembly, options => options.RemoteServiceName = "digital-collectibles"); options.ConventionalControllers.Create(typeof(YiFrameworkStockApplicationModule).Assembly, - options => options.RemoteServiceName = "stock"); + options => options.RemoteServiceName = "ai-stock"); //统一前缀 options.ConventionalControllers.ConventionalControllerSettings.ForEach(x => x.RootPath = "api/app"); });