Skip to content

Releases: QianKunBoss/ClassFire

V0.3.2-新时代信息化建设项目-ClassFire

Choose a tag to compare

@QianKunBoss QianKunBoss released this 21 Sep 00:21

ClassFire v0.3.2 发布说明

0. 关于本文件

v0.3.0 对项目做了一次整体重构:后端框架、数据访问层、权限模型、部署方式全部更换,改动覆盖整个产品。因此本发布说明不采用增量变更清单的写法,而是完整描述 v0.3.2 的产品能力,作为该版本的功能基线。v0.3.1 与 v0.3.2 的增量内容见第 8 节和第 11 节。

1. 概述

ClassFire(班级操行分管理系统)面向各级学校,用于管理操行分(班级积分)。系统以多租户架构为基础,每所学校使用独立的数据库文件;以四级权限体系支撑「总系统 / 学校 / 年级 / 班级 / 学生」的层级管理。原本依靠纸质台账、黑板公示与 Excel 核算的操行分管理,在系统中变为可实时查询、可追溯、可统计、可对接第三方平台的线上能力。

2. 重构前后对照

维度 重构前(PHP 版) 重构后(v0.3.x)
后端框架 PHP 原生脚本 Nuxt 4(Nitro 服务端引擎,SSR)
前端架构 多页面 PHP + jQuery Vue 3 SPA + 服务端渲染,TypeScript 全量类型
数据访问 手写 SQL 字符串拼接 Drizzle ORM(类型安全查询构造器)
数据库 单库单表结构 SQLite 多租户分裂库(主库 + 每校独立 .db)
权限模型 单班级管理员 四级权限体系(super_admin / school_admin / grade_admin / class_admin),另有学生端
数据隔离 靠 WHERE 条件约束 靠物理文件隔离,跨校数据不在同一个数据库文件内
部署方式 Web 服务器 + PHP-FPM 单进程 Nitro 产物,node .output/server/index.mjs 即可启动
第三方对接 无 外部开放 API v1(22 个端点 + 凭证体系 + 审计)
客户端形态 仅网页 PWA 可安装应用(离线缓存 + 主屏幕图标)
安全基线 口令明文、弱校验 BCrypt + 会话密封 + 启动期安全守卫 + 登录限流

重构带来的主要收益是数据隔离方式的改变。跨校数据不再依靠 SQL 条件约束,而是依靠文件系统隔离:学校 A 的数据库文件中不存在学校 B 的表,因此漏写一处 WHERE school_id = ? 不会造成跨校数据泄露。

3. 功能说明

3.1 多租户架构与权限体系

租户模型:一校一库

