在几个免费CRM之间来回切换折腾了大半年之后我下定决心把客户管理彻底收回来自己搭了一套DeskcommCRM——一套长期运行在自己服务器上、完全由自己掌控数据和功能的CRM系统。说实话这个决定最初被团队里的同事质疑过明明有现成的免费CRM为什么还要折腾一个“私人网站”但跑了大半年后这种“永久在线”的自托管方案带来的自由度是任何第三方免费套餐都给不了的。这套系统现在承担着我们整个销售团队的客户信息管理、跟进记录、商机流转和合同提醒每天都有十几个人在同时使用。这篇文章就把我搭这套DeskcommCRM的完整思路、技术选型、部署流程和踩坑记录整理出来。如果你也在犹豫要不要自建CRM或者已经在用免费CRM但被各种限制卡得难受这篇文章应该能给你一个比较完整的参考。1. 为什么把CRM从SaaS手里收回来1.1 免费CRM的“免费”到底意味着什么市面上所有打着免费旗号的CRM本质上都不是在做慈善。免费套餐看起来功能齐全但真正用起来你会发现每个关键节点都有一堵看不见的墙。最直接的痛点是数据量限制。我最早用某款知名免费CRM时联系人数量超过500条就开始频繁弹窗提示升级导出功能也被限制成只能导出部分字段甚至字段顺序都被固定死。对于一个销售团队来说500条客户记录差不多就是两三个月的量之后要么删旧数据要么付费没有任何中间选项。更隐蔽的问题是数据主权。你用免费CRM录入的每一家客户、每一个联系人、每一次跟进记录都存在别人的服务器上。对方修改隐私条款、调整服务边界、甚至直接停止某项功能你作为用户基本没有议价能力。我看过不少团队因为SaaS产品调整收费策略被迫在短期内迁移几万条客户数据的案例那种感觉就像房子的产权是别人的你只是租客房东说涨租就得涨租。还有一类“永久在线”的SaaS网站表面上一直能用但背后的服务稳定性并不受你控制。对方做一次架构升级可能你的某些页面就白屏了对方某个接口改了鉴权方式你的自动同步脚本就全部失效。这种不确定性在做to B业务时非常致命——客户数据是公司最核心的资产之一不该建立在别人随时可能变更的沙地上。1.2 免费CRM与自建私人网站的核心区别这里要讲清楚一个很多人混淆的概念免费CRM和自建CRM也就是自托管私人网站式的CRM到底差在哪里。免费CRM本质上是租用模式。你用的是别人开发好的产品数据存在别人的数据库里功能边界由别人定义。好处是上手快不需要维护服务器坏处是灵活性低、数据归属模糊、长期成本不可控。自建CRM本质上是自有模式。你买一台服务器装好系统域名解析过来所有数据都存在自己的数据库里。你说加一个字段就加一个字段说改一个流程就改一个流程没有任何人限制你。代价是你需要承担运维工作——服务器要续费、系统要更新、备份要做、安全要管。我列一个对比表方便你直观感受两者的差异对比维度免费SaaS CRM自建CRM私人网站式数据归属存在厂商服务器厂商可接触存在自己服务器完全自主掌控功能边界固定受套餐限制完全自定义想怎么改怎么改使用人数通常有上限超出要付费取决于服务器性能无软件层限制长期成本免费期后可能强制收费迁移成本高云服务器费用固定数据自由可迁移扩展性依赖官方API受限开源或自研代码完全可控维护难度零维护厂商负责需要自己管备份、安全、升级稳定性依赖厂商不可控取决于自己的运维水平通常较稳定所以“免费CRM与私人网站的区别在哪”这个问题答案其实就一句话一个是租别人的房子一个是盖自己的房子。DeskcommCRM走的就是“盖自己的房子”这条路。前期确实多花了一些精力但之后每一次功能调整、权限变更、数据导出我都再也不需要看任何人的脸色。1.3 自托管CRM到底适合哪些人自建CRM不是万能解药它不适合所有人。如果你的团队只有两三个人客户量也不大直接用免费SaaS CRM是完全合理的。但如果你符合下面几个特征自托管方案就值得认真考虑了第一客户数据量大且敏感。制造业贸易公司、医疗健康、金融咨询这类行业客户资料和合同信息非常敏感数据放在第三方平台本身就是合规风险。自己搭建一套系统数据不出自己的服务器至少在物理层面保证可控。第二业务逻辑特殊标准CRM满足不了。标准CRM的销售阶段、跟进状态、权限体系都是预设好的如果你的团队有一套自己的打法——比如按区域加产品线双重维度管理客户每个客户经理只允许看到自己区域的数据——自建系统可以根据你的规则精确落地。第三你希望系统真正“永久在线”。这里说的永久在线不只是服务器不宕机而是产品和数据都不受任何第三方商业决策影响。只要你的服务器在续费、数据在备份这套系统就可以一直跑下去没有任何外部力量能突然叫停它。我做DeskcommCRM的时候团队正好是十几个人、几千条客户数据、有一套自己定义的销售流程三个条件全中。所以从结果看这个决定是值得的。2. DeskcommCRM的整体设计与技术选型2.1 为什么选择前后端分离 Docker ComposeDeskcommCRM的架构我第一版就想清楚了前端一套独立应用后端一套独立API服务数据库单独容器通过Docker Compose统一编排。很多人在自建系统时第一步就纠结“该选什么框架”我的建议永远是先想清楚怎么部署和怎么维护框架反而是次要的。前后端分离的好处是逻辑清晰。销售团队用的前端界面和后端业务逻辑完全解耦改前端样式不会影响后端数据接口改后端逻辑也不会牵扯页面渲染。我用的是前端Vue 3加Element Plus组件库后端用Node.js的Express框架数据库选了PostgreSQL。这个组合不是最花哨的但非常成熟稳定社区资料多遇到问题随便一搜就能找到答案。Docker Compose是这个项目里我最庆幸的一个选择。所有服务——后端、前端、数据库、反向代理——都定义在一个docker-compose.yml文件里任何一台新服务器上只要装了Docker和Compose一条命令就能把整套环境拉起来。对于要“永久在线”的系统来说这种可移植性极其重要。服务器到期换新机器的时候不需要重新配置任何环境直接把整个目录拷过去重启服务就完事。为什么不用LAMP一键安装包或者宝塔面板那种方案不是不能用而是对于要长期维护的项目来说容器化让依赖管理精确到版本级别。Node.js 18和PostgreSQL 16的版本组合被写死在镜像里永远不会因为某个系统库升级导致环境崩溃。实测下来Docker方式部署的CRM在搬迁和升级时省掉的时间不是一点点。2.2 数据模型怎么设计才经得起业务考验CRM的核心是数据模型数据模型设计得好不好直接决定这个系统能用多久。我一开始也想着把客户、联系人、跟进记录、商机全部塞进一个表里后来发现这是新手最容易犯的错误。标准的CRM数据关系是分层的。客户Customer是最高层实体代表一个公司联系人Contact属于客户代表公司里的具体对接人商机Opportunity关联客户代表一笔潜在的销售机会跟进记录Activity则分散关联到任意一个实体上记录跟这个客户或商机的每次沟通。我在DeskcommCRM里设计了几张核心表字段大致如下客户表公司名称、行业、地区、客户状态、来源渠道、负责人ID、创建时间、更新时间。联系人表姓名、职位、手机、邮箱、微信、所属客户ID、是否主要联系人。商机表商机名称、关联客户ID、预计金额、销售阶段、预计成交日期、负责人ID。跟进记录表关联对象类型客户/联系人/商机、关联对象ID、跟进方式电话/邮件/面谈/线上会议、跟进内容、下次跟进时间、记录人ID、创建时间。这套模型跑了大半年没有出现没法扩展的情况。关键点在于客户和联系人分开存可以支持一个客户有多个联系人的真实业务场景跟进记录做成多态关联不管跟进的是客户还是商机都能共用一张表。字段设计上我有一个比较深的体会状态字段一定要预留“其他”选项。很多团队的销售流程是不完全标准化的硬性枚举值会导致录数据的人找不到合适的选项最终在备注里乱填数据分析就废了。2.3 “永久在线”到底靠什么保证很多SaaS网站标榜“永久在线”但对于自建系统“永久在线”不是靠口号而是靠三样东西加起来的稳定的部署、自动的备份、可靠的监控。部署稳定是指服务器和网络环境可靠。服务器建议选大厂云服务器最低也要2核4G起步带宽按实际并发量估算。国内团队部署要注意ICP备案这个在买服务器的时候一定要先问清楚服务商否则域名解析会出问题。备份是“永久在线”的底线。我的策略是每天凌晨3点自动备份PostgreSQL数据库到本地磁盘同时压缩后同步一份到另一台存储服务器。备份保留最近30天每周一额外保留一份整周备份。数据是自建系统最宝贵的资产服务器可以随时换数据丢了就什么都没了。监控是很多自建项目最容易忽略的。我推荐用UptimeRobot这类免费服务每5分钟访问一次系统登录页如果连续3次访问失败就通过邮件和手机推送通知。另外在服务器上跑一个简单的cron脚本检查后端进程是否正常运行挂了就自动重启。别小看这些基础手段它们能保证系统在被你发现出问题之前已经自动恢复或者至少及时通知到你了。3. 从零部署一个永久在线的CRM网站3.1 服务器准备与环境初始化部署这套CRM的服务器配置我建议最低2核4G内存40G SSD硬盘带宽5M起步。这个配置足够支撑十几个人同时使用以及几千条客户数据的常规查询。如果你团队规模更大直接升到4核8G数据库性能和并发能力会宽裕很多。买好服务器之后第一步是更新系统并安装Docker和Compose插件。以Ubuntu 22.04为例先做基础更新sudo apt update sudo apt upgrade -y然后安装Docker官方脚本curl -fsSL https://get.docker.com | bash sudo usermod -aG docker $USER装完之后重启登录验证一下docker --version docker compose version接下来配置防火墙。这是很多人容易忽略的步骤——只开放必需的端口其余全部关闭。我在这台服务器上只开放了22SSH管理、80HTTP、443HTTPS数据库端口没有对外暴露只允许Docker内网访问。sudo ufw allow 22/tcp sudo ufw allow 80/tcp sudo ufw allow 443/tcp sudo ufw enable3.2 DeskcommCRM的容器编排配置整个系统的服务编排都写在docker-compose.yml里。我的配置大概长这样version: 3.8 services: db: image: postgres:16-alpine container_name: deskcomm-db restart: always environment: POSTGRES_USER: deskcomm POSTGRES_PASSWORD: your_strong_password POSTGRES_DB: deskcomm_crm volumes: - db_data:/var/lib/postgresql/data networks: - deskcomm-net backend: build: ./backend container_name: deskcomm-backend restart: always depends_on: - db environment: DATABASE_URL: postgresql://deskcomm:your_strong_passworddb:5432/deskcomm_crm JWT_SECRET: change_this_to_a_long_random_string networks: - deskcomm-net frontend: build: ./frontend container_name: deskcomm-frontend restart: always ports: - 8080:80 depends_on: - backend networks: - deskcomm-net nginx: image: nginx:alpine container_name: deskcomm-nginx restart: always ports: - 80:80 - 443:443 volumes: - ./nginx/conf.d:/etc/nginx/conf.d - ./certbot/conf:/etc/letsencrypt - ./certbot/www:/var/www/certbot depends_on: - frontend - backend networks: - deskcomm-net volumes: db_data: networks: deskcomm-net:几个需要特别说明的点数据库密码、JWT密钥这类敏感信息上生产环境时一定要用强随机字符串不要用123456这种。我用的生成方式是openssl rand -base64 32。数据库数据一定要挂载到命名卷db_data否则容器一旦删除数据全部丢失而且这种丢失经常无法恢复。frontend容器把Nginx的80端口映射为8080实际对外的80和443完全交给宿主机上的Nginx容器处理。这个分层设计让我可以独立升级前端镜像而不影响反向代理配置。3.3 Nginx反向代理与HTTPS证书配置永久在线的CRM网站必须上HTTPS。没有HTTPS数据在传输过程中是明文客户资料泄露的风险非常高。而且现在浏览器对HTTP站点都有“不安全”的警告标识给客户演示系统的时候特别掉档次。DeskcommCRM的Nginx配置我放在nginx/conf.d/crm.conf下server { listen 80; server_name crm.example.com; location /.well-known/acme-challenge/ { root /var/www/certbot; } location / { return 301 https://$host$request_uri; } } server { listen 443 ssl http2; server_name crm.example.com; ssl_certificate /etc/letsencrypt/live/crm.example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/crm.example.com/privkey.pem; location /api/ { proxy_pass http://backend:3000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } location / { proxy_pass http://frontend:80; proxy_set_header Host $host; } }证书用Let’s Encrypt免费证书配合Certbot容器实现自动申请和续期。首次申请时先把HTTP证书验证目录挂进去然后执行docker compose run --rm certbot certonly \ --webroot \ --webroot-path/var/www/certbot \ --email your_emailexample.com \ --agree-tos \ --no-eff-email \ -d crm.example.com证书有效期是90天如果不自动续期三个月后HTTPS就会失效。我在crontab里加了一条定时任务每天凌晨检查一次快过期时自动续签并重载Nginx0 3 * * * docker compose run --rm certbot renew --webroot docker exec deskcomm-nginx nginx -s reload3.4 备份策略与恢复演练部署完成后的第一件事不是宣布“上线”而是把备份策略跑通。DeskcommCRM的备份分两个层面数据库和配置文件。数据库备份我用的是PostgreSQL自带的pg_dump。在宿主机上写一个备份脚本#!/bin/bash BACKUP_DIR/opt/deskcomm/backups DATE$(date %Y%m%d_%H%M%S) docker exec deskcomm-db pg_dump -U deskcomm deskcomm_crm | gzip $BACKUP_DIR/db_$DATE.sql.gz find $BACKUP_DIR -name db_*.sql.gz -mtime 30 -delete数据库备份之外docker-compose.yml和nginx/conf.d这些配置文件同样需要备份因为它们记录了整套系统的部署逻辑。我是直接把整个/opt/deskcomm目录每天同步到另一台机器上的包括配置和备份文件。备份恢复演练是最容易被忽视但最重要的环节。我强烈建议你每季度做一次完整的恢复测试拿一台新服务器把备份文件拷贝过去启动容器导入SQL确认数据能正常访问。这个流程如果你从来没有跑通过那你的备份在真正出事的时候大概率也派不上用场。4. 团队协作与员工邀请的实现4.1 从单人使用到多人协作的权限模型DeskcommCRM从一开始就考虑了多人协作所以权限模型是核心模块之一。权限设计不合理的后果是要么所有数据对所有人开放泄露风险大要么权限过于僵硬销售人员之间无法共享客户信息。我采用了RBAC基于角色的访问控制模型。系统内置四种角色超级管理员拥有全部权限包括系统配置、用户管理、删除数据。销售经理可以查看所辖团队所有数据可以分配客户、审批商机、修改商机阶段。销售人员只能查看自己负责的客户、联系人和商机可以新增客户并创建跟进记录。只读成员通常用于财务或运营人员只能查看报表和数据不能修改任何记录。这个角色模型的落地并不复杂。用户表里加一个role字段后端在每个接口的调用入口处校验当前用户的角色和资源归属关系前端根据角色动态渲染可操作的按钮。权限校验的核心原则是后端永远要再做一次校验不能只靠前端隐藏按钮。4.2 员工邀请流程设计链接、权限和有效期系统上线后团队不可避免地要新增成员所以邀请员工这个流程必须做得丝滑。我之前用某些免费CRM时邀请员工只能通过邮箱收到邀请链接如果邮箱被垃圾邮件拦截新员工根本登不进来非常痛苦。DeskcommCRM的邀请机制我做了两条路邮箱邀请和邀请码邀请。管理员在后台点“添加成员”填写对方姓名和邮箱系统生成一个一次性邀请链接同时生成一个短时有效的邀请码。把这两个信息通过飞书或企业微信发给对方对方不依赖邮件也能完成注册。流程上我分了三个阶段避免一步到位给权限创建邀请管理员填写新成员姓名和邮箱选择初始角色先选销售或只读后续可调整。成员激活被邀请人通过链接或邀请码打开激活页面设置自己的登录密码。权限生效激活后账号立即获得对应角色权限管理员可以在成员列表里实时调整。考虑到实际使用中可能会出现邀请链接过期的情况我设置了48小时的有效期过期后管理员可以一键重新生成。另外所有邀请记录都有审计日志什么时候、由谁、邀请了谁后台一查就能查到。4.3 邀请环节的几个坑邮件进垃圾箱、链接失效、角色选错邀请流程上线后我踩过几个具体的坑这里分享出来帮你避雷。第一个坑是邮件送达率。自建服务器的IP信誉度通常不高发给QQ邮箱或163邮箱的邀请邮件很容易被判定为垃圾邮件。解决思路有两个一是配置SPF、DKIM和DMARC三种邮件验证记录把邮件发送域的认证信息写到DNS里二是干脆放弃邮件作为主要通知渠道改用团队内部的企业微信或飞书机器人推送邀请链接。实测下来企业微信机器人的触达效率比邮件高得多几乎不会丢失。第二个坑是邀请链接的幂等性。最初我设计的邀请链接被点击多次后仍然有效导致同一个员工可以反复激活重置密码。后来改成链接一旦被使用立即标记为失效再次请求时返回“链接已失效请联系管理员重新发送”。第三个坑是角色选错导致的数据可见性问题。有一次我邀请一个新同事时顺手选了销售经理角色结果他进系统后能看到整个团队的客户还好发现及时。后来我强制邀请页面的角色选择框默认选中“销售人员”并且加了一个二次确认弹窗——“确认分配该角色吗”这才避免了误操作造成的权限泄露。5. 踩坑实录DeskcommCRM上线后的实际问题5.1 多人同时修改客户资料数据被互相覆盖这是上线后遇到的最严重的问题。两个销售同时打开同一个客户页面A修改了联系方式并保存B修改了跟进状态并保存因为B的页面数据是打开时加载的旧数据B保存后A的修改就被悄悄覆盖了没有任何提示。排查思路是典型的并发控制问题。我采用的解决方案是乐观锁客户表增加一个version字段每次更新时SQL语句带上版本条件——UPDATE customer SET ..., version version 1 WHERE id ? AND version ?。如果更新影响的行数为0说明数据已经被别人改过后端返回“数据已变更请刷新后重试”的提示前端弹窗通知用户重新加载。这个改动只涉及后端十几个接口和前端几个表单提交函数但彻底解决了数据互相覆盖的问题。自建系统的优势这时候体现出来了如果是SaaS CRM这种并发问题你只能提交工单等官方修复而在自己的系统里自己动手半小时就能搞定。5.2 数据库时间少了8小时时区配置的连锁反应上线第二周有销售反馈跟进记录的时间不对明明下午3点写的记录系统里显示的是早上7点。第一反应以为是数据库出问题排查后发现是时区配置的锅。DeskcommCRM的后端容器时区默认是UTC而业务上需要东八区时间。我做了三层修正首先在docker-compose.yml里给所有容器设置TZ: Asia/Shanghai环境变量其次PostgreSQL的时区变量也改为东八区最后前端在展示时间时统一使用UTC时间戳转换为本地时区显示。经过这一轮修正后所有时间记录都准确了。这里想提醒自建系统的朋友们但凡涉及服务器、数据库、容器、前端四层架构时间字段一定要从一开始就约定存储格式。我的经验是数据库统一存UTC时间戳展示层再按用户时区转换这样以后就算有海外同事加入时间也不会乱。5.3 服务莫名重启内存不足导致的OOM跑了一个月后系统突然出现几次偶尔白屏的情况查看Docker日志才发现是backend容器被OOM Killer干掉了。2G内存的服务器跑着PostgreSQL、Node后端、Nginx和前端容器内存已经非常紧张高峰期数据库查询再占多一点内存进程就直接被杀。这个问题的排查比较隐蔽因为服务杀完会自动重启页面刷新后看起来又是正常的根本不会注意到中间断了几分钟。直到有一次并发比较高用户反复反馈打不开页面我才去查容器的退出状态和系统日志。解决方案分两步首先是数据库调优PostgreSQL的shared_buffers默认值对2G内存的机器偏高我把它改成了512M同时把effective_cache_size调低其次是给容器加上内存限制通过docker-compose里的mem_limit参数防止某一个容器把整台机器的内存耗尽。经过这两项调整系统之后再也没有因为内存问题重启过。5.4 备份文件只有几十KB一个差点酿成大祸的定时任务这个坑是让我最后背发凉的。部署后我把备份脚本设成了每天凌晨3点自动执行前两周也没检查过备份文件。结果第三周想看看数据备份情况发现备份的SQL压缩包只有几十KB而数据库本身应该有几百MB。一查原因问题出在cron执行Docker命令的环境上。crontab运行时的PATH环境变量跟手动执行时不一样docker命令的路径没有正确加载导致脚本里docker exec deskcomm-db pg_dump实际执行失败stderr被丢弃了依然生成一个空文件。修复方法是脚本里显式指定Docker的绝对路径并且在脚本末尾加上失败检测逻辑如果生成的备份文件小于1MB就当作失败处理并发一条告警消息到通知群里。经历过这次之后我的教训很明确备份脚本写完不是终点必须验证备份文件真的可用才算是完成了备份。5.5 邀请邮件总是石沉大海SPF和DKIM的完整配置前面提到邀请邮件容易被判垃圾邮件这个问题我是在同事反复确认“真的没收到邮件”之后才认真解决的。排查邮件问题的通用思路是先确认邮件有没有被服务器成功发送再确认接收方有没有在垃圾箱里找到最后检查域名的DNS验证记录是否完整。SPF的作用是声明“哪些服务器可以代表你的域名发邮件”DKIM则是用签名验证邮件在传输过程中没有被篡改。我在域名DNS管理后台加了三条记录SPF记录vspf1 include:your_mail_provider ~allDKIM记录在邮件服务商提供的公钥值基础上加入krsa; pyour_public_keyDMARC记录vDMARC1; pquarantine; ruamailto:your_emailexample.com配置完成之后再发一封测试邮件去mail-tester.com检查得分从原来的2分直接跳到10分满分。从这以后邀请邮件再也没有出现在垃圾箱里。如果你自建系统需要发邮件这个检查流程强烈建议走一遍。写在最后这套DeskcommCRM从最初的一个想法到现在稳定运行前后大概花了两周时间集中开发和部署。回过头看最值钱的不是代码本身而是过程中建立起来的一套认知数据是自己的、备份是可恢复的、权限是可控的这种感觉用任何SaaS产品都换不来。最后再分享一个小技巧。每次部署完一套CRM系统后我都会特意用一台干净的机器做一次完整的恢复演练——从零开始拉取备份、重建容器、恢复数据库直到所有页面正常打开。这个流程跑通一次你对这套系统的信心会完全不一样。平时多花几十分钟去验证备份远好过出事之后对着空目录发呆。如果你的业务也对数据自主性有要求不妨从一套轻量自托管CRM开始试起。
企业数字化 ERP 产品动态
相关推荐
ESP32小智源码换板适配指南:板级抽象层原理与实战 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 5:59:57
Windows CMD目录跳转完全指南:从cd命令到批处理实战 先说我自己的感受。用命令行跳转目录这件事,看起来是Windows用户最基础的操作,但我在带新人的时候发现,很多人连cd用起来都磕磕绊绊。要么是切到别的盘符直接报错,要么是路径太深一层一层cd到怀疑人生。更别提那些藏在细节里的坑&… · 2026/9/25 5:59:57
Agentic Runtime 设计实战:从状态机到Kubernetes调度 1. 从“ax”这个标题说起:一个被低估的运行时抽象层第一次看到“ax”这个标题,很多人会一头雾水。它不像“Kubernetes 入门”那样直白,也不像“agentic rag”那样自带热度。但把热搜词摊开来看,ax、agentic、orchestration、runti… · 2026/9/25 6:22:28
Keil工程打不开?常见原因与完整排查解决指南 先说句实在话,“KEIL工程打不开”这个报错,遇上过一次就够让人头疼的。明明昨天还好好的工程,今天双击.uvprojx文件,界面闪一下或者干脆弹个红叉,瞬间心态就炸了。尤其是项目做到一半、急着改代码交差的时候࿰… · 2026/9/25 6:22:22
展讯平台刷机深度解析:Bootloader解锁与fastboot适配指南 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 6:22:22
RVM相关向量机分类与预测实战:小样本稀疏贝叶斯Matlab实现 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 6:22:22
数字图像处理与机器视觉:九次实验从像素操作到分类器落地 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 6:22:09
ROS 2 RViz2 完全指南:从安装配置到TF调试与URDF显示 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 6:22:03
创维E900V22D刷机全攻略:S905L3SB芯片兼容性解析与救砖实战 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:31
MQTT协议原理与Broker服务器搭建实战:从Mosquitto到EMQX /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:37