数字人民币教学仿真后端
You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Go to file
chenyuan 79ecc277e2 feat: 实训任务进度支持随时保存答案,并统一覆盖模块一至五
/api/v1/training-tasks 原先只表示"哪些步骤完成了",且模块二、四、五的动作链、
模块三的各接口都不会写入,导致步骤做完了进度不更新。同时新需求要求学员操作过程中
可以随时保存答案。

接口
- PUT    /training-tasks/{moduleCode}/steps/{stepCode}  保存答案(JSON),覆盖上一次
- GET    /training-tasks/{moduleCode}/steps/{stepCode}  读取答案和步骤状态
- DELETE /training-tasks/{moduleCode}                   重新实训,清空模块进度
- 步骤新增状态 SAVED(已保存草稿未完成);模块/步骤新增 savedSteps、hasData、savedAt、locked
- 非法输入(空、非 JSON、非对象/数组、超 10 万字符、未知模块/步骤)一律 400

防止学员改答案
- 步骤完成之前答案可反复覆盖;完成之后只再接受一次保存(页面做完最后一个动作会自动存一次),
  随即锁定。锁定后提交不同内容返回 409(新增 ErrorCode.CONFLICT),原答案保留;
  相同内容(忽略空白和键顺序)视为成功。重新实训清空整个模块,包括锁定状态
- 保存时对该步骤行加锁,避免并发请求绕过锁定检查

进度写入
- 模块一、二、四、五的评分服务在步骤完成时统一同步进度;模块三在拦截器里按
  前端各步完成判据对应到最后一个写接口,并恢复为 5 步可用
- 去掉拦截器里"仅打开页面的读接口也记步骤完成"的三处映射(兑换/支付 context、发行库存),
  否则步骤一进入就被当成已完成,答案会被提前锁定
- 草稿不计入完成数:module-completion 只统计 completed_at 不为空的记录

数据库(必须先于后端部署,按顺序执行,均可重复执行)
1. db/manual/training_task_progress_draft_upgrade.sql  新增 step_data/saved_at/sealed_at,completed_at 改为可空
2. db/manual/training_task_progress_draft_migrate.sql  把旧 user_step_progress_new 的答案迁入
3. db/manual/training_task_progress_backfill.sql       补录历史漏记的完成记录,并封存已完成且有答案的步骤
   第 3 个脚本会锁定存量答案,建议在没有学员正在操作时执行

测试
- 新增服务层 22、接口层 6、拦截器 5、评分服务若干用例;锁定与进度同步的用例已验证
  在去掉实现后会失败
- 完整套件的 29 个失败(institutionidentity 三个类和 WalletRuntimeResetTest)在改动前的
  master 上同样存在,与本次无关
4 days ago
.superpowers/sdd/2026-08-03-issuance-request-implementation fix: audit issuance writes with current account 2 months ago
docs feat: score input errors in modules 2 4 5 3 weeks ago
src feat: 实训任务进度支持随时保存答案,并统一覆盖模块一至五 4 days ago
.gitignore chore: ignore local worktrees 2 months ago
README.md Merge branch 'feat/issuance-request-module' 2 months ago
pom.xml feat:文件上传的功能开发 2 weeks ago

README.md

数字人民币教学仿真后端

开发规范与模块目录约定见 开发规范。

运行环境

  • JDK 8(已按 Temurin 8 验证)
  • Spring Boot 2.7.18、Spring Security 5.7、MyBatis-Plus 3.5.17、Knife4j 4.4.0
  • MySQL 8

登录方式

  • 兼容综合实训平台登录:POST /api/user/login。
    • 账号密码登录参数:username、passwordEncode。
    • Token 单点登录参数:TOKEN。接口解析智云 HS256 Token,同步本地用户并直接返回本系统访问 Token。
  • 原有主平台跳转登录:GET /api/v1/auth/sso?token=...,验证成功后携带本系统 Token 跳转前端回调地址。
  • 本地账号密码:POST /api/v1/auth/login 请求体为 {"studentId":"tzs001","password":"123qwe"},按 sys_user.student_id 查询并校验本系统保存的 BCrypt 密码哈希。旧字段 username 暂时作为兼容别名。

Token 单点登录中的平台 userId 保存为 sys_user.zy_user_id;本地 sys_user.user_id 始终使用 UUID 主键。本系统只接受管理员、教师和学生角色。

必需配置

生产环境通过环境变量配置:

变量 说明
DIGITAL_RMB_DB_URL 本系统 MySQL JDBC 地址
DIGITAL_RMB_DB_USERNAME 本系统数据库账号
DIGITAL_RMB_DB_PASSWORD 本系统数据库密码
DIGITAL_RMB_JWT_SECRET 至少 64 字符的应用 JWT 密钥
DIGITAL_RMB_PLATFORM_DB_URL 主平台 MySQL JDBC 地址
DIGITAL_RMB_PLATFORM_DB_USERNAME 主平台只读数据库账号
DIGITAL_RMB_PLATFORM_DB_PASSWORD 主平台只读数据库密码
DIGITAL_RMB_CAS_LOGIN_URL 学校 CAS 登录地址
DIGITAL_RMB_CAS_VALIDATE_URL CAS serviceValidate 地址
DIGITAL_RMB_CAS_CALLBACK_URL 本系统固定 CAS 回调地址
DIGITAL_RMB_FRONTEND_CALLBACK_URL 前端接收一次性 code 的固定回调地址

主平台数据库账号必须仅授予 SELECT 权限。不要将主平台 Token 写入日志、数据库或前端最终 URL。

本地运行

mvn spring-boot:run -Dspring-boot.run.profiles=local -Dspring-boot.run.arguments=--server.port=8081

本地 Swagger:http://localhost:8081/doc.html

数字货币发行实验模块

学生携带有效 JWT 可操作商业银行端和中央银行端;接口不区分教师、学生角色。

  • 商业银行端:/api/v1/commercial-banks/issuance,包含库存查询、发行申请创建与更新、待签名原文、SM3 摘要、SM2 签名、报文封装和发送。
  • 中央银行端:/api/v1/central-banks/issuance/requests/{id},只读返回请求接收状态、接收时间和请求报文。
  • 启动测试库配置:mvn spring-boot:run -Dspring-boot.run.profiles=dev。
  • Swagger 接口说明按“数字货币发行模块 - 商业银行端”和“数字货币发行模块 - 中央银行端”分组,使用中文 UTF-8 文本。

测试环境会执行 schema.sql,创建或更新测试账号 tzs001。dev 配置的 spring.sql.init.mode 为 never,不会自动修改真实 MySQL;开发库必须已有 sys_user 记录,并且 password 必须保存 BCrypt 哈希,不能保存密码明文。