Files
2026-08-29 19:07:04 +08:00

42 lines
3.9 KiB
Markdown

# 第一阶段架构说明
## 模块边界
`Identity` 仅维护本地用户与未来外部身份提供商的映射;`Organization` 维护组织树和成员范围;`Election`、`Voting`、`OfflineCounting`、`Cms`、`PublicBoard` 和 `Audit` 预留为独立业务模块。
公开内容采用 Razor Pages 的静态服务端渲染;需要即时校验和状态更新的区域采用 Blazor Web App 的 Interactive Server 渲染。交互组件不能承担投票防重、资格或计票规则,这些规则仍必须由服务端事务和数据库约束执行。
线上投票实现时,资格/已投状态与匿名选票将使用不同实体和数据库约束,禁止常规查询将选民反向关联到选票内容。本阶段没有创建选票表,因此不会产生该关联。
## MySQL 配置
开发环境只提交不含密码的连接字符串模板。设置本机密码:
```powershell
dotnet user-secrets set "ConnectionStrings:ElectionDatabase" "Server=localhost;Port=3306;Database=election;User ID=election;Password=<password>;" --project src/ElectionSystem.Api
```
生产环境请以 `ConnectionStrings__ElectionDatabase` 环境变量注入。迁移由运维明确执行,不在应用启动时自动运行。
CMS 使用独立的 `ElectionSystem.Cms` Orchard Core 主机及数据库;具体初始化和内容模型见 [cms-setup.md](cms-setup.md)。
## 当前数据库对象
初始迁移仅创建 `identity_users`、`organization_units` 和 `audit_entries`。审计元数据只记录受影响的字段名,不能用于保存线上匿名选票内容或关联信息。
## 第二阶段:地域、人员与候选人
`administrative_regions` 是行政区划目录,不承载单位、支部或选举组织。其层级固定为省、市、区县、镇街、村社区五级;省市区镇基础数据应由 AreaCity-JsSpider-StatsGov 的受控版本导入,村社区只能由本地确认目录预校验后导入,并保留 `Source` 与 `SourceVersion`。补齐节点保留 `IsSynthetic`,不可擅自扁平化。
`identity_user_regional_roles` 将用户角色与地域范围分开保存。省、市、区、镇、村管理员的范围自动覆盖全部下级地域;系统管理员没有地域限制。计票员和监督员还必须经 `identity_user_counting_stations` 分配到具体计票所,未来线下计票接口必须同时检查地域角色和计票所分配。
主站使用 ASP.NET Core Identity 的本地账号与安全 Cookie 认证;`ApplicationUser.Id` 是地域角色和选民账号关联的唯一主体。密码哈希、锁定、登录安全戳由成熟的 Identity 组件处理,业务表不保存明文密码。保留 JWT Bearer 验证注册,后续接 OpenIddict 或 Keycloak 时可为 API 客户端启用令牌流程;未认证请求不能触发地域范围查询或写入。
`voter_profiles` 是选民主数据,按地域、状态查询和写入均须先应用管理员范围。选民 Excel 采用“上传预校验—逐行错误—同一操作者确认”模式,预览在 30 分钟后失效,确认前重新检查范围和重复选民编号。它不保存投票内容,后续 `Voting` 模块只可从选民 ID 创建资格/已投状态。
`candidate_profiles` 维护候选人地域归属和提名、审核、撤回、取消资格、公示状态;状态转换必须在服务端验证,撤回和取消资格必须说明原因。候选人材料文件将在对象存储接入后作为独立、授权的附件实体实现。
## 管理端
主站使用混合 Razor Pages 与 Blazor Interactive Server,不引入单页应用构建链。`/admin` 是需要认证的 Razor Pages 入口;`/admin/dashboard`、`/admin/regions`、`/admin/voters`、`/admin/candidates`、`/admin/roles`、`/admin/counting-stations` 使用 Blazor Server 完成交互;`/admin/voter-import` 和 `/admin/region-import` 使用 Razor Pages 的受控文件上传表单。两类页面均复用同一用户声明和 `RegionScopeService`,不能通过 UI 参数越出地域范围。