/** * 名片云(card addon)API 收口层 * * 单一事实来源:后端《名片云(card addon)API 对接文档》CARD_API_REFERENCE.md(2026-10-13) * 文档与源码如有出入,以源码为准;URL 路径一个字符都不能变,只做收口不做改名。 * * 收口要求(来自后端 checklist): * 1. 所有 /card/api/* URL 必须集中在本层,页面不得再直连字面量; * 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(数字),不要混用。 * * 用法(页面内 this.$cardApi): * this.$cardApi.cardLists({ data: { page: 1 }, success: res => {}, fail: () => {} }) * * 注意:本层只做"URL 收口 + 通道选择",不做业务加工; * 业务字典(状态/来源/字段白名单)随端口导出,供各页面复用。 */ import Http from './http.js'; /** 所有端点路径(与后端文档逐一比对,改动需两边同步) */ export const CARD_API_URL = { // === 名片夹 /card/api/card/* === CARD_LISTS: '/card/api/card/lists', CARD_DETAIL: '/card/api/card/detail', CARD_UPDATE: '/card/api/card/update', CARD_FAVORITE: '/card/api/card/toggleFavorite', // 收藏(双向 toggle, 后端 2.9.12) CARD_CREATE: '/card/api/card/create', // 新建数字名片(后端源码已有, 文档未列; 以源码为准) CARD_CLAIM: '/card/api/card/claim', CARD_RECOGNIZE: '/card/api/card/recognize', CARD_RETRY: '/card/api/card/retry', CARD_RECOGNIZE_BATCH: '/card/api/card/recognizeBatch', CARD_DELETE: '/card/api/card/delete', // 删除自己的名片(软删, 2.11.91) // === 跟进完成态 2.11.3 /card/api/card/* === CARD_FOLLOW_DONE: '/card/api/card/followDone', // === 访客轨迹 2.11.4 /card/api/card/* === CARD_VIEWS: '/card/api/card/views', // === 员工建卡申请 2.11.15 /card/api/apply/* === APPLY_SUBMIT: '/card/api/apply/submit', APPLY_STATUS: '/card/api/apply/status', // === 人脉库 /card/api/contact/* === CONTACT_LISTS: '/card/api/contact/lists', CONTACT_ADD: '/card/api/contact/add', CONTACT_INFO: '/card/api/contact/info', CONTACT_UPDATE: '/card/api/contact/update', CONTACT_DELETE: '/card/api/contact/delete', CONTACT_TO_LEAD: '/card/api/contact/toLead', // === 潜在客户 /card/api/lead/* === LEAD_LISTS: '/card/api/lead/lists', LEAD_SET_STATUS: '/card/api/lead/setStatus', // === 交换名片 /card/api/exchange/* === EXCHANGE_LISTS: '/card/api/exchange/lists', EXCHANGE_AGREE: '/card/api/exchange/agree', EXCHANGE_IGNORE: '/card/api/exchange/ignore', // === 名片设计(员工端可选样式, 后端 v2) /card/api/design/* === // 预设列表必须与商家后台 CardTemplatePresets 同源(避免前端自建漂移) // ⚠ v2 路径无 /card/ 段: 初版 /card/api/card/design/* 在本框架 action 单段路由下 404 CARD_DESIGN_PRESETS: '/card/api/design/presets', // 预设列表(同源后台 CardTemplatePresets) CARD_DESIGN_SAVE: '/card/api/design/save', // 应用预设/保存本卡样式 // === 企业名片 /card/api/enterprise/* (2.13.6) === // 业务模型: 企业卡片 owner_id=0(店铺级), 同一时刻仅 1 张 is_active=1 生效; // 名片区三模式 header_mode: official(指定/默认官方企业卡) / self(员工自选个人卡) / staff(员工轮播) ENTERPRISE_DETAIL: '/card/api/enterprise/detail', // GET ?card_id= 不传=当前生效卡 ENTERPRISE_SAVE: '/card/api/enterprise/save', // POST {card_id?,fields?,design?,header_mode?,official_card_id?} ENTERPRISE_MINE: '/card/api/enterprise/mine', // GET 自己名下企业卡列表 ENTERPRISE_ACTIVATE: '/card/api/enterprise/activate', // POST {card_id} 切换生效(互斥) ENTERPRISE_CHOOSE_SELF: '/card/api/enterprise/chooseSelf', // POST {card_id} 员工自选展示个人卡 ENTERPRISE_DELETE: '/card/api/enterprise/delete' // POST {card_id} 删候选卡(生效卡禁删) }; /** * 社交媒体类型白名单:必须与后端 CardRichFields::SOCIAL_TYPES 保持一致(增减需两边同步)。 * type 非法或 value 为空的条目会被后端静默丢弃。 * ⚠️ 2026-10-13:telegram / messenger 由独立标量字段软下线,统一并入本数组; * 旧数据后端读取时自动合并进 socials_list(见 CARD_API_REFERENCE.md 3.3)。 */ export const SOCIAL_TYPES = [ { key: 'alipay', label: '支付宝' }, { key: 'douyin', label: '抖音' }, { key: 'wxvideo', label: '视频号' }, { key: 'xiaohongshu', label: '小红书' }, { key: 'weibo', label: '微博' }, { key: 'kuaishou', label: '快手' }, { key: 'bilibili', label: '哔哩哔哩' }, { key: 'qq', label: 'QQ' }, { key: 'linkedin', label: 'LinkedIn' }, { key: 'facebook', label: 'Facebook' }, { key: 'instagram', label: 'Instagram' }, { key: 'x', label: 'X' }, { key: 'telegram', label: 'Telegram' }, { key: 'messenger', label: 'Messenger' }, { key: 'other', label: '其他' } ]; /** 富化字段上限:与后端 CardRichFields::MAX_* 一致 */ export const RICH_FIELD_LIMITS = { MAX_MOBILES: 5, MAX_SOCIALS: 10, MAX_CUSTOM: 10 }; /** 线索跟进状态:与后端 Lead::STATUSES 一致(0-3,其它值报「参数不合法」) */ export const LEAD_STATUS = [ { value: 0, label: '新客户' }, { value: 1, label: '已联系' }, { value: 2, label: '已成交' }, { value: 3, label: '无效' } ]; /** 人脉来源:与后端 Contact::SOURCES 一致(scan/exchange 暂无产生入口) */ export const CONTACT_SOURCES = [ { value: 'manual', label: '手工录入' }, { value: 'lead_in', label: '潜在客户转入' }, { value: 'scan', label: '扫描' }, { value: 'exchange', label: '交换' } ]; /** 名片来源:与后端 relation.source_type 一致 */ export const CARD_SOURCE_TYPES = [ { value: 'manual', label: '手动创建' }, { value: 'manual_batch', label: '批量制作' }, { value: 'scan', label: '扫描识别' }, { value: 'import_csv', label: 'CSV 导入' }, { value: 'import_xlsx', label: 'Excel 导入' }, { value: 'clone', label: '克隆' }, { value: 'api', label: '接口创建' } ]; /** * 名片编辑标量字段:与后端 BusinessCardFieldNormalizer 输出对齐。 * ⚠️ 2026-10-13:telegram / messenger 已软下线为独立标量(传了也被忽略), * 统一走 fields.socials 数组按类型添加;读取时旧值自动合并进 socials_list。 */ export const CARD_FIELDS = [ 'name', 'company', 'job_title', 'avatar', 'mobile', 'phone', 'email', 'website', 'wechat', 'country', 'province', 'city', 'address', 'postal_code', 'bio' ]; /** 人脉可更新白名单:与后端 Contact::EDITABLE_FIELDS 一致 */ export const CONTACT_FIELDS = [ 'name', 'mobile', 'company', 'job_title', 'wechat', 'email', 'website', 'address', 'remark', 'status' ]; const CardApi = { url: CARD_API_URL, /* ================= 名片夹 ================= */ /** * 我的名片列表 * @param {Object} p { page, page_size(<=100), keyword, success, fail } * 返回 data: { list, count, page_count } */ cardLists(p) { Http.sendRequest(Object.assign({ url: CARD_API_URL.CARD_LISTS }, p || {})); }, /** * 卡片详情 * @param {Object} p { card_id, success, fail } * 返回 data: { relation, source, share_list } */ cardDetail(p) { Http.sendRequest(Object.assign({ url: CARD_API_URL.CARD_DETAIL }, p || {})); }, /** * 更新卡片(normalize 语义:键存在才写;空串=清空;键缺席=不擦除) * 局部更新时只传用户实际编辑过的键。走 JSON body(fields 为嵌套对象)。 * @param {Object} p { card_id, fields, success, fail } */ cardUpdate(p) { Http.sendJson(Object.assign({ url: CARD_API_URL.CARD_UPDATE }, p || {})); }, /** * 新建数字名片(商家端批量制作/单张新建入口) * 入参:`fields`(与 card/update 同结构,`name` 必填)+ 可选 `owner_id`(指定归属员工,0=未归属待认领) * 返回 `data`:`{ card_id, ...relation }`(前端用 data.card_id 跳详情) * ⚠️ 该端点后端源码已实现但旧文档未列出,按「文档与源码出入以源码为准」收口。 */ cardCreate(p) { Http.sendJson(Object.assign({ url: CARD_API_URL.CARD_CREATE }, p || {})); }, /** * 认领名片(商家后台建的卡未归属 owner_id=0,员工认领到自己名下) * 入参(二选一, claim_code 优先): { data: { claim_code } } 或 { data: { card_id } } * 成功 data.claimed: true=新认领, false=早已是自己的(幂等) * 文档: card_claim_api.md(POST /card/api/card/claim,token 自动带) * @param {Object} p { data: { claim_code | card_id }, success, fail } */ cardClaim(p) { Http.sendRequest(Object.assign({ url: CARD_API_URL.CARD_CLAIM }, p || {})); }, /** * 切换收藏(双向 toggle,幂等可逆:未收藏→置1,已收藏→置0) * 直接用返回值 data.is_favorite 回填 UI,前端不自行判断状态。 * @param {Object} p { data: { card_id }, success, fail } * 返回 data: { card_id, is_favorite: 0|1 } * 拒绝(message 直接 toast): 卡不存在 / 非自己名下卡(统一「名片不存在」) / 参数不合法 / 未登录 */ cardToggleFavorite(p) { Http.sendJson(Object.assign({ url: CARD_API_URL.CARD_FAVORITE }, p || {})); }, /** * 删除自己的名片(软删, 2.11.91) * 文档: CARD_DELETE_API.md(POST /card/api/card/delete,token 自动带,不传 site_id) * 通道: 与 cardClaim/cardFollowDone 同款 sendRequest(表单编码);只需 card_id 一个字段 * 交互: 调用前页面必须已做二次确认;成功后 toast「已删除」并刷新列表(接口不再返回该卡) * 口径: 「卡片不存在」是故意模糊(他人/已删/不存在同一文案),前端统一按 message toast,不特殊处理 * @param {Object} p { data: { card_id }, success, fail } */ cardDelete(p) { Http.sendRequest(Object.assign({ url: CARD_API_URL.CARD_DELETE }, p || {})); }, /** * 识别建卡 * @param {Object} p { media_path, media_type?, source_type?, success, fail } * 返回 data: { source_id, relation_id, card_id, deduped, fields } * deduped=true 表示站点内已有同手机号名片,未新建,前端提示"已存在同名片" */ cardRecognize(p) { Http.sendRequest(Object.assign({ url: CARD_API_URL.CARD_RECOGNIZE }, p || {})); }, /** * 识别失败重试(仅本站 + status=failed 的来源可重试,有次数上限) * @param {Object} p { source_id, success, fail } */ cardRetry(p) { Http.sendRequest(Object.assign({ url: CARD_API_URL.CARD_RETRY }, p || {})); }, /** * 批量识别(1~10 条,逐项独立成败) * @param {Object} p { items: [{ source_type?, media_type?, media_path, media_key? }], success, fail } * 返回 data: { items: [{ ok, message, data }], ok, failed } */ cardRecognizeBatch(p) { Http.sendJson(Object.assign({ url: CARD_API_URL.CARD_RECOGNIZE_BATCH }, p || {})); }, /** * 标记跟进完成(2.11.3 跟进闭环) * 行级归属: 只能标记自己名下的名片(与收藏/认领同一套口径) * 成功 data: { card_id, follow_up_done: 1 } * 失败 message 直接 toast: 卡片不存在 / 只能标记自己名下的名片 * @param {Object} p { data: { card_id }, success, fail } */ cardFollowDone(p) { Http.sendRequest(Object.assign({ url: CARD_API_URL.CARD_FOLLOW_DONE }, p || {})); }, /** * 访客轨迹(2.11.4 谁看了我) * 入参(全部可选): { data: { card_id?, page?, page_size?(<=50, 建议20) } } * 不传 card_id = 当前员工名下全部名片; 成功 data: { list, total, page, page_size, * summary: { today_pv, today_uv, total_pv, total_uv } } * @param {Object} p { data: {...}, success, fail } */ cardViews(p) { Http.sendRequest(Object.assign({ url: CARD_API_URL.CARD_VIEWS }, p || {})); }, /* ================= 人脉库 ================= */ /** * 人脉列表 * @param {Object} p { page, page_size(<=100), keyword, source?, status?, success, fail } * 返回 data: { list, count, page_count } */ contactLists(p) { Http.sendRequest(Object.assign({ url: CARD_API_URL.CONTACT_LISTS }, p || {})); }, /** * 新增人脉 * @param {Object} p { fields: { name(必填), company?, ... }, success, fail } */ contactAdd(p) { Http.sendJson(Object.assign({ url: CARD_API_URL.CONTACT_ADD }, p || {})); }, /** * 人脉详情(编辑页回填;id 为数字自增主键,注意与名片 card_id 字符串不同) * @param {Object} p { id, success, fail } */ contactInfo(p) { Http.sendRequest(Object.assign({ url: CARD_API_URL.CONTACT_INFO }, p || {})); }, /** * 更新人脉(兼容 fields 对象或顶层平铺字段) * @param {Object} p { id, fields?, ...平铺字段, success, fail } */ contactUpdate(p) { Http.sendJson(Object.assign({ url: CARD_API_URL.CONTACT_UPDATE }, p || {})); }, /** * 删除人脉(真删不可恢复,前端需二次确认弹窗) * @param {Object} p { id, success, fail } */ contactDelete(p) { Http.sendRequest(Object.assign({ url: CARD_API_URL.CONTACT_DELETE }, p || {})); }, /** * 人脉 → 潜在客户(不删人脉行;同员工同手机号已转过则报错) * @param {Object} p { id, success, fail } */ contactToLead(p) { Http.sendRequest(Object.assign({ url: CARD_API_URL.CONTACT_TO_LEAD }, p || {})); }, /* ================= 潜在客户 ================= */ /** * 线索列表(自己名下名片收到的线索 + 自己从人脉转入的线索) * @param {Object} p { page, page_size(<=100), status?(0-3), keyword, success, fail } * 返回 data: { list, count, page_count } */ leadLists(p) { Http.sendRequest(Object.assign({ url: CARD_API_URL.LEAD_LISTS }, p || {})); }, /** * 更新跟进状态(status 只能是 0/1/2/3) * @param {Object} p { id, status, success, fail } * 返回 data: { id, status } */ leadSetStatus(p) { Http.sendRequest(Object.assign({ url: CARD_API_URL.LEAD_SET_STATUS }, p || {})); }, /* ================= 交换名片 ================= */ /** * 待处理交换请求列表(返回 status=0;已同意/已忽略员工端不可见) * @param {Object} p { page, page_size(<=100), success, fail } * 返回 data: { list:[{ id, from_card_id, name, avatar, job_title, company, * create_time, create_time_txt, status }], count, page_count } * ⚠️ 详情页红点计数技巧: lists?page=1&page_size=1 取 count 即可 * ⚠️ 后端契约要求 lists 走 GET(分页在 query); 而 Http.sendRequest 是 * 「带 data 就发 POST」的语义, 所以这里把分页拼进 url、不传 data, * 否则会被发成 POST 导致接口不匹配、列表恒为空。 */ exchangeLists(p) { const opt = Object.assign({}, p || {}); const src = opt.data || opt; const page = src.page || 1; const pageSize = src.page_size || 20; delete opt.data; delete opt.page; delete opt.page_size; opt.url = CARD_API_URL.EXCHANGE_LISTS + '?page=' + page + '&page_size=' + pageSize; Http.sendRequest(opt); }, /** * 同意交换(后端自动双方建人脉,前端无需再调 contact/add) * 幂等: 同侧已存在同手机号人脉时 receiver_created=0,仍是成功,不当失败 * @param {Object} p { data: { id }, success, fail } * 返回 data: { id, status:1, receiver_created, initiator_created } */ exchangeAgree(p) { Http.sendJson(Object.assign({ url: CARD_API_URL.EXCHANGE_AGREE }, p || {})); }, /** * 忽略交换(仅本方隐藏 status=2,对方不发通知、可再次发起) * @param {Object} p { data: { id }, success, fail } * 返回 data: { id, status:2 } */ exchangeIgnore(p) { Http.sendJson(Object.assign({ url: CARD_API_URL.EXCHANGE_IGNORE }, p || {})); }, /** * 同意交换后「校验 + 兜底」建人脉(页面点「同意」后必调;幂等,可安全重复调用)。 * 背景: 后端声明 CardExchange::agree 会双向互存人脉(我方人脉收对方名片 / 对方人脉收我方名片), * 但实测出现「同意成功、对方名片却没进我的人脉」, 故前端不再只信 receiver_created, * 统一在同意后按「对方名片编号」校验一次: 我的人脉里没有同手机号记录才补建。 * 流程: 取对方名片详情 → 按手机号查我的人脉 → 不存在则以 source=exchange 新建人脉。 * 幂等: 同手机号人脉已存在(含后端已建)时 created=0, 与后台已建不会重复。 * @param {Object} p { fromCardId, success, fail } * 回调 done(data): { code, created, existed } created=1 新建 / 0 已存在或无需建; * existed = 命中的同手机号人脉行(未命中为 null), 供页面提示「人脉中已有该联系人」。 */ ensureExchangeContact(p) { const self = this; const done = p.success, fail = p.fail; const finish = (d) => { typeof done === 'function' && done(d); }; const fromCardId = p.fromCardId; if (!fromCardId) { finish({ code: 0, created: 0 }); return; } this.cardDetail({ data: { card_id: fromCardId }, success: res => { if (res.code != 0) { typeof fail === 'function' && fail(res); return; } const r = (res.data && (res.data.relation || res.data)) || {}; const mobile = r.mobile || ''; const fields = { name: r.name || '', company: r.company || '', job_title: r.job_title || '', mobile: mobile, source: 'exchange' }; // 富化字段仅在对方有名片值时带上(空串=清空语义, 新建人脉时不传空键) if (r.wechat) fields.wechat = r.wechat; if (r.email) fields.email = r.email; if (r.website) fields.website = r.website; if (r.address) fields.address = r.address; const add = () => self.contactAdd({ data: { source: 'exchange', fields: fields }, success: res2 => { // code!=0(如手机号已存在被拒): 交换已同意成功, 兜底不打扰用户, 按无需新建收口 const ok = res2 && res2.code == 0; finish({ code: ok ? 0 : ((res2 && res2.code) || 0), created: ok ? 1 : 0, raw: res2 }); }, fail: err => { typeof fail === 'function' && fail(err); } }); // 按手机号去重: 已存在同手机号人脉则不重复建(兼容后台已建 / 重复同意) if (mobile) { self.contactLists({ data: { page: 1, page_size: 20, keyword: mobile }, success: res3 => { const d3 = res3.data || {}; const list = Array.isArray(d3) ? d3 : (d3.list || []); const hit = list.find(c => (c.mobile || '') === mobile); // 命中: 对方已在我的人脉里(可能显示为旧姓名), 不覆盖用户维护过的数据, 只回传命中行 if (hit) { finish({ code: 0, created: 0, existed: hit }); return; } add(); }, fail: () => add() }); } else { add(); } }, fail: err => { typeof fail === 'function' && fail(err); } }); }, /* ================= 员工建卡申请 2.11.15 ================= */ /** * 提交建卡申请(空态申请 → 商家审批 → 自动建卡归属) * 约束: 同一会员同时只允许一条待审申请(重复提交后端会拒) * 入参: { data: { name, mobile } } * @param {Object} p { data: { name, mobile }, success, fail } */ applySubmit(p) { Http.sendRequest(Object.assign({ url: CARD_API_URL.APPLY_SUBMIT }, p || {})); }, /** * 查询我的建卡申请状态(进入名片夹/空态时调用或轮询) * 成功 data: { status: 0 待审/1 已同意/2 已拒绝, status_text, note, has_card } * @param {Object} p { success, fail } */ applyStatus(p) { Http.sendRequest(Object.assign({ url: CARD_API_URL.APPLY_STATUS }, p || {})); }, /* ================= 名片设计(员工端可选样式) ================= */ /** * 拉取名片预设列表(与商家后台 CardTemplatePresets 同一份, 同源) * 成功 data: { list:[{ key, name, desc, thumb, * design:{ theme_color, text_color, bg_color, layout, cover, font_family, * font_scale, card_radius, header_gradient_end, header_gradient_angle, quick_style } }] } * @param {Object} p { success, fail } */ cardDesignPresets(p) { Http.sendRequest(Object.assign({ url: CARD_API_URL.CARD_DESIGN_PRESETS }, p || {})); }, /** * 应用预设 / 保存本卡样式(员工端选择后台预设后落库) * 入参(包在 data 里): { card_id, preset_key } —— 后端按 preset_key 取 CardTemplatePresets * 的 design 合并进本卡 lucky_card_design(非空覆盖), 返回 { code:0 } * @param {Object} p { data: { card_id, preset_key }, success, fail } */ cardDesignSave(p) { Http.sendJson(Object.assign({ url: CARD_API_URL.CARD_DESIGN_SAVE }, p || {})); }, /* ================= 企业名片 2.13.6 ================= */ /** * 企业名片详情(核心) * GET ?card_id= 不传返回当前生效企业名片;传候选卡 id 可预览(is_active=0) * 成功 data: { card_id, is_active, is_owner, fields:{name,company,job_title,mobile,email, * website,address,wechat,avatar,bio,name_en,company_en,job_title_en,bio_en}, * design:{theme_color,bg_color,text_color,template_id,canvas,header_mode,official_card_id}, * header:{mode,official_card_id,official,self,staff} } * 渲染: 名片区按 header.mode 取 official/self/staff 数据, 内容区用 fields+design.canvas * 失败「企业名片不存在」→ 前端空态引导去管理端创建 * @param {Object} p { data: { card_id? }, success, fail } */ enterpriseDetail(p) { Http.sendRequest(Object.assign({ url: CARD_API_URL.ENTERPRISE_DETAIL }, p || {})); }, /** * 保存企业名片(后台/会员;owner_id=0 的卡会员不可改) * @param {Object} p { data: { card_id?, fields?, design?, header_mode?, official_card_id? }, success, fail } */ enterpriseSave(p) { Http.sendJson(Object.assign({ url: CARD_API_URL.ENTERPRISE_SAVE }, p || {})); }, /** * 我的企业名片列表(自己名下) * 成功 data: { list: [{ card_id, name, is_active }] } * @param {Object} p { success, fail } */ enterpriseMine(p) { Http.sendRequest(Object.assign({ url: CARD_API_URL.ENTERPRISE_MINE }, p || {})); }, /** * 切换生效企业名片(互斥:全店仅 1 张 is_active=1,仅能切自己名下的卡) * @param {Object} p { data: { card_id }, success, fail } */ enterpriseActivate(p) { Http.sendJson(Object.assign({ url: CARD_API_URL.ENTERPRISE_ACTIVATE }, p || {})); }, /** * 员工自选展示名片(self 模式):card_id 必须是自己名下的 contact 卡 * 选择按会员存储;detail 的 header.self.chosen=1 表示已自选 * @param {Object} p { data: { card_id }, success, fail } */ enterpriseChooseSelf(p) { Http.sendJson(Object.assign({ url: CARD_API_URL.ENTERPRISE_CHOOSE_SELF }, p || {})); }, /** * 删除企业名片(会员端;生效卡不可删,删除候选卡会清理官方名片引用) * @param {Object} p { data: { card_id }, success, fail } */ enterpriseDelete(p) { Http.sendJson(Object.assign({ url: CARD_API_URL.ENTERPRISE_DELETE }, p || {})); } }; export default CardApi;