资讯详情

资讯详情

ThinkPHP进销存源码实战:采购销售库存与权限报表配置

简介这是一套基于ThinkPHP与MySQL开发的仓库管理进销存系统源码面向中小商贸企业、仓储管理开发者及需要二次开发的技术人员可解决采购、销售、库存与财务数据分散、难以统一管控的问题。系统主要模块包括采购管理、销售管理、库位管理、报表查询、系统管理、财务管理与设备管理等支持库存状况、出入库统计等报表并对角色权限做了细致控制同时提供API接口、语音播报、扫码枪与盘点机接入及第三方平台对接能力运行环境要求PHP5.6以上。资源包共863个文件以447个PHP业务代码、145个JavaScript脚本、69个HTML页面、36个CSS样式及62张PNG图片为主另含SQL数据库脚本与配置文件压缩包约4.16MB目录结构完整便于部署与二次开发。目前已有112人学习下载适合作为进销存项目实战参考或企业仓储系统搭建基础。1. 一套能跑起来的进销存源码到底解决了什么问题很多做企业信息化的朋友都遇到过这种局面客户要一套仓库管理加进销存预算不高工期又紧从零写一套采购、销售、库存、报表、权限的完整闭环光是把单据流转逻辑理顺就得耗掉大半个月。这套基于 ThinkPHP MySQL 的仓库管理进销存系统源码恰好卡在这个需求点上——它把采购管理、销售管理、库位管理、出入库统计、报表查询、角色权限控制这些模块都做完了拿到手改改配置就能跑。它适合谁一是接中小型仓储、批发零售类私活的开发者需要一套能快速交付的底子二是企业内部 IT想给仓库部门搭一套带扫码枪、盘点机对接的轻量系统三是学 ThinkPHP 的人想拿一个业务闭环完整的项目练手。运行环境要求 PHP5.6 以上MySQL 做数据存储属于典型的 LAMP/LNMP 架构部署门槛不高。下面我从环境搭建一路讲到权限配置和报表口径把这份源码怎么落地说透。2. 环境搭建与数据库初始化从 run.bat 到第一个登录页拿到源码包第一件事不是急着改代码而是把运行环境跑通。这套系统是 ThinkPHP 框架入口文件、配置目录、应用目录结构都比较规整但 PHP 版本和 MySQL 字符集这两个点如果没配对后面会一路报错。2.1 PHP 与 MySQL 版本选择系统要求 PHP5.6 以上但这里有个血泪经验PHP7.4 和 PHP8.x 对 ThinkPHP 老版本的兼容性差异很大。如果你拿到的源码是基于 ThinkPHP 3.2 或 5.0 的PHP8 下很多函数签名变了会直接白屏。我一般会先看ThinkPHP/ThinkPHP.php或vendor/topthink里的版本号再决定用哪个 PHP。组件推荐版本说明PHP7.2 / 7.4兼容性最稳5.6 也能跑但部分扩展偏旧MySQL5.7字符集用 utf8mb4避免中文乱码Web 服务器Apache / Nginx需要开启 rewriteThinkPHP 的 pathinfo 模式依赖它扩展pdo_mysql、mbstring、gdgd 用于报表导出图片mbstring 处理中文MySQL 建库时字符集一定选utf8mb4排序规则utf8mb4_general_ci。我见过有人用latin1建库结果商品名称里的中文全变问号查半天以为是代码问题。2.2 导入数据库与修改配置文件数据库文件一般在源码包的data或sql目录下后缀是.sql。导入方式有两种命令行更快# 创建数据库字符集必须 utf8mb4 mysql -u root -p -e CREATE DATABASE warehouse DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; # 导入 SQL 文件注意路径换成你实际的 mysql -u root -p warehouse /path/to/warehouse.sql导入完成后找到数据库配置文件。ThinkPHP 的配置通常在Application/Common/Conf/config.php或config/database.php里面有几项必须改// 数据库连接配置按实际环境填写 DB_TYPE mysql, DB_HOST 127.0.0.1, DB_NAME warehouse, // 刚创建的库名 DB_USER root, DB_PWD your_password, // 改成你的密码 DB_PORT 3306, DB_PREFIX tp_, // 表前缀要和 SQL 文件里一致这里DB_PREFIX是最容易翻车的地方。如果 SQL 文件里的表名是tp_admin而你配置的前缀是空系统会提示表不存在。改完配置后访问入口文件默认账号密码一般在 SQL 文件的admin表里密码是 MD5 加密的初始通常是admin或123456。2.3 run.bat 与启动脚本项目正文里反复出现run.bat config这其实是 Windows 下的启动批处理。它的作用通常是设置环境变量、指定 PHP 路径、启动内置服务器或执行初始化命令。在 Windows 上双击运行前先确认run.bat里的 PHP 路径指向你本机的 php.exeecho off REM 设置 PHP 可执行文件路径按实际安装位置修改 set PHP_PATHD:\phpstudy\php\php-7.4\php.exe REM 启动 ThinkPHP 内置服务器端口 8000 %PHP_PATH% -S 0.0.0.0:8000 -t public pause如果你在 Linux 或 Mac 上这个 bat 用不了直接手动起服务就行。config参数一般是让脚本读取配置或执行初始化具体看脚本里的判断逻辑。跑起来后浏览器访问http://localhost:8000能看到登录页就说明环境通了。3. 采购、销售、库存三大模块的配置与数据流转环境通了只是第一步真正决定这套系统能不能用的是采购入库、销售出库、库存扣减这三条数据链是否对得上。很多进销存系统表面功能都有一跑真实单据就发现库存对不上问题往往出在单据状态和库存更新的时机上。3.1 采购管理从下单到入库的完整链路采购模块一般包含采购订单、采购入库、采购退货几个环节。配置时重点看两个地方一是入库时是否自动更新库存二是采购单价是否影响库存成本。在Application/Admin/Controller/PurchaseController.php这类文件里能找到入库确认的方法。// 采购入库确认核心是更新库存表和写入库存流水 public function confirmIn() { $orderId I(post.order_id); $items M(purchase_items)-where([order_id $orderId])-select(); foreach ($items as $item) { // 库存增加注意这里用 setInc 保证原子性 M(stock)-where([goods_id $item[goods_id], warehouse_id $item[warehouse_id]]) -setInc(quantity, $item[num]); // 写入库存流水方便后续出入库统计 M(stock_log)-add([ goods_id $item[goods_id], warehouse_id $item[warehouse_id], type purchase_in, quantity $item[num], create_time time(), ]); } M(purchase_order)-where([id $orderId])-save([status 2]); // 2 表示已入库 }这段逻辑的关键参数是status状态机0 待审核、1 已审核、2 已入库。如果状态没卡住重复点入库按钮会导致库存重复增加。我一般会在前端加个 disabled后端再查一次状态做幂等。3.2 销售出库与库存扣减销售模块和采购是对称的但多了一个库存不足的校验。出库时如果库存不够系统应该拦截而不是让库存变成负数。在销售出库的控制器里扣减前先查库存// 销售出库先校验库存再扣减 public function confirmOut() { $orderId I(post.order_id); $items M(sale_items)-where([order_id $orderId])-select(); foreach ($items as $item) { $stock M(stock)-where([goods_id $item[goods_id], warehouse_id $item[warehouse_id]])-find(); if (!$stock || $stock[quantity] $item[num]) { $this-error(商品库存不足 . $item[goods_name]); } M(stock)-where([id $stock[id]])-setDec(quantity, $item[num]); M(stock_log)-add([ goods_id $item[goods_id], warehouse_id $item[warehouse_id], type sale_out, quantity -$item[num], // 负数表示出库 create_time time(), ]); } M(sale_order)-where([id $orderId])-save([status 2]); }注意stock_log里出库记负数这样出入库统计报表直接 SUM 就能得到净库存变动不用区分正负逻辑。这是常见做法但有些源码出库也记正数靠 type 区分改报表时要注意口径。3.3 库位管理与预警提示库位管理是这套系统比普通进销存细的地方。同一个商品可以放在不同库位出库时按先进先出或指定库位扣减。配置库位需要在warehouse和location表里建立关联商品入库时选择具体库位。预警提示一般分两种库存下限预警和保质期预警。库存下限在商品资料里设min_stock字段系统定时或每次出入库后检查。语音提示和语音播报功能通常是出库扫码时调用浏览器的 Web Speech API 或本地语音库播报商品名称和数量仓库人员不用一直盯屏幕。提示库位和库存的关联如果设计成多对多查询时要用 JOIN别在循环里查库位否则订单一多就慢成蜗牛。4. 权限、报表与外部设备对接的落地细节功能模块跑通后接下来是让这套系统真正适配企业场景不同角色看到不同菜单报表数据能导出扫码枪和盘点机能接进来。这几块配置不到位系统就只能演示用。4.1 角色权限的细粒度控制系统对角色和权限做了细致控制一般是 RBAC 模型用户关联角色角色关联节点菜单和操作。配置入口在系统管理里的角色管理。关键表通常是role、node、access。-- 查询某个角色拥有的权限节点 SELECT n.id, n.name, n.pid, n.level FROM tp_node n JOIN tp_access a ON a.node_id n.id WHERE a.role_id 3 ORDER BY n.pid, n.id;配置时注意level层级菜单是一级操作按钮是二级或三级。如果只给了菜单没给操作权限用户能看到页面但点按钮提示无权限。我一般会先把管理员角色的所有节点全勾上再复制一份改成普通角色逐个去掉敏感操作。4.2 报表查询与出入库统计口径报表模块包含库存状况、出入库统计、财务相关报表。库存状况是当前快照出入库统计是时间段内的流水汇总。这两个口径要对齐否则客户会问为什么库存状况和出入库统计对不上。报表数据来源关键字段常见问题库存状况stock 表goods_id、warehouse_id、quantity多库位时需按商品汇总出入库统计stock_log 表type、quantity、create_time出库记负数则 SUM 即可采购报表purchase_order items供应商、金额、状态未入库订单是否计入销售报表sale_order items客户、金额、状态退货单要冲减导出 Excel 时如果数据量大别一次性查全部再写用分页或游标。常见做法是用 PHPExcel 或 PhpSpreadsheet但 PHP7.4 以上建议用后者前者已经停止维护。4.3 扫码枪、盘点机与 API 接口设备管理这块扫码枪本质是一个键盘输入设备扫出来的条码会直接输入到光标位置。所以对接扫码枪不需要特殊驱动只要在出库、入库、盘点页面把焦点默认放在条码输入框扫完触发查询即可。盘点机通常是安卓设备通过 API 接口和系统通信。系统提供的 api 接口一般用 token 鉴权盘点机拉取商品列表离线盘点后回传数据。配置 API 时注意跨域和 token 有效期// API 鉴权中间件检查请求头里的 token public function checkToken() { $token $_SERVER[HTTP_X_TOKEN] ?? ; if (empty($token)) { exit(json_encode([code 401, msg 缺少 token])); } $user M(api_user)-where([token $token])-find(); if (!$user || $user[expire_time] time()) { exit(json_encode([code 401, msg token 无效或已过期])); } }第三方平台接入一般走 webhook 或定时同步把订单推过来生成销售单或者把库存推过去。这块要特别注意幂等同一个外部订单号重复推送不能生成两张单。5. 避坑与排查那些让系统跑不起来的常见问题这套源码功能全但正因为模块多配置和运行时的坑也集中。下面几条是我在实际部署和调试中反复遇到的按现象、原因、解决三段来说。现象一登录页能打开输入账号密码后白屏或提示“模块不存在”。原因通常是入口文件绑定了默认模块而 URL 重写没生效导致 pathinfo 解析失败。ThinkPHP 在 Nginx 下需要配置try_filesApache 下需要.htaccess开启 rewrite。解决方法是检查服务器 rewrite 规则或者临时把 URL 模式改成普通模式在配置里设URL_MODEL 0。现象二商品列表中文全是乱码数据库里看又是正常的。这是连接字符集问题。MySQL 库和表是 utf8mb4但 PHP 连接时没指定字符集。在数据库配置里加DB_CHARSET utf8mb4或者在连接后执行SET NAMES utf8mb4。另外页面头部要有meta charsetutf-8缺一不可。现象三采购入库后库存没变化但单据状态变成已入库了。多半是库存更新逻辑被注释掉了或者stock表里没有对应商品和仓库的记录setInc更新了 0 行。解决方法是先确认stock表有没有初始化数据没有的话入库时应该用add而不是setInc。我一般会在入库前先查一次不存在就插入存在再增加。现象四报表导出 Excel 时内存溢出或超时。数据量超过几千行时一次性查询加 PHPExcel 写入会吃光内存。解决方法是分批查询每批 500 条写入或者直接用 MySQL 的SELECT ... INTO OUTFILE导出 CSV。另外把memory_limit调到 256M 以上max_execution_time调到 300。现象五扫码枪扫出来的条码多了回车或前缀查询不到商品。扫码枪可以配置结束符和后缀有些默认带回车。如果条码输入框没处理回车就会触发提交或换行。解决方法是在输入框的keydown事件里判断回车键手动触发查询并阻止默认行为或者在扫码枪配置里去掉多余后缀。6. 二次开发与数据验证让这套源码真正变成自己的拿到源码直接交付客户迟早会提新需求。这套系统基于 ThinkPHP二次开发的成本主要看你对框架的熟悉程度。我的习惯是先在本地把数据流转验证一遍再动代码。验证数据是否对得上最直接的方法是写一个对账脚本把库存流水和库存快照做比对// 库存对账脚本检查 stock 表和 stock_log 汇总是否一致 $goodsList M(stock)-field(goods_id, warehouse_id, quantity)-select(); foreach ($goodsList as $row) { $logSum M(stock_log) -where([goods_id $row[goods_id], warehouse_id $row[warehouse_id]]) -sum(quantity); if (abs($logSum - $row[quantity]) 0.001) { echo 不一致商品{$row[goods_id]} 仓库{$row[warehouse_id]} 快照{$row[quantity]} 流水{$logSum}\n; } }这个脚本跑一遍如果全部一致说明出入库逻辑是闭环的。不一致的地方就是你要排查的单据。我一般会在每次大版本改动后强制跑一遍比人工翻单据快得多。二次开发时新增模块建议遵循原有目录结构控制器放Application/Admin/Controller/模型放Application/Admin/Model/模板放Application/Admin/View/。数据库改动用 migration 或 SQL 文件记录别直接在生产库上改。API 接口新增时记得在权限节点里注册否则角色管理里看不到。语音播报这块如果想增强可以接本地的 TTS 引擎把出库商品名称和数量拼成文本播报。设备管理里扫码枪和盘点机的对接核心是统一条码格式商品条码、库位条码、单据条码要能区分开我一般用前缀区分商品P开头库位L开头单据O开头。从那以后我每次拿到一套新源码都强制先跑一遍对账脚本再改代码这个习惯帮我省了太多返工。希望帮到你。本文还有配套的精品资源点击获取
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →