☰
AI名片小程序开发实战:Spring Boot后端与小程序实现原理
2026/10/15 4:54:19 网站建设 项目流程

直接说结论:AI名片小程序不是什么玄学,本质上就是一个“电子名片 + AI内容生成 + 扫码递名片”的组合体。后端用Java(Spring Boot)做服务端,小程序端承载交互,再对接一个大模型接口用来生成名片文案、销售话术、客户摘要这些内容。我在实际项目中完整走了一遍从零到上线的流程,这篇就把核心实现原理和源码层面的关键设计拆开讲清楚。

你可能已经看过不少所谓“AI名片”的演示视频,扫码、递名片、AI生成一段个人简介,感觉很酷。但真到要复现的时候,问题会陆续冒出来:名片数据结构怎么设计才能被AI理解?AI生成的文案怎么保证是结构化JSON而不是乱七八糟的散文?扫码之后怎么精准定位到某一张名片而不是整个公司?客户递了名片之后怎么跟进?这些问题不解决,做出来的东西就是个玩具,没法真正投入业务用。

这篇文章适合谁看:公司准备做智能销售工具、想给SaaS产品增加名片模块的开发者,或者纯粹想学习Java后端怎么写AI类接口的同学。不需要你已经很懂大模型,但要有一定的Spring Boot基础。

1. 项目整体设计与技术选型

1.1 AI名片的核心功能边界

先想明白AI名片到底承担什么角色。真实业务场景中,名片只是销售转化的起点,所以这张电子名片不能只是一张静态图片。我做的这套系统核心功能有五个:

  • 名片管理:创建、编辑、展示属于个人的结构化名片,包括姓名、职位、公司、联系方式、个人介绍、擅长领域、成功案例这些字段。
  • AI内容生成:根据用户的原始输入(可能是几句话,也可能是一段很散的文字),自动扩写并结构化为得体的名片文案,包括个人简介、服务亮点、合作话术、客户跟进首语。
  • 扫码递名片:客户扫名片上的二维码,直接进入小程序的H5名片详情页,不需要安装额外App,也不需要注册。
  • 表单留资:访客可以在名片页上留言、预约沟通、填写合作意向,后端记录进线索池。
  • 销售辅助:AI根据名片主的业务标签生成针对特定客户的打招呼话术或跟进建议。

这些功能决定了后端的技术复杂度。不要一上来就画很大的架构图,建议先按最小可用闭环来做:名片CRUD + AI生成 + 扫码落地页 + 留资记录。

1.2 技术栈选型与实际理由

后端我用了Spring Boot 2.7.x + MyBatis-Plus + MySQL + Redis,这个组合在Java生态里属于“稳妥到无聊”但可靠的选择。Redis 在这里不只是缓存,还承担了扫码递名片时token的临时存储和过期控制。

小程序端用的是微信原生框架,没有引入uni-app。原因是这个项目逻辑不复杂,微信原生语法已经够用,少一层框架少一层坑,特别是不用担心小程序基础库版本兼容问题。

AI服务这块,我选择通过HTTP调用大模型API,而不是直接把任何SDK打进业务代码。好处是模型迭代不影响业务代码,换个Base URL和API Key就能切换服务商。这里必须强调一个合规前提:调用AI能力必须使用正规服务商提供的公开合规接口,接入前仔细阅读服务协议和内容合规要求,业务数据在传输和存储时必须走加密通道。

数据库就一张主表加几张关联表,核心表结构下面会讲到。

1.3 目录结构与源码组织

源码组织直接影响后续维护效率。后端我采用的是经典的分层结构,但做了一点调整,把AI相关的调用独立成一个模块:

src/main/java/com/example/ainamecard ├── common // 通用工具、统一返回体、异常处理 ├── config // 拦截器、Redis配置、HTTP客户端配置 ├── controller // 暴露给小程序端的REST接口 ├── service // 业务逻辑 │ ├── card // 名片业务 │ ├── ai // AI调用、提示词管理、响应解析 │ └── visit // 扫码递名片与线索沉淀 ├── mapper // MyBatis-Plus数据访问层 ├── entity // 数据库实体 └── dto // 入参出参对象

