本轮迁移已完成,生产运行链路现已切换为纯 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:
@@ -1,6 +1,6 @@
|
||||
# 衡准 · 考试信息管理系统
|
||||
|
||||
一个完整可运行的分级权限考试信息管理系统,使用 Node.js 后端;本地开发采用 SQLite,生产环境支持 MySQL 8.4。
|
||||
一个完整可运行的分级权限考试信息管理系统,后端使用 ASP.NET Core 10;本地开发采用 SQLite,生产环境支持 MySQL 8.4。
|
||||
|
||||
## 已实现功能
|
||||
|
||||
@@ -80,16 +80,16 @@
|
||||
- 组织、学校、班级三级数据范围在服务端强制过滤
|
||||
- 审批实例、当前责任人、转交和监督操作全程留痕
|
||||
- 桌面端与移动端响应式布局
|
||||
- Excel 文件使用 `exceljs` 生成和解析,并限制上传文件大小
|
||||
- Excel 文件使用 ClosedXML 生成和解析,并限制上传文件大小
|
||||
- 成绩单与录取通知书以 PDF 下载,使用服务端 HMAC 防伪码支持公开验真
|
||||
|
||||
## 运行
|
||||
|
||||
需要 Node.js 22.5 或更高版本(SQLite 使用 Node.js 内置驱动)。
|
||||
需要 .NET 10 SDK。
|
||||
|
||||
```powershell
|
||||
npm install
|
||||
npm start
|
||||
dotnet restore .\Eis.slnx
|
||||
dotnet run --project .\src\Eis.Web\Eis.Web.csproj
|
||||
```
|
||||
|
||||
打开 <http://127.0.0.1:4173>。
|
||||
@@ -98,7 +98,7 @@ npm start
|
||||
|
||||
生产环境还必须单独设置至少 32 个字符的 `DOCUMENT_VERIFICATION_SECRET`。系统用它为成绩单和录取通知书生成 HMAC 防伪查询码;更换该值会使此前下载文书的查询码失效,因此应独立生成、稳定保存且不得与 TOTP 密钥共用。
|
||||
|
||||
本地开发无需额外配置,首次运行会自动创建 `data/exam.sqlite` 和完整关系型数据库结构,但不会导入学校、考生、考试或报名测试数据。首次建库只写入系统基础配置和一个超级管理员;账号、密码和显示名可通过 `INITIAL_ADMIN_USERNAME`、`INITIAL_ADMIN_PASSWORD`、`INITIAL_ADMIN_DISPLAY_NAME` 设置。当前数据库结构版本为 v17;v16 数据库会自动增加 TOTP 字段,低于 v15 的开发库会提示重建。
|
||||
本地开发无需额外配置,首次运行会自动创建 `data/exam.sqlite` 和完整关系型数据库结构,但不会导入学校、考生、考试或报名测试数据。首次建库会写入系统基础配置、默认审批流程和一个超级管理员;账号、密码和显示名可通过 `INITIAL_ADMIN_USERNAME`、`INITIAL_ADMIN_PASSWORD`、`INITIAL_ADMIN_DISPLAY_NAME` 设置。当前数据库结构版本为 v20。
|
||||
|
||||
### Docker
|
||||
|
||||
@@ -131,11 +131,11 @@ docker compose logs --follow app
|
||||
docker build --tag hengzhun-exam-system:local .
|
||||
```
|
||||
|
||||
镜像默认监听 `0.0.0.0:4173`,以非 root 用户运行,并通过 `/api/public/home` 执行健康检查。需要连接 MySQL 或 Redis 时,用运行环境变量覆盖 `DATABASE_CLIENT`、`DATABASE_URL`/`MYSQL_*`、`REDIS_URL`;认证状态默认使用同一 Redis 服务的独立 DB 1,也可以通过 `REDIS_SESSION_DB` 或 `REDIS_SESSION_URL` 单独配置。此时 SQLite 数据卷可以移除。
|
||||
镜像仅包含 ASP.NET Core 10 运行时,默认监听 `0.0.0.0:4173`,以非 root 用户运行,并通过 `/health/live` 执行健康检查。需要连接 MySQL 或 Redis 时,用运行环境变量覆盖 `DATABASE_CLIENT`、`DATABASE_URL`/`MYSQL_*`、`REDIS_URL`;认证状态默认使用同一 Redis 服务的独立 DB 1,也可以通过 `REDIS_SESSION_DB` 或 `REDIS_SESSION_URL` 单独配置。此时 SQLite 数据卷可以移除。
|
||||
|
||||
#### Gitea Actions 自动发布到 Docker Hub 与 Gitea 软件包
|
||||
|
||||
工作流位于 `.gitea/workflows/docker-publish.yml`。它会先安装依赖并运行测试,然后构建 `linux/amd64`、`linux/arm64` 双架构镜像,并同时推送到 Docker Hub 与 `git.biss.click/biss/exam-information-system`。
|
||||
工作流位于 `.gitea/workflows/docker-publish.yml`。它会使用 .NET 10 运行测试,然后构建 `linux/amd64`、`linux/arm64` 双架构镜像,并同时推送到 Docker Hub 与 `git.biss.click/biss/exam-information-system`。
|
||||
|
||||
使用前需要完成以下配置:
|
||||
|
||||
@@ -165,11 +165,11 @@ git push origin v1.3.0-rc.1
|
||||
|
||||
首次成功推送后,容器镜像会出现在 `biss` 所有者的软件包列表。Gitea 的软件包归属于用户或组织,不会天然归属于某个仓库;打开该软件包的设置页面,将它关联到 `Exam-Information-System`,即可让它显示在此仓库的“软件包”页。之后可使用 `docker pull git.biss.click/biss/exam-information-system:latest` 拉取。
|
||||
|
||||
需要清空并重建空业务库时运行 `npm run reset-db`;该命令与 `npm run initialize-system` 使用同一套初始化流程,会读取项目根目录的 `.env`,并根据 `DATABASE_CLIENT` 选择 SQLite 或 MySQL。也可通过 `npm run reset-db -- --sqlite` 或 `npm run reset-db -- --mysql` 显式选择数据库;MySQL 中存在无法识别为样例数据的业务记录时仍会拒绝覆盖,只有确认目标可清空后才能追加 `--force`。需要测试数据时再手动运行 `npm run seed-test-data`;导入脚本会生成 5 所学校、1200 名批量考生及对应的不同状态报名数据。省市区县下拉数据位于 `src/data/china-regions.mjs`,当前版本为国家地名信息库截至 2025-12-31 的三级快照,并补入和康县(653228)与和安县(653229);从新版 CSV 更新时可运行 `node scripts/build-regions.mjs <CSV路径> src/data/china-regions.mjs`。
|
||||
应用会在空库上自动创建结构和基础配置。旧版 Node 数据重置、样例数据和地区快照构建脚本仍保留为开发维护工具,不会被生产镜像复制或执行;运行这些脚本前必须明确数据库目标,且不得对生产业务库执行。
|
||||
|
||||
## 数据库配置
|
||||
|
||||
应用启动时会自动读取项目根目录的 `.env`,可先运行 `Copy-Item .env.example .env` 创建配置文件。命令行或部署平台已经注入的进程环境变量优先于 `.env`。应用根据 `DATABASE_CLIENT` 使用不同数据库;未设置时,开发/测试环境默认 `sqlite`,`NODE_ENV=production` 默认 `mysql`。
|
||||
应用启动时会自动读取项目根目录的 `.env`,可先运行 `Copy-Item .env.example .env` 创建配置文件。命令行或部署平台已经注入的进程环境变量优先于 `.env`。应用根据 `DATABASE_CLIENT` 使用不同数据库;未设置时,开发/测试环境默认 `sqlite`,ASP.NET Core 生产环境默认 `mysql`。
|
||||
|
||||
公开首页的机构名称、机构代码、电话、地址、邮箱、主标语和页脚提示分别由 `PUBLIC_SITE_NAME`、`PUBLIC_SITE_CODE`、`PUBLIC_SITE_PHONE`、`PUBLIC_SITE_ADDRESS`、`PUBLIC_SITE_EMAIL`、`PUBLIC_SITE_HERO_*`、`PUBLIC_SITE_FOOTER_NOTICE` 配置。修改 `.env` 后需要重启应用;这些配置会覆盖数据库中的演示机构信息,且只通过公开首页接口返回非敏感展示字段。
|
||||
|
||||
@@ -178,7 +178,7 @@ git push origin v1.3.0-rc.1
|
||||
```powershell
|
||||
$env:DATABASE_CLIENT = 'sqlite'
|
||||
$env:SQLITE_PATH = './data/exam.sqlite'
|
||||
npm start
|
||||
dotnet run --project .\src\Eis.Web\Eis.Web.csproj
|
||||
```
|
||||
|
||||
`SQLITE_PATH` 可省略,默认路径就是 `./data/exam.sqlite`。
|
||||
@@ -217,15 +217,15 @@ GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, ALTER ON exam_information.* TO 'ex
|
||||
成绩和学生资料发生变化后,专属表会自动同步;总表继续承担跨考试、跨学校查询和外键完整性约束。
|
||||
|
||||
```powershell
|
||||
$env:NODE_ENV = 'production'
|
||||
$env:ASPNETCORE_ENVIRONMENT = 'Production'
|
||||
$env:DATABASE_CLIENT = 'mysql'
|
||||
$env:MYSQL_HOST = '127.0.0.1'
|
||||
$env:MYSQL_PORT = '3306'
|
||||
$env:MYSQL_USER = 'exam_app'
|
||||
$env:MYSQL_PASSWORD = 'replace-with-a-strong-password'
|
||||
$env:MYSQL_DATABASE = 'exam_information'
|
||||
$env:HOST = '0.0.0.0'
|
||||
npm start
|
||||
$env:ASPNETCORE_URLS = 'http://0.0.0.0:4173'
|
||||
dotnet run --project .\src\Eis.Web\Eis.Web.csproj
|
||||
```
|
||||
|
||||
也可以只设置标准连接地址 `DATABASE_URL=mysql://user:password@host:3306/database`。完整模板见 `.env.example`;将模板复制为 `.env` 后取消 MySQL 配置项的注释并填写实际连接信息即可。生产部署仍建议由部署平台注入环境变量,避免在服务器文件中保存密码。
|
||||
@@ -245,7 +245,7 @@ $env:REDIS_CACHE_TTL_SECONDS = '60'
|
||||
$env:REDIS_RESULTS_CACHE_TTL_SECONDS = '86400'
|
||||
$env:REDIS_SESSION_DB = '1'
|
||||
$env:AUTH_SESSION_TTL_SECONDS = '28800'
|
||||
npm start
|
||||
dotnet run --project .\src\Eis.Web\Eis.Web.csproj
|
||||
```
|
||||
|
||||
生产环境可使用 `redis://` 或启用 TLS 的 `rediss://` 连接地址,并通过 `REDIS_CONNECT_TIMEOUT_MS` 调整启动连接超时。若 Redis Cluster 不支持非 0 逻辑 DB,请用 `REDIS_SESSION_URL` 为认证状态配置独立 Redis 实例。
|
||||
@@ -325,47 +325,29 @@ MySQL 模式会自动识别由本项目生成的批量样例数据并清理。
|
||||
## 自动化测试
|
||||
|
||||
```powershell
|
||||
npm test
|
||||
dotnet test .\Eis.slnx
|
||||
pwsh.exe -NoLogo -NoProfile -NonInteractive -File .\scripts\smoke-dotnet-native.ps1
|
||||
```
|
||||
|
||||
测试使用独立临时 SQLite 数据库,覆盖固定报名号跨考试复用、首次登录强制改密、完整资料补录、自主注册开关、三级管理员数据范围、本校班级与班级管理员管理、多级审批、同级转交、校级按班级批量申领与终审原子建号、三级管理员范围内缴费状态修改与名单导出、结构化考点考场及变更审批、多资源 Excel 导入导出、多科目报名、独立科目及格规则、成绩 Excel 预览后原子提交、五级准考证混编、四种号码规则、多科目同考点、成绩复议、校班严格匹配和多人均分。
|
||||
xUnit 测试使用独立临时 SQLite 数据库,覆盖认证兼容性、迁移开关约束、文书防伪码、文件处理、缓存以及空库 v20 初始化;测试不会连接或修改生产数据库。
|
||||
|
||||
## 项目结构
|
||||
|
||||
项目采用模块化单体架构:仍由一个 Node.js 进程部署,但 HTTP、权限、业务路由、数据库适配和前端页面按职责分开。
|
||||
项目采用 ASP.NET Core 10 模块化单体架构,由一个 `Eis.Web` 进程部署;HTTP、权限、业务服务、数据库适配和前端页面按职责分层。
|
||||
|
||||
```text
|
||||
index.html 页面入口
|
||||
styles.css 公共首页、考生端、管理端响应式样式
|
||||
app.js 前端路由、事件与表单控制器
|
||||
server.mjs HTTP 服务启动、模块装配与静态文件服务
|
||||
database.mjs 数据仓储与数据库模块装配
|
||||
excel.mjs Excel 模板、导入解析与导出工作簿
|
||||
Eis.slnx .NET 10 解决方案
|
||||
src/Eis.Domain 领域模型与业务值
|
||||
src/Eis.Application 应用服务契约
|
||||
src/Eis.Infrastructure SQLite/MySQL、认证、缓存、Excel 与业务实现
|
||||
src/Eis.Web ASP.NET Core 宿主、端点和发布静态资源
|
||||
tests/Eis.Infrastructure.Tests xUnit 自动化测试
|
||||
|
||||
src/data/base.mjs 空业务库与系统基础配置
|
||||
src/data/seed.mjs 手动测试数据生成器
|
||||
scripts/import-test-data.mjs 独立测试数据导入脚本
|
||||
src/http/responses.mjs JSON、文件与请求体处理
|
||||
src/security/auth-state.mjs Redis / 本机会话与 TOTP 临时状态
|
||||
src/security/session.mjs Cookie 解析与当前用户
|
||||
src/security/authorization.mjs 管理层级、权限和数据范围
|
||||
src/routes/public.routes.mjs 公开 API
|
||||
src/routes/auth.routes.mjs 登录、注册与改密 API
|
||||
src/routes/candidate.routes.mjs 考生业务 API
|
||||
src/routes/admin.routes.mjs 管理业务 API
|
||||
|
||||
src/database/schema.mjs SQLite / MySQL 关系模型
|
||||
src/database/sqlite-adapter.mjs SQLite 初始化、迁移与事务适配
|
||||
src/database/mysql-adapter.mjs MySQL 初始化、迁移与事务适配
|
||||
|
||||
src/client/state.mjs 前端共享状态
|
||||
src/client/api.mjs 浏览器 API 请求封装
|
||||
src/client/ui.mjs 格式化、图标与通用 UI 工具
|
||||
src/client/public-views.mjs 公共首页与登录注册视图
|
||||
src/client/candidate-views.mjs 考生中心视图
|
||||
src/client/admin-views.mjs 管理后台视图
|
||||
|
||||
tests/system.test.mjs 端到端系统测试
|
||||
index.html / styles.css / app.js 前端入口、样式和控制器
|
||||
src/client 公共、考生、管理及招生前端模块
|
||||
src/database/schema.mjs 兼容 SQLite/MySQL 的 v20 建库定义
|
||||
scripts 迁移验证与旧版开发数据维护工具
|
||||
server.mjs / src/routes 仅保留的旧 Node 行为对照源码
|
||||
data/exam.sqlite 本地运行后生成的 SQLite 数据库
|
||||
.env.example 开发与生产环境变量模板
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user