大数跨境

实操记录:从 0 到 1 打造外贸人专用 CRM:我的开发经验与心得分享!

实操记录:从 0 到 1 打造外贸人专用 CRM:我的开发经验与心得分享! 陈金凌
2026-08-02
2
导读:实操记录:从 0 到 1 打造外贸人专用 CRM:我的开发经验与心得分享!


实操记录:从 0 到 1 打造外贸人专用 CRM:开发经验与心得分享

本文记录了「外贸人 CRM 系统」从需求构思到代码落地的全过程开发经验。

这是一套面向外贸个人的轻量获客 + 客户管理 + 智能跟进工具,技术栈为 PHP + MySQL + Bootstrap,运行于 XAMPP 环境。

不讲大道理,只分享真实踩过的坑、做过的取舍以及回头看值得改进的地方。


一、为什么做这个项目

外贸人的工作日常被三件事割裂:找客户、管客户、跟客户。

找客户需切换 GoogleLinkedIn海关数据;管客户靠 Excel 表格满天飞;跟进记录散落在微信、邮件、备忘录里。工具切换成本高、客户跟进断层、获客转化低效,是几乎所有外贸个人从业者的共同痛点。

因此决定打造一款「够用、轻量、一站式」的 CRM,目标明确:

  • 不追求重型 CRM(如 Salesforce)的复杂,避免给个人造成负担;
  • 打通获客与管理,搜到的线索可一键转为客户;
  • 实现跟进闭环,下次跟进时间、提醒及历史记录一目了然;
  • 内置外贸场景工具(关键词生成、时差查询、黄页导航等),无需开启多个标签页。

定位清晰后,所有功能取舍便有了标尺。


二、技术选型:为什么是 PHP + 自研 MVC

2.1 选 PHP 而非 Node/Python/Java

这是个易受争议的决定,但对外贸目标人群而言,PHP 是最优解:

考量 PHP 的优势
部署门槛 XAMPP 一键安装,放入 htdocs 即可运行,外贸人无需配置环境
主机成本 几十元的虚拟主机即可运行 PHP+MySQL,远低于 VPS 成本
生态成熟 邮件、PDF、CSV、PDO 等原生支持,无需折腾依赖
迭代速度 修改后刷新即生效,无编译打包等待时间

技术选型容易陷入「技术先进性」的执念,但用户的部署能力才是第一约束。外贸人非程序员,若要求安装 Node、配置 npm 或运行 Docker,项目往往死在安装环节。


2.2 自研轻量 MVC 而非使用 Laravel/ThinkPHP

这是更激进的取舍。为何不直接用 Laravel?

  • 学习成本:项目需长期维护,框架越重,后人接手越难;
  • 部署体积Laravel 的 vendor 目录高达几百兆,在虚拟主机上传极为不便;
  • 可控性:自研框架每行代码皆由己出,出问题能快速定位。

因此编写了 8 个核心类(App/Router/Controller/Model/Database/Auth/Session/Helper),总计不到 1000 行,覆盖路由、ORM 基类、PDO 单例、认证、Session、CSRF 及视图渲染。既够用,又易懂。

心得:框架并非越先进越好,而是越匹配场景越好。对于总代码量不足 2 万行的项目,引入全家桶框架属于过度设计。当然,代价是缺少了 Laravel 的迁移、队列、Eloquent 等利器,后续将通过约定来弥补。

三、架构设计:几个关键决策

3.1 单入口 + 约定式路由

所有请求经 .htaccess 重写到 index.php?url=xxx,再由 Router 解析成 Controller/action。

路由器做了优化:连字符自动转驼峰。例如 URL 中写 followup,自动映射到 FollowUpController。此举既兼顾 SEO 与用户友好度,又符合 PHP 类命名规范。

3.2 Model 基类:用约定换 ORM

心得:必须设置 fillable 白名单。早期未加 fillable,导致前端多传 is_admin 字段直接入库,形成典型的批量赋值漏洞。加上白名单后,多余字段被 array_intersect_key 过滤,从根源堵住风险。

3.3 控制器基类:收敛重复逻辑

所有控制器继承 Controller,统一处理:

  • 视图渲染(render 自动套用主布局,renderPartial 输出裸视图);
  • JSON 响应(jsonSuccess/jsonError 统一格式);
  • CSRF 校验(validateCsrf,所有 POST 请求必过);
  • 权限前置(requireLogin/requireAdmin);
  • 闪存消息(flash 一次性提示)。

这套基类让业务控制器保持精简,业务方法平均仅 20-30 行,易于阅读。

四、数据库设计的心得

4.1 18 张表够不够

