恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
自研桌面CRM实战:从数据模型到性能优化的完整技术复盘
首页
资讯中心
/
自研桌面CRM实战:从数据模型到性能优化的完整技术复盘
自研桌面CRM实战:从数据模型到性能优化的完整技术复盘
发布时间:2026/9/19 10:38:25
1. 为什么一个几十人的销售团队需要自己造CRM这辆“车”1.1 从Excel和微信工作群里的“客户管理”说起每个销售团队在规模超过某个临界点后都会经历一段极其痛苦的“混沌期”。客户资料散落在销售的个人Excel表格里有些沉淀在微信聊天记录里还有一些躺在各类名片扫描App中。管理员想统计本月新增客户数问一圈下来每人交上来的表格格式都不一样光整理数据就要花半天。这个问题不是某家公司特有的几乎所有中小型销售团队成长到20人左右时都会遇到。DeskcommCRM这个项目的起点正是我们团队在某个月度复盘会上暴露出来的数据问题。当时我们做B2B企业服务销售周期长客单价高一个客户往往需要跟进几个月中间要经历多次沟通、方案调整、报价确认。人少的时候销售自己心里有本账客户状态、下一步计划都装在脑子里。但人一多再加上人员流动客户资料交接不干净丢客户、撞客户、漏跟进的情况开始频繁出现。领导问起来销售说“在推进”但具体推进到哪一步谁也说不清。1.2 被通用CRM折磨的三个月功能很多能落地的很少决定上CRM之后我们第一时间试用了几款市面上主流的SaaS产品。说实话产品本身不小客户管理、销售漏斗、工作流自动化、呼叫中心集成……功能清单拉出来很长试用期一开始大家也很兴奋。但用了不到两个月问题就暴露出来了。最大的问题不是功能不够而是功能太多、配置太灵活。灵活意味着用户需要花大量时间去设计流程、配置字段、画审批流才能真正用起来。负责牵头的人如果本身没有足够的业务理解很容易把系统配成一个看起来很专业、实际用起来非常别扭的“四不像”。其次是权限问题。SaaS产品的权限模型往往是通用型的“角色-权限”模式但我们的业务场景里有非常特殊的“客户认领”“销售保护期”“公海回收”逻辑通用CRM很难通过简单配置实现只能做得很曲折。最后是数据安全。客户资料是我们公司最核心的资产之一全部放在别人的云服务器上虽然合同里有保密条款但心里始终不踏实。试用三个月的结论是功能强大不代表适合自己。我们需要的是门槛低、贴合业务、能随时改的CRM而不是一个功能百科全书。1.3 DeskcommCRM的立项目标做一套能真正随业务走的工具正是这段经历让我们萌生了自研一套桌面CRM的想法。DeskcommCRM这个名字当时取的是“Desk Communication CRM”的意思定位是一个跑在桌面端、强调沟通与协作的客户管理系统。选择桌面端而不是Web端是因为销售日常工作大量依赖本机数据客户资料、沟通记录如果能在本地存储性能和离线使用体验会好很多。立项时我们定了三个核心目标第一数据必须自主可控所有客户资料存在本地数据库备份和迁移足够简单第二业务逻辑必须贴合自己的流程比如客户认领规则、跟进计划提醒、销售保护期等这些都要按我们的规则来实现第三使用门槛要低销售团队没有太多时间学习复杂系统打开就能用最好不用培训。后来的实践证明这三个目标定得还算明确但实现起来每一步都有不少坑。在正式讲技术细节之前先说明一点DeskcommCRM并不是一个商业产品它只是我们内部团队用了很长时间的一套业务工具。这篇文章想把其中比较核心的设计思路、实现细节和踩坑经验写出来给那些同样在考虑自研内部系统的团队一些参考。2. DeskcommCRM的技术选型与数据模型先把地基夯实2.1 为什么选Electron React SQLite技术选型是项目启动后第一件要拍板的事。我们团队之前主要写JavaScript和前端所以桌面端技术选型上优先考虑的是我们拿得动的方案。桌面端框架我们在Electron和Tauri之间犹豫过。Tauri的包体积小、内存占用低但当时Rust的生态还不算成熟团队里没人写过Rust遇到问题很难搞。Electron虽然被很多人吐槽“跑个桌面应用跟开个浏览器一样”但它最大的优势是生态成熟、文档多、出问题能搜到答案。对一个内部工具来说稳定性和可维护性远比虚荣的包体积重要所以最终选了Electron。前端界面用的是React Ant Design。Ant Design对于这种后台管理类界面太合适了表格、表单、日期选择器都是现成的能省下大量开发时间。打包工具用的electron-builder数据库用了SQLite通过better-sqlite3这个库来访问。为什么选SQLite而不是直接连服务器上的MySQL因为产品定位是桌面端优先数据先落在本地再通过同步机制和服务器交互。本地用SQLite最合适零配置、单文件、性能足够。这里也说一个反直觉的经验Electron的内存占用确实不低但在现代办公电脑上完全可接受。实际使用中DeskcommCRM常驻内存大概在180MB左右对于一个需要长期开着、随时录入数据的工具来说这个量级没有造成任何困扰。2.2 核心数据表设计客户、联系人、跟进记录数据模型是整个系统的灵魂。如果表结构设计得不好后面加功能的时候会非常痛苦。我们第一版大致设计了这些表customers、contacts、follow_ups、tasks、users、customer_owner_history、operation_logs。下面把最核心的几张表拿出来讲。customers表是核心存客户的基本信息和管理字段。基本信息包括公司名称、行业、规模、来源渠道、客户状态等管理字段包括归属人、保护期截止时间、最后跟进时间、下次跟进时间、创建时间等。contacts表存客户下的联系人。一个客户可能有多个联系人比如决策人、技术对接人、财务对接人。联系人信息包括姓名、职位、手机、微信、邮箱等。follow_ups表存每次跟进记录这是销售团队的“工作日志”包括跟进方式电话、微信、上门、邮件、跟进内容、下一步计划等。-- 客户主表部分字段 CREATE TABLE customers ( id INTEGER PRIMARY KEY AUTOINCREMENT, company_name TEXT NOT NULL, industry TEXT, company_scale TEXT, source_channel TEXT, status TEXT DEFAULT new, -- new: 新客户, following: 跟进中, won: 已成交, lost: 已流失 owner_id INTEGER, -- 归属销售 protected_until TEXT, -- 保护期截止时间 last_follow_up_at TEXT, -- 最后跟进时间 next_follow_up_at TEXT, -- 下次跟进时间 created_at TEXT DEFAULT (datetime(now, localtime)), updated_at TEXT DEFAULT (datetime(now, localtime)) ); CREATE INDEX idx_customers_owner ON customers(owner_id); CREATE INDEX idx_customers_status ON customers(status); CREATE INDEX idx_customers_next_follow ON customers(next_follow_up_at);设计时有一个反复权衡的点跟进记录和任务到底该分成两张表还是合成一张表最后我们分开了。跟进记录是历史不能变任务是待办会改状态。混在一起的话查询历史时会很别扭。这个分法后来被证明是对的因为当团队开始做数据统计时跟进记录直接被拿来算工作量而任务表主要服务于提醒和待办列表两者完全独立。2.3 客户归属与权限模型的设计客户归属是CRM里最敏感的业务逻辑。在我们的销售流程里一个客户一旦被销售认领就进入该销售的名下其他销售默认不能查看。但如果销售超过一定时间没有跟进客户会被释放回“公海”其他销售可以重新认领。这套逻辑在很多CRM产品里叫“公海池”和“回收规则”。权限模型我们做得很简单没有用复杂的RBAC就是三种角色管理员、销售组长、销售。管理员能看到所有数据销售组长能看到本组所有销售的数据销售只能看到自己的客户。为什么不用更细的权限因为业务阶段决定了授权模型越复杂出问题的地方越多。员工离职交接时我们只需要把客户从离职销售名下批量转移给指定销售或者释放回公海就够了。还有一个细节是数据可见性。销售之间默认不可见但同组销售在“撞单”时又需要核对。我们的处理是同组销售之间可以看到客户名称但看不到联系方式和跟进记录如果要“申请协作”得由组长审批后打开共享。这个设计在权限和协作之间取得了平衡。2.4 数据字典与字段扩展性刚用自研工具的人大概率都会遇到一个问题过了三个月业务部门说“我们要在客户上加一个字段”。如果代码里硬编码字段就会很麻烦。我们一开始就把字段定义做成了数据字典模式客户表的扩展字段存成JSON需要新增字段时在界面配置即可不需要重新建表。这么做有个好处也有个坏处。好处是灵活加字段快坏处是JSON字段无法参与索引查询性能会受到一定影响。我们目前的处理方式是高频查询的字段仍然使用独立的业务列低频的、只是展示用的字段才放JSON。比如客户列表页的筛选条件中“行业”和“来源渠道”是高频筛选字段所以它们在customers表里有独立列和索引像“客户预算范围”“采购决策链”这类只用来详情展示的字段就统一丢进extra_info的JSON列里。这个折中方案实践下来效果不错。3. 核心功能模块的落地从原型到可用的距离3.1 客户池与公海回收机制不止是定时任务这么简单客户池公海是销售CRM的核心机制之一。销售如果长期不跟进客户系统应该自动把客户释放到公海让其他有意愿、有精力的销售去接手。这个逻辑看起来简单实现起来要解决几个实际问题。第一个问题什么叫“长期不跟进”我们在系统里定义的是“超过7天没有新增跟进记录客户自动释放”。判断依据是customers表的last_follow_up_at字段。这个逻辑通过一个定时任务扫描实现每天凌晨自动跑一次。但实际问题比这复杂比如周末算不算7天里法定节假日要不要顺延后来我们做了个配置项允许管理员自定义“N个自然日未跟进”和“跳过节假日”两个参数默认值还是7天。第二个问题释放之后客户保留多少历史数据释放时不能把跟进记录清了新销售认领后必须能看到历史跟进记录才能快速了解客户情况。所以释放操作只是改了客户归属业务数据统统保留。我们专门建了customer_owner_history表记录每一次归属变更包含从谁转移到谁、什么时间、什么原因手动分配、公海释放、离职交接这张表后来帮我们解决了很多次“客户到底是谁的”这类纠纷。第三个问题保护期。我们给新认领的客户设置了7天保护期。在保护期内组长可以把客户收回重新分配给其他人比如认领错了但其他销售不能抢。过了保护期就按照“超过7天未跟进”的规则正常流转。这块如果用SQL实现就是每次查询时先过滤一下当前时间和protected_until的关系代码不复杂但对业务理解的要求很高。3.2 跟进计划、日程提醒与任务中心销售的大脑外包销售跟进客户不能靠脑子记系统必须主动提醒。我们做了一套“任务中心”每个客户都可以生成跟进任务。比如在跟进记录里勾选“两周后再联系”系统会自动在任务中心生成一条待办时间到了自动提醒。提醒的实现方式包括两种一种是Electron主进程里的Notification通知直接弹Windows系统通知另一种是应用内红点提醒。Electron的Notification接口用起来很简单但要注意Windows上的Toast通知需要配合app.setAppUserModelId才能正常显示这个坑我们踩过。如果不设置在某些Windows版本上通知可能弹不出来或者弹出来不显示应用名称直接显示“Electron”四个字非常尴尬。任务还可以分级和设置优先级。我们的任务是按“到期时间客户状态”动态排序的今天到期的任务排最前面高价值客户状态为“跟进中”且客单价高的任务排前面。这个排序逻辑上线后销售每天打开系统的第一件事就是看任务中心从这里知道今天该干什么。3.3 可视化看板从统计报表反推需求销售管理者最需要的是数据看板。我们第一版做了一个简单的“今日概览”包括今日新增客户数、今日跟进次数、今日到期任务数、本周成交金额等。后来又加了“销售排行”和“客户状态分布”两个图表让组长能看到每个人的工作量和业务转化情况。图表库用了Ant Design Charts最初是为了快速集成后续如果不够用再换ECharts。这里有个真实经验Charts对常见需求覆盖得不错柱状图、饼图、折线图都很顺手但一旦要做复杂的自定义图表——比如带联动筛选的下钻漏斗或者某个特定场景的甘特图就会觉得还是ECharts更灵活。我们目前是两者共存90%的场景用Charts遇到特殊需求时再单独引入ECharts。看板数据的实时性也值得聊一下。最初我们做的是每次打开页面时重新查询数据库后来发现销售们习惯把看板页面一直开着挂在大屏上频繁查询没有必要就改成了每5分钟自动刷新一次。对于内部管理工具这种“准实时”的刷新频率已经足够没必要追求秒级。3.4 搜索与全局检索从LIKE到FTS5客户多了之后快速找到目标客户是非常核心的操作。我们在顶部做了一体化搜索框支持按客户名称、联系人姓名、手机号、微信号搜索。由于数据在本地SQLite里最简单的方案就是SQL的LIKE查询。但到了几万条数据之后LIKE %keyword%的前缀匹配会变慢特别是多表关联时的检索更明显。我们的排查过程是这样的先用EXPLAIN QUERY PLAN查看SQLite的执行计划发现每次搜索都会做全表扫描然后尝试给高频字段加索引但必须承认LIKE %keyword%这种前后模糊的写法根本走不了普通索引。最后的方案是主要的客户列表和联系人搜索用带索引的列搜索时支持手机号精确匹配、客户名称的FTS5全文搜索。FTS5是SQLite内置的全文搜索引擎建虚拟表和触发器同步后搜索速度提升非常明显。比如原来搜“科技”两个字要遍历全部5万条客户记录耗时大概在600到800毫秒改用FTS5后基本在100毫秒以内返回结果。值得一提的是FTS5的虚拟表同步也是需要小心处理的。如果你直接在customers表上建了FTS5触发器那么每次INSERT、UPDATE、DELETE都要触发同步。批量导入数据时如果逐条插入性能会惨不忍睹。我们的做法是批量导入时先关掉触发器导入完再重建FTS索引。SQLite提供了INSERT INTO fts_table(fts_table) VALUES(rebuild)这种内建命令一行代码就能全量重建索引速度比逐条同步快好几个数量级。4. 开发过程中的关键实现选几个有代表性的功能深入讲讲4.1 批量导入与客户查重Excel迁移的第一道坎团队从Excel迁移到DeskcommCRM的第一个障碍就是历史客户数据怎么导进去。Excel导出成CSV再写一个导入页面用户上传文件后端解析写入数据库。看起来不难但有几个坑。第一个坑是编码。中文Windows下Excel导出的CSV默认是GBK编码程序读取时如果不判断编码中文会变成乱码。我们的处理方式是上传文件后先用jschardet检测编码再读取内容。现在看这一点好像很简单但当时是上线后才遇到的问题用户导出一批数据全是乱码非常头疼。第二个坑是数据清洗。Excel里经常有合并单元格、换行符、多余空格、数字被自动变成科学计数法等问题。我们写了一个清洗函数把常见问题统一处理掉包括把手机号强制转成文本、去首尾空格、把空值统一为NULL。这里分享一个细节手机号如果以文本格式存从Excel复制出来特别容易带隐藏的零宽字符肉眼看不出来但程序比对时就是不一致。我们后来在清洗函数里显式去掉了\u200b、\u200c、\u200d这类特殊字符。第三个坑是查重。客户导入时必须判断是否已存在。我们规定手机号完全一致就认为是同一个联系人联系人完全一致就把客户信息合并到已有客户上。查重逻辑不能做得太严格否则导入一批有微小差异的客户会全部失败也不能太宽松否则会漏掉重复数据。我们做了两档匹配精确匹配手机号、模糊匹配姓名公司名称的相似度。模糊匹配用的字符串编辑距离算法Levenshtein Distance阈值为0.85。批量导入的代码不算复杂但数据容错非常重要。一条数据格式不对不应该导致整个导入失败应该记录错误原因让用户下载错误报告后修改再导入。我们的导入页面会实时显示进度结束后生成一份“导入错误报告.csv”每行标注是哪一条数据、哪个字段有问题、该怎么改。这个体验细节让用户对系统的信任度提升了不少。4.2 提醒系统的实现从轮询到主动推送前面提到的任务提醒我们第一版用的是每30秒轮询一次数据库查有没有到期的任务有就弹通知。这个方案实现简单但问题在于如果任务到期时间正好落在两个轮询周期的中间提醒会晚几十秒。对内部工具来说晚几十秒倒无所谓但轮询的额外开销和桌面应用应有的体验不符。后来改成了Electron主进程和渲染进程的IPC联动每次打开应用时主动拉取一次所有未完成任务操作任务时通过IPC通知主进程更新提醒状态主进程仍然保留定时器做兜底但缩短到每5分钟一次。改完之后提醒基本是实时的而且定时器的资源占用小了很多。Electron实现系统通知的代码很简单核心就这几行// 主进程 const { Notification } require(electron); app.setAppUserModelId(com.deskcomm.crm); function showTaskNotification(task) { if (!Notification.isSupported()) return; const notification new Notification({ title: 待跟进${task.customer_name}, body: ${task.content}截止时间${task.due_at}, silent: false, }); notification.on(click, () { mainWindow.show(); mainWindow.focus(); mainWindow.webContents.send(navigate-to-task, task.id); }); notification.show(); }点击通知时唤起主窗口并跳转到对应任务这个交互对销售来说很贴心。他们看到弹窗点一下系统直接定位到那条任务不需要自己在列表里翻。4.3 本地数据的同步与冲突处理追加式日志是救命稻草数据全部存在本地SQLite那多人协作怎么办销售A添加了一个客户销售B怎么能看到我们的做法是每个客户端在本地维护一个同步表sync_queue所有写操作都先写入本地库同时往同步表里塞一条待同步记录。后台线程持续把待同步记录推送到服务器服务器再把变更广播给其他在线客户端。同步方向是双向的冲突处理简单粗暴以最后修改时间为准Last Write Wins。对于客户资料这种低频更新场景LWW策略足够用。但如果涉及到金额、状态这类敏感字段的并发修改LWW可能产生覆盖。我们这边的经验是重要的状态变更尽量做成追加式日志而不是更新字段。比如“客户状态从A变成B”的操作在数据库里插入一条状态变更记录而不是直接改customers表的状态字段。这样即使同步冲突也能从历史记录里找出事实来源。这里有一个很现实的问题同一时间两个销售都在自己的客户列表里把同一个客户的状态改成了“已成交”以最后修改时间为准可能其中一个人的修改被覆盖了。但因为状态变更是追加日志的模式管理员在操作日志里能看到两条记录必要时可以人工纠正。如果直接改字段被覆盖的那个销售可能要过很久才会发现自己的修改丢了。4.4 桌面端的用户体验细节快捷键和离线能力桌面应用和Web应用的使用体验差异在几个小细节上体现得很明显。快捷键。销售录跟进记录是高频操作我们绑定了全局快捷键CtrlShiftK来快速呼出“新建跟进”窗口这样即使销售在别的窗口写邮件、查资料也能一键呼出系统录入信息。这个功能上线后大家反馈“终于不用来回切窗口了”使用频率比我们想象的还高。离线可用。由于数据在本地即使办公网络断了销售依然可以正常查看客户资料、录入跟进记录。等网络恢复后同步线程自动把离线期间的变更推送到服务器。对经常跑外勤的销售来说这个体验是Web版CRM完全给不了的。还有一个细节是启动速度。第一版应用启动要3到4秒主要是初始化数据库连接和重建索引。后来我们把数据库预热加到了启动加载页里启动时显示一个非常轻量的品牌页面后台并行做数据初始化。整体启动时间控制在1.5秒左右用户的感知好了很多。5. 上线后的复盘性能优化的坑和体验改进的迭代过程5.1 当客户数据到5万条时列表和搜索都开始卡了上线前我们测过几千条数据一切流畅。上线三个月后客户总量接近5万条列表滚动、全局搜索开始出现明显卡顿。这属于“能用但很不爽”的状态。定位问题花了点时间。第一个瓶颈是列表渲染一次查询加载了全部符合条件的记录比如2000条客户每行又有多个列渲染开销一下就上去了。解决方案是后端分页加前端虚拟滚动。React的antd表格自带分页能力但我们做了大量自定义操作一开始没接好。后来把列表改成了服务端分页每页50条加上一个轻量级的虚拟滚动库卡顿问题解决了一大半。第二个瓶颈是索引缺失。我们有last_follow_up_at字段参与排序最初建表时没加索引导致ORDER BY越来越慢。检查SQLite的EXPLAIN QUERY PLAN之后给高频排序字段加上了索引查询时间从几百毫秒降到了几十毫秒。这里也提醒了大家不要等到卡了才建索引表在建完后就应该把常用的查询条件列出来把索引一次性配好。-- 查看SQLite执行计划 EXPLAIN QUERY PLAN SELECT * FROM customers WHERE owner_id 1 ORDER BY last_follow_up_at DESC LIMIT 50; -- 加索引后的执行计划 CREATE INDEX idx_customers_owner_follow ON customers(owner_id, last_follow_up_at DESC);第三个瓶颈是表格列太多。客户列表有十几个字段每行都要渲染十几个列即使数据量不大也会造成滚动时的性能压力。我们的做法是默认只展示8个核心字段其余字段通过“列设置”按需勾选。这个改动表面上是为了性能实际上也提升了操作效率——信息密度降低后销售更容易聚焦到关键字段上。5.2 数据安全与备份策略本地数据绝不能只存一份数据在本地有个风险电脑坏了怎么办文件被误删怎么办所以备份策略必须在一开始就想好。我们的做法是三层备份。第一层是服务器端主库所有变更实时同步到服务器服务器数据库可以做每日快照。第二层是客户端自动备份每天应用退出时本地数据库文件压缩成一个带日期的备份文件保留最近30天。第三层是手动备份在设置界面提供“导出全部数据”按钮导出成一个加密的JSON文件方便做最终归档。这里有个细节值得强调SQLite的备份不能直接复制数据库文件。因为在写入过程中直接复制文件很容易得到一份损坏的数据库。我们用的是SQLite官方推荐的在线备份API即sqlite3的backup()函数通过这个接口生成一致性快照。在better-sqlite3中可以通过db.backup()方法实现。5.3 从“不愿意用”到“离不开”的三次迭代第一版上线时销售们其实是抵触的。很多人觉得我已经有自己的Excel了为什么要用你这个系统最开始两周录入率和更新率都很低。我们没有强制要求而是观察大家的使用习惯找到阻力最大的环节。结果发现大家不愿意用不是因为懒而是录入成本高。原来的Excel里客户信息、跟进记录都是手打的自由文本新的系统里我们设计了十几个字段其中很多是必填的录一个客户要花三分钟太费劲。于是我们做了第一次重要调整把必填字段从十几个减少到四个录入页面重新设计打开后光标自动定位到公司名称输入框。操作路径缩短后录入率明显上升。第二次调整是把“录入客户”和“录跟进”这两个孤立动作串联起来录完一个客户系统自动生成一条待办——“给这个客户打第一通电话”。这条待办会出现在任务中心里销售打开系统就能看到今天该做什么。第三次调整是加入“销售排行榜”看板。虽然有点“内卷”的味道但销售团队确实有竞争心理看到自己的名字排在后面自然会想把客户跟进得更勤一些。三次迭代之后系统从“公司要求用”变成了“我们自己想用”。有个销售在换电脑后第一句话是“赶紧帮我把DeskcommCRM装回来我客户资料都在里面”听到这句话我就知道这个项目算是立住了。6. 如果你也想做一套公司内部的业务工具几点掏心窝的建议6.1 哪些场景适合自研哪些不适合自研一套内部业务系统既要考虑成本也要考虑风险。我觉得最核心的判断标准是你的业务流程是否足够特殊、足够稳定如果你们跟同行一样用一套标准的销售流程大概率直接买成熟的CRM更划算别折腾。但如果你们的流程里有一些不标准但约定俗成的规则比如特殊的分配机制、特定的保护期逻辑那么自研能让你把这些规则变成系统的默认行为而不是在通用系统里靠一堆折中方案硬凑。另外自研工具得考虑维护成本。内部系统一般没有专职团队长期维护如果开发这个系统的人离职了后面谁来改代码所以代码质量、文档、部署方式都要有意识地面向“未来的接盘侠”来做。我们当时给DeskcommCRM写了一份简单的架构文档里面记录了技术栈、目录结构、同步流程和常见问题后来新同事接手时帮了大忙。6.2 低成本起步的一些建议如果你决定做我的建议是别一上来就放大炮。第一版不要追求功能多先把“录客户、查客户、录跟进、看数据”这四个最核心的动作做扎实。至于报表、权限、公海、自动化放到第二期、第三期再做。很多团队在自研工具上失败不是技术不行而是初期需求范围失控做了半年还在做“平台”。技术栈方面我强烈建议用团队最熟悉的语言。DeskcommCRM选Electron是因为团队会JavaScript如果你团队会Python那可以考虑PyQt或Tauri加其他前端但凡是能让自己快速上手的方案就是好方案。不要为了追求所谓的技术先进性选一个团队没人熟悉的架构那样项目大概率会烂尾。6.3 对DeskcommCRM后续的规划这个系统到目前为止解决了我们的核心问题客户数据集中管理了跟进记录完整了销售交接有底了。但要说它完美肯定不是。当前最让我头疼的是报表能力还太弱销售管理者想要的漏斗分析、转化率、回款周期这些现在还没有做到位。下一步我会重点补上这块同时考虑做一个简单的API层方便以后和其他系统比如财务软件对接。另外还有一点是移动端。销售外出拜访客户时偶尔需要在手机上快速查一下客户资料。我们目前还停留在桌面端移动端最多是把数据同步到服务器用Web版临时应急。长期来看做一个轻量的移动端应用或者至少是移动适配的H5页面会是提升使用体验的重要方向。不过这属于下一阶段的事了内部工具的开发要跟着业务节奏走不能为了堆功能而堆功能。