feat: 修复 H5 底部导航覆盖 + 更新项目进度文档

## H5 底部导航修复 (Bug #10)
- 精简 App.vue,移除重复 tabbar,仅保留全局样式
- uni-page 设置 height: calc(100% - 50px) + overflow-y: auto
- 内容区域精确停在底部导航上方,独立滚动不再叠加
- 恢复 custom-tab-bar 组件

## 项目进度文档
- PROGRESS.md 更新至 10 个 Bug 修复
- 新增 H5 底部导航修复记录
- 新增历史变更条目
This commit is contained in:
TradeMate Dev
2026-05-12 20:24:42 +08:00
parent 69e164dcae
commit 7b62c2f8b4
125 changed files with 19725 additions and 728 deletions
+59 -2
View File
@@ -85,6 +85,48 @@ class WhatsAppService:
)
return resp.status_code == 200
async def send_media(self, to: str, media_url: str, media_type: str = "image", caption: Optional[str] = None) -> bool:
if not self.api_token or not self.phone_number_id:
return False
body = {
"messaging_product": "whatsapp",
"to": to,
"type": media_type,
media_type: {"link": media_url},
}
if caption:
body[media_type]["caption"] = caption
async with httpx.AsyncClient() as client:
resp = await client.post(
f"{self.api_base}/messages",
headers={"Authorization": f"Bearer {self.api_token}", "Content-Type": "application/json"},
json=body,
timeout=30,
)
if resp.status_code != 200:
logger.error(f"WhatsApp media send failed: {resp.text}")
return False
return True
async def mark_as_read(self, message_id: str) -> bool:
if not self.api_token:
return False
async with httpx.AsyncClient() as client:
resp = await client.post(
f"{self.api_base}/messages",
headers={"Authorization": f"Bearer {self.api_token}", "Content-Type": "application/json"},
json={
"messaging_product": "whatsapp",
"status": "read",
"message_id": message_id,
},
timeout=10,
)
return resp.status_code == 200
def parse_webhook(self, body: Dict) -> Optional[Dict]:
try:
entry = body.get("entry", [{}])[0]
@@ -96,14 +138,29 @@ class WhatsAppService:
return None
msg = messages[0]
msg_type = msg.get("type", "text")
content = ""
if msg_type == "text":
content = msg.get("text", {}).get("body", "")
elif msg_type in ("image", "document", "audio", "video"):
media = msg.get(msg_type, {})
content = media.get("caption", "") or media.get("filename", "") or f"[{msg_type}]"
return {
"from": msg.get("from"),
"text": msg.get("text", {}).get("body", ""),
"text": content,
"msg_id": msg.get("id"),
"timestamp": msg.get("timestamp"),
"type": msg.get("type", "text"),
"type": msg_type,
"profile_name": value.get("contacts", [{}])[0].get("profile", {}).get("name"),
}
except Exception as e:
logger.warning(f"Failed to parse WhatsApp webhook: {e}")
return None
def _build_headers(self) -> Dict[str, str]:
return {
"Authorization": f"Bearer {self.api_token}",
"Content-Type": "application/json",
}