02-客户管理API接口.md 38 KB

客户管理模块 - API接口文档

模块: 02-客户管理
版本: v1.0
日期: 2025-10-03
关联文档:

  • 需求文档: docs/02-客户管理模块需求.md
  • 原型图: yuanxing/02-客户管理原型图.md
  • 数据库: sql/crm/02-crm_customer.sql

📋 目录


1. 客户管理接口

1.1 查询客户列表(分页)

接口地址: GET /crm/customer/list

接口描述: 分页查询客户列表,支持多条件筛选

权限标识: crm:customer:list

请求参数: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | pageNum | Integer | 否 | 页码,默认1 | | pageSize | Integer | 否 | 每页条数,默认10 | | customerName | String | 否 | 客户名称(模糊查询) | | customerNo | String | 否 | 客户编号(模糊查询) | | mobile | String | 否 | 手机号(模糊查询) | | customerType | String | 否 | 客户类型:字典值crm_customer_type | | level | String | 否 | 客户级别:key/normal/potential | | source | String | 否 | 客户来源 | | industry | String | 否 | 所属行业 | | scale | String | 否 | 企业规模 | | province | String | 否 | 省份 | | city | String | 否 | 城市 | | status | String | 否 | 客户状态:normal/pool/invalid | | dealStatus | String | 否 | 成交状态:not_deal/dealed/lost | | ownerUserId | Long | 否 | 负责人ID | | beginTime | String | 否 | 开始时间 yyyy-MM-dd HH:mm:ss | | endTime | String | 否 | 结束时间 yyyy-MM-dd HH:mm:ss |

返回示例:

{
  "code": 200,
  "msg": "查询成功",
  "rows": [
    {
      "id": 1,
      "customerNo": "C202501010001",
      "customerName": "华为技术有限公司",
      "shortName": "华为",
      "customerType": "company",
      "mobile": "13900001234",
      "telephone": "0571-12345678",
      "email": "contact@huawei.com",
      "website": "https://www.huawei.com",
      "level": "key",
      "source": "website",
      "industry": "互联网/IT",
      "scale": "500人以上",
      "province": "广东省",
      "city": "深圳市",
      "district": "龙岗区",
      "address": "XXX科技园",
      "status": "normal",
      "dealStatus": "dealed",
      "ownerUserId": 1,
      "ownerUserName": "张三",
      "lastTime": "2025-01-02 10:30:00",
      "nextTime": "2025-01-05 14:00:00",
      "followCount": 15,
      "dealTime": "2024-12-15 16:00:00",
      "dealAmount": 150000.00,
      "contactCount": 3,
      "opportunityCount": 2,
      "contractCount": 1,
      "clueId": 10,
      "createTime": "2024-12-01 09:00:00",
      "remark": ""
    }
  ],
  "total": 230
}

1.2 查询客户详情

接口地址: GET /crm/customer/{id}

接口描述: 根据ID查询客户详细信息

权限标识: crm:customer:query

请求参数: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | id | Long | 是 | 客户ID |

返回示例:

{
  "code": 200,
  "msg": "操作成功",
  "data": {
    "id": 1,
    "customerNo": "C202501010001",
    "customerName": "华为技术有限公司",
    "shortName": "华为",
    "customerType": "company",
    "mobile": "13900001234",
    "telephone": "0571-12345678",
    "email": "contact@huawei.com",
    "website": "https://www.huawei.com",
    "level": "key",
    "source": "website",
    "industry": "互联网/IT",
    "scale": "500人以上",
    "province": "广东省",
    "city": "深圳市",
    "district": "龙岗区",
    "address": "XXX科技园",
    "status": "normal",
    "dealStatus": "dealed",
    "ownerUserId": 1,
    "ownerUserName": "张三",
    "lastTime": "2025-01-02 10:30:00",
    "nextTime": "2025-01-05 14:00:00",
    "followCount": 15,
    "dealTime": "2024-12-15 16:00:00",
    "dealAmount": 150000.00,
    "contactCount": 3,
    "opportunityCount": 2,
    "contractCount": 1,
    "intoPoolTime": null,
    "claimTime": null,
    "protectTime": null,
    "clueId": 10,
    "createTime": "2024-12-01 09:00:00",
    "createBy": 1,
    "updateTime": "2025-01-02 10:30:00",
    "updateBy": 1,
    "remark": ""
  }
}

1.3 新增客户

接口地址: POST /crm/customer

接口描述: 新增客户信息

权限标识: crm:customer:add

请求体:

