feat: 富消息升级 — 催办用模板卡片 + 公告用 Markdown
scheduler.py: - 未填报经理 → 模板卡片消息(标题+描述+「去填报」按钮) - 支局长/领导 → Markdown 每日填报汇总(markdown) - 文本消息作为降级方案 wecom.py API: - remind: 模板卡片优先 → 降级文本 - announcement: Markdown 优先 → 降级文本 Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -201,9 +201,17 @@ async def send_reminder(
|
|||||||
wecom_ids = [r[0] for r in result.all() if r[0]]
|
wecom_ids = [r[0] for r in result.all() if r[0]]
|
||||||
|
|
||||||
content = data.message or "📋 请及时完成今日拜访记录填报。"
|
content = data.message or "📋 请及时完成今日拜访记录填报。"
|
||||||
success = await wecom_client.send_text_message(wecom_ids, content)
|
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")
|
@router.post("/announcement")
|
||||||
@@ -212,14 +220,16 @@ async def send_announcement(
|
|||||||
current_user: dict = Depends(require_director),
|
current_user: dict = Depends(require_director),
|
||||||
db: AsyncSession = Depends(get_db),
|
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)))
|
result = await db.execute(select(User.wecom_userid).where(User.wecom_userid.isnot(None)))
|
||||||
wecom_ids = [r[0] for r in result.all()]
|
wecom_ids = [r[0] for r in result.all()]
|
||||||
|
|
||||||
content = f"📢 支局长公告\n\n{data.content}"
|
markdown = f"## 📢 支局长公告\n\n{data.content}"
|
||||||
success = await wecom_client.send_text_message(wecom_ids, 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")
|
@router.post("/test-message")
|
||||||
|
|||||||
@@ -21,6 +21,9 @@ async def check_daily_reporting(db: AsyncSession) -> dict:
|
|||||||
)
|
)
|
||||||
managers = result.scalars().all()
|
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
|
# Get managers who have reported today
|
||||||
reported_visits = await db.execute(
|
reported_visits = await db.execute(
|
||||||
select(Visit.manager_id).where(Visit.visit_date == today)
|
select(Visit.manager_id).where(Visit.visit_date == today)
|
||||||
@@ -40,21 +43,43 @@ async def check_daily_reporting(db: AsyncSession) -> dict:
|
|||||||
else:
|
else:
|
||||||
not_reported.append(m)
|
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:
|
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]
|
user_ids = [m.wecom_userid for m in not_reported if m.wecom_userid]
|
||||||
if user_ids:
|
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 {
|
return {
|
||||||
"status": "ok",
|
"status": "ok",
|
||||||
|
|||||||
Reference in New Issue
Block a user