ARTICLE DETAIL

资讯详情

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

PHP CRM系统源码本地部署与二次开发实战指南

PHP CRM系统源码本地部署与二次开发实战指南 简介这套CRM客户管理系统旗舰版源码基于PHP开发定位面向中小企业及PHP开发者的完整业务管理解决方案可应用于市场、销售、采购、库存、售后等业务场景。系统内置线索、客户、商机、合同、财务、销售、采购、库存、任务、日志、营销等十余个功能模块支持线索池自动回收、客户高级筛选、自定义字段、审批流程、进销存联动等机制新增报价单快速生成合同、合同审核通过后自动创建应收款与出库单、回款计划到期站内信提醒、库存流水账、移库单等功能并优化了销售与财务权限、停用用户审批统计、知识分类、任务进度颜色、统一推送等细节同时修复了详情页返回、地址搜索、客户行业下拉、选择性导出等问题。源码无加密、无域名限制可在本地环境导入数据库后安装运行适合直接部署或作为PHP二次开发项目研读。压缩包约12.3MB资源已有1058人学习下载目录与模块逻辑清晰能帮助开发者快速看懂企业级客户关系管理系统的整体结构并依据自身需求调整字段、流程与界面展示。1. 这套 CRM 系统源码到底值不值先把定位说清楚把客户资料从 Excel 迁进一套 PHP 写的 CRM 系统源码大部分团队试过之后又迁回去原因是免费版装完发现加密、限域名、字段改不了。这套旗舰版源码不一样无加密、无域名限制市场、销售、采购、库存、售后五个环节串在一条业务链上这是它跟网上免费版最本质的区别。它做了线索、客户、商机、合同、财务、进销存等十多个功能模块并且加了报价单自动转合同、合同审核自动生成应收款、合同完成自动出库这一套联动逻辑。适合中小企业里想从人管客户改成系统管客户、同时又有技术能力做二次开发的人。如果你只是装个 Demo 看看界面免费版够用如果你想让 CRM 真的跟着公司流程跑二开能力才是这套源码的性价比所在。2. 本地部署四件事PHP 版本、伪静态、导库、改配置2.1 环境选型PHP 版本别追新老源码的第一原则是兼容先说结论PHP 7.4 是我部署这类经典 PHP CRM 源码用得最多的版本MySQL 5.7 搭配起来几乎不用改代码。7.4 之后 PHP 8.x 对很多老写法做了破坏性变更比如未定义常量默认不再当字符串处理、部分旧函数移除这套源码里如果有老语法直接跑在 8.1 上大概率报 500。如果你机器上已经装了更高的 PHP常见处理方式不是去改 composer.json 的版本约束——因为很多国产现货源码根本不走 composer直接定位报错函数去改代码反而更省事。MySQL 建议 5.7 还有一个具体原因源码里的 SQL 可能用了老的排序规则写法5.7 的兼容边界比 8.0 宽。数据表字符集最好跟随源码自带的 SQL 文件一般默认是 utf8mb4导入之后先别急着改表结构等业务流程验证完再说。注意PHP 版本和 MySQL 版本是装完启动就报错的最大来源先确认这两个再谈后面的功能配置。2.2 伪静态规则地址好不好看是小事SESSION 和跳转依赖它这类 CRM 的 URL 一般是 index.php/模块/控制器/操作 这种 PATHINFO 形态。如果服务器没开伪静态部分跳转和登录状态校验会出问题典型表现是打开二级页面白屏、登录成功后又跳回登录页。Nginx 环境我一般用这段location / { if (!-e $request_filename) { rewrite ^/(.*)$ /index.php?s$1 last; } }参数说明$request_filename 是当前请求对应的真实文件路径。这句的意思是当请求的不是一个真实存在的文件或目录时把整个路径作为参数交给 index.php 处理。s 参数的具体写法取决于源码的路由入口有的版本用 /index.php?s/模块/控制器/操作有的用 /index.php?m模块c控制器a操作改成你实际的入口写法即可。Apache 环境就简单了源码包里一般自带了 .htaccess缺的话自己补一份RewriteEngine On RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^(.*)$ index.php/$1 [L]这里 !-f 和 !-d 分别是“不是文件”和“不是目录”作用跟 Nginx 的 !-e 一样。配完记得重载服务nginx -s reload 或者 service apache2 reload不然改了等于没改。2.3 导入数据库并完成安装两步命令加一个文件修改拿到源码包之后第一步是找 SQL 文件。一般放在根目录的 install.sql、crm.sql 或者 database 目录里文件名因版本而异。建库导库我习惯用命令行而不是 phpMyAdmin大文件不容易超时mysql -uroot -p -e CREATE DATABASE crm_db DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; mysql -uroot -p crm_db /path/to/crm.sql第一行创建数据库 crm_db显式指定 utf8mb4 字符集避免导入时出现中文乱码。第二行把 SQL 文件导入这个库。如果 SQL 文件超过几十兆phpMyAdmin 经常导入到一半超时命令行没有这个限制这也是我不推荐图形工具的原因。导完之后改数据库配置。PHP 源码的数据库连接配置一般在根目录下的配置目录里常见命名是 config.php 或 application/database.php按你拿到的实际文件来。需要修改的就是四个参数// 数据库连接配置示例以源码实际 config 文件为准 return [ host 127.0.0.1, // 本机安装用 127.0.0.1远程库改服务器 IP port 3306, // MySQL 默认端口 database crm_db, // 第一步创建的库名 username crm_user, // 建议单独建业务账号不要直接用 root password 你的数据库密码, ];这里多说一句很多源码自带的数据库账号是 root密码为空本地测试没问题但只要这台机器能通过局域网访问风险就兜不住。我一般会单独建一个账号只授予 crm_db 的权限mysql -uroot -p -e CREATE USER crm_userlocalhost IDENTIFIED BY 密码; GRANT ALL PRIVILEGES ON crm_db.* TO crm_userlocalhost; FLUSH PRIVILEGES;权限收紧之后即使源码文件被泄露拿到配置文件也动不了你机器上的其他数据库。2.4 首次登录三件事改管理员密码、看缓存目录、校准时区装完登录后台先别急着录客户处理三件事。第一是改管理员密码默认的 admin/admin123 这类弱口令在 CRM 里危害比论坛大得多里面有完整的客户资料、合同金额和联系方式。第二是确认缓存目录可写这类源码的 runtime 或者 cache 目录如果权限不够页面会白屏或者一直转圈。本地调试直接 chmod -R 777 省事线上环境建议把用户组切给 Web 服务用户PHP-FPM 一般是 www-data。第三是时区如果服务器不在东八区PHP 的 date.timezone 没配的话审批、任务、下次联系时间的显示会跟本地时间差 8 小时看起来像 bug实际就是时区问题。到这儿系统已经能登录了。接下来才是这份源码真正值钱的部分——业务闭环和二开能力。3. 业务闭环怎么转线索池、合同联动、自定义字段三条主线3.1 线索限时领取反资源闲置的设计思路线索模块是这个版本最值得看的部分。员工限时限额领取线索领取后规定时间内没有跟进利用线索自动回流到公共线索池。这个机制解决的是销售团队里最典型的问题——好线索被占着不动别人想跟跟不了。实现逻辑其实不难线索表里有两个核心字段一个是领取人 ID一个是领取时间或最后跟进时间。定时任务或者每次有用户操作时扫描这两个字段超过时限就把领取人置空归还到池子。二开时你要找的就是这两个字段。如果后台没有直接给配置项可以改配置表里的常量比如-- 假设线索表为 crm_clue修改线索领取时限为 72 小时 UPDATE crm_config SET config_value 72 WHERE config_key clue_follow_limit;三个坑要注意第一时限建议按线索来源分开设置自然来线和活动线的转化周期不一样统一一个值容易误伤第二自动回流不能只看领取时间还要看“最后跟进时间”销售每次写跟进都算活跃线索不该被回收第三回流前要有站内信提醒不然销售会觉得系统不讲道理这套源码本身带站内信模块直接调用消息接口就能实现。这个模块还有一个细节是列表页的下次联系时间和下次联系内容。很多销售填完跟进就忘了下一步动作列表页把这两个字段单独优化展示目的就是让“该联系谁、要聊什么”一眼可见。二开时如果想加强可以再加一个“逾期未联系自动置顶”的排序规则比单纯靠人翻列表更有效。3.2 合同驱动的状态联动从商机到出库一条链这个版本对合同相关逻辑的改动是整个源码里最值得看的业务设计。合同创建成功之后商机状态自动变成“成功”客户自动锁定合同审核通过后自动生成应收款应收款创建后可以设回款计划到期有站内信提醒合同创建完又自动生成出库单出库单审核之后仓管才能出库。这一串动作的本质是状态机不是简单的字段更新。商机、客户、应收款、出库单四个实体被合同这个中心节点串起来。你在二开时最应该理解的是这些触发条件写在哪里、每个动作往前能不能回滚。常见做法是合同保存或审核的 service 方法里按顺序调下面几个操作// 合同审核通过后执行的联动逻辑伪代码方法名以实际源码为准 function afterContractAudit($contractId) { // 1. 商机状态置为“成功”客户状态置为“锁定” $opp $this-opportunityModel-findByContractId($contractId); $this-opportunityModel-updateStatus($opp[id], success); $this-customerModel-lock($opp[customer_id]); // 2. 生成应收款记录 $receivableId $this-receivableModel-createFromContract($contractId); // 3. 自动生成出库单等待仓管审核 $this-outStockModel-createFromContract($contractId); // 4. 按合同回款计划生成站内信提醒任务 $this-messageModel-createPlanNotice($contractId); }参数说明afterContractAudit 是合同审核通过后的回调入口。第 2 步为什么是审核通过才生成应收款而不是合同创建时生成——合同创建还在草稿阶段审核通过才具备业务效力。第 3 步生成的出库单是先锁库存还是先过审核取决于你公司的仓库流程一般建议出库单审核通过后再做库存扣减避免取消订单后库存对不上。回滚问题容易被忽略。合同审核通过后如果发现填错了流程上应该走“作废”而不是直接删记录。你二开时要额外处理的是作废合同后应收款和出库单应该跟着什么状态走源码默认不一定处理得很完整这个可以自己补。另外这套源码还带了普通审批、请假审批、差旅审批、报销审批这些工作流跟合同审核走的是同一套审批引擎改审批状态的颜色和推送消息时注意别只改了合同审核把其他审批也一并覆盖到。3.3 自定义字段给客户表加“规格”字段的完整操作这个版本的自定义字段又叫“开放模型”意思是客户、商机、线索这些模块的字段可以根据公司流程加加减减。报检单要显示图片、要加规格字段就是在这个机制上做的。操作分两步数据库加字段表单加输入项。先加数据库字段ALTER TABLE crm_customer ADD COLUMN spec VARCHAR(255) NULL DEFAULT COMMENT 产品规格 AFTER industry;AFTER 指定字段在表里的物理位置industry 换成你想放的前一个字段名即可。VARCHAR(255) 够用如果规格是长文本改成 TEXT 类型。这一步如果找不到要改的是哪张表最快的办法是在源码里搜“客户”模块的列表页模板看它读的是哪个模型再对应到数据表。第二步是模板加字段。客户表单一般是列表页或弹窗模板新增一个输入框div classform-group label产品规格/label input typetext namespec value{$customer.spec} placeholder请输入产品规格 /div代码逻辑说明name 要和数据库字段名一致value 绑定表单回显字段。保存之后列表页和商机转报价单的时候如果要把这个字段带出去还要在对应的列表查询处把 spec 字段加入可查询列。这一步新手最容易漏——数据库字段加了、表单能填了但列表页看不见不是因为没生效而是列表展示列的配置里没加这个字段。自定义字段的核心边界要记住加字段简单难的是字段跟业务流联动。比如你在客户表加了“月采购量”它不会自动出现在商机的统计报表里。要联动得在对应的数据聚合逻辑里手动纳入这个字段。这是所有“开放模型”产品共同的边界不是这套源码独有的坑。4. 二开避坑排查五个高频问题的现象、原因与修复这个源码自带的【修复】列表里列的几项恰好都是二开用户最容易撞上的场景。这些问题的共同特点是官方版也许已经修了但你自己在旧版本上做二开时如果动过模板、权限或导出逻辑很容易把同类问题再引出来。下面按现象、原因、解决逐条写。4.1 客户导出无法选择性导出导出来一堆用不到的列现象点击客户导出页面上有导出按钮但没有字段选择弹窗导出的 Excel 包含全部列连身份证、备注等敏感字段也一起导出发给别人容易泄露。 原因导出功能写死了一个固定字段数组没有从当前模块的自定义字段配置动态读取。这是源码常见简写逻辑跟后台“可以加自定义字段”这个能力其实是脱节的。 解决改导出方法让它从字段配置表读取当前用户角色允许导出的字段。// 导出前动态拼接字段伪代码 $fields [name, mobile, company]; if ($systemConfig[export_use_custom_fields] ?? false) { $fields $this-fieldModel-getExportFields(customer); // 后台配置里勾选了导出的字段 }参数说明第一行是默认导出字段第二行判断后台配置开关决定是否用自定义字段配置替代默认。如果你不想改代码同时又只要“选择性”导出的效果可以在后台把不需要的字段从前台展示列表里移除因为不少 CRM 的导出是跟着列表可见字段走的这也是最快的规避方案。4.2 地址搜索搜不到区域关键词输入后结果为空现象在客户列表或商机录入里用地址关键词搜索地区返回结果一直是空但库里明明有对应客户。在行政区划选择器里也有同类问题。 原因地址搜索依赖地区数据表或前端行政区划 JS这类数据经常是初始化数据的一部分。两种情况最常见一是导入 SQL 时地区数据表没导全二是搜索逻辑用的是 LIKE 查询但地址字段存的是“地区 ID 详细地址”你搜的时候拿关键词直接比对地区 ID自然匹配不上。 解决先查地区表数据是否完整SELECT COUNT(*) FROM crm_region WHERE pid 0;如果返回 0说明地区数据没进来重新导入地区数据文件。如果是 LIKE 匹配问题把查询条件改成对“地区名称 详细地址”做拼接匹配$where[address] [like, % . $keyword . %];参数说明LIKE 后面的 %keyword% 是模糊匹配写法适配“客户在 XX 路”这种中间带关键词的场景。注意 MySQL 对中文 LIKE 默认走全表扫描地区表数据量不大没关系量大的时候要考虑全文索引。4.3 停用用户仍然出现在审批统计里现象管理员在用户管理里停用了一个离职销售的账号但在审批统计、任务统计面板里这个人的名字和数据还在正常显示甚至还能看到他的历史审批记录。 原因统计报表的查询 JOIN 用户表时没加状态过滤只判断了记录存在性没判断 status 是否为启用。停用用户的本质是改状态标记不是删除记录所以统计时照查不误。 解决给统计查询补上用户状态条件。$where[u.status] 1; // 只统计启用用户参数说明u.status 对应的是用户表别名的状态字段1 表示启用具体取值以你源码的用户状态定义为准。改完清理一下统计缓存不然页面上还是旧数据。4.4 模块详情页点“返回”按钮报错或跳回空白页现象在客户详情、商机详情、合同详情这些页面点击“返回”有时回到空白页有时跳到登录页但直接改 URL 访问列表页又是正常的。 原因问题根源基本都在二开模板。常见三种一是返回按钮写成了 JS history.back()而详情页是从新窗口打开的历史栈里没有上一页二是返回链接写的是绝对域名本地测试用的 IP 或不同端口就对不上三是改模板的时候不小心把隐藏域里的模块标识带丢了返回路由少了模块前缀。 解决把返回按钮改成显式链接不依赖浏览器历史。a href/crm/index.php?s/customer/lists返回客户列表/a参数说明s 后面的 /customer/lists 是按你源码实际路由写的作用是直接进入列表页。如果想保留返回前的筛选条件可以带上分页参数比如 ?page2。改动成本低但能解决大部分“返回失效”问题。4.5 手机端报检单不显示图片现象电脑端报检单图片正常显示手机浏览器打开报检单详情图片全部裂开或者只显示文件名不显示图。 原因这类 CRM 二开加“报检单手机显图片”时最容易出现的是图片路径问题。图片上传后存的是相对路径 upload/images/xxx.jpg电脑端和手机端访问的域名不一致时相对路径解析出来的完整地址就指错了位置比如电脑用 http://192.168.1.10手机用 http://crm.你的域名.com。 解决模板里输出图片时强制拼完整域名或者用相对根路径。img src?php echo (isHttps() ? https : http) . :// . $_SERVER[HTTP_HOST] . / . $imagePath; ?参数说明isHttps() 是判断当前请求是否走 HTTPS避免写成死协议导致浏览器拦截。也可以更省事一点把图片路径改成站点根目录相对路径也就是开头带斜杠的写法这样无论从哪个域名访问浏览器都按当前域名解析。这里有个通用排查套路遇到“电脑正常手机不正常”的问题先 F12 看图片请求实际发出的 URL一切以那个 URL 为准十有八九是路径拼接问题。5. 进销存一体化出库单、库存流水账与回款计划的正确打开方式5.1 合同到出库单审核权限和打印边界要分清这个源码把进销存跟销售流程打通了核心路径是合同创建完成自动生成出库单出库单可以打印出库单审核之后仓管才能执行出库。这套逻辑如果光看“自动生成”四个字会觉得简单实际二开时有两个细节值得单独说。第一个细节是“自动生成”不等于“自动执行出库”。系统帮你做的是把合同里的产品明细、数量、客户地址这些信息带进一张新的出库单草稿省去仓库重复录入。但出库单还需要审核审核通过才真正从库存里扣减数量。这个分层设计是对的合同是商务动作出库是仓储动作两边权限不能混在一起。商务能创建合同不代表商务能直接动库存。第二个细节是打印。出库单打印通常需要一式三联或者带公司抬头模板里要能自定义打印样式。二开时别去改详情页模板来满足打印需求应该在打印模板目录里单独建打印样式用 CSS 的 media print 控制打印区域。常见做法是这样media print { .no-print { display: none; } /* 隐藏按钮、导航等不需要打印的元素 */ .print-area { width: 100%; } /* 打印区域占满纸张 */ body { background: #fff; } }参数说明media print 是打印时才会生效的样式块。no-print 类加在页面上不需要打印的功能按钮上print-area 是实际打印的表格区域。这样做的价值是屏幕预览和打印效果分离不会出现点打印把左侧菜单也带出来的尴尬。5.2 库存流水账和移库单盘盈盘亏的正确入账方式普通 CRM 里库存就是个数字卖一件减一件减成负数也能出。这个版本加了库存流水账和移库单相当于把库存从“一个数字”升级成“一本流水账”。库存流水账的核心是不可篡改。每次入库、出库、退货、盘盈盘亏都要生成一条流水记录记录操作前数量、操作数量、操作后数量、操作人、操作时间和关联单据号。就算后面发现入错了也应该用新的冲销单反向修正而不是直接改旧流水。二开时最容易出错的是把库存汇总表改成可随意修改的普通字段这样库存对不上账时连问题出在哪一步都查不出来。移库单解决的是仓库之间调拨的问题。A 仓调到 B 仓如果直接改库存数字就会在流水账里留下两个窟窿A 仓少了但没有出库单B 仓多了但没有入库单。正确流程是创建移库单审核通过后同时生成 A 仓的出库流水和 B 仓的入库流水数量和成本价保持一致。移库单一般还要带一个“调拨原因”字段方便后续盘点追溯。盘盈盘亏是进销存里最容易被忽略的场景。实际库存比账上多或者少都算盘点差异。盘盈盘亏单通常要填入盘点前后的数量审核后自动生成一条库存调整流水。这里有一个参数建议盘盈盘亏单最好留一项“原因说明”这样月底财务核对时不用再回头翻聊天记录。5.3 收款单发票开关与回款计划配置别藏在代码里这个版本做了两个对中小企业很实用的设置。一个是收款单支持“是否已开具发票”这个字段还可以在系统配置里决定要不要显示。为什么要做成开关而不是直接删字段因为不同公司的开票流程不一样有的先收款后开票有的先开票后收款。把字段做成配置开关比每个公司去改代码要省事。还有一个权限设计值得单独说默认配置下销售人员可以创建收款单但审核权在财务。这个分工是有意为之的。销售只负责录入收款信息减小财务建账的工作量审核权保留在财务手里避免销售自行核销应收款导致账实不符。如果你要把这个权限改成销售直接生效谨慎一点改成销售创建收款单后需要财务确认再进应收款核销。如果你接手的部署里老板要求“收款时必须填写发票号码”但后台配置里没有对应开关那就在收款单表单校验里加一个必填规则// 收款单提交前的校验逻辑伪代码 if ($systemConfig[invoice_required] ?? false) { if (empty($post[invoice_no])) { return error(请填写发票号码); } }参数说明invoice_required 是配置项false 时不校验true 时收款单必须带发票号码。这种做法比直接改死逻辑好在不同分公司的制度不同通过配置项可以按需切换不用改代码重新部署。回款计划也是这个版本的亮点。应收款创建完成后可以设置不同时间的回款计划到期站内信提醒收款负责人。站内信的核心价值是自动催收财务不需要每天翻账本系统到点提醒能明显减少“我们忘了催”导致的回款延迟。配置提醒时间时建议把提前提醒和到期提醒分开到期前三天一次到期当天一次超过期限每天一次到三次。别只在到期日提醒一次业务上回款常常是拖几天才到账的。6. 验证部署是否成功用一条合同把全链路走通再交付前面写的大部分内容都是模块层面的分析这套源码跑起来到底有没有问题建议你部署完成之后拿一条真实的小合同走完整链路比任何检查清单都可靠。我自己的习惯是这样的先用测试账号建一个客户录入基础信息后转成商机商机里填产品、数量和价格然后在商机详情页生成报价单再由报价单快捷生成合同。合同提交审核用管理员账号审核通过紧接着去看三个位置的联动结果——商机状态是否自动变成“成功”、客户是否被锁定、应收款是否已生成。然后打开应收款设置一个三天后的回款计划确认站内信提醒能触发。再去进销存模块看出库单是否自动生成走审核流程看库存流水账里库存扣减的数字和合同数量是否一致。到这里销售、财务、仓储三条线的数据才算是通的。验证的时候重点记录两件事哪一步的时间有偏差哪一步的数据对不上。时间偏差基本是时区问题数据对不上才是代码逻辑问题。如果发现回款计划不提醒先看定时任务有没有配这类源码不少提醒功能依赖 cron 或者计划任务本地测试时没人配 cron功能就像没做一样。从那以后我每次部署这套系统都会强制走一遍这条合同链路再交给业务用。宁可多花二十分钟验证也不要等销售用了一个月之后跑来告诉你“合同都录进去了但财务说没看到应收款”。希望帮到你。本文还有配套的精品资源点击获取
返回列表