{
  "customerNo": "C202501010001",
  "customerName": "华为技术有限公司",
  "shortName": "华为",
  "customerType": "company",
  "mobile": "13900001234",
  "telephone": "0571-12345678",
  "email": "contact@huawei.com",
  "website": "https://www.huawei.com",
  "level": "key",
  "source": "website",
  "industry": "互联网/IT",
  "scale": "500人以上",
  "province": "广东省",
  "city": "深圳市",
  "district": "龙岗区",
  "address": "XXX科技园",
  "ownerUserId": 1,
  "nextTime": "2025-01-05 14:00:00",
  "remark": ""
}

请求参数说明: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | customerNo | String | 是 | 客户编号,唯一,最大50字符 | | customerName | String | 是 | 客户名称,最大200字符 | | shortName | String | 否 | 客户简称,最大100字符 | | customerType | String | 否 | 客户类型:字典值crm_customer_type | | mobile | String | 否 | 手机号,最大20字符 | | telephone | String | 否 | 固定电话,最大30字符 | | email | String | 否 | 邮箱,最大100字符 | | website | String | 否 | 客户网站,最大500字符 | | level | String | 否 | 客户级别:key/normal/potential,默认normal | | source | String | 否 | 客户来源 | | industry | String | 否 | 所属行业,最大50字符 | | scale | String | 否 | 企业规模 | | province | String | 否 | 省份,最大50字符 | | city | String | 否 | 城市,最大50字符 | | district | String | 否 | 区县,最大50字符 | | address | String | 否 | 详细地址,最大255字符 | | ownerUserId | Long | 否 | 负责人ID,默认为当前用户 | | nextTime | String | 否 | 下次联系时间 yyyy-MM-dd HH:mm:ss | | remark | String | 否 | 备注,最大500字符 |

校验规则:

  • 客户编号必须唯一
  • 邮箱需符合邮箱格式
  • 负责人ID必须存在

返回示例:

{
  "code": 200,
  "msg": "操作成功"
}

1.4 修改客户

接口地址: PUT /crm/customer

接口描述: 修改客户信息

权限标识: crm:customer:edit

请求体: 同新增接口,但需要传入id

返回示例:

{
  "code": 200,
  "msg": "操作成功"
}

1.5 删除客户

接口地址: DELETE /crm/customer/{ids}

接口描述: 删除客户(支持批量)

权限标识: crm:customer:remove

请求参数: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | ids | Long[] | 是 | 客户ID数组,多个用逗号分隔 |

业务规则:

  • 已成交的客户不允许删除
  • 有关联商机、合同的客户不允许删除
  • 删除客户时同时删除关联的联系人和跟进记录

返回示例:

{
  "code": 200,
  "msg": "操作成功"
}

1.6 批量分配客户

接口地址: PUT /crm/customer/assign

接口描述: 批量分配客户给指定负责人

权限标识: crm:customer:assign

请求体:

{
  "ids": [1, 2, 3],
  "ownerUserId": 5,
  "remark": "分配原因"
}

请求参数说明: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | ids | Long[] | 是 | 客户ID数组 | | ownerUserId | Long | 是 | 新负责人ID | | remark | String | 否 | 分配说明 |

业务规则:

  • 公海池中的客户不允许分配,需先领取
  • 记录分配时间和分配人

返回示例:

{
  "code": 200,
  "msg": "操作成功"
}

1.7 修改客户级别

接口地址: PUT /crm/customer/level

接口描述: 修改客户级别

权限标识: crm:customer:edit

请求体:

{
  "id": 1,
  "level": "key",
  "remark": "客户升级为重点客户"
}

请求参数说明: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | id | Long | 是 | 客户ID | | level | String | 是 | 客户级别:key/normal/potential | | remark | String | 否 | 级别变更说明 |

返回示例:

{
  "code": 200,
  "msg": "操作成功"
}

1.8 修改成交状态

接口地址: PUT /crm/customer/dealStatus

接口描述: 修改客户成交状态

权限标识: crm:customer:edit

请求体:

{
  "id": 1,
  "dealStatus": "dealed",
  "dealTime": "2025-01-05 16:00:00",
  "dealAmount": 150000.00,
  "remark": "签订了CRM系统合同"
}

请求参数说明: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | id | Long | 是 | 客户ID | | dealStatus | String | 是 | 成交状态:not_deal/dealed/lost | | dealTime | String | 否 | 成交时间(状态为dealed时必填) | | dealAmount | BigDecimal | 否 | 成交金额(状态为dealed时必填) | | remark | String | 否 | 状态变更说明 |

返回示例:

{
  "code": 200,
  "msg": "操作成功"
}

1.9 放入公海池

接口地址: PUT /crm/customer/intoPool