最终落地 18 张表 + 2 视图 + 1 存储过程。核心实体包括:用户、客户、线索、跟进、邮件、产品、报价单、订单、寄样、会员。

心得:勿为「显得专业」而过度拆表。早期曾想将客户联系方式独立拆表,后发现外贸场景下 90% 的客户仅有一个主联系人,拆表反而导致查询需频繁 JOIN。最终将 contact_name/position/email/phone 作为单字段存入 customers 表,简单直接。

注:若是 B2B 大客户场景,联系人则必须拆表——表结构应服务于业务形态,而非设计范式。

4.2 用存储过程处理撞单

外贸 CRM 最敏感的是撞单(同一客户被两销售争抢),此处采用存储过程解决。

4.3 公海私海用 is_public 一个字段

简化状态管理,仅用一个字段区分公海与私海。

4.4 全文索引解决模糊搜索

客户搜索若用 LIKE '%关键词%',数据量大时性能极差。因此在 customers 表上添加了全文索引。

五、安全实践:这是底线不是加分项

CRM 涉及客户数据,安全不容马虎。该系统落地了 6 道防线。


六、几个有意思的功能实现

6.1 撞单检测:实时 AJAX 校验

客户录入时,邮箱失焦即触发 AJAX 调用 customer/checkConflict。若被占用直接弹出红色提示,体验远优于「提交后才报错」。

6.2 报价单:明细动态计算

报价单创建页支持前端动态加行并计算小计,提交时将 items 数组 JSON 化传至后端。

后端 QuoteController::save 解析 JSON 后循环计算总价,连同明细入库。报价单转订单亦可一键完成,复用客户和金额字段。

6.3 13 个外贸工具的集成

将外贸人常用的十几个小工具(关键词生成、时差查询、黄页导航等)集成进系统,做成侧边栏折叠菜单。

每个工具即为独立 view(如 views/tools/1.b2b.php ... 12.huangye.php),控制器仅需简单 render 调用。工具逻辑全在前端 JS,不占后端资源,也不增加数据库负担。

心得:并非所有功能都要后端化。纯前端工具应留在前端,后端仅负责持久化和权限控制。「厚前端薄后端」的分工让系统更轻盈。

虽然生产环境需改为正式域名,但这带来重要启示:复杂能力可独立部署再嵌入。AI 工具迭代快,与 CRM 主系统解耦后,AI 端可独立升级而不影响 CRM 稳定。

七、第三方接口的「预留」哲学

本项目特别之处在于:AI 邮件、邮箱验证、邮件发送、海关数据、支付等功能均为模拟实现,但全部预留了接口开关。

config/api.php 中每个第三方服务均配置 enabled/api_key/api_url 三件套:

业务代码通过 if (config('api.doubao.enabled')) 切换「模拟返回」与「真实调用」。

为何如此设计?

  1. 开发阶段不依赖外部服务:AI 接口收费、邮件接口需配域名、支付需资质,开发时若全卡住将无法编码。
  2. MVP 先跑通流程:模拟发送邮件设定 90% 成功率,确保前端逻辑、状态流转、错误处理全跑通,接真实接口时仅需替换函数。
  3. 降低用户上手门槛:用户装完即用,无需先申请一堆 API key,待用熟后再配真实接口。

心得:预留接口是工程上的「渐进式替换」策略,而非偷懒。但需警惕陷阱——模拟实现与真实实现的行为应尽量一致。例如模拟邮件发送设定 90% 成功、10% 失败,旨在测试前端对失败状态的处理。若模拟永远成功,上线后必因未测失败处理而出错。

八、会员体系与商业化预留

系统设计之初即考虑商业化,memberships 表包含配额字段:

max_customers          -- 最大客户数
max_leads_per_month    -- 每月线索数
max_emails_per_month   -- 每月邮件数

设 4 档套餐:免费版(¥0,50 客户)、基础版(¥99)、专业版(¥299)、企业版(¥999,无限)。

心得:商业化字段需一开始就设计好,切勿等做付费时再加。后加配额字段意味着要修改所有写入点并增加校验,工作量翻倍且易遗漏。第一版即在 customers 写入前预留配额检查钩子。

支付接口(微信/支付宝)同样预留配置项,后台设有支付配置页和记录展示。真正接入时,前端下单→支付→异步通知→开通会员的链路清晰可见。

九、踩过的坑与反思

9.1 安装脚本的 DELIMITER 坑

install.php 用 PDO 执行 SQL 文件,但 PDO 不支持 DELIMITER // 语法(此为 mysql 命令行客户端特性),导致存储过程段报错。

解法:用正则去掉存储过程段,逻辑改用 PHP 实现。

$sql = preg_replace('/DELIMITER\s\/\/.?DELIMITER\s;/is', '', $sql);

