做台账管理系统已经是两三年前的活儿了,但这类项目到今天依然很典型——尤其是用 “SpringBoot + Vue” 这套组合来做。前阵子整理硬盘翻出一套完整的“基于SpringBoot+Vue的移动台账管理系统”的交付材料(源码 + 文档 + PPT),恰好有人问起这种全栈项目该怎么准备,索性把思路和实操梳理成一篇,供准备毕设、团队内部练手,或者想快速搭一套台账系统的人参考。
台账这东西,干过企业信息化的人都不陌生。资产管理、耗材领用、设备巡检、车辆使用、公文交接……但凡跟“记录”沾边的,基本都能叫台账。早年大家用 Excel 管理,一人一版,传来传去,改没改过都说不清,领导想看一眼某个部门的汇总,得等下班前的“数据接龙”。移动台账管理系统要解决的,就是让这些记录数据能随时随地录入、查询、审批和统计,而不是被锁在一台办公电脑的 Excel 表格里。我从头到尾拆一拆做这类项目的关键思路和落地细节。
1. 项目整体设计与思路拆解
1.1 选型逻辑:为什么偏偏是 SpringBoot + Vue
先聊选型。这套系统的后端用 SpringBoot,前端用 Vue,几乎成了近些年中小型管理系统的事实标准组合。
SpringBoot 选它的理由不用多讲:内置 Tomcat,不需要额外配置容器,起步依赖一把梭,一个mvn spring-boot:run就能跑起来。相比早期 Spring MVC 那套 XML 配置满天飞的时代,SpringBoot 把开发成本降了一个量级。对于台账这类以 CRUD 为核心、附带审批和统计的业务系统,它的稳定性、生态和招聘市场认知度都是最优解。用微服务?杀鸡用牛刀,运维成本反而会成为压垮小项目的最后一根稻草。
Vue 这边的理由也类似。它对比 React 更“温和”,模板语法接近 HTML,学习曲线缓,对于前端经验不那么深的开发者很友好。选 Vue 3 + Vite + Element Plus 而不是 Vue 2 + Element UI,原因很直白:新项目不要再碰旧技术栈。Vite 冷启动秒开,Element Plus 组件库对表单、表格、弹窗、分页这些后台管理场景覆盖完整,几乎不需要自己造轮子。唯一要留个心眼的是,Element Plus 的表格在移动端宽度不够时体验一般,这个问题会留到移动端适配那部分细说。
注意:如果在校生做课程设计或毕设,选这套技术栈还有一个隐藏优势——资料多、找参考容易。SpringBoot + Vue 的文档、社区答案、现成脚手架一抓一大把,遇到问题基本都能搜到解法,不至于卡死在冷门技术上。
1.2 台账系统区别于普通 CRUD 的地方在哪里
很多人把台账系统做成一个“增删改查全家桶”,技术上说没错,但这恰恰是项目做得“平”的原因。台账系统的核心不在 CRUD,而在这三点:
第一,台账类型多变。不同的业务场景,台账字段完全不一样。设备台账要型号、购置日期、保修期;车辆台账要车牌、驾驶人、里程数;物资台账要分类、库存量、供应商。如果为每类台账建一张表,系统会变成表和业务的堆砌。合理的做法是“模板化”,让管理员能自己创建台账类型,定义字段名、字段类型,用户录入时动态渲染表单。
第二,数据录入必须移动优先。维护台账的人往往不在电脑前。库管员在仓库里,巡检员在设备旁,外勤在客户现场。他们在现场掏出手机拍个照、填几个字段、提交一条台账记录,这才是“移动台账”四个字的真正意义。这意味着前端要主动适配窄屏,表单要精简,关键按钮要大,能拍照就别让用户传文件。
第三,数据有审核链路。台账不是日记本,改错了要能追溯。很多业务场景下,新增或修改一条记录需要经过复核、审批,最后入库归档。所以系统要设计审批流的状态机:待提交、审批中、已通过、已驳回。加上操作日志后,一条记录的整个生命周期都是透明可溯的。
想清楚这三点,系统的价值就立住了。别上来就闷头写代码,这三点是后面所有设计决策的“纲”。
1.3 模块拆分:先定边界,再谈实现
根据上面的思路,系统可以拆成这些模块:
- 登录认证模块:账号密码登录、验证码、Token 签发与鉴权
- 用户与权限模块:用户管理、角色管理、菜单权限分配
- 台账模板管理:台账类型定义、字段定义、模板启用/停用
- 台账数据管理:记录新增、编辑、删除、查询、批量导入导出
- 审批流模块:提交审批、审批通过/驳回、审批历史
- 数据统计模块:按台账类型、时间、部门维度统计
- 系统管理模块:操作日志、登录日志、数据字典
每个模块的业务边界清晰,再做页面和接口设计会顺很多。模块拆分的另一个好处是文档和 PPT 好写——每一章对应一个模块讲,评审的人看起来不费劲,你自己答辩也有条理。
2. 数据库设计与核心接口实现
2.1 表结构怎么设计才不返工
数据库设计是这种项目最容易返工的地方。下面这套是经过验证、能在模板化台账场景下稳定跑的表结构,表名和字段名做了通用化处理,照着建就行。
用户表、角色表、菜单权限表这些标准 RBAC 表的建法网上很多,不展开。重点看台账领域这几张表:
第一张是台账模板表。字段包括id、template_code(如 asset_device)、template_name、status、create_time等。模板表本身不存字段定义,字段定义单独存成一段 JSON 字符串放在模板表里,或者放一张字段表。建议用 JSON 字段存储,格式模仿如下:
[ {"field": "equipName", "label": "设备名称", "type": "input", "required": true}, {"field": "purchaseDate", "label": "购置日期", "type": "date", "required": true}, {"field": "amount", "label": "购置金额", "type": "number"}, {"field": "remark", "label": "备注", "type": "textarea"} ]这样做的好处是字段定义与数据存储解耦。新加一种台账,只需在配置界面点几下,不用改代码、改表。坏处是查询时没法用原生 SQL 在 JSON 字段里做复杂条件过滤,但台账场景的查询大多可以用数据库的 JSON 查询函数解决,完全够用。
第二张是台账数据表。主表叫台账记录表,字段包括id、template_id、record_code(记录编号,可用日期 + 序列号生成)、title(摘要)、content_data(JSON,存具体字段值)、status(0 草稿 / 1 审批中 / 2 已通过 / 3 已驳回)、create_user、create_time、approve_user、approve_time、approve_remark。再配一张台账附件表,存图片、文件路径,用record_id关联。
第三张是审批记录表。字段包括id、record_id、approve_user、approve_action(通过/驳回)、approve_remark、create_time。把所有审批历史留痕,后续追溯和审计都靠它。
注意:
content_data用 JSON 类型还是text类型?MySQL 5.7+ 有原生 JSON 类型,支持索引和部分查询函数,建议用 JSON。如果担心兼容性,用text也能跑,只是查询时没法利用 JSON 函数。
2.2 后端分层与关键实现
后端采用经典三层:Controller 负责接收参数和返回结果,Service 写业务逻辑,Mapper(用 MyBatis-Plus)处理数据访问。这套分层虽然朴素,但足够清晰,项目结构也符合多数人的阅读习惯。
几个关键实现值得单独说:
统一返回结果类。不要每个接口返回裸对象,定义一个Result<T>包装。前端可以统一判断code,省去一堆重复的容错代码。参考代码如下:
public class Result<T> { private Integer code; private String message; private T data; public static <T> Result<T> ok(T data) { Result<T> r = new Result<>(); r.code = 200; r.message = "success"; r.data = data; return r; } public static <T> Result<T> fail(Integer code, String message) { Result<T> r = new Result<>(); r.code = code; r.message = message; return r; } }全局异常处理。用@RestControllerAdvice拦截业务异常、参数校验异常、未知异常,封装成统一格式返回。这一步能避免“前端收到一个 500 的 HTML 页面”这种糟心情况。业务异常建议自定义一个BizException,带错误码和错误信息,Service 层直接抛出,由全局处理器统一兜底。
JWT 鉴权。登录成功后发一个 token,前端存到 localStorage,每次请求带在Authorization头里。后端写一个拦截器(HandlerInterceptor)或过滤器,校验 token 并解析出用户信息。启动时用拦截器排除白名单:登录接口、验证码接口、静态资源。
密码存储一定用 BCrypt。不要用 MD5——MD5 撞库太快了,随便一个彩虹表都能破。如果不引入 Spring Security,也能单独用 hutool 的BCrypt工具类做加密和校验。
分页查询。MyBatis-Plus 的Page对象配合分页插件,几行代码搞定。注意分页插件必须在配置类里注册,否则分页不生效,这个坑我踩过。
2.3 审批状态机的流转逻辑
审批模块的代码其实没什么高深的,核心就是状态机。用一个integer字段存状态,配合下面的状态流转:
| 状态值 | 含义 | 可执行操作 |
|---|---|---|
| 0 | 草稿 | 创建人可编辑、删除、提交审批 |
| 1 | 审批中 | 审批人可通过/驳回,创建人可撤回 |
| 2 | 已通过 | 数据正式生效,不可修改 |
| 3 | 已驳回 | 创建人可修改后重新提交 |
实现上就用 if 判断当前状态和用户角色,决定是否允许某种操作。更规范一点的可以引入状态机框架,但小项目没必要,反而显得过度设计。审批通过后的“生效”动作其实就是把记录状态改为 2,不需要真的复制一份数据,台账场景没有“快照”需求,别想复杂。
2.4 开放接口的权限校验
这部分容易被忽略,但非常关键。后端接口必须做权限校验,不能只靠前端路由守卫。前端隐藏菜单只是体验优化,后端要用拦截器按角色判断接口权限。否则懂技术的人绕过前端直接调接口就能越权操作。
实现方式不复杂:写一个权限注解@RequirePermission("ledger:record:approve"),用 Spring AOP 或拦截器校验当前用户是否拥有对应权限码。权限码定义成常量,配置在角色与菜单的关联表里。这样每个接口的权限声明是显式的,不会出现“谁能调谁不能调全靠猜”的情况。
3. 前端与移动端适配实现
3.1 前端技术栈与工程结构
前端技术栈建议 Vue3 + Vite + Element Plus + Pinia + Axios。工程结构上,src下按模块分目录:api(接口封装)、router(路由)、store(Pinia 状态)、layout(整体布局)、views(页面)、components(通用组件)。
页面主要分为:登录页、首页仪表盘、台账列表页、台账详情/编辑页、审批页、个人中心。路由配置需要配合登录态和权限做导航守卫:未登录跳/login,无权限跳 403。Pinia 存用户信息和登录状态,刷新后重新拉取接口恢复会话。
3.2 移动端适配的几个关键原则
移动端适配是最容易糊弄但也最能拉开差距的部分。
原则一:布局用响应式栅格,尽量不要单独写一套“移动端页面”。Element Plus 的el-col宽度可以跟随屏幕宽度变化,小屏时侧边栏自动隐藏,导航切换成底部 Tab 或汉堡菜单。
原则二:表格在手机上不好用。宽表会横向溢出,用户得左右滑动,体验极差。更好的做法是列表页在移动端用卡片布局:一张卡片显示一条记录的标题、关键字段、状态标签、操作按钮。实现方式不复杂,用 CSS 媒体查询或监听窗口宽度,在小于某个断点(比如 768px)时切换渲染模式。桌面端显示表格,移动端渲染卡片列表,用v-if切换两套模板结构。
卡片布局的细节要注意:卡片内只展示最重要的 2~3 个字段,其余信息放详情页,不要试图在大一屏里堆满所有内容。操作按钮做成图标加文字的样式,触控面积至少 44px × 44px,这是移动端交互的基础要求。
原则三:表单控件做“移动化”。日期选择器在手机上有原生 picker,用el-date-picker的时候可以加参数让它调起系统原生控件。图片上传用input[type=file]的capture="environment"属性,可以在手机上调起后置摄像头直接拍照。这些细节小程序和 App 司空见惯,但 Web 项目经常被忽略,做了就是加分项。
原则四:真机调试。开发时用电脑 Chrome 的移动模拟器只能看布局,真机上还要关注触摸反馈、字体大小、安全区域(iPhone 底部小黑条)。最简单的办法是让电脑和手机连同一个局域网,把 SpringBoot 的端口(默认 8080)和 Vite(默认 5173)都改为监听0.0.0.0,然后用手机浏览器访问电脑的局域网 IP。注意 Windows 防火墙要放行这两个端口,否则手机死活连不上。
3.3 图片上传与附件管理的细节
台账记录经常要带现场照片,比如设备铭牌、车辆剐蹭、物资到货验收。图片上传的路径规划要提前想好:按日期分目录存储,文件名为时间戳加随机串,避免重名覆盖。保存路径不要用绝对路径,配置一个upload.dir属性,开发环境指向本地目录,生产环境指向服务器挂载目录。
文件访问要写成静态资源映射,或者单独做一个“下载文件”接口,接口里做权限校验。不要直接把文件目录暴露成静态资源,否则未登录的人也能猜到 URL 下载全部附件。图片压缩也建议做一下,手机拍照一张 3MB 起步,不压缩的话列表页加载会卡成 PPT。
4. 从零跑通这套项目的实操记录
4.1 环境准备:版本踩坑点提前说
我用这套环境跑过 N 遍,最省心的组合如下:
- JDK 1.8(别用 17,除非代码里明确兼容;SpringBoot 2.7.x 对 JDK 8 最稳)
- Maven 3.6+ 或 3.8+
- Node.js 18+(Vite 5 需要 18+,直接上 Node 20 也行)
- MySQL 5.7 / 8.0(MySQL 8 注意驱动要配
com.mysql.cj.jdbc.Driver) - Redis 可以不用。台账系统用 JWT 的话不需要 session 共享,没必要引入 Redis 增加部署复杂度
4.2 导入与启动:五步走
第一步,创建数据库并导入。源码里一般有db.sql,直接用 Navicat 或命令行执行。导入时如果报错,优先检查字符集,sql 文件用 UTF-8,库字符集设置 utf8mb4。
第二步,改配置。后端application.yml里配数据库用户名密码。如果改了端口号,记得前端的代理配置也要同步。Vite 开发服务器的代理配置在vite.config.js的server.proxy里,后端接口前缀/api转发到http://localhost:8080。
第三步,启动后端。IDE 里直接跑main方法即可。启动过程中最常报的是端口被占用,用netstat -ano查一下,把占用端口的进程结束,或者改后端端口。
第四步,启动前端。npm install装依赖,npm run dev跑开发服务器。npm install如果报错,八成是 Node 版本太老或 registry 源的问题,换镜像源能解决一半问题。
第五步,访问。浏览器打开http://localhost:5173,管理员账号输入默认密码。如果打开白屏,先看 Console 有无 JS 报错;接口全部 404,检查代理配置和后端是否真的启动。
4.3 跑通核心业务闭环
建议拿到源码后,不要急着改代码,先把一个完整的业务闭环跑通,这样对系统的数据流向会非常清晰。
用管理员账号登录,进入台账模板管理,创建一个“设备台账”模板,字段定义为:设备名称(input)、购置日期(date)、金额(number)、备注(textarea)。保存后,模板状态改为启用。
注册一个普通用户角色,用这个用户登录。在台账数据管理页面,选择“设备台账”,新增一条记录,填写设备名称、购置日期、金额,保存。此时这条记录状态为 0(草稿)。点“提交审批”。
切回管理员账号(可以在另一个浏览器窗口登录,避免被强制下线),进入审批列表,看到这条待审批记录。点“通过”,填写审批意见。回到台账记录列表,发现记录状态变为 2(已通过)。
到这一步,核心业务闭环已经走通,对系统各模块的职责和相互依赖就有了直观理解。之后再去看代码,带着问题看,比盲目翻仓库有效率得多。
5. 文档和 PPT:怎么组织才是加分项
5.1 文档结构:项目文档不是说明书
很多人把文档写成“复制粘贴代码说明书”——每个类都贴一段代码,然后写“本类实现了 XXXX”。评委和导师翻两页就失去耐心。
真正加分的文档结构是这样:
第一章,绪论。写行业背景和管理痛点。重点突出“为什么需要移动台账系统”,至少交代两个真实场景:库管员仓库现场记录、审批人移动端审批。然后写国内外现状,不用写得很外交辞令,能说出“Excel 管理无法多人协作、无法移动填报、无法留痕”这三条就比空话强。
第二章,需求分析。功能需求用用例图 + 用例表呈现,非功能需求别漏了性能、安全、易用性。台账场景性能不用吹太高,支撑 500 并发足够;安全要写密码加密、操作日志、权限控制。
第三章,系统设计。放三张图:系统架构图(前后端分离架构)、功能模块图、数据库 E-R 图。这三张图是文档里最值钱的东西,一定要画清楚。架构图别画成“浏览器—SpringBoot—MySQL”这种三框流水账,应该包含前端、后端、拦截器、统一异常、数据库,尽量细化。
第四章,系统实现。这里不要贴大段代码,精选核心代码片段,配流程图说明思路。比如审批状态机的几个状态转移、JWT 拦截器的执行流程,每段代码 10~20 行足够,后面加两句话说明“为什么这样实现”。
第五章,系统测试。写功能测试用例表,覆盖登录、模板配置、记录增删改查、审批流、权限拦截这几个核心模块。加上简单的性能测试(并发 50 下发登录接口看响应时间),就比光写“测试全部通过”有说服力。
5.2 PPT:答辩演示时要讲“故事”而不是“目录”
PPT 控制在 10 页左右,结构和文档对应,但每页只说一个重点:
第 1 页:系统名称 + 一句话定位(“面向现场作业的移动台账管理平台”)。第 2 页:背景与痛点。用“旧方式 vs 新方式”的对比讲,不要念大段文字。第 3 页:系统功能总览,一张功能架构图。第 4 页:技术架构,一张图说明前后端、数据库、鉴权方式。第 5 页:核心业务流程时序图——从提交到审批入库。第 6 页:系统截图 2~3 张,选移动端界面截图最加分。第 7 页:核心代码片段 1~2 段,讲“难点怎么解决的”。第 8 页:测试结果摘要。第 9 页:总结与展望。第 10 页:Q&A。
答辩演示的核心就一句话:演示时先讲业务痛点和系统价值,再讲技术实现,最后做 Demo。千万别一上来就打开 IDEA 刷代码,评审最关心的不是你的代码写了几百行,而是你的系统解决了什么问题。
5.3 源码交付:README 写清楚三件事
源码交付不要只丢一个仓库地址,README 至少写三块内容:环境要求版本列表(JDK/Node/MySQL)、启动步骤(创建库、改配置、启动后端、启动前端)、默认账号和权限说明。我见过太多人源码拿到手,第一步就卡在数据库起不来,写得越详细,后续质疑“这个项目是不是跑不起来”的声音就越少。
6. 常见问题与排查技巧实录
6.1 启动与部署期高频问题
| 问题现象 | 排查顺序 | 处理办法 |
|---|---|---|
前端npm install一直报错 | 换源、删 node_modules、看 Node 版本 | 用镜像源;删除依赖目录重装 |
| 后端报数据库连接失败 | MySQL 服务状态、账号密码、驱动版本 | 检查 MySQL 是否启动;确认 URL 和驱动类名;加时区参数 |
| 前端访问接口跨域报错 | Vite proxy、后端 CORS、代理是否生效 | 开发环境用 Vite 代理,生产环境用 Nginx 反代 |
| 打好的 jar 包运行后静态资源 404 | 前端未打包进后端 | 将前端dist目录复制到后端resources/static,或单独部署前端 |
6.2 业务逻辑与权限的经典坑
Q:普通用户能访问管理员接口怎么办?
A:后端接口必须做权限校验,不能只靠前端路由守卫。前端隐藏菜单只是体验,后端要用拦截器按角色判断接口权限,否则懂技术的人绕过前端直接调接口就捅破天了。
Q:审批通过的记录还能编辑怎么办?
A:这是状态机没做好。后端修改接口里必须判断 status,只有 status 为 0(草稿)或 3(已驳回)的记录允许编辑;status 为 1(审批中)和 2(已通过)应拒绝修改。否则审批流程就是摆设。
Q:操作日志记不全?
A:可以在 Service 层统一记录,用一个自定义注解标记需要记录日志的方法,AOP 切面自动捕获用户、时间、操作类型、参数快照。不要在 Controller 里逐段手写日志代码,改一处漏一处。
6.3 移动端体验的几个真实经验
第一次在 iPhone Safari 上打开页面时,输入框点击会被放大,影响体验。解决方案是在 HTML head 里加 viewport meta:width=device-width, initial-scale=1.0。还有就是移动端点击事件有 300ms 延迟,现代浏览器一般自动消除,但加一句touch-action: manipulation的 CSS 更保险。
真机调试时如果手机访问不到电脑,90% 的原因不是代码问题,而是防火墙或网段隔离。公司或学校的 WiFi 经常做设备隔离,两个设备看似连同一个 WiFi,实际不通。这时候最简单的办法是手机开热点,电脑连手机热点,再访问。
7. 这套项目还能怎么扩展
如果做完基础功能还想往上走,几个扩展方向供参考:
一是接入工作流引擎。当审批链路变成多级(普通员工 → 主管 → 经理),手写状态机就开始吃力了,可以引入流程引擎。不过对多数毕设和内部小系统,单级审批完全够用,别过度设计。
二是增加导入导出能力。台账场景里 Excel 导入导出是刚需:导入用 POI 解析,导出用模板下载 + 数据填充。这个功能在工作汇报里非常显眼,因为它是“减轻用户工作量”的最好证明。
三是做数据可视化大屏。把台账记录按时间、部门、状态汇总成 ECharts 图表,投屏到办公室的电视上,能一下子让系统从“demo”变成“能汇报的系统”。实现不难,前端加两个图表组件,后端加几个统计接口。
四是考虑轻量离线能力。移动网络不稳定的场景,可以研究一下在本地暂存记录、网络恢复后自动同步的方案。这个方向工作量比较大,但做好了能称得上“创新点”。
我个人在实际操作中的体会是:这类全栈项目,最难的不是某个技术点,而是把“台账管理”这四个字的业务逻辑想透。技术栈大家都在用,能让你的系统区别于别人作品的,往往是你对业务流程的理解深度、对移动端体验的重视、以及文档里能不能讲清楚“为什么这样设计”。把这三点做扎实,源码 + 文档 + PPT 就是一个真正拿得出手的完整作品。
最后再分享一个小技巧:跑完项目后,用手机流量访问一次自己的系统,模拟一个最普通的现场用户——不会 F12、不懂接口、只看页面好不好用。如果手机上的体验能让你自己满意,这个项目就离优秀不远了。