Files
shanxia2.0/backend/app/schemas/crm/clue.py
T
2026-08-22 09:08:05 +08:00

178 lines
9.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""CRM 线索管理 Pydantic Schemas"""
from typing import List, Optional
from pydantic import BaseModel, ConfigDict, Field
# ── 线索列表查询 ──────────────────────────────────────────────────
class ClueListBody(BaseModel):
model_config = ConfigDict(populate_by_name=True)
page: int = Field(default=1, ge=1, description="页码")
pageSize: int = Field(default=10, ge=1, le=500, description="每页条数")
keyword: Optional[str] = Field(default=None, description="搜索关键词(线索名称/手机号)")
search_keyword: Optional[str] = Field(
default=None, alias="searchKeyword", description="快速搜索关键词(与 keyword 等价)"
)
clue_name: Optional[str] = Field(default=None, alias="clueName", description="线索名称")
company: Optional[str] = Field(default=None, description="公司名称")
mobile: Optional[str] = Field(default=None, description="手机号")
source: Optional[str] = Field(default=None, description="线索来源")
level: Optional[str] = Field(default=None, description="线索级别")
status: Optional[str] = Field(default=None, description="线索状态")
industry: Optional[str] = Field(default=None, description="所属行业")
park_area: Optional[str] = Field(default=None, alias="parkArea", description="所在园区")
owner_user_id: Optional[str] = Field(default=None, alias="ownerUserId", description="负责人ID")
view_type: Optional[str] = Field(
default=None, alias="viewType", description="视图类型(mine/all/toFollow/todayNew/converted)"
)
view_mode: Optional[str] = Field(default=None, alias="viewMode", description="视图模式(mine/all)")
create_time_range: Optional[List[str]] = Field(
default=None, alias="createTimeRange", description="创建时间范围 [start, end]"
)
begin_time: Optional[str] = Field(default=None, alias="beginTime", description="创建时间起")
end_time: Optional[str] = Field(default=None, alias="endTime", description="创建时间止")
# ── 线索新增/编辑 ──────────────────────────────────────────────────
ids: Optional[List[str]] = Field(default=None, description="导出指定ID列表")
columns: Optional[List[str]] = Field(default=None, description="导出列(前端 visibleColumns)")
class ClueCreateBody(BaseModel):
model_config = ConfigDict(populate_by_name=True)
clue_name: str = Field(..., alias="clueName", min_length=1, max_length=100, description="线索名称")
mobile: str = Field(..., min_length=1, max_length=20, description="手机号")
company: Optional[str] = Field(default=None, max_length=200, description="公司名称")
customer_type: Optional[str] = Field(default=None, alias="customerType", max_length=20, description="客户类型")
telephone: Optional[str] = Field(default=None, max_length=30, description="座机")
email: Optional[str] = Field(default=None, max_length=100, description="邮箱")
title: Optional[str] = Field(default=None, max_length=10, description="称谓")
position: Optional[str] = Field(default=None, max_length=50, description="职位")
source: str = Field(..., max_length=20, description="线索来源")
level: Optional[str] = Field(default="unrated", max_length=10, description="线索级别")
industry: Optional[str] = Field(default=None, max_length=50, description="所属行业")
park_area: Optional[str] = Field(default=None, alias="parkArea", max_length=100, description="所在园区")
province: Optional[str] = Field(default=None, max_length=50, description="省份")
city: Optional[str] = Field(default=None, max_length=50, description="城市")
district: Optional[str] = Field(default=None, max_length=50, description="区县")
address: Optional[str] = Field(default=None, max_length=255, description="详细地址")
website: Optional[str] = Field(default=None, max_length=500, description="网站")
intent_products: Optional[str] = Field(
default=None, alias="intentProducts", max_length=500, description="意向产品"
)
expect_time: Optional[str] = Field(default=None, alias="expectTime", description="预计购买时间")
budget: Optional[str] = Field(default=None, max_length=20, description="预算")
requirement: Optional[str] = Field(default=None, description="需求描述")
owner_user_id: Optional[str] = Field(default=None, alias="ownerUserId", description="负责人ID")
next_time: Optional[str] = Field(default=None, alias="nextTime", description="下次联系时间")
remark: Optional[str] = Field(default=None, max_length=512, description="备注")
class ClueUpdateBody(ClueCreateBody):
id: str = Field(..., min_length=1, description="线索ID")
# ── 线索操作 ──────────────────────────────────────────────────
class ClueDeleteBody(BaseModel):
model_config = ConfigDict(populate_by_name=True)
ids: List[str] = Field(..., min_length=1, description="线索ID列表")
class ClueAssignBody(BaseModel):
model_config = ConfigDict(populate_by_name=True)
ids: List[str] = Field(..., min_length=1, description="线索ID列表")
owner_user_id: str = Field(..., alias="ownerUserId", description="新负责人ID")
remark: Optional[str] = Field(default=None, description="分配说明")
class ClueConvertBody(BaseModel):
model_config = ConfigDict(populate_by_name=True)
id: str = Field(..., min_length=1, description="线索ID")
customer_name: Optional[str] = Field(default=None, alias="customerName", description="客户名称")
customer_type: Optional[str] = Field(default=None, alias="customerType", description="客户类型")
contact_name: Optional[str] = Field(default=None, alias="contactName", description="联系人姓名")
contact_mobile: Optional[str] = Field(default=None, alias="contactMobile", description="联系人手机号")
remark: Optional[str] = Field(default=None, description="转化说明")
class ClueStatusBody(BaseModel):
model_config = ConfigDict(populate_by_name=True)
id: str = Field(..., min_length=1, description="线索ID")
status: str = Field(..., max_length=20, description="目标状态")
class ClueLevelBody(BaseModel):
model_config = ConfigDict(populate_by_name=True)
ids: List[str] = Field(..., min_length=1, description="线索ID列表")
level: str = Field(..., max_length=10, description="目标级别")
class ClueInvalidBody(BaseModel):
model_config = ConfigDict(populate_by_name=True)
id: Optional[str] = Field(default=None, description="线索ID")
ids: Optional[List[str]] = Field(default=None, description="线索ID列表")
remark: Optional[str] = Field(default=None, description="作废原因")
# ── 跟进记录 ──────────────────────────────────────────────────
class ClueFollowListBody(BaseModel):
model_config = ConfigDict(populate_by_name=True)
clue_id: str = Field(..., alias="clueId", description="线索ID")
page: int = Field(default=1, ge=1, description="页码")
pageSize: int = Field(default=10, ge=1, le=500, description="每页条数")
class ClueFollowCreateBody(BaseModel):
model_config = ConfigDict(populate_by_name=True)
clue_id: str = Field(..., alias="clueId", description="线索ID")
follow_type: str = Field(..., alias="followType", max_length=20, description="跟进方式")
follow_content: str = Field(..., alias="followContent", description="跟进内容")
next_time: Optional[str] = Field(default=None, alias="nextTime", description="下次联系时间")
attachments: Optional[str] = Field(default=None, max_length=1000, description="附件URL(逗号分隔)")
remark: Optional[str] = Field(default=None, description="备注")
class ClueFollowDeleteBody(BaseModel):
model_config = ConfigDict(populate_by_name=True)
ids: List[str] = Field(..., min_length=1, description="跟进记录ID列表")
class ClueFollowUpdateBody(BaseModel):
model_config = ConfigDict(populate_by_name=True)
id: str = Field(..., min_length=1, description="跟进记录ID")
follow_type: Optional[str] = Field(default=None, alias="followType", description="跟进方式")
follow_content: Optional[str] = Field(default=None, alias="followContent", description="跟进内容")
next_time: Optional[str] = Field(default=None, alias="nextTime", description="下次联系时间")
attachments: Optional[str] = Field(default=None, max_length=1000, description="附件URL(逗号分隔)")
remark: Optional[str] = Field(default=None, description="备注")
class ClueStatisticsBody(BaseModel):
model_config = ConfigDict(populate_by_name=True)
begin_time: Optional[str] = Field(default=None, alias="beginTime", description="开始日期")
end_time: Optional[str] = Field(default=None, alias="endTime", description="结束日期")
owner_user_id: Optional[str] = Field(default=None, alias="ownerUserId", description="负责人ID")
time_unit: Optional[str] = Field(default="day", alias="timeUnit", description="趋势粒度 day/week/month")
type: Optional[str] = Field(default=None, description="趋势粒度别名")