Files
lucky_shop/docs/CARD_API_REFERENCE.md

9.9 KiB
Raw Blame History

名片云(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(前端收口时逐条核对)

  1. 所有 /card/api/* URL 收口到 API 层,与本文档路径逐一比对(现有 7 个页面 12 处直连,路径不可变)。
  2. 统一走项目请求工具(自动带 token / uniacid),任何接口不传 site_id。
  3. 失败分支统一 toast(message);「不存在」类错误按"内容不存在或已删除"提示。
  4. card/update 只传编辑过的键(键存在才写语义)。
  5. 详情/列表渲染富化字段用 *_list 解码键,不解析原始 JSON 串。
  6. 编辑页对 locked_fields 命中的字段渲染只读。
  7. recognize 成功后检查 deduped,为 true 时提示"已存在同手机号名片"。
  8. 分页参数 page_size 不超过 100。
  9. 名片路由参数用 card_id(字符串),人脉/线索用 id(数字),不要混用。