本轮迁移已完成,生产运行链路现已切换为纯 ASP.NET Core 10。

主要完成:
补齐招生学校计划、投档审核、报到、扫码、补录等原生接口。
新增 SQLite/MySQL 空库初始化及默认审批流、号码规则。
删除 Node 兼容代理,未知 API 直接返回原生 404。
Docker、Compose、Gitea CI 全部切换到 Eis.Web.dll。
CKEditor 已固化到 Web 发布资源,不再依赖 node_modules。
新增纯 .NET 冒烟脚本:[smoke-dotnet-native.ps1 (line 1)](C:/Users/BI/Documents/EIS-dotnet/scripts/smoke-dotnet-native.ps1:1)。
迁移状态已更新:[MIGRATION.md (line 14)](C:/Users/BI/Documents/EIS-dotnet/MIGRATION.md:14)。
容器入口见 [Dockerfile (line 31)](C:/Users/BI/Documents/EIS-dotnet/Dockerfile:31)。
This commit is contained in:
2026-07-23 15:14:42 +08:00 Unverified
parent fea91a19af
commit e3c04dad8a
36 changed files with 1449 additions and 491 deletions
@@ -34,17 +34,16 @@ public sealed class AdminMigrationOptionsTests
}
[Fact]
public void RequiresSharedSessionsOutsideIsolatedTests()
public void AllowsStandaloneMemorySessionsAfterLegacyBackendRemoval()
{
WithEnvironment("true", null, null, () =>
{
var exception = Assert.Throws<InvalidOperationException>(() =>
AdminMigrationOptions.FromEnvironment(
configuredNativeReadsEnabled: false,
authenticationNativeEnabled: true,
sharesLegacySessions: false));
var options = AdminMigrationOptions.FromEnvironment(
configuredNativeReadsEnabled: false,
authenticationNativeEnabled: true,
sharesLegacySessions: false);
Assert.Contains("Redis", exception.Message);
Assert.True(options.NativeReadsEnabled);
});
}
@@ -0,0 +1,52 @@
using Eis.Infrastructure.Authentication;
using Eis.Infrastructure.Data;
using Microsoft.Data.Sqlite;
namespace Eis.Infrastructure.Tests.Data;
public sealed class DatabaseInitializerTests
{
[Fact]
public async Task InitializeAsync_CreatesFreshDatabaseAndIsIdempotent()
{
var root = Path.Combine(Path.GetTempPath(), $"eis-fresh-init-{Guid.NewGuid():N}");
var path = Path.Combine(root, "eis.sqlite");
Directory.CreateDirectory(root);
try
{
var options = DatabaseOptions.CreateSqliteForTests(path);
var factory = new RelationalConnectionFactory(options);
var passwords = new PasswordCompatibilityService();
var initializer = new DatabaseInitializer(factory, options, passwords);
await initializer.InitializeAsync(CancellationToken.None);
await initializer.InitializeAsync(CancellationToken.None);
await using var connection = new SqliteConnection($"Data Source={path}");
await connection.OpenAsync();
Assert.True(await ScalarAsync(connection,
"SELECT COUNT(*) FROM sqlite_master WHERE type = 'table' AND name NOT LIKE 'sqlite_%'") >= 32);
Assert.Equal(20, await ScalarAsync(connection,
"SELECT schema_version FROM schema_metadata WHERE id = 1"));
Assert.Equal(1, await ScalarAsync(connection,
"SELECT COUNT(*) FROM users WHERE id = 'usr_admin' AND role = 'admin' AND admin_level = 'super'"));
Assert.Equal(5, await ScalarAsync(connection,
"SELECT COUNT(*) FROM workflow_definitions WHERE active = 1"));
Assert.Equal(4, await ScalarAsync(connection,
"SELECT COUNT(*) FROM admission_number_rules WHERE active = 1"));
await connection.DisposeAsync();
SqliteConnection.ClearAllPools();
}
finally
{
if (Directory.Exists(root)) Directory.Delete(root, recursive: true);
}
}
private static async Task<long> ScalarAsync(SqliteConnection connection, string sql)
{
await using var command = connection.CreateCommand();
command.CommandText = sql;
return Convert.ToInt64(await command.ExecuteScalarAsync());
}
}
@@ -6,12 +6,16 @@ namespace Eis.Infrastructure.Tests.Migration;
public sealed class MigrationFeatureCatalogTests
{
[Fact]
public void ReportsCandidateAreaFromItsIndependentMigrationFlag()
public void ReportsCompletedNativeFeatureAreas()
{
var features = MigrationFeatureCatalog.Current(authenticationNative: true, candidateNative: true);
Assert.True(features.Single(item => item.Area == FeatureArea.Authentication).Native);
Assert.True(features.Single(item => item.Area == FeatureArea.Candidate).Native);
Assert.False(features.Single(item => item.Area == FeatureArea.Administration).Native);
Assert.True(features.Single(item => item.Area == FeatureArea.Administration).Native);
Assert.True(features.Single(item => item.Area == FeatureArea.Admission).Native);
Assert.True(features.Single(item => item.Area == FeatureArea.Documents).Native);
Assert.True(features.Single(item => item.Area == FeatureArea.Excel).Native);
Assert.True(features.Single(item => item.Area == FeatureArea.Caching).Native);
}
}