升级并完成 Razor Pages + Blazor Web App 骨架。
- 项目现为 net10.0,使用本机 .NET SDK 10.0.400 / runtime 10.0.11。 - MySQL 驱动当前最新兼容版本是 Pomelo 9.0,因此 EF Core 保持在 9.0.11;迁移已可正常读取。 - Razor Pages 静态 SSR: - [公开首页](E:\\election system\\src\\ElectionSystem.Api\\Pages\\Index.cshtml) - [公开公告示例](E:\\election system\\src\\ElectionSystem.Api\\Pages\\Content\\Notice.cshtml) - Blazor Interactive Server: - [投票交互预览](E:\\election system\\src\\ElectionSystem.Api\\Components\\Pages\\BallotPreview.razor),仅演示交互,不提交或保存选票。 - 已加入 Blazor 所需的反伪造中间件,架构说明同步更新:[architecture.md](E:\\election system\\docs\\architecture.md)。
This commit is contained in:
1 parent
ab935480b0
commit
2eddb1217e
17 files changed
+251
-9
No files matched your search
@@ -4,6 +4,8 @@
|
||||
|
||||
`Identity` 仅维护本地用户与未来外部身份提供商的映射;`Organization` 维护组织树和成员范围;`Election`、`Voting`、`OfflineCounting`、`Cms`、`PublicBoard` 和 `Audit` 预留为独立业务模块。
|
||||
|
||||
公开内容采用 Razor Pages 的静态服务端渲染;需要即时校验和状态更新的区域采用 Blazor Web App 的 Interactive Server 渲染。交互组件不能承担投票防重、资格或计票规则,这些规则仍必须由服务端事务和数据库约束执行。
|
||||
|
||||
线上投票实现时,资格/已投状态与匿名选票将使用不同实体和数据库约束,禁止常规查询将选民反向关联到选票内容。本阶段没有创建选票表,因此不会产生该关联。
|
||||
|
||||
## MySQL 配置
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
"isRoot": true,
|
||||
"tools": {
|
||||
"dotnet-ef": {
|
||||
"version": "8.0.17",
|
||||
"version": "9.0.11",
|
||||
"commands": [
|
||||
"dotnet-ef"
|
||||
],
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
$psi = [System.Diagnostics.ProcessStartInfo]::new()
|
||||
$psi.FileName = 'dotnet'
|
||||
$psi.UseShellExecute = $false
|
||||
$psi.RedirectStandardOutput = $true
|
||||
$psi.RedirectStandardError = $true
|
||||
$psi.Environment['ASPNETCORE_ENVIRONMENT'] = 'Development'
|
||||
$psi.Environment['Security__EnableHttpsRedirection'] = 'false'
|
||||
|
||||
$argList = @(
|
||||
'run', '--no-build', '--configuration', 'Release', '--project', 'src/ElectionSystem.Api',
|
||||
'--', '--urls', 'http://127.0.0.1:5055'
|
||||
)
|
||||
foreach ($arg in $argList) {
|
||||
$null = $psi.ArgumentList.Add($arg)
|
||||
}
|
||||
|
||||
$process = [System.Diagnostics.Process]::Start($psi)
|
||||
try {
|
||||
$ready = $false
|
||||
for ($i = 0; $i -lt 20; $i++) {
|
||||
Start-Sleep -Milliseconds 500
|
||||
try {
|
||||
$response = Invoke-WebRequest -Uri 'http://127.0.0.1:5055/' -UseBasicParsing -TimeoutSec 2
|
||||
if ($response.StatusCode -eq 200) {
|
||||
$ready = $true
|
||||
break
|
||||
}
|
||||
} catch { }
|
||||
}
|
||||
|
||||
if (-not $ready) {
|
||||
throw "Application did not become ready. $($process.StandardError.ReadToEnd())"
|
||||
}
|
||||
|
||||
$homeResponse = Invoke-WebRequest -Uri 'http://127.0.0.1:5055/' -UseBasicParsing -TimeoutSec 5
|
||||
$notice = Invoke-WebRequest -Uri 'http://127.0.0.1:5055/content/notice' -UseBasicParsing -TimeoutSec 5
|
||||
$interactive = Invoke-WebRequest -Uri 'http://127.0.0.1:5055/ballot-preview' -UseBasicParsing -TimeoutSec 5
|
||||
|
||||
if ($homeResponse.Content -notmatch '公开内容以服务端渲染快速交付') { throw 'Home page content check failed.' }
|
||||
if ($notice.Content -notmatch '公开公告模板') { throw 'Notice page content check failed.' }
|
||||
if ($interactive.Content -notmatch '投票交互预览') { throw 'Interactive component content check failed.' }
|
||||
|
||||
"Runtime page checks passed: / ($($homeResponse.StatusCode)), /content/notice ($($notice.StatusCode)), /ballot-preview ($($interactive.StatusCode))"
|
||||
} catch {
|
||||
if (-not $process.HasExited) {
|
||||
$process.Kill($true)
|
||||
$process.WaitForExit()
|
||||
}
|
||||
$serverError = $process.StandardError.ReadToEnd()
|
||||
$serverOutput = $process.StandardOutput.ReadToEnd()
|
||||
throw "Runtime verification failed: $($_.Exception.Message)`n$serverError`n$serverOutput"
|
||||
} finally {
|
||||
if (-not $process.HasExited) {
|
||||
$process.Kill($true)
|
||||
$process.WaitForExit()
|
||||
}
|
||||
}
|
||||
Loaded 3 of 17 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user