接口描述: 将客户放入公海池

权限标识: crm:customer:pool

请求体:

{
  "ids": [1, 2, 3],
  "reason": "长期未跟进",
  "remark": "客户3个月未联系"
}

请求参数说明: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | ids | Long[] | 是 | 客户ID数组 | | reason | String | 是 | 放入原因 | | remark | String | 否 | 备注说明 |

业务规则:

  • 只能放入本人负责的客户
  • 已成交的客户不允许放入公海
  • 放入时记录进入公海时间和原因

返回示例:

{
  "code": 200,
  "msg": "操作成功"
}

1.10 导出客户

接口地址: POST /crm/customer/export

接口描述: 导出客户数据到Excel

权限标识: crm:customer:export

请求体: 查询参数同1.1列表查询接口

返回: Excel文件流


1.11 导入客户

接口地址: POST /crm/customer/import

接口描述: 批量导入客户数据

权限标识: crm:customer:import

请求参数: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | file | MultipartFile | 是 | Excel文件 | | updateSupport | Boolean | 否 | 是否更新已存在的客户,默认false |

返回示例:

{
  "code": 200,
  "msg": "操作成功",
  "data": {
    "total": 100,
    "success": 95,
    "fail": 5,
    "errors": [
      {
        "row": 3,
        "error": "客户编号已存在"
      }
    ]
  }
}

1.12 下载导入模板

接口地址: POST /crm/customer/importTemplate

接口描述: 下载客户导入Excel模板

权限标识: crm:customer:import

请求参数: 无

返回: Excel文件流


1.13 查询我的客户

接口地址: GET /crm/customer/mine

接口描述: 查询当前用户负责的客户列表

权限标识: crm:customer:list

请求参数: 同1.1列表查询接口

返回示例: 同1.1列表查询接口


1.14 根据编号查询客户

接口地址: GET /crm/customer/no/{customerNo}

接口描述: 根据客户编号查询客户信息

权限标识: crm:customer:query

请求参数: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | customerNo | String | 是 | 客户编号 |

返回示例: 同1.2查询详情接口


2. 联系人管理接口

2.1 查询联系人列表(分页)

接口地址: GET /crm/contact/list

接口描述: 分页查询联系人列表

权限标识: crm:contact:list

请求参数: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | pageNum | Integer | 否 | 页码,默认1 | | pageSize | Integer | 否 | 每页条数,默认10 | | customerId | Long | 否 | 客户ID | | contactName | String | 否 | 联系人姓名(模糊查询) | | mobile | String | 否 | 手机号(模糊查询) | | position | String | 否 | 职位 | | role | String | 否 | 角色:decision/manager/user/other | | isKey | Integer | 否 | 是否关键决策人:0-否 1-是 | | isPrimary | Integer | 否 | 是否主要联系人:0-否 1-是 | | status | String | 否 | 状态:active/leave |

返回示例:

{
  "code": 200,
  "msg": "查询成功",
  "rows": [
    {
      "id": 1,
      "customerId": 1,
      "customerName": "华为技术有限公司",
      "contactName": "张伟",
      "gender": "male",
      "mobile": "13900001234",
      "telephone": "0571-12345678",
      "email": "zhangwei@huawei.com",
      "wechat": "zhangwei123",
      "qq": "123456789",
      "department": "技术部",
      "position": "技术总监",
      "role": "decision",
      "birthday": "1980-05-15",
      "address": "深圳市XXX",
      "isKey": 1,
      "isPrimary": 1,
      "status": "active",
      "createTime": "2024-12-01 09:30:00",
      "remark": ""
    }
  ],
  "total": 156
}

2.2 查询联系人详情

接口地址: GET /crm/contact/{id}

接口描述: 根据ID查询联系人详细信息

权限标识: crm:contact:query

请求参数: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | id | Long | 是 | 联系人ID |

返回示例: 同2.1列表返回的单条数据


2.3 新增联系人

接口地址: POST /crm/contact

接口描述: 新增联系人信息

权限标识: crm:contact:add

请求体:

{
  "customerId": 1,
  "contactName": "张伟",
  "gender": "male",
  "mobile": "13900001234",
  "telephone": "0571-12345678",
  "email": "zhangwei@huawei.com",
  "wechat": "zhangwei123",
  "qq": "123456789",
  "department": "技术部",
  "position": "技术总监",
  "role": "decision",
  "birthday": "1980-05-15",
  "address": "深圳市XXX",
  "isKey": 1,
  "isPrimary": 1,
  "remark": ""
}

