diff --git a/.gitea/workflows/publish-nuget.yml b/.gitea/workflows/publish-nuget.yml
new file mode 100644
index 0000000..197afb6
--- /dev/null
+++ b/.gitea/workflows/publish-nuget.yml
@@ -0,0 +1,26 @@
+name: Publish NuGet Package
+
+on:
+ push:
+ tags:
+ - 'v*'
+
+jobs:
+ publish:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v4
+
+ - name: Setup .NET
+ uses: actions/setup-dotnet@v4
+ with:
+ dotnet-version: '10.0'
+
+ - name: Publish NuGet packages
+ run: |
+ ./push-platform-nuget.sh all
+ env:
+ GITEA_HOST: gitea.shtao1.cn
+ GITEA_ORG: fengling
+ GITEA_API_TOKEN: ${{ secrets.GITEA_API_TOKEN }}
diff --git a/Fengling.Platform.Domain/Fengling.Platform.Domain.csproj b/Fengling.Platform.Domain/Fengling.Platform.Domain.csproj
index cbb48aa..5a90850 100644
--- a/Fengling.Platform.Domain/Fengling.Platform.Domain.csproj
+++ b/Fengling.Platform.Domain/Fengling.Platform.Domain.csproj
@@ -14,4 +14,8 @@
+
+
+
+
diff --git a/Fengling.Platform.Infrastructure/Extensions.cs b/Fengling.Platform.Infrastructure/Extensions.cs
new file mode 100644
index 0000000..16dcdc5
--- /dev/null
+++ b/Fengling.Platform.Infrastructure/Extensions.cs
@@ -0,0 +1,27 @@
+using Microsoft.Extensions.DependencyInjection;
+
+namespace Fengling.Platform.Infrastructure;
+
+public static class Extensions
+{
+ public static IServiceCollection AddPlatformCore(this IServiceCollection services,
+ Action? optionsAction = null,
+ Action? serviceAction = null
+ )
+ where TContext : PlatformDbContext
+ {
+ if (optionsAction != null)
+ {
+ var isRegistry = services.Any(x => x.ImplementationType == typeof(TContext));
+ if (!isRegistry)
+ {
+ services.AddDbContext(optionsAction);
+ }
+ }
+ services.AddScoped>();
+ services.AddScoped();
+ serviceAction?.Invoke(services);
+
+ return services;
+ }
+}
\ No newline at end of file
diff --git a/Fengling.Platform.Infrastructure/Fengling.Platform.Infrastructure.csproj b/Fengling.Platform.Infrastructure/Fengling.Platform.Infrastructure.csproj
index 5aef5b6..08493d9 100644
--- a/Fengling.Platform.Infrastructure/Fengling.Platform.Infrastructure.csproj
+++ b/Fengling.Platform.Infrastructure/Fengling.Platform.Infrastructure.csproj
@@ -13,7 +13,6 @@
-
diff --git a/Fengling.Platform.Infrastructure/PlatformDbContext.cs b/Fengling.Platform.Infrastructure/PlatformDbContext.cs
index 91f702d..4ee1efa 100644
--- a/Fengling.Platform.Infrastructure/PlatformDbContext.cs
+++ b/Fengling.Platform.Infrastructure/PlatformDbContext.cs
@@ -8,12 +8,12 @@ using Microsoft.EntityFrameworkCore;
namespace Fengling.Platform.Infrastructure;
-public partial class PlatformDbContext(DbContextOptions options)
+public class PlatformDbContext(DbContextOptions options)
: IdentityDbContext(options)
{
public DbSet Tenants => Set();
public DbSet AccessLogs => Set();
- public DbSet AuditLogs => Set();
+ public DbSet AuditLogs => Set();
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
diff --git a/Fengling.Platform.Infrastructure/TenantManager.cs b/Fengling.Platform.Infrastructure/TenantManager.cs
index f338b1e..1251f61 100644
--- a/Fengling.Platform.Infrastructure/TenantManager.cs
+++ b/Fengling.Platform.Infrastructure/TenantManager.cs
@@ -1,8 +1,9 @@
-namespace Fengling.Platform.Infrastructure;
-
using Fengling.Platform.Domain.AggregatesModel.TenantAggregate;
using Microsoft.AspNetCore.Identity;
+namespace Fengling.Platform.Infrastructure;
+
+
public interface ITenantManager
{
Task FindByIdAsync(long? tenantId, CancellationToken cancellationToken = default);
diff --git a/Fengling.Platform.Infrastructure/TenantStore.cs b/Fengling.Platform.Infrastructure/TenantStore.cs
index c358929..b464278 100644
--- a/Fengling.Platform.Infrastructure/TenantStore.cs
+++ b/Fengling.Platform.Infrastructure/TenantStore.cs
@@ -4,12 +4,13 @@ using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Fengling.Platform.Domain.AggregatesModel.TenantAggregate;
-public class TenantStore : ITenantStore
+public class TenantStore : ITenantStore
+where TContext : PlatformDbContext
{
- private readonly PlatformDbContext _context;
+ private readonly TContext _context;
private readonly DbSet _tenants;
- public TenantStore(PlatformDbContext context)
+ public TenantStore(TContext context)
{
_context = context;
_tenants = context.Tenants;
diff --git a/NuGet.Config b/NuGet.Config
new file mode 100644
index 0000000..62a0353
--- /dev/null
+++ b/NuGet.Config
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/push-platform-nuget.sh b/push-platform-nuget.sh
new file mode 100755
index 0000000..15737e3
--- /dev/null
+++ b/push-platform-nuget.sh
@@ -0,0 +1,311 @@
+#!/bin/bash
+
+# =============================================================================
+# Fengling.Platform NuGet 包上传脚本
+# 用于上传 Fengling.Platform.Domain 和 Fengling.Platform.Infrastructure 到 Gitea NuGet
+# 支持 CI/CD 集成,自动从 git tag 获取版本
+# =============================================================================
+
+# =========================== 环境变量配置 ===========================
+# CI/CD 时通过环境变量传入,本地可修改默认值
+
+## TODO: 请在这里填入你的 Gitea API Token,或通过环境变量 GITEA_API_TOKEN 传入
+#export GITEA_HOST="${GITEA_HOST:-gitea.shtao1.cn}" # Gitea 域名
+#export GITEA_ORG="${GITEA_ORG:-fengling}" # 组织名称
+#export GITEA_API_TOKEN="${GITEA_API_TOKEN:-}" # Gitea API Token (必填)
+#export GITEA_USE_HTTPS="${GITEA_USE_HTTPS:-true}" # 是否使用 HTTPS (外网用 true)
+# CI/CD 时通过环境变量传入,本地可修改默认值
+
+export GITEA_HOST="${GITEA_HOST:-gitea.shtao1.cn}" # Gitea 地址 (内网)
+export GITEA_ORG="${GITEA_ORG:-fengling}" # 组织名称
+export GITEA_API_TOKEN="${GITEA_API_TOKEN:-}" # Gitea API Token (必填)
+export GITEA_USE_HTTPS="${GITEA_USE_HTTPS:-true}" # 是否使用 HTTPS (内网用 false)
+
+# =========================== 内部变量 ===========================
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+NUGET_SOURCE_NAME="gitea"
+
+# 根据是否使用 HTTPS 构建 URL
+if [ "$GITEA_USE_HTTPS" = "true" ]; then
+ NUGET_SOURCE_URL="https://${GITEA_HOST}/api/packages/${GITEA_ORG}/nuget/index.json"
+else
+ NUGET_SOURCE_URL="http://${GITEA_HOST}/api/packages/${GITEA_ORG}/nuget"
+fi
+
+# 输出目录
+NUPKG_DIR="${SCRIPT_DIR}/nupkg"
+if [ "$GITEA_USE_HTTPS" = "true" ]; then
+ NUGET_SOURCE_URL="https://${GITEA_HOST}/api/packages/${GITEA_ORG}/nuget/index.json"
+else
+ NUPKG_DIR="${SCRIPT_DIR}/nupkg"
+NUGET_SOURCE_URL="http://${GITEA_HOST}/api/packages/${GITEA_ORG}/nuget"
+fi
+
+# NuGet 配置文件路径
+NUGET_CONFIG_DIR="${SCRIPT_DIR}/.nuget"
+NUGET_CONFIG_FILE="${NUGET_CONFIG_DIR}/NuGet.Config"
+
+# =========================== 版本获取 ===========================
+get_version_from_git() {
+ # 优先使用环境变量中的版本
+ if [ -n "$PACKAGE_VERSION" ]; then
+ echo "$PACKAGE_VERSION"
+ return
+ fi
+
+ # 尝试从 git tag 获取版本
+ local git_dir="${SCRIPT_DIR}/.git"
+ if [ -d "$git_dir" ]; then
+ local latest_tag=$(git -C "$SCRIPT_DIR" describe --tags --abbrev=0 2>/dev/null)
+ if [ -n "$latest_tag" ]; then
+ # 去掉 v 前缀 (如 v1.0.0 -> 1.0.0)
+ echo "${latest_tag#v}"
+ return
+ fi
+ fi
+
+ # 默认版本
+ echo "1.0.0"
+}
+
+# =========================== 颜色输出 ===========================
+RED='\033[0;31m'
+GREEN='\033[0;32m'
+YELLOW='\033[1;33m'
+BLUE='\033[0;34m'
+NC='\033[0m'
+
+log_info() {
+ echo -e "${GREEN}[INFO]${NC} $1"
+}
+
+log_warn() {
+ echo -e "${YELLOW}[WARN]${NC} $1"
+}
+
+log_error() {
+ echo -e "${RED}[ERROR]${NC} $1"
+}
+
+log_debug() {
+ if [ "$DEBUG" = "true" ]; then
+ echo -e "${BLUE}[DEBUG]${NC} $1"
+ fi
+}
+
+# =========================== 检查配置 ===========================
+check_config() {
+ if [ -z "$GITEA_API_TOKEN" ]; then
+ log_error "请设置环境变量 GITEA_API_TOKEN"
+ echo ""
+ echo "设置方式:"
+ echo " export GITEA_API_TOKEN=你的GiteaToken"
+ echo ""
+ echo "或运行时传入:"
+ echo " GITEA_API_TOKEN=你的Token $0 all"
+ echo ""
+ echo "CI/CD 示例 (GitHub Actions):"
+ echo " env:"
+ echo " GITEA_API_TOKEN: \${{ secrets.GITEA_API_TOKEN }}"
+ echo " GITEA_ORG: fengling"
+ exit 1
+ fi
+
+ log_info "Gitea: ${GITEA_HOST}, Org: ${GITEA_ORG}, HTTPS: ${GITEA_USE_HTTPS}"
+}
+
+# =========================== 创建 NuGet 配置 ===========================
+create_nuget_config() {
+ # 创建 .nuget 目录
+ mkdir -p "${NUGET_CONFIG_DIR}"
+
+ # 创建 NuGet.Config,启用 HTTP 支持
+ cat > "${NUGET_CONFIG_FILE}" << 'EOF'
+
+
+
+
+
+
+
+
+
+EOF
+
+ log_info "已创建 NuGet 配置文件: ${NUGET_CONFIG_FILE}"
+}
+
+# =========================== 还原并构建包 ===========================
+restore_and_build() {
+ # 获取版本
+ PACKAGE_VERSION=$(get_version_from_git)
+ log_info "包版本: ${PACKAGE_VERSION}"
+
+ log_info "开始构建 NuGet 包..."
+
+ local projects=(
+ "${SCRIPT_DIR}/Fengling.Platform.Domain/Fengling.Platform.Domain.csproj"
+ "${SCRIPT_DIR}/Fengling.Platform.Infrastructure/Fengling.Platform.Infrastructure.csproj"
+ )
+
+ for project in "${projects[@]}"; do
+ if [ ! -f "$project" ]; then
+ log_error "项目文件不存在: $project"
+ exit 1
+ fi
+
+ local project_name=$(basename $(dirname $project))
+ log_info "正在构建: ${project_name}"
+
+ # 还原依赖
+ dotnet restore "$project" --configfile "${NUGET_CONFIG_FILE}"
+ if [ $? -ne 0 ]; then
+ log_error "还原失败: $project"
+ exit 1
+ fi
+
+ # 构建并打包
+ dotnet build "$project" -c Release --no-restore
+ if [ $? -ne 0 ]; then
+ log_error "构建失败: $project"
+ exit 1
+ fi
+
+ dotnet pack "$project" -c Release --no-build -p:PackageVersion=${PACKAGE_VERSION} -o "${NUPKG_DIR}"
+ if [ $? -ne 0 ]; then
+ log_error "打包失败: $project"
+ exit 1
+ fi
+ done
+
+ log_info "NuGet 包构建完成!"
+}
+
+# =========================== 配置 NuGet 源 ===========================
+configure_nuget_source() {
+ log_info "配置 NuGet 源: ${NUGET_SOURCE_URL}"
+
+ # 使用 configfile 参数添加源
+ dotnet nuget add source \
+ --name "${NUGET_SOURCE_NAME}" \
+ --username "movingsam" \
+ --password "${GITEA_API_TOKEN}" \
+ --store-password-in-clear-text \
+ "${NUGET_SOURCE_URL}" \
+ --configfile "${NUGET_CONFIG_FILE}"
+
+ if [ $? -eq 0 ]; then
+ log_info "NuGet 源配置成功!"
+ else
+ log_error "NuGet 源配置失败"
+ exit 1
+ fi
+}
+
+# =========================== 上传包 ===========================
+push_packages() {
+ log_info "开始上传 NuGet 包..."
+
+ if [ ! -d "$NUPKG_DIR" ]; then
+ log_error "nupkg 目录不存在,请先运行构建"
+ exit 1
+ fi
+
+ # 上传所有 nupkg 文件
+ for nupkg in "${NUPKG_DIR}"/*.nupkg; do
+ [ -f "$nupkg" ] || continue
+
+ local filename=$(basename $nupkg)
+ log_info "上传: $filename"
+
+ dotnet nuget push "$nupkg" \
+ --source "${NUGET_SOURCE_URL}" \
+ --api-key "${GITEA_API_TOKEN}" \
+ --configfile "${NUGET_CONFIG_FILE}" \
+ --skip-duplicate
+
+ if [ $? -eq 0 ]; then
+ log_info "上传成功: $filename"
+ else
+ log_warn "上传失败或包已存在: $filename"
+ fi
+ done
+}
+
+# =========================== 显示帮助 ===========================
+show_help() {
+ echo "用法: $0 [命令]"
+ echo ""
+ echo "命令:"
+ echo " all 执行全部步骤 (构建 -> 配置源 -> 上传)"
+ echo " build 仅构建 NuGet 包"
+ echo " config 仅配置 NuGet 源"
+ echo " push 仅上传包 (需要先构建)"
+ echo " clean 清理构建产物"
+ echo " help 显示帮助"
+ echo ""
+ echo "环境变量:"
+ echo " GITEA_HOST Gitea 地址 (默认: 192.168.100.120:8418)"
+ echo " GITEA_ORG 组织名称 (默认: fengling)"
+ echo " GITEA_API_TOKEN Gitea API Token (必填)"
+ echo " GITEA_USE_HTTPS 是否使用 HTTPS (默认: false, 内网用 false)"
+ echo " PACKAGE_VERSION 包版本 (自动从 git tag 获取)"
+ echo ""
+ echo "示例:"
+ echo " # 方式1: 设置环境变量"
+ echo " export GITEA_API_TOKEN=your_token"
+ echo " $0 all"
+ echo ""
+ echo " # 方式2: 运行时传入环境变量"
+ echo " GITEA_API_TOKEN=your_token $0 all"
+ echo ""
+ echo " # 使用 HTTPS (外网)"
+ echo " GITEA_API_TOKEN=your_token GITEA_USE_HTTPS=true GITEA_HOST=gitea.shtao1.cn $0 all"
+}
+
+# =========================== 清理 ===========================
+clean() {
+ log_info "清理构建产物..."
+ rm -rf "${NUPKG_DIR}"
+ rm -rf "${NUGET_CONFIG_DIR}"
+ log_info "清理完成"
+}
+
+# =========================== 主程序 ===========================
+main() {
+ local command="${1:-all}"
+
+ check_config
+ create_nuget_config
+
+ case "$command" in
+ all)
+ restore_and_build
+ configure_nuget_source
+ push_packages
+ log_info "全部完成!"
+ ;;
+ build)
+ restore_and_build
+ ;;
+ config)
+ configure_nuget_source
+ ;;
+ push)
+ push_packages
+ ;;
+ clean)
+ clean
+ ;;
+ help|--help|-h)
+ show_help
+ ;;
+ *)
+ log_error "未知命令: $command"
+ show_help
+ exit 1
+ ;;
+ esac
+}
+
+main "$@"