ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

基于SpringBoot+Vue的高校物品捐赠管理系统设计与部署实战

基于SpringBoot+Vue的高校物品捐赠管理系统设计与部署实战 高校物品捐赠管理系统听起来像是个课程设计或者毕设题目但真正动手做过的人才知道这个“小系统”背后踩的坑一点都不少尤其是前后端分离这套东西稍不留神就变成“前后端各写各的接口对不上”的翻车现场。我最近把这一整套SpringBoot Vue MyBatis MySQL的捐赠管理系统完整跑通并部署上线了从需求拆解、表结构设计、接口联调到打包部署整个过程走了不少弯路也积累了一些心得。这篇就把完整的设计思路、核心代码、部署过程和避坑经验一次性写清楚给正在做同类项目或者打算用前后端分离架构练手的同学一个可以直接参考的完整方案。这套系统的核心场景很简单高校里经常有毕业生捐书捐物、社团活动需要物资流转、实验室设备闲置需要调剂过去全靠辅导员在群里发通知、人工登记效率低还容易漏。捐赠管理系统的价值就是把“捐赠—入库—领用—归还—统计”这条链路线上化让管理员能审核、让捐赠人能追踪、让领用有记录。适合的人群也很明确正在做SpringBoot和Vue整合项目的学生开发者、想快速搭一套管理系统的外包型开发者以及需要一套轻量级资产管理方案的校内组织。1. 项目整体设计与需求拆解1.1 高校捐赠场景的核心痛点高校物品捐赠和一般电商系统最大的区别在于物品是单向或半单向流动的而且生命周期很长。一本书捐进来可能要在仓库放一学期然后被某个社团借走用完之后再还回来中间还可能出现损坏、丢失、调剂给其他部门等状态变化。普通管理系统只盯着“入库出库”两个节点根本不够用。所以我在设计这套系统时第一个动作不是写代码而是把所有可能的物品状态全部列出来。最终定下来五态循环可捐赠、待审核、已入库、已领用、已归还。加上一个“已报废”作为兜底状态。每一个状态变化都要在流水表里留痕迹谁在什么时间把物品从什么状态改成了什么状态这条记录必须永久保留。这是很多自制系统容易忽略的点删库跑路不可怕可怕的是连追踪记录都没有。第二个痛点是角色权限。高校场景下至少有三类人系统管理员、捐赠人学生/教职工、领用方社团/实验室/部门。不同角色看到的界面和操作权限完全不一样。捐赠人只能提交物品信息、查看审核结果领用方只能申请领用已入库物品管理员则掌握全流程。这套权限模型要放到设计的最前面先定好角色再谈功能代码实现时用拦截器统一处理而不是散落在各个接口里。1.2 角色权限与业务流程设计整个系统我按照角色拆成三个端管理员端是重头戏。功能包括物品审核判断捐赠物品是否合格、入库登记、物资列表管理、领用审批、归还登记、报废操作、用户管理、捐赠流水查询、分类统计。这些功能汇总成一句话管理员掌握物资的完整生命周期。捐赠人端相对轻量。提交捐赠申请物品名称、分类、数量、新旧程度、捐赠人信息、查看审核进度、收到入库通知。这里要注意一个细节捐赠人提交的未必是实物直接到库很多学校是先在线上登记预约然后线下送到指定地点管理员验收后才生成入库单。所以代码里要把“捐赠申请”和“入库单”分开不能合并成一张表。领用方端更简单。浏览可领用物资、提交领用申请、按时归还登记。如果是社团借设备搞活动借出和归还之间可能还有延期需求所以要支持“申请延期”这个操作否则活动还没结束系统里就显示逾期了。业务流程上核心链路是捐赠人提交申请 - 管理员审核通过 - 物品入库 - 领用方申请领用 - 管理员审批 - 出库给领用方 - 归还登记 - 管理员确认入库。任何一个节点断了系统都会卡住。所以每个操作接口都要做状态校验不能允许越级跳转。比如物品还在“待审核”状态就直接被领用这在逻辑上是非法的接口层必须拦掉。1.3 为什么采用前后端分离说实话这类管理系统用传统的服务端渲染技术也能做JSP加Servlet照样能跑甚至开发速度更快。但前后端分离的价值在后期维护和二次开发上体现得非常明显。分离开之后后端只负责提供RESTful接口前端只负责页面渲染两边可以并行开发。比如后端还在调试捐赠申请的接口前端就已经在用Mock数据画页面了。我这次实际开发中感触最深的一点是前端页面改了十七八遍后端接口一个都没动。如果放在传统单体项目里改个前端样式可能烦到想摔键盘放在前后端分离的项目里重新构建一下前端就完事了。另一个现实理由是团队协作。高校里做这类项目通常是两三个人分工一个管数据库和后端逻辑一个管页面。前后端分离意味着彼此不用在同一个代码库里互相踩踏只要把接口文档约定清楚Git冲突都能少很多。再加上SpringBoot天然适合做纯接口服务Vue在构建富交互页面时体验极好这个组合用起来顺畅。2. 技术选型与核心架构解析2.1 后端组合SpringBoot MyBatis 为什么这么搭SpringBoot在这个项目里的角色是“地基”负责接管HTTP请求、做参数校验、权限拦截、业务编排。它的自动配置机制让我不用像Spring时代那样写一大堆XML配置文件起步特别快。而且内嵌Tomcat让部署变得极其简单一个java -jar就能跑起来不用再单独装Servlet容器。MyBatis的核心价值则体现在SQL控制力上。捐赠管理系统虽然业务逻辑不复杂但查询场景非常多样按分类查、按状态查、按时间段查、按捐赠人查还有各种条件的组合。MyBatis允许我直接写SQL遇到复杂查询时脑子里怎么想的SQL代码里就能怎么写不会像JPA那样容易生成一堆低效的查询。而且它有个特别实用的功能——动态SQL类似 标签这种可以根据传入参数动态拼接WHERE条件完美适配“字段可选”的筛选场景。那为什么不选MyBatis-Plus而用原生MyBatis我的思路是这样的如果是开发生产级项目MyBatis-Plus的效率确实高内置的单表CRUD方法几乎不用写SQL。但这个项目本质上是个学习型项目用原生MyBatis能让人真正理解SQL是怎么写的、Mapper接口和XML是怎么映射的、分页是怎么实现的。把底层搞清楚之后再切换到MyBatis-Plus的成本非常低。所以我在这里选择了能看到更多细节的原生方案。2.2 前端架构Vue的路由、状态管理与组件划分前端技术栈是Vue 2如果是新项目建议直接上Vue 3但如果参考的源码是基于Vue 2的保持版本一致能少踩很多坑配合Vue Router做路由管理、Axios发请求、Element-UI做UI组件库。这套组合是国内管理后台的“国民组合”资料多、坑少、见效快。路由设计上我采用了两层结构登录页是一层登录成功后的主布局是一层。主布局里面套着嵌套路由管理员端的物资管理、审核管理、用户管理、统计看板捐赠人端的我的申请、提交捐赠领用方的物资大厅、我的领用。嵌套路由的好处是侧边导航栏和顶部栏不用每个页面重复写只需要在布局组件里写一次。Axios封装是最容易忽视的重头戏。我在项目里统一封装了一个request工具类做了三件最关键的事统一把登录接口返回的token附加到请求头统一拦截所有HTTP错误码并给出提示统一处理未登录状态下的重定向。这一步如果做不好后面联调时每一次401都要手动跳转一次登录页非常崩溃。组件划分的思路是按“页面组件 复用组件”两个维度来的。页面组件就是路由对应的视图比如DonationList.vue、AuditPanel.vue这些复用组件则包括UploadImage.vue图片上传、StatusTag.vue状态标签显示、PaginationTable.vue封装了分页逻辑的表格。我把分页表格封装成复用组件后几个管理页面每页至少省了读代码的几秒钟更重要的是保证所有列表页的分页交互一致不会出现一个页面翻页正常、另一个页面翻页失效的情况。2.3 MySQL表结构设计要点数据库设计是整个系统的灵魂我在表结构上花的时间比写前后端代码加起来还多。核心表一共六张外加一张流水表用户表sys_user存账号、密码BCrypt加密后的密文、角色、姓名、学号/工号、联系方式、所属学院或部门。物品表donation_item存物品名称、分类、描述、数量、新旧程度、图片路径、当前状态、入库时间。注意这里的设计是“物品”和“捐赠申请”不混在一张表里物品表只管物品本身谁捐的、什么时候申请的用外键关联到申请单。捐赠申请表donation_application存捐赠人ID、物品ID、捐赠意向描述、审核状态、审核意见、审核时间。领用申请表borrow_application存领用方ID、物品ID、领用数量、预计归还时间、实际归还时间、审批状态。流水表item_flow_log是状态追踪的关键每条记录包含物品ID、操作人ID、操作类型捐赠/审核/入库/领用/归还/报废、从哪个状态变到哪个状态、备注。字典表sys_dict存物品种类、学院列表这些可枚举的数据。之前有一个版本把分类直接写死在代码里后来发现加一个新分类就得改代码重新打包换成字典表之后管理界面直接能增删分类运营效率高得多。外键关联我是故意没在MySQL层面加的。教务系统、社团系统对接进来之后如果硬加外键会有很多锁表风险而且删除数据的灵活性也没有了。要保持数据正确性靠的是应用层的逻辑约束和定时对账脚本。3. 核心功能模块的实现细节3.1 登录鉴权与请求拦截的实现登录逻辑用的是JWT方案。用户输入账号密码后端校验通过后生成一个带过期时间的token返回给前端。前端把token存到localStorage里之后每次请求都在拦截器里加到Authorization头。后端这边用拦截器统一解析token把用户ID和角色信息塞进ThreadLocal或请求上下文里业务接口直接从中获取当前操作人。核心代码如下这段是后端拦截器的骨架public class JwtInterceptor implements HandlerInterceptor { Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 放行登录接口 if (request.getRequestURI().contains(/login)) { return true; } String token request.getHeader(Authorization); if (token null || token.isEmpty()) { throw new BusinessException(未登录或登录已过期); } // 解析token需要引入jwt依赖 Claims claims JwtUtil.parseToken(token); // 将用户信息存入上下文 UserContext.set(claims); return true; } Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { // 请求结束后清理上下文防止线程池复用导致数据串号 UserContext.clear(); } }比较容易被忽略的是afterCompletion里清理上下文那一步。Tomcat多线程环境下线程会被复用如果不清理ThreadLocal下一笔请求可能会读到上一个请求的用户信息这种bug查起来极其隐蔽而且偶发必须从根上解决。前端Axios拦截器对应的逻辑是这样处理的// request拦截器附加token axios.interceptors.request.use(config { const token localStorage.getItem(token); if (token) { config.headers[Authorization] token; } return config; }); // response拦截器统一处理错误 axios.interceptors.response.use( response response.data, error { if (error.response error.response.status 401) { localStorage.removeItem(token); router.push(/login); // 这里只做跳转不用提示因为用户大概率知道是登录过期了 } else { ElementUI.Message.error(error.response?.data?.message || 请求失败); } return Promise.reject(error); } );这里有个经验心得不要每一个接口都手动调一次localhost写基础路径要在axios的baseURL里统一配置并且按环境变量区分开发和生产环境。我之前有段时间把请求路径硬编码在代码里结果部署到服务器上联调时找了一个上午才发现是IP地址拼错了这种低级错误一次就够。3.2 捐赠申请与审核流程的实现捐赠流程的代码实现重点是状态机的严格控制。捐赠人提交申请时系统把捐赠申请表初始化为“待审核”然后插入一条物品表的草稿记录状态也置为“待审核”。管理员审核通过时后端要在一个事务里完成三个操作更新申请状态为“已通过”、更新物品状态为“已入库”、写入流水日志。这三个操作中间任何一个失败整体回滚保证数据一致性。审核不通过时逻辑稍微不同。因为物品并没有真正进入仓库所以物品记录可以直接删除或置为无效状态把审核意见回填到申请单上让捐赠人看到被打回的原因。这里有个细节不要用物理删除要用逻辑删除加一个deleted字段原因很简单——如果有一天需要追溯某个捐赠人的历史记录物理删除会让数据彻底丢失。事务控制方面我用了Transactional注解。但在配置时需要特别注意一个问题事务默认只对RuntimeException回滚如果代码里catch住了异常不重新抛出事务根本不会生效。我踩过这个坑花了两个多小时最后发现是一个try-catch吞掉了异常导致部分数据入库了但状态没更新。正确姿势是事务范围内要么不catch要么catch之后重新抛出运行时异常。3.3 领用归还与逾期预警机制领用流程比捐赠更复杂一点因为涉及数量核对和归还时间管理。领用方提交申请时带上预计归还时间管理员审批通过后物品状态变为“已领用”同时后台开启一个定时任务每天扫描一次所有已领用的记录对比预计归还时间和当前日期超过就自动发站内信通知领用方同时把逾期状态标记到管理端看板。这里我介绍一下定时任务的核心实现用的是Spring自带的Scheduled注解Component public class BorrowExpireTask { Autowired private BorrowApplicationMapper borrowApplicationMapper; // 每天凌晨1点执行一次 Scheduled(cron 0 0 1 * * ?) public void checkExpire() { ListBorrowApplication overdueList borrowApplicationMapper.selectOverdue(new Date()); for (BorrowApplication borrow : overdueList) { // 标记逾期 borrowApplicationMapper.markOverdue(borrow.getId()); // 发送站内通知 notifyService.sendMessage(borrow.getUserId(), 您借用的物品已逾期请尽快归还或申请延期); } } }归还登记时同样要校验状态必须是“已领用”状态才能归还归还之后管理员确认物品完好再置为“已入库”。如果归还时发现破损就走“维修”或“报废”分支。这套逻辑里最值得分享的一点是不要试图把归还操作写得“智能”就老老实实让管理员手动确认宁可多一步操作也不要让系统自动判断物品是否完好。自动判断需要引入图片识别或者人工标注在高校场景里运维成本太高。3.4 数据统计与看板展示管理端看板我做了三个维度的统计捐赠趋势按月份统计捐赠数量、类别分布当前库存物品的分类占比、状态总览待审核/已入库/已领用/已归还各有多少。前端用ECharts画图后端提供统计接口。统计接口的SQL是这类功能的核心。按月份统计的接口思路是这样select idcountByMonth resultTypemap SELECT DATE_FORMAT(create_time, %Y-%m) AS month, COUNT(*) AS total FROM donation_application WHERE audit_status approved GROUP BY DATE_FORMAT(create_time, %Y-%m) ORDER BY month DESC LIMIT 12 /select这样前端拿到的就是最近12个月的月度捐赠数据直接塞给ECharts的柱状图即可。类别分布就简单多了按category_id分组计数因为字典表里有分类名所以联查一下就能输出中文字段。统计接口的性能优化这块我当时用的数据量还比较小几千条记录MySQL毫无压力。但如果数据量起来一定要给create_time和status这两个字段加复合索引否则GROUP BY和WHERE的性能会随着数据量增长快速恶化。这是我后来反思表结构时觉得应该提前做的优化点。4. 完整部署流程与配置说明4.1 环境准备三件套部署前要准备好三个基础环境JDK8或11都行我用的8、MySQL5.7或8.0、Node.js前端构建用Vue 2项目建议用14或16版本太高版本反而可能出现依赖兼容问题。服务器我用的是一台Linux云主机2核4G的配置跑这个项目完全够用。本地开发环境是Windows所以部署手册里我同时写了Windows和Linux两个版本的安装步骤。MySQL这边最容易出问题的是初始密码和远程访问权限。安装完MySQL后第一步就要改root密码然后设置允许远程连接否则后端跑在本机、数据库在服务器上时根本连不上。这里给出后端连接数据库的配置参考server: port: 8080 spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/donation_system?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/ShanghaiuseSSLfalse username: root password: yourpassword连接串里面那三个参数缺一不可serverTimezoneAsia/Shanghai解决时区问题不然会差8个小时useSSLfalse避免连接时做SSL握手导致慢且报错characterEncodingutf8保证中文不乱码。这三个参数我可以说是血泪教训第一次部署时漏了时区参数所有时间字段显示都跟实际差了8小时排查了半天才找到原因。4.2 后端打包与部署后端打包用Maven直接执行mvn clean package -DskipTests打包完成后在target目录下会生成一个jar文件。如果项目分模块就把启动模块的jar拿过来用。部署时用nohup命令让进程在后台持续运行nohup java -jar donation-server.jar --spring.profiles.activeprod app.log 21 我为什么单独强调--spring.profiles.activeprod这个参数因为开发环境的数据库密码、日志级别、接口地址跟生产环境大概率不一样前端把环境配置放在.env.development和.env.production里后端也做同样的区分。把不同环境的配置拆到application-dev.yml和application-prod.yml里部署指定环境避免手动改配置出错。这里有部署经验的提醒jar包进程挂在后台后要检查它确实是活着而不是启动了立刻崩了。用jps命令看Java进程在不在再用tail -f app.log看启动日志重点看Tomcat started on port这一行。如果没有这行说明启动有问题此时先不要看业务代码问题先看报错里的Caused by部分90%的情况是数据库连不上、端口被占、或者缺少某个配置项。4.3 前端构建与部署前端构建前要确认环境配置正确。项目根目录的.env.production文件内容大概是这样NODE_ENVproduction VUE_APP_BASE_APIhttp://your-server-ip:8080/api这个VUE_APP_BASE_API就是Axios的baseURL来源在代码里用process.env.VUE_APP_BASE_API读取。部署到服务器后这里必须写服务器的公网IP或域名不能写localhost否则浏览器访问页面时请求会发到用户自己的电脑上直接404。确认配置后执行npm install npm run build构建完成后dist目录里就是纯静态文件。把这些文件部署到Nginx的html目录下。Nginx配置里需要做两件事一是将根路径指向dist目录二是将/api开头的请求反向代理到后端8080端口。这一步是前后端分离部署的最关键环节配置参考如下server { listen 80; server_name your-domain-or-ip; # 前端静态资源 location / { root /usr/share/nginx/html; index index.html; # 很重要刷新页面时不会404 try_files $uri $uri/ /index.html; } # API反向代理 location /api/ { proxy_pass http://127.0.0.1:8080/api/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } }其中的try_files我必须要重点说明。这是前后端分离项目部署中最常见的坑不配置try_files时用户访问某个路由比如/donation/list刷新一下页面Nginx会直接报404因为服务器上根本没有这个物理目录。配置了try_files $uri $uri/ /index.html之后Nginx会在找不到对应文件时回退到index.html由前端路由接管页面就能正常显示了。做前端项目部署没配置这一行的基本都会遇到刷新白屏。给前端配置反向代理而不是让前端直接请求8080端口的理由也很清晰一是避免跨域问题同源请求根本不需要处理CORS二是隐藏后端真实端口减少暴露面三是后期做HTTPS证书时只需要在Nginx层配置一次就好。4.4 本地快速运行验证在本地开发时我不建议把前后端构建产物混在一起跑而是用两个开发服务器并行后端用SpringBoot内置Tomcat跑在8080端口前端用Vue CLI的devServer跑在8081端口然后通过devServer的代理把接口转发到8080。Vue.config.js里这样配置代理module.exports { devServer: { port: 8081, proxy: { /api: { target: http://localhost:8080, changeOrigin: true, pathRewrite: { ^/api: /api } } } } }这样前端的Axios请求都写在/api路径下开发环境被devServer代理到8080生产环境被Nginx代理到8080代码本身不需要改任何东西纯粹通过环境配置切换这才是前后端分离的正确工作姿势。本地验证部署是否成功的标准动作是我总结出来的先访问前端页面看能不能出来登录框再登录一个账号看能不能跳转到主界面然后创建一个捐赠申请看能否成功提交。三步走完核心链路基本通了一半。5. 常见问题与排查技巧实录5.1 启动阶段报错排查表这次部署过程中我把遇到过的问题和对应的解法整理成了一个速查表这些内容比教程正文更值钱是排错时真正能救命的东西。我自己在本地和服务器上踩过的坑按阶段来分集中在下面这几个环节现象可能原因排查方案后端启动成功但接口404接口路径写错或没加RequestMapping前缀看控制台日志中打印的Mapping列表跟请求路径核对前端能打开但登录报跨域没走代理直接请求了8080确认是否走/api前缀看浏览器Network里的请求完整URL前端调接口401token过期或没传Authorization头看localStorage里有没有token看请求头带没带MyBatis报Invalid bound statementMapper.xml没扫描到检查application.yml里mapper-locations路径确认xml文件在resources目录下数据库中中文乱码连接串没指定utf8或建表时用了latin1连接串加characterEncodingutf8检查表字符集刷新页面404Nginx没配try_files按上面的配置补上try_files5.2 MyBatis分页查询失效问题系统里所有列表都做了分页但我在第一次运行时就发现列表数据永远只能查出第一页的内容翻到第二页返回的还是第一页数据。我排查了很久才发现问题根源我用了简单的limit偏移量手动分页但是PageHelper没有配置正确。正确的PageHelper配置是这样的dependency groupIdcom.github.pagehelper/groupId artifactIdpagehelper-spring-boot-starter/artifactId version1.4.7/version /dependency然后代码里这样调用PageHelper.startPage(pageNum, pageSize); ListDonationItem list donationItemMapper.selectByCondition(condition); PageInfoDonationItem pageInfo new PageInfo(list);关键用法是PageHelper.startPage()必须在Mapper查询语句之前且紧挨着中间不能插入其他数据库操作否则分页参数会应用到错误的SQL上导致数据对不上。还有一个相关的问题是返回字段对不上。前端期望的数据结构是{ list: [], total: 100 }但后端返回PageInfo之后前端读取的是records字段两边对不上。我的处理方式是做一个统一响应包装类把分页数据统一封装成下面这个结构再返回给前端public class PageResultT { private ListT list; private long total; private int pageNum; private int pageSize; }定好接口协议后前端再也不用关心后端用了什么分页插件拿到的永远是这个结构。5.3 MySQL连接失败的细节坑MySQL连接失败是另一个反复出现的坑。我遇到过的报错主要有两种第一种是好长一段英文里带Access denied for user这是用户名密码不对或者该用户没有远程访问权限。处理方式是进入MySQL执行授权GRANT ALL PRIVILEGES ON donation_system.* TO root% IDENTIFIED BY password; FLUSH PRIVILEGES;第二种是Cant connect to MySQL server on localhost这种情况通常是MySQL服务本身没启动或者绑定的IP不对。Linux下检查命令systemctl status mysqld如果服务没起来执行systemctl start mysqld拉起来。如果服务起来了还连不上检查my.cnf配置文件里的bind-address如果写的是127.0.0.1则只会监听本机回环地址远程连接会被直接拒绝。改成0.0.0.0然后重启MySQL。关于数据库连接这块我还想分享一个容易忽略的细节不要用root账号跑生产环境。我开发时图省事一直用root后来后端部署到服务器上觉得没什么问题。直到有天监控发现一个可疑连接才赶紧建了专用账号只给这个账号分配捐赠系统数据库的权限。养成安全意识越早越好。5.4 前端运行常见问题前端这边遇到的最多问题是npm安装依赖失败。这种问题在校园网络环境下很常见。解决思路是切换镜像源最多用npm淘宝镜像npm config set registry https://registry.npmmirror.com设置完镜像源之后再执行npm install速度能提升好几倍。如果还是安装失败优先检查Node.js版本。Vue 2项目在Node 17以上版本经常遇到OpenSSL错误报错信息为error:0308010C:digital envelope routines::unsupported。这时不要慌两个解法一是把Node版本降到16这个问题尤其常见二是给Node加openssl-legacy-provider参数。前端组件层面还有一个我记忆深刻的bugElement-UI的表格在重新加载数据后明明数据变了但表格显示还是老数据。后来发现是没给el-table的每一列设置唯一的key值Vue的虚拟DOM diff时找不到对应的行就复用了旧节点。解决办法是给数据增加一个唯一的id字段并在表格列绑定上key重新渲染就正常了。6. 经验总结与可扩展方向做完整套系统我最大的体会有这么几点第一先画状态机再写代码。物品的状态流转是整个系统最核心的约束把这个理清楚了接口设计和表结构设计会顺利很多。我一开始先写代码后补状态代码里各种杂乱的if-else判断逻辑混乱还容易漏后来静下心把状态图画出来代码结构完全重写了一遍顺畅太多。第二接口文档是前后端协作的生命线。我们项目里前后端基本是并行开发的靠的就是一份在线接口文档。每个接口的路径、请求参数、返回结构、错误码都写清楚前端自己Mock数据后端自己调接口。没有文档做约束联调阶段一定会有双方各自为政的局面。第三日志记录不嫌多。我开发时习惯在每个关键操作捐赠申请提交、审核、领用、归还里都打了操作日志后期排查问题时基本可以还原整条时间线。像审核意见、未通过原因这些都要记录完整不能只存一个状态字段。等到系统上线后有人问“为什么我的捐赠被拒了”你把日志一拉就能说清楚。关于可扩展的方向这套系统的架构留了很好的延展空间。如果学校要求对接统一身份认证只需在登录逻辑里增加一个认证接口的适配层如果想让捐赠全流程可追踪也可以在现有流水表基础上增加二维码或条码功能每件入库物品打印一个唯一编码扫码即可查看历史轨迹如果后续数据量变大需要做数据可视化大屏现有统计接口已经预留了维度直接扩展前端即可。最后说一句实在话这类管理系统编程技术上并不算高深真正拉开差距的是对业务的理解深度和对细节的用心程度。做好表结构设计再琢磨透状态机这套系统的骨架和核心逻辑就立住了前端页面和技术文档只是锦上添花的部分。希望这篇实操笔记能让正在做同类项目的你少走几步弯路。
返回列表