请求参数说明: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | customerId | Long | 是 | 客户ID | | contactName | String | 是 | 联系人姓名,最大100字符 | | gender | String | 否 | 性别:male/female | | mobile | String | 否 | 手机号,最大20字符 | | telephone | String | 否 | 固定电话,最大30字符 | | email | String | 否 | 邮箱,最大100字符 | | wechat | String | 否 | 微信号,最大100字符 | | qq | String | 否 | QQ号,最大20字符 | | department | String | 否 | 部门,最大100字符 | | position | String | 否 | 职位,最大50字符 | | role | String | 否 | 角色:decision/manager/user/other | | birthday | String | 否 | 生日,格式yyyy-MM-dd | | address | String | 否 | 住址,最大255字符 | | isKey | Integer | 否 | 是否关键决策人:0-否 1-是,默认0 | | isPrimary | Integer | 否 | 是否主要联系人:0-否 1-是,默认0 | | remark | String | 否 | 备注,最大500字符 |

业务规则:

  • 新增联系人后,客户的contactCount自动+1
  • 如果设置为主要联系人,需要取消其他联系人的主要标识

返回示例:

{
  "code": 200,
  "msg": "操作成功"
}

2.4 修改联系人

接口地址: PUT /crm/contact

接口描述: 修改联系人信息

权限标识: crm:contact:edit

请求体: 同新增接口,但需要传入id

返回示例:

{
  "code": 200,
  "msg": "操作成功"
}

2.5 删除联系人

接口地址: DELETE /crm/contact/{ids}

接口描述: 删除联系人(支持批量)

权限标识: crm:contact:remove

请求参数: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | ids | Long[] | 是 | 联系人ID数组 |

业务规则:

  • 删除联系人后,客户的contactCount自动-1

返回示例:

{
  "code": 200,
  "msg": "操作成功"
}

2.6 设置主要联系人

接口地址: PUT /crm/contact/setPrimary/{id}

接口描述: 设置为主要联系人

权限标识: crm:contact:edit

请求参数: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | id | Long | 是 | 联系人ID |

业务规则:

  • 同一客户只能有一个主要联系人
  • 设置新的主要联系人时,自动取消其他联系人的主要标识

返回示例:

{
  "code": 200,
  "msg": "操作成功"
}

2.7 根据客户查询联系人

接口地址: GET /crm/contact/customer/{customerId}

接口描述: 查询指定客户的所有联系人

权限标识: crm:contact:list

请求参数: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | customerId | Long | 是 | 客户ID |

返回示例:

{
  "code": 200,
  "msg": "查询成功",
  "data": [
    {
      "id": 1,
      "contactName": "张伟",
      "mobile": "13900001234",
      "position": "技术总监",
      "role": "decision",
      "isKey": 1,
      "isPrimary": 1,
      "status": "active"
    }
  ]
}

3. 客户跟进记录接口

3.1 查询跟进记录列表

接口地址: GET /crm/customer/follow/list

接口描述: 查询指定客户的跟进记录列表

权限标识: crm:customer:query

请求参数: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | customerId | Long | 是 | 客户ID | | pageNum | Integer | 否 | 页码,默认1 | | pageSize | Integer | 否 | 每页条数,默认10 |

返回示例:

{
  "code": 200,
  "msg": "查询成功",
  "rows": [
    {
      "id": 1,
      "customerId": 1,
      "customerName": "华为技术有限公司",
      "contactId": 1,
      "contactName": "张伟",
      "followType": "phone",
      "followContent": "电话沟通了项目进展情况",
      "nextTime": "2025-01-08 14:00:00",
      "attachments": "/upload/2025/01/file1.pdf",
      "createBy": 1,
      "createByName": "张三",
      "createTime": "2025-01-05 10:30:00",
      "remark": ""
    }
  ],
  "total": 15
}

3.2 新增跟进记录

接口地址: POST /crm/customer/follow

接口描述: 新增客户跟进记录

权限标识: crm:customer:follow

请求体:

{
  "customerId": 1,
  "contactId": 1,
  "followType": "phone",
  "followContent": "电话沟通了项目进展情况",
  "nextTime": "2025-01-08 14:00:00",
  "attachments": "/upload/2025/01/file1.pdf",
  "remark": ""
}

请求参数说明: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | customerId | Long | 是 | 客户ID | | contactId | Long | 否 | 联系人ID | | followType | String | 是 | 跟进方式:phone/wechat/email/visit/other | | followContent | String | 是 | 跟进内容,文本类型 | | nextTime | String | 否 | 下次联系时间 yyyy-MM-dd HH:mm:ss | | attachments | String | 否 | 附件路径,多个用逗号分隔 | | remark | String | 否 | 备注,最大500字符 |

