3285e22142
=== 导入系统全面增强 === - 5 Sheet 完整导入:拜访/计划/商机/要客/纪要 - 同访人智能解析:中英文逗号/顿号/分号 → 系统用户UUID + 外部人员TEXT - 客户自动创建:Excel中不存在的客户自动入库 - 模糊名称匹配:去空格 + 包含关系纠错 - manager_id 修正:导入时用客户分配的经理(非Excel列/非导入人) - 模板更新:Sheet5「客户经理」→「填报人」,同访人示例含逗号分隔 === 客户合并功能 === - PUT 改名碰撞检测 → 409 + 合并预览 - GET merge-preview / POST merge 端点 - 事务级迁移:Visit/WorkPlan/MiniBusiness/KeyVisit/联系人/分配 - 去重逻辑:联系人(name+phone)、分配(manager+role) - last_visit_date 取最大值 === 拜访记录完善 === - visits 新增 companion_names TEXT[] 列 - 同访人支持自定义输入(外部人员),el-select allow-create - 移动端 VisitForm + PC端 ManagerWorkspace 统一 - 周报「客户经理」→「相关人员」(创建人+同访人) - 纪要「客户经理」→「填报人」 - 删除拜访后重新计算 customer.last_visit_date === 客户选择放开 === - 客户经理可看到全部客户(不再限自己分配的) - 拜访时客户下拉返回全量 === 前端性能优化 === - Element Plus 按需加载 (unplugin-vue-components + unplugin-element-plus) - 周报照片URL并行请求 (Promise.all) - onMounted 三路并行 (loadReport + dropdowns + AI) - nginx Cache-Control: immutable for /assets/ - Google Fonts preconnect hints - 图片上传前 Canvas 压缩 (max 1920px, quality 0.8) Co-Authored-By: Claude <noreply@anthropic.com>
70 lines
1.9 KiB
Python
70 lines
1.9 KiB
Python
from pydantic import BaseModel, Field
|
|
from typing import Optional
|
|
import uuid
|
|
from datetime import date, datetime
|
|
|
|
|
|
class VisitCreate(BaseModel):
|
|
customer_id: uuid.UUID
|
|
visit_date: str # "YYYY-MM-DD"
|
|
visit_method: str = "上门"
|
|
time_range: str = ""
|
|
visitor_name: str = ""
|
|
visitor_phone: str = ""
|
|
communication_content: str = ""
|
|
customer_demand: str = ""
|
|
companions: list[uuid.UUID] = []
|
|
companion_names: list[str] = []
|
|
photos: list[str] = []
|
|
|
|
|
|
class VisitUpdate(BaseModel):
|
|
customer_id: Optional[uuid.UUID] = None
|
|
visit_date: Optional[str] = None
|
|
visit_method: Optional[str] = None
|
|
time_range: Optional[str] = None
|
|
visitor_name: Optional[str] = None
|
|
visitor_phone: Optional[str] = None
|
|
communication_content: Optional[str] = None
|
|
customer_demand: Optional[str] = None
|
|
companions: Optional[list[uuid.UUID]] = None
|
|
companion_names: Optional[list[str]] = None
|
|
photos: Optional[list[str]] = None
|
|
|
|
|
|
class VisitOut(BaseModel):
|
|
id: uuid.UUID
|
|
customer_id: uuid.UUID
|
|
visit_date: date
|
|
visit_method: str
|
|
time_range: str
|
|
visitor_name: str = ""
|
|
visitor_phone: str = ""
|
|
communication_content: str
|
|
customer_demand: str
|
|
companions: Optional[list[uuid.UUID]] = None
|
|
companion_names: list[str] = []
|
|
photos: Optional[list[str]] = None
|
|
manager_id: uuid.UUID
|
|
created_at: datetime
|
|
updated_at: datetime
|
|
# Joined fields
|
|
customer_name: Optional[str] = None
|
|
manager_name: Optional[str] = None
|
|
|
|
model_config = {"from_attributes": True}
|
|
|
|
|
|
class VisitListOut(BaseModel):
|
|
id: uuid.UUID
|
|
customer_id: uuid.UUID
|
|
visit_date: date
|
|
visit_method: str
|
|
time_range: str
|
|
manager_id: uuid.UUID
|
|
customer_name: Optional[str] = None
|
|
manager_name: Optional[str] = None
|
|
has_photos: bool = False
|
|
|
|
model_config = {"from_attributes": True}
|