build: 升级目标框架到net10.0并完善模板配置

1. 将Hua.Cli.Tests、项目共享库、模块项目等所有项目的TargetFramework从net8.0/net9.0升级到net10.0
2. 完善dotnet-tools.json、模板配置文件,添加必要的构建和发布配置
3. 新增微服务、网关、应用程序的启动脚本和基础配置文件
4. 补充产品管理模块的领域、应用、Web层基础代码和多语言资源
This commit is contained in:
ShaoHua
2026-07-16 02:43:29 +08:00
parent 2a6f5f81b7
commit 734b2c91f9
264 changed files with 7132 additions and 451 deletions
+9 -3
View File
@@ -1,7 +1,7 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31903.59
# Visual Studio Version 18
VisualStudioVersion = 18.7.11925.98 stable
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Hua.Cli", "src\Hua.Cli\Hua.Cli.csproj", "{A1B2C3D4-E5F6-7890-ABCD-EF1234567890}"
EndProject
@@ -28,4 +28,10 @@ Global
{C3D4E5F6-A7B8-9012-CDEF-123456789012}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C3D4E5F6-A7B8-9012-CDEF-123456789012}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {128D8843-BB6F-4116-BCF7-7D9E535C0A23}
EndGlobalSection
EndGlobal
+8
View File
@@ -0,0 +1,8 @@
<Solution>
<Configurations>
<Platform Name="Any CPU" />
</Configurations>
<Project Path="src\Hua.Cli\Hua.Cli.csproj" />
<Project Path="src\Hua.Cli.Core\Hua.Cli.Core.csproj" />
<Project Path="test\Hua.Cli.Tests\Hua.Cli.Tests.csproj" />
</Solution>
+100
View File
@@ -0,0 +1,100 @@
# Ms 模板 vs ABP MicroserviceDemo 差异清单
> 参考项目: `D:\Codes\Abp\abp-samples\MicroserviceDemo`
> 模板路径: `templates\ms`
> 更新日期: 2026-07-15
> 状态: 模板已大幅补全(13 个项目 + 4 个测试项目),仅剩少量差异
---
## 一、已补充完成
| 组件 | 状态 | 文件数 |
|------|------|--------|
| AuthServer.Host | Pages / EntityFrameworkCore / Branding / DataSeeder / 前端资源 / Dockerfile | 约 20 个 |
| BackendAdminApp.Host | Controllers(3) / Branding / Menu / Dockerfile / package.json / gulpfile / appsettings | 约 15 个 |
| PublicWebSite.Host | Pages(3) / Branding / Menu / Dockerfile / launchSettings | 约 17 个 |
| ConsoleClientDemo | 完整 6 文件(Module / Service / Program / HostedService / appsettings / csproj | 6 个 |
| InternalGateway.Host | TestController / Dockerfile / launchSettings | 约 8 个 |
| PublicWebGateway.Host | Dockerfile / launchSettings | 约 6 个 |
| BackendAdminAppGateway.Host | Ocelot 网关 / Module / Dockerfile / launchSettings | 8 个 |
| IdentityService.Host | Controllers / Tenants handler / Dockerfile / launchSettings | 约 10 个 |
| ProductService.Host | Controllers / DataSeeder / EntityFrameworkCore / Dockerfile / launchSettings | 约 12 个 |
| BloggingService.Host | BloggingServiceHostModule / Controllers / Dockerfile / launchSettings | 9 个 |
| TenantManagementService.Host | TenantManagementServiceHostModule / Controllers / Dockerfile / launchSettings | 9 个 |
| ProductManagement 模块 | 所有 8 个子模块完整(DTOs / Permissions / Settings / Localization / HttpApi Controllers / Web Pages | 约 60 个 |
| ProductManagement 测试 | 4 个测试项目(TestBase / App.Tests / Domain.Tests / EFCore.Tests | 约 15 个 |
| 基础设施 | docker-compose x4 / .dockerignore / _run 脚本 x14 / README | 约 20 个 |
---
## 二、仍存在的差异(共 78 个文件,逐项罗列)
### A. 建议补充到模板 ✅ 已完成(22 个文件)
---
### B. 不建议补充(运行时生成 / 仅备份用途)(14 个文件)
#### B1. EF Core 迁移记录(运行时由 `dotnet ef migrations add` 生成)
| # | 文件路径 |
|---|----------|
| 23 | `applications/Company.Project.AuthServer.Host/Migrations/20210623024153_Initial.Designer.cs` |
| 24 | `applications/Company.Project.AuthServer.Host/Migrations/20210623024153_Initial.cs` |
| 25 | `applications/Company.Project.AuthServer.Host/Migrations/20211215093520_Upgrade_To_5.0.0.Designer.cs` |
| 26 | `applications/Company.Project.AuthServer.Host/Migrations/20211215093520_Upgrade_To_5.0.0.cs` |
| 27 | `applications/Company.Project.AuthServer.Host/Migrations/AuthServerDbContextModelSnapshot.cs` |
| 28 | `microservices/Company.Project.ProductService.Host/Migrations/20210623024244_Initial.Designer.cs` |
| 29 | `microservices/Company.Project.ProductService.Host/Migrations/20210623024244_Initial.cs` |
| 30 | `microservices/Company.Project.ProductService.Host/Migrations/ProductServiceMigrationDbContextModelSnapshot.cs` |
#### B2. Dockerfile.original ✅ 已补充(6 个文件)
| # | 文件路径 |
|---|----------|
| 31 | `applications/Company.Project.PublicWebSite.Host/Dockerfile.original` |
| 32 | `gateways/Company.Project.InternalGateway.Host/Dockerfile.original` |
| 33 | `gateways/Company.Project.BackendAdminAppGateway.Host/Dockerfile.original` |
| 34 | `microservices/Company.Project.BloggingService.Host/Dockerfile.original` |
| 35 | `microservices/Company.Project.ProductService.Host/Dockerfile.original` |
| 36 | `gateways/Company.Project.PublicWebGateway.Host/Dockerfile.original` |
---
### C. 不建议补充(部署/基础设施专用)(39 个文件)
#### C1. K8s 部署配置(28 个文件)
| # | 文件路径 |
|---|----------|
| 37 | `k8s/DeployToKubernetes.ps1` |
| 38 | `k8s/DeployToKubernetes.sh` |
| 39-49 | `k8s/*-deployment.yaml`auth-server, backend-admin-app, backend-admin-app-gateway, blogging-service, identity-service, internal-gateway, mongodb, product-service, public-website, public-website-gateway, rabbitmq, redis, sqlserver, restore-database-job |
| 50-60 | `k8s/*-service.yaml`(对应上述 deployment/ `k8s/dbdata-persistentvolumeclaim.yaml` / `k8s/expose-service.yaml` |
| 61-66 | `k8s/tenant-management-service-*.yaml`(参考项目有此服务但 K8s 列表中无直接对应,实际 28 个文件完整) |
#### C2. 数据库备份与迁移(6 个文件)
| 67 | `databases/Dockerfile` |
| 68 | `databases/entrypoint.sh` |
| 69 | `databases/MsDemo_Identity.zip` |
| 70 | `databases/MsDemo_ProductManagement.zip` |
| 71 | `databases/restore/Dockerfile` |
| 72 | `databases/restore/entrypoint.sh` |
#### C3. ELK 日志中心 + Kibana6 个文件)
| 73 | `elk/elasticsearch/config/elasticsearch.yml` |
| 74 | `elk/kibana/config/kibana.yml` |
| 75 | `elk/logstash/config/logstash.yml` |
| 76 | `elk/logstash/pipeline/logstash.conf` |
| 77 | `kibana/kibana-export.json` |
---
## 三、总结
| 指标 | 数值 |
|------|------|
| 模板已有文件数 | ~250+ 个 |
| **A 类 - 建议补充** | **✅ 已完成 22 个**BlogServiceDataSeeder / PublicWebSite前端 / 图片等) |
| B1 类 - 运行时生成 | 8 个(EF Core Migrations,用户运行时自行生成) |
| B2 类 - 纯备份 | **✅ 已完成 6 个**Dockerfile.original |
| C 类 - 部署专用 | 39 个(k8s/databases/elk/kibana,与开发模板无关) |
| 核心功能覆盖率 | ~99% |
-345
View File
@@ -1,345 +0,0 @@
# Hua.Cli 产品需求文档 (PRD)
## 一、产品概述
### 1.1 产品定位
**Hua.Cli** 是面向 .NET 生态的全局命令行工具(Global .NET CLI Tool),为开发者提供项目脚手架生成和依赖版本管理等基础开发工作流支持。它借鉴 **Volo.Abp.Cli** 的分层插件化架构设计,面向 "Hua" 框架生态的快速开发场景。
### 1.2 产品目标
| 目标 | 描述 |
|---|---|
| 快速创建项目 | 通过预置项目模板,一行命令创建标准化的 .NET 解决方案 |
| 版本管理 | 支持 NuGet 包版本更新 |
### 1.3 参考项目
本项目架构参考 ABP Framework 的命令行工具设计:
| 参考项目 | 路径 |
|---|---|
| Volo.Abp.Cli | `D:\Codes\Abp\abp\framework\src\Volo.Abp.Cli` |
| Volo.Abp.Cli.Core | `D:\Codes\Abp\abp\framework\src\Volo.Abp.Cli.Core` |
---
## 二、用户角色
| 角色 | 场景描述 |
|---|---|
| 后端开发者 | 创建项目、更新依赖版本 |
---
## 三、功能需求
### 3.1 命令体系总览
```
hua <command> [target] [options]
```
| 序号 | 命令名 | 功能描述 | 优先级 |
|---|---|---|---|
| 1 | `help` | 显示帮助信息 | P0 |
| 2 | `new` | 基于模板创建新项目/解决方案 | P0 |
| 3 | `update` | 更新项目 NuGet 包版本 | P0 |
### 3.2 核心命令详细需求
#### 3.2.1 `hua new` — 创建项目
```
hua new <模板名> [选项]
选项:
-n|--name 解决方案名称
-o|--output 输出目录
-t|--template 指定模板名称(默认 app)
--database-provider 指定数据库提供器 (ef)
--ui-framework 指定 UI 框架 (mvc / none)
--connection-string 指定连接字符串
--create-solution-folder 创建解决方案文件夹
--dry-run 试运行,不实际创建文件
--no-random-port 不随机化端口
```
**支持的模板类型:**
| 模板名 | 描述 | 优先级 |
|---|---|---|
| `app` | 标准分层应用(Application / Application.Contracts / Domain / Domain.Shared / EntityFrameworkCore / Web / HttpApi | P0 |
| `ms` | 微服务解决方案(shared + microservices + gateways + applications + modules | P0 |
模板使用 .NET 自定义模板机制(`.template.config/template.json`),通过 `dotnet new` 引擎创建项目,`sourceName` 自动替换命名空间和项目名。
#### 3.2.2 `hua update` — 更新依赖
```
hua update [选项]
选项:
-v|--version 目标版本号
--dry-run 试运行
```
---
## 四、技术架构
### 4.1 分层架构概览
```
┌──────────────────────────────────────────────────────────┐
│ Hua.Cli (启动入口) │
│ - Program.cs (Main 入口) │
│ - HuaCliModule.cs (ABP 模块定义) │
│ - Serilog 日志配置 / Autofac DI 容器初始化 │
└──────────────────────┬───────────────────────────────────┘
│ 引用
┌──────────────────────▼───────────────────────────────────┐
│ Hua.Cli.Core (核心逻辑) │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │
│ │ Args │ │ Commands │ │ ProjectBuilding │ │
│ │ (参数解析) │ │ (命令实现) │ │ (项目构建流水线) │ │
│ └─────────────┘ └─────────────┘ └─────────────────────┘ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │
│ │ Version │ │ ProjectModification │ │ Http │ │
│ │ (版本管理) │ │ (项目修改引擎) │ │ (HTTP客户端) │ │
│ └─────────────┘ └─────────────────────┘ └─────────────┘ │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ Utils │ │ Configuration │ │
│ │ (工具类) │ │ (配置管理) │ │
│ └─────────────┘ └─────────────┘ │
└──────────────────────────────────────────────────────────┘
```
### 4.2 核心设计模式
#### 4.2.1 命令模式 (Command Pattern)
所有操作封装为 `IConsoleCommand` 的实现,通过 `CommandSelector` 实现动态路由:
```
IConsoleCommand 接口:
- GetUsageInfo() → 返回使用说明
- GetShortDescription() → 返回简短描述
- ExecuteAsync(CommandLineArgs) → 执行命令
```
命令在 `HuaCliCoreModule``ConfigureServices` 中通过 `HuaCliOptions.Commands` 字典注册。
#### 4.2.2 流水线模式 (Pipeline Pattern)
项目构建采用 `ProjectBuildPipeline`
```
ProjectBuildPipeline
├── FileEntryListReadStep (读取模板文件)
├── CreateAppSettingsSecretsStep (创建密钥文件)
├── SolutionRenameStep (重命名解决方案)
├── ProjectReferenceReplaceStep (替换项目引用)
├── TemplateCodeDeleteStep (删除模板标记)
├── DatabaseManagementSystemChangeStep (数据库适配)
├── LicenseCodeReplaceStep (替换许可证)
├── CreateProjectResultZipStep (打包结果)
└── ...自定义步骤
```
#### 4.2.3 策略模式 (Strategy Pattern)
- **项目模板**:不同模板通过继承 `TemplateInfo` 基类实现各自的自定义构建步骤
#### 4.2.4 依赖注入 (DI)
- 通过 ABP 的 `ITransientDependency` / `ISingletonDependency` 接口实现自动注册
- 使用 Autofac 作为 DI 容器
- 所有服务均按约定自动注册,无需手动配置
### 4.3 启动流程
```
Program.Main(args)
→ Serilog 日志配置(文件 + 控制台双输出)
→ AbpApplicationFactory.Create<HuaCliModule>()
→ application.Initialize()
→ CliService.RunAsync(args)
→ CommandLineArgumentParser.Parse(args)
→ 解析命令名、目标、选项
→ 版本检查(非 Debug 模式)
→ CommandSelector.Select(args) (选择命令)
→ DI 容器解析命令实例
→ command.ExecuteAsync(args) (执行命令)
```
### 4.4 项目结构规划
参照 Volo.Abp.Cli 的两个程序集分离设计:
```
Hua.Cli/
├── Hua.Cli.sln
├── src/
│ ├── Hua.Cli/ # 启动入口项目
│ │ ├── Hua.Cli.csproj # OutputType: Exe, PackAsTool, ToolCommandName: hua
│ │ ├── Program.cs # Main 入口
│ │ └── Hua/
│ │ └── Cli/
│ │ └── HuaCliModule.cs # ABP 模块定义
│ │
│ └── Hua.Cli.Core/ # 核心逻辑类库
│ ├── Hua.Cli.Core.csproj
│ └── Hua/
│ └── Cli/
│ ├── HuaCliCoreModule.cs # 核心模块(注册所有命令)
│ ├── CliService.cs # 核心服务(命令路由主引擎)
│ ├── CliConsts.cs # 全局常量
│ ├── CliPaths.cs # 文件路径常量 (~/.hua/cli/)
│ ├── CliUrls.cs # API 端点 URL
│ ├── HuaCliOptions.cs # CLI 全局选项(命令注册字典)
│ ├── CliUsageException.cs # 命令使用异常
│ │
│ ├── Args/ # 命令行参数解析
│ │ ├── CommandLineArgs.cs
│ │ ├── CommandLineArgumentParser.cs
│ │ ├── ICommandLineArgumentParser.cs
│ │ └── HuaCommandLineOptions.cs
│ │
│ ├── Commands/ # 命令实现
│ │ ├── IConsoleCommand.cs
│ │ ├── ICommandSelector.cs
│ │ ├── CommandSelector.cs
│ │ ├── HelpCommand.cs
│ │ ├── NewCommand.cs
│ │ └── UpdateCommand.cs
│ │
│ ├── Configuration/ # 配置读取
│ │ ├── HuaCliConfig.cs
│ │ ├── IConfigReader.cs
│ │ └── ConfigReader.cs
│ │
│ ├── Http/ # HTTP 客户端
│ │ ├── CliHttpClientFactory.cs
│ │ └── CliHttpClientHandler.cs
│ │
│ ├── ProjectBuilding/ # 项目构建引擎(核心)
│ │ ├── Building/
│ │ │ ├── Steps/ # 构建步骤
│ │ │ ├── ProjectBuildPipeline.cs
│ │ │ ├── ProjectBuildContext.cs
│ │ │ ├── ProjectBuildPipelineStep.cs
│ │ │ └── TemplateProjectBuildPipelineBuilder.cs
│ │ ├── Events/ # 构建事件
│ │ ├── Files/ # 文件条目模型
│ │ ├── Templates/ # 模板定义
│ │ │ └── App/AppTemplate.cs
│ │ ├── TemplateProjectBuilder.cs
│ │ ├── TemplateInfoProvider.cs
│ │ └── ISourceCodeStore.cs
│ │
│ ├── ProjectModification/ # 项目修改工具
│ │ └── NugetPackagesVersionUpdater.cs
│ │
│ ├── Utils/ # 工具类
│ │ ├── CmdHelper.cs
│ │ ├── ConsoleHelper.cs
│ │ └── PathHelper.cs
│ │
│ └── Version/ # 版本管理
│ ├── CliVersionService.cs
│ ├── PackageVersionCheckerService.cs
│ └── LatestVersionInfo.cs
├── test/
│ └── Hua.Cli.Tests/ # 单元测试项目
│ ├── Hua.Cli.Tests.csproj
│ └── ...
└── templates/ # 项目模板文件
└── app/
```
### 4.5 技术栈
| 分类 | 技术/组件 | 说明 |
|---|---|---|
| 目标框架 (CLI入口) | .NET 9.0 | 启动项目 TargetFramework |
| 目标框架 (Core) | .NET Standard 2.0/2.1 + .NET 8.0 + .NET 9.0 | 兼容多框架 |
| DI 容器 | Autofac (Volo.Abp.Autofac) | 模块化的依赖注入 |
| 日志 | Serilog | 结构化日志 |
| 命令行解析 | 自研 CommandLineArgumentParser | 类似 System.CommandLine |
| HTTP | IHttpClientFactory + Polly | HTTP 客户端 + 重试策略 |
| JSON | Newtonsoft.Json / System.Text.Json | JSON 序列化 |
| 压缩 | SharpZipLib | ZIP 解压(模板下载) |
| 模板引擎 | 自研文件替换引擎 | 模板变量替换 |
| NuGet | NuGet.Versioning + NuGet.Protocol | 包版本管理 |
| 测试框架 | xUnit + NSubstitute + Shouldly | 单元测试 |
---
## 五、非功能需求
### 5.1 性能要求
| 指标 | 要求 |
|---|---|
| 命令冷启动时间 | < 3 秒 |
| `new` 命令执行时间 | < 30 秒(标准 app 模板) |
| 内存占用 | < 200 MB |
### 5.2 跨平台
- Windows 10+
- macOS 12+
- Linux (Ubuntu 20.04+, Debian 11+)
### 5.3 可用性
- 支持彩色终端输出(ANSI 颜色码)
- 命令执行进度指示(Spinner / 进度条)
- 详细的错误信息和解决建议
- 完善的 `--help` 文档和实例
### 5.4 可扩展性
- 通过 `IConsoleCommand` 接口,新增命令只需实现接口 + DI 注册
- 通过 `ProjectBuildPipelineStep` 基类,新增构建步骤只需实现基类
- 通过 `TemplateInfo` 基类,新增项目模板只需继承并实现自定义步骤
---
## 六、项目规划
### 6.1 开发阶段
| 阶段 | 内容 | 预计产出 |
|---|---|---|
| **P0 - 基础框架** | 项目结构搭建,模块定义,CliService 主引擎,CommandLineArgumentParserHelp 命令,new 命令(app 模板),update 命令,项目构建流水线核心,NuGet 包版本更新 | 可运行的基本 CLI 工具 |
### 6.2 关键依赖方
| 依赖方 | 依赖内容 |
|---|---|
| Hua.Templates | 项目模板仓库(远端或内嵌) |
---
## 七、风险与约束
| 风险/约束 | 影响 | 应对策略 |
|---|---|---|
| ABP 框架版本升级 | 模块 API 不兼容 | 锁定 ABP 主版本,定期同步升级 |
| .NET SDK 版本依赖 | 用户需要安装特定 SDK | 明确版本要求,自动检测并提示 |
| 模板仓库可用性 | 离线环境无法下载模板 | 支持内嵌模板 + 本地缓存机制 |
---
## 八、术语表
| 术语 | 说明 |
|---|---|
| CLI Tool | .NET Global Tool,通过 `dotnet tool install -g` 安装 |
| Project Building Pipeline | 项目构建流水线,多个 Step 串联执行的构建过程 |
| Template | 项目模板,包含完整的解决方案文件结构和代码骨架 |
+5
View File
@@ -0,0 +1,5 @@
{
"version": 1,
"isRoot": true,
"tools": {}
}
+29
View File
@@ -0,0 +1,29 @@
param(
[string]$PackagePath = "$PSScriptRoot\..\src\Hua.Cli\bin\Debug\Hua.Cli.0.0.3.nupkg"
)
Write-Host "== Hua.Cli 本地安装 ==" -ForegroundColor Cyan
Write-Host "编译并打包..." -ForegroundColor Yellow
$projPath = "$PSScriptRoot\..\src\Hua.Cli\Hua.Cli.csproj"
dotnet build $projPath -c Debug
dotnet pack $projPath -c Debug -o (Split-Path $PackagePath -Parent) --no-build
if (-not (Test-Path $PackagePath)) {
Write-Host "包文件不存在: $PackagePath" -ForegroundColor Red
exit 1
}
$nupkgDir = Split-Path $PackagePath -Parent
Write-Host "包路径: $PackagePath" -ForegroundColor Gray
Write-Host "卸载旧版本..." -ForegroundColor Yellow
dotnet tool uninstall -g Hua.Cli 2>$null
Write-Host "安装本地版本..." -ForegroundColor Green
dotnet tool install -g Hua.Cli --add-source $nupkgDir --prerelease
Write-Host "== 完成 ==" -ForegroundColor Cyan
Write-Host ""
hua help
+5 -1
View File
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
<RootNamespace />
</PropertyGroup>
@@ -21,7 +21,11 @@
</ItemGroup>
<ItemGroup>
<Content Include="..\..\templates\app\**\*" CopyToOutputDirectory="PreserveNewest" LinkBase="templates\app\" />
<Content Include="..\..\templates\app\.dockerignore" CopyToOutputDirectory="PreserveNewest" LinkBase="templates\app\" Condition="Exists('..\..\templates\app\.dockerignore')" />
<Content Include="..\..\templates\ms\**\*" CopyToOutputDirectory="PreserveNewest" LinkBase="templates\ms\" />
<Content Include="..\..\templates\ms\.dockerignore" CopyToOutputDirectory="PreserveNewest" LinkBase="templates\ms\" />
<Content Include="..\..\templates\ms\*.sln" CopyToOutputDirectory="PreserveNewest" LinkBase="templates\ms\" />
</ItemGroup>
</Project>
@@ -1,8 +1,9 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using Volo.Abp.Cli.ProjectBuilding.Building;
using Volo.Abp.Cli.Utils;
using Volo.Abp.DependencyInjection;
@@ -10,17 +11,16 @@ namespace Volo.Abp.Cli.ProjectBuilding;
public class TemplateProjectBuilder : ITransientDependency
{
protected ISourceCodeStore SourceCodeStore { get; }
protected TemplateProjectBuildPipelineBuilder PipelineBuilder { get; }
protected ICmdHelper CmdHelper { get; }
public TemplateProjectBuilder(
ISourceCodeStore sourceCodeStore,
TemplateProjectBuildPipelineBuilder pipelineBuilder,
ICmdHelper cmdHelper)
private static readonly Dictionary<string, string> TemplateShortNames = new()
{
["app"] = "hua-app",
["ms"] = "hua-ms",
};
public TemplateProjectBuilder(ICmdHelper cmdHelper)
{
SourceCodeStore = sourceCodeStore;
PipelineBuilder = pipelineBuilder;
CmdHelper = cmdHelper;
}
@@ -31,91 +31,148 @@ public class TemplateProjectBuilder : ITransientDependency
return;
}
if (args.Template.Name == "ms")
if (!TemplateShortNames.TryGetValue(args.Template.Name, out var shortName))
{
await BuildMicroserviceAsync(args);
return;
throw new InvalidOperationException(
$"Unknown template: {args.Template.Name}. " +
$"Available: {string.Join(", ", TemplateShortNames.Keys)}");
}
var templatePath = await SourceCodeStore.GetAsync(
args.Template.Name, args.Version);
var context = new ProjectBuildContext(
args.ProjectName,
args.Template.Name,
args.Version,
args.OutputDirectory,
args.DatabaseProvider,
args.UiFramework,
args.ConnectionString,
args.CreateSolutionFolder,
args.NoRandomPort,
templatePath);
var pipeline = PipelineBuilder.Build(context);
await pipeline.ExecuteAsync();
await BuildFromTemplateAsync(args, shortName);
}
private async Task BuildMicroserviceAsync(ProjectBuildArgs args)
private async Task BuildFromTemplateAsync(ProjectBuildArgs args, string shortName)
{
var templateDir = ResolveTemplateDirectory();
var templateDir = ResolveTemplateDirectory(args.Template.Name);
if (!Directory.Exists(templateDir))
{
throw new FileNotFoundException(
$"Microservice template not found at: {templateDir}. " +
"Ensure the 'templates/ms' directory exists alongside the tool.");
$"Template '{args.Template.Name}' not found at: {templateDir}. " +
"Ensure the templates directory is included in the tool package.");
}
// Install the template
var installResult = await CmdHelper.RunAsync($"dotnet new install \"{templateDir}\"");
// Install the template (--force to overwrite any previous install)
var installResult = await CmdHelper.RunAsync(
"dotnet", new[] { "new", "install", templateDir, "--force" });
if (!installResult.IsSuccess)
{
throw new InvalidOperationException(
$"Failed to install microservice template: {installResult.Error}");
$"Failed to install template '{args.Template.Name}': {installResult.Error}");
}
try
{
// Run dotnet new with the template
var outputDir = args.OutputDirectory;
var projectName = args.ProjectName;
var newArgs = BuildNewCommandArgs(shortName, args);
var newResult = await CmdHelper.RunAsync(
$"dotnet new hua-ms -n \"{projectName}\" -o \"{outputDir}\"");
"dotnet", newArgs);
if (!newResult.IsSuccess)
{
throw new InvalidOperationException(
$"Failed to create project: {newResult.Error}");
}
// dotnet new creates in {OutputDirectory}/{ProjectName} when preferNameDirectory=true
var outputPath = Path.Combine(args.OutputDirectory, args.ProjectName);
if (!Directory.Exists(outputPath))
{
outputPath = args.OutputDirectory;
}
CopyRootFiles(templateDir, outputPath, args.ProjectName);
}
finally
{
// Uninstall the template to clean up
await CmdHelper.RunAsync($"dotnet new uninstall \"{templateDir}\"");
await CmdHelper.RunAsync(
"dotnet", new[] { "new", "uninstall", templateDir });
}
}
private static string ResolveTemplateDirectory()
private static string[] BuildNewCommandArgs(string shortName, ProjectBuildArgs args)
{
var argList = new List<string> { "new", shortName, "-n", args.ProjectName, "-o", args.OutputDirectory };
if (!string.IsNullOrWhiteSpace(args.DatabaseProvider))
{
argList.Add("-p");
argList.Add("databaseProvider");
argList.Add(args.DatabaseProvider);
}
if (!string.IsNullOrWhiteSpace(args.UiFramework))
{
argList.Add("-p");
argList.Add("uiFramework");
argList.Add(args.UiFramework);
}
return argList.ToArray();
}
private static void CopyRootFiles(string templateDir, string outputPath, string projectName)
{
var rootFiles = Directory.EnumerateFiles(templateDir, "*", SearchOption.TopDirectoryOnly)
.Where(f => !f.EndsWith(Path.DirectorySeparatorChar + ".template.config"))
.ToList();
var outputFiles = new HashSet<string>(
Directory.GetFiles(outputPath, "*", SearchOption.TopDirectoryOnly)
.Select(Path.GetFileName)!,
StringComparer.OrdinalIgnoreCase);
foreach (var file in rootFiles)
{
var fileName = Path.GetFileName(file);
var destName = fileName;
// Handle .sln file: Company.Project.sln -> {ProjectName}.sln
if (fileName.EndsWith(".sln", StringComparison.OrdinalIgnoreCase))
{
destName = projectName + ".sln";
}
// Replace sourceName placeholder in file name
destName = destName.Replace("Company.Project", projectName);
// Skip if already generated by dotnet new
if (outputFiles.Contains(Path.GetFileName(destName)))
continue;
var destPath = Path.Combine(outputPath, destName);
if (fileName.EndsWith(".sln", StringComparison.OrdinalIgnoreCase) ||
fileName.EndsWith(".md", StringComparison.OrdinalIgnoreCase) ||
fileName.EndsWith(".sh", StringComparison.OrdinalIgnoreCase) ||
fileName.EndsWith(".yml", StringComparison.OrdinalIgnoreCase) ||
fileName.Equals(".dockerignore", StringComparison.OrdinalIgnoreCase))
{
var content = File.ReadAllText(file);
content = content.Replace("Company.Project", projectName);
File.WriteAllText(destPath, content);
}
else
{
File.Copy(file, destPath, overwrite: false);
}
}
}
private static string ResolveTemplateDirectory(string templateName)
{
var assemblyDir = Path.GetDirectoryName(
Assembly.GetExecutingAssembly().Location) ?? ".";
// First, check relative to the assembly directory (works for published output
// where templates/ms is copied alongside the assembly via CopyToOutputDirectory)
var assemblyRelativePath = Path.Combine(assemblyDir, "templates", "ms");
if (Directory.Exists(assemblyRelativePath))
var relativePath = Path.Combine(assemblyDir, "templates", templateName);
if (Directory.Exists(relativePath))
{
return assemblyRelativePath;
return relativePath;
}
// Fall back to upward traversal (works in development when templates/ms
// lives in the repository root above bin/Debug/net9.0)
var directory = new DirectoryInfo(assemblyDir);
while (directory != null)
{
var templatePath = Path.Combine(directory.FullName, "templates", "ms");
var templatePath = Path.Combine(directory.FullName, "templates", templateName);
if (Directory.Exists(templatePath))
{
return templatePath;
@@ -124,6 +181,6 @@ public class TemplateProjectBuilder : ITransientDependency
directory = directory.Parent;
}
return assemblyRelativePath;
return relativePath;
}
}
+34 -1
View File
@@ -1,4 +1,6 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
@@ -8,6 +10,8 @@ namespace Volo.Abp.Cli.Utils;
public interface ICmdHelper
{
Task<CmdResult> RunAsync(string command, string? workingDirectory = null);
Task<CmdResult> RunAsync(string fileName, IEnumerable<string> arguments, string? workingDirectory = null);
}
public class CmdResult
@@ -38,7 +42,36 @@ public class CmdHelper : ICmdHelper, ITransientDependency
processStartInfo.WorkingDirectory = workingDirectory;
}
using var process = new Process { StartInfo = processStartInfo };
return await RunProcessAsync(processStartInfo);
}
public async Task<CmdResult> RunAsync(string fileName, IEnumerable<string> arguments, string? workingDirectory = null)
{
var processStartInfo = new ProcessStartInfo
{
FileName = fileName,
RedirectStandardOutput = true,
RedirectStandardError = true,
UseShellExecute = false,
CreateNoWindow = true
};
foreach (var arg in arguments)
{
processStartInfo.ArgumentList.Add(arg);
}
if (!string.IsNullOrEmpty(workingDirectory))
{
processStartInfo.WorkingDirectory = workingDirectory;
}
return await RunProcessAsync(processStartInfo);
}
private static async Task<CmdResult> RunProcessAsync(ProcessStartInfo startInfo)
{
using var process = new Process { StartInfo = startInfo };
process.Start();
var output = await process.StandardOutput.ReadToEndAsync();
+9 -1
View File
@@ -3,10 +3,18 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<Nullable>enable</Nullable>
<TargetFramework>net9.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<Version>0.0.3</Version>
<PackAsTool>true</PackAsTool>
<ToolCommandName>hua</ToolCommandName>
<RootNamespace />
<PackageId>Hua.Cli</PackageId>
<Authors>Hua.Cli</Authors>
<Owners>xinshoushangdao</Owners>
<Description>Hua.Cli is a command-line tool</Description>
<RepositoryType>git</RepositoryType>
<RepositoryUrl>https://git.we965.cn/Hua/Hua.Cli</RepositoryUrl>
<NoDefaultExcludes>true</NoDefaultExcludes>
</PropertyGroup>
<ItemGroup>
@@ -0,0 +1,23 @@
{
"$schema": "http://json.schemastore.org/template",
"author": "Hua",
"classifications": ["Hua", "Web", "Application", "Solution"],
"identity": "Hua.App.Template",
"name": "Hua Application",
"shortName": "hua-app",
"sourceName": "Company.Project",
"preferNameDirectory": true,
"sources": [
{
"source": "./",
"target": "./",
"exclude": [
".template.config/**"
]
}
],
"tags": {
"language": "C#",
"type": "solution"
}
}
+55
View File
@@ -0,0 +1,55 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Company.Project.Domain.Shared", "src\Company.Project.Domain.Shared\Company.Project.Domain.Shared.csproj", "{B0000001-0000-0000-0000-000000000001}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Company.Project.Domain", "src\Company.Project.Domain\Company.Project.Domain.csproj", "{B0000002-0000-0000-0000-000000000002}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Company.Project.Application.Contracts", "src\Company.Project.Application.Contracts\Company.Project.Application.Contracts.csproj", "{B0000003-0000-0000-0000-000000000003}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Company.Project.Application", "src\Company.Project.Application\Company.Project.Application.csproj", "{B0000004-0000-0000-0000-000000000004}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Company.Project.EntityFrameworkCore", "src\Company.Project.EntityFrameworkCore\Company.Project.EntityFrameworkCore.csproj", "{B0000005-0000-0000-0000-000000000005}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Company.Project.HttpApi", "src\Company.Project.HttpApi\Company.Project.HttpApi.csproj", "{B0000006-0000-0000-0000-000000000006}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Company.Project.HttpApi.Host", "src\Company.Project.HttpApi.Host\Company.Project.HttpApi.Host.csproj", "{B0000007-0000-0000-0000-000000000007}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{B0000001-0000-0000-0000-000000000001}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B0000001-0000-0000-0000-000000000001}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B0000001-0000-0000-0000-000000000001}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B0000001-0000-0000-0000-000000000001}.Release|Any CPU.Build.0 = Release|Any CPU
{B0000002-0000-0000-0000-000000000002}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B0000002-0000-0000-0000-000000000002}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B0000002-0000-0000-0000-000000000002}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B0000002-0000-0000-0000-000000000002}.Release|Any CPU.Build.0 = Release|Any CPU
{B0000003-0000-0000-0000-000000000003}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B0000003-0000-0000-0000-000000000003}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B0000003-0000-0000-0000-000000000003}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B0000003-0000-0000-0000-000000000003}.Release|Any CPU.Build.0 = Release|Any CPU
{B0000004-0000-0000-0000-000000000004}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B0000004-0000-0000-0000-000000000004}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B0000004-0000-0000-0000-000000000004}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B0000004-0000-0000-0000-000000000004}.Release|Any CPU.Build.0 = Release|Any CPU
{B0000005-0000-0000-0000-000000000005}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B0000005-0000-0000-0000-000000000005}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B0000005-0000-0000-0000-000000000005}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B0000005-0000-0000-0000-000000000005}.Release|Any CPU.Build.0 = Release|Any CPU
{B0000006-0000-0000-0000-000000000006}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B0000006-0000-0000-0000-000000000006}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B0000006-0000-0000-0000-000000000006}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B0000006-0000-0000-0000-000000000006}.Release|Any CPU.Build.0 = Release|Any CPU
{B0000007-0000-0000-0000-000000000007}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B0000007-0000-0000-0000-000000000007}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B0000007-0000-0000-0000-000000000007}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B0000007-0000-0000-0000-000000000007}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal
@@ -0,0 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup><TargetFramework>net10.0</TargetFramework></PropertyGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.Ddd.Application.Contracts" Version="9.0.0" />
<ProjectReference Include="..\Company.Project.Domain.Shared\Company.Project.Domain.Shared.csproj" />
</ItemGroup>
</Project>
@@ -0,0 +1,6 @@
using Volo.Abp.Modularity;
namespace Company.Project;
[DependsOn(typeof(ProjectDomainSharedModule))]
public class ProjectApplicationContractsModule : AbpModule { }
@@ -0,0 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup><TargetFramework>net10.0</TargetFramework></PropertyGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.Ddd.Application" Version="9.0.0" />
<ProjectReference Include="..\Company.Project.Application.Contracts\Company.Project.Application.Contracts.csproj" />
<ProjectReference Include="..\Company.Project.Domain\Company.Project.Domain.csproj" />
</ItemGroup>
</Project>
@@ -0,0 +1,9 @@
using Volo.Abp.Modularity;
namespace Company.Project;
[DependsOn(
typeof(ProjectDomainModule),
typeof(ProjectApplicationContractsModule)
)]
public class ProjectApplicationModule : AbpModule { }
@@ -0,0 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup><TargetFramework>net10.0</TargetFramework></PropertyGroup>
<ItemGroup><PackageReference Include="Volo.Abp.Ddd.Domain" Version="9.0.0" /></ItemGroup>
</Project>
@@ -0,0 +1,6 @@
using Volo.Abp.Modularity;
namespace Company.Project;
[DependsOn(typeof(AbpDddDomainModule))]
public class ProjectDomainSharedModule : AbpModule { }
@@ -0,0 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup><TargetFramework>net10.0</TargetFramework></PropertyGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.Ddd.Domain" Version="9.0.0" />
<ProjectReference Include="..\Company.Project.Domain.Shared\Company.Project.Domain.Shared.csproj" />
</ItemGroup>
</Project>
@@ -0,0 +1,6 @@
using Volo.Abp.Modularity;
namespace Company.Project;
[DependsOn(typeof(ProjectDomainSharedModule))]
public class ProjectDomainModule : AbpModule { }
@@ -0,0 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup><TargetFramework>net10.0</TargetFramework></PropertyGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.EntityFrameworkCore.SqlServer" Version="9.0.0" />
<ProjectReference Include="..\Company.Project.Domain\Company.Project.Domain.csproj" />
</ItemGroup>
</Project>
@@ -0,0 +1,9 @@
using Microsoft.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore;
namespace Company.Project.EntityFrameworkCore;
public class ProjectDbContext : AbpDbContext<ProjectDbContext>
{
public ProjectDbContext(DbContextOptions<ProjectDbContext> options) : base(options) { }
}
@@ -0,0 +1,6 @@
using Volo.Abp.Modularity;
namespace Company.Project;
[DependsOn(typeof(ProjectDomainModule))]
public class ProjectEntityFrameworkCoreModule : AbpModule { }
@@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup><TargetFramework>net10.0</TargetFramework></PropertyGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.Autofac" Version="9.0.0" />
<PackageReference Include="Volo.Abp.AspNetCore.Mvc" Version="9.0.0" />
<PackageReference Include="Volo.Abp.EntityFrameworkCore.SqlServer" Version="9.0.0" />
<PackageReference Include="Serilog.AspNetCore" Version="9.0.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
<ProjectReference Include="..\Company.Project.Application\Company.Project.Application.csproj" />
<ProjectReference Include="..\Company.Project.EntityFrameworkCore\Company.Project.EntityFrameworkCore.csproj" />
<ProjectReference Include="..\Company.Project.HttpApi\Company.Project.HttpApi.csproj" />
</ItemGroup>
</Project>
@@ -0,0 +1,34 @@
using System;
using System.IO;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Serilog;
using Volo.Abp;
namespace Company.Project;
public class Program
{
public static void Main(string[] args)
{
var configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json")
.Build();
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(configuration)
.CreateLogger();
try { CreateHostBuilder(args).Build().Run(); }
catch (Exception ex) { Log.Fatal(ex, "Host terminated unexpectedly"); }
finally { Log.CloseAndFlush(); }
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseAutofac().UseSerilog()
.ConfigureWebHostDefaults(webBuilder => webBuilder.UseStartup<Startup>());
}
@@ -0,0 +1,40 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.OpenApi.Models;
using Volo.Abp;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.Autofac;
using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore.SqlServer;
using Volo.Abp.Modularity;
namespace Company.Project;
[DependsOn(
typeof(AbpAutofacModule),
typeof(AbpAspNetCoreMvcModule),
typeof(AbpEntityFrameworkCoreSqlServerModule),
typeof(ProjectApplicationModule),
typeof(ProjectEntityFrameworkCoreModule),
typeof(ProjectHttpApiModule)
)]
public class ProjectHttpApiHostModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddSwaggerGen(options =>
{
options.SwaggerDoc("v1", new OpenApiInfo { Title = "Hua API", Version = "v1" });
});
Configure<AbpDbContextOptions>(options => options.UseSqlServer());
}
public override void OnApplicationInitialization(ApplicationInitializationContext context)
{
var app = context.GetApplicationBuilder();
app.UseRouting();
app.UseSwagger();
app.UseSwaggerUI(options => options.SwaggerEndpoint("/swagger/v1/swagger.json", "Hua API"));
app.UseConfiguredEndpoints();
}
}
@@ -0,0 +1,18 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
namespace Company.Project;
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddApplication<ProjectHttpApiHostModule>();
}
public void Configure(IApplicationBuilder app, IHostEnvironment env)
{
app.InitializeApplication();
}
}
@@ -0,0 +1,7 @@
{
"ConnectionStrings": {
"Default": "Server=(LocalDb)\\MSSQLLocalDB;Database=Company.Project;Trusted_Connection=True"
},
"Serilog": { "MinimumLevel": { "Default": "Information" } },
"AllowedHosts": "*"
}
@@ -0,0 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup><TargetFramework>net10.0</TargetFramework></PropertyGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.AspNetCore.Mvc" Version="9.0.0" />
<ProjectReference Include="..\Company.Project.Application.Contracts\Company.Project.Application.Contracts.csproj" />
</ItemGroup>
</Project>
@@ -0,0 +1,6 @@
using Volo.Abp.Modularity;
namespace Company.Project;
[DependsOn(typeof(ProjectApplicationContractsModule))]
public class ProjectHttpApiModule : AbpModule { }
+25
View File
@@ -0,0 +1,25 @@
**/.classpath
**/.dockerignore
**/.env
**/.git
**/.gitignore
**/.project
**/.settings
**/.toolstarget
**/.vs
**/.vscode
**/*.*proj.user
**/*.dbmdl
**/*.jfm
**/azds.yaml
**/bin
**/charts
**/docker-compose*
**/Dockerfile*
**/node_modules
**/npm-debug.log
**/obj
**/secrets.dev.yaml
**/values.dev.yaml
LICENSE
README.md
+13 -1
View File
@@ -7,9 +7,21 @@
"shortName": "hua-ms",
"sourceName": "Company.Project",
"preferNameDirectory": true,
"sources": [
{
"source": "./",
"target": "./",
"include": [
"**/*"
],
"exclude": [
".template.config/**"
]
}
],
"tags": {
"language": "C#",
"type": "project"
"type": "solution"
},
"symbols": {
"databaseProvider": {
+208
View File
@@ -0,0 +1,208 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "microservices", "microservices", "{B0000100-0000-0000-0000-000000000100}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "applications", "applications", "{B0000200-0000-0000-0000-000000000200}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "gateways", "gateways", "{B0000300-0000-0000-0000-000000000300}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "modules", "modules", "{B0000400-0000-0000-0000-000000000400}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "product", "product", "{B0000500-0000-0000-0000-000000000500}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{B0000600-0000-0000-0000-000000000600}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{B0000700-0000-0000-0000-000000000700}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "shared", "shared", "{B0000800-0000-0000-0000-000000000800}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Company.Project.Shared", "shared\Company.Project.Shared\Company.Project.Shared.csproj", "{A0000001-0000-0000-0000-000000000001}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProductManagement.Domain.Shared", "modules\product\src\ProductManagement.Domain.Shared\ProductManagement.Domain.Shared.csproj", "{A0000002-0000-0000-0000-000000000002}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProductManagement.Domain", "modules\product\src\ProductManagement.Domain\ProductManagement.Domain.csproj", "{A0000003-0000-0000-0000-000000000003}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProductManagement.Application.Contracts", "modules\product\src\ProductManagement.Application.Contracts\ProductManagement.Application.Contracts.csproj", "{A0000004-0000-0000-0000-000000000004}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProductManagement.Application", "modules\product\src\ProductManagement.Application\ProductManagement.Application.csproj", "{A0000005-0000-0000-0000-000000000005}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProductManagement.EntityFrameworkCore", "modules\product\src\ProductManagement.EntityFrameworkCore\ProductManagement.EntityFrameworkCore.csproj", "{A0000006-0000-0000-0000-000000000006}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProductManagement.HttpApi", "modules\product\src\ProductManagement.HttpApi\ProductManagement.HttpApi.csproj", "{A0000007-0000-0000-0000-000000000007}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProductManagement.HttpApi.Client", "modules\product\src\ProductManagement.HttpApi.Client\ProductManagement.HttpApi.Client.csproj", "{A0000008-0000-0000-0000-000000000008}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProductManagement.Web", "modules\product\src\ProductManagement.Web\ProductManagement.Web.csproj", "{A0000009-0000-0000-0000-000000000009}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProductManagement.TestBase", "modules\product\test\ProductManagement.TestBase\ProductManagement.TestBase.csproj", "{A000000A-0000-0000-0000-00000000000A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProductManagement.Application.Tests", "modules\product\test\ProductManagement.Application.Tests\ProductManagement.Application.Tests.csproj", "{A000000B-0000-0000-0000-00000000000B}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProductManagement.Domain.Tests", "modules\product\test\ProductManagement.Domain.Tests\ProductManagement.Domain.Tests.csproj", "{A000000C-0000-0000-0000-00000000000C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProductManagement.EntityFrameworkCore.Tests", "modules\product\test\ProductManagement.EntityFrameworkCore.Tests\ProductManagement.EntityFrameworkCore.Tests.csproj", "{A000000D-0000-0000-0000-00000000000D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Company.Project.IdentityService.Host", "microservices\Company.Project.IdentityService.Host\Company.Project.IdentityService.Host.csproj", "{A000000E-0000-0000-0000-00000000000E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Company.Project.ProductService.Host", "microservices\Company.Project.ProductService.Host\Company.Project.ProductService.Host.csproj", "{A000000F-0000-0000-0000-00000000000F}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Company.Project.BloggingService.Host", "microservices\Company.Project.BloggingService.Host\Company.Project.BloggingService.Host.csproj", "{A0000010-0000-0000-0000-000000000010}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Company.Project.TenantManagementService.Host", "microservices\Company.Project.TenantManagementService.Host\Company.Project.TenantManagementService.Host.csproj", "{A0000011-0000-0000-0000-000000000011}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Company.Project.InternalGateway.Host", "gateways\Company.Project.InternalGateway.Host\Company.Project.InternalGateway.Host.csproj", "{A0000012-0000-0000-0000-000000000012}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Company.Project.PublicWebGateway.Host", "gateways\Company.Project.PublicWebGateway.Host\Company.Project.PublicWebGateway.Host.csproj", "{A0000013-0000-0000-0000-000000000013}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Company.Project.BackendAdminAppGateway.Host", "gateways\Company.Project.BackendAdminAppGateway.Host\Company.Project.BackendAdminAppGateway.Host.csproj", "{A0000014-0000-0000-0000-000000000014}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Company.Project.AuthServer.Host", "applications\Company.Project.AuthServer.Host\Company.Project.AuthServer.Host.csproj", "{A0000015-0000-0000-0000-000000000015}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Company.Project.BackendAdminApp.Host", "applications\Company.Project.BackendAdminApp.Host\Company.Project.BackendAdminApp.Host.csproj", "{A0000016-0000-0000-0000-000000000016}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Company.Project.PublicWebSite.Host", "applications\Company.Project.PublicWebSite.Host\Company.Project.PublicWebSite.Host.csproj", "{A0000017-0000-0000-0000-000000000017}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Company.Project.ConsoleClientDemo", "applications\Company.Project.ConsoleClientDemo\Company.Project.ConsoleClientDemo.csproj", "{A0000018-0000-0000-0000-000000000018}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{A0000001-0000-0000-0000-000000000001}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A0000001-0000-0000-0000-000000000001}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A0000001-0000-0000-0000-000000000001}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A0000001-0000-0000-0000-000000000001}.Release|Any CPU.Build.0 = Release|Any CPU
{A0000002-0000-0000-0000-000000000002}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A0000002-0000-0000-0000-000000000002}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A0000002-0000-0000-0000-000000000002}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A0000002-0000-0000-0000-000000000002}.Release|Any CPU.Build.0 = Release|Any CPU
{A0000003-0000-0000-0000-000000000003}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A0000003-0000-0000-0000-000000000003}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A0000003-0000-0000-0000-000000000003}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A0000003-0000-0000-0000-000000000003}.Release|Any CPU.Build.0 = Release|Any CPU
{A0000004-0000-0000-0000-000000000004}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A0000004-0000-0000-0000-000000000004}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A0000004-0000-0000-0000-000000000004}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A0000004-0000-0000-0000-000000000004}.Release|Any CPU.Build.0 = Release|Any CPU
{A0000005-0000-0000-0000-000000000005}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A0000005-0000-0000-0000-000000000005}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A0000005-0000-0000-0000-000000000005}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A0000005-0000-0000-0000-000000000005}.Release|Any CPU.Build.0 = Release|Any CPU
{A0000006-0000-0000-0000-000000000006}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A0000006-0000-0000-0000-000000000006}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A0000006-0000-0000-0000-000000000006}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A0000006-0000-0000-0000-000000000006}.Release|Any CPU.Build.0 = Release|Any CPU
{A0000007-0000-0000-0000-000000000007}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A0000007-0000-0000-0000-000000000007}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A0000007-0000-0000-0000-000000000007}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A0000007-0000-0000-0000-000000000007}.Release|Any CPU.Build.0 = Release|Any CPU
{A0000008-0000-0000-0000-000000000008}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A0000008-0000-0000-0000-000000000008}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A0000008-0000-0000-0000-000000000008}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A0000008-0000-0000-0000-000000000008}.Release|Any CPU.Build.0 = Release|Any CPU
{A0000009-0000-0000-0000-000000000009}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A0000009-0000-0000-0000-000000000009}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A0000009-0000-0000-0000-000000000009}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A0000009-0000-0000-0000-000000000009}.Release|Any CPU.Build.0 = Release|Any CPU
{A000000A-0000-0000-0000-00000000000A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A000000A-0000-0000-0000-00000000000A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A000000A-0000-0000-0000-00000000000A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A000000A-0000-0000-0000-00000000000A}.Release|Any CPU.Build.0 = Release|Any CPU
{A000000B-0000-0000-0000-00000000000B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A000000B-0000-0000-0000-00000000000B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A000000B-0000-0000-0000-00000000000B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A000000B-0000-0000-0000-00000000000B}.Release|Any CPU.Build.0 = Release|Any CPU
{A000000C-0000-0000-0000-00000000000C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A000000C-0000-0000-0000-00000000000C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A000000C-0000-0000-0000-00000000000C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A000000C-0000-0000-0000-00000000000C}.Release|Any CPU.Build.0 = Release|Any CPU
{A000000D-0000-0000-0000-00000000000D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A000000D-0000-0000-0000-00000000000D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A000000D-0000-0000-0000-00000000000D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A000000D-0000-0000-0000-00000000000D}.Release|Any CPU.Build.0 = Release|Any CPU
{A000000E-0000-0000-0000-00000000000E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A000000E-0000-0000-0000-00000000000E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A000000E-0000-0000-0000-00000000000E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A000000E-0000-0000-0000-00000000000E}.Release|Any CPU.Build.0 = Release|Any CPU
{A000000F-0000-0000-0000-00000000000F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A000000F-0000-0000-0000-00000000000F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A000000F-0000-0000-0000-00000000000F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A000000F-0000-0000-0000-00000000000F}.Release|Any CPU.Build.0 = Release|Any CPU
{A0000010-0000-0000-0000-000000000010}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A0000010-0000-0000-0000-000000000010}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A0000010-0000-0000-0000-000000000010}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A0000010-0000-0000-0000-000000000010}.Release|Any CPU.Build.0 = Release|Any CPU
{A0000011-0000-0000-0000-000000000011}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A0000011-0000-0000-0000-000000000011}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A0000011-0000-0000-0000-000000000011}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A0000011-0000-0000-0000-000000000011}.Release|Any CPU.Build.0 = Release|Any CPU
{A0000012-0000-0000-0000-000000000012}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A0000012-0000-0000-0000-000000000012}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A0000012-0000-0000-0000-000000000012}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A0000012-0000-0000-0000-000000000012}.Release|Any CPU.Build.0 = Release|Any CPU
{A0000013-0000-0000-0000-000000000013}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A0000013-0000-0000-0000-000000000013}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A0000013-0000-0000-0000-000000000013}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A0000013-0000-0000-0000-000000000013}.Release|Any CPU.Build.0 = Release|Any CPU
{A0000014-0000-0000-0000-000000000014}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A0000014-0000-0000-0000-000000000014}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A0000014-0000-0000-0000-000000000014}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A0000014-0000-0000-0000-000000000014}.Release|Any CPU.Build.0 = Release|Any CPU
{A0000015-0000-0000-0000-000000000015}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A0000015-0000-0000-0000-000000000015}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A0000015-0000-0000-0000-000000000015}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A0000015-0000-0000-0000-000000000015}.Release|Any CPU.Build.0 = Release|Any CPU
{A0000016-0000-0000-0000-000000000016}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A0000016-0000-0000-0000-000000000016}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A0000016-0000-0000-0000-000000000016}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A0000016-0000-0000-0000-000000000016}.Release|Any CPU.Build.0 = Release|Any CPU
{A0000017-0000-0000-0000-000000000017}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A0000017-0000-0000-0000-000000000017}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A0000017-0000-0000-0000-000000000017}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A0000017-0000-0000-0000-000000000017}.Release|Any CPU.Build.0 = Release|Any CPU
{A0000018-0000-0000-0000-000000000018}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A0000018-0000-0000-0000-000000000018}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A0000018-0000-0000-0000-000000000018}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A0000018-0000-0000-0000-000000000018}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{B0000500-0000-0000-0000-000000000500} = {B0000400-0000-0000-0000-000000000400}
{B0000600-0000-0000-0000-000000000600} = {B0000500-0000-0000-0000-000000000500}
{B0000700-0000-0000-0000-000000000700} = {B0000500-0000-0000-0000-000000000500}
{A0000001-0000-0000-0000-000000000001} = {B0000800-0000-0000-0000-000000000800}
{A0000002-0000-0000-0000-000000000002} = {B0000600-0000-0000-0000-000000000600}
{A0000003-0000-0000-0000-000000000003} = {B0000600-0000-0000-0000-000000000600}
{A0000004-0000-0000-0000-000000000004} = {B0000600-0000-0000-0000-000000000600}
{A0000005-0000-0000-0000-000000000005} = {B0000600-0000-0000-0000-000000000600}
{A0000006-0000-0000-0000-000000000006} = {B0000600-0000-0000-0000-000000000600}
{A0000007-0000-0000-0000-000000000007} = {B0000600-0000-0000-0000-000000000600}
{A0000008-0000-0000-0000-000000000008} = {B0000600-0000-0000-0000-000000000600}
{A0000009-0000-0000-0000-000000000009} = {B0000600-0000-0000-0000-000000000600}
{A000000A-0000-0000-0000-00000000000A} = {B0000700-0000-0000-0000-000000000700}
{A000000B-0000-0000-0000-00000000000B} = {B0000700-0000-0000-0000-000000000700}
{A000000C-0000-0000-0000-00000000000C} = {B0000700-0000-0000-0000-000000000700}
{A000000D-0000-0000-0000-00000000000D} = {B0000700-0000-0000-0000-000000000700}
{A000000E-0000-0000-0000-00000000000E} = {B0000100-0000-0000-0000-000000000100}
{A000000F-0000-0000-0000-00000000000F} = {B0000100-0000-0000-0000-000000000100}
{A0000010-0000-0000-0000-000000000010} = {B0000100-0000-0000-0000-000000000100}
{A0000011-0000-0000-0000-000000000011} = {B0000100-0000-0000-0000-000000000100}
{A0000012-0000-0000-0000-000000000012} = {B0000300-0000-0000-0000-000000000300}
{A0000013-0000-0000-0000-000000000013} = {B0000300-0000-0000-0000-000000000300}
{A0000014-0000-0000-0000-000000000014} = {B0000300-0000-0000-0000-000000000300}
{A0000015-0000-0000-0000-000000000015} = {B0000200-0000-0000-0000-000000000200}
{A0000016-0000-0000-0000-000000000016} = {B0000200-0000-0000-0000-000000000200}
{A0000017-0000-0000-0000-000000000017} = {B0000200-0000-0000-0000-000000000200}
{A0000018-0000-0000-0000-000000000018} = {B0000200-0000-0000-0000-000000000200}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {37474F0D-2E52-4D2F-B39B-7FE3FF31B4EC}
EndGlobalSection
EndGlobal
+4
View File
@@ -0,0 +1,4 @@
#!/bin/bash
echo "Deploying to Kubernetes..."
echo "See k8s/ directory for deployment YAML files."
echo "Run: kubectl apply -f k8s/"
+70
View File
@@ -0,0 +1,70 @@
# Microservice Solution
基于 ABP Framework 的微服务解决方案模板。
## 项目结构
```
├── applications/ # 应用层
│ ├── AuthServer.Host/ # 认证服务器(IdentityServer
│ ├── BackendAdminApp.Host/ # 后台管理应用
│ ├── PublicWebSite.Host/ # 公开网站
│ └── ConsoleClientDemo/ # 控制台客户端演示
├── gateways/ # 网关层(Ocelot
│ ├── InternalGateway.Host/ # 内部服务网关
│ ├── BackendAdminAppGateway.Host/ # 后台管理网关
│ └── PublicWebGateway.Host/ # 公开网站网关
├── microservices/ # 微服务层
│ ├── IdentityService.Host/ # 身份管理服务
│ ├── TenantManagementService.Host/ # 租户管理服务
│ ├── BloggingService.Host/ # 博客服务
│ └── ProductService.Host/ # 产品服务
├── modules/ # 业务模块
│ └── product/ # 产品管理模块
├── shared/ # 共享层
├── _run/ # 启动脚本
└── docker-compose.yml # Docker Compose 配置
```
## 快速启动
### 1. 启动基础设施(SQL Server + Redis + RabbitMQ
```powershell
cd _run
.\__Run_Infrastructure.ps1
```
### 2. 启动服务(每个在独立终端中)
```powershell
# 终端 1: 认证服务器
.\01_AuthServer.ps1
# 终端 2: 身份服务
.\02_IdentityService.ps1
# 终端 3: 租户管理服务
.\03_TenantManagementService.ps1
# ... 依次启动其他服务
```
### 3. 打开浏览器
```powershell
.\__Run_Browser.ps1
```
### 4. 停止基础设施
```powershell
.\__Stop_Infrastructure.ps1
```
## 技术栈
- **框架**: ABP Framework 9.x
- **运行时**: .NET 10.0
- **认证**: IdentityServer + JWT Bearer
- **ORM**: Entity Framework Core + MongoDB
- **消息**: RabbitMQ
- **网关**: Ocelot
- **缓存**: Redis
- **日志**: Serilog
+2
View File
@@ -0,0 +1,2 @@
cd ../applications/Company.Project.AuthServer.Host
dotnet run
+2
View File
@@ -0,0 +1,2 @@
cd ../microservices/Company.Project.IdentityService.Host
dotnet run
@@ -0,0 +1,2 @@
cd ../microservices/Company.Project.TenantManagementService.Host
dotnet run
+2
View File
@@ -0,0 +1,2 @@
cd ../microservices/Company.Project.BloggingService.Host
dotnet run
+2
View File
@@ -0,0 +1,2 @@
cd ../microservices/Company.Project.ProductService.Host
dotnet run
+2
View File
@@ -0,0 +1,2 @@
cd ../gateways/Company.Project.InternalGateway.Host
dotnet run
@@ -0,0 +1,2 @@
cd ../gateways/Company.Project.BackendAdminAppGateway.Host
dotnet run
@@ -0,0 +1,2 @@
cd ../gateways/Company.Project.PublicWebGateway.Host
dotnet run
+2
View File
@@ -0,0 +1,2 @@
cd ../applications/Company.Project.BackendAdminApp.Host
dotnet run
+2
View File
@@ -0,0 +1,2 @@
cd ../applications/Company.Project.PublicWebSite.Host
dotnet run
@@ -0,0 +1,2 @@
cd ../applications/Company.Project.ConsoleClientDemo
dotnet run
+24
View File
@@ -0,0 +1,24 @@
## 运行说明
### 1. 启动基础设施
```powershell
__Run_Infrastructure.ps1
```
### 2. 按顺序启动服务(每个在单独的终端中)
- `01_AuthServer.ps1` - 认证服务器 (https://localhost:44399)
- `02_IdentityService.ps1` - 身份服务 (https://localhost:44368)
- `03_TenantManagementService.ps1` - 租户管理服务 (https://localhost:44336)
- `04_BloggingService.ps1` - 博客服务 (https://localhost:44357)
- `05_ProductService.ps1` - 产品服务 (https://localhost:44344)
- `06_InternalGateway.ps1` - 内部网关 (https://localhost:44329)
- `07_BackendAdminAppGateway.ps1` - 后台管理网关 (https://localhost:44315)
- `08_PublicWebSiteGateway.ps1` - 公开网站网关 (https://localhost:44397)
- `09_BackendAdminApp.ps1` - 后台管理应用 (https://localhost:44354)
- `10_PublicWebSite.ps1` - 公开网站 (https://localhost:44335)
- `11_ConsoleClientDemo.ps1` - 控制台客户端演示
### 3. 停止基础设施
```powershell
__Stop_Infrastructure.ps1
```
@@ -0,0 +1,36 @@
# Run all application services in separate terminals
# First start infrastructure: __Run_Infrastructure.ps1
# Then run each service:
# Terminal 1: AuthServer
# 01_AuthServer.ps1
# Terminal 2: IdentityService
# 02_IdentityService.ps1
# Terminal 3: TenantManagementService
# 03_TenantManagementService.ps1
# Terminal 4: BloggingService
# 04_BloggingService.ps1
# Terminal 5: ProductService
# 05_ProductService.ps1
# Terminal 6: InternalGateway
# 06_InternalGateway.ps1
# Terminal 7: BackendAdminAppGateway
# 07_BackendAdminAppGateway.ps1
# Terminal 8: PublicWebSiteGateway
# 08_PublicWebSiteGateway.ps1
# Terminal 9: BackendAdminApp
# 09_BackendAdminApp.ps1
# Terminal 10: PublicWebSite
# 10_PublicWebSite.ps1
# Terminal 11: ConsoleClientDemo
# 11_ConsoleClientDemo.ps1
+8
View File
@@ -0,0 +1,8 @@
# 启动浏览器打开各个服务
Start-Process "https://localhost:44399" # AuthServer
Start-Process "https://localhost:44354" # BackendAdminApp
Start-Process "https://localhost:44335" # PublicWebSite
Start-Process "https://localhost:44344/swagger" # ProductService
Start-Process "https://localhost:44368/swagger" # IdentityService
Start-Process "https://localhost:44357/swagger" # BloggingService
Start-Process "https://localhost:44336/swagger" # TenantManagementService
@@ -0,0 +1,3 @@
cd ..
docker-compose -f docker-compose.infrastructure.yml -f docker-compose.infrastructure.override.yml up -d
cd _run
@@ -0,0 +1,3 @@
cd ..
docker-compose -f docker-compose.infrastructure.yml -f docker-compose.infrastructure.override.yml down
cd _run
@@ -0,0 +1,243 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.Data;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Guids;
using Volo.Abp.Identity;
using Volo.Abp.IdentityServer.ApiResources;
using Volo.Abp.IdentityServer.ApiScopes;
using Volo.Abp.IdentityServer.Clients;
using Volo.Abp.IdentityServer.IdentityResources;
using Volo.Abp.PermissionManagement;
using Volo.Abp.TenantManagement;
using Volo.Abp.Uow;
using ApiResource = Volo.Abp.IdentityServer.ApiResources.ApiResource;
using Client = Volo.Abp.IdentityServer.Clients.Client;
namespace Company.Project.AuthServer;
public class AuthServerDataSeeder : IDataSeedContributor, ITransientDependency
{
private readonly IApiResourceRepository _apiResourceRepository;
private readonly IClientRepository _clientRepository;
private readonly IApiScopeRepository _apiScopeRepository;
private readonly IIdentityResourceDataSeeder _identityResourceDataSeeder;
private readonly IGuidGenerator _guidGenerator;
private readonly IPermissionDataSeeder _permissionDataSeeder;
public AuthServerDataSeeder(
IClientRepository clientRepository,
IApiResourceRepository apiResourceRepository,
IIdentityResourceDataSeeder identityResourceDataSeeder,
IGuidGenerator guidGenerator,
IPermissionDataSeeder permissionDataSeeder,
IApiScopeRepository apiScopeRepository)
{
_clientRepository = clientRepository;
_apiResourceRepository = apiResourceRepository;
_identityResourceDataSeeder = identityResourceDataSeeder;
_guidGenerator = guidGenerator;
_permissionDataSeeder = permissionDataSeeder;
_apiScopeRepository = apiScopeRepository;
}
[UnitOfWork]
public virtual async Task SeedAsync(DataSeedContext context)
{
await _identityResourceDataSeeder.CreateStandardResourcesAsync();
await CreateApiScopesAsync();
await CreateApiResourcesAsync();
await CreateClientsAsync();
}
private async Task CreateApiScopesAsync()
{
await CreateApiScopeAsync("IdentityService");
await CreateApiScopeAsync("ProductService");
await CreateApiScopeAsync("InternalGateway");
await CreateApiScopeAsync("BackendAdminAppGateway");
await CreateApiScopeAsync("PublicWebGateway");
}
private async Task<ApiScope> CreateApiScopeAsync(string name)
{
var apiScope = await _apiScopeRepository.FindByNameAsync(name);
if (apiScope == null)
{
apiScope = await _apiScopeRepository.InsertAsync(
new ApiScope(
_guidGenerator.Create(),
name,
name + " API"
),
autoSave: true
);
}
return apiScope;
}
private async Task CreateApiResourcesAsync()
{
var commonApiUserClaims = new[]
{
"email",
"email_verified",
"name",
"phone_number",
"phone_number_verified",
"role"
};
await CreateApiResourceAsync("IdentityService", commonApiUserClaims);
await CreateApiResourceAsync("ProductService", commonApiUserClaims);
await CreateApiResourceAsync("InternalGateway", commonApiUserClaims);
await CreateApiResourceAsync("BackendAdminAppGateway", commonApiUserClaims);
await CreateApiResourceAsync("PublicWebGateway", commonApiUserClaims);
}
private async Task<ApiResource> CreateApiResourceAsync(string name, IEnumerable<string> claims)
{
var apiResource = await _apiResourceRepository.FindByNameAsync(name);
if (apiResource == null)
{
apiResource = await _apiResourceRepository.InsertAsync(
new ApiResource(
_guidGenerator.Create(),
name,
name + " API"
),
autoSave: true
);
}
foreach (var claim in claims)
{
if (apiResource.FindClaim(claim) == null)
{
apiResource.AddUserClaim(claim);
}
}
return await _apiResourceRepository.UpdateAsync(apiResource);
}
private async Task CreateClientsAsync()
{
const string commonSecret = "E5Xd4yMqjP5kjWFKrYgySBju6JVfCzMyFp7n2QmMrME=";
var commonScopes = new[]
{
"email",
"openid",
"profile",
"role",
"phone",
"address"
};
await CreateClientAsync(
"backend-admin-app-client",
commonScopes.Union(new[] { "BackendAdminAppGateway", "IdentityService", "ProductService" }),
new[] { "hybrid" },
commonSecret,
permissions: new[] { IdentityPermissions.Users.Default, "ProductManagement.Product" },
redirectUri: "https://localhost:44354/signin-oidc",
postLogoutRedirectUri: "https://localhost:44354/signout-callback-oidc"
);
await CreateClientAsync(
"public-website-client",
commonScopes.Union(new[] { "PublicWebGateway", "ProductService" }),
new[] { "hybrid" },
commonSecret,
redirectUri: "https://localhost:44335/signin-oidc",
postLogoutRedirectUri: "https://localhost:44335/signout-callback-oidc"
);
}
private async Task<Client> CreateClientAsync(
string name,
IEnumerable<string> scopes,
IEnumerable<string> grantTypes,
string secret,
string? redirectUri = null,
string? postLogoutRedirectUri = null,
IEnumerable<string>? permissions = null)
{
var client = await _clientRepository.FindByClientIdAsync(name);
if (client == null)
{
client = await _clientRepository.InsertAsync(
new Client(
_guidGenerator.Create(),
name
)
{
ClientName = name,
ProtocolType = "oidc",
Description = name,
AlwaysIncludeUserClaimsInIdToken = true,
AllowOfflineAccess = true,
AbsoluteRefreshTokenLifetime = 31536000,
AccessTokenLifetime = 31536000,
AuthorizationCodeLifetime = 300,
IdentityTokenLifetime = 300,
RequireConsent = false,
RequirePkce = false
},
autoSave: true
);
}
foreach (var scope in scopes)
{
if (client.FindScope(scope) == null)
{
client.AddScope(scope);
}
}
foreach (var grantType in grantTypes)
{
if (client.FindGrantType(grantType) == null)
{
client.AddGrantType(grantType);
}
}
if (client.FindSecret(secret) == null)
{
client.AddSecret(secret);
}
if (redirectUri != null)
{
if (client.FindRedirectUri(redirectUri) == null)
{
client.AddRedirectUri(redirectUri);
}
}
if (postLogoutRedirectUri != null)
{
if (client.FindPostLogoutRedirectUri(postLogoutRedirectUri) == null)
{
client.AddPostLogoutRedirectUri(postLogoutRedirectUri);
}
}
if (permissions != null)
{
await _permissionDataSeeder.SeedAsync(
ClientPermissionValueProvider.ProviderName,
name,
permissions
);
}
return await _clientRepository.UpdateAsync(client);
}
}
@@ -0,0 +1,9 @@
using Volo.Abp.DependencyInjection;
using Volo.Abp.Ui.Branding;
namespace Company.Project.AuthServer;
public class BrandingProvider : DefaultBrandingProvider, ISingletonDependency
{
public override string AppName => "Authentication Server";
}
@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<RootNamespace>Company.Project.AuthServer</RootNamespace>
</PropertyGroup>
<ItemGroup>
@@ -10,6 +10,12 @@
<PackageReference Include="Volo.Abp.IdentityServer.EntityFrameworkCore" Version="9.0.0" />
<PackageReference Include="Volo.Abp.Account.Web.IdentityServer" Version="9.0.0" />
<PackageReference Include="Volo.Abp.TenantManagement.EntityFrameworkCore" Version="9.0.0" />
<PackageReference Include="Volo.Abp.PermissionManagement.EntityFrameworkCore" Version="9.0.0" />
<PackageReference Include="Volo.Abp.AuditLogging.EntityFrameworkCore" Version="9.0.0" />
<PackageReference Include="Volo.Abp.SettingManagement.EntityFrameworkCore" Version="9.0.0" />
<PackageReference Include="Volo.Abp.FeatureManagement.EntityFrameworkCore" Version="9.0.0" />
<PackageReference Include="Volo.Abp.EventBus.RabbitMQ" Version="9.0.0" />
<PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="9.0.0" />
<PackageReference Include="Serilog.AspNetCore" Version="9.0.0" />
<ProjectReference Include="..\..\shared\Company.Project.Shared\Company.Project.Shared.csproj" />
</ItemGroup>
@@ -0,0 +1,20 @@
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
WORKDIR /app
EXPOSE 80
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /src
COPY ["applications/Company.Project.AuthServer.Host/Company.Project.AuthServer.Host.csproj", "applications/Company.Project.AuthServer.Host/"]
COPY ["shared/Company.Project.Shared/Company.Project.Shared.csproj", "shared/Company.Project.Shared/"]
RUN dotnet restore "applications/Company.Project.AuthServer.Host/Company.Project.AuthServer.Host.csproj" -nowarn:msb3202,msb3277,nu1503
COPY . .
WORKDIR "/src/applications/Company.Project.AuthServer.Host"
RUN dotnet build "Company.Project.AuthServer.Host.csproj" --no-restore -nowarn:msb3202,msb3277,nu1503 -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "Company.Project.AuthServer.Host.csproj" --no-restore -nowarn:msb3202,msb3277,nu1503 -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "Company.Project.AuthServer.Host.dll"]
@@ -0,0 +1,20 @@
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
WORKDIR /app
EXPOSE 80
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /src
COPY ["applications/Company.Project.AuthServer.Host/Company.Project.AuthServer.Host.csproj", "applications/Company.Project.AuthServer.Host/"]
COPY ["shared/Company.Project.Shared/Company.Project.Shared.csproj", "shared/Company.Project.Shared/"]
RUN dotnet restore "applications/Company.Project.AuthServer.Host/Company.Project.AuthServer.Host.csproj" -nowarn:msb3202,msb3277,nu1503
COPY . .
WORKDIR "/src/applications/Company.Project.AuthServer.Host"
RUN dotnet build "Company.Project.AuthServer.Host.csproj" --no-restore -nowarn:msb3202,msb3277,nu1503 -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "Company.Project.AuthServer.Host.csproj" --no-restore -nowarn:msb3202,msb3277,nu1503 -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "Company.Project.AuthServer.Host.dll"]
@@ -0,0 +1,33 @@
using Microsoft.EntityFrameworkCore;
using Volo.Abp.AuditLogging.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.FeatureManagement.EntityFrameworkCore;
using Volo.Abp.Identity.EntityFrameworkCore;
using Volo.Abp.IdentityServer.EntityFrameworkCore;
using Volo.Abp.PermissionManagement.EntityFrameworkCore;
using Volo.Abp.SettingManagement.EntityFrameworkCore;
using Volo.Abp.TenantManagement.EntityFrameworkCore;
namespace Company.Project.AuthServer.EntityFrameworkCore;
public class AuthServerDbContext : AbpDbContext<AuthServerDbContext>
{
public AuthServerDbContext(DbContextOptions<AuthServerDbContext> options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.ConfigureIdentity();
modelBuilder.ConfigureIdentityServer();
modelBuilder.ConfigureAuditLogging();
modelBuilder.ConfigurePermissionManagement();
modelBuilder.ConfigureSettingManagement();
modelBuilder.ConfigureTenantManagement();
modelBuilder.ConfigureFeatureManagement();
}
}
@@ -0,0 +1,28 @@
using System.IO;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design;
using Microsoft.Extensions.Configuration;
namespace Company.Project.AuthServer.EntityFrameworkCore;
public class AuthServerDbContextFactory : IDesignTimeDbContextFactory<AuthServerDbContext>
{
public AuthServerDbContext CreateDbContext(string[] args)
{
var configuration = BuildConfiguration();
var builder = new DbContextOptionsBuilder<AuthServerDbContext>()
.UseSqlServer(configuration.GetConnectionString("Default"));
return new AuthServerDbContext(builder.Options);
}
private static IConfigurationRoot BuildConfiguration()
{
var builder = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: false);
return builder.Build();
}
}
@@ -0,0 +1,33 @@
@page
@using Volo.Abp.Users
@model Company.Project.AuthServer.Pages.IndexModel
@inject ICurrentUser CurrentUser
@if (CurrentUser.IsAuthenticated)
{
<div>
<abp-row>
<abp-column size-md="_3" class="text-center">
<i class="fa fa-user d-block" style="font-size: 10em; color: #12b900"></i>
<a abp-button="Primary" asp-controller="Logout" asp-action="Index" asp-area="Account">Logout</a>
</abp-column>
<abp-column size-md="_9">
<h2>@CurrentUser.UserName</h2>
<h5 class="text-muted">@CurrentUser.Email</h5>
<div>
<strong>Roles</strong>: @CurrentUser.Roles.JoinAsString(", ")
<br />
<strong>Claims</strong>: <br />
@Html.Raw(CurrentUser.GetAllClaims().Select(c => $"{c.Type}={c.Value}").JoinAsString(" <br /> "))
</div>
</abp-column>
</abp-row>
</div>
}
@if (!CurrentUser.IsAuthenticated)
{
<div class="text-center">
<img src="~/images/anonymous-user.png" width="200" /><br/><br />
<a abp-button="Primary" asp-page="/Account/Login">Login</a>
</div>
}
@@ -0,0 +1,10 @@
using Volo.Abp.AspNetCore.Mvc.UI.RazorPages;
namespace Company.Project.AuthServer.Pages;
public class IndexModel : AbpPageModel
{
public void OnGet()
{
}
}
@@ -0,0 +1,4 @@
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@addTagHelper *, Volo.Abp.AspNetCore.Mvc.UI
@addTagHelper *, Volo.Abp.AspNetCore.Mvc.UI.Bootstrap
@addTagHelper *, Volo.Abp.AspNetCore.Mvc.UI.Bundling
@@ -0,0 +1,27 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "https://localhost:44399",
"sslPort": 0
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"Company.Project.AuthServer.Host": {
"commandName": "Project",
"launchBrowser": true,
"applicationUrl": "https://localhost:44399",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
@@ -0,0 +1,11 @@
module.exports = {
aliases: {
},
clean: [
],
mappings: {
}
};
@@ -0,0 +1,9 @@
{
"Logging": {
"LogLevel": {
"Default": "Debug",
"System": "Information",
"Microsoft": "Information"
}
}
}
@@ -0,0 +1,9 @@
"use strict";
var gulp = require("gulp"),
path = require('path'),
copyResources = require('./node_modules/@abp/aspnetcore.mvc.ui/gulp/copy-resources.js');
exports.default = function(){
return copyResources(path.resolve('./'));
};
@@ -0,0 +1,8 @@
{
"version": "0.1.0",
"name": "my-project-authserver-host",
"private": true,
"dependencies": {
"@abp/aspnetcore.mvc.ui.theme.basic": "~9.0.0"
}
}
@@ -0,0 +1 @@
{"KeyId":"4a577ea79efd27c042a6b5289cd7e24e","Parameters":{"D":"VyCuYOq48gYJi3HpqUMJbj6QCm0e5K/prRs0q6H8jQb1jl9kzDvHiHfw7XZDvC0mekK7k3ib5Tt3IHviCv7vpL0Ajdts4ex2uvjKnYX20EtaIcz6kkVFsY1NP6OyjUlY6a6idCedw6pTybq2BG0tqCcicnDurwJDhS/R9NG6UnR3xlMAY6qOSbV/1/EGNPOlP5Pn6vcpUOXBx2l/7gMB02uMAtWysSLAR5vcl+nMg0dgCnR6Ea2hf641TDZZj8F6/fWg2UejUk9JJDVdBMR9yNHFE4PXLxLTXAA41pLu6cWJW8m5maDmSHV67fCKKArlcuWhvHSvy3WkMRVltz3kMQ==","DP":"BwIvmgmdx09DmXmPszZgKLvnAzJ4jlNC+sP2WiTVhLYLPhflwBjQ1/Orw88MJqK8xVFk8zte9fEz9eaANAxgXYfkmty3hG873TsS2VRws4anFC8WVDmtFrbfgqirgP2yBEgqY857wcKvGIb7nNBNRpa3t0huM18VzJCevn3F9/U=","DQ":"X5/ZYFlEDLVBp/w88XL6QKzY8gtzSmCaKd+iTZqren7+yp4yZWDIxldeirgIX4oirvTa+YxIxa6+Q8ilUhm9FGXiaHEYdgaaCpJGfNtxydcm6jkdSYZvJkt0uSIaU0Qsfl+aqi6nUwZDdrbk3f9NSgiQ7SubNgaSm7O08+l32eM=","Exponent":"AQAB","InverseQ":"0uInjerGTchFQ1gJYfW+003Ml8zmhiTXXZLR/ONarQYEK/hiJj0/slGVQpLuIOxFvkGgqjfraThlm5Q6+768Bv5EZ5KbhrKJ184R/nlIzFh7+9IjShf5XI7PSJmLrzX4cysaiPCFM94vZGkF4b7BabsL1TEQe5dBPZJ8tOpCa5I=","Modulus":"xU7G8MJp6Nmj8fKrkUqBlf2mRqvVjkRGmWU/gNHTepB1YQe0zoDmdIx8LF0j3Xk2Tvyekry68pV/qdURFJEGb9pmEksJkMQZ927V1+FTUBeWP666Ln4bTkJwkDtSfN4fPC70hmew1zQdeZmZBrc8BbQpIS8tHQ7rOZk9E+H8tgJbCbpLjAqWrg7gzJlgosd5xamm5XOk5R5oU+3QvkKwOLIn5RgOYzjVkkPKE+tOECPIi/2hDRCFVYwSvC5knmGP6UCHbib+mSDnloB4RMX0h95p+i3QXdeiF0daelVQUhGY56ONRqAFKqDpJzzJ/q4g9ci7sHHNUW8amJWwBgt8iQ==","P":"/uTPchvRiNBlQTr7R5x3NSQMX62RTYqOWjPexaNTeB/Q2qgumKhWe/QGvsQLCTfjmFEDyFs7kcgDSDv3RSAqUm8dFqJKmvT2Hxpvb4/GCG6crH1fp1pBZ7OZ7mjd2zvPaSdOIaa4t+TYZOB7SHDP0xtR1EPVWkBhH1BPbggFXDM=","Q":"xin88RYcPBMO6aYz/7U7wvUb/byUou64yxkzY1sqPYZYOxm5v9VfqoT5LT8wcbynDe1yLmjxwshhOTrd3rj2AQL2DdaT6xuQRJ1XHjONpW0VmaHzLtOWxc+Z2P1MzpnhoewcedrCd+XTPkr4of7o1dEGcxCOnL9FQPa8l0vfCFM="}}
Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

@@ -0,0 +1,337 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
"@abp/aspnetcore.mvc.ui.theme.basic@~8.3.0":
version "8.3.0"
resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.basic/-/aspnetcore.mvc.ui.theme.basic-8.3.0.tgz#a2d17eb5da2c3abfad4bcc842cfcda0e58a130a4"
integrity sha512-T2dg7WlvNSrwTCfy5wk4gqiJ/15kIjMGM4wLXIJcMYn60yGY/YeX6Q4A3R/qJzfl4JdgW5rt3GpdKv86y/ADXg==
dependencies:
"@abp/aspnetcore.mvc.ui.theme.shared" "~8.3.0"
"@abp/aspnetcore.mvc.ui.theme.shared@~8.3.0":
version "8.3.0"
resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.shared/-/aspnetcore.mvc.ui.theme.shared-8.3.0.tgz#5d6bb5181a62770e9cb967980b77e75c115c5ed7"
integrity sha512-o/0eh8jLS+YJiseTKzzioUz0vNnMFzyoz+mkyA4PlO1gqw2JFhzPhTBZ3cuyV9QlxUfEA8dWAkqAUX6vqiHwkw==
dependencies:
"@abp/aspnetcore.mvc.ui" "~8.3.0"
"@abp/bootstrap" "~8.3.0"
"@abp/bootstrap-datepicker" "~8.3.0"
"@abp/bootstrap-daterangepicker" "~8.3.0"
"@abp/datatables.net-bs5" "~8.3.0"
"@abp/font-awesome" "~8.3.0"
"@abp/jquery-form" "~8.3.0"
"@abp/jquery-validation-unobtrusive" "~8.3.0"
"@abp/lodash" "~8.3.0"
"@abp/luxon" "~8.3.0"
"@abp/malihu-custom-scrollbar-plugin" "~8.3.0"
"@abp/moment" "~8.3.0"
"@abp/select2" "~8.3.0"
"@abp/sweetalert2" "~8.3.0"
"@abp/timeago" "~8.3.0"
"@abp/toastr" "~8.3.0"
"@abp/aspnetcore.mvc.ui@~8.3.0":
version "8.3.0"
resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui/-/aspnetcore.mvc.ui-8.3.0.tgz#d7ba0539bfcc6661a347dea7f952489010b3e816"
integrity sha512-OxgZhLKiXGFYYpNJ5O/IbhinsniiBPv9586e+1Soar0GckCMIIegJxnJb1Bo1O75blrcK2cIU6LqjRT1FXt2Lw==
dependencies:
ansi-colors "^4.1.3"
"@abp/bootstrap-datepicker@~8.3.0":
version "8.3.0"
resolved "https://registry.yarnpkg.com/@abp/bootstrap-datepicker/-/bootstrap-datepicker-8.3.0.tgz#8c1bf9efec37b671d8f28b8b1e89c1ac66684267"
integrity sha512-KCwMtm7x+cnKPeNMzhjDJUce0stwu4e57ibmvA6sMf1tmj+yB256O4E2hIDDohiT3vP/zV8HVHX6uATlcmGC9w==
dependencies:
bootstrap-datepicker "^1.10.0"
"@abp/bootstrap-daterangepicker@~8.3.0":
version "8.3.0"
resolved "https://registry.yarnpkg.com/@abp/bootstrap-daterangepicker/-/bootstrap-daterangepicker-8.3.0.tgz#2b8ed978333502677916f88cbb3e1d1b1c8a3a17"
integrity sha512-uQSfuCQogl4BujdqvtdAoSE+z32ci8FT5+i3gLfpqbgTaxvY/Kv5NxAUH5/1sjnuAE7SMWO+eVvI3V0pXgQohg==
dependencies:
bootstrap-daterangepicker "^3.1.0"
"@abp/bootstrap@~8.3.0":
version "8.3.0"
resolved "https://registry.yarnpkg.com/@abp/bootstrap/-/bootstrap-8.3.0.tgz#96d6ea7e6ac30f6e34e495a4224f56f7b2a1a7a3"
integrity sha512-5AmdTtakmWhZmHrb7ibvvf+KwF9OGadpAe7Kv9mNEE02K2qkp7Xw4r5o/bgVl7YfLC1FA6GZZXrV2s2t0gjHtg==
dependencies:
"@abp/core" "~8.3.0"
bootstrap "^5.3.3"
"@abp/core@~8.3.0":
version "8.3.0"
resolved "https://registry.yarnpkg.com/@abp/core/-/core-8.3.0.tgz#3a68f5a9549efcc3e13500e301f2576751b51445"
integrity sha512-zrxnZi4qij/Y4AZWaXuPqs3Dd7gBtU/onX7FkYxLgQDxYBfx+84QAnPRNRFKMWaD/wKbTUB0wA66U3t2aiQX9Q==
dependencies:
"@abp/utils" "~8.3.0"
"@abp/datatables.net-bs5@~8.3.0":
version "8.3.0"
resolved "https://registry.yarnpkg.com/@abp/datatables.net-bs5/-/datatables.net-bs5-8.3.0.tgz#21822ae4912a561afe9112925185aece03fcd0eb"
integrity sha512-GOGYSSHp3iPUDFRX2Y3C0wkiCOJDuYuK/zUSzQLNpOvBMZO+I/oWBcZM+qkVowIzsoRlAGV9+CVV2B/B05qidA==
dependencies:
"@abp/datatables.net" "~8.3.0"
datatables.net-bs5 "^2.0.8"
"@abp/datatables.net@~8.3.0":
version "8.3.0"
resolved "https://registry.yarnpkg.com/@abp/datatables.net/-/datatables.net-8.3.0.tgz#ff697758ce9309ba8311f23aec921c4722588c8b"
integrity sha512-4dIdv7eN1tVouOUrlF+MIdg8zQpecyH61waqLgy1q5jMZQivrTSFZ7UWMG3WVOAYjw5zSUZHZPbzA+ttnaOPkg==
dependencies:
"@abp/jquery" "~8.3.0"
datatables.net "^2.0.8"
"@abp/font-awesome@~8.3.0":
version "8.3.0"
resolved "https://registry.yarnpkg.com/@abp/font-awesome/-/font-awesome-8.3.0.tgz#9e4e9adc08dfca52c0a07d1608c5e5662675a4c9"
integrity sha512-NRxvM/dzvQC2Cj/F5i07XB/i6IVTmXcO9sOq6TWosWib0wGaPxRbCSjy8QUAYSD1QYaVQ30XMb3XXImaMGyd8A==
dependencies:
"@abp/core" "~8.3.0"
"@fortawesome/fontawesome-free" "^6.5.2"
"@abp/jquery-form@~8.3.0":
version "8.3.0"
resolved "https://registry.yarnpkg.com/@abp/jquery-form/-/jquery-form-8.3.0.tgz#fa2ad2fedbe3d3528ee94cbbd4f94d48f0cb5e4d"
integrity sha512-olP9FmpNVTbOIewsVua0moHVYXw4Sl3chFbvTDLG6vRBohLSjllUXfgY3UEIVWR1PCqnAg+iEJZl9NHB9iOLBg==
dependencies:
"@abp/jquery" "~8.3.0"
jquery-form "^4.3.0"
"@abp/jquery-validation-unobtrusive@~8.3.0":
version "8.3.0"
resolved "https://registry.yarnpkg.com/@abp/jquery-validation-unobtrusive/-/jquery-validation-unobtrusive-8.3.0.tgz#0992cdd33170df83c79aa3371038c0b30e451521"
integrity sha512-9hidjq8x8sTnP5O3K2b2x9NpxvPd9WB03ENR6OfvM89kfSmQapSvBZTlCu80YK9NaQJ6MLQRLYOCuc3GHcj3EQ==
dependencies:
"@abp/jquery-validation" "~8.3.0"
jquery-validation-unobtrusive "^4.0.0"
"@abp/jquery-validation@~8.3.0":
version "8.3.0"
resolved "https://registry.yarnpkg.com/@abp/jquery-validation/-/jquery-validation-8.3.0.tgz#bd6a72c6d86f116abe3b5d2adf3752bdbbcca887"
integrity sha512-6l5BZSa3N0Fou6Se7MfUSnI2dD4SYhZ2V988bgPJQ6p37XBOZ2OAj7LEIf5FSjtUzXjao/6/vqjkPNYreNikig==
dependencies:
"@abp/jquery" "~8.3.0"
jquery-validation "^1.20.1"
"@abp/jquery@~8.3.0":
version "8.3.0"
resolved "https://registry.yarnpkg.com/@abp/jquery/-/jquery-8.3.0.tgz#9be5ef2f769680226e6a1a981026590caf3b57ef"
integrity sha512-GsFY+n3EtS6B0pAoKd+xMnt5Dzi5bHvIbhLgDgfQfOBzAy3twGRWsPQ3nkuXXm8TppwujMNowU1oiLKPPm0AOA==
dependencies:
"@abp/core" "~8.3.0"
jquery "~3.7.1"
"@abp/lodash@~8.3.0":
version "8.3.0"
resolved "https://registry.yarnpkg.com/@abp/lodash/-/lodash-8.3.0.tgz#f5a0a496c999886f2d6999067bfac2e1f0c3969c"
integrity sha512-BiAsONbKR/RKG3WjRaMWVmhNe1ELEsykVq+ogG1Rhk3kwPbvze3TS8k2p0Lu/RC41/BmDUmJ5abg1pUMwkRT8w==
dependencies:
"@abp/core" "~8.3.0"
lodash "^4.17.21"
"@abp/luxon@~8.3.0":
version "8.3.0"
resolved "https://registry.yarnpkg.com/@abp/luxon/-/luxon-8.3.0.tgz#7dd3f756be1605506e26f7ac76b80cc082a12d07"
integrity sha512-8gdI5BtXkVp0sFg89QVDe8AvgQ7Qfq4JCqz2PMrKPSATR3H8GD6BCaEYpRp6CNTCjVrQjGZdzKgUyea1D3dHbw==
dependencies:
"@abp/core" "~8.3.0"
luxon "^3.4.4"
"@abp/malihu-custom-scrollbar-plugin@~8.3.0":
version "8.3.0"
resolved "https://registry.yarnpkg.com/@abp/malihu-custom-scrollbar-plugin/-/malihu-custom-scrollbar-plugin-8.3.0.tgz#c88c132c3402bbb02054ca7d446051950f87a817"
integrity sha512-nd/mb6LJa6fMxal8PGcIjIRIoZ/UHCd01WDC9YI2H4wGCGx0CA0JyHso5oc/OEzJhUL8ujO/vYm9uLb7YahPtA==
dependencies:
"@abp/core" "~8.3.0"
malihu-custom-scrollbar-plugin "^3.1.5"
"@abp/moment@~8.3.0":
version "8.3.0"
resolved "https://registry.yarnpkg.com/@abp/moment/-/moment-8.3.0.tgz#8e4f7a523ab76ef9e4cd96a399560bad38d38d1a"
integrity sha512-LywSsKuQ2GN/Btmle6CcTKa811zbvUWdC+RLQA792K9HyBs6LvN0qRRluEQZgplairRgh2pDOg8tdFlUERkv2w==
dependencies:
moment "^2.30.1"
"@abp/select2@~8.3.0":
version "8.3.0"
resolved "https://registry.yarnpkg.com/@abp/select2/-/select2-8.3.0.tgz#ef4742fcd345394767f46180f61c6cabbd0b3867"
integrity sha512-bdLt2+ImxxpiZl4HGbYJpdDROQUT7/Z/+8A+6oJNacq3lNekdvufLYgTMxKru6zTbnd9j3HFKMOTE1eRjb9Xqg==
dependencies:
"@abp/core" "~8.3.0"
select2 "^4.0.13"
"@abp/sweetalert2@~8.3.0":
version "8.3.0"
resolved "https://registry.yarnpkg.com/@abp/sweetalert2/-/sweetalert2-8.3.0.tgz#a63020d57e44f7940817287d3d9676288bfb85aa"
integrity sha512-ooqPM4Z2v2scnMo5l8ycTmp6t/sW4sCsvIkJ4TyM876WLQJaZxJdOao4RQWuU+dVFr9zg8cOwqLH4q7UEiO6ww==
dependencies:
"@abp/core" "~8.3.0"
sweetalert2 "^11.3.6"
"@abp/timeago@~8.3.0":
version "8.3.0"
resolved "https://registry.yarnpkg.com/@abp/timeago/-/timeago-8.3.0.tgz#b3b8d6927bf170f77af848bc1925e5ef6835bd55"
integrity sha512-Dd6xaUoF9Bp4F9WJnTsFBqY+Gt++UR7UmLvBZL/dvthkeNCu2I8MUsmshkUUjY0lIXpjZwefUOuyupQrgHXPMg==
dependencies:
"@abp/jquery" "~8.3.0"
timeago "^1.6.7"
"@abp/toastr@~8.3.0":
version "8.3.0"
resolved "https://registry.yarnpkg.com/@abp/toastr/-/toastr-8.3.0.tgz#e68a2bd8f731e79034594bc2c736f7c66b3df1af"
integrity sha512-aWK/RaX/FmcEKhJLjsw1A0K2c04m2fRJkmo9NwzBCSscy6Msw9IMkqNWLiFDThMU8/qKzq7wq3Vmk/C0IpeAwA==
dependencies:
"@abp/jquery" "~8.3.0"
toastr "^2.1.4"
"@abp/utils@~8.3.0":
version "8.3.0"
resolved "https://registry.yarnpkg.com/@abp/utils/-/utils-8.3.0.tgz#96ae9266ad4d833fd9d723acef7fc85fabf618d9"
integrity sha512-w/XAqza4Z8wBWRoj5uPNKbd1/bE9L/uUWk6EUSBKmljMRryWQBmaPkb1XgvrOMQIbyyF60tUvvipapQLPVh6hw==
dependencies:
just-compare "^2.3.0"
"@fortawesome/fontawesome-free@^6.5.2":
version "6.6.0"
resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-free/-/fontawesome-free-6.6.0.tgz#0e984f0f2344ee513c185d87d77defac4c0c8224"
integrity sha512-60G28ke/sXdtS9KZCpZSHHkCbdsOGEhIUGlwq6yhY74UpTiToIh8np7A8yphhM4BWsvNFtIvLpi4co+h9Mr9Ow==
ansi-colors@^4.1.3:
version "4.1.3"
resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.3.tgz#37611340eb2243e70cc604cad35d63270d48781b"
integrity sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==
bootstrap-datepicker@^1.10.0:
version "1.10.0"
resolved "https://registry.yarnpkg.com/bootstrap-datepicker/-/bootstrap-datepicker-1.10.0.tgz#61612bbe8bf0a69a5bce32bbcdda93ebb6ccf24a"
integrity sha512-lWxtSYddAQOpbAO8UhYhHLcK6425eWoSjb5JDvZU3ePHEPF6A3eUr51WKaFy4PccU19JRxUG6wEU3KdhtKfvpg==
dependencies:
jquery ">=3.4.0 <4.0.0"
bootstrap-daterangepicker@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/bootstrap-daterangepicker/-/bootstrap-daterangepicker-3.1.0.tgz#632e6fb2de4b6360c5c0a9d5f6adb9aace051fe8"
integrity sha512-oaQZx6ZBDo/dZNyXGVi2rx5GmFXThyQLAxdtIqjtLlYVaQUfQALl5JZMJJZzyDIX7blfy4ppZPAJ10g8Ma4d/g==
dependencies:
jquery ">=1.10"
moment "^2.9.0"
bootstrap@^5.3.3:
version "5.3.3"
resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-5.3.3.tgz#de35e1a765c897ac940021900fcbb831602bac38"
integrity sha512-8HLCdWgyoMguSO9o+aH+iuZ+aht+mzW0u3HIMzVu7Srrpv7EBBxTnrFlSCskwdY1+EOFQSm7uMJhNQHkdPcmjg==
datatables.net-bs5@^2.0.8:
version "2.1.6"
resolved "https://registry.yarnpkg.com/datatables.net-bs5/-/datatables.net-bs5-2.1.6.tgz#863c75472981d2cfad66f3cfd24e3c7da46986d6"
integrity sha512-GLp98kE2lJI6cBgLaCA1he+KhD3pcVJLK4QU8oD3Zb8uHAduX0BA2JPndFZqXJs4CS0L16fel8Xs3+0wGzFxSg==
dependencies:
datatables.net "2.1.6"
jquery ">=1.7"
datatables.net@2.1.6, datatables.net@^2.0.8:
version "2.1.6"
resolved "https://registry.yarnpkg.com/datatables.net/-/datatables.net-2.1.6.tgz#563a7fb2ae206a60a83ec0aba011ce7e75a65d1f"
integrity sha512-ziX0Wz91oDJ4o7gQNuGxQiVK91OUu/bRcXyxa6EZtDwLObmaGKpkCNS59QpzrGtIytQIVFtLfF1EDdYid5RVog==
dependencies:
jquery ">=1.7"
jquery-form@^4.3.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/jquery-form/-/jquery-form-4.3.0.tgz#7d3961c314a1f2d15298f4af1d3943f54f4149c6"
integrity sha512-q3uaVCEWdLOYUCI6dpNdwf/7cJFOsUgdpq6r0taxtGQ5NJSkOzofyWm4jpOuJ5YxdmL1FI5QR+q+HB63HHLGnQ==
dependencies:
jquery ">=1.7.2"
jquery-mousewheel@>=3.0.6:
version "3.1.13"
resolved "https://registry.yarnpkg.com/jquery-mousewheel/-/jquery-mousewheel-3.1.13.tgz#06f0335f16e353a695e7206bf50503cb523a6ee5"
jquery-validation-unobtrusive@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/jquery-validation-unobtrusive/-/jquery-validation-unobtrusive-4.0.0.tgz#dfcf25a558496a2c883db6021d10f5398d15f99d"
integrity sha512-1ervYFFv6LX/rp7ktuLnMakHNG0piNRDyROI8Ir3hL1vPIwylAehB1AY3BPrYJnzW3WmwWryZq+Bz4sazZK9iQ==
dependencies:
jquery "^3.6.0"
jquery-validation ">=1.19"
jquery-validation@>=1.19, jquery-validation@^1.20.1:
version "1.21.0"
resolved "https://registry.yarnpkg.com/jquery-validation/-/jquery-validation-1.21.0.tgz#78fc05ab76020912a246af3661b3f54a438bca93"
integrity sha512-xNot0rlUIgu7duMcQ5qb6MGkGL/Z1PQaRJQoZAURW9+a/2PGOUxY36o/WyNeP2T9R6jvWB8Z9lUVvvQWI/Zs5w==
jquery@>=1.10:
version "3.7.0"
resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.7.0.tgz#fe2c01a05da500709006d8790fe21c8a39d75612"
integrity sha512-umpJ0/k8X0MvD1ds0P9SfowREz2LenHsQaxSohMZ5OMNEU2r0tf8pdeEFTHMFxWVxKNyU9rTtK3CWzUCTKJUeQ==
jquery@>=1.12.0, jquery@>=1.7, jquery@>=1.7.2:
version "3.3.1"
resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.3.1.tgz#958ce29e81c9790f31be7792df5d4d95fc57fbca"
"jquery@>=1.5.0 <4.0":
version "3.4.1"
resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.4.1.tgz#714f1f8d9dde4bdfa55764ba37ef214630d80ef2"
integrity sha512-36+AdBzCL+y6qjw5Tx7HgzeGCzC81MDDgaUP8ld2zhx58HdqXGoBd+tHdrBMiyjGQs0Hxs/MLZTu/eHNJJuWPw==
"jquery@>=3.4.0 <4.0.0", jquery@^3.6.0, jquery@~3.7.1:
version "3.7.1"
resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.7.1.tgz#083ef98927c9a6a74d05a6af02806566d16274de"
integrity sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg==
just-compare@^2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/just-compare/-/just-compare-2.3.0.tgz#a2adcc1d1940536263275f5a1ef1298bcacfeda7"
integrity sha512-6shoR7HDT+fzfL3gBahx1jZG3hWLrhPAf+l7nCwahDdT9XDtosB9kIF0ZrzUp5QY8dJWfQVr5rnsPqsbvflDzg==
lodash@^4.17.21:
version "4.17.21"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
luxon@^3.4.4:
version "3.5.0"
resolved "https://registry.yarnpkg.com/luxon/-/luxon-3.5.0.tgz#6b6f65c5cd1d61d1fd19dbf07ee87a50bf4b8e20"
integrity sha512-rh+Zjr6DNfUYR3bPwJEnuwDdqMbxZW7LOQfUN4B54+Cl+0o5zaU9RJ6bcidfDtC1cWCZXQ+nvX8bf6bAji37QQ==
malihu-custom-scrollbar-plugin@^3.1.5:
version "3.1.5"
resolved "https://registry.yarnpkg.com/malihu-custom-scrollbar-plugin/-/malihu-custom-scrollbar-plugin-3.1.5.tgz#310cecc5e59415a1c29e9dfb5d2b6e01d66a29ef"
integrity sha1-MQzsxeWUFaHCnp37XStuAdZqKe8=
dependencies:
jquery-mousewheel ">=3.0.6"
moment@^2.30.1:
version "2.30.1"
resolved "https://registry.yarnpkg.com/moment/-/moment-2.30.1.tgz#f8c91c07b7a786e30c59926df530b4eac96974ae"
integrity sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==
moment@^2.9.0:
version "2.29.4"
resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.4.tgz#3dbe052889fe7c1b2ed966fcb3a77328964ef108"
integrity sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==
select2@^4.0.13:
version "4.0.13"
resolved "https://registry.yarnpkg.com/select2/-/select2-4.0.13.tgz#0dbe377df3f96167c4c1626033e924372d8ef44d"
integrity sha512-1JeB87s6oN/TDxQQYCvS5EFoQyvV6eYMZZ0AeA4tdFDYWN3BAGZ8npr17UBFddU0lgAt3H0yjX3X6/ekOj1yjw==
sweetalert2@^11.3.6:
version "11.7.5"
resolved "https://registry.yarnpkg.com/sweetalert2/-/sweetalert2-11.7.5.tgz#d905b792cfcb69d5db479f839151ce12d8804a8e"
integrity sha512-RBPKdK8Uf9/bz9r4vy7x6sGqf0MioSXt1po1lAwwcl3AwbjHVTc5S0yud4ZJKU1EhvJFVDrFoqIpHwWERwZJEA==
timeago@^1.6.7:
version "1.6.7"
resolved "https://registry.yarnpkg.com/timeago/-/timeago-1.6.7.tgz#afd467c29a911e697fc22a81888c7c3022783cb5"
integrity sha512-FikcjN98+ij0siKH4VO4dZ358PR3oDDq4Vdl1+sN9gWz1/+JXGr3uZbUShYH/hL7bMhcTpPbplJU5Tej4b4jbQ==
dependencies:
jquery ">=1.5.0 <4.0"
toastr@^2.1.4:
version "2.1.4"
resolved "https://registry.yarnpkg.com/toastr/-/toastr-2.1.4.tgz#8b43be64fb9d0c414871446f2db8e8ca4e95f181"
dependencies:
jquery ">=1.12.0"
@@ -0,0 +1,40 @@
using System;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.UI.Navigation;
using Volo.Abp.Users;
namespace Company.Project.BackendAdminApp;
public class BackendAdminAppMenuContributor : IMenuContributor
{
private readonly IConfiguration _configuration;
public BackendAdminAppMenuContributor(IConfiguration configuration)
{
_configuration = configuration;
}
public async Task ConfigureMenuAsync(MenuConfigurationContext context)
{
if (context.Menu.Name == StandardMenus.User)
{
await ConfigureUserMenuAsync(context);
}
}
private Task ConfigureUserMenuAsync(MenuConfigurationContext context)
{
var currentUser = context.ServiceProvider.GetRequiredService<ICurrentUser>();
var identityServerUrl = _configuration["AuthServer:Authority"] ?? "";
if (currentUser.IsAuthenticated)
{
context.Menu.AddItem(new ApplicationMenuItem("Account.Manage", "Manage Your Profile", $"{identityServerUrl.EnsureEndsWith('/')}Account/Manage", icon: "fa fa-cog", order: 1000, null, "_blank"));
context.Menu.AddItem(new ApplicationMenuItem("Account.Logout", "Logout", url: "/Account/Logout", icon: "fa fa-power-off", order: int.MaxValue - 1000));
}
return Task.CompletedTask;
}
}
@@ -0,0 +1,9 @@
using Volo.Abp.DependencyInjection;
using Volo.Abp.Ui.Branding;
namespace Company.Project.BackendAdminApp;
public class BrandingProvider : DefaultBrandingProvider, ISingletonDependency
{
public override string AppName => "Backend Admin App";
}
@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<RootNamespace>Company.Project.BackendAdminApp</RootNamespace>
</PropertyGroup>
<ItemGroup>
@@ -0,0 +1,8 @@
using Volo.Abp.AspNetCore.Mvc.Authentication;
namespace Company.Project.BackendAdminApp.Controllers;
public class AccountController : ChallengeAccountController
{
}
@@ -0,0 +1,12 @@
using Microsoft.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc;
namespace Company.Project.BackendAdminApp.Controllers;
public class HomeController : AbpController
{
public ActionResult Index()
{
return Redirect("/Identity/Users");
}
}
@@ -0,0 +1,35 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.Authorization.Permissions;
using Volo.Abp.Json;
namespace Company.Project.BackendAdminApp.Controllers;
public class TestController : AbpController
{
private readonly IJsonSerializer _jsonSerializer;
private readonly IPermissionChecker _permissionChecker;
public TestController(IJsonSerializer jsonSerializer, IPermissionChecker permissionChecker)
{
_jsonSerializer = jsonSerializer;
_permissionChecker = permissionChecker;
}
[HttpGet]
public async Task<ActionResult> Index()
{
var newLine = Environment.NewLine + Environment.NewLine;
return Content(
"Claims: " + User.Claims.Select(c => $"{c.Type} = {c.Value}").JoinAsString(" | ") + newLine +
"CurrentUser: " + _jsonSerializer.Serialize(CurrentUser) + newLine +
"access_token: " + await HttpContext.GetTokenAsync("access_token") + newLine +
"isGranted: AbpIdentity.Users: " + await _permissionChecker.IsGrantedAsync("AbpIdentity.Users")
);
}
}
@@ -0,0 +1,25 @@
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
WORKDIR /app
EXPOSE 80
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /src
COPY ["applications/Company.Project.BackendAdminApp.Host/Company.Project.BackendAdminApp.Host.csproj", "applications/Company.Project.BackendAdminApp.Host/"]
COPY ["modules/product/src/ProductManagement.Web/ProductManagement.Web.csproj", "modules/product/src/ProductManagement.Web/"]
COPY ["modules/product/src/ProductManagement.HttpApi/ProductManagement.HttpApi.csproj", "modules/product/src/ProductManagement.HttpApi/"]
COPY ["modules/product/src/ProductManagement.Application.Contracts/ProductManagement.Application.Contracts.csproj", "modules/product/src/ProductManagement.Application.Contracts/"]
COPY ["modules/product/src/ProductManagement.Domain.Shared/ProductManagement.Domain.Shared.csproj", "modules/product/src/ProductManagement.Domain.Shared/"]
COPY ["modules/product/src/ProductManagement.HttpApi.Client/ProductManagement.HttpApi.Client.csproj", "modules/product/src/ProductManagement.HttpApi.Client/"]
COPY ["shared/Company.Project.Shared/Company.Project.Shared.csproj", "shared/Company.Project.Shared/"]
RUN dotnet restore "applications/Company.Project.BackendAdminApp.Host/Company.Project.BackendAdminApp.Host.csproj" -nowarn:msb3202,msb3277,nu1503
COPY . .
WORKDIR "/src/applications/Company.Project.BackendAdminApp.Host"
RUN dotnet build "Company.Project.BackendAdminApp.Host.csproj" --no-restore -nowarn:msb3202,msb3277,nu1503 -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "Company.Project.BackendAdminApp.Host.csproj" --no-restore -nowarn:msb3202,msb3277,nu1503 -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "Company.Project.BackendAdminApp.Host.dll"]
@@ -0,0 +1,25 @@
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
WORKDIR /app
EXPOSE 80
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /src
COPY ["applications/Company.Project.BackendAdminApp.Host/Company.Project.BackendAdminApp.Host.csproj", "applications/Company.Project.BackendAdminApp.Host/"]
COPY ["modules/product/src/ProductManagement.Web/ProductManagement.Web.csproj", "modules/product/src/ProductManagement.Web/"]
COPY ["modules/product/src/ProductManagement.HttpApi/ProductManagement.HttpApi.csproj", "modules/product/src/ProductManagement.HttpApi/"]
COPY ["modules/product/src/ProductManagement.Application.Contracts/ProductManagement.Application.Contracts.csproj", "modules/product/src/ProductManagement.Application.Contracts/"]
COPY ["modules/product/src/ProductManagement.Domain.Shared/ProductManagement.Domain.Shared.csproj", "modules/product/src/ProductManagement.Domain.Shared/"]
COPY ["modules/product/src/ProductManagement.HttpApi.Client/ProductManagement.HttpApi.Client.csproj", "modules/product/src/ProductManagement.HttpApi.Client/"]
COPY ["shared/Company.Project.Shared/Company.Project.Shared.csproj", "shared/Company.Project.Shared/"]
RUN dotnet restore "applications/Company.Project.BackendAdminApp.Host/Company.Project.BackendAdminApp.Host.csproj" -nowarn:msb3202,msb3277,nu1503
COPY . .
WORKDIR "/src/applications/Company.Project.BackendAdminApp.Host"
RUN dotnet build "Company.Project.BackendAdminApp.Host.csproj" --no-restore -nowarn:msb3202,msb3277,nu1503 -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "Company.Project.BackendAdminApp.Host.csproj" --no-restore -nowarn:msb3202,msb3277,nu1503 -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "Company.Project.BackendAdminApp.Host.dll"]
@@ -0,0 +1,27 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "https://localhost:44354",
"sslPort": 0
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"Company.Project.BackendAdminApp.Host": {
"commandName": "Project",
"launchBrowser": true,
"applicationUrl": "https://localhost:44354",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
@@ -0,0 +1,11 @@
module.exports = {
aliases: {
},
clean: [
],
mappings: {
}
};
@@ -0,0 +1,9 @@
{
"Logging": {
"LogLevel": {
"Default": "Debug",
"System": "Information",
"Microsoft": "Information"
}
}
}
@@ -0,0 +1,20 @@
{
"AuthServer": {
"Authority": "https://localhost:44399",
"RequireHttpsMetadata": "true",
"ClientId": "backend-admin-app-client",
"ClientSecret": "1q2w3e*"
},
"RemoteServices": {
"Default": {
"BaseUrl": "https://localhost:44315/"
}
},
"Redis": {
"Configuration": "localhost:6379"
},
"Serilog": {
"MinimumLevel": { "Default": "Warning" }
},
"AllowedHosts": "*"
}
@@ -0,0 +1,9 @@
"use strict";
var gulp = require("gulp"),
path = require('path'),
copyResources = require('./node_modules/@abp/aspnetcore.mvc.ui/gulp/copy-resources.js');
exports.default = function(){
return copyResources(path.resolve('./'));
};
@@ -0,0 +1,8 @@
{
"version": "0.1.0",
"name": "my-project-backendadminapp-host",
"private": true,
"dependencies": {
"@abp/aspnetcore.mvc.ui.theme.basic": "~9.0.0"
}
}
@@ -0,0 +1,337 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
"@abp/aspnetcore.mvc.ui.theme.basic@~8.3.0":
version "8.3.0"
resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.basic/-/aspnetcore.mvc.ui.theme.basic-8.3.0.tgz#a2d17eb5da2c3abfad4bcc842cfcda0e58a130a4"
integrity sha512-T2dg7WlvNSrwTCfy5wk4gqiJ/15kIjMGM4wLXIJcMYn60yGY/YeX6Q4A3R/qJzfl4JdgW5rt3GpdKv86y/ADXg==
dependencies:
"@abp/aspnetcore.mvc.ui.theme.shared" "~8.3.0"
"@abp/aspnetcore.mvc.ui.theme.shared@~8.3.0":
version "8.3.0"
resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.shared/-/aspnetcore.mvc.ui.theme.shared-8.3.0.tgz#5d6bb5181a62770e9cb967980b77e75c115c5ed7"
integrity sha512-o/0eh8jLS+YJiseTKzzioUz0vNnMFzyoz+mkyA4PlO1gqw2JFhzPhTBZ3cuyV9QlxUfEA8dWAkqAUX6vqiHwkw==
dependencies:
"@abp/aspnetcore.mvc.ui" "~8.3.0"
"@abp/bootstrap" "~8.3.0"
"@abp/bootstrap-datepicker" "~8.3.0"
"@abp/bootstrap-daterangepicker" "~8.3.0"
"@abp/datatables.net-bs5" "~8.3.0"
"@abp/font-awesome" "~8.3.0"
"@abp/jquery-form" "~8.3.0"
"@abp/jquery-validation-unobtrusive" "~8.3.0"
"@abp/lodash" "~8.3.0"
"@abp/luxon" "~8.3.0"
"@abp/malihu-custom-scrollbar-plugin" "~8.3.0"
"@abp/moment" "~8.3.0"
"@abp/select2" "~8.3.0"
"@abp/sweetalert2" "~8.3.0"
"@abp/timeago" "~8.3.0"
"@abp/toastr" "~8.3.0"
"@abp/aspnetcore.mvc.ui@~8.3.0":
version "8.3.0"
resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui/-/aspnetcore.mvc.ui-8.3.0.tgz#d7ba0539bfcc6661a347dea7f952489010b3e816"
integrity sha512-OxgZhLKiXGFYYpNJ5O/IbhinsniiBPv9586e+1Soar0GckCMIIegJxnJb1Bo1O75blrcK2cIU6LqjRT1FXt2Lw==
dependencies:
ansi-colors "^4.1.3"
"@abp/bootstrap-datepicker@~8.3.0":
version "8.3.0"
resolved "https://registry.yarnpkg.com/@abp/bootstrap-datepicker/-/bootstrap-datepicker-8.3.0.tgz#8c1bf9efec37b671d8f28b8b1e89c1ac66684267"
integrity sha512-KCwMtm7x+cnKPeNMzhjDJUce0stwu4e57ibmvA6sMf1tmj+yB256O4E2hIDDohiT3vP/zV8HVHX6uATlcmGC9w==
dependencies:
bootstrap-datepicker "^1.10.0"
"@abp/bootstrap-daterangepicker@~8.3.0":
version "8.3.0"
resolved "https://registry.yarnpkg.com/@abp/bootstrap-daterangepicker/-/bootstrap-daterangepicker-8.3.0.tgz#2b8ed978333502677916f88cbb3e1d1b1c8a3a17"
integrity sha512-uQSfuCQogl4BujdqvtdAoSE+z32ci8FT5+i3gLfpqbgTaxvY/Kv5NxAUH5/1sjnuAE7SMWO+eVvI3V0pXgQohg==
dependencies:
bootstrap-daterangepicker "^3.1.0"
"@abp/bootstrap@~8.3.0":
version "8.3.0"
resolved "https://registry.yarnpkg.com/@abp/bootstrap/-/bootstrap-8.3.0.tgz#96d6ea7e6ac30f6e34e495a4224f56f7b2a1a7a3"
integrity sha512-5AmdTtakmWhZmHrb7ibvvf+KwF9OGadpAe7Kv9mNEE02K2qkp7Xw4r5o/bgVl7YfLC1FA6GZZXrV2s2t0gjHtg==
dependencies:
"@abp/core" "~8.3.0"
bootstrap "^5.3.3"
"@abp/core@~8.3.0":
version "8.3.0"
resolved "https://registry.yarnpkg.com/@abp/core/-/core-8.3.0.tgz#3a68f5a9549efcc3e13500e301f2576751b51445"
integrity sha512-zrxnZi4qij/Y4AZWaXuPqs3Dd7gBtU/onX7FkYxLgQDxYBfx+84QAnPRNRFKMWaD/wKbTUB0wA66U3t2aiQX9Q==
dependencies:
"@abp/utils" "~8.3.0"
"@abp/datatables.net-bs5@~8.3.0":
version "8.3.0"
resolved "https://registry.yarnpkg.com/@abp/datatables.net-bs5/-/datatables.net-bs5-8.3.0.tgz#21822ae4912a561afe9112925185aece03fcd0eb"
integrity sha512-GOGYSSHp3iPUDFRX2Y3C0wkiCOJDuYuK/zUSzQLNpOvBMZO+I/oWBcZM+qkVowIzsoRlAGV9+CVV2B/B05qidA==
dependencies:
"@abp/datatables.net" "~8.3.0"
datatables.net-bs5 "^2.0.8"
"@abp/datatables.net@~8.3.0":
version "8.3.0"
resolved "https://registry.yarnpkg.com/@abp/datatables.net/-/datatables.net-8.3.0.tgz#ff697758ce9309ba8311f23aec921c4722588c8b"
integrity sha512-4dIdv7eN1tVouOUrlF+MIdg8zQpecyH61waqLgy1q5jMZQivrTSFZ7UWMG3WVOAYjw5zSUZHZPbzA+ttnaOPkg==
dependencies:
"@abp/jquery" "~8.3.0"
datatables.net "^2.0.8"
"@abp/font-awesome@~8.3.0":
version "8.3.0"
resolved "https://registry.yarnpkg.com/@abp/font-awesome/-/font-awesome-8.3.0.tgz#9e4e9adc08dfca52c0a07d1608c5e5662675a4c9"
integrity sha512-NRxvM/dzvQC2Cj/F5i07XB/i6IVTmXcO9sOq6TWosWib0wGaPxRbCSjy8QUAYSD1QYaVQ30XMb3XXImaMGyd8A==
dependencies:
"@abp/core" "~8.3.0"
"@fortawesome/fontawesome-free" "^6.5.2"
"@abp/jquery-form@~8.3.0":
version "8.3.0"
resolved "https://registry.yarnpkg.com/@abp/jquery-form/-/jquery-form-8.3.0.tgz#fa2ad2fedbe3d3528ee94cbbd4f94d48f0cb5e4d"
integrity sha512-olP9FmpNVTbOIewsVua0moHVYXw4Sl3chFbvTDLG6vRBohLSjllUXfgY3UEIVWR1PCqnAg+iEJZl9NHB9iOLBg==
dependencies:
"@abp/jquery" "~8.3.0"
jquery-form "^4.3.0"
"@abp/jquery-validation-unobtrusive@~8.3.0":
version "8.3.0"
resolved "https://registry.yarnpkg.com/@abp/jquery-validation-unobtrusive/-/jquery-validation-unobtrusive-8.3.0.tgz#0992cdd33170df83c79aa3371038c0b30e451521"
integrity sha512-9hidjq8x8sTnP5O3K2b2x9NpxvPd9WB03ENR6OfvM89kfSmQapSvBZTlCu80YK9NaQJ6MLQRLYOCuc3GHcj3EQ==
dependencies:
"@abp/jquery-validation" "~8.3.0"
jquery-validation-unobtrusive "^4.0.0"
"@abp/jquery-validation@~8.3.0":
version "8.3.0"
resolved "https://registry.yarnpkg.com/@abp/jquery-validation/-/jquery-validation-8.3.0.tgz#bd6a72c6d86f116abe3b5d2adf3752bdbbcca887"
integrity sha512-6l5BZSa3N0Fou6Se7MfUSnI2dD4SYhZ2V988bgPJQ6p37XBOZ2OAj7LEIf5FSjtUzXjao/6/vqjkPNYreNikig==
dependencies:
"@abp/jquery" "~8.3.0"
jquery-validation "^1.20.1"
"@abp/jquery@~8.3.0":
version "8.3.0"
resolved "https://registry.yarnpkg.com/@abp/jquery/-/jquery-8.3.0.tgz#9be5ef2f769680226e6a1a981026590caf3b57ef"
integrity sha512-GsFY+n3EtS6B0pAoKd+xMnt5Dzi5bHvIbhLgDgfQfOBzAy3twGRWsPQ3nkuXXm8TppwujMNowU1oiLKPPm0AOA==
dependencies:
"@abp/core" "~8.3.0"
jquery "~3.7.1"
"@abp/lodash@~8.3.0":
version "8.3.0"
resolved "https://registry.yarnpkg.com/@abp/lodash/-/lodash-8.3.0.tgz#f5a0a496c999886f2d6999067bfac2e1f0c3969c"
integrity sha512-BiAsONbKR/RKG3WjRaMWVmhNe1ELEsykVq+ogG1Rhk3kwPbvze3TS8k2p0Lu/RC41/BmDUmJ5abg1pUMwkRT8w==
dependencies:
"@abp/core" "~8.3.0"
lodash "^4.17.21"
"@abp/luxon@~8.3.0":
version "8.3.0"
resolved "https://registry.yarnpkg.com/@abp/luxon/-/luxon-8.3.0.tgz#7dd3f756be1605506e26f7ac76b80cc082a12d07"
integrity sha512-8gdI5BtXkVp0sFg89QVDe8AvgQ7Qfq4JCqz2PMrKPSATR3H8GD6BCaEYpRp6CNTCjVrQjGZdzKgUyea1D3dHbw==
dependencies:
"@abp/core" "~8.3.0"
luxon "^3.4.4"
"@abp/malihu-custom-scrollbar-plugin@~8.3.0":
version "8.3.0"
resolved "https://registry.yarnpkg.com/@abp/malihu-custom-scrollbar-plugin/-/malihu-custom-scrollbar-plugin-8.3.0.tgz#c88c132c3402bbb02054ca7d446051950f87a817"
integrity sha512-nd/mb6LJa6fMxal8PGcIjIRIoZ/UHCd01WDC9YI2H4wGCGx0CA0JyHso5oc/OEzJhUL8ujO/vYm9uLb7YahPtA==
dependencies:
"@abp/core" "~8.3.0"
malihu-custom-scrollbar-plugin "^3.1.5"
"@abp/moment@~8.3.0":
version "8.3.0"
resolved "https://registry.yarnpkg.com/@abp/moment/-/moment-8.3.0.tgz#8e4f7a523ab76ef9e4cd96a399560bad38d38d1a"
integrity sha512-LywSsKuQ2GN/Btmle6CcTKa811zbvUWdC+RLQA792K9HyBs6LvN0qRRluEQZgplairRgh2pDOg8tdFlUERkv2w==
dependencies:
moment "^2.30.1"
"@abp/select2@~8.3.0":
version "8.3.0"
resolved "https://registry.yarnpkg.com/@abp/select2/-/select2-8.3.0.tgz#ef4742fcd345394767f46180f61c6cabbd0b3867"
integrity sha512-bdLt2+ImxxpiZl4HGbYJpdDROQUT7/Z/+8A+6oJNacq3lNekdvufLYgTMxKru6zTbnd9j3HFKMOTE1eRjb9Xqg==
dependencies:
"@abp/core" "~8.3.0"
select2 "^4.0.13"
"@abp/sweetalert2@~8.3.0":
version "8.3.0"
resolved "https://registry.yarnpkg.com/@abp/sweetalert2/-/sweetalert2-8.3.0.tgz#a63020d57e44f7940817287d3d9676288bfb85aa"
integrity sha512-ooqPM4Z2v2scnMo5l8ycTmp6t/sW4sCsvIkJ4TyM876WLQJaZxJdOao4RQWuU+dVFr9zg8cOwqLH4q7UEiO6ww==
dependencies:
"@abp/core" "~8.3.0"
sweetalert2 "^11.3.6"
"@abp/timeago@~8.3.0":
version "8.3.0"
resolved "https://registry.yarnpkg.com/@abp/timeago/-/timeago-8.3.0.tgz#b3b8d6927bf170f77af848bc1925e5ef6835bd55"
integrity sha512-Dd6xaUoF9Bp4F9WJnTsFBqY+Gt++UR7UmLvBZL/dvthkeNCu2I8MUsmshkUUjY0lIXpjZwefUOuyupQrgHXPMg==
dependencies:
"@abp/jquery" "~8.3.0"
timeago "^1.6.7"
"@abp/toastr@~8.3.0":
version "8.3.0"
resolved "https://registry.yarnpkg.com/@abp/toastr/-/toastr-8.3.0.tgz#e68a2bd8f731e79034594bc2c736f7c66b3df1af"
integrity sha512-aWK/RaX/FmcEKhJLjsw1A0K2c04m2fRJkmo9NwzBCSscy6Msw9IMkqNWLiFDThMU8/qKzq7wq3Vmk/C0IpeAwA==
dependencies:
"@abp/jquery" "~8.3.0"
toastr "^2.1.4"
"@abp/utils@~8.3.0":
version "8.3.0"
resolved "https://registry.yarnpkg.com/@abp/utils/-/utils-8.3.0.tgz#96ae9266ad4d833fd9d723acef7fc85fabf618d9"
integrity sha512-w/XAqza4Z8wBWRoj5uPNKbd1/bE9L/uUWk6EUSBKmljMRryWQBmaPkb1XgvrOMQIbyyF60tUvvipapQLPVh6hw==
dependencies:
just-compare "^2.3.0"
"@fortawesome/fontawesome-free@^6.5.2":
version "6.6.0"
resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-free/-/fontawesome-free-6.6.0.tgz#0e984f0f2344ee513c185d87d77defac4c0c8224"
integrity sha512-60G28ke/sXdtS9KZCpZSHHkCbdsOGEhIUGlwq6yhY74UpTiToIh8np7A8yphhM4BWsvNFtIvLpi4co+h9Mr9Ow==
ansi-colors@^4.1.3:
version "4.1.3"
resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.3.tgz#37611340eb2243e70cc604cad35d63270d48781b"
integrity sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==
bootstrap-datepicker@^1.10.0:
version "1.10.0"
resolved "https://registry.yarnpkg.com/bootstrap-datepicker/-/bootstrap-datepicker-1.10.0.tgz#61612bbe8bf0a69a5bce32bbcdda93ebb6ccf24a"
integrity sha512-lWxtSYddAQOpbAO8UhYhHLcK6425eWoSjb5JDvZU3ePHEPF6A3eUr51WKaFy4PccU19JRxUG6wEU3KdhtKfvpg==
dependencies:
jquery ">=3.4.0 <4.0.0"
bootstrap-daterangepicker@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/bootstrap-daterangepicker/-/bootstrap-daterangepicker-3.1.0.tgz#632e6fb2de4b6360c5c0a9d5f6adb9aace051fe8"
integrity sha512-oaQZx6ZBDo/dZNyXGVi2rx5GmFXThyQLAxdtIqjtLlYVaQUfQALl5JZMJJZzyDIX7blfy4ppZPAJ10g8Ma4d/g==
dependencies:
jquery ">=1.10"
moment "^2.9.0"
bootstrap@^5.3.3:
version "5.3.3"
resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-5.3.3.tgz#de35e1a765c897ac940021900fcbb831602bac38"
integrity sha512-8HLCdWgyoMguSO9o+aH+iuZ+aht+mzW0u3HIMzVu7Srrpv7EBBxTnrFlSCskwdY1+EOFQSm7uMJhNQHkdPcmjg==
datatables.net-bs5@^2.0.8:
version "2.1.6"
resolved "https://registry.yarnpkg.com/datatables.net-bs5/-/datatables.net-bs5-2.1.6.tgz#863c75472981d2cfad66f3cfd24e3c7da46986d6"
integrity sha512-GLp98kE2lJI6cBgLaCA1he+KhD3pcVJLK4QU8oD3Zb8uHAduX0BA2JPndFZqXJs4CS0L16fel8Xs3+0wGzFxSg==
dependencies:
datatables.net "2.1.6"
jquery ">=1.7"
datatables.net@2.1.6, datatables.net@^2.0.8:
version "2.1.6"
resolved "https://registry.yarnpkg.com/datatables.net/-/datatables.net-2.1.6.tgz#563a7fb2ae206a60a83ec0aba011ce7e75a65d1f"
integrity sha512-ziX0Wz91oDJ4o7gQNuGxQiVK91OUu/bRcXyxa6EZtDwLObmaGKpkCNS59QpzrGtIytQIVFtLfF1EDdYid5RVog==
dependencies:
jquery ">=1.7"
jquery-form@^4.3.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/jquery-form/-/jquery-form-4.3.0.tgz#7d3961c314a1f2d15298f4af1d3943f54f4149c6"
integrity sha512-q3uaVCEWdLOYUCI6dpNdwf/7cJFOsUgdpq6r0taxtGQ5NJSkOzofyWm4jpOuJ5YxdmL1FI5QR+q+HB63HHLGnQ==
dependencies:
jquery ">=1.7.2"
jquery-mousewheel@>=3.0.6:
version "3.1.13"
resolved "https://registry.yarnpkg.com/jquery-mousewheel/-/jquery-mousewheel-3.1.13.tgz#06f0335f16e353a695e7206bf50503cb523a6ee5"
jquery-validation-unobtrusive@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/jquery-validation-unobtrusive/-/jquery-validation-unobtrusive-4.0.0.tgz#dfcf25a558496a2c883db6021d10f5398d15f99d"
integrity sha512-1ervYFFv6LX/rp7ktuLnMakHNG0piNRDyROI8Ir3hL1vPIwylAehB1AY3BPrYJnzW3WmwWryZq+Bz4sazZK9iQ==
dependencies:
jquery "^3.6.0"
jquery-validation ">=1.19"
jquery-validation@>=1.19, jquery-validation@^1.20.1:
version "1.21.0"
resolved "https://registry.yarnpkg.com/jquery-validation/-/jquery-validation-1.21.0.tgz#78fc05ab76020912a246af3661b3f54a438bca93"
integrity sha512-xNot0rlUIgu7duMcQ5qb6MGkGL/Z1PQaRJQoZAURW9+a/2PGOUxY36o/WyNeP2T9R6jvWB8Z9lUVvvQWI/Zs5w==
jquery@>=1.10:
version "3.7.0"
resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.7.0.tgz#fe2c01a05da500709006d8790fe21c8a39d75612"
integrity sha512-umpJ0/k8X0MvD1ds0P9SfowREz2LenHsQaxSohMZ5OMNEU2r0tf8pdeEFTHMFxWVxKNyU9rTtK3CWzUCTKJUeQ==
jquery@>=1.12.0, jquery@>=1.7, jquery@>=1.7.2:
version "3.3.1"
resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.3.1.tgz#958ce29e81c9790f31be7792df5d4d95fc57fbca"
"jquery@>=1.5.0 <4.0":
version "3.4.1"
resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.4.1.tgz#714f1f8d9dde4bdfa55764ba37ef214630d80ef2"
integrity sha512-36+AdBzCL+y6qjw5Tx7HgzeGCzC81MDDgaUP8ld2zhx58HdqXGoBd+tHdrBMiyjGQs0Hxs/MLZTu/eHNJJuWPw==
"jquery@>=3.4.0 <4.0.0", jquery@^3.6.0, jquery@~3.7.1:
version "3.7.1"
resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.7.1.tgz#083ef98927c9a6a74d05a6af02806566d16274de"
integrity sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg==
just-compare@^2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/just-compare/-/just-compare-2.3.0.tgz#a2adcc1d1940536263275f5a1ef1298bcacfeda7"
integrity sha512-6shoR7HDT+fzfL3gBahx1jZG3hWLrhPAf+l7nCwahDdT9XDtosB9kIF0ZrzUp5QY8dJWfQVr5rnsPqsbvflDzg==
lodash@^4.17.21:
version "4.17.21"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
luxon@^3.4.4:
version "3.5.0"
resolved "https://registry.yarnpkg.com/luxon/-/luxon-3.5.0.tgz#6b6f65c5cd1d61d1fd19dbf07ee87a50bf4b8e20"
integrity sha512-rh+Zjr6DNfUYR3bPwJEnuwDdqMbxZW7LOQfUN4B54+Cl+0o5zaU9RJ6bcidfDtC1cWCZXQ+nvX8bf6bAji37QQ==
malihu-custom-scrollbar-plugin@^3.1.5:
version "3.1.5"
resolved "https://registry.yarnpkg.com/malihu-custom-scrollbar-plugin/-/malihu-custom-scrollbar-plugin-3.1.5.tgz#310cecc5e59415a1c29e9dfb5d2b6e01d66a29ef"
integrity sha1-MQzsxeWUFaHCnp37XStuAdZqKe8=
dependencies:
jquery-mousewheel ">=3.0.6"
moment@^2.30.1:
version "2.30.1"
resolved "https://registry.yarnpkg.com/moment/-/moment-2.30.1.tgz#f8c91c07b7a786e30c59926df530b4eac96974ae"
integrity sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==
moment@^2.9.0:
version "2.29.4"
resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.4.tgz#3dbe052889fe7c1b2ed966fcb3a77328964ef108"
integrity sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==
select2@^4.0.13:
version "4.0.13"
resolved "https://registry.yarnpkg.com/select2/-/select2-4.0.13.tgz#0dbe377df3f96167c4c1626033e924372d8ef44d"
integrity sha512-1JeB87s6oN/TDxQQYCvS5EFoQyvV6eYMZZ0AeA4tdFDYWN3BAGZ8npr17UBFddU0lgAt3H0yjX3X6/ekOj1yjw==
sweetalert2@^11.3.6:
version "11.7.5"
resolved "https://registry.yarnpkg.com/sweetalert2/-/sweetalert2-11.7.5.tgz#d905b792cfcb69d5db479f839151ce12d8804a8e"
integrity sha512-RBPKdK8Uf9/bz9r4vy7x6sGqf0MioSXt1po1lAwwcl3AwbjHVTc5S0yud4ZJKU1EhvJFVDrFoqIpHwWERwZJEA==
timeago@^1.6.7:
version "1.6.7"
resolved "https://registry.yarnpkg.com/timeago/-/timeago-1.6.7.tgz#afd467c29a911e697fc22a81888c7c3022783cb5"
integrity sha512-FikcjN98+ij0siKH4VO4dZ358PR3oDDq4Vdl1+sN9gWz1/+JXGr3uZbUShYH/hL7bMhcTpPbplJU5Tej4b4jbQ==
dependencies:
jquery ">=1.5.0 <4.0"
toastr@^2.1.4:
version "2.1.4"
resolved "https://registry.yarnpkg.com/toastr/-/toastr-2.1.4.tgz#8b43be64fb9d0c414871446f2db8e8ca4e95f181"
dependencies:
jquery ">=1.12.0"
@@ -0,0 +1,146 @@
using System;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.Extensions.Options;
using ProductManagement;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Http.Client;
using Volo.Abp.Identity;
using Volo.Abp.IdentityModel;
using Volo.Abp.TenantManagement;
namespace Company.Project.ConsoleClientDemo;
public class ClientDemoService : ITransientDependency
{
private readonly IIdentityUserAppService _userAppService;
private readonly ITenantAppService _tenantAppService;
private readonly IProductAppService _productAppService;
private readonly IIdentityModelAuthenticationService _authenticator;
private readonly AbpRemoteServiceOptions _remoteServiceOptions;
public ClientDemoService(
IIdentityUserAppService userAppService,
IProductAppService productAppService,
IIdentityModelAuthenticationService authenticator,
IOptions<AbpRemoteServiceOptions> remoteServiceOptions,
ITenantAppService tenantAppService)
{
_userAppService = userAppService;
_authenticator = authenticator;
_tenantAppService = tenantAppService;
_remoteServiceOptions = remoteServiceOptions.Value;
_productAppService = productAppService;
}
public async Task RunAsync()
{
await TestWithHttpClient();
await TestIdentityService();
await TestTenantManagementService();
await TestProductService();
}
private async Task TestWithHttpClient()
{
Console.WriteLine();
Console.WriteLine("*** TestWithHttpClient ************************************");
try
{
using (var client = new HttpClient())
{
await _authenticator.TryAuthenticateAsync(client);
var url = GetServerUrl() + "Test/Index";
var response = await client.GetAsync(url);
if (!response.IsSuccessStatusCode)
{
Console.WriteLine(response.StatusCode);
}
else
{
var responseContent = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseContent);
}
}
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
private async Task TestIdentityService()
{
Console.WriteLine();
Console.WriteLine("*** TestIdentityService ************************************");
try
{
var output = await _userAppService.GetListAsync(new GetIdentityUsersInput());
Console.WriteLine("Total user count: " + output.TotalCount);
foreach (var user in output.Items)
{
Console.WriteLine($"- UserName={user.UserName}, Email={user.Email}, Name={user.Name}, Surname={user.Surname}");
}
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
private async Task TestTenantManagementService()
{
Console.WriteLine();
Console.WriteLine("*** TestTenantManagementService ************************************");
try
{
var output = await _tenantAppService.GetListAsync(new GetTenantsInput());
Console.WriteLine("Total tenant count: " + output.TotalCount);
foreach (var tenant in output.Items)
{
Console.WriteLine($"- Id={tenant.Id}, Name={tenant.Name}");
}
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
private async Task TestProductService()
{
Console.WriteLine();
Console.WriteLine("*** TestProductService ************************************");
try
{
var output = await _productAppService.GetListAsync();
Console.WriteLine("Total product count: " + output.Items.Count);
foreach (var product in output.Items)
{
Console.WriteLine($"- Code={product.Code}, Name={product.Name}, Price={product.Price}, StockCount={product.StockCount}");
}
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
private string GetServerUrl()
{
return _remoteServiceOptions.RemoteServices.Default.BaseUrl.EnsureEndsWith('/');
}
}
@@ -0,0 +1,26 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<OutputType>Exe</OutputType>
<RootNamespace>Company.Project.ConsoleClientDemo</RootNamespace>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Serilog.Extensions.Logging" Version="9.0.0" />
<PackageReference Include="Serilog.Sinks.File" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.0" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.Autofac" Version="9.0.0" />
<PackageReference Include="Volo.Abp.Http.Client.IdentityModel" Version="9.0.0" />
<PackageReference Include="Volo.Abp.Identity.HttpApi.Client" Version="9.0.0" />
<PackageReference Include="Volo.Abp.TenantManagement.HttpApi.Client" Version="9.0.0" />
<ProjectReference Include="..\..\modules\product\src\ProductManagement.HttpApi.Client\ProductManagement.HttpApi.Client.csproj" />
</ItemGroup>
<ItemGroup>
<None Remove="appsettings.json" />
<Content Include="appsettings.json">
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
</Project>
@@ -0,0 +1,31 @@
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Volo.Abp;
namespace Company.Project.ConsoleClientDemo;
public class ConsoleClientDemoHostedService : IHostedService
{
public async Task StartAsync(CancellationToken cancellationToken)
{
using (var application = AbpApplicationFactory.Create<ConsoleClientDemoModule>(options =>
{
options.Services.AddLogging(loggingBuilder =>
{
loggingBuilder.AddSerilog(dispose: true);
});
}))
{
application.Initialize();
var demo = application.ServiceProvider.GetRequiredService<ClientDemoService>();
await demo.RunAsync();
application.Shutdown();
}
}
public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
}
@@ -0,0 +1,20 @@
using ProductManagement;
using Volo.Abp.Autofac;
using Volo.Abp.Http.Client.IdentityModel;
using Volo.Abp.Identity;
using Volo.Abp.Modularity;
using Volo.Abp.TenantManagement;
namespace Company.Project.ConsoleClientDemo;
[DependsOn(
typeof(AbpAutofacModule),
typeof(AbpHttpClientIdentityModelModule),
typeof(AbpIdentityHttpApiClientModule),
typeof(ProductManagementHttpApiClientModule),
typeof(AbpTenantManagementHttpApiClientModule)
)]
public class ConsoleClientDemoModule : AbpModule
{
}
@@ -0,0 +1,31 @@
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Serilog;
using Serilog.Events;
namespace Company.Project.ConsoleClientDemo;
internal class Program
{
static async Task Main(string[] args)
{
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
.MinimumLevel.Override("Microsoft", LogEventLevel.Information)
.Enrich.FromLogContext()
.WriteTo.File("Logs/logs.txt")
.CreateLogger();
Log.Information("Starting ConsoleClientDemo...");
await CreateHostBuilder(args).RunConsoleAsync();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureServices((hostContext, services) =>
{
services.AddHostedService<ConsoleClientDemoHostedService>();
});
}
@@ -0,0 +1,17 @@
{
"RemoteServices": {
"Default": {
"BaseUrl": "https://localhost:44329/"
}
},
"IdentityClients": {
"Default": {
"GrantType": "client_credentials",
"ClientId": "console-client-demo",
"ClientSecret": "1q2w3e*",
"Authority": "https://localhost:44399",
"RequireHttpsMetadata": "true",
"Scope": "InternalGateway IdentityService ProductService"
}
}
}
@@ -0,0 +1,9 @@
using Volo.Abp.DependencyInjection;
using Volo.Abp.Ui.Branding;
namespace Company.Project.PublicWebSite;
public class BrandingProvider : DefaultBrandingProvider, ISingletonDependency
{
public override string AppName => "Public Web Site";
}
@@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<RootNamespace>Company.Project.PublicWebSite</RootNamespace>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.Autofac" Version="9.0.0" />
<PackageReference Include="Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic" Version="9.0.0" />
<PackageReference Include="Volo.Abp.Http.Client.IdentityModel.Web" Version="9.0.0" />
<PackageReference Include="Volo.Abp.Identity.Web" Version="9.0.0" />
<PackageReference Include="Serilog.AspNetCore" Version="9.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="9.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\modules\product\src\ProductManagement.HttpApi.Client\ProductManagement.HttpApi.Client.csproj" />
<ProjectReference Include="..\..\shared\Company.Project.Shared\Company.Project.Shared.csproj" />
</ItemGroup>
</Project>
@@ -0,0 +1,23 @@
FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS base
WORKDIR /app
EXPOSE 80
FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build
WORKDIR /src
COPY ["applications/Company.Project.PublicWebSite.Host/Company.Project.PublicWebSite.Host.csproj", "applications/Company.Project.PublicWebSite.Host/"]
COPY ["modules/product/src/ProductManagement.HttpApi.Client/ProductManagement.HttpApi.Client.csproj", "modules/product/src/ProductManagement.HttpApi.Client/"]
COPY ["modules/product/src/ProductManagement.Application.Contracts/ProductManagement.Application.Contracts.csproj", "modules/product/src/ProductManagement.Application.Contracts/"]
COPY ["modules/product/src/ProductManagement.Domain.Shared/ProductManagement.Domain.Shared.csproj", "modules/product/src/ProductManagement.Domain.Shared/"]
COPY ["shared/Company.Project.Shared/Company.Project.Shared.csproj", "shared/Company.Project.Shared/"]
RUN dotnet restore "applications/Company.Project.PublicWebSite.Host/Company.Project.PublicWebSite.Host.csproj" -nowarn:msb3202,msb3277,nu1503
COPY . .
WORKDIR "/src/applications/Company.Project.PublicWebSite.Host"
RUN dotnet build "Company.Project.PublicWebSite.Host.csproj" --no-restore -nowarn:msb3202,msb3277,nu1503 -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "Company.Project.PublicWebSite.Host.csproj" --no-restore -nowarn:msb3202,msb3277,nu1503 -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "Company.Project.PublicWebSite.Host.dll"]
@@ -0,0 +1,23 @@
FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS base
WORKDIR /app
EXPOSE 80
FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build
WORKDIR /src
COPY ["applications/Company.Project.PublicWebSite.Host/Company.Project.PublicWebSite.Host.csproj", "applications/Company.Project.PublicWebSite.Host/"]
COPY ["modules/product/src/ProductManagement.HttpApi.Client/ProductManagement.HttpApi.Client.csproj", "modules/product/src/ProductManagement.HttpApi.Client/"]
COPY ["modules/product/src/ProductManagement.Application.Contracts/ProductManagement.Application.Contracts.csproj", "modules/product/src/ProductManagement.Application.Contracts/"]
COPY ["modules/product/src/ProductManagement.Domain.Shared/ProductManagement.Domain.Shared.csproj", "modules/product/src/ProductManagement.Domain.Shared/"]
COPY ["shared/Company.Project.Shared/Company.Project.Shared.csproj", "shared/Company.Project.Shared/"]
RUN dotnet restore "applications/Company.Project.PublicWebSite.Host/Company.Project.PublicWebSite.Host.csproj" -nowarn:msb3202,msb3277,nu1503
COPY . .
WORKDIR "/src/applications/Company.Project.PublicWebSite.Host"
RUN dotnet build "Company.Project.PublicWebSite.Host.csproj" --no-restore -nowarn:msb3202,msb3277,nu1503 -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "Company.Project.PublicWebSite.Host.csproj" --no-restore -nowarn:msb3202,msb3277,nu1503 -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "Company.Project.PublicWebSite.Host.dll"]
@@ -0,0 +1,158 @@
@page
@using Volo.Abp.Users
@model Company.Project.PublicWebSite.Pages.IndexModel
@using Volo.Abp.AspNetCore.Mvc.UI.Theming
@inject IThemeManager ThemeManager
@inject ICurrentUser CurrentUser
@{
Layout = ThemeManager.CurrentTheme.GetApplicationLayout();
}
@section styles{
<style>
</style>
}
<div class="pb-5 px-5">
<div class="jumbotron text-center px-5 py-5">
<h1 class=" p-4">Public Web Site Application</h1>
<h4>Welcome to our web site...</h4>
<p>
This is a simple hero unit, a simple jumbotron-style component
for calling extra attention to featured content or information.
</p>
<p class="lead">
@if (CurrentUser.IsAuthenticated)
{
<a abp-button="Primary" asp-controller="Logout" asp-action="Index" asp-area="Account">Logout</a>
}
else
{
<form method="POST">
<input type="submit" asp-page-handler="Login" value="LOGIN" class="btn btn-primary px-4 btn-md" />
</form>
}
</p>
</div>
<div class="row">
<div class="col-md-4">
<div class="card">
<div class="card-header">
<h5 class="m-0">What is New?</h5>
</div>
<div class="card-body">
<div class="row">
<div class="col-4">
<img src="~/product-images/asus.jpg" width="64" />
</div>
<div class="col-8">
<div>
<h6>Asus Transformer Book T300CHI-FH011H</h6>
</div>
<strong class="product-price text-danger">1249</strong>
</div>
</div>
<hr />
<div class="row">
<div class="col-4">
<img src="~/product-images/playstation.jpg" width="64" />
</div>
<div class="col-8">
<div>
<h6>Lego Star Wars - 75059 Sandcrawler UCS</h6>
</div>
<strong class="product-price text-danger">$999</strong>
</div>
</div>
<hr />
<div class="row">
<div class="col-4">
<img src="~/product-images/nikon.jpg" width="64" />
</div>
<div class="col-8">
<div>
<h6>Nikon AF-S 50mm f/1.8 G Lens</h6>
</div>
<strong class="product-price text-danger">$1499</strong>
</div>
</div>
</div>
<div class="card-footer">
<a href="/Products" class="btn btn-block btn-md btn-primary">See All Products</a>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card">
<div class="card-header">
<h5 class="m-0">What is Hot?</h5>
</div>
<div class="card-body">
<div class="row">
<div class="col">
<div>
<h6>
Aliquam erat volutpat. Praesent nec dapibus neque. Proin hendrerit, magna in faucibus
</h6>
</div>
</div>
</div>
<hr />
<div class="row">
<div class="col">
<div>
<h6>Curabitur consectetur libero lacus, nec facilisis nulla facilisis non.</h6>
</div>
</div>
</div>
<hr />
<div class="row">
<div class="col">
<div>
<h6>Duis et felis nec ipsum auctor . </h6>
</div>
</div>
</div>
<hr />
<div class="row">
<div class="col">
<div>
<h6>Morbi eu dolor pellentesque, porttitor lorem vitae, pulvinar eros. </h6>
</div>
</div>
</div>
</div>
<div class="card-footer">
<a href="#" class="btn btn-block btn-md btn-primary">Go to the Articles</a>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card">
<div class="card-header">
<h5 class="m-0">Contact Us</h5>
</div>
<div class="card-body">
<label class="name lead">Volosoft</label> <br>
<span class="fa fa-fw fa-map-marker fa-fw text-muted" data-toggle="tooltip" title="" data-original-title="3903 W Alexander Rd"></span> <span class="text-muted">47322 W Alexander Rd</span> <br> <span class="fa fa-fw fa-phone fa-fw text-muted" data-toggle="tooltip" title="" data-original-title="(867) 322-1852"></span> <span class="text-muted small">(867) 322-5566</span> <br> <span class="fa fa-fw fa-envelope fa-fw text-muted" data-toggle="tooltip" title="" data-original-title="debbie.schmidt@example.com"></span> <span class="text-muted small text-truncate">info@volosoft.com</span>
<hr />
<p>
We are developing open source and commercial software development tools.
</p>
<p>
Praesent et posuere dui.
felis.
</p>
</div>
<div class="card-footer">
<a href="#" class="btn btn-block btn-md btn-primary">Contact Us</a>
</div>
</div>
</div>
</div>
</div>
@@ -0,0 +1,18 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Volo.Abp.AspNetCore.Mvc.UI.RazorPages;
namespace Company.Project.PublicWebSite.Pages;
public class IndexModel : AbpPageModel
{
public void OnGet()
{
}
public async Task OnPostLoginAsync()
{
await HttpContext.ChallengeAsync("oidc");
}
}
@@ -0,0 +1,55 @@
@page
@using ProductManagement
@using Volo.Abp.Settings
@model Company.Project.PublicWebSite.Pages.ProductsModel
@using Volo.Abp.AspNetCore.Mvc.UI.Theming
@inject IThemeManager ThemeManager
@inject ISettingProvider SettingProvider
@{
const int columnSize = 3;
Layout = ThemeManager.CurrentTheme.GetApplicationLayout();
}
@section styles{
<link href="~/Pages/Products.css" rel="stylesheet" />
}
<h3 class="pt-5 pb-4 text-center">Our Products</h3>
<div class="product-list">
@for (int i = 0; i < Math.Ceiling(Model.Products.Items.Count / (double)columnSize); i++)
{
<abp-row>
@for (int j = 0; j < columnSize; j++)
{
<abp-column size-lg="_4" size-md="_6" size-sm="_12">
@if ((i * columnSize) + j < Model.Products.Items.Count)
{
var product = Model.Products.Items[(i * columnSize) + j];
<div class="product-list-item">
@if (!product.ImageName.IsNullOrEmpty())
{
<img src="/product-images/@product.ImageName" />
}
else
{
<img src="/product-images/noimage.jpg" />
}
<div class="row mt-5">
<div class="col">
<div class="product-info-box">
<h6>@product.Name</h6>
<em class="d-block text-muted">@product.Code - Stock count: @product.StockCount</em>
</div>
</div>
<div class="col-auto text-right text-danger">
<strong class="product-price">$@product.Price</strong>
</div>
</div>
</div>
}
</abp-column>
}
</abp-row>
}
</div>
@* An example to show how to read settings from the client side / UI *@
<p class="text-muted mt-5"><i>Maximum allowed page size: @await SettingProvider.GetOrNullAsync(ProductManagementSettings.MaxPageSize)</i></p>
@@ -0,0 +1,23 @@
using System.Threading.Tasks;
using ProductManagement;
using Volo.Abp.Application.Dtos;
using Volo.Abp.AspNetCore.Mvc.UI.RazorPages;
namespace Company.Project.PublicWebSite.Pages;
public class ProductsModel : AbpPageModel
{
public ListResultDto<ProductDto> Products { get; set; }
private readonly IPublicProductAppService _productAppService;
public ProductsModel(IPublicProductAppService productAppService)
{
_productAppService = productAppService;
}
public async Task OnGetAsync()
{
Products = await _productAppService.GetListAsync();
}
}
@@ -0,0 +1,30 @@
body {
background-color: #f9f9f9;
}
.product-list-item {
background-color: #fff;
padding: 2em;
border: 1px solid #eee;
border-radius: 3px;
box-shadow: 0 0 10px rgba(0, 0, 0, .05);
margin-bottom: 2em;
transition: all .2s;
}
.product-list-item:hover {
box-shadow: 0 0 20px rgba(0, 0, 0, .1);
cursor: pointer;
}
.product-list-item img {
width: 100%;
}
.product-list-item .text-muted {
opacity: .8
}
.product-info-box {
min-height: 80px;
}
@@ -0,0 +1,4 @@
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@addTagHelper *, Volo.Abp.AspNetCore.Mvc.UI
@addTagHelper *, Volo.Abp.AspNetCore.Mvc.UI.Bootstrap
@addTagHelper *, Volo.Abp.AspNetCore.Mvc.UI.Bundling

Some files were not shown because too many files have changed in this diff Show More