业务规则:

  • 新增跟进记录后,自动更新客户的lastTime和followCount
  • 如果设置了nextTime,同步更新客户的nextTime

返回示例:

{
  "code": 200,
  "msg": "操作成功"
}

3.3 修改跟进记录

接口地址: PUT /crm/customer/follow

接口描述: 修改跟进记录信息

权限标识: crm:customer:follow

请求体: 同新增接口,但需要传入id

业务规则:

  • 只能修改自己创建的跟进记录

返回示例:

{
  "code": 200,
  "msg": "操作成功"
}

3.4 删除跟进记录

接口地址: DELETE /crm/customer/follow/{ids}

接口描述: 删除跟进记录(支持批量)

权限标识: crm:customer:follow

请求参数: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | ids | Long[] | 是 | 跟进记录ID数组 |

业务规则:

  • 只能删除自己创建的跟进记录
  • 删除后需要重新计算客户的followCount

返回示例:

{
  "code": 200,
  "msg": "操作成功"
}

4. 客户公海池接口

4.1 查询公海池列表

接口地址: GET /crm/customer/pool/list

接口描述: 查询公海池中的客户列表

权限标识: crm:customer:pool:list

请求参数: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | pageNum | Integer | 否 | 页码,默认1 | | pageSize | Integer | 否 | 每页条数,默认10 | | customerName | String | 否 | 客户名称(模糊查询) | | level | String | 否 | 客户级别 | | industry | String | 否 | 所属行业 | | province | String | 否 | 省份 | | city | String | 否 | 城市 |

返回示例:

{
  "code": 200,
  "msg": "查询成功",
  "rows": [
    {
      "id": 10,
      "customerNo": "C202501010010",
      "customerName": "XXX科技有限公司",
      "level": "normal",
      "industry": "互联网/IT",
      "province": "浙江省",
      "city": "杭州市",
      "intoPoolTime": "2025-01-01 10:00:00",
      "followCount": 3,
      "lastTime": "2024-12-15 14:00:00",
      "protectTime": null,
      "poolReason": "长期未跟进",
      "poolRemark": "客户3个月未联系"
    }
  ],
  "total": 45
}

4.2 领取客户

接口地址: POST /crm/customer/pool/claim

接口描述: 从公海池领取客户

权限标识: crm:customer:pool:claim

请求体:

{
  "ids": [10, 11, 12],
  "remark": "领取原因"
}

请求参数说明: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | ids | Long[] | 是 | 客户ID数组 | | remark | String | 否 | 领取说明 |

业务规则:

  • 只能领取公海池中的客户
  • 领取后客户状态变为normal
  • 负责人设置为当前用户
  • 记录领取时间和领取人
  • 设置保护期(如7天内不能再次放入公海)

返回示例:

{
  "code": 200,
  "msg": "操作成功"
}

4.3 查询公海池记录

接口地址: GET /crm/customer/pool/record/list

接口描述: 查询客户的公海池记录(进出记录)

权限标识: crm:customer:query

请求参数: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | customerId | Long | 是 | 客户ID |

返回示例:

{
  "code": 200,
  "msg": "查询成功",
  "data": [
    {
      "id": 1,
      "customerId": 10,
      "operateType": "into",
      "reason": "长期未跟进",
      "operateBy": 1,
      "operateByName": "张三",
      "operateTime": "2025-01-01 10:00:00",
      "remark": "客户3个月未联系"
    },
    {
      "id": 2,
      "customerId": 10,
      "operateType": "claim",
      "reason": "重新跟进",
      "operateBy": 5,
      "operateByName": "李四",
      "operateTime": "2025-01-03 14:00:00",
      "remark": "领取客户"
    }
  ]
}

5. 统计分析接口

5.1 客户统计概览

接口地址: GET /crm/customer/statistics/overview

接口描述: 获取客户统计概览数据

权限标识: crm:customer:list

请求参数: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | ownerUserId | Long | 否 | 负责人ID,不传则查询当前用户 | | beginTime | String | 否 | 开始时间 | | endTime | String | 否 | 结束时间 |

返回示例:

{
  "code": 200,
  "msg": "查询成功",
  "data": {
    "totalCount": 230,
    "keyCount": 45,
    "normalCount": 150,
    "potentialCount": 35,
    "dealedCount": 89,
    "notDealCount": 128,
    "lostCount": 13,
    "weekAddCount": 12,
    "poolCount": 15,
    "dealRate": 38.70,
    "totalDealAmount": 5680000.00
  }
}

5.2 客户级别分布

接口地址: GET /crm/customer/statistics/level

