已完成管理后台第四批 ASP.NET Core 10 迁移:报名号规则与审批流程配置。

原生接口:
GET/POST /api/admin/number-rules
GET /api/admin/workflows
PUT /api/admin/workflows/{businessType}
实现包括:
报名号规则预览、创建和更新
自动停用旧规则
审批流程步骤重建
班级、校级、超级管理员层级校验
考点及批量申领流程禁止班级审批
批量申领最终步骤强制为超级管理员
配置更新与审计日志事务提交
This commit is contained in:
biss committed 2026-07-23 08:28:53 +08:00
1 parent f7c34247fd
commit 3665aa3aa9
13 files changed
+454 -18

No files matched your search

+2
View File
@@ -31,6 +31,8 @@ ADMIN_NATIVE_READS_ENABLED=false
ADMIN_NATIVE_ORGANIZATION_WRITES_ENABLED=false
# 批量报名号申领、审批与账号生成;必须同时启用管理端只读接口。
ADMIN_NATIVE_ACCOUNT_BATCHES_ENABLED=false
# 报名号规则与审批流程定义维护;必须同时启用管理端只读接口。
ADMIN_NATIVE_CONFIGURATION_ENABLED=false
# 仅在首次创建空数据库时使用。部署前务必修改初始密码。
INITIAL_ADMIN_USERNAME=admin
+4 -3
View File
@@ -12,7 +12,7 @@
- [x] 招生公示与 HMAC 文书验真公开接口
- [x] 登录、自主注册、Session 与 TOTP(兼容开关默认关闭)
- [x] 考生业务
- [ ] 管理后台、审批流和考务编排(管理端读取、组织维护及批量报名号审批已原生化)
- [ ] 管理后台、审批流和考务编排(管理端读取、组织维护、批量报名号审批及流程配置已原生化)
- [x] 考生志愿填报与招生录取查询
- [ ] Excel、文书和缓存
- [ ] 容器入口切换及 Node.js 后端移除
@@ -54,7 +54,7 @@ $env:AUTH_NATIVE_ENABLED = 'true'
$env:CANDIDATE_NATIVE_ENABLED = 'true'
```
管理后台第一批只读接口(管理上下文、仪表盘、学校、学校组织、管理员和考试列表)已经原生化,并保留超级、校级、班级管理员的权限与数据作用域。第二批覆盖学校、班级和管理员的创建与维护、管理员密码重置及自主注册开关;更新操作与审计日志在同一事务中提交,停用或重置管理员会同步失效其会话。第三批覆盖批量报名号申领的读取、提交和审批,终审会按照当前号码规则原子生成考生账号、初始密码和待补录资料。
管理后台第一批只读接口(管理上下文、仪表盘、学校、学校组织、管理员和考试列表)已经原生化,并保留超级、校级、班级管理员的权限与数据作用域。第二批覆盖学校、班级和管理员的创建与维护、管理员密码重置及自主注册开关;更新操作与审计日志在同一事务中提交,停用或重置管理员会同步失效其会话。第三批覆盖批量报名号申领的读取、提交和审批,终审会按照当前号码规则原子生成考生账号、初始密码和待补录资料。第四批覆盖报名号规则及审批流程定义的读取与维护,并保留流程层级和批量申领终审约束。
其余审批流和考务编排接口仍转发给 Node,因此两个管理端开关都要求原生认证和共享 Redis;组织维护开关还必须与只读开关一起启用:
@@ -63,9 +63,10 @@ $env:AUTH_NATIVE_ENABLED = 'true'
$env:ADMIN_NATIVE_READS_ENABLED = 'true'
$env:ADMIN_NATIVE_ORGANIZATION_WRITES_ENABLED = 'true'
$env:ADMIN_NATIVE_ACCOUNT_BATCHES_ENABLED = 'true'
$env:ADMIN_NATIVE_CONFIGURATION_ENABLED = 'true'
```
`GET /health/migration` 的 `administration.nativeReadsEnabled`、`administration.nativeOrganizationWritesEnabled`、`administration.nativeAccountBatchesEnabled` 和 `administration.nativeRoutes` 会报告这些端点是否已切换。
`GET /health/migration` 的 `administration.nativeReadsEnabled`、`administration.nativeOrganizationWritesEnabled`、`administration.nativeAccountBatchesEnabled`、`administration.nativeConfigurationEnabled` 和 `administration.nativeRoutes` 会报告这些端点是否已切换。
完整的宿主、静态资源、JSON 转发和 Session Cookie 冒烟测试:
+50
View File
@@ -425,6 +425,7 @@ try {
ADMIN_NATIVE_READS_ENABLED = 'true'
ADMIN_NATIVE_ORGANIZATION_WRITES_ENABLED = 'true'
ADMIN_NATIVE_ACCOUNT_BATCHES_ENABLED = 'true'
ADMIN_NATIVE_CONFIGURATION_ENABLED = 'true'
ADMIN_NATIVE_ALLOW_MEMORY = 'true'
LegacyNode__Enabled = 'true'
LegacyNode__BaseUrl = $legacyBaseUrl
@@ -739,6 +740,54 @@ try {
throw 'Native admins route did not preserve the class-admin boundary'
}
foreach ($configurationRoute in @('number-rules', 'workflows')) {
$legacyConfiguration = Invoke-WebRequest -Uri "$legacyBaseUrl/api/admin/$configurationRoute" -WebSession $session
$nativeConfiguration = Invoke-WebRequest -Uri "$nativeAuthBaseUrl/api/admin/$configurationRoute" -WebSession $nativeSession
if ($nativeConfiguration.Headers['X-EIS-Implementation'] -ne 'aspnet-core') {
throw "Native admin configuration route '$configurationRoute' did not use ASP.NET Core"
}
Assert-JsonEquivalent -Expected $legacyConfiguration.Content -Actual $nativeConfiguration.Content -Label "Admin configuration '$configurationRoute'"
}
foreach ($configurationRoute in @('number-rules', 'workflows')) {
$schoolConfigurationForbidden = Invoke-WebRequest -Uri "$nativeAuthBaseUrl/api/admin/$configurationRoute" -WebSession $nativeSchoolSession -SkipHttpErrorCheck
if ($schoolConfigurationForbidden.StatusCode -ne 403) {
throw "Admin configuration route '$configurationRoute' did not preserve the super-admin boundary"
}
}
$numberRuleState = Invoke-RestMethod -Uri "$nativeAuthBaseUrl/api/admin/number-rules" -WebSession $nativeSession
$activeNumberRule = $numberRuleState.activeRule
$numberRuleBody = @{
id = $activeNumberRule.id
name = '原生年度学校流水号'
separator = $activeNumberRule.separator
segments = @($activeNumberRule.segments | ForEach-Object {
@{ type = $_.type; value = $_.value; width = $_.width }
})
} | ConvertTo-Json -Depth 5 -Compress
$savedNumberRule = Invoke-WebRequest -Uri "$nativeAuthBaseUrl/api/admin/number-rules" -Method Post -ContentType 'application/json' -Body $numberRuleBody -WebSession $nativeSession
if ($savedNumberRule.Headers['X-EIS-Implementation'] -ne 'aspnet-core' -or ($savedNumberRule.Content | ConvertFrom-Json).rule.name -ne '原生年度学校流水号') {
throw 'Native number-rule update did not persist the requested definition'
}
$workflowState = Invoke-RestMethod -Uri "$nativeAuthBaseUrl/api/admin/workflows" -WebSession $nativeSession
$accountWorkflow = @($workflowState.workflows | Where-Object { $_.businessType -eq 'candidate_account_batch' })[0]
$invalidWorkflowBody = @{ name = '无效流程'; steps = @(@{ name = '学校终审'; adminLevel = 'school' }) } | ConvertTo-Json -Depth 4 -Compress
$invalidWorkflow = Invoke-WebRequest -Uri "$nativeAuthBaseUrl/api/admin/workflows/candidate_account_batch" -Method Put -ContentType 'application/json' -Body $invalidWorkflowBody -WebSession $nativeSession -SkipHttpErrorCheck
if ($invalidWorkflow.StatusCode -ne 400) {
throw 'Native workflow update allowed a non-super final account-batch step'
}
$workflowBody = @{
name = '原生批量报名号审批'
steps = @($accountWorkflow.steps | ForEach-Object {
@{ name = $_.name; adminLevel = $_.adminLevel }
})
} | ConvertTo-Json -Depth 5 -Compress
$savedWorkflow = Invoke-WebRequest -Uri "$nativeAuthBaseUrl/api/admin/workflows/candidate_account_batch" -Method Put -ContentType 'application/json' -Body $workflowBody -WebSession $nativeSession
if ($savedWorkflow.Headers['X-EIS-Implementation'] -ne 'aspnet-core' -or ($savedWorkflow.Content | ConvertFrom-Json).workflow.name -ne '原生批量报名号审批') {
throw 'Native workflow update did not persist the account-batch definition'
}
$legacySuperBatches = Invoke-WebRequest -Uri "$legacyBaseUrl/api/admin/candidate-account-batches" -WebSession $session
$nativeSuperBatches = Invoke-WebRequest -Uri "$nativeAuthBaseUrl/api/admin/candidate-account-batches" -WebSession $nativeSession
if ($nativeSuperBatches.Headers['X-EIS-Implementation'] -ne 'aspnet-core') {
@@ -989,6 +1038,7 @@ try {
NativeAdminReads = 'passed'
NativeAdminOrganizationWrites = 'passed'
NativeAdminAccountBatches = 'passed'
NativeAdminConfiguration = 'passed'
} | Format-List
}
finally {
Loaded 3 of 13 files, more files were not shown because too many files have changed in this diff. Show more