校园报修管理系统
提供故障报修、维修派单、进度跟踪、评价反馈等功能,面向师生和维修人员,管理员可分配任务和统计报表,采用Flask+MySQL,支持图片上传。
版本
v1 · done
需求
58 条
文件
2211 个 · 72 MB
公开时间
2026/6/22 11:01:54
更新时间
2026/6/22 17:40:06
需求树
58 条用户认证与权限
管理登录、注册、Token、密码找回及按角色路由分流,覆盖学生/教师/维修人员/管理员四类用户的身份认证与权限校验。
登录表单
学号/工号输入框 + 密码输入框 + 图形验证码(4位字母数字,点击刷新);前端校验非空,错误时 inline 红色提示;提交后 loading 态按钮禁用;按账号锁定(与 IP 无关):同一 user_id 连续 3 次密码错误触发 15 分钟锁定,Redis key=login_lock:{user_id},锁定期间返回 429 并提示剩余秒数。
JWT 登录 API
POST /api/auth/login,入参 {user_id, password, captcha_id, captcha_text},出参 {access_token(2h), refresh_token(7d), role, user_name};错误码 401(账号或密码错误)、403(账号已禁用)、429(触发锁定)。验证码从 Redis 按 captcha_id 读取并一次性消费,校验不通过返回 400「验证码错误」。
按角色路由分流
登录成功后:学生/教师角色跳转至报修首页 /repairs;维修人员跳转至工单列表 /tasks;管理员跳转至仪表盘 /dashboard。前端路由守卫校验 token 存在且角色匹配目标页。
Token 刷新接口
POST /api/auth/refresh,入参 {refresh_token},出参新 {access_token, refresh_token} 并废弃旧 refresh_token;refresh_token 过期返回 401,前端跳转登录页并保留当前路由参数 redirect。
密码修改
表单含旧密码、新密码(≥8位含字母+数字)、确认新密码三字段;前端校验新密码强度与两次输入一致;PUT /api/auth/password,入参 {old_password, new_password},校验旧密码正确后更新,返回 200;旧密码错误返回 403。
找回密码(邮箱验证)
两步流程:1)输入学号/工号,系统向预留邮箱发送 6 位数字验证码(Redis 5min 有效,60s 内不可重发);2)输入验证码 + 新密码 + 确认密码,验证通过后重置。POST /api/auth/reset-password,入参 {user_id, code, new_password};前端显示「验证码已发送至 ***@***」提示。
用户注册
注册表单含学号/工号、姓名、手机号、邮箱、密码(≥8位含字母+数字)、确认密码;前端校验密码强度与两次一致性;POST /api/auth/register,入参 {user_id, name, phone, email, password},后端校验学号/工号唯一性(重复返回 409)、邮箱格式,注册成功自动分配学生角色并返回 201;注册后跳转登录页并 toast「注册成功,请登录」。
图形验证码生成 API
GET /api/auth/captcha,无需认证;后端生成 4 位字母数字混合验证码图片(120×40px,含干扰线),返回 {captcha_id(UUID), captcha_image(base64)};验证码明文存入 Redis,key=captcha:{captcha_id},TTL 5min;前端登录页加载时自动调用并渲染图片,点击图片刷新重新获取。
故障报修
报修提交、图片上传、我的报修列表与详情查看、取消报修,面向学生和教师用户。
报修表单
报修类型下拉(水电/门窗/网络/家具/电器/其他)、故障位置四级级联选择器(校区→楼栋→楼层→房号)、问题描述 textarea(20-200字实时计数)、图片上传区(复用 FR-REPORT-006 可复用图片上传组件,拖拽/点击,最多5张,单张≤10MB,格式jpg/png/webp,缩略图预览+删除按钮);提交后表单重置并 toast「报修提交成功」。
创建报修单 API
POST /api/repairs,Content-Type: application/json,入参 {category, building_id, room_id, description, image_urls[]}(图片先通过 /api/upload 上传拿到 url 再提交);后端自动生成流水号(格式 R+yyyyMMdd+4位序号)、关联当前用户、初始状态 pending;5min内相同用户+相同位置+相同描述去重提示 409;出参完整工单对象。
我的报修列表
表格列:工单号、类型标签(彩色)、状态标签(pending黄/assigned蓝/in_progress绿/awaiting_confirmation青/completed灰/cancelled红)、提交时间;顶部状态筛选 tabs(全部/待处理/处理中/待确认/已完成/已取消);分页 15 条/页;空态显示「暂无报修记录」插画+引导按钮。
报修详情侧滑面板
点击列表行右侧滑出面板(宽 480px),展示:工单号+状态标签、报修类型+位置、描述文字、图片网格(点击放大)、处理日志时间线(操作人+时间+状态变更+备注)、维修人员姓名电话;已完成工单底部显示评价入口按钮。
取消报修
仅 pending 状态工单行显示「取消」操作按钮;点击弹出确认对话框「确定取消该报修单吗?取消后不可恢复」;确认后 PUT /api/repairs/{id}/cancel,状态变更为 cancelled,写入操作日志并通知报修人;cancelled 工单不可恢复。(管理员端取消见 FR-DISPATCH-006)
可复用图片上传组件
全局可复用 Vue 组件,被报修表单(FR-REPORT-001)、完工回填(FR-TRACK-002)等多处引用。拖拽或点击触发文件选择;先调用 POST /api/upload 逐张上传,上传中显示百分比进度条;上传完成返回 {url, thumb_url} 存入组件内部数组;已上传图片以缩略图网格展示,hover 显示删除角标;支持 maxCount/maxSize/accept 参数化配置(报修表单:maxCount=5, maxSize=10MB, accept=jp(g|eg)|png|webp);超出限制时 toast 提示;上传失败显示红色感叹号+「重试」按钮;支持 jpg/png/webp 格式前端魔术字预校验。
维修派单
管理员视角的工单分配、维修人员选择、指派/改派,以及维修人员视角的待处理工单列表。
待分配工单池
管理员视图表格,展示所有 pending 状态工单;列:工单号、类型、位置、提交人、提交时间、已等待时长(超 2h 黄色标记);顶部筛选:报修类型下拉、楼栋下拉;支持复选框批量勾选;点击行展开快速预览描述和图片。
指派维修人员弹窗
选中一个或多个工单后点击「指派」,弹出维修人员选择器:搜索框(按姓名模糊搜索)+ 列表(姓名、当前负载工单数、技能标签);支持批量指派:选中 N 个 pending 工单 → 选择同一维修人员 → 确认后每个工单独立更新 assigned + 写入操作日志;toast「已指派 N 个工单给 XXX」。
指派 API
PUT /api/repairs/{id}/assign,入参 {maintainer_id};后端校验:工单状态必须为 pending(否则 409)、maintainer_id 必须存在且 role=maintainer(否则 400);成功更新状态 assigned + 写入操作日志(操作人、时间、动作);若并发指派同一工单,乐观锁 version 冲突返回 409。
维修人员工单列表
维修人员登录后默认展示分配给自己或自己接单的工单;顶部状态 tabs(待接单/处理中/待确认/已完成);每行显示工单号、类型、位置、提交时间、紧急标记(超时红色);点击进入工单详情可查看报修人姓名+手机号,方便联系确认位置;支持下拉刷新获取最新派单。
重新指派
管理员对 assigned 状态的工单可「改派」;操作时弹出维修人员选择器 + 改派原因输入框(必填,≤100字);确认后 PUT /api/repairs/{id}/reassign,入参 {maintainer_id, reason},原维修人员从工单移除,写入操作日志并通知新旧维修人员及报修人;in_progress 及之后状态不可改派。
管理员取消工单
管理员在工单详情或列表中对非 completed/cancelled 状态工单可点击「关闭工单」;弹出原因输入框(必填 ≤100字)+ 二次确认;确认后 PUT /api/repairs/{id}/cancel,状态变更为 cancelled,写入操作日志并站内信通知报修人;cancelled 工单不可恢复。(报修人端取消见 FR-REPORT-005)
进度跟踪
工单生命周期状态流转(接单→维修中→完工),处理日志时间线,催单与超时预警。
维修人员接单
assigned 状态工单详情底部显示蓝色「接单」按钮;点击后二次确认,确认后 PUT /api/repairs/{id}/accept,状态变为 in_progress,记录接单时间并写入操作日志;按钮变为「开始维修」并置灰不可重复点击。
维修完工回填
in_progress 状态工单详情底部显示「完成维修」按钮;点击进入完工表单:完工照片上传区(必填 1-3 张,调用 /api/upload 上传后提交 url)+ 维修备注 textarea(选填 ≤200字);提交后 PUT /api/repairs/{id}/complete,状态变为 awaiting_confirmation(而非直接 completed),记录完成时间并写入操作日志,通知报修人确认;toast 提示「已提交完工,等待报修人确认」并刷新列表。
处理日志时间线组件
垂直时间线 UI:每条记录左侧圆点+连线,右侧展示操作描述(如「张三提交报修」「管理员指派给李四」)、操作人姓名、精确到分钟的时间戳、备注信息(如有);当前状态圆点高亮,已完成节点绿色,取消节点灰色。
催单功能
pending 或 assigned 状态工单详情显示「催单」按钮;点击后 toast「已催单,维修人员将收到提醒」;同一工单同一用户 24h 内限催 1 次,超出返回 429 并提示「今日已催单,请耐心等待」;催单后管理员仪表盘该工单标记「已催」角标。
超时预警标记
工单 pending 超 2h 未分配:当前时间 − created_at > 2h 且状态仍为 pending → 行背景淡黄 +「超时未分配」标签;in_progress 超 24h 未完成:当前时间 − 状态变为 in_progress 的时间 > 24h 且状态仍为 in_progress → 行背景淡红 +「超时未完成」标签;awaiting_confirmation 不设超时预警(已有 72h 自动确认兜底,见 FR-TRACK-003);超时数据统一供 FR-STATS-001 仪表盘超时卡片消费;维修人员列表对应工单同样高亮。
维修人员拒单
assigned 状态工单详情底部显示「拒绝」按钮;点击弹出拒绝原因输入框(必填 ≤100字);确认后 PUT /api/repairs/{id}/reject,入参 {reason},工单回到 pending 状态,写入操作日志并站内信通知管理员;同一工单同一人不可重复拒绝。
报修人确认完工
维修人员提交完工后,工单进入 awaiting_confirmation 中间状态;报修人端工单详情底部显示「确认完成」绿色按钮和「有问题,重新打开」红色按钮;确认后 PUT /api/repairs/{id}/confirm → 状态变为 completed,写入操作日志,触发评价入口展示;重新打开后 PUT /api/repairs/{id}/reopen,入参 {reason ≤100字} → 状态回退至 in_progress,通知维修人员;若报修人 72h 内未操作,系统自动确认并标记「超时自动确认」。
评价反馈
完工后星级评分与文字评价,评价展示与维修人员评分聚合。
评价表单
5 星评分组件(hover 预览亮星、click 锁定评分);文字评价 textarea(选填 ≤100字,实时计数);仅 completed 状态(报修人已确认完工后)且当前用户为报修人时在详情面板底部显示评价入口;已评价工单显示已有评价内容且不可再评。
评价提交 API
POST /api/repairs/{id}/feedback,入参 {rating(1-5整数), comment(string, ≤100)};校验工单状态必须为 completed(否则 422)、当前用户必须为报修人(否则 403)、该工单未评价过(否则 409);写入评价记录并更新维修人员评分聚合。
评价展示
工单详情展示星级+文字评价;维修人员个人信息页展示累计平均分(精确到小数点后1位)+ 总评价数 + 最近 5 条评价列表(含工单简述、星级、评价时间)。
维修人员个人页
路径 /maintainer/:id,展示:头像、姓名、技能标签列表、累计完成工单数、平均评分(精确到小数点后 1 位)、好评率百分比;下方「最近评价」列表(含工单简述、星级、评价时间,最多 20 条,分页 10 条/页);管理员及报修人均可查看,维修人员本人可查看自己页面。
统计报表
管理员仪表盘(工单概览卡片+趋势图+分类饼图)、维修人员绩效表、报修热力图、Excel 导出。
管理员仪表盘
顶部统计卡片行:今日新增/待处理/处理中/已完成/超时工单 5 张卡片(数字+环比箭头),其中超时卡片数据源来自 FR-TRACK-006 超时预警标记规则,点击可筛选查看超时工单列表;下方近 7 天工单趋势折线图(X轴日期 Y轴数量,双线:新增 vs 完成);右侧报修类型饼图(含图例);所有图表加载时显示骨架占位,数据为空显示「暂无数据」。
维修人员绩效表
表格列:姓名、完成工单数、平均响应时间(仅计最终接单人的指派时间→接单时间间隔;若工单被改派,原被指派人记录一次"未响应"事件但不纳入平均计算)、平均评分、好评率;顶部时间范围选择器(今天/本周/本月/自定义日期区间);支持按完成数降序/评分降序排序;空态显示「所选时间范围内无数据」。
报修热力图
按楼栋统计报修量,以柱状图或色块矩阵展示;X轴楼栋名称,Y轴报修数量;支持切换时间范围;点击某楼栋柱可下钻查看该楼栋报修类型分布。
报表导出
仪表盘和绩效表页面提供「导出 Excel」按钮;点击后 GET /api/reports/export?type=repairs|performance&date_from=&date_to=,后端生成 .xlsx 文件流下载;导出含表头格式化和自动列宽;大数据量时分批写入防止 OOM。
系统管理
用户 CRUD、报修类型管理、楼栋房号树形管理、操作日志审计。
用户管理列表
表格列:学号/工号、姓名、角色(彩色标签)、手机号、状态(启用绿色/禁用灰色)、创建时间;顶部搜索框(按姓名/学号模糊)+ 角色筛选下拉;分页 20 条/页;操作列:编辑、启用/禁用开关。
新增/编辑用户表单
新增弹窗表单:学号/工号(后端唯一校验,重复 toast 提示)、姓名、角色下拉(学生/教师/维修人员/管理员)、手机号(11位校验)、初始密码(≥8位);编辑时学号/工号只读;提交 POST/PUT /api/users,校验失败字段红色 inline 提示。
用户启用/禁用开关
列表行内 Switch 开关组件;切换时 PUT /api/users/{id}/toggle-status;禁用用户无法登录(返回 403),已分配工单不受影响;切换成功后 toast「用户状态已更新」。
报修类型管理
表格展示类型名称、图标、排序号、状态(启用/停用);顶部「新增类型」按钮弹出表单(名称、图标选择、排序号);行内编辑和停用/启用;被工单引用的类型不可删除,仅可停用并 toast 提示原因。
楼栋房号管理
左侧树形结构:校区→楼栋→楼层→房号,支持展开/折叠;右键菜单新增/编辑/删除节点;删除节点时若有关联工单则禁止并提示;「批量导入」按钮支持上传 Excel(模板下载链接),校验后批量写入。
操作日志审计
表格展示:操作时间、操作人、IP 地址、操作类型(登录/指派/状态变更/用户变更)、目标对象、详情摘要;支持按操作类型筛选 + 时间范围过滤 + 操作人搜索;日志只读不可删除,支持按时间范围归档导出;分页 30 条/页。
字典查询 API
GET /api/dict/categories 返回启用中的报修类型列表 {id, name, icon};GET /api/dict/buildings?parent_id= 按父节点返回楼栋树子节点;均优先从 Redis 缓存读取,miss 时回源 MySQL;无需认证即可调用(登录页和报修表单使用)。
技术交付
数据库设计、缓存策略、文件上传服务、原型与 UI/UX 文档、消息通知机制。
MySQL 数据库设计
设计表结构:users(含 role 枚举、avg_rating DECIMAL(2,1) DEFAULT 0、total_feedbacks INT DEFAULT 0 冗余字段);repairs(含 status 枚举:pending/assigned/in_progress/awaiting_confirmation/completed/cancelled,version INT DEFAULT 0 乐观锁字段,每次 UPDATE 时 WHERE version=旧值 SET version=version+1);repair_logs(操作日志);feedbacks(评价);notifications(站内信);dict_categories(报修类型);dict_buildings(楼栋树形四级:校区→楼栋→楼层→房号,含 parent_id 自关联);迁移脚本使用 Flask-Migrate,初始数据种子含默认管理员账号 admin/admin123。
Redis 缓存策略
报修类型/楼栋字典缓存(hash 结构,1h TTL,更新时主动失效);图形验证码缓存(string,key=captcha:{captcha_id},5min TTL,验证后立即删除);登录失败计数(string,key=login_fail:{user_id},incr + expire 15min 滑动窗口,达 3 次设置锁定标记 key=login_lock:{user_id} TTL 900s);缓存不可用时降级直查 MySQL,日志告警。
图片上传服务
POST /api/upload 接收 multipart 图片,校验文件魔术字(jpg FF D8、png 89 50、webp 52 49)防伪造;上传后生成 200px 缩略图;存储路径按日期分目录;返回 {url, thumb_url};支持配置切换本地存储 / OSS;单文件限 10MB,返回 413 超限。
高保真原型 HTML
单文件 HTML + Tailwind CDN + Fake 数据,覆盖全部 UI 叶子页面:登录页、报修表单、我的报修列表、报修详情侧滑面板、管理员待分配工单池、指派弹窗、维修人员工单列表、完工回填表单、管理员仪表盘(含图表模拟)、用户管理、操作日志;每页面均含 loading 骨架屏 / 空数据插画 / 错误重试三态。
UI/UX 设计文档
Tailwind 设计 token(颜色/间距/圆角/阴影/字体)、组件清单(Button/Input/Select/Table/Modal/Drawer/Toast/Timeline/StarRating/Pagination/StatCard/Chart)、信息架构图、工单生命周期 mermaid 状态图、报修核心流程用户旅程图。
消息通知机制
站内信表 notifications(user_id、type、title、content、is_read、created_at)。通知触发全场景:①新报修提交→通知所有管理员;②新派单→通知被指派维修人员;③催单→通知当前维修人员+管理员;④状态变更(接单/拒单/完工/确认/重新打开)→通知报修人;⑤改派→通知新旧维修人员+报修人;⑥取消工单→通知报修人;⑦评价提交→通知被评维修人员。维修人员顶部导航栏 Bell 图标红点未读数(前端每 30s 轮询 GET /api/notifications/unread-count);点击 Bell 调用 GET /api/notifications?page=&size=20 拉取列表(按时间倒序),点击单条标记已读并跳转对应工单;预留微信公众号模板消息推送接口。
邮件发送服务
接入 Flask-Mail + SMTP(支持 QQ邮箱/Gmail/企业邮箱配置);提供 send_email(to, subject, body) 工具函数;密码找回验证码通过邮件发送(6位数字,5min 有效);发送失败重试 2 次并记录错误日志;支持异步发送避免阻塞请求。
API 权限中间件
Flask 请求钩子:解析 Authorization Bearer JWT → 提取 role 字段 → 与路由白名单比对。白名单规则:/api/admin/* 仅 admin;/api/repairs/assign|reassign 仅 admin;/api/repairs/accept|complete|reject 仅 maintainer;/api/repairs 提交仅 student/teacher;无权限返回 403 {error:"权限不足"};Token 过期返回 401 {error:"登录已过期"};未登录返回 401 {error:"请先登录"}。白名单放行:/api/auth/*、/api/dict/*、/api/upload(需登录但无角色限制)。