基于微信小程序的办公用品管理系统设计与实现

发布时间:2026/10/22 21:07:09
基于微信小程序的办公用品管理系统设计与实现 最近刚完整做完一套“基于微信小程序的办公用品管理系统”的交付包含源码、文档、调试和讲解服务。这算是办公自动化类项目里很典型的一个方向也是很多在校生在课程设计或毕业设计中会碰到的选题。这个系统解决的核心问题特别实在公司或学校内部的办公用品申领以前靠纸质登记、Excel表格、口头报备流程混乱、库存对不上、谁领了多少也查不清。用小程序做前端员工直接用手机就能查库存、提交领用申请管理员在后台完成审批和库存管理整个流程清晰可控。这篇文章会把整个项目的设计思路、技术选型、核心代码、调试心得和文档讲解交付经验完整梳理一遍。适合正在做类似选题的同学也适合刚接触小程序开发、想了解一个完整项目如何落地的开发者。你会看到整个系统从业务分析到数据建模、从接口实现到真机调试的完整链路所有内容和代码都基于实际跑通的项目可以直接参考。1. 业务场景与功能设计拆解1.1 办公用品管理的核心痛点做系统前先把业务想清楚这是整个项目能不能让人信服的关键。办公用品管理看似简单实际上的痛点非常具体员工领笔、领纸、领文件夹以前要跑到行政那里说一声行政翻一下纸质台账或者Excel表格记录一下。如果公司有几十上百号人这种模式立刻暴露问题——台账记录不完整、实际库存和账面对不上、临时查看数量只能靠人工清点、月底统计消耗量要翻半天记录。我把这个业务拆成了三个核心诉求谁在什么时候领了什么用品、库存还剩多少、领用是否合规需要审批。围绕这三个诉求系统必须有清晰的用户身份边界也就是角色权限管理。员工可以提交领用申请、查看自己的申请记录管理员可以处理审批、管理用品库存、查看全公司领用数据。还有一个看板角色也可以考虑比如领导层只看统计数据但这在小项目里通常会并入管理员。1.2 功能模块与权限矩阵设计整个系统的功能可以用一张权限矩阵讲清楚功能模块普通员工管理员用品分类与列表浏览查看增加/删除/修改库存查询查看可用数量查看含预警状态领用申请提交/撤销审批/驳回领用记录查看自己的记录查看全量记录用户管理无添加/禁用账号数据统计无按月份/部门统计业务闭环是员工提交申请→管理员收到待审批请求→管理员同意后库存扣减→员工看到审批结果。这里有一个重要的设计点什么时候扣库存。有人会把库存扣减放在提交申请时但这样会导致申请被驳回时库存已经不对了。正确做法是扣减动作放在审批通过之后驳回或撤销时则不动库存。考虑到不同公司的实际诉求还可以加上“办公室地点”这个维度例如总部一楼有库房分部二楼有储位用品表里预留一个location字段标识存放位置领用时的出库位置就更准确。虽然这会增加一定的复杂度但对演示项目来说反而是个不错的加分点。1.3 页面流程与交互设计小程序端我规划了五个主要页面登录页、首页用品列表、用品详情页、申请记录页和个人中心。首页不能是简单列表要支持顶部按分类筛选同时把库存数量用明显颜色标识出来库存充足的显示正常色低于预警值的用红色提醒这样员工一看就知道哪些可以放心申请哪些可能没货。申请流程是用户从用品列表点进详情页看到规格、单位、当前库存数点击“申请领用”后填写数量和使用原因。这里要防止用户提交明显不合理的大数量前端要校验申请数量不能超过当前库存后端接口还要再做一次校验。双端校验是这类项目的基本功只做前端校验很容易被绕过。个人中心里展示当前登录用户的信息和申请记录列表。每一条记录用状态标识区分待审批、已通过、已驳回。已通过的可以查看审批时间已驳回的显示驳回原因。2. 技术选型与整体架构2.1 为什么选择微信小程序加后端服务的模式办公用品管理系统的实际使用场景决定了它的平台选择用户是公司内部员工需要用尽可能轻的方式访问。微信小程序天然满足这个需求——用户不用安装单独App打开微信就能用用完即走非常契合内部工具的使用习惯。小程序再搭配一套后端服务和数据库构成完整的前后端分离架构。有些同学在做这类项目时想用云开发把数据库和云函数都放在微信云托管上。这样确实省事不用搭建本地服务但存在两个问题一是云开发环境免费额度有限超出要付费二是如果用于课程设计或简历项目传统的前后端分离结构更能展示数据库设计能力和接口开发能力。所以我选择自建后端服务。2.2 后端框架与数据库设计方案后端我用的是Spring Boot加MyBatis Plus加MySQL的组合。Spring Boot是目前Java开发最主流的框架起步依赖很方便内置了Tomcat打包成Jar就可以直接部署。MyBatis Plus在MyBatis基础上做了增强单表CRUD几乎不用写SQL节省大量精力。MySQL是关系型数据库里最通用的适合存储结构化的业务数据。数据库设计了五张核心表user用户表包含openid、姓名、部门、角色等category用品分类表包含分类名称、排序material用品表包含名称、规格、单位、库存总量、库存预警值、所在位置、图片URL、是否启用apply_record申请记录表包含申请用户ID、关联用品ID、申请数量、申请原因、审批人ID、审批状态、审批意见、创建时间operation_log操作日志表记录关键操作这里要说一下openid的用法。用户第一次通过wx.login拿到code后端调用微信接口换取openid这是用户在微信体系里的唯一标识。openid要存在user表里下次登录时通过openid找到对应用户而用户名和密码这个传统方案的体验完全不同——员工不用注册直接进入系统系统自动根据openid识别身份。2.3 请求链路与技术要点小程序前端通过wx.request发起HTTP请求到后端接口后端统一接收后分发到不同Controller层。请求链路的顺序是请求进入网关项目里没有单独网关Spring Boot就是入口、经过Controller参数接收和统一响应包装、Service层处理业务逻辑、Mapper层访问数据库、结果返回前端。技术要点上有两个需要特别注意。第一是跨域问题小程序端请求域名必须是HTTPS协议才能在正式环境下使用但开发阶段可以在微信开发者工具里勾选“不校验合法域名、web-view业务域名、TLS版本以及HTTPS证书”这样本地调试就能用http协议加上局域网IP访问后端。第二是后端需要实现简单的token机制用户登录后后端生成一个随机token返回给前端前端把token存储在storage中后续每个请求都在header里带上token保证用户身份可识别。3. 核心模块实现与代码解析3.1 登录鉴权模块登录鉴权是整个系统的地基所有接口都要依赖当前用户身份。微信小程序的登录流程分三步前端调用wx.login获取临时code、后端根据code加appid和secret调用微信的接口换取openid和session_key、后端根据openid查询用户如果存在就生成token返回。这里需要看一次关键的代码逻辑。后端部分PostMapping(/login) public Result login(RequestBody LoginRequest request) { String code request.getCode(); // 调用微信接口凭证校验接口换取openid String openid authService.getOpenidByCode(code); if (openid null) { return Result.error(登录失败); } User user userService.findByOpenid(openid); if (user null) { // 新用户默认注册为普通员工角色 user userService.register(openid, request.getNickname()); } if (user.getStatus() 0) { return Result.error(账号已被禁用请联系管理员); } String token jwtUtil.generateToken(user.getId(), user.getRole()); return Result.success(token); }前端小程序对应部分wx.login({ success: async (res) { const code res.code; const loginRes await request.post(/api/login, { code }); if (loginRes.code 1) { wx.setStorageSync(token, loginRes.data.token); wx.setStorageSync(userInfo, loginRes.data.userInfo); } } });这一段里有个值得留意的点普通员工首次登录时应该自动注册不能因为没有账号就拒绝进入。管理员的账号则需要预先由系统初始化完成。我在项目初始化时写了一个数据脚本预置一个管理员账号并将第一次通过该账号登录的用户赋予管理员角色。这样做的好处是项目演示时不用额外注册多个账号再切换角色体验上很顺滑。3.2 用品列表与分类查询用品列表是员工最常访问的页面接口设计上要考虑分类筛选、分页加载和库存状态标识这三个能力。后端MyBatis Plus的QueryWrapper可以很方便地组合查询条件public PageResultMaterialDTO listMaterial(Long categoryId, Integer page, Integer size) { PageMaterial p new Page(page, size); LambdaQueryWrapperMaterial wrapper new LambdaQueryWrapper(); if (categoryId ! null categoryId 0) { wrapper.eq(Material::getCategoryId, categoryId); } wrapper.eq(Material::getStatus, 1).orderByAsc(Material::getSortOrder); PageMaterial result materialMapper.selectPage(p, wrapper); // 转换为DTO附带库存状态标识 ListMaterialDTO dtoList result.getRecords().stream() .map(m - new MaterialDTO(m, m.getStock() m.getWarningValue())) .collect(Collectors.toList()); return new PageResult(dtoList, result.getTotal()); }前端页面效果上用品卡片展示图标、名称、规格、库存数量和所在位置。库存充足显示“可申请”不足显示“库存紧张”并标红。每张卡片点击后进入详情页这个详情页同时承载领用申请功能所以页面结构分上下两块上方物品信息下方申请表单。3.3 领用申请与审批状态机领用申请是整个系统的业务核心状态管理决定了系统逻辑是否完善。我把状态设计成四个值1待审批、2已通过、3已驳回、4已撤销。初始创建时为1管理员审批时改为2或3用户按申请记录里的撤销操作改为4。状态流转有明确边界只有待审批状态才能被修改已审批通过的单子不能再回退。提交申请的后端逻辑PostMapping(/apply) public Result apply(RequestBody ApplyRequest request, RequestHeader(token) String token) { Long userId authService.getUserIdByToken(token); Material material materialService.getById(request.getMaterialId()); if (material null || material.getStatus() 0) { return Result.error(用品不存在或已下架); } Integer stock material.getStock(); if (stock request.getCount()) { return Result.error(库存不足当前剩余 stock); } ApplyRecord record new ApplyRecord(); record.setUserId(userId); record.setMaterialId(request.getMaterialId()); record.setCount(request.getCount()); record.setReason(request.getReason()); record.setStatus(1); record.setCreateTime(new Date()); applyRecordMapper.insert(record); return Result.success(申请已提交等待管理员审批); }审批通过后的库存扣减要考虑并发问题。两个人同时申请最后一件物品如果都在提交时校验库存充足审批时都直接扣减库存就可能变成负数。我的处理方式是在审批通过时使用乐观锁更新库存UPDATE material SET stock stock - #{count}, version version 1 WHERE id #{id} AND stock #{count} AND version #{version}如果执行更新后影响行数为0说明库存不足或版本冲突返回审批失败信息让管理员联系申请人调整数量。这段逻辑是项目中一个很实在的亮点面试时讲出来会有加分效果。3.4 管理员端接口设计管理员端的核心功能是审批、库存管理和数据统计。审批列表要展示申请人的姓名、部门、用品名称、申请数量、申请理由、申请时间管理员审阅后可以选择通过或驳回驳回时填写驳回原因。库存管理接口包括新增用品、编辑用品、调整库存、开启或关闭用品状态。调整库存的场景比较有意思采购补货和损耗报损都要调库存但含义不同。我设计成库存变更记录记录变更前后的数值差异和变更原因这样每一条数据都能追踪来源。这个设计在文档里可以作为数据库设计的亮点来写。数据统计部分用三个接口实现按月份统计申请次数、按用品统计领用数量排行、按部门统计消耗量。统计逻辑用SQL的GROUP BY聚合实现返回结果是简单的列表结构前端用小程序原生的canvas绘制柱状图或折线图展示。canvas绘制对新手来说有点门槛但代码量不大值得在讲解时重点提一下。4. 调试过程与常见问题排查4.1 局域网联调与真机调试配置小程序开发中最常见的问题就是前端请求不到后端。开发阶段我推荐这样配置后端启动时绑定0.0.0.0地址小程序端的request URL写成http://局域网IP:8080/api/xxx。同一台开发电脑上启动后端用微信开发者工具模拟器可以正常访问。换到真机调试时局域网IP必须改成手机能访问到的IP即开发电脑在局域网内的IPv4地址。这里有一个很容易踩的坑电脑开了防火墙或者连了两个网络导致手机实际上无法访问到开发电脑的IP。排查方法是在手机的浏览器里直接输入后端的接口地址如果能访问说明网络通不能访问就检查防火墙入站规则。正式发布时还需注意小程序后台必须配置服务器域名域名必须备案且支持HTTPS。这个流程比较繁琐所以在交付演示时通常直接用开发模式勾选不校验合法域名即可。4.2 常见报错与解决方案速查报错现象产生原因解决方案提示“request:fail”后端服务未启动或网络不通检查后端日志与防火墙确认手机可访问后端IP登录后页面空白用户信息存储异常查看storage中的token清缓存重新登录提交申请后提示“系统错误”后端抛异常未捕获查看后端控制台日志多半是SQL或参数问题审批通过后库存变为负数并发扣减控制缺失使用乐观锁更新库存并返回失败信息中文乱码数据库编码不是utf8mb4建库时指定utf8mb4连接参数加characterEncodingutf8时间显示多了8小时时区未设置UTC 8数据库连接参数加serverTimezoneAsia/Shanghai真机上看不到图片图片域名没配置或是本地路径开发模式勾选不校验域名或改用线上图片URL刷新后token失效token过期时间太短设置合理的过期时长小程序端收到401时重新登录以上都是实际调试中非常高频的问题。我建议在项目文档里单独开一个“常见问题与解决方案”章节把这些问题和解决方案写进去既方便复盘也方便答辩或讲解时让听众看到你真实踩过来坑的痕迹这种经历比完美的代码更有说服力。4.3 调试工具与效率技巧微信开发者工具里我常用的调试技巧有两个。第一个是Network面板每个请求的耗时、请求参数、响应数据都看得一清二楚前端传参错误或后端返回异常时用这个面板定位问题最快。第二个是vConsole在真机调试时可以看到前端console日志这点非常关键因为真机环境复现问题时开发者工具的模拟器不一定暴露同样的问题。后端调试方面我习惯用IDEA的断点调试功能。在Service方法入口打断点逐行查看参数值和变量变化。有一次排查审批后库存没扣减的问题就是用断点发现事务注解没加对地方Service内部方法调用的自调用导致事务失效。这类问题不打断点根本看不出原因。这里有一个想特别提醒的点如果后端服务使用Spring Boot一定要搞懂事务失效的几种情况。同类方法调用、异常被捕获、类没有被Spring管理都会导致Transactional失效。我在项目里就遇到过一次审批记录刷新了但库存没变更的情况最后定位是事务没生效整个方法执行过程中前边更新成功了后边异常回滚不掉。这种坑在正常开发中不常见但在讲解演示时可以特意提一句显得你确实对事务机制有理解。5. 文档编写与项目讲解的交付心得5.1 一套好的项目文档应该包含什么很多同学写项目文档就是应付一下把代码贴一遍。我理解中的文档核心是让别人不看代码也能知道整个系统的来龙去脉。我的文档结构比较固定需求分析、系统设计、数据库设计、接口文档、系统部署、使用说明、常见问题。需求分析要写清楚业务背景、参与者角色、功能需求和非功能需求。非功能需求容易被忽略但实际很重要比如并发库存扣减的安全性、接口响应时间、数据备份方案。系统设计包含架构图文字说明也可以和模块拆分说明。数据库设计重点讲每张表每个字段的含义以及表与表之间的关联关系。接口文档用表格列出请求路径、请求方式、参数说明和返回示例。部署说明要写两套一套是本地开发环境启动步骤一套是服务器部署的流程。接口文档我会贴出真实请求和响应示例比如POST /api/apply Content-Type: application/json Header: tokenabc123 Body: { materialId: 3, count: 5, reason: 部门例会用笔 } Response: { code: 1, message: 申请已提交等待管理员审批, data: null }这样读者根据文档可以直接测试接口不需要去翻前端代码猜测字段叫什么。文档的价值就在这里用最小成本让别人运行起这个系统。5.2 完整交付的讲解流程与演示技巧“源码加文档加调试加讲解”这套交付方式重点在于把项目串起来。我个人习惯的讲解流程是先讲业务用实际的办公场景引出痛点再讲解决方案说明为什么用小程序而不是网页或桌面软件紧接着演示前端页面逐一展示每个功能模块然后讲解数据库设计将表结构和业务对应起来最后讲核心代码逻辑挑登录鉴权、审批状态机、库存并发扣减这几个亮点展开。演示时有一个重要的技巧预先造好一批数据不要让演示现场出现空白列表或待审批列表为空的情况。我的做法是在清空数据库后导入一份demo数据包含两个部门、五个分类、二十种用品、若干条申请记录。这样演示过程中可以直接展示“待审批→通过→库存扣减”的完整链路而不需要临时花时间造数。讲解阶段要用好类比。比如Spring Boot的Controller、Service、Mapper三层结构可以类比成餐厅的传菜员、后厨和大厨Controller接收请求传菜Service处理业务逻辑炒菜Mapper负责从冰箱拿原料操作数据库。这个类比虽然简单但对初学者理解代码分层结构非常有效。5.3 面试或答辩时如何讲出亮点这套系统的亮点不能只体现在“能跑”要能在讲解时展现设计能力。我总结了几处值得深挖的点库存扣减采用乐观锁控制并发避免了超卖问题审批通过后才扣库存保证数据一致性用户通过openid自动注册降低使用门槛库存变更记录可追踪方便追溯数据来源操作日志记录关键行为方便安全审计。每个亮点都可以用“遇到了什么问题→我怎么解决→解决了之后效果如何”的结构来讲。比如库存超卖申请人同时提交两笔申请都通过审批后发现库存变成负数于是我在扣减操作中使用版本号控制并发保证数据库层面的原子操作再配合事务实现要么全部成功要么全部回滚。这样一个有故事、有分析、有解决方案的表达比单纯背代码的效果好很多。6. 从项目完成到系统扩展6.1 可以继续优化的方向这套系统作为课程设计或简历项目已经完整但距离真正的商用系统还有一段距离。真实场景里往往还需要这几个能力审批规则多样化比如金额在一定范围内自动审批超过范围才走人工审批消息通知即时化审批结果通过模板消息推送给员工微信数据报表图形化通过图表展示月度消耗趋势移动端适配差异化针对管理员的大屏工作台。我最建议加入的是消息订阅功能。员工提交申请后等待审批如果不在系统里刷新不知道审批结果。通过小程序的订阅消息能力审批完成后给员工手机发一条模板消息体验会上一整个档次。这个功能开发量不大但效果非常明显。如果你要扩展项目优先从这一个点入手。6.2 多端复用的思考微信小程序版的办公用品管理系统完成度已经足够但在实际部署时你可能会遇到一个需求不习惯用微信的员工怎么办。一套成熟的产品会考虑多端复用比如同一套后端可以同时支撑小程序端和管理后台。现在很多公司内部系统都是小程序做前端管理后台用Vue加Element Plus搭建前后端分离后端完全复用。从这个角度看后端接口设计时就要注意返回结构的通用性还是建议从一开始就统一使用Result封装响应。提醒一下如果你决定扩展管理后台接口权限这层需要重新设计。小程序端和管理后台虽然调用同一套数据层但接口本身的鉴权机制不同管理后台的接口对安全性要求更高建议token超时时间更短操作审批类接口要重新校验管理员身份不能只依赖前端隐藏入口来保证安全。最后再说点实在的整个项目做下来我个人体会最深的一点是业务逻辑比技术难想清楚数据库设计决定了代码写起来顺不顺畅。如果你只把精力放在页面上而忽略了审批状态流转、库存扣减、权限边界这些深一层的设计做出来的东西即使页面好看逻辑也会站不住。刚开始动手时不要急着写代码先花一晚上把业务闭环想透把每张表的字段和状态值列出来后续编码会快很多。这套项目的源码和文档我整理了完整版部署环境是Java 8加Maven加Node环境拿到后只要按文档里的步骤配置好数据库连接和微信小程序appid就能完整跑起来。如果你在跑通的过程中遇到任何报错优先查一下常见问题表大部分坑我在调试时都已经踩过一遍了。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询