9.9 KiB
9.9 KiB
名片云(card addon)API 对接文档
读者:UniApp 前端开发人员(微信小程序 / H5 / 鸿蒙元服务三端)。 事实来源:
backend/src/addon/card/api/controller/(Card.php / Contact.php / Lead.php / Recognize.php / BaseCardApi.php)。 文档与源码如有出入,以源码为准。最后更新:2026-10-13。
1. 总览
| 模块 | URL 前缀 | 用途 |
|---|---|---|
| 名片夹 | /card/api/card/* |
我的名片(列表 / 详情 / 编辑 / 认领 / 识别建卡) |
| 人脉库 | /card/api/contact/* |
我的人脉(增删改查 / 转线索) |
| 潜在客户 | /card/api/lead/* |
名片收到的留资线索(列表 / 跟进状态) |
| 识别(旧) | /card/api/recognize/execute |
旧版识别入口,新代码请用 /card/api/card/recognize |
前端收口要求:所有 URL 必须集中在 API 层统一管理(项目内已有页面直连这些地址,路径一个字符都不能变,只做收口不做改名)。
2. 通用约定
2.1 URL 规则
addon 标准路由:/{addon}/api/{controller}/{action},例如:
POST https://<域名>/card/api/card/lists
2.2 鉴权(全部接口强制)
- 所有接口都要求 member token(后端
BaseCardApi::requireAuth()强制,匿名一律code < 0拒绝)。 - 走项目现有请求工具(自动携带
token与uniacid参数/头),不要额外传site_id——后端 site_id 只认 token 绑定值,入参传了也会被忽略。
2.3 返回信封
统一 JSON:
{ "code": 0, "message": "success", "data": { } }
code === 0:成功,业务数据在data。code !== 0:失败,message可直接 toast(用户可读文案)。
2.4 行级权限语义(重要,影响 UI)
- 所有数据按
owner_id = token 会员行级隔离:列表只返回自己的卡/人脉/线索。 - 访问不存在或不属于自己的资源,后端统一报「不存在」(如「卡片不存在」「人脉不存在」「线索不存在」),不区分两种情况(防探测)。前端提示文案按"内容不存在或已删除"处理,不要提示"无权限"。
owner_id、source_type等系统字段不可通过入参修改(后端显式收口)。
3. 名片夹 /card/api/card/*
3.1 我的名片列表 card/lists
- 入参:
page(默认 1)、page_size(默认 20,上限 100)、keyword(姓名/手机/公司模糊,选填) - 返回
data:
{ "list": [ /* relation 行,见 3.2 字段说明;不含 access_password */ ],
"count": 0, "page_count": 0 }
3.2 卡片详情 card/detail
- 入参:
card_id(必填,字符串,形如c_1_shop_20261013...) - 返回
data:
{
"relation": { /* 卡片主行,字段见下方"卡片字段表" */ },
"source": { /* 识别来源行,可为 null */ },
"share_list": [ /* 关联分享配置 */ ]
}
卡片字段表(relation,渲染用带 _list 后缀的键):
| 键 | 说明 |
|---|---|
card_id |
卡片唯一标识(页面路由参数用它,不用自增 id) |
name / company / job_title / mobile / phone / email / website / address / postal_code / country / city / province / wechat / telegram / messenger / avatar / bio |
标量字段 |
mobiles_list |
[{value}] 多手机号(解码后) |
socials_list |
[{type, label, value}] 社交账号(label 是后端翻译好的中文名,直接展示)。Telegram/Messenger 已并入此处(旧独立字段软下线,后端读取时自动合并旧列值) |
custom_list |
[{label, value}] 自定义字段 |
locked_fields |
[{key}] 站点锁定字段清单,编辑页据此渲染只读,提交时后端也会剥离(静默丢弃,不报错) |
source_type |
来源:manual / manual_batch / scan / import_csv / import_xlsx / clone / api |
owner_id |
归属会员 id(只读) |
- 原始 JSON 串
mobiles / socials / custom_fields仍在返回中(兼容保留),新代码一律消费*_list。
3.3 更新卡片 card/update
- 入参:
card_id(必填)+fields(嵌套对象;后端按fields/a收) - ⚠️ normalize 语义(历史事故定稿,必须遵守):
- 键存在才写:
fields里带了哪个键就更新哪个键; - 空字符串
""= 显式清空该字段; - 键缺席 = 不擦除(保持原值);
- 因此局部更新时只传用户实际编辑过的键,不要把整包表单无脑回传。
- 键存在才写:
- 富化字段入参 wire format(放在
fields内):
{
"mobiles": ["13800000000", { "value": "13911112222" }],
"socials": [ { "type": "douyin", "value": "xxx" } ],
"custom_fields": [ { "label": "展厅号", "value": "E3-108" } ]
}
socials.type白名单:alipay / douyin / wxvideo / xiaohongshu / weibo / kuaishou / bilibili / qq / linkedin / facebook / instagram / x / telegram / messenger / other(type 非法或 value 空的条目被后端静默丢弃);- ⚠️
telegram / messenger已不再是独立标量字段(2026-10-13 软下线):fields.telegram/fields.messenger传了也会被忽略,统一走socials数组按类型添加;旧数据由后端在socials_list中自动合并返回; custom_fields:label 与 value 必须同时非空,否则该条被丢弃;label 截断 20 字,value 截断 255 字。- 返回
data:更新后的 relation 行。 - 嵌套对象跨端序列化:请用 JSON body(或项目
sendJson()通道);后端收fields为对象/数组。
3.4 认领名片 card/claim
- 入参:
card_id(必填) - 场景:商家后台建的卡未归属(owner_id=0),员工把它认领到自己名下。
- 返回
data:认领结果(失败时message可直接展示)。
3.5 识别建卡 card/recognize
- 入参:
media_path(必填,图片/媒体地址)、media_type(默认image)、source_type(默认scan) - 返回
data:
{ "source_id": 1, "relation_id": 2, "card_id": "c_1_shop_...",
"deduped": false, "fields": { /* 归一化后的识别字段 */ } }
- ⚠️
deduped === true表示站点内已有同手机号名片,未新建、绑到了既有卡上——前端应提示用户"已存在同名片"。 - 注意:当前后端识别服务为桩实现(
识别服务未注册会作为错误返回),对接时请按失败分支兜底 UI。
3.6 识别失败重试 card/retry
- 入参:
source_id(必填) - 约束:仅本站 + status=failed 的来源可重试,有次数上限(超限报错,message 可直接展示)。
- 返回
data:{ source_id, relation_id, card_id, retry_count, deduped, message }。
3.7 批量识别 card/recognizeBatch
- 入参:
items:非空数组,1~10 条,每项{ source_type?, media_type?, media_path, media_key? }。 - 返回
data:{ items: [ { ok: bool, message, data } ], ok: 成功数, failed: 失败数 }——逐项独立成败,单条失败不影响其它。
3.8 旧入口 recognize/execute
- 入参与
card/recognize相同。已上线页面可能仍在用,新代码一律用card/recognize。
4. 人脉库 /card/api/contact/*
4.1 人脉列表 contact/lists
- 入参:
page、page_size(≤100)、keyword(姓名/手机/公司模糊)、source(manual/scan/exchange/lead_in,选填)、status(0/1,选填) - 返回
data:{ list, count, page_count }
4.2 新增人脉 contact/add
- 入参:
name(必填);选填:company / job_title / mobile / email / wechat / website / address / remark - 返回
data:新增行。
4.3 人脉详情 contact/info
- 入参:
id(数字自增主键,注意与名片的card_id字符串不同) - 返回
data:人脉行(编辑页回填用)。
4.4 更新人脉 contact/update
- 入参:
id+ 字段。兼容两种传参:fields对象,或顶层平铺字段(顶层会剔除id/token/uniacid/fields)。 - 可更新白名单:
name / company / job_title / mobile / email / wechat / website / address / remark / status - 返回
data:更新后行。
4.5 删除人脉 contact/delete
- 入参:
id。真删(不可恢复),前端建议二次确认弹窗。
4.6 人脉 → 潜在客户 contact/toLead
- 入参:
id(人脉 id) - 行为:写一条潜在客户线索(归属当前员工),不删人脉行;同员工同手机号已转过则报错(手机号为空时直接插入)。
- 返回
data:新线索信息。
5. 潜在客户 /card/api/lead/*
5.1 线索列表 lead/lists
- 入参:
page、page_size(≤100)、status(0-3,选填)、keyword(姓名/手机模糊) - 可见范围:自己名下名片收到的线索(按名片归属过滤)+ 自己从人脉转入的线索。没有名片时列表为空属正常现象。
- 返回
data:{ list, count, page_count }
5.2 更新跟进状态 lead/setStatus
- 入参:
id(线索 id)、status(只能是 0/1/2/3,其它值报「参数不合法」) - 返回
data:{ id, status }
6. 对接 checklist(前端收口时逐条核对)
- 所有
/card/api/*URL 收口到 API 层,与本文档路径逐一比对(现有 7 个页面 12 处直连,路径不可变)。 - 统一走项目请求工具(自动带 token / uniacid),任何接口不传
site_id。 - 失败分支统一
toast(message);「不存在」类错误按"内容不存在或已删除"提示。 card/update只传编辑过的键(键存在才写语义)。- 详情/列表渲染富化字段用
*_list解码键,不解析原始 JSON 串。 - 编辑页对
locked_fields命中的字段渲染只读。 recognize成功后检查deduped,为 true 时提示"已存在同手机号名片"。- 分页参数
page_size不超过 100。 - 名片路由参数用
card_id(字符串),人脉/线索用id(数字),不要混用。