接口描述: 按客户级别统计分布情况

权限标识: crm:customer:list

请求参数: 无

返回示例:

{
  "code": 200,
  "msg": "查询成功",
  "data": [
    {
      "level": "key",
      "levelName": "重点客户",
      "count": 45,
      "percent": 19.57,
      "dealAmount": 3200000.00
    },
    {
      "level": "normal",
      "levelName": "普通客户",
      "count": 150,
      "percent": 65.22,
      "dealAmount": 2100000.00
    },
    {
      "level": "potential",
      "levelName": "潜在客户",
      "count": 35,
      "percent": 15.22,
      "dealAmount": 380000.00
    }
  ]
}

5.3 客户来源统计

接口地址: GET /crm/customer/statistics/source

接口描述: 按客户来源统计数量和成交情况

权限标识: crm:customer:list

请求参数: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | beginTime | String | 否 | 开始时间 | | endTime | String | 否 | 结束时间 |

返回示例:

{
  "code": 200,
  "msg": "查询成功",
  "data": [
    {
      "source": "website",
      "sourceName": "网站留言",
      "count": 67,
      "dealedCount": 28,
      "dealRate": 41.79,
      "dealAmount": 1500000.00
    }
  ]
}

5.4 客户成交趋势

接口地址: GET /crm/customer/statistics/trend

接口描述: 查询客户新增和成交趋势(按天/周/月)

权限标识: crm:customer:list

请求参数: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | type | String | 否 | 统计类型:day/week/month,默认day | | beginTime | String | 否 | 开始时间 | | endTime | String | 否 | 结束时间 |

返回示例:

{
  "code": 200,
  "msg": "查询成功",
  "data": [
    {
      "date": "2025-01-01",
      "addCount": 8,
      "dealCount": 3,
      "dealAmount": 450000.00
    }
  ]
}

5.5 负责人客户统计

接口地址: GET /crm/customer/statistics/owner

接口描述: 按负责人统计客户数量和成交情况

权限标识: crm:customer:list

请求参数: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | beginTime | String | 否 | 开始时间 | | endTime | String | 否 | 结束时间 |

返回示例:

{
  "code": 200,
  "msg": "查询成功",
  "data": [
    {
      "ownerUserId": 1,
      "ownerUserName": "张三",
      "totalCount": 56,
      "keyCount": 12,
      "dealedCount": 23,
      "dealRate": 41.07,
      "dealAmount": 2100000.00,
      "avgFollowCount": 8.5
    }
  ]
}

6. 数据模型

6.1 CustomerBo(客户业务对象)

public class CrmCustomerBo extends BaseEntity {
    /** 主键ID */
    @NotNull(message = "主键不能为空", groups = { EditGroup.class })
    private Long id;

    /** 客户编号 */
    @NotBlank(message = "客户编号不能为空", groups = { AddGroup.class, EditGroup.class })
    private String customerNo;

    /** 客户名称 */
    @NotBlank(message = "客户名称不能为空", groups = { AddGroup.class, EditGroup.class })
    private String customerName;

    /** 客户简称 */
    private String shortName;

    /** 客户类型 */
    private String customerType;

    /** 手机号 */
    private String mobile;

    /** 固定电话 */
    private String telephone;

    /** 邮箱 */
    @Email(message = "邮箱格式错误")
    private String email;

    /** 客户网站 */
    private String website;

    /** 客户级别 */
    private String level;

    /** 客户来源 */
    private String source;

    /** 所属行业 */
    private String industry;

    /** 企业规模 */
    private String scale;

    /** 省 */
    private String province;

    /** 市 */
    private String city;

    /** 区 */
    private String district;

    /** 详细地址 */
    private String address;

    /** 负责人ID */
    private Long ownerUserId;

    /** 下次联系时间 */
    private LocalDateTime nextTime;

    /** 备注 */
    private String remark;
}

6.2 CustomerVo(客户视图对象)

public class CrmCustomerVo implements Serializable {
    /** 主键ID */
    @ExcelProperty(value = "ID")
    private Long id;

    /** 客户编号 */
    @ExcelProperty(value = "客户编号")
    private String customerNo;

    /** 客户名称 */
    @ExcelProperty(value = "客户名称")
    private String customerName;

    /** 客户简称 */
    @ExcelProperty(value = "客户简称")
    private String shortName;

    /** 客户类型 */
    @ExcelProperty(value = "客户类型", converter = ExcelDictConvert.class)
    @ExcelDictFormat(dictType = "crm_customer_type")
    private String customerType;

    /** 手机号 */
    @ExcelProperty(value = "手机号")
    private String mobile;