反思:这是绕过的坑,非彻底解决。若未来真需用存储过程,得用 multi_query 或单独迁移脚本。此事表明:SQL 文件并非跨工具可移植,DELIMITER、CREATE PROCEDURE、触发器等均属 mysql 客户端特性。

9.2 路由器的「约定式」陷阱

路由器自动将 controller/action 解析成类,省去了写路由表,但也导致任何不存在的控制器均返回 404,而无明确「路由未注册」提示。

早期因拼写错误(custmer 少个 o),用户点击即 404,后端却无日志记录访问痕迹。若用显式路由表,未注册路由一开始便会暴露。

教训:约定优于配置虽好,但调试性差。折中方案是:显式注册核心路由 + 兜底约定式解析,既保留灵活性又有可观测性。

9.3 权限控制停留在「展示」层

admin/permissions 页面展示了角色权限矩阵,但 Auth::can() 的细粒度校验并未在所有控制器方法中落地。例如「普通用户不能删除客户」的规则,代码中实际未拦截。

反思:权限设计要「先做减法再做加法」。与其设计一套 RBAC 矩阵却落地不全,不如先将「管理员 vs 普通用户」的二态权限做扎实,待真有多角色需求再上 RBAC。半套权限系统比没有更危险——它给人「已防护」的错觉。

9.4 报价单 PDF 的妥协

报价单「生成 PDF」功能最终仅输出了 HTML:

header('Content-Type: text/html');
echo $this->renderQuoteHtml($quote, $customer);

理由是 TCPDF/mpdf 库体积大、虚拟主机运行慢。但这对用户是半成品体验——他们需要可下载的 PDF 文件,而非网页。

教训:功能可分期做,但要明确标注「未完成」。代码注释中的 TODO 在迭代中易被遗忘,后来在需求文档中专门列出「待完善项」清单,集中管理此类半成品。

十、给后来者的几条建议


若重来一次或给类似项目建议,我会说:

  1. 先想清楚给谁用,再选技术栈。给程序员用就上 Laravel + Docker;给外贸人用就 PHP + XAMPP。技术选型的第一约束是用户,而非技术本身。
  2. 核心类自己写一遍。框架用多了会「会用不会改」。亲手实现 MVC、ORM 基类、认证,能对底层机制形成肌肉记忆,排查问题快十倍。
  3. 第三方接口一律预留开关。任何付费/外部服务,开发阶段全用模拟,上线再切真实。但模拟行为要逼近真实(包括失败概率)。
  4. 安全措施做成默认项。CSRF、XSS、密码加密等不能是「可选」,必须在基类强制实施。一个疏漏就是一次事故。
  5. 状态机能简单就简单。公海私海一个 is_public 字段搞定,别拆两个字段。复杂度是累加的,每多一个字段就多一份不一致风险。
  6. 待办事项集中管理。所有 TODO、半成品、预留接口都写入清单文档,定期 Review。散落在代码注释里的 TODO 会被遗忘。
  7. 前端工具能独立就独立。纯展示型工具(导航、生成器)让它们待在前端,后端只管需要持久化的业务。系统越薄越稳。
  8. 会员配额字段一开始就建好。商业化字段后加成本极高,第一版表结构就要留好位置。
  9. 安装流程要傻瓜化。制作 4 步安装向导(环境检测→数据库→管理员→完成),这对非技术用户是刚需。难装的系统,功能再强也推不开。
  10. 写文档。不是写给别人看,是写给三个月后的自己看。撰写需求方案文档的过程,让我重新审视了整个项目,发现了 7 处待完善——写文档是最好的代码 Review。


十一、写在最后

这个项目不算大,但五脏俱全。从需求定位、技术选型、架构设计、数据库建模、安全实践、第三方集成、商业化预留,到踩过的坑和反思,它完整呈现了一个「能跑且能卖」的 SaaS 雏形是如何诞生的。

它不完美——PDF 未真做、权限未全落地、多语言没埋钩子、AI 接口仍是模拟。但它有一个最大优点:每一行代码都知道为什么这么写,每一个妥协都记录在案。

做产品最大的敌人不是技术难度,而是「不知道为什么这么做」的混沌状态。把这个项目从混沌推到「清晰且有据可查」,是此次开发最大的收获。

如果你也在做类似项目,或对某个模块的实现细节感兴趣,欢迎交流。代码和完整的需求方案文档均在仓库中,本文即是它的「开发日记」。



【声明】内容源于网络
0
0
陈金凌
各类跨境出海行业相关资讯
内容 2814
粉丝 2
陈金凌 各类跨境出海行业相关资讯
总阅读39.4k
粉丝2
内容2.8k