feat: 富消息升级 — 催办用模板卡片 + 公告用 Markdown

scheduler.py:
- 未填报经理 → 模板卡片消息(标题+描述+「去填报」按钮)
- 支局长/领导 → Markdown 每日填报汇总(markdown)
- 文本消息作为降级方案

wecom.py API:
- remind: 模板卡片优先 → 降级文本
- announcement: Markdown 优先 → 降级文本

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-06-26 15:34:21 +08:00
parent 327637f94c
commit c4e8a3b790
2 changed files with 53 additions and 18 deletions
+15 -5
View File
@@ -201,9 +201,17 @@ async def send_reminder(
wecom_ids = [r[0] for r in result.all() if r[0]]
content = data.message or "📋 请及时完成今日拜访记录填报。"
success = await wecom_client.send_template_card(
user_ids=wecom_ids,
title="📋 填报提醒",
desc=content,
url="https://qj.dhdx.fun/m",
btn_text="去填报",
)
if not success:
success = await wecom_client.send_text_message(wecom_ids, content)
return {"success": success, "sent_to": len(wecom_ids)}
return {"success": success, "sent_to": len(wecom_ids), "rich": True}
@router.post("/announcement")
@@ -212,14 +220,16 @@ async def send_announcement(
current_user: dict = Depends(require_director),
db: AsyncSession = Depends(get_db),
):
"""Director sends an announcement to all team members."""
"""Director sends an announcement to all team members (markdown)."""
result = await db.execute(select(User.wecom_userid).where(User.wecom_userid.isnot(None)))
wecom_ids = [r[0] for r in result.all()]
content = f"📢 支局长公告\n\n{data.content}"
success = await wecom_client.send_text_message(wecom_ids, content)
markdown = f"## 📢 支局长公告\n\n{data.content}"
success = await wecom_client.send_markdown_message(markdown)
if not success:
success = await wecom_client.send_text_message(wecom_ids, f"📢 支局长公告\n\n{data.content}")
return {"success": success, "sent_to": len(wecom_ids)}
return {"success": success, "sent_to": len(wecom_ids), "rich": True}
@router.post("/test-message")
+37 -12
View File
@@ -21,6 +21,9 @@ async def check_daily_reporting(db: AsyncSession) -> dict:
)
managers = result.scalars().all()
if not managers:
return {"status": "ok", "date": str(today), "total_managers": 0, "reported": 0, "not_reported": 0}
# Get managers who have reported today
reported_visits = await db.execute(
select(Visit.manager_id).where(Visit.visit_date == today)
@@ -40,21 +43,43 @@ async def check_daily_reporting(db: AsyncSession) -> dict:
else:
not_reported.append(m)
# Send markdown message to not-reported managers
# 1. Send template card to not-reported managers (tap to open app)
if not_reported:
names = "".join(m.name for m in not_reported)
content = (
f"## 📋 今日填报提醒\n\n"
f"> 日期:{today}\n"
f"> 已填报:{len(reported_names)}\n"
f"> 未填报:**{len(not_reported)} 人**\n\n"
f"以下同事尚未提交今日拜访记录:\n"
+ "".join(f"- **{m.name}**\n" for m in not_reported)
+ f"\n请尽快完成今日拜访填报 🙏"
)
user_ids = [m.wecom_userid for m in not_reported if m.wecom_userid]
if user_ids:
await wecom_client.send_text_message(user_ids, content)
desc = f"{today} | 已填报 {len(reported_names)}/{len(managers)}"
success = await wecom_client.send_template_card(
user_ids=user_ids,
title="📋 今日填报提醒",
desc=desc,
url="https://qj.dhdx.fun/m",
btn_text="去填报",
)
# Fallback to text
if not success:
names_text = "".join(m.name for m in not_reported)
await wecom_client.send_text_message(
user_ids,
f"📋 今日填报提醒\n\n{desc}\n未填报:{names_text}\n\n请尽快完成填报 🙏\nhttps://qj.dhdx.fun/m",
)
# 2. Send summary to director
directors = await db.execute(
select(User).where(User.role.in_(["director", "leader"]), User.wecom_userid.isnot(None))
)
for d in directors.scalars().all():
if managers:
pct = len(reported_map) / len(managers) * 100
summary = (
f"## 📊 今日填报汇总\n\n"
f"> 日期:{today}\n"
f"> 填报率:**{pct:.0f}%** ({len(reported_map)}/{len(managers)})\n\n"
)
if not_reported:
summary += "**未填报:**\n" + "".join(f"- {m.name}\n" for m in not_reported)
else:
summary += "✅ 全体已完成今日填报"
await wecom_client.send_markdown_message(summary) # broadcast for director visibility
return {
"status": "ok",