Merge branch 'main' into develop

# Conflicts:
#	backend/app/api/key_visits.py
#	backend/app/api/mini_business.py
#	backend/app/api/visits.py
#	backend/app/api/work_plans.py
#	backend/app/main.py
#	backend/app/models/__init__.py
#	backend/app/schemas/key_visit.py
#	backend/app/schemas/mini_business.py
#	backend/app/schemas/work_plan.py
#	backend/app/services/light_board.py
#	frontend/src/components/DesktopLayout.vue
#	frontend/src/stores/theme.ts
#	frontend/src/views/desktop/ManagerWorkspace.vue
#	frontend/src/views/desktop/WorkPlans.vue
#	frontend/src/views/mobile/KeyVisitForm.vue
#	frontend/src/views/mobile/LeaveForm.vue
#	frontend/src/views/mobile/PlansList.vue
#	frontend/src/views/mobile/VisitForm.vue
#	frontend/src/views/mobile/WorkPlanForm.vue
This commit is contained in:
2026-08-17 09:31:12 +08:00
46 changed files with 2682 additions and 213 deletions
+4
View File
@@ -45,6 +45,7 @@ class ContactOut(BaseModel):
# ── Customer ──
class CustomerCreate(BaseModel):
name: str
customer_type: str = "unit"
industry: str = ""
address: str = ""
in_use_services: str = ""
@@ -56,6 +57,7 @@ class CustomerCreate(BaseModel):
class CustomerUpdate(BaseModel):
name: Optional[str] = None
customer_type: Optional[str] = None
industry: Optional[str] = None
address: Optional[str] = None
in_use_services: Optional[str] = None
@@ -67,6 +69,7 @@ class CustomerUpdate(BaseModel):
class CustomerOut(BaseModel):
id: uuid.UUID
name: str
customer_type: str = "unit"
industry: str
address: str
in_use_services: str
@@ -84,6 +87,7 @@ class CustomerOut(BaseModel):
class CustomerListOut(BaseModel):
id: uuid.UUID
name: str
customer_type: str = "unit"
industry: str
in_use_services: str
primary_manager_name: Optional[str] = None
+2
View File
@@ -9,6 +9,7 @@ class DailyNoteCreate(BaseModel):
category: str = "其他"
content: str = ""
time_range: str = ""
manager_id: Optional[uuid.UUID] = None
class DailyNoteUpdate(BaseModel):
@@ -16,6 +17,7 @@ class DailyNoteUpdate(BaseModel):
category: Optional[str] = None
content: Optional[str] = None
time_range: Optional[str] = None
manager_id: Optional[uuid.UUID] = None
class DailyNoteOut(BaseModel):
+2 -1
View File
@@ -11,6 +11,7 @@ class KeyVisitCreate(BaseModel):
planned_date: str = ""
planned_visitor: str = ""
visit_target: str = ""
manager_id: Optional[uuid.UUID] = None
class KeyVisitUpdate(BaseModel):
@@ -21,7 +22,7 @@ class KeyVisitUpdate(BaseModel):
planned_date: Optional[str] = None
planned_visitor: Optional[str] = None
visit_target: Optional[str] = None
manager_id: Optional[str] = None
manager_id: Optional[uuid.UUID] = None
class KeyVisitOut(BaseModel):
+2 -1
View File
@@ -10,6 +10,7 @@ class MiniBusinessCreate(BaseModel):
follow_up_detail: str = ""
status: str = "跟进中"
expected_revenue_date: str = ""
manager_id: Optional[uuid.UUID] = None
class MiniBusinessUpdate(BaseModel):
@@ -19,7 +20,7 @@ class MiniBusinessUpdate(BaseModel):
follow_up_detail: Optional[str] = None
status: Optional[str] = None
expected_revenue_date: Optional[str] = None
manager_id: Optional[str] = None
manager_id: Optional[uuid.UUID] = None
class MiniBusinessOut(BaseModel):
+33
View File
@@ -0,0 +1,33 @@
"""MiniBusinessLog Pydantic schemas."""
from datetime import date, datetime
from uuid import UUID
from typing import Optional
from pydantic import BaseModel, Field
FOLLOW_UP_METHODS = ["电话", "微信", "上门", "邮件", "其他"]
class MiniBusinessLogCreate(BaseModel):
log_date: date
method: str = Field(default="电话", pattern="^(电话|微信|上门|邮件|其他)$")
content: str = ""
class MiniBusinessLogUpdate(BaseModel):
log_date: Optional[date] = None
method: Optional[str] = Field(default=None, pattern="^(电话|微信|上门|邮件|其他)$")
content: Optional[str] = None
class MiniBusinessLogOut(BaseModel):
id: UUID
business_id: UUID
log_date: date
method: str
content: str
created_by: UUID
created_by_name: str = ""
created_at: datetime | None = None
model_config = {"from_attributes": True}
+2
View File
@@ -16,6 +16,7 @@ class VisitCreate(BaseModel):
companions: list[uuid.UUID] = []
companion_names: list[str] = []
photos: list[str] = []
manager_id: Optional[uuid.UUID] = None # director/leader can specify
class VisitUpdate(BaseModel):
@@ -28,6 +29,7 @@ class VisitUpdate(BaseModel):
communication_content: Optional[str] = None
customer_demand: Optional[str] = None
companions: Optional[list[uuid.UUID]] = None
manager_id: Optional[uuid.UUID] = None
companion_names: Optional[list[str]] = None
photos: Optional[list[str]] = None
manager_id: Optional[str] = None
+2 -1
View File
@@ -9,6 +9,7 @@ class WorkPlanCreate(BaseModel):
plan_content: str = ""
plan_date: str # "YYYY-MM-DD"
status: str = "计划中"
manager_id: Optional[uuid.UUID] = None
class WorkPlanUpdate(BaseModel):
@@ -16,7 +17,7 @@ class WorkPlanUpdate(BaseModel):
plan_content: Optional[str] = None
plan_date: Optional[str] = None
status: Optional[str] = None
manager_id: Optional[str] = None
manager_id: Optional[uuid.UUID] = None
class WorkPlanOut(BaseModel):