controller 层尽量薄,业务判断往下沉。AI代理层单独抽出来是因为这个模块替换频率最高,而且每一个调用都要做超时、重试、限流的控制。

小程序端的页面组织:

pages/ ├── index/ // 首页:名片列表 ├── cardEdit/ // 名片编辑与AI生成入口 ├── cardDetail/ // H5名片展示页(也用于访客扫码落地) ├── profile/ // 我的:数据统计、线索列表 └── log/ // 递名片记录

2. 核心功能实现原理与数据库设计

2.1 名片数据模型是整张网的关键

名片数据不能只存一张图。AI名片的核心资产是“结构化文本”,只有字段拆得清,才能喂给大模型做二次加工,也才能支撑后续的检索与分类。

核心表设计如下:

CREATE TABLE `t_business_card` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `user_id` bigint(20) NOT NULL COMMENT '归属用户ID', `name` varchar(64) NOT NULL COMMENT '姓名', `title` varchar(64) DEFAULT NULL COMMENT '职位', `company` varchar(128) DEFAULT NULL COMMENT '公司', `phone` varchar(32) DEFAULT NULL COMMENT '电话', `email` varchar(128) DEFAULT NULL COMMENT '邮箱', `wechat` varchar(64) DEFAULT NULL COMMENT '微信号', `address` varchar(255) DEFAULT NULL COMMENT '地址', `profile` text COMMENT '个人简介(AI生成后存储)', `tags` varchar(255) DEFAULT NULL COMMENT '业务标签,逗号分隔', `card_style` varchar(32) DEFAULT 'default' COMMENT '名片模板风格', `share_token` varchar(64) NOT NULL COMMENT '分享唯一标识', `visit_count` int(11) DEFAULT 0 COMMENT '被访问次数', `status` tinyint(4) DEFAULT 1, `create_time` datetime DEFAULT NULL, `update_time` datetime DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `uk_share_token` (`share_token`), KEY `idx_user_id` (`user_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='AI名片主表';

关键在于share_token这个字段。每一次名片创建或重新保存,都会用UUID生成新的分享token,二维码和分享链接里带的就是这个token。扫二维码进来,小程序拿到token,后端凭token查名片,不用暴露数据库自增ID,避免被人遍历抓取所有名片。UUID生成的token是一长串随机字符,猜测成本高,配合有效期控制,整体安全性可接受。

访客留资表:

CREATE TABLE `t_card_lead` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `card_id` bigint(20) NOT NULL COMMENT '关联名片ID', `visitor_name` varchar(64) DEFAULT NULL, `visitor_phone` varchar(32) DEFAULT NULL, `visitor_company` varchar(128) DEFAULT NULL, `message` text COMMENT '访客留言', `intention` varchar(255) DEFAULT NULL COMMENT '合作意向标签', `create_time` datetime DEFAULT NULL, PRIMARY KEY (`id`), KEY `idx_card_id` (`card_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='访客留资表';

访问日志表用来记录谁在什么时间看了名片,甚至可以记录访问来源(扫了什么渠道的码)。这个数据对名片主做销售跟进很有指导意义。

2.2 AI生成内容的实现原理

AI在这套系统里承担的核心任务是“把用户零散输入整理成结构化的、得体的名片文案”。实现上分三步。

第一步是提示词设计。不要以为调用大模型就是“帮我写个介绍”,必须给模型明确的输出格式约束。我实践下来的提示词框架长这样:

你是资深商务文案专家。请根据用户提供的原始信息,生成以下三段内容: 1. profile:个人简介,150字以内,突出专业能力和可信度; 2. greetings:首次给客户发微信的打招呼语,不超过50字; 3. highlights:三个服务亮点,每条不超过20字。 严格输出JSON格式,不要包含JSON以外的任何内容: {"profile":"","greetings":"","highlights":["","",""]}

这个设计里有两个实际验证过的关键点。

  • 明确字数上限。名片空间有限,不能让模型自由发挥写成作文。
  • 要求“严格输出JSON”。但现实是大模型偶尔会在JSON外面包一层markdown代码块标记,或者加一句“好的,这是您需要的...”之类的废话。所以解析不能只做一次JSON.parse,要写一个容错解析器。

容错解析思路:先尝试直接JSON.parse,失败后用正则提取第一个{到最后一个}之间的内容再解析,再不行就丢弃本轮结果,让用户点击“重新生成”。我个人建议不要过度尝试AI修复,成本高且不稳定,失败就让用户重试是更可控的方案。

第二步是请求与响应处理。HTTP调用大模型接口的封装要注意三个参数:temperature控制在0.7左右,太高文案发飘,太低千篇一律;max_tokens控制在800左右,名片文案不是长文,给太多额度反而容易让模型把JSON截断;超时时间要给够,设置10秒。我遇到过一个实际问题:默认HTTP客户端超时设置5秒,大模型响应稍微慢一点就超时了,然后用户反复点击,既浪费额度又造成重复生成。

第三步是生成后的字段映射。模型返回的JSON解析成DTO后,不能直接覆盖数据库里的字段。要等用户确认“应用这份AI内容”之后才写入,给用户保留反悔余地。我把AI生成结果放在一个内存DTO里,前台预览,确认后调一次更新接口落库。

2.3 扫码递名片的完整链路

这是整个系统最强调体验的部分,技术实现其实不复杂。流程如下:

  1. 用户在名片详情页点击“分享名片”,后端生成带share_token的二维码图片。
  2. 微信扫码后,小程序通过onLoad的options.scene参数拿到二维码里的场景值。
  3. 场景值通常是经过URL编码的share_token,解码后调用后端接口GET /api/card/shared/info?token=xxx。
  4. 后端先查Redis里有没有该token的缓存,有就直接返回;没有则查数据库,写入Redis并设置过期时间。
  5. 小程序展示名片详情页。

这里有一个容易被忽略的细节:微信小程序的scene参数有长度限制,通过encodeURIComponent编码后的token不能太长,否则会被截断。我的解决方法是token取UUID去掉横线的前16位,再加2位随机字符凑成18位固定长度。实测下来,这个长度在微信系统里很安稳。

Redis缓存的键设计:

card:share:{share_token} -> 名片JSON大对象

有效期设置为24小时。名片内容更新时,要主动删除对应的缓存键,不然访客看到的会是旧数据。这个联动逻辑容易漏,我在项目初期就踩过坑,名片改了头像,扫码出去还是老样子,排查半天才意识到是缓存没清。

3. 后端关键源码实现

3.1 统一返回体与异常处理

所有接口返回统一结构,前端解析起来心智负担小。我的返回体就三个字段:

@Data public class Result<T> { private int code; // 0成功,非0失败 private String msg; private T data; }

异常处理用@RestControllerAdvice统一拦截,业务异常直接抛自定义BizException,避免每个controller里写try-catch。实际开发中这个设计可以省掉至少30%的冗余代码。

3.2 AI调用层的实现

AI调用核心代码可以拆成三段:构建请求、发送请求、解析响应。

@Service public class AiGenerateService { private static final String MODEL_NAME = "qwen-plus"; // 按实际服务商配置,此处示例 private final RestTemplate restTemplate; public AiGenerateService(RestTemplate restTemplate) { this.restTemplate = restTemplate; } public AiCardContent generateCardContent(String rawInput) { // 1. 构建提示词 String prompt = PromptTemplate.buildCardPrompt(rawInput); // 2. 构造请求体 JSONObject requestBody = new JSONObject(); requestBody.put("model", MODEL_NAME); requestBody.put("temperature", 0.7); requestBody.put("max_tokens", 800); // 实际项目需要按要求组装消息结构 requestBody.put("messages", new JSONArray() .put(new JSONObject() .put("role", "system") .put("content", "你是资深商务文案专家...") ) .put(new JSONObject() .put("role", "user") .put("content", prompt) ) ); // 3. 发送请求,设置超时 String url = "https://api.example.com/v1/chat/completions"; // 此处为占位示例 HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); // 鉴权头按实际服务商要求配置 headers.set("Authorization", "Bearer " + apiKey); HttpEntity<String> entity = new HttpEntity<>(requestBody.toJSONString(), headers); // 4. 解析响应与容错处理 String responseBody = restTemplate.postForObject(url, entity, String.class); String content = parseContentFromResponse(responseBody); return parseJsonContent(content); } }

响应解析有两个层次的容错。第一层是从大模型的HTTP响应体里提取出choices[0].message.content字段,这里要注意不同服务商的响应结构略有差异,字段名可能不同。第二层是对content里的JSON再做容错清理。

private AiCardContent parseJsonContent(String content) { // 清理内容,去掉可能的markdown标记 String cleaned = content.trim(); if (cleaned.startsWith("```")) { cleaned = cleaned.replaceAll("^```[a-zA-Z]*", "").replaceAll("```$", "").trim(); } // 提取第一个{到最后一个}之间的内容 int first = cleaned.indexOf("{"); int last = cleaned.lastIndexOf("}"); if (first >= 0 && last > first) { cleaned = cleaned.substring(first, last + 1); } return JSON.parseObject(cleaned, AiCardContent.class); }

这段代码看起来不复杂,但每一项都是在线上问题里摸出来的。最初版本只做了JSON.parseObject,用户反馈 “AI生成偶尔失败”,排查日志发现模型确实返回了内容,只是外面包了一层````json`标记。从那以后我才加上了清理逻辑。

3.3 扫码递名片的Controller实现

@RestController @RequestMapping("/api/card") public class SharedCardController { @Autowired private StringRedisTemplate stringRedisTemplate; @Autowired private BusinessCardService cardService; @GetMapping("/shared/info") public Result<SharedCardVO> getSharedCard(@RequestParam("token") String token) { // 1. 查缓存 String cacheKey = "card:share:" + token; String cached = stringRedisTemplate.opsForValue().get(cacheKey); if (cached != null) { return Result.ok(JSON.parseObject(cached, SharedCardVO.class)); } // 2. 查数据库 BusinessCard card = cardService.getByShareToken(token); if (card == null) { throw new BizException("名片不存在或已失效"); } // 3. 叠加访问计数,异步处理,避免阻塞主流程 cardService.incrementVisitCount(card.getId()); // 4. 组装VO并写缓存 SharedCardVO vo = convertToVO(card); stringRedisTemplate.opsForValue().set(cacheKey, JSON.toJSONString(vo), 24, TimeUnit.HOURS); return Result.ok(vo); } }

访问计数用异步方式处理,不要同步等待数据库更新,否则高并发扫码时接口会变慢。异步可以用@Async注解或者扔到线程池,我用的是@Async配合自定义线程池配置。

另一个注意点是SharedCardVO里不直接返回数据库实体,而是要裁剪字段。手机号、微信号这些字段要不要完整展示,取决于名片主的设置。如果名片主开启了“仅展示脱敏信息”,后端要在这里做判断。这个权限点在数据库实体直接返给前端的时候最容易漏。

3.4 小程序端的配对逻辑

小程序端扫码进入时,核心代码在onLoad里:

onLoad(options) { // 从扫码场景值解析token const scene = decodeURIComponent(options.scene || ''); // 二维码生成时格式为 "token=xxxxxx" const token = getQueryParam(scene, 'token'); if (token) { this.fetchSharedCard(token); } }

fetchSharedCard请求后端接口拿到名片数据后,渲染到页面上。有一点要提醒:如果用户是从公众号菜单点进来的scene参数和扫码的scene参数形式可能不同,要做好兼容,不能只认一种格式。

名片页渲染时,用rich-text组件还是自定义模板?我选了自定义模板,因为名片要展示的字段样式太个性化,rich-text不容易控制间距和强调效果。

4. 实操中的几个关键难点与排查记录

4.1 JSON格式化输出失败的处理

AI输出不稳定是必然的,不要追求100%成功率。我统计过线上数据,按上述提示词设计,成功率在92%左右。剩余8%的失败,给用户一个“重新生成”按钮就完事了。千万不要在这里设计复杂的重试逻辑,大模型接口的调用是有成本的,无脑重试只会让账单变得难看。

但有一个优化值得做:在请求参数里带上“已生成的参考示例”。具体做法是在提示词里加一段示例:

参考示例: {"profile":"十年ToB销售经验,专注制造业数字化转型,累计服务客户超200家...","greetings":"张总您好,我是XX科技的陈明,看了贵公司官网的产品线,觉得我们在供应链数字化方面有合作空间,方便简单聊5分钟吗?","highlights":["制造业数字化顾问","200+客户落地经验","全流程陪跑实施"]}

模型模仿示例的能力很强,加上这段参考示例后,成功率提升到97%左右,而且输出格式更稳定。这是我自己实验得出的数据,你实际项目可能不完全一致,但这个优化思路是通用的。

4.2 名片二维码生成的最佳实践

生成二维码常规做法是后端调用一个二维码库直接输出图片,但我试过之后不推荐。原因有两个:一是后端二维码工具库的样式定制能力有限,想在码中间塞头像、改配色很费劲;二是增加后端维护成本。

更好的做法是小程序端生成,用wxbarcode这个组件,直接在canvas上画二维码,样式自由度极高。后端只需要返回share_token和名片信息,前端负责画码。

需要提醒的是,在canvas上画二维码时要注意清晰度问题。真机上大量出现二维码模糊、扫不出来。原因是canvas尺寸不够或者图片被拉伸。我的做法是canvas内部画布宽度400px,二维码占中间320px,导出图片时用wx.canvasToTempFilePath的destWidth设为宽度的2倍甚至3倍,亲测扫码率大幅提升。

4.3 内容合规与安全拦截

AI生成的内容必须经过合规校验再展示。两个层面的处理:

  • 请求侧:在提示词里明确要求,禁止输出任何违法违规和违背公序良俗的内容。
  • 响应侧:后端对生成结果做关键词过滤和敏感信息校验,校验不通过直接丢弃本次结果并返回友好提示。

对访客提交的表单内容(留资信息)同样要做过滤,防止有人利用留言功能提交恶意内容。这块用简单的敏感词库加正则就能覆盖大部分情况。签名和加密传输是底线,整个小程序强制HTTPS,这也是微信平台的基础要求。

4.4 数据库字段长度与编码的坑

名片简介用text类型没问题,但tags字段容易被人忽视。业务标签我是用逗号分隔存在varchar(255)里的,刚开始没问题,直到一位用户把他的20个标签全填进去,直接报错。后来我改成text类型,并且写入前检查长度,超长就截断。

另一个坑是utf8mb4编码。如果不小心用了utf8,遇到生僻字或者特殊符号(比如人名里的生僻字)会变成问号。建表统一用utf8mb4并指定排序规则,一劳永逸。

4.5 AI接口调用的限流与降级

多人同时点击AI生成的时候,接口压力会明显上升。我加了简单的单机限流:每个用户每分钟最多调用3次AI生成接口,用Redis自增计数实现。

String key = "ai:limit:" + userId; Long count = stringRedisTemplate.opsForValue().increment(key); if (count != null && count == 1) { stringRedisTemplate.expire(key, 60, TimeUnit.SECONDS); } if (count != null && count > 3) { throw new BizException("操作太频繁,请稍后再试"); }

这个逻辑简单且够用。如果未来用户量大,再把限流升级为令牌桶或漏桶算法,但现阶段没必要过度设计。

AI接口不可用时的降级方案:生成接口超时后,返回提示要求用户稍后再试,同时允许用户手动填写名片文案。不能让AI服务不可用就阻塞核心名片创建流程。手动编辑永远是最兜底的选项。

5. 部署、配置与小程序上线细节

5.1 后端部署的关键配置项

Spring Boot配置文件里要注意几个点:

spring: redis: host: 127.0.0.1 port: 6379 timeout: 3000ms datasource: url: jdbc:mysql://127.0.0.1:3306/ainamecard?useUnicode=true&characterEncoding=utf8mb4&serverTimezone=Asia/Shanghai username: root password: 123456 # AI服务配置 ai: api-key: ${AI_API_KEY} base-url: https://api.example.com/v1 model: qwen-plus max-tokens: 800 temperature: 0.7 timeout-seconds: 10

api-key不要明文写在配置文件里,用环境变量注入,或者放到配置中心。上线前一定要检查有没有把密钥提交到代码仓库,这是新手最容易犯的错误。

数据库连接池用的druid,配置了初始5个连接,最大20个连接。实测单机扛住几百人同时扫码没有问题。如果后面量再大,再加读写分离和横向扩容。

5.2 小程序端配置要点

小程序后台要把request合法域名配置成HTTPS地址。开发调试时可以在开发者工具里勾选“不校验合法域名”,但上线前必须关闭。

订阅消息这块要重点提醒:小程序模板消息已经下线,现在用的是订阅消息机制,而且一次性订阅,用户点击授权一次只能发送一条。所以访客在名片页留资时,如果想给名片主发通知,需要引导用户授权订阅。这里一定不要做诱导式授权,微信审核会卡,而且用户体验也差。我的做法是:留资成功后弹窗说明可以订阅“名片主回复提醒”,把授权作为可选项而不是必选项。

5.3 上线前的自测清单

根据我自己的上线经历,整理一份自测清单供参考:

  • 创建名片 -> AI生成内容 -> 确认保存 -> 全部流程走通
  • 打开分享链接,不登录状态下访客能否看到名片
  • 扫码递名片 -> 后台访问计数是否增加
  • 名片主修改内容 -> 再扫同一个码,是否拿到最新内容(缓存是否清除)
  • 访客留资 -> 名片主是否能收到订阅消息
  • 容错验证:AI接口超时、数据库故障时页面是否给出友好提示
  • 安全自测:直接访问他人分享token是否拿到数据、非法参数是否被拦截
  • 性能粗测:模拟100个并发扫码请求,接口响应时间控制在合理范围内

这些自测项都是我踩过的坑汇集来的,比如缓存不清这个事,如果不主动测,多半会漏。

6. 成本控制与体验优化心得

6.1 AI调用成本估算

AI生成接口不是免费的,用之前要心里有数。以每张名片生成一次为例,输入提示词+参考示例大概消耗几百个token,输出大概300~500个token,单次成本约0.01元左右(不同服务商定价不同,仅作量级参考)。如果每个用户创建名片时生成次数不超过3次(用户可能反复点生成),再叠加销售话术等功能,日活1000用户的用量,每月成本可控在可接受范围内。

省钱技巧有两个:一是提示词里限制max_tokens,不设上限模型可能放飞自我;二是生成结果做缓存,相同输入直接命中之前的结果,不重复调用。

6.2 缓存策略的进一步优化

除了card:share:{token}这个缓存外,AI生成结果也可以做短时缓存。用户反复点击“重新生成”时,如果连续几次传入的原始输入一致,可以在10分钟内直接返回到已有的生成结果,避免无意义消耗。但要注意,这个缓存有必要加验证码或用户维度隔离,防止用户A生成的结果被用户B拿到。

另外,名片列表页也适合做缓存,但不是全局缓存,而是按用户维度,键为card:list:{userId},修改或删除名片时主动失效。

6.3 体验上的几个细节打磨

第一,AI生成过程中按钮要做loading状态,防止用户重复提交。加载文案要明确“AI生成中,约需几秒”,减少用户焦虑。

第二,生成结果预览页要把“不满意可重新生成”的入口放在显眼位置,降低用户的预期,也减少对AI的抱怨。

第三,名片模板可以搞个简单的样式切换,虽然技术上只是切换CSS变量,但用户感知差异很大。预设三套模板,暗色商务、浅色简约、蓝白科技,基本满足大多数场景。

第四,访客留资后,名片主那边最好有短信或者服务通知触达。短信要花钱,服务通知要订阅授权,各有利弊。前期可以只做站内消息 + 名片主打开小程序时红点提醒,成本最低。

7. 避坑指南:我在实际项目中踩过的坑

7.1 微信登录的静默授权问题

小程序冷启动时,直接wx.login拿code换openid没问题,但换取手机号必须用getPhoneNumber按钮组件,不能通过后端接口直接获取。这是微信平台的硬性要求,开发时容易想当然,以为后端传个参数就能拿手机号。

另外,如果业务需要用户绑定手机号才能创建名片,前端要把获取手机号和创建名片的流程打通,避免用户在名片编辑页填了一堆信息,最后卡在手机号授权环节,体验很割裂。

7.2 Redis不可用时的降级

扫码递名片走Redis缓存,但Redis宕机了不能整个接口就挂掉。代码里要做降级处理,Redis查询失败后直接查数据库,数据库有数据就正常返回,只是慢一点。用try-catch包住Redis操作,异常时不影响主流程。

7.3 时间字段的时区问题

数据库datetime字段如果没指定serverTimezone=Asia/Shanghai,在高版本JDBC驱动下可能出现时间差8小时的问题。这个坑就像鞋里进了沙,不致命但无时无刻不在干扰你。页面显示名片创建时间总是差8小时,排查良久才发现是连接串没配置时区。

7.4 长文本参数的传输问题

AI生成的个人简介如果很长(超过某些服务器默认的请求体大小限制),小程序端提交时要确认没有超过Nginx的client_max_body_size限制。我在一次测试中遇到名片简介提交后一直报400错误,排查后发现Nginx默认只允许1MB请求体,而某个用户的简介包含一张base64图片,超过限制。后来把图片改传对象存储,只提交图片URL,问题才解决。

7.5 异步线程池的监控

用了@Async之后,需要注意线程池的监控。线上出现访问计数不更新的情况,原因是线程池满了,异步任务被丢弃。排查后发现是核心线程数配置太小,只有2,而扫码高峰时任务堆积。后来调整为核心线程8、最大线程16、队列容量100,并加了任务拒绝策略的日志记录。

如果你决定用异步,建议把线程池参数做成可配置项,并输出线程池运行指标到日志,方便后续调优。不要图省事直接用默认值,生产环境必踩坑。

8. 从“能跑”到“能用”的进阶方向

8.1 从单一名片到团队名片夹

现在这套系统只有个人名片。往上一层做团队版,就有很多增值点:组织架构树状展示、按部门或业务线分组、团队成员名片互相推荐,甚至团队统一品牌名片模板。后端的变化集中在增加组织和成员关系表,前端则是名片列表支持分组和搜索。

8.2 从固定模板到智能匹配

AI不只生成文案,还可以参与设计层面的决策。比如根据名片主的行业、职位、风格偏好,推荐合适的名片模板。这一段不需要复杂的算法,本质上是一个标签匹配系统,把用户标签与模板标签做多维度匹配即可。

8.3 从被动等待到主动跟进

名片只是数字化获客的第一步,真正提效的是后续的自动跟进。访客扫码递名片后,系统可以定时触发“3小时后发送一条跟进提醒”这类运营动作,再结合AI生成个性化的首访话术。这部分我把定时任务框架用起来,任务表存好待办事件,到点触发消息推送。后续如果数据积累够多,甚至可以总结出哪些行业的名片转化率更高,反向优化AI提示词。

做这个项目最大的体会是:不要把AI当成一个神奇黑盒,放在系统里什么都想交给它。要把AI当作一个需要精准控制输入和输出的服务模块。提示词和输出解析的设计,比调什么模型参数都重要。整个项目里最复杂的不是AI部分,而是业务逻辑的边界划分和数据的一致性,把地基打稳了,上层怎么搭都不慌。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询