资讯动态

SSM+Vue仓库管理系统毕设实战:出入库与库存联动全解析

发布时间:2026/10/18 20:19:16 来源:尧图企业网站定制
简介面向毕业设计的Java仓库管理信息系统完整源码包基于SSM框架搭建后台后台管理页面采用Vue前端页面为HTML搭配MySQL数据库与JDK 1.8适配Eclipse、MyEclipse、STS、IDEA等主流开发工具适合计算机相关专业学生完成课程设计或毕业设计时直接参考与二次开发。系统功能覆盖个人中心、员工管理、仓库公告、供应商与客户信息管理以及仓库、货物信息及入库出库管理等核心业务模块可完整演示仓库日常管理流程。包内共464个文件包含112个Java源码、45个Vue页面、162个SVG图标、数据库脚本与XML配置以及环境工具包、说明文档中的同框架安装教程压缩包约44MB结构清晰便于按模块查阅。已有82人学习下载适用于需要快速搭建SSMVue项目管理环境并理解前后端联动逻辑的开发者。1. 仓库管理系统能做什么先看懂这套 SSMVue 的毕设项目一个小仓库的账目对不上十有八九不是人不够仔细而是出入库的记录方式太原始。这套基于 SSM Vue MySQL 的仓库管理信息系统把「入库有单、出库有据、库存可查」做成了完整闭环解决的就是这个最接地气的痛点。后端用 Spring SpringMVC MyBatis 处理业务后台管理用 Vue 渲染前端展示用 HTML功能覆盖个人中心、员工管理、仓库公告、供应商、客户、仓库信息、货物信息以及货物入库、出库两大核心单据流程。对正在做毕业设计或课程设计的同学来说它最值钱的地方不是页面好不好看而是数据库表、三层代码、前端路由都能拆开看改起来有明确落点不是一个黑匣子。2. 项目结构与技术选型SSM 后端 Vue 管理端 HTML 前台的联动关系2.1 技术栈全景为什么是 SSM Vue MySQL 这个组合SSM 是 Spring SpringMVC MyBatis 的缩写在教学项目里出现频率极高。选它有三个实际理由第一Spring 管对象和事务SpringMVC 管请求分发MyBatis 管 SQL 映射每一层边界清楚一个请求从页面到数据库的路径能一条线讲完第二这套组合的 XML 配置虽然多但恰恰把 IOC 容器、拦截器、SqlSessionFactory 这些概念暴露在明面上适合答辩时展开讲第三JDK 1.8 加 MySQL 的环境在旧电脑上也能跑没有额外硬件门槛。后台管理页面用 Vue 是个值得说两句的设计。它不是前后端分离的大型工程而是把 Vue 以资源文件形式嵌进 Web 工程HTML 页面引用 Vue 的 js用 Vue 语法控制表格渲染、弹窗和表单提交避免了大量手写 DOM 操作。前台展示页面则用纯 HTML 实现能直接打开看效果也能和后台部署在同一个 Tomcat 下。这种混搭风格在毕设项目里很常见好处是核心里面是后端 Java 逻辑前端只做交互壳上手门槛低。这套系统的管理端功能清单包括个人中心、员工管理、仓库公告管理、供应商管理、客户信息管理、仓库信息管理、货物信息管理、货物入库管理、货物出库管理。从模块命名能看出来它没有做采购订单、销售订单这类偏上下游的业务核心就是基础资料加两张出入库单据正好卡在中小型内部仓库的使用边界上。对毕设选题来说这个范围不大不小每个模块都能单独展开讲。2.2 工程目录与文件.bat 脚本、.vue.bak 备份和 .classpath 说明了什么拿到源码包建议先看一遍文件清单文件结构本身能透露不少信息。.classpath是 Eclipse 工程的类路径文件说明这是一套标准 Eclipse Java 工程org.eclipse.wst.common.component是 Eclipse WTP 的组件描述文件说明它同时被识别为动态 Web 项目。换句话说Eclipse 导入时选择 Existing Projects into Workspace 就能直接识别。用 IDEA 的同学注意IDEA 不会自动读 .classpath要按 Maven 或 Web 项目的方式重新导入这一步后面单独讲。三个批处理文件是这套项目的「三步走」设计1-install.bat安装依赖2-run.bat启动项目3-build.bat打包部署。文件名带数字前缀保证按顺序执行避免依赖没装就去启动的翻车现场。这种脚本化思路在毕设源码里很常见图的就是让不熟悉 Maven 命令的人也能双击跑起来说明文档里对应的安装教程也因此能写得短。那批.vue.bak文件值得单独说update-password.vue.bak、IndexMain.vue.bak、IndexAsideStatic.vue.bak、BreadCrumbs.vue.bak、IndexHeader.vue.bak。.bak是备份后缀说明作者在改版之前把原文件留了底。比如IndexHeader.vue.bak大概率是改顶部导航栏之前的旧版本。这也是给你的一次提醒二开这套项目时改任何 Vue 文件之前都复制一份 .bak出问题还能撤回等于给自己留后悔药。再往下是标准的 SSM 工程布局按常见做法描述src/main/java 下按 controller、service、mapper、entity 分包src/main/resources 里放 spring-mvc.xml、spring-mybatis.xml、jdbc.properties 和 mapper 映射目录webapp 目录里是前台 HTML 和后台 Vue 相关的 js、css数据库脚本通常在 doc 或 sql 目录下。源码包整体还带了数据库脚本、环境工具包和说明文档说明文档里除了本项目的安装教程还附带一份相同框架项目的安装教程也就是说以后你再拿到同框架的源码照着同一套流程也能跑起来这层价值比单跑通一个项目更实用。提示.vue.bak是备份文件不参与编译。改页面时优先认准不带 .bak 的正式文件不要改错副本。2.3 数据库设计仓库业务拆成几张表每张表管什么这套系统按功能可以拆出 8 张核心表员工表同时承担登录账号的角色、仓库公告表、供应商表、客户信息表、仓库信息表、货物信息表、货物入库表、货物出库表。其中货物表是主数据入库表和出库表是单据流水员工表兼任用户表没有单独拆权限表——登录用户直接在员工表里校验。这是教学项目里「功能够用、结构不过度设计」的典型做法涉及到的表都能在两张 ER 图里画清楚。货物表的设计决定了后面出入库能不能做联动。货物表至少要有货物编号、货物名称、规格型号、单位、类别和所属仓库 ID入库表记录单号、货物 ID、入库数量、单价、入库时间、经办人出库表结构类似多一个接收方或领用部门字段。供应商和客户表只做基础资料维护不参与库存计算模块耦合度很低。下面给一段常见建表写法以货物表和入库表为例实际库里字段会略多但主干就是这两张表。CREATE TABLE tb_goods ( id INT(11) NOT NULL AUTO_INCREMENT, goods_no VARCHAR(32) DEFAULT NULL COMMENT 货物编号, goods_name VARCHAR(64) DEFAULT NULL COMMENT 货物名称, spec VARCHAR(64) DEFAULT NULL COMMENT 规格型号, unit VARCHAR(16) DEFAULT NULL COMMENT 单位, warehouse_id INT(11) DEFAULT NULL COMMENT 所属仓库ID, stock_num INT(11) DEFAULT 0 COMMENT 当前库存数量, PRIMARY KEY (id) ) ENGINEINNODB DEFAULT CHARSETutf8mb4; CREATE TABLE tb_stock_in ( id INT(11) NOT NULL AUTO_INCREMENT, in_no VARCHAR(32) DEFAULT NULL COMMENT 入库单号, goods_id INT(11) DEFAULT NULL COMMENT 货物ID, in_num INT(11) DEFAULT NULL COMMENT 入库数量, in_price DECIMAL(10,2) DEFAULT NULL COMMENT 入库单价, in_time DATETIME DEFAULT NULL COMMENT 入库时间, operator VARCHAR(32) DEFAULT NULL COMMENT 经办人, PRIMARY KEY (id) ) ENGINEINNODB DEFAULT CHARSETutf8mb4;stock_num放在货物表里而不是实时从流水表聚合计算是为了列表页直接显示库存数减少联表查询这是小项目常用的取舍。in_no入库单号建议加唯一索引避免重复单据。入库表只存增量数据库存通过更新货物表的stock_num联动这也是后面出入库逻辑能保持简单的关键前提。3. 核心模块拆解入库、出库、登录三条链路的前后端协作3.1 登录与个人中心拦截器校验和密码修改的实现细节登录流程的数据流大致是这样员工表里存账号和密码前端把账号密码 POST 给登录接口Service 层用账号查员工表比对密码。这里有个常见细节密码入库前先做 MD5 加密而不是存明文虽然 MD5 在今天的安全级别不高但作为教学项目至少演示了「不能明文存密码」的意识生产环境再换加盐或 BCrypt。登录成功后把员工对象放进 session同时配一个拦截器统一拦后台管理路径。拦截器是这套系统权限控制的全部比 Shiro 轻量也更容易看懂。核心代码大致如下public class LoginInterceptor implements HandlerInterceptor { Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { Object user request.getSession().getAttribute(loginUser); if (user null) { // 未登录跳回登录页 response.sendRedirect(request.getContextPath() /login.html); return false; } return true; } }然后在 spring-mvc.xml 里配置拦截规则mvc:interceptors mvc:interceptor mvc:mapping path/admin/**/ mvc:exclude-mapping path/admin/login/ bean classcom.warehouse.interceptor.LoginInterceptor/ /mvc:interceptor /mvc:interceptorsmapping指定拦截哪些路径exclude-mapping放行登录接口。最常翻车的地方就是排除路径没配全导致登录接口自己也被拦表现是账号密码正确却一直跳回登录页。解决思路是先把登录 Controller 的路径单独排除再确认静态资源js、css、图片没有被拦截规则命中否则页面样式会全部丢失。个人中心对应源码里的update-password.vue页面逻辑是旧密码校验加新密码写入两步。前端把旧密码和新密码提交给后端后端按 session 里的用户 ID 查出原密码比对一致才执行 UPDATE。Vue 页面的提交部分大致这样updatePassword() { if (this.oldPwd || this.newPwd ) { this.$message.warning(请输入完整信息); return; } this.$http.post(/admin/updatePassword, { oldPwd: this.oldPwd, newPwd: this.newPwd }).then((res) { if (res.data.code 200) { this.$message.success(密码修改成功); } else { this.$message.error(res.data.msg); } }); }this.$http是 Vue 项目里常见的 axios 实例封装baseURL 指向后端接口地址统一走 POST响应携带code、msg、data三个字段。约定简单明确code 200成功其余全部弹msg里的提示。这套封装在整个后台管理页面里通用新加模块时直接复用即可。3.2 货物入库从 Vue 表单到 MyBatis 写库的一条完整链路入库是本系统最核心的业务之一。页面表单字段是入库单号、货物选择下拉框、入库数量、入库单价、经办人、入库时间提交后调用/admin/stockIn/add接口。Controller 只做参数接收和结果包装事务放在 Service 层先插入库流水再更新货物表的库存数量。Controller 的常见写法Controller RequestMapping(/admin/stockIn) public class StockInController { Autowired private StockInService stockInService; RequestMapping(/add) ResponseBody public Result add(RequestBody StockIn stockIn) { try { stockInService.addStockIn(stockIn); return Result.success(); } catch (Exception e) { return Result.error(e.getMessage()); } } }Service 的addStockIn是整个流程的闸门事务必须在这里Transactional public void addStockIn(StockIn stockIn) { // 1. 生成入库单号并保存入库流水 stockIn.setInNo(RK System.currentTimeMillis()); stockInMapper.insert(stockIn); // 2. 更新货物表的当前库存 Goods goods goodsMapper.selectById(stockIn.getGoodsId()); int newStock goods.getStockNum() stockIn.getInNum(); goodsMapper.updateStock(goods.getId(), newStock); }这里要分清两个参数inNum是本次入库数量对应页面填的「入库数量」stockNum是货物当前累计库存对应货物表的字段。单号生成用了System.currentTimeMillis()高并发下可能重复但毕设场景完全够用。如果以后接真实业务建议改成「日期 自增序列」的格式。事务注解Transactional保证两个写操作要么都成功、要么都回滚避免出现「流水插了但库存没加」这种脏数据。还有一个容易踩的细节入库表单里的货物下拉框数据来自货物表。前端在页面初始化时调一次/admin/goods/list把全部货物存到 data 里。如果货物表是空的下拉框自然没选项这时候应该先去「货物信息管理」录货物再回来做入库单顺序反了会以为系统坏了。3.3 货物出库与库存联动出库单如何扣减库存出库和入库基本对称保存出库单加扣减库存。区别在于扣减前要做库存校验——如果货物当前库存小于出库数量直接报错返回不能让库存变成负数。这是仓库系统最基础的一条业务规则也是面试官最容易追问的点。Transactional public void addStockOut(StockOut stockOut) { Goods goods goodsMapper.selectById(stockOut.getGoodsId()); if (goods.getStockNum() stockOut.getOutNum()) { throw new RuntimeException(库存不足当前库存 goods.getStockNum()); } stockOut.setOutNo(CK System.currentTimeMillis()); stockOutMapper.insert(stockOut); int newStock goods.getStockNum() - stockOut.getOutNum(); goodsMapper.updateStock(goods.getId(), newStock); }RuntimeException抛到 Controller 后被全局异常处理器包装成Result.error(msg)前端弹出提示。注意事务边界Transactional默认只对未检查异常回滚如果throw的是Exception这类受检异常事务不会回滚。新手写库存系统最容易在这里栽跟头库存扣了但流水没删或反过来。出库列表页一般要联查货物名称和仓库名称MyBatis 的 mapper 用一个 resultMap 映射联查结果SQL 写在 XML 里比注解拼串好维护。典型查询写法select idselectStockOutList resultTypeStockOutVO SELECT so.*, g.goods_name, w.warehouse_name FROM tb_stock_out so LEFT JOIN tb_goods g ON so.goods_id g.id LEFT JOIN tb_warehouse w ON g.warehouse_id w.id ORDER BY so.out_time DESC /selectStockOutVO是比实体多出goodsName和warehouseName两个展示字段的视图对象避免往实体类里塞冗余属性。排序用out_time DESC让最新出库记录排在最前这是列表页的通用习惯。到这步为止入库、出库、库存联动的核心链路已经完整闭环下面对应到本地运行。4. 本地跑通全流程install.bat、run.bat、build.bat 的三步部署4.1 环境准备JDK 1.8、MySQL、Tomcat 的版本搭配拿到这份资源后先按四件事排序装 JDK 1.8、装 MySQL、准备 Tomcat、导入源码。源码包里的「环境工具包」目录通常放的就是 JDK 和 MySQL 安装包加上 Tomcat 压缩包还有一个说明文档里面除了本项目的安装步骤还带了一份相同框架项目的安装教程也就是说你后面再拿到同框架的源码照着同一套流程就能复现环境。JDK 1.8 装完先做两个确认命令行执行java -version看版本是不是 1.8.x再确认JAVA_HOME环境变量指向 JDK 安装目录。很多启动失败不是代码问题而是JAVA_HOME指向了 11 或 17SSM 的 EL 表达式和 Tomcat 版本对 JDK 版本很敏感版本不对启动日志会抛各种看不懂的类版本错误。MySQL 建议装 5.7 或 8.0。如果本机是 8.0要注意驱动版本必须配套 8.x 的com.mysql.cj.jdbc.Driver连接串还要加serverTimezoneAsia/Shanghai否则会报时区错误。项目里的 jdbc.properties 就是连接信息的总入口后面连不上库时八成是这里的问题。4.2 导入工程Eclipse / IDEA 打开项目的两种方式源码解开后是一个标准 Eclipse Web 工程。Eclipse 导入用 File → Import → Existing Projects into Workspace选择根目录IDE 会读取.classpath自动识别 Java 工程和 Web 工程特性。MyEclipse 和 STS 底层都是 Eclipse 生态操作完全一样。如果你习惯 IDEA注意它不认.classpath推荐 File → Open 选工程根目录如果工程是 Maven 结构IDEA 会自动读取 pom.xml 拉依赖如果不是 Maven 结构就要手动把 src 标记为 Sources Root把 webapp 配置成 Web 资源目录再建 Artifacts 和 Tomcat 运行配置。步骤比 Eclipse 多一点但后续编码体验更好断点调试也顺手。导入后第一件事检查 JDK 级别Project Structure → Project SDK 选 1.8Modules 的 Language level 同步选 1.8。级别配错会报diamond operator is not supported in -source 1.6这类编译错误看到这个就说明 JDK 版本没对上不是代码的问题。4.3 数据库初始化执行 SQL 脚本的顺序与验证方法数据库脚本一般在 doc/sql 目录或工程根目录文件名带 01、02 前缀的按顺序执行。先建库字符集建议 utf8mb4用 MySQL 命令行导入CREATE DATABASE IF NOT EXISTS warehouse_db DEFAULT CHARACTER SET utf8mb4; USE warehouse_db; SOURCE 数据库脚本路径.sql;SOURCE是 MySQL 命令行的导入方式比在图形工具里复制粘贴更可靠能避开 SQLyog、Navicat 里文件编码不一致导致的中文乱码。导入完成后做两个验证SHOW TABLES;看表数量是否和文档描述一致再查员工表确认管理员账号已存在通常是 admin初始密码在说明文档里能找到。图形工具导入时文件编码选自动或 UTF-8。如果脚本本身是 ANSI 编码导入 utf8mb4 的库会出现中文乱码这个在第 5 章还会展开。数据库这块一定要在启动 Tomcat 之前搞定否则项目起来也是卡在登录上。4.4 启动验证与打包三个 .bat 脚本的职责划分环境就绪后按1-install.bat→2-run.bat→3-build.bat的顺序执行。这三个脚本封装的是 Maven 命令教学项目里最常见的内容对应关系如下# 1-install.bat安装依赖并编译 mvn clean install -DskipTests # 2-run.bat启动内置 Tomcat mvn tomcat7:run # 3-build.bat打包成 war mvn clean package -DskipTests2-run.bat里的tomcat7:run是 Maven 插件方式的启动端口由 pom.xml 配置决定默认通常是 8080。启动日志出现Server startup in xxx ms说明成功浏览器访问http://localhost:8080/项目名/。如果拿到的是非 Maven 工程1-install.bat的实际任务可能是把依赖 jar 复制到 WEB-INF/lib效果等价核心思路都是「先把依赖准备好再启动最后打包」。验证顺序建议分三步先直接访问前台 HTML 页面确认静态资源能打开再用 admin 登录后台进入「货物入库」提交一条测试数据最后去「货物信息」列表看库存数字有没有变化。一条数据能走通入库链路项目就算真正跑通了。最后用3-build.bat打的 war 包可以丢到独立 Tomcat 的 webapps 目录这就从开发模式切到了部署模式。5. 避坑与排查跑这套仓库系统最常见的 5 个问题5.1 Tomcat 启动失败端口被占用现象双击 run.bat 或从 IDE 启动 Tomcat控制台报Port 8080 required by Tomcat ... is already in use浏览器访问 8080 打不开或者打开的是另一个应用的页面。原因8080 端口被其他进程占用常见的有别的 Tomcat 实例、某个 Java 进程或者其他软件内置的调试服务。Tomcat 遇到端口冲突会直接放弃启动不会自动换端口。解决在命令行执行netstat -ano | findstr 8080看占用端口对应的 PID再按 PID 在任务管理器里结束进程。如果不想杀进程就改端口Maven 插件启动方式改 pom.xml 里 Tomcat 插件的port独立 Tomcat 方式改 conf/server.xml 里的Connector port8080两处保持一致就行。5.2 数据库连不上时区、编码、授权三件事现象Tomcat 起来了页面能打开但登录时提示Access denied for user rootlocalhost或者日志里报The server time zone value xxx is unrecognized。原因要么是 jdbc.properties 里的账号密码和本机 MySQL 不一致要么是 MySQL 8.x 的驱动和时区参数没配。SSM 项目如果连接串还是老的jdbc:mysql://localhost:3306/warehouse_db在 MySQL 8.x 下驱动能连上但时区校验会直接抛异常。解决把 jdbc.properties 改成jdbc.drivercom.mysql.cj.jdbc.Driver jdbc.urljdbc:mysql://localhost:3306/warehouse_db?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai jdbc.usernameroot jdbc.password你的密码改完重启服务。如果是账号密码本身错了要么去 MySQL 里执行ALTER USER rootlocalhost IDENTIFIED BY 新密码;要么直接改配置文件的 password两边保持一致别改完了一处漏一处。5.3 登录后页面空白Vue 文件与静态资源路径现象账号密码正确登录后跳转后台首页结果整页空白F12 控制台报一堆 404指向IndexMain.js、IndexHeader.js之类文件不存在。原因后台页面是 Vue 渲染的HTML 里通过script src引用编译后的 js 文件。如果 webapp 目录下的实际文件路径和页面里的引用路径不一致比如项目名变化导致 contextPath 变了就会全部 404。另外.vue.bak备份文件如果被误改成.vue使用但目录下没有对应的编译链也会引发找不到模块的问题。解决检查页面里的资源引用路径把绝对路径改成相对路径或者在 js 引用前拼接${pageContext.request.contextPath}再确认实际参与运行的 Vue 文件是主版本不要拿 .bak 备份当正式文件。排查时先看 F12 里 404 的具体 URL把你访问的端口和项目名拼一下基本就能定位是路径少了项目名还是文件名不对。5.4 中文乱码从数据库到页面的编码链现象录入的中文货物名称保存后变成???或者页面显示正常但后台管理界面中文全是乱码。原因编码链上某一环不一致。数据库表用了 latin1 或 utf8 但连接串没指定 characterEncoding页面表单提交时用了 ISO-8859-1或者 Tomcat 的 URI 编码没设成 UTF-8。乱码问题基本是这三处至少有一处没对齐。解决分段排查。先确认建表时DEFAULT CHARSETutf8mb4已建的表用ALTER TABLE tb_goods CONVERT TO CHARACTER SET utf8mb4;转换再确认 jdbc 连接串包含characterEncodingutf8最后给 Tomcat 的 server.xml 里 Connector 加URIEncodingUTF-8属性。三层都改到位中文基本恢复正常。注意修改后要重启 Tomcat光改配置不重启不行。5.5 改了代码不生效.bak 备份文件惹的祸现象改了update-password.vue里的某个接口地址重新启动后页面弹的还是旧的提示甚至改完文件后控制台报编译错误。原因第一种是改错了文件——源码目录下同时存在.vue和.vue.bak可能顺手改了.bak而.bak不参与编译和页面加载改了等于白改第二种是 Tomcat 没有真正重启或者浏览器缓存了旧的 js。Java 代码改了还能被热部署识别Vue 和 HTML 这类静态资源经常被浏览器缓存坑刷新一下其实就正常了。解决先全局搜索修改的文件名确认改的是不带 .bak 的正式文件再强制刷新浏览器缓存CtrlF5最后确认 Tomcat 进程已彻底结束重新执行 run 脚本。这个排查思路建议记下来省得以后白改半天。我自己就吃过这个亏改了半天页面纹丝不动结果发现一直在动备份文件。6. 二次开发实战给系统加一个库存盘点模块系统跑通之后最常见的需求就是加模块。比如仓库每个月要做一次盘点账面库存和实物对不上时要有据可查。下面在这个 SSMVue 工程上加一个库存盘点模块链路是建表 → Service → Controller → Vue 页面 → 菜单全程复用现有代码风格。6.1 三步接入从建表到页面一条线走完第一步建盘点表。盘点单和入库单结构类似但多两个关键字段账面数量stock_num和实盘数量real_num差异由后端计算不手工填。CREATE TABLE tb_stock_check ( id INT(11) NOT NULL AUTO_INCREMENT, check_no VARCHAR(32) DEFAULT NULL COMMENT 盘点单号, goods_id INT(11) DEFAULT NULL COMMENT 货物ID, stock_num INT(11) DEFAULT NULL COMMENT 账面数量, real_num INT(11) DEFAULT NULL COMMENT 实盘数量, diff_num INT(11) DEFAULT NULL COMMENT 差异数量, check_user VARCHAR(32) DEFAULT NULL COMMENT 盘点人, check_time DATETIME DEFAULT NULL COMMENT 盘点时间, PRIMARY KEY (id) ) ENGINEINNODB DEFAULT CHARSETutf8mb4;第二步写 Service 核心逻辑。保存盘点单的同时如果差异不为零就把货物表库存修正为实盘数这是盘盈盘亏的标准处理方法Transactional public void addStockCheck(StockCheck check) { Goods goods goodsMapper.selectById(check.getGoodsId()); check.setStockNum(goods.getStockNum()); check.setDiffNum(check.getRealNum() - goods.getStockNum()); stockCheckMapper.insert(check); if (check.getDiffNum() ! 0) { goodsMapper.updateStock(goods.getId(), check.getRealNum()); } }这段代码的关键在于账面数量不是前端传的而是后端读货物表拿到的防止手填偏差差异数也是后端算保证口径一致。第三步接入页面。Vue 页面直接复制入库管理页改成盘点表单路由和菜单加上stockCheck对应路径接口沿用/admin/stockCheck/add的格式。验证方式很直接录一条账面 10、实盘 8 的盘点单提交后回货物管理页看库存是否变成 8差异数是否显示 -2。这套项目里 .bak 文件给我留下的习惯最后想分享给你任何改造动作之前先复制一份 .bak数据表加字段前先导出旧库结构。从那以后我每次在这个系统里改核心库存逻辑都强制走一遍「新增入库 → 新增出库 → 盘点差异修正」的闭环确保库存永远不会变成负数或凭空消失。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