    /** 固定电话 */
    @ExcelProperty(value = "固定电话")
    private String telephone;

    /** 邮箱 */
    @ExcelProperty(value = "邮箱")
    private String email;

    /** 客户网站 */
    @ExcelProperty(value = "客户网站")
    private String website;

    /** 客户级别 */
    @ExcelProperty(value = "客户级别", converter = ExcelDictConvert.class)
    @ExcelDictFormat(dictType = "crm_customer_level")
    private String level;

    /** 客户来源 */
    @ExcelProperty(value = "客户来源", converter = ExcelDictConvert.class)
    @ExcelDictFormat(dictType = "crm_clue_source")
    private String source;

    /** 所属行业 */
    @ExcelProperty(value = "所属行业")
    private String industry;

    /** 企业规模 */
    @ExcelProperty(value = "企业规模", converter = ExcelDictConvert.class)
    @ExcelDictFormat(dictType = "crm_company_scale")
    private String scale;

    /** 省 */
    @ExcelProperty(value = "省")
    private String province;

    /** 市 */
    @ExcelProperty(value = "市")
    private String city;

    /** 区 */
    @ExcelProperty(value = "区")
    private String district;

    /** 详细地址 */
    @ExcelProperty(value = "详细地址")
    private String address;

    /** 客户状态 */
    @ExcelProperty(value = "客户状态", converter = ExcelDictConvert.class)
    @ExcelDictFormat(dictType = "crm_customer_status")
    private String status;

    /** 成交状态 */
    @ExcelProperty(value = "成交状态", converter = ExcelDictConvert.class)
    @ExcelDictFormat(dictType = "crm_deal_status")
    private String dealStatus;

    /** 负责人ID */
    private Long ownerUserId;

    /** 负责人姓名 */
    @ExcelProperty(value = "负责人")
    private String ownerUserName;

    /** 最后跟进时间 */
    @ExcelProperty(value = "最后跟进时间")
    private LocalDateTime lastTime;

    /** 下次联系时间 */
    @ExcelProperty(value = "下次联系时间")
    private LocalDateTime nextTime;

    /** 跟进次数 */
    @ExcelProperty(value = "跟进次数")
    private Integer followCount;

    /** 成交时间 */
    @ExcelProperty(value = "成交时间")
    private LocalDateTime dealTime;

    /** 累计成交金额 */
    @ExcelProperty(value = "累计成交金额")
    private BigDecimal dealAmount;

    /** 联系人数量 */
    private Integer contactCount;

    /** 商机数量 */
    private Integer opportunityCount;

    /** 合同数量 */
    private Integer contractCount;

    /** 进入公海时间 */
    private LocalDateTime intoPoolTime;

    /** 领取时间 */
    private LocalDateTime claimTime;

    /** 保护到期时间 */
    private LocalDateTime protectTime;

    /** 关联线索ID */
    private Long clueId;

    /** 创建时间 */
    @ExcelProperty(value = "创建时间")
    private LocalDateTime createTime;

    /** 更新时间 */
    @ExcelProperty(value = "更新时间")
    private LocalDateTime updateTime;

    /** 备注 */
    @ExcelProperty(value = "备注")
    private String remark;
}

6.3 ContactBo(联系人业务对象)

public class CrmContactBo extends BaseEntity {
    /** 主键ID */
    @NotNull(message = "主键不能为空", groups = { EditGroup.class })
    private Long id;

    /** 客户ID */
    @NotNull(message = "客户ID不能为空", groups = { AddGroup.class })
    private Long customerId;

    /** 联系人姓名 */
    @NotBlank(message = "联系人姓名不能为空", groups = { AddGroup.class, EditGroup.class })
    private String contactName;

    /** 性别 */
    private String gender;

    /** 手机号 */
    private String mobile;

    /** 固定电话 */
    private String telephone;

    /** 邮箱 */
    @Email(message = "邮箱格式错误")
    private String email;

    /** 微信号 */
    private String wechat;

    /** QQ号 */
    private String qq;

    /** 部门 */
    private String department;

    /** 职位 */
    private String position;

    /** 角色 */
    private String role;

    /** 生日 */
    private String birthday;

    /** 住址 */
    private String address;

    /** 是否关键决策人 */
    private Integer isKey;

    /** 是否主要联系人 */
    private Integer isPrimary;

    /** 备注 */
    private String remark;
}

6.4 ContactVo(联系人视图对象)

public class CrmContactVo implements Serializable {
    /** 主键ID */
    private Long id;

    /** 客户ID */
    private Long customerId;

    /** 客户名称 */
    @ExcelProperty(value = "客户名称")
    private String customerName;

