去年帮本地零售协会做数字化转型时,发现很多社区商店还在用纸质记账本管理进销存。店主老张跟我说:"每天关店后对账到半夜,月底盘货更是头疼,想用电脑又怕系统太复杂学不会。"这促使我基于ThinkPHP开发了一套轻量级社区零售经营平台,目前已在17家社区店稳定运行8个月。
这套系统最核心的特点是"三低一高":低学习成本(店主平均2小时上手)、低硬件要求(普通电脑就能跑)、低维护难度(自动更新+一键备份),同时提供高实用性的四大核心模块:智能进销存、会员营销、经营报表和移动端管理。下面分享具体实现方案和踩坑经验。
选择ThinkPHP6.x版本主要基于三点考量:
注意:必须锁定TP版本为6.0.14,我们测试发现6.1.x的session机制改动会导致老版本Windows服务器兼容性问题
针对社区店商品SKU少(通常<500种)但交易频繁的特点,采用分表策略:
关键字段示例(商品表):
sql复制CREATE TABLE `goods` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`barcode` varchar(20) NOT NULL COMMENT '国际条码',
`short_code` varchar(6) NOT NULL COMMENT '店内简码',
`name` varchar(100) NOT NULL,
`category_id` smallint(6) NOT NULL DEFAULT 0,
`price` decimal(10,2) NOT NULL COMMENT '零售价',
`cost` decimal(10,2) NOT NULL COMMENT '进货价',
`stock` int(11) NOT NULL DEFAULT 0 COMMENT '当前库存',
`safety_stock` int(11) NOT NULL DEFAULT 10 COMMENT '安全库存',
`supplier_id` int(11) NOT NULL COMMENT '供应商',
`last_restock` datetime DEFAULT NULL COMMENT '最后补货时间',
`is_weigh` tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否称重商品',
PRIMARY KEY (`id`),
UNIQUE KEY `barcode` (`barcode`),
KEY `short_code` (`short_code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
考虑到店主多为中老年用户,收银台设计坚持"三秒原则":
核心JS逻辑:
javascript复制// 简码快速搜索
$('#barcode_input').on('keyup', debounce(function(){
let code = $(this).val();
if(code.length == 6){ // 店内简码长度
axios.get('/goods/search', {params: {code}}).then(res => {
if(res.data.id){
addToCart(res.data);
$(this).val('');
}
});
}
}, 300));
每天凌晨自动执行库存检查:
核心算法:
php复制public function checkInventory()
{
// 获取需要预警的商品
$warningGoods = Goods::where('stock', '<', Db::raw('safety_stock'))
->where('is_archived', 0)
->select();
// 生成补货建议
foreach($warningGoods as $goods){
$suggestQty = ceil(($goods->safety_stock - $goods->stock) * 1.2); // 多补20%
Replenishment::create([
'goods_id' => $goods->id,
'suggest_qty' => $suggestQty,
'urgency' => $goods->stock == 0 ? 1 : 0
]);
}
}
| 项目 | 最低配置 | 推荐配置 |
|---|---|---|
| 操作系统 | Windows 7 | Windows 10 LTSC |
| PHP版本 | 7.3 | 7.4 |
| 数据库 | MySQL 5.6 | MySQL 5.7 |
| 内存 | 2GB | 4GB |
| 存储空间 | 50GB(含日志) | 100GB SSD |
用Inno Setup制作安装包时需要注意:
关键配置片段:
ini复制[Files]
Source: "php-7.4.33-nts-Win32-vc15-x86\*"; DestDir: "{app}\php"; Flags: ignoreversion recursesubdirs
Source: "mysql-5.7.39-winx64\*"; DestDir: "{app}\mysql"; Flags: ignoreversion recursesubdirs
[Run]
Filename: "{app}\init.bat"; Description: "初始化系统"; Flags: postinstall
为方便店主从旧系统迁移,开发了Excel导入工具:
典型问题处理:
php复制// 处理价格格式混乱问题
private function normalizePrice($input)
{
if(preg_match('/[^\d\.]/', $input)){
return floatval(preg_replace('/[^\d\.]/', '', $input));
}
return $input;
}
| 现象 | 可能原因 | 解决方案 |
|---|---|---|
| 扫码枪输入无效 | 1. 端口冲突 | 设备管理器检查COM端口占用 |
| 打印小票乱码 | 字体未嵌入 | 安装打印机驱动附带的字体包 |
| 月末报表生成慢 | 交易数据量过大 | 执行OPTIMIZE TABLE命令优化表 |
| 移动端无法连接 | 电脑防火墙拦截 | 开放8000端口或配置反向代理 |
针对3个月后数据量增大的情况,我们做了以下优化:
sql复制ALTER TABLE `goods`
ADD INDEX `idx_search` (`category_id`, `stock`, `is_archived`);
基础防护:
交易安全:
php复制// 防止收银金额篡改
public function checkout(Request $request)
{
$realTotal = Order::calculateTotal($request->items);
if(abs($realTotal - $request->total) > 0.01){
Log::warning('金额异常', $request->all());
return $this->error('交易金额校验失败');
}
// ...正常处理逻辑
}
根据店主反馈,后续可增加:
开发称重模块的要点:
python复制# 串口读取电子秤数据示例
import serial
ser = serial.Serial('COM3', 9600, timeout=1)
while True:
data = ser.readline().decode('ascii').strip()
if data.startswith('W:'):
weight = float(data[2:])
print(f'当前重量: {weight}kg')
这套系统最大的成就感,是看到65岁的王阿姨现在能熟练地用平板电脑查库存、给老顾客发优惠券。技术真正的价值,就是让复杂的事情变简单。