feat: 亮灯表重构 — 点击卡片弹窗替代跳转周报
后端 light_board.py: - 每张客户卡片返回 plans[] (活跃工作计划) + recent_visits[] (最近2条) - 计划过期检测 (plan_overdue) 前端 LightBoard.vue: - 点击卡片 → el-dialog 弹窗 (不再跳转周报) - 绿灯: 显示最近拜访记录 - 黄/红灯: 客户信息 + 快速制定拜访计划表单 - 卡片显示计划标签 (📅正常 / ⚠过期闪烁) - 弹窗底部保留「查看周报记录」链接 计划过期逻辑: plan_date < 当月首日 且 status=计划中 Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -15,6 +15,7 @@ from app.models.user import User
|
||||
from app.models.customer import Customer
|
||||
from app.models.customer_assignment import CustomerAssignment
|
||||
from app.models.visit import Visit
|
||||
from app.models.work_plan import WorkPlan
|
||||
from app.utils.timezone import today_cst
|
||||
|
||||
|
||||
@@ -156,6 +157,59 @@ async def get_light_board(
|
||||
else:
|
||||
mgr_entry["not_visited_2months"] += 1
|
||||
|
||||
# ── Active work plans per customer ──
|
||||
active_plans_result = await db.execute(
|
||||
select(
|
||||
WorkPlan.customer_id,
|
||||
WorkPlan.plan_content,
|
||||
WorkPlan.plan_date,
|
||||
WorkPlan.status,
|
||||
WorkPlan.manager_id,
|
||||
).where(
|
||||
WorkPlan.customer_id.in_(assigned_customer_ids),
|
||||
WorkPlan.status == "计划中",
|
||||
).order_by(WorkPlan.plan_date)
|
||||
)
|
||||
plans_map: dict[UUID, list] = {}
|
||||
for row in active_plans_result.all():
|
||||
cid, content, pdate, pstatus, pmanager = row
|
||||
plans_map.setdefault(cid, []).append({
|
||||
"plan_content": content,
|
||||
"plan_date": str(pdate),
|
||||
"status": pstatus,
|
||||
"plan_overdue": pdate < ref,
|
||||
"manager_id": str(pmanager) if pmanager else None,
|
||||
})
|
||||
|
||||
# ── Recent visits for green/yellow customers ──
|
||||
recent_visits_result = await db.execute(
|
||||
select(
|
||||
Visit.customer_id,
|
||||
Visit.visit_date,
|
||||
Visit.visit_method,
|
||||
Visit.communication_content,
|
||||
Visit.manager_id,
|
||||
).where(
|
||||
Visit.customer_id.in_(assigned_customer_ids),
|
||||
).order_by(Visit.visit_date.desc()).limit(500)
|
||||
)
|
||||
visits_map: dict[UUID, list] = {}
|
||||
for row in recent_visits_result.all():
|
||||
cid, vdate, vmethod, vcontent, vmanager = row
|
||||
visits_map.setdefault(cid, []).append({
|
||||
"visit_date": str(vdate),
|
||||
"visit_method": vmethod,
|
||||
"content": (vcontent or "")[:120],
|
||||
"manager_id": str(vmanager) if vmanager else None,
|
||||
})
|
||||
|
||||
# ── Merge plans & visits into customer entries ──
|
||||
for mgr_entry in manager_map.values():
|
||||
for c in mgr_entry["customers"]:
|
||||
cid = UUID(c["customer_id"])
|
||||
c["plans"] = plans_map.get(cid, [])
|
||||
c["recent_visits"] = (visits_map.get(cid, []) or [])[:2]
|
||||
|
||||
# ── Calculate coverage rates ──
|
||||
for mgr_entry in manager_map.values():
|
||||
total = mgr_entry["total_customers"]
|
||||
|
||||
Reference in New Issue
Block a user