    /** 联系人姓名 */
    @ExcelProperty(value = "联系人姓名")
    private String contactName;

    /** 性别 */
    @ExcelProperty(value = "性别", converter = ExcelDictConvert.class)
    @ExcelDictFormat(dictType = "sys_user_sex")
    private String gender;

    /** 手机号 */
    @ExcelProperty(value = "手机号")
    private String mobile;

    /** 固定电话 */
    @ExcelProperty(value = "固定电话")
    private String telephone;

    /** 邮箱 */
    @ExcelProperty(value = "邮箱")
    private String email;

    /** 微信号 */
    @ExcelProperty(value = "微信号")
    private String wechat;

    /** QQ号 */
    @ExcelProperty(value = "QQ号")
    private String qq;

    /** 部门 */
    @ExcelProperty(value = "部门")
    private String department;

    /** 职位 */
    @ExcelProperty(value = "职位")
    private String position;

    /** 角色 */
    @ExcelProperty(value = "角色", converter = ExcelDictConvert.class)
    @ExcelDictFormat(dictType = "crm_contact_role")
    private String role;

    /** 生日 */
    @ExcelProperty(value = "生日")
    private String birthday;

    /** 住址 */
    @ExcelProperty(value = "住址")
    private String address;

    /** 是否关键决策人 */
    @ExcelProperty(value = "关键决策人")
    private Integer isKey;

    /** 是否主要联系人 */
    @ExcelProperty(value = "主要联系人")
    private Integer isPrimary;

    /** 状态 */
    @ExcelProperty(value = "状态", converter = ExcelDictConvert.class)
    @ExcelDictFormat(dictType = "crm_contact_status")
    private String status;

    /** 创建时间 */
    @ExcelProperty(value = "创建时间")
    private LocalDateTime createTime;

    /** 备注 */
    @ExcelProperty(value = "备注")
    private String remark;
}

7. 数据字典

7.1 客户类型 (crm_customer_type)

字典值 字典标签 说明
company 企业客户 企业法人客户
person 个人客户 个人客户

7.2 客户级别 (crm_customer_level)

字典值 字典标签 说明
key 重点客户 重要客户
normal 普通客户 普通客户
potential 潜在客户 潜在客户

7.3 客户状态 (crm_customer_status)

字典值 字典标签 说明
normal 正常 正常状态
pool 公海 公海池中
invalid 无效 无效客户

7.4 成交状态 (crm_deal_status)

字典值 字典标签 说明
not_deal 未成交 尚未成交
dealed 已成交 已成交
lost 已流失 客户流失

7.5 企业规模 (crm_company_scale)

字典值 字典标签 说明
1_50 1-50人 小微企业
50_200 50-200人 小型企业
200_500 200-500人 中型企业
500_plus 500人以上 大型企业

7.6 联系人角色 (crm_contact_role)

字典值 字典标签 说明
decision 决策人 决策者
manager 管理者 管理层
user 使用者 使用人员
other 其他 其他角色

7.7 联系人状态 (crm_contact_status)

字典值 字典标签 说明
active 在职 在职状态
leave 离职 已离职

8. 权限标识汇总

权限标识 说明
crm:customer:list 客户列表查询
crm:customer:query 客户详情查询
crm:customer:add 客户新增
crm:customer:edit 客户修改
crm:customer:remove 客户删除
crm:customer:export 客户导出
crm:customer:import 客户导入
crm:customer:assign 客户分配
crm:customer:follow 添加跟进记录
crm:customer:pool 放入公海池
crm:customer:pool:list 公海池列表查询
crm:customer:pool:claim 领取客户
crm:contact:list 联系人列表查询
crm:contact:query 联系人详情查询
crm:contact:add 联系人新增
crm:contact:edit 联系人修改
crm:contact:remove 联系人删除

9. 注意事项

  1. 客户编号唯一性: 同一租户下客户编号必须唯一
  2. 数据权限: 需要根据负责人字段实现数据权限控制
  3. 跟进记录关联: 新增跟进记录时自动更新客户的跟进统计信息
  4. 联系人计数: 新增/删除联系人时自动维护客户的contactCount
  5. 公海池规则: 放入公海池需要满足一定条件(如长期未跟进)
  6. 保护期机制: 领取客户后设置保护期,期间不能再次放入公海
  7. 主要联系人: 同一客户只能有一个主要联系人
  8. 成交限制: 已成交的客户不允许删除和放入公海
  9. 批量操作: 批量操作需要注意事务一致性
  10. 数据脱敏: 手机号和邮箱需要根据权限进行脱敏显示

文档结束