add

biss committed 2026-07-24 12:00:48 +08:00
1 parent 65135c72bf
commit ee5dfa6d61
11 files changed
+2730 -1

No files matched your search

+334
@@ -0,0 +1,334 @@
# 管理操作指南
本页面向超级管理员、校级管理员、班级管理员和招生学校账号。系统会同时在前端和服务端执行权限检查,管理员不能通过手工拼接 URL 越过数据范围。
## 1. 角色与权限边界
| 功能域 | 超级管理员 | 校级管理员 | 班级管理员 | 招生学校 |
| --- | --- | --- | --- | --- |
| 全局运行总览 | 全部 | 本校 | 本班 | 本校招生业务 |
| 学校与班级 | 管理全部学校 | 管理本校组织 | 只读本班相关信息 | 不适用 |
| 管理员账号 | 管理各级管理员 | 按业务入口管理本校班级相关事项 | 不适用 | 不适用 |
| 批量申领报名号 | 审批、监督 | 发起并接收结果 | 不直接发起 | 不适用 |
| 考生资料 | 全部并可监督 | 本校 | 本班 | 投档后必要资料 |
| 报名与缴费 | 全部 | 本校 | 本班 | 不适用 |
| 考试与科目 | 创建、修改、归档 | 查看相关考试 | 查看相关考试 | 查看招生关联考试 |
| 成绩录入与发布 | 可操作 | 范围内查看、导出、参与流程 | 范围内查看、参与复议 | 仅投档材料中的必要成绩 |
| 考点考场 | 全局维护、审批 | 本校档案变更申请 | 查看相关安排 | 不适用 |
| 审批流 | 设计、监督、退回 | 处理本校步骤、转交 | 处理本班步骤、转交 | 招生业务指定动作 |
| 招生录取 | 全局设置与投档签发 | 确认本校指标资格 | 不可代确认指标资格 | 计划、投档、报到、模板 |
| 通知公告 | 创建、发布、撤回 | 查看 | 查看 | 查看相关公示 |
同一级可以配置多个管理员。待办会按当前待办数和历史分配量在同一业务范围内自动均分,当前处理人还可把流程转交给同范围同级管理员。
## 2. 超级管理员首次配置
建议按以下顺序完成初始化:
1. 登录后立即修改初始密码。
2. 在“账户安全”绑定 TOTP 并离线保存恢复码。
3. 在“学校管理”建立学校,填写稳定且唯一的学校代码。
4. 根据学校职责标记生源校、招生校,或同时具备两类职责。
5. 建立校级、班级管理员,明确学校和班级数据范围。
6. 在“报名号规则”配置年份、学校代码、性别、固定值和流水号等号码段。
7. 在“流程设计”配置各业务的审批步骤。
8. 在“考试与科目”建立考试和科目。
9. 需要自主注册时才临时开启,并在结束后关闭。
生产系统完成初始化后,不要继续使用模板初始密码。
## 3. 组织、账号和报名号
### 学校与班级
学校代码会参与报名号、录取通知书编号和考务数据识别,应在投入使用前确定。系统保存学校和班级的数据范围关联,不能把权限控制仅理解为页面筛选。
### 管理员账号
- 超级管理员可建立多个同级账号,避免共享一个管理员账户。
- 校级和班级管理员必须绑定正确的学校、班级范围。
- 停用账号后,其有效登录状态会失效。
- 密码重置产生的是新凭据,管理员不能读取旧密码。
- 交接人员时,应创建或启用个人账号,不建议多人长期共用。
### 报名号规则
规则可组合:
- 年份;
- 学校代码;
- 性别;
- 固定文本;
- 流水号。
超级管理员只维护规则,不直接替代学校的批量申领流程。报名号在考生账户创建时原子生成一次,后续参加不同考试仍复用同一号码。
### 批量建号
校级管理员:
1. 选择一个或多个班级;
2. 为每班填写申请人数;
3. 提交批次审批;
4. 等待最终批准;
5. 下载按班级返回的报名号和初始密码 Excel;
6. 通过安全渠道分别下发。
即使只申请一名考生,也按一人批次进入审批。最终批准时系统一次性生成报名号、随机初始密码和待补录账户,避免部分成功造成数量不一致。
## 4. 审批流程
可配置审批的主要业务包括:
- 考生资料修改;
- 考试报名;
- 成绩复议;
- 批量报名号申领;
- 考点和考场档案变更。
处理原则:
1. 先核对完整业务上下文和申请快照。
2. 通过时确认下游步骤和最终生效条件。
3. 退回时填写可执行的修改意见。
4. 需要更换处理人时使用“转交”,不要让其他管理员共享账号操作。
5. 超级管理员监督处理时保留原因,避免无说明改写流程历史。
班级和校级步骤会自动限制到考生所属班级和学校。审批实例、责任人、转交和监督动作均留痕。
## 5. 考生资料、报名与缴费
### 考生资料
各级管理员在自身范围内查看考生资料、审核状态和流程历史。Excel 导入会逐行校验并返回具体行号;批量修改资料仍需经过配置的审批流程,不因使用 Excel 而绕过审批。
### 报名审核
核对:
- 考试和科目;
- 考生资料状态;
- 报名时间;
- 费用;
- 当前审批步骤;
- 历史处理意见。
### 缴费管理
报名终审与缴费确认彼此独立。超级、校级和班级管理员均可在各自数据范围内维护缴费状态,确认时系统记录办理人和时间。
缴费台账应通过页面筛选后导出。系统不接入支付 SDK,因此“已缴费”表示管理员已登记确认,不代表平台完成了在线支付交易。
## 6. 考试与科目
超级管理员可配置:
- 考试代码、名称和状态;
- 报名、考试、准考证、成绩等时间;
- 科目日期、开始结束时间;
- 科目费用和满分;
- 固定单科线、排名前百分比或不设单科线;
- 固定总分线、总排名前百分比、单科均达线或不判定整场合格。
默认成绩等级按同场同科排名百分位计算:
| 区间 | 等级 |
| --- | --- |
| 前 10% | A+ |
| 前 25% | A |
| 前 50% | B+ |
| 前 70% | B |
| 前 90% | C |
| 其余 | D |
同分共享名次。
### 考试归档
归档是整场考试的不可逆业务动作。归档后锁定:
- 手工成绩录入;
- 成绩 Excel 导入;
- 复议改分;
- 考试配置修改。
归档前应确认报名、编排、成绩、复议、发布和必要导出均已完成。历史报名、准考证与成绩在页面中默认折叠展示。
## 7. 考点、考场与准考证编排
考点档案包括:
- 代码、名称和状态;
- 负责人、应急电话;
- 开放时间、交通说明;
- 楼栋、楼层;
- 考场容量、类型;
- 座位编排说明。
考点新增以及考点、考场修改会先形成申请快照,审批通过后再整体更新正式档案。
### 批量编排
超级管理员选择整场考试后:
1. 选择混编范围:班内、校内、县区内、市内或省内。
2. 选择准考证号码规则。
3. 设置是否保留备用考场和稳定随机种子。
4. 先执行预检。
5. 处理所有阻断问题。
6. 再确认正式编排。
预检检查:
- 科目时间冲突;
- 考点与考场容量;
- 档案完整性;
- 准考证号码唯一性;
- 多科考生的考点一致性。
预置号码规则包括:
- 县区编号 + 考场号 + 座位号;
- 县区号 + 考场号 + 流水号;
- 考点学校代码 + 考场号 + 座位号;
- 考生学校代码 + 考场号 + 座位号。
预检只用于验证,不应写入正式编排结果;正式应用后再开放准考证下载。
## 8. 成绩管理
成绩管理中心按考试切换,提供:
- 录入和发布进度;
- 成绩出齐人数;
- 整场合格率;
- 缺失科次;
- 复议数量;
- 可筛选成绩台账;
- Excel 导入导出;
- 缓存刷新。
### Excel 导入
成绩导入采用两阶段流程:
1. 上传并逐行校验;
2. 页面暂存预览;
3. 管理员核对错误、人数和变更内容;
4. 明确确认;
5. 在事务内原子批量写库。
预览不会修改数据库。不要把“解析成功”误认为“导入完成”。
### 成绩复议
终审时查看考试、科目、原分、当前分、当前排名和达线规则。批准改分后系统更新成绩并重新计算受影响结论。考试归档后不能批准会造成改分的操作。
### 发布与缓存
成绩录入不等于发布。发布、批量导入、归档和复议改分会自动使相关结果缓存失效;超级管理员也可在成绩管理中心手动刷新全部成绩缓存。
## 9. 通知与系统公示
超级管理员可:
- 新建草稿;
- 编辑内容;
- 发布;
- 撤回;
- 设置首页置顶;
- 管理系统生成的招生公示可见性。
系统公示和人工公告来源不同。撤回、隐藏或重新公开后,应以公开首页实际显示结果为准。
招生流程会按阶段生成:
- 招生计划公示;
- 指标资格公示;
- 录取与补录公示;
- 报到情况公示;
- 脱敏录取名单;
- 按学校、类别统计的录取分数线。
## 10. 招生录取全流程
### 录取设置
超级管理员按考试配置:
- 是否启用志愿;
- 填报起止时间;
- 普通志愿数量;
- 最多提交次数;
- 当前阶段。
### 招生账户和计划
超级管理员为招生学校建立专用账号。招生学校以结构化表单提交普通生、特长生和生源校指标计划;超级管理员审核后生效,也可代为上传并直接审核。
### 指标资格
生源校校级管理员按考试逐人确认本校考生指标资格。必须完成本校全部资料已完善在册考生的确认后,系统才公开资格结果。超级管理员和班级管理员不能代替校级管理员完成此确认。
### 志愿和投档
填报结束后,超级管理员执行投档。系统按总成绩降序逐人检索志愿,区分指标与普通计划池。
投档材料只发送给对应招生学校,包含必要个人资料和当次成绩,不包含其他志愿。
### 招生学校审核
招生学校可:
- 接收投档;
- 填写特殊理由申请退档;
- 查看本校计划录取率;
- 维护录取通知书标题、正文、落款和配色。
退档由超级管理员统一审批。
### 正式录取
超级管理员签发正式录取后,系统按“招生学校代码 + 考试代码 + 校内独立流水号”生成稳定通知书编号,并开启招生学校报到工作台。
### 报到与补录
招生学校可以:
- 逐人暂存 `Y`、`N`、`P` 报到状态;
- 导出带下拉校验的 Excel;
- 修改后导入;
- 扫描通知书二维码预检;
- 确认扫描后登记;
- 提交完整报到情况;
- 选择不补录或申请补录。
扫描预览只做核验,不写入报到状态;正式扫描确认才产生业务变更。学校提交前的草稿不会进入超级管理员审批。
超级管理员审批各学校决定后,按缺额进入下一轮补录或结束录取。每轮结果都应独立保留和发布,不能只保留最终总状态。
## 11. Excel 操作建议
系统为班级、管理员、报名号、考生、缴费、考点考场、成绩、志愿、录取和报到等业务提供模板、导入与导出。
操作前:
1. 从当前页面下载最新模板,不复用旧版本模板。
2. 保留隐藏标识列和表头。
3. 不随意修改单元格数据验证。
4. 使用页面提供的当前范围导出作为修改基础。
5. 导入后逐条检查错误行和预览摘要。
6. 只有确认目标范围正确后才提交写入。
只读角色可能仍保留导出能力,但不能通过修改请求完成写操作。
## 12. 审计与操作规范
- 每名管理员使用自己的账号。
- 重要审批意见说明事实和原因。
- 批量操作前先筛选并核对选中范围。
- 不通过数据库直接修改业务状态。
- 数据导出按敏感文件管理,使用后及时清理。
- 归档、正式录取、批量导入、重建数据库等高影响操作执行前保留备份或导出。
- 发现登录过期时重新登录,不要求使用者靠刷新页面恢复会话。
+297
@@ -0,0 +1,297 @@
# 系统架构
衡准考试信息管理系统采用 ASP.NET Core 10 模块化单体架构。生产环境部署一个 `Eis.Web` 进程,前端静态资源和 API 由同一宿主提供;数据库维护工具 `Eis.Tools` 独立发布。
## 1. 总体结构
```text
浏览器
├─ Vue 3 单页应用
├─ 公开页面 / 考生中心 / 管理后台 / 招生学校端
└─ PDF 文书生成模块
│ HTTPS / JSON / Cookie
▼
Eis.Web(ASP.NET Core)
├─ 静态资源与 SPA History 回退
├─ Minimal API 端点
├─ 身份识别、角色与数据范围校验
└─ 健康检查
│
▼
Eis.Application
└─ 应用服务契约
│
▼
Eis.Infrastructure
├─ 业务服务与仓储
├─ SQLite / MySQL
├─ Redis / 本机缓存
├─ Redis / 内存认证状态
├─ ClosedXML
└─ 安全与防伪服务
```
## 2. 项目依赖
### Eis.Domain
领域层保存稳定业务概念和值,不包含 Web、数据库或前端细节。
### Eis.Application
应用层以接口描述用例,包括:
- 认证;
- 考生服务;
- 公开查询;
- 管理中心;
- 组织、账号、配置;
- 考试、编排、成绩;
- 审批、招生和录取。
端点依赖这些契约,而不是直接依赖数据库实现。
### Eis.Infrastructure
基础设施层实现:
- 关系数据库连接和初始化;
- 管理员、考生、招生业务仓储;
- 缓存和会话状态;
- 密码、TOTP 和文书防伪;
- Excel 读写;
- 准考证、成绩单和录取通知书数据;
- 审批流、统计和投档业务。
部分大型业务通过同名 partial 类拆分文件,例如考生服务和招生服务,以保持单个文件可维护。
### Eis.Web
Web 层负责:
- 加载 `.env` 和运行环境;
- 组合依赖注入;
- 初始化数据库;
- HTTP 输入输出;
- 获取当前身份;
- 注册安全响应头;
- 健康检查;
- 静态资源;
- SPA 路由回退。
复杂业务规则应留在 Infrastructure 的应用实现中,而不是放在端点委托。
### Eis.Tools
数据库工具复用 Infrastructure 的数据库选项、初始化和维护服务,提供:
- `database init`
- `database reset`
- `database seed`
工具可以和 Web 一起发布,但执行时不要求 Web 正在运行。SQLite 数据维护时反而应先停止 Web,避免并发写入。
## 3. HTTP 与前端
### API 域
| 前缀 | 面向对象 |
| --- | --- |
| `/api/public` | 未登录访客 |
| `/api/auth` | 注册、登录、密码、TOTP、退出 |
| `/api/candidate` | 当前考生 |
| `/api/admin` | 超级、校级、班级管理员 |
| `/api/admission` | 当前招生学校 |
未注册的 `/api/*` 由统一兜底端点返回 JSON 404,不会回退成 HTML,也不会转发到旧 Node.js 服务。
### SPA 路由
前端使用 Vue Router History 模式:
- `/candidate/...`
- `/admin/...`
- `/admission/...`
开发时由 Vite 提供页面并代理 API;生产时 ASP.NET Core 提供 `wwwroot/vue-app`,对非 API 语义 URL 返回前端入口。
### 会话初始化
前端进入路由前加载当前会话:
1. 未登录访问受保护页面:跳转登录页并携带返回地址。
2. 已登录但角色不匹配:返回该角色首页。
3. 考生必须改初始密码或资料未完成:跳转首次登录流程。
4. 会话失效:重新登录,而不是假定刷新可恢复。
## 4. 认证与授权
### 凭据
- 密码使用 PBKDF2 加盐哈希。
- TOTP 密钥使用 `TOTP_ENCRYPTION_KEY` 派生的材料,以 AES-256-GCM 加密保存。
- 恢复码只保存带服务端密钥的哈希。
- 登录状态通过 HttpOnly、SameSite Cookie 标识。
### 状态存储
未配置 Redis时:
- 登录 Session:进程内内存;
- TOTP 登录挑战:进程内内存;
- TOTP 绑定临时状态:进程内内存;
- 进程重启后需要重新登录。
配置 Redis 时:
- 普通缓存通常使用 DB 0;
- 认证状态默认自动使用 DB 1;
- 也可用 `REDIS_SESSION_URL` 指向独立 Redis;
- 系统拒绝让普通缓存和认证状态使用同一端点的同一逻辑 DB。
明确配置的认证 Redis 连接失败会阻止服务启动,避免多实例部署时静默退回本机内存。
### 数据范围
授权是多维度的:
```text
角色
└─ 管理级别
└─ 学校
└─ 班级
└─ 具体业务状态
```
招生学校角色另按自己的学校 ID 限制计划、投档和报到数据。投档材料不会包含考生的其他志愿。
## 5. 数据持久化
### 双数据库适配
- SQLite:本地开发、自动化测试、单机和默认 Docker 部署。
- MySQL 8.4:生产、多实例或独立数据库部署。
两种数据库共享同一业务服务,并分别使用内嵌 schema SQL。数据库结构版本记录在 `schema_metadata`,当前为 v20。
### 总表与专属分表
系统采用“总表索引 + 独立物理分表”:
- 创建考试时建立:
- `exam_<partition>_candidates`
- `exam_<partition>_admissions`
- `exam_<partition>_results`
- `exam_<partition>_centers`
- 创建学校时建立:
- `school_<partition>_students`
分区键由业务 ID 的 SHA-256 摘要生成,不直接拼接用户输入。总表继续承担跨考试、跨学校查询和外键完整性,专属表支持按业务对象组织数据。
### 事务与审计
以下操作强调原子性:
- 报名号批量生成;
- 批量成绩确认写入;
- 成绩复议改分和相关结论;
- 招生投档与正式录取;
- 业务写入和审计日志。
批量操作失败时应整体回滚,避免半批状态。预览类操作不得开启正式写入。
## 6. 数据库状态快照
关系表读取会在进程内复用只读快照,避免每个请求重复扫描和转换全部业务数据。
- 应用自身写入:立即使快照失效。
- SQLite:通过 `PRAGMA data_version` 识别其他连接的提交。
- MySQL 外部直写:默认最多延迟 `DATABASE_STATE_CACHE_TTL_MS` 后可见。
因此不建议绕过应用直接写数据库。除审计缺失外,外部直写还可能造成短时间读到旧快照。
## 7. 应用缓存
缓存命名空间:
- `public`:首页和已发布公告;
- `results`:考生已发布成绩。
特性:
- Redis 可选;
- Redis 不可用时回退到有界本机缓存;
- 热点请求合并,避免同一 key 并发回源;
- 通过命名空间版本做批量失效;
- 写入后主动失效。
公开缓存默认 60 秒,成绩缓存默认 24 小时。本机缓存默认最多 200 条。
## 8. Excel 和 PDF
### Excel
ClosedXML 在服务端生成和解析工作簿。导入一般遵循:
```text
下载模板
→ 填写
→ 上传
→ 逐行校验
→ 页面预览
→ 明确确认
→ 事务写入
```
这保证文件解析错误不会产生部分业务写入。
### PDF 文书
成绩单和录取通知书在浏览器端下载 PDF,数据由服务端按当前身份和发布状态提供。文书包含:
- 防伪查询码;
- 二维码;
- 公开验真地址;
- HMAC 签名。
验真服务只返回允许公开核对的信息。
## 9. 健康检查
### `/health/live`
用于容器和进程存活检查,返回服务名和框架。
### `/health/migration`
用于诊断:
- 旧 API 已移除;
- 原生认证、考生和管理模块状态;
- 缓存 `ready`、`disabled` 或 `unavailable`;
- 认证状态使用 `redis` 或 `memory`;
- 当前启用的原生能力。
该路径名保留了迁移阶段语义,但当前系统已经完全运行于 ASP.NET Core。
## 10. 部署模型
### 单机
```text
Eis.Web + SQLite + 内存会话/缓存
```
适合开发、演示和低并发单实例。
### 生产
```text
一个或多个 Eis.Web
├─ MySQL 8.4
├─ Redis 缓存 DB
└─ Redis 认证状态 DB/实例
```
多实例必须共享认证状态。静态资源包含在每个 Web 发布物中,不需要独立 Node.js 服务。
+228
@@ -0,0 +1,228 @@
# 配置参考
应用从进程环境变量和仓库根目录 `.env` 读取配置。进程环境变量优先:如果同名变量已经由操作系统、容器或部署平台注入,`.env` 不会覆盖它。
## 1. 配置文件
本地开发:
```powershell
Copy-Item -LiteralPath .\.env.example -Destination .\.env
```
Docker Compose:
```powershell
Copy-Item -LiteralPath .\.env.docker.example -Destination .\.env.docker
```
`.env` 支持:
- 空行;
- `#` 注释;
- `KEY=value`;
- 可选 `export KEY=value`;
- 单引号或双引号包裹的完整值。
修改 `.env` 后需要重启应用。
## 2. 基础运行配置
| 变量 | 默认/示例 | 说明 |
| --- | --- | --- |
| `ASPNETCORE_ENVIRONMENT` | 本地 `Development` | `Production` 会启用生产密钥和数据库要求 |
| `ASPNETCORE_URLS` | `http://127.0.0.1:4173` | Kestrel 监听地址 |
| `DATABASE_CLIENT` | 开发 `sqlite`,生产 `mysql` | 仅支持 `sqlite`、`mysql` |
如果直接设置 `ASPNETCORE_ENVIRONMENT=Production` 而没有配置 MySQL 和两个生产密钥,应用会拒绝启动,这是预期的安全行为。
## 3. SQLite
| 变量 | 默认值 | 说明 |
| --- | --- | --- |
| `SQLITE_PATH` | `./data/exam.sqlite` | 相对路径按应用根目录解析,也可使用绝对路径 |
示例:
```powershell
$env:DATABASE_CLIENT = 'sqlite'
$env:SQLITE_PATH = './data/exam.sqlite'
dotnet run --project .\src\Eis.Web\Eis.Web.csproj
```
## 4. MySQL 8.4
可以使用分项变量:
| 变量 | 必填 | 默认值 | 说明 |
| --- | --- | --- | --- |
| `MYSQL_HOST` | 是 | 无 | MySQL 主机 |
| `MYSQL_PORT` | 否 | `3306` | 端口 |
| `MYSQL_USER` | 是 | 无 | 应用账号 |
| `MYSQL_PASSWORD` | 视账号而定 | 空 | 密码 |
| `MYSQL_DATABASE` | 是 | 无 | 数据库名 |
| `MYSQL_CONNECTION_LIMIT` | 否 | `10` | 连接池最大连接数 |
也可以只设置:
| 变量 | 示例 |
| --- | --- |
| `DATABASE_URL` | `mysql://exam_app:password@127.0.0.1:3306/exam_information` |
`DATABASE_URL` 优先于全部 `MYSQL_*` 连接项。用户名和密码含特殊字符时必须按 URL 规则编码。
连接默认:
- 字符集 `utf8mb4`;
- 连接超时 10 秒;
- 命令超时 30 秒;
- 启用连接池和连接重置。
## 5. 初始管理员
这些变量只在创建空数据库的初始管理员时使用:
| 变量 | 本地模板 | 说明 |
| --- | --- | --- |
| `INITIAL_ADMIN_USERNAME` | `admin` | 初始超级管理员账号 |
| `INITIAL_ADMIN_PASSWORD` | `Admin123!` | 初始密码,生产必须更换 |
| `INITIAL_ADMIN_DISPLAY_NAME` | `系统管理员` | 显示名 |
修改这些变量不会自动修改已经存在的管理员。已有账号应通过系统的密码修改或管理员重置功能维护。
## 6. TOTP 与文书防伪
| 变量 | 生产要求 | 说明 |
| --- | --- | --- |
| `TOTP_ENCRYPTION_KEY` | 至少 32 个字符 | 加密 TOTP 密钥并保护恢复码哈希 |
| `DOCUMENT_VERIFICATION_SECRET` | 至少 32 个字符 | 对成绩单和录取通知书防伪载荷签名 |
要求:
- 两个值相互独立;
- 不与数据库密码、Cookie 或其他系统密钥共用;
- 由秘密管理平台或部署平台注入;
- 部署后稳定保存;
- 不提交到 Git。
影响:
- 更换 `TOTP_ENCRYPTION_KEY`:已绑定 TOTP 可能无法解密。
- 更换 `DOCUMENT_VERIFICATION_SECRET`:历史文书查询码会失效。
开发环境未配置时使用仅供开发的稳定派生值。`DOCUMENT_VERIFICATION_SECRET` 未设置时还兼容读取 `SESSION_SECRET`,但新部署应使用独立变量,不依赖兼容路径。
## 7. Redis 普通缓存
| 变量 | 默认值 | 说明 |
| --- | --- | --- |
| `REDIS_URL` | 未配置 | `redis://` 或 `rediss://` 地址,可在路径指定逻辑 DB |
| `REDIS_CACHE_PREFIX` | `exam-information` | 缓存 key 前缀 |
| `REDIS_CACHE_TTL_SECONDS` | `60` | 公开数据缓存秒数,最大 86400 |
| `REDIS_RESULTS_CACHE_TTL_SECONDS` | `86400` | 已发布成绩缓存秒数 |
| `REDIS_CONNECT_TIMEOUT_MS` | `1500` | Redis 连接超时,最大 30000 |
| `LOCAL_CACHE_MAX_ENTRIES` | `200` | 本机回退缓存上限,最大 5000 |
普通缓存 Redis 暂时不可用时,应用回退到本机缓存,并保持写后失效语义。
## 8. Redis 认证状态
| 变量 | 默认值 | 说明 |
| --- | --- | --- |
| `REDIS_SESSION_URL` | 复用 `REDIS_URL` 端点 | 可指定独立 Redis |
| `REDIS_SESSION_DB` | 缓存 DB 为 0 时自动选 1,否则选 0 | 认证状态逻辑 DB |
| `REDIS_SESSION_PREFIX` | `exam-information:auth` | Session 和临时状态 key 前缀 |
| `AUTH_SESSION_TTL_SECONDS` | `28800` | 登录 Session,默认 8 小时,最大 30 天 |
| `AUTH_LOGIN_CHALLENGE_TTL_SECONDS` | `300` | TOTP 登录挑战,最大 1 小时 |
| `AUTH_TOTP_SETUP_TTL_SECONDS` | `600` | TOTP 绑定临时状态,最大 1 小时 |
普通缓存和认证状态不得使用同一 Redis 端点的同一逻辑 DB。错误配置时应用拒绝启动。
示例:
```text
REDIS_URL=redis://127.0.0.1:6379/0
REDIS_SESSION_DB=1
```
独立实例:
```text
REDIS_URL=rediss://cache.example.com:6379/0
REDIS_SESSION_URL=rediss://session.example.com:6379/0
```
Redis Cluster 通常不支持非 0 逻辑 DB,此时应使用 `REDIS_SESSION_URL` 指向独立端点或实例。
## 9. 数据状态快照
| 变量 | 默认值 | 说明 |
| --- | --- | --- |
| `DATABASE_STATE_CACHE_TTL_MS` | `30000` | MySQL 外部直写后,全量只读快照最长复用毫秒数 |
应用内写入会立即失效;SQLite 还会通过 `PRAGMA data_version` 识别外部连接提交。
## 10. 公开站点信息
| 变量 | 用途 |
| --- | --- |
| `PUBLIC_SITE_NAME` | 机构名称 |
| `PUBLIC_SITE_CODE` | 机构代码 |
| `PUBLIC_SITE_PHONE` | 联系电话 |
| `PUBLIC_SITE_ADDRESS` | 地址 |
| `PUBLIC_SITE_EMAIL` | 邮箱 |
| `PUBLIC_SITE_HERO_EYEBROW` | 首页英文眉题 |
| `PUBLIC_SITE_HERO_TITLE` | 首页主标题前半段 |
| `PUBLIC_SITE_HERO_HIGHLIGHT` | 首页主标题强调段 |
| `PUBLIC_SITE_HERO_DESCRIPTION` | 首页说明 |
| `PUBLIC_SITE_FOOTER_NOTICE` | 页脚提示 |
这些变量会覆盖数据库中的演示机构展示信息,只通过公开首页接口返回非敏感字段。
## 11. 兼容迁移开关
源码仍可读取 `AUTH_NATIVE_ENABLED`、`CANDIDATE_NATIVE_ENABLED` 和若干 `ADMIN_NATIVE_*` 变量,但当前 `appsettings.json` 已默认启用全部 ASP.NET Core 原生域,旧 Node.js API 已移除。
正常部署不需要设置这些变量。除非正在调试迁移兼容行为,不应把它们加入新环境模板。
## 12. 生产配置示例
以下只展示结构,密钥和密码必须替换:
```text
ASPNETCORE_ENVIRONMENT=Production
ASPNETCORE_URLS=http://0.0.0.0:4173
DATABASE_CLIENT=mysql
MYSQL_HOST=mysql.internal
MYSQL_PORT=3306
MYSQL_USER=exam_app
MYSQL_PASSWORD=replace-me
MYSQL_DATABASE=exam_information
MYSQL_CONNECTION_LIMIT=20
REDIS_URL=rediss://cache.internal:6379/0
REDIS_SESSION_URL=rediss://session.internal:6379/0
REDIS_CACHE_PREFIX=exam-information
REDIS_SESSION_PREFIX=exam-information:auth
TOTP_ENCRYPTION_KEY=replace-with-a-unique-secret-at-least-32-characters
DOCUMENT_VERIFICATION_SECRET=replace-with-another-unique-secret-at-least-32-characters
INITIAL_ADMIN_USERNAME=admin
INITIAL_ADMIN_PASSWORD=replace-with-a-strong-initial-password
INITIAL_ADMIN_DISPLAY_NAME=系统管理员
```
## 13. 上线检查
- `ASPNETCORE_ENVIRONMENT=Production`。
- 数据库目标明确,不是测试库或旧 SQLite 文件。
- 两项 32 字符以上的独立密钥已由秘密管理注入。
- 初始管理员密码已更换。
- Redis 缓存与认证状态未使用同一逻辑 DB。
- 多实例已使用共享认证 Redis。
- `.env`、`.env.docker` 未提交到版本库。
- 公开机构信息已改成真实信息。
- `/health/live` 和 `/health/migration` 可由运维系统检查。
Loaded 3 of 11 files, more files were not shown because too many files have changed in this diff. Show more