data/
├── classfire.db                  ← 主库:学校、管理员、入驻申请、公告、系统设置、
│                              邮件服务与模板、API 凭证、API 审计日志
└── schools/
    ├── 1.db                 ← 学校 1 的独立业务库
    ├── 7.db                 ← 学校 7 的独立业务库
    └── ...
        (每库含:年级、班级、学生、积分流水、积分模板、座位布局、座位数据、幂等键)
  • 新学校审批通过时,由 create-school-db 工具动态生成该校数据库文件并初始化 schema。
  • 两个库均启用 PRAGMA journal_mode = WAL(并发读写友好)与 PRAGMA foreign_keys = ON(SQLite 默认关闭外键约束,需显式开启)。
  • 防止幽灵库:useSchoolDb() 在打开分库前先调用 assertSchoolExists(schoolId)(server/database/db.ts:55,调用点 :89)确认主库 schools 表中存在该记录,否则拒绝打开。否则超级管理员传入任意 ?schoolId= 就能凭空产生一个空库。
  • 启动期全量迁移:migrateAllSchoolDbs()(db.ts:275)在 initDatabase() 之后扫描 data/schools/*.db,逐个执行 migrateSchoolDb()。这样长期未被访问的学校库不会停留在旧 schema,避免某校长时间未登录、升级后一登录就报缺列。
  • 删除学校提供两种模式(DELETE /api/schools/[id],需超管权限,并通过 x-confirm-password 二次验密):
    • 默认(deleteData=0)只删除主库中的学校记录,保留 data/schools/{id}.db 数据文件,误删后可人工恢复;
    • 显式传入 ?deleteData=1 才物理删除数据库文件,学生、班级、年级、积分数据全部清除且不可恢复;
    • 删除前先做外键解绑而非级联删除:将 applications.reviewed_by / created_admin_id、announcements.created_by 置空以保留审计记录,再删除该校管理员账号,最后删除学校记录,整个过程在一个事务内完成;
    • 删除与封禁是两个不同操作。封禁走 PATCH /api/schools/[id],将 disabled 置为 1,学校及其数据完整保留,可随时解封。
  • 跨库引用只在必要处出现:主库的 admins.school_id 用于定位学校库;admins.grade_id / class_id 仅作为管辖范围提示,不建立跨库外键(SQLite 不支持跨文件外键),一致性由应用层保证。权限判定以当前登录管理员的真实身份和实时解析的管辖范围为准,不信任前端传入的 schoolId / gradeId / classId。
  • useDb() 旧接口已废弃(db.ts:41),统一使用 useMainDb() / useSchoolDb()。

四级角色与管辖范围

角色 标识 管辖范围 主要职责
超级管理员 super_admin 全局,无所属 学校入驻审核与封禁、管理员账号管理、公告发布、邮件与系统设置、全平台数据管理
学校管理员 school_admin 本校 年级管理、班级管理、教师账号管理、本校 API 凭证签发
年级管理员 grade_admin 本校 + 本年级 本年级班级管理、年级统计查看
班级管理员(班主任) class_admin 本校 + 本年级 + 本班 学生管理、加减分、模板、座位表、班级统计
学生 学生表 本人 查看个人积分与流水、班级排名,绑定邮箱,修改个人信息
  • 管理员的所属范围可编辑,可选范围由管理级别约束:super_admin 无所属,school_admin 仅可选学校,grade_admin 可选学校与年级,class_admin 可选学校、年级与班级。
  • 涉及管辖范围的接口统一通过 assertClassManagement 一类函数校验,内部接口与外部开放 API 共用同一套范围语义,避免出现两套互相矛盾的规则。

鉴权模型

  • 内部接口(/api/**)只接受 Session(nuxt-auth-utils 密封 Cookie)。
  • 外部接口(/api/v1/**)只接受 api_token。
  • 两套鉴权相互隔离。外部调用无法操作系统级数据,这一点由路由结构保证,不需要在上百个接口中逐个维护黑名单。

3.2 积分引擎

加减分的三种方式

  1. 单条:指定学生、分值与事由。
  2. 批量:一次提交多个学生(上限 200 条),逐条校验并逐条返回结果。
  3. 模板:选用预置模板,一键套用其分值与事由描述。

四列账本口径

每个学生记录上维护四个与积分流水实时同步的聚合列:

列 含义
total_score 当前总分(add_score - deduct_score)
add_score 累计加分
deduct_score 累计扣分
score_count 积分记录条数
  • 加分、扣分、撤销都通过同一个 score-service 执行,内部接口与外部开放 API 共用,保证任何入口写入都不会造成四列口径不一致。
  • 撤销采用对称回滚:撤销一条 +5 的记录,会同时把 total_score 减 5、add_score 减 5、score_count 减 1,而不是再记一次扣分。语义上该记录视为不存在,而不是被抵消。
  • 单次分值上限为 ±10000(MAX_SCORE_DELTA),超出返回 40002 参数非法。
  • 提供全量重算接口(recalculate-scores):聚合列因异常写入发生漂移时,可按流水重建四列,作为兜底修复手段。

积分流水

  • 每条记录保存学生 ID、用户名快照、分值变化、事由描述、创建时间(UTC ISO 8601)。
  • 支持按学生、用户名、班级、年级、类型(加分 / 扣分)、时间区间筛选与分页。
  • 支持删除单条记录,删除时同步回滚聚合列,操作带二次确认。
  • 学生可查看自己的全部流水,管理员可查看管辖范围内的全部流水。

积分模板

  • 两种归属:班级专属模板与全校通用模板。
  • 支持创建、编辑(名称、分值、描述)与删除。同一归属下不允许重名,重名返回 40901。
  • 模板归属在创建时确定,不可修改。需要更换归属时删除后重建,避免历史记录语义漂移。
  • 全校通用模板仅学校级及以上管理员可创建。

学期切换

  • 一键开启新学期,重置学生的四列积分统计,用于学期制操行分重新起算。
  • 该操作需要超级管理员权限,属高风险操作。

3.3 排行榜与图表

排行榜

  • 按总分排序,默认展示前 10 名。
  • 名次排序使用 localeCompare,保证中英文姓名混排顺序符合习惯。
  • 前三名显示奖牌标识。
  • 支持校级、年级、班级三级范围切换。超管可查看全校、按年级、按班级;年级管理员可查看全年级、按班级。

图表组件(Chart.js 4 + vue-chartjs 5)

组件 用途
ScoreTrendLine 积分趋势折线图,按日期聚合的累积与增量走势
ScoreCandlestick 积分 K 线图,将每日加减分聚合成开高低收,呈现当日净变化幅度
MiniSparkline 列表行内的迷你折线走势
MiniCandles 排行榜行内的迷你 K 线趋势预览
ScoreAddDeductBar 加减分对比柱状图,红色表示加分、绿色表示减分
  • 趋势接口提供按班级聚合与按学生个体两个维度(scores/trend 与 scores/trend/users),学生端另有独立的个人趋势接口。
  • scores/breakdown 提供分值构成拆解,展示各事由贡献的分数。
  • stats/records 提供积分记录的统计口径(按人、按类型、按时间)。

配色遵循项目统一规范:宇宙科技风钢蓝色系,全站不使用渐变(无 linear-gradient、radial-gradient、bg-gradient-*),发光效果通过纯色配合 box-shadow / text-shadow 实现,语义色保留 emerald / amber / red。

3.4 可视化座位表

  • 拖拽式编排,直接拖动学生到目标座位,所见即所得。
  • 分组布局,可配置组数(groupCount)、每组行数(rowsPerGroup)、每组列数(colsPerGroup)。
  • 过道配置(hasAisle),支持在组间留出过道,贴合真实教室排布。
  • 支持按配置一键生成座位网格,再手工微调。
  • seat_data 表以 (班级, 组序号, 行序号, 列序号) 唯一约束一个格位,格位可以绑定学生,也可以标记为过道。
  • 学生被删除时座位自动置空(ON DELETE SET NULL),不会留下指向已删除学生的座位记录。
  • 班级删除或学生转班时,座位与学生的对应关系按班级维度整体管理,避免跨班错位。

3.5 数据统计

  • 工作台仪表盘(/admin)是管理后台首页,展示班级态势、积分概览、排行榜等概览信息。
  • 概览统计(stats/overview):班级数、学生数、总积分、加分合计、扣分合计、记录总数、今日记录数、TOP 榜。
  • 记录统计(stats/records):按时间、类型、人员聚合记录。
  • 多级筛选:超管支持全校、年级、班级三级切换,年级管理员支持全年级、班级两级切换。
  • 趋势分析:加分、扣分、净变化随时间的走势,可用于发现纪律问题集中的时间段。

3.6 学生端

学生是系统中唯一自证身份的角色,有独立的登录入口与界面。

  • 独立登录页与登录接口(auth/student/login),与管理员体系分离。
  • 个人主页:展示本人总分、加分、扣分、记录条数以及最近积分流水。
  • 个人趋势:本人积分随时间的变化曲线。
  • 班级排行榜:查看本班排名,默认前 10 名。
  • 同班同学列表:仅展示用户名、姓名等公开信息。
  • 个人设置:修改用户名、修改姓名、修改密码、绑定邮箱(用于找回密码)。其中用户名允许学生自助修改。
  • 邮箱验证码找回密码:绑定邮箱后可通过验证码自助重置密码,无需联系班主任。
  • 强制改密:新学生使用默认口令(如 123456)或管理员重置后的临时口令首次登录时,must_change_password 标记为 1,系统跳转到 setup-required 页面,未完成改密无法进入系统。
  • 账号禁用:学生被禁用(disabled = 1)后无法登录。

3.7 学校入驻与审批

入驻链路从公开申请到自动开户,共九个环节。

  1. 公开申请页(/apply),无需登录即可访问。
  2. 校名实时校验:输入校名时防抖检查是否重名,已存在则提示并禁用提交与获取验证码按钮;提交时再校验一次,防止并发绕过。
  3. 重复判定放宽:已删除、已拒绝的学校不计入重复,允许重新申请,避免一次申请永久占位。
  4. 邮箱验证码:申请时通过邮箱验证码确认申请人邮箱真实性,复用邮件服务系统。
  5. 超管审核(/superadmin/applications):通过或拒绝,可填写审核备注。
  6. 通过后自动开户:创建学校记录、该校独立数据库以及学校管理员账号,并分配初始账号密码。
  7. 结果邮件通知:审核结果自动发送到申请时填写的邮箱,邮件中可携带账号、密码、学校 ID 等变量。
  8. 学校封禁:超管可将学校置为 disabled = 1,被封禁学校的全部管理员与学生均无法登录,超管仍可查看与解封。
  9. 删除留痕:
    • 已审核通过的学校被删除后,入驻申请页对应记录显示黄色「已删除」标签(school_deleted 标记);
    • 新增 deleted_school_id 快照列。删除学校时把原学校 ID 复制到该列再置空外键,使申请记录在学校数据库文件已删除后仍能展示原始学校 ID,不会变成无法追溯的孤儿记录;
    • 删除行为本身有两种模式(默认保留数据文件,可显式要求物理删库),详见 3.1 节。封禁与删除是两个操作,封禁只置 disabled = 1,学校与其数据完整保留。

3.8 公告系统

  • 全局公告由超级管理员统一发布,全平台可见。
  • 三种类型:通知(info)、警告(warning)、重要(important),前端按类型区分颜色。
  • 导航栏下方固定公告栏(AnnouncementBar),进站即可看到,不打断操作。
  • 内容支持加粗、链接、换行等基础 HTML。
  • 所有公告内容经 sanitizeHtml 白名单过滤后才渲染。公告是三端共享的注入面,此处为硬性防线。
  • 关闭记忆:用户关闭某条公告后,24 小时内不再显示(本地记忆),避免反复打扰。
  • 公告可整体下线而不删除,保留历史记录。
  • 提供公开拉取接口,登录页等未鉴权页面也能获取公告,该接口只读且内容已过滤。

3.9 认证与账号安全

管理员登录方式

  1. 用户名 + 密码
  2. 邮箱 + 密码(登录标识符可切换)
  3. 邮箱验证码登录(免密)

密码找回与绑定

  • 管理员忘记密码可通过邮箱验证码自助重置。
  • 邮箱绑定分两步:send-code 发送验证码,verify 校验并写入数据库,绑定时间记录在 email_bound_at。
  • 邮箱在各自作用域内唯一(管理员全局唯一,学生全校唯一)。SQLite 唯一索引允许多个 NULL,因此未绑定的记录不冲突。
  • 改密码、改邮箱等敏感操作走 security/send-code 二次验证码确认。

强制修改密码与强制安全设置

  • 管理员与学生两张表都带 must_change_password 标志。
  • 管理员重置他人密码,或用默认密码新建账号后,被重置者登录时会被强制改密;学生用默认口令首次登录同样被强制改密。
  • 跳转落点不同:管理员进入 /settings?force=true,学生进入 /student/setup-required。两者均为独立布局(blank),未完成设置无法进入系统其余部分。
  • 为避免死锁,全局中间件只在 mustChangePassword 为真,或者未绑定邮箱且系统确实已配置邮件服务时才强制跳转。未配置 SMTP 时不以未绑邮箱为由拦截,否则新建学校在配好邮件服务之前,全校管理员会被困在无法完成的绑定页上。

密码存储

  • 统一使用 BCrypt(bcryptjs)哈希,带随机盐,不可逆。
  • 不存储明文,也不使用 md5、sha1 等弱哈希。

会话管理

  • 会话基于 nuxt-auth-utils 的密封票据(iron-webcrypto),不使用自签 JWT。
  • Cookie 安全标志显式声明,不依赖框架默认值:
    • httpOnly: true:前端 JS 不可读,缓解 XSS 窃取会话;
    • secure: true(生产环境):仅通过 HTTPS 传输;
    • sameSite: 'lax':缓解 CSRF,跨站 POST 不携带 Cookie;
    • path: '/'。
  • 会话有效期 7 天,同时作为 Cookie 的 expires 与票据 TTL,到期需重新登录。

启动期安全守卫(v0.3.2 新增)

  • 会话密钥是密封票据的唯一完整性来源。如果密钥可预测,例如沿用代码中的示例值,攻击者可以离线伪造任意 super_admin 会话,绕过全部鉴权。
  • server/plugins/00.security-guard.ts 在 Nitro 启动阶段审计会话密钥,检查四项:是否为空、长度是否小于 32 字符、是否命中已知示例或默认密钥黑名单、字符种类是否少于 8(随机性不足)。
  • 生产环境下校验不通过时执行三步处理:打印带修复指引的错误信息;注册请求级 503 兜底,避免宿主吞掉启动异常后仍以不安全配置对外服务;抛出异常使进程退出。
  • 开发环境仅告警不阻断,nuxt-auth-utils 会自动生成随机密钥并写入 .env。

登录失败限流(v0.3.2 新增)

  • 登录接口原本对失败次数没有约束,学生默认口令 123456 与管理员 6 位弱口令都可能被短时间爆破。
  • 采用双桶策略:
    • 账号桶:同一账号 10 分钟内失败 5 次,锁定 15 分钟,防止针对特定账号的爆破;
    • IP 桶:同一 IP 10 分钟内失败 40 次,锁定 10 分钟,防止撞库。
  • IP 桶阈值比账号桶宽松。学校网络普遍使用 NAT 共享出口,全校师生对外只有一个 IP,如果两个桶同样严格,一个人输错密码就会导致整校被锁。
  • 账号不存在、密码错误、验证码错误均计入失败次数,避免通过响应差异枚举账号是否存在。
  • 超限返回 429 并带 Retry-After 响应头。
  • 不同登录入口(admin-password / admin-email-code / student-password)独立计数,因为管理员与学生可能同名。
  • 已知取舍:限流状态存储在单进程内存中,PM2 cluster 多 worker 运行时实际阈值约为单 worker 阈值乘以 worker 数,横向扩容需要迁移到共享存储。

其它安全措施

  • 多角色权限中间件(middleware/auth.global.ts / student.ts / super-admin.ts)在路由层拦截越权访问。
  • 删除学生、删除班级、删除年级、删除积分记录等破坏性操作均需二次确认。
  • 前端渲染统一经 sanitizeHtml 白名单过滤,覆盖公告、邮件模板等。
  • 超级管理员可以免密登录任意管理员账号,用于线上排查问题。该能力仅超管可用,退出后需重新登录超管账号。

3.10 邮件通知

多服务与优先级故障转移

  • 主库 mail_services 表支持配置多个邮件服务,包括 QQ、163、Gmail、Outlook、阿里云和自定义 SMTP。
  • 每个服务带 priority(0 最高)与 enabled 开关。发送时按 priority 升序依次尝试,前一个失败自动降级到下一个。
  • 支持 none / ssl / tls 三种加密方式,端口与发件人(from_name / from_address)均可配置。
  • 提供连通性测试(`...
Read more

0.3.0-Pre-release

0.3.0-Pre-release Pre-release
Pre-release

Choose a tag to compare

@QianKunBoss QianKunBoss released this 24 Jun 14:46
32c3641

由单机系统转变为多极联动,多级合一,现进入公测状态。
可以使用文档的安装方法在大内网搭建。

首次支持多级分级管理

公测地址:https://csms.tianrld.top

v0.2.5

Choose a tag to compare

@QianKunBoss QianKunBoss released this 18 Apr 10:35
0aa221b

v0.2.5(最后一个个人使用版本,没有bug需要修的话)

  • 移除原本需要的QQ号码绑定
  • 完美适配CSMS-koishi插件认证
  • 优化token生成/处理策略(机器人绑定服务器后会重置token)
  • 允许记录被更改或删除(需要验证管理员密码)

v0.2.4

Choose a tag to compare

@QianKunBoss QianKunBoss released this 29 Mar 10:37
b134ab8

更新日志:

1、修复了已知Bug
2、新增_全局API(global_api.php),拥有更大的开发空间
3、新增
个性化定制,可更改配色、更改页面背景
4、新增
深色模式,适合夜间操作和查看
5、新增
系统功能优化_:

  • 迁移独立登录页面和密码重置页面(./admin.php → ./pages/admin.php | ./dengluye.php → ./pages/dengluye.php)
  • 新增安装前系统环境检测
  • 在设置页新增GitHub版本自动检查功能
  • 新增数据库在线备份
  • 优化新学期切换功能
  • 优化模态框显示图层

6、新增_数据库功能增强_:

  • 新增SQLite数据库支持(无需MySQL,开箱即用)
  • 新增QQ号码字段支持,便于记录学生联系方式,为后续QQ群机器人项目奠定了基础

请下载ClassScoreManageSystem-v0.2.4.zip

v0.2.3-Release

Choose a tag to compare

@QianKunBoss QianKunBoss released this 28 Dec 11:16
68f6cc5

更新日志:

1、修复了已知Bug
2、新增_座位表视图,便于选择和寻找
3、改善样式一致性
4、新增
数据仪表盘页面,用于显示综合信息
5、新增
平均分、最高分、最低分数据公示(可开关)
6、支持可添加多个管理员账号
7、支持用户
反选_
8、简化页面(添加用户和批量导入页面二合一页面),并且取消管理页主页删除用户按钮,移植至用户管理
9、数据导出直接支持xlsx表格导出
10、支持可自定记录时间

请下载ClassScoreManageSystem-v0.2.3.zip

v0.2.2-Release

Choose a tag to compare

@QianKunBoss QianKunBoss released this 21 Jun 07:02
ab59f64

新增内容:

  1. 修复已知bug
  2. 更换Boostrap CDN源
  3. 新增学期更换按钮(功能)

请下载score-system0.2.2.zip

v0.2.1-Release

Choose a tag to compare

@QianKunBoss QianKunBoss released this 31 May 05:37
aa2ae89

新增内容:

  1. 修复已知bug
  2. 新增开屏动画(可开关)
  3. 将管理员信息移植数据库存储
  4. 使用字体:HarmonyOS_Sans_SC_Black
  5. 文件目录规范化

请下载score-system0.2.1.zip

v0.2.0-Release

Choose a tag to compare

@QianKunBoss QianKunBoss released this 23 May 19:39
4cd0dcf

新增内容:

  1. 由于原本的手动安装对于某些人来说过于麻烦,所以直接更新出快速安装引导页

  2. 可开关主页显示内容,包括搜索栏是否显示、排行榜是否显示以及主页排行榜是否可以直接点击用户名访问用户详情

  3. 新增用户详情页排名显示

  4. 新增设置页面,以综合设置系统功能,除第二条以外,还可以修改管理员用户名和登录密码、导航栏标题、标签页标题。

  5. 新增初始图标_(自认为很垃圾)_

请下载score-system0.2.0.zip

Release 0.1.2

Choose a tag to compare

@QianKunBoss QianKunBoss released this 09 May 10:36
4c4ed3f

新增功能:
1、预设模板
2、当日日志查询

bug修复:
有bug吗?
包有的老弟!
(来人帮我试试呗,有的请提issue^V^)

如果不想要仓库中无用文件的可以下载score_system.zip压缩包
环境请自行搭建

Release v0.1.1

Choose a tag to compare

@QianKunBoss QianKunBoss released this 25 Apr 10:35
7665938

新增功能:
1、密码验证
2、批量名单导入
3、csv表格数据导出

bug修复:
有bug吗?
包有的老弟!
(来人帮我试试呗,有的请提issue^V^)