修改通知模板
This commit is contained in:
+8
-2
@@ -57,7 +57,7 @@ wechat_app:
|
|||||||
- **立即搜索**:执行一次完整的公告搜索,获取最新数据
|
- **立即搜索**:执行一次完整的公告搜索,获取最新数据
|
||||||
- **今日统计**:查看今日公告统计信息和数据概览
|
- **今日统计**:查看今日公告统计信息和数据概览
|
||||||
- **关键词搜索**:输入关键词搜索相关公告
|
- **关键词搜索**:输入关键词搜索相关公告
|
||||||
- **最新公告**:浏览最近发布的10条公告
|
- **最新公告**:选择公告来源查看该来源的最新10条公告
|
||||||
|
|
||||||
#### ⚙️ 系统管理
|
#### ⚙️ 系统管理
|
||||||
- **关键词管理**:查看当前系统监控的关键词
|
- **关键词管理**:查看当前系统监控的关键词
|
||||||
@@ -89,8 +89,14 @@ wechat_app:
|
|||||||
统计 # 查看系统统计信息
|
统计 # 查看系统统计信息
|
||||||
|
|
||||||
# 最新数据
|
# 最新数据
|
||||||
最新公告 # 查看最新发布的公告
|
最新公告 # 选择公告来源查看最新公告
|
||||||
最新 # 同上
|
最新 # 同上
|
||||||
|
|
||||||
|
# 公告来源选择 (发送数字)
|
||||||
|
1 # 查看采购公告
|
||||||
|
2 # 查看结果公告
|
||||||
|
3 # 查看更正公告
|
||||||
|
全部 # 查看全部公告
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 🛠️ 系统管理
|
#### 🛠️ 系统管理
|
||||||
|
|||||||
Binary file not shown.
@@ -37,6 +37,10 @@ class WeChatMessageHandler:
|
|||||||
self.config = get_config()
|
self.config = get_config()
|
||||||
self.monitor_app = None
|
self.monitor_app = None
|
||||||
|
|
||||||
|
# 重复请求保护
|
||||||
|
self._request_cache = {} # {f"{user_id}:{content}": timestamp}
|
||||||
|
self._cache_timeout = 30 # 30秒内相同请求不处理
|
||||||
|
|
||||||
# 菜单配置
|
# 菜单配置
|
||||||
self.menu_config = {
|
self.menu_config = {
|
||||||
"crawl_now": {
|
"crawl_now": {
|
||||||
@@ -158,6 +162,11 @@ class WeChatMessageHandler:
|
|||||||
|
|
||||||
content = content.strip()
|
content = content.strip()
|
||||||
|
|
||||||
|
# 重复请求保护
|
||||||
|
if self._is_duplicate_request(from_user, content):
|
||||||
|
logger.info(f"检测到重复请求: user={from_user}, content={content[:20]}...")
|
||||||
|
return self._create_text_response("请求过于频繁,请稍后再试。", from_user)
|
||||||
|
|
||||||
if content == "帮助" or content == "help":
|
if content == "帮助" or content == "help":
|
||||||
return self._handle_help_guide(from_user)
|
return self._handle_help_guide(from_user)
|
||||||
elif content.startswith("爬取") or content.startswith("搜索"):
|
elif content.startswith("爬取") or content.startswith("搜索"):
|
||||||
@@ -180,6 +189,9 @@ class WeChatMessageHandler:
|
|||||||
return self._handle_clear_cache(from_user)
|
return self._handle_clear_cache(from_user)
|
||||||
elif content in ["采购公告", "结果公告", "更正公告", "合同公告", "预公示", "单一来源", "电子卖场", "履约验收", "工程公告"]:
|
elif content in ["采购公告", "结果公告", "更正公告", "合同公告", "预公示", "单一来源", "电子卖场", "履约验收", "工程公告"]:
|
||||||
return self._handle_search_by_type(content, from_user)
|
return self._handle_search_by_type(content, from_user)
|
||||||
|
elif content in ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "全部", "all"]:
|
||||||
|
# 处理最新公告来源选择
|
||||||
|
return self._handle_latest_news_by_source(content, from_user)
|
||||||
else:
|
else:
|
||||||
return self._handle_keyword_search(f"关键词 {content}", from_user)
|
return self._handle_keyword_search(f"关键词 {content}", from_user)
|
||||||
|
|
||||||
@@ -302,30 +314,152 @@ class WeChatMessageHandler:
|
|||||||
return self._create_text_response("操作失败,请稍后重试", from_user)
|
return self._create_text_response("操作失败,请稍后重试", from_user)
|
||||||
|
|
||||||
def _handle_latest_news(self, from_user: str) -> Optional[str]:
|
def _handle_latest_news(self, from_user: str) -> Optional[str]:
|
||||||
"""处理最新公告菜单"""
|
"""处理最新公告菜单 - 显示来源选择"""
|
||||||
try:
|
try:
|
||||||
logger.info(f"用户 {from_user} 请求最新公告")
|
logger.info(f"用户 {from_user} 请求最新公告")
|
||||||
|
|
||||||
|
response = """📋 最新公告查询
|
||||||
|
|
||||||
|
请选择要查看的公告来源:
|
||||||
|
|
||||||
|
1️⃣ 采购公告 - 招标采购信息
|
||||||
|
2️⃣ 结果公告 - 中标成交信息
|
||||||
|
3️⃣ 更正公告 - 变更澄清信息
|
||||||
|
4️⃣ 合同公告 - 合同签订信息
|
||||||
|
5️⃣ 预公示 - 招标文件预公示
|
||||||
|
6️⃣ 单一来源 - 单一来源采购
|
||||||
|
7️⃣ 电子卖场 - 电子化采购平台
|
||||||
|
8️⃣ 履约验收 - 项目验收信息
|
||||||
|
9️⃣ 工程公告 - 工程建设信息
|
||||||
|
🔟 采购意向 - 采购意向公开
|
||||||
|
|
||||||
|
💡 使用方法:
|
||||||
|
• 发送对应数字选择来源
|
||||||
|
• 例如:发送 "1" 查看采购公告
|
||||||
|
• 发送 "10" 查看采购意向
|
||||||
|
|
||||||
|
或发送 "全部" 查看所有来源的最新公告。"""
|
||||||
|
|
||||||
|
return self._create_text_response(response, from_user)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"最新公告菜单处理异常: {str(e)}")
|
||||||
|
return self._create_text_response("获取最新公告失败,请稍后重试", from_user)
|
||||||
|
|
||||||
|
def _handle_latest_news_by_source(self, source_choice: str, from_user: str) -> Optional[str]:
|
||||||
|
"""处理按来源查看最新公告"""
|
||||||
|
try:
|
||||||
|
logger.info(f"用户 {from_user} 选择公告来源: {source_choice}")
|
||||||
|
|
||||||
|
# 来源映射
|
||||||
|
source_mapping = {
|
||||||
|
"1": ("purchase", "采购公告"),
|
||||||
|
"2": ("result", "结果公告"),
|
||||||
|
"3": ("correction", "更正公告"),
|
||||||
|
"4": ("contract", "合同公告"),
|
||||||
|
"5": ("pre_announcement", "预公示"),
|
||||||
|
"6": ("single_source", "单一来源"),
|
||||||
|
"7": ("electronic_market", "电子卖场"),
|
||||||
|
"8": ("acceptance", "履约验收"),
|
||||||
|
"9": ("engineering", "工程公告"),
|
||||||
|
"10": ("intention", "采购意向")
|
||||||
|
}
|
||||||
|
|
||||||
|
if source_choice == "全部" or source_choice == "all":
|
||||||
|
# 显示所有来源的最新公告
|
||||||
|
return self._handle_latest_news_all(from_user)
|
||||||
|
|
||||||
|
if source_choice not in source_mapping:
|
||||||
|
response = """❌ 无效的选择
|
||||||
|
|
||||||
|
请发送正确的数字(1-10)或"全部"。
|
||||||
|
|
||||||
|
返回公告查询菜单,请点击"最新公告"重新选择。"""
|
||||||
|
return self._create_text_response(response, from_user)
|
||||||
|
|
||||||
|
ann_type, type_name = source_mapping[source_choice]
|
||||||
|
|
||||||
|
# 查询该类型的最新公告
|
||||||
|
try:
|
||||||
|
from ..storage.postgresql import get_storage_manager
|
||||||
|
storage = get_storage_manager()
|
||||||
|
# 获取所有最近公告,然后过滤类型
|
||||||
|
all_announcements = storage.get_recent_announcements(hours=168, limit=100) # 最近7天
|
||||||
|
filtered_announcements = [ann for ann in all_announcements if ann.announcement_type.value == ann_type][:10]
|
||||||
|
|
||||||
|
if filtered_announcements:
|
||||||
|
response = f"""📋 {type_name} - 最新10条
|
||||||
|
|
||||||
|
🕒 更新时间:{datetime.now().strftime('%Y-%m-%d %H:%M')}
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
for i, announcement in enumerate(filtered_announcements, 1):
|
||||||
|
title = announcement.title[:25] + "..." if len(announcement.title) > 25 else announcement.title
|
||||||
|
time_str = announcement.publish_date.strftime('%m-%d %H:%M') if announcement.publish_date else "未知"
|
||||||
|
response += f"{i}. {title}\n 🕒 {time_str} | 🏷️ {announcement.purchase_name or '未知'}\n\n"
|
||||||
|
|
||||||
|
response += "💡 发送关键词可进一步筛选,点击菜单可查看更多功能。"
|
||||||
|
else:
|
||||||
|
response = f"""📋 {type_name}
|
||||||
|
|
||||||
|
暂无该类型的最新公告数据。
|
||||||
|
|
||||||
|
💡 建议:
|
||||||
|
• 点击"立即搜索"更新数据
|
||||||
|
• 该类型公告可能较少出现
|
||||||
|
• 返回重新选择其他类型"""
|
||||||
|
|
||||||
|
except Exception as db_error:
|
||||||
|
logger.warning(f"数据库查询失败: {str(db_error)}")
|
||||||
|
response = f"""📋 {type_name}
|
||||||
|
|
||||||
|
暂时无法获取数据,请稍后重试。
|
||||||
|
|
||||||
|
您可以返回重新选择其他类型。"""
|
||||||
|
|
||||||
|
return self._create_text_response(response, from_user)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"按来源查看最新公告异常: {str(e)}")
|
||||||
|
return self._create_text_response("获取最新公告失败,请稍后重试", from_user)
|
||||||
|
|
||||||
|
def _handle_latest_news_all(self, from_user: str) -> Optional[str]:
|
||||||
|
"""处理查看所有来源的最新公告"""
|
||||||
|
try:
|
||||||
|
logger.info(f"用户 {from_user} 请求查看所有来源最新公告")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from ..storage.postgresql import get_storage_manager
|
from ..storage.postgresql import get_storage_manager
|
||||||
storage = get_storage_manager()
|
storage = get_storage_manager()
|
||||||
latest_announcements = storage.get_recent_announcements(hours=168, limit=10)
|
latest_announcements = storage.get_recent_announcements(hours=168, limit=10)
|
||||||
|
|
||||||
if latest_announcements:
|
if latest_announcements:
|
||||||
response = f"""最新公告 (最近10条)
|
response = f"""📋 全部公告 - 最新10条
|
||||||
|
|
||||||
更新时间: {datetime.now().strftime('%Y-%m-%d %H:%M')}
|
🕒 更新时间:{datetime.now().strftime('%Y-%m-%d %H:%M')}
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
for i, announcement in enumerate(latest_announcements, 1):
|
for i, announcement in enumerate(latest_announcements, 1):
|
||||||
title = announcement.title[:25] + "..." if len(announcement.title) > 25 else announcement.title
|
title = announcement.title[:25] + "..." if len(announcement.title) > 25 else announcement.title
|
||||||
time_str = announcement.publish_date.strftime('%m-%d %H:%M') if announcement.publish_date else "未知"
|
time_str = announcement.publish_date.strftime('%m-%d %H:%M') if announcement.publish_date else "未知"
|
||||||
response += f"{i}. {title}\n {time_str} | {announcement.purchase_name or '未知'}\n\n"
|
type_name = {
|
||||||
|
'purchase': '采购',
|
||||||
|
'result': '结果',
|
||||||
|
'correction': '更正',
|
||||||
|
'contract': '合同',
|
||||||
|
'pre_announcement': '预公示',
|
||||||
|
'single_source': '单一来源',
|
||||||
|
'electronic_market': '电子卖场',
|
||||||
|
'acceptance': '履约验收',
|
||||||
|
'engineering': '工程'
|
||||||
|
}.get(announcement.announcement_type.value, announcement.announcement_type.value)
|
||||||
|
response += f"{i}. [{type_name}] {title}\n 🕒 {time_str} | 🏷️ {announcement.purchase_name or '未知'}\n\n"
|
||||||
|
|
||||||
response += "发送关键词可搜索相关公告,点击菜单可查看更多功能。"
|
response += "💡 发送关键词可搜索相关公告,点击菜单可查看更多功能。"
|
||||||
else:
|
else:
|
||||||
response = """最新公告
|
response = """📋 全部公告
|
||||||
|
|
||||||
暂无最新公告数据。
|
暂无最新公告数据。
|
||||||
|
|
||||||
@@ -335,7 +469,7 @@ class WeChatMessageHandler:
|
|||||||
|
|
||||||
except Exception as db_error:
|
except Exception as db_error:
|
||||||
logger.warning(f"数据库查询失败: {str(db_error)}")
|
logger.warning(f"数据库查询失败: {str(db_error)}")
|
||||||
response = """最新公告
|
response = """📋 全部公告
|
||||||
|
|
||||||
暂时无法获取数据,请稍后重试。
|
暂时无法获取数据,请稍后重试。
|
||||||
|
|
||||||
@@ -344,7 +478,7 @@ class WeChatMessageHandler:
|
|||||||
return self._create_text_response(response, from_user)
|
return self._create_text_response(response, from_user)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"最新公告处理异常: {str(e)}")
|
logger.error(f"查看全部最新公告异常: {str(e)}")
|
||||||
return self._create_text_response("获取最新公告失败,请稍后重试", from_user)
|
return self._create_text_response("获取最新公告失败,请稍后重试", from_user)
|
||||||
|
|
||||||
def _handle_keyword_manage(self, from_user: str) -> Optional[str]:
|
def _handle_keyword_manage(self, from_user: str) -> Optional[str]:
|
||||||
@@ -407,8 +541,24 @@ class WeChatMessageHandler:
|
|||||||
}
|
}
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from ..storage.postgresql import test_database_connection
|
# 确保数据库已初始化
|
||||||
status_info["database"] = "正常" if test_database_connection() else "异常"
|
from ..core.database import init_database
|
||||||
|
try:
|
||||||
|
init_database() # 这个函数没有返回值
|
||||||
|
except Exception as init_error:
|
||||||
|
status_info["database"] = f"初始化失败: {str(init_error)[:20]}..."
|
||||||
|
else:
|
||||||
|
# 简单的数据库连接测试
|
||||||
|
from ..core.database import get_db_connection
|
||||||
|
with get_db_connection() as conn:
|
||||||
|
# 执行一个简单的查询来测试连接
|
||||||
|
with conn.cursor() as cursor:
|
||||||
|
cursor.execute("SELECT 1")
|
||||||
|
result = cursor.fetchone()
|
||||||
|
if result and result[0] == 1:
|
||||||
|
status_info["database"] = "正常"
|
||||||
|
else:
|
||||||
|
status_info["database"] = "异常"
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
status_info["database"] = f"连接失败: {str(e)[:20]}..."
|
status_info["database"] = f"连接失败: {str(e)[:20]}..."
|
||||||
|
|
||||||
@@ -438,16 +588,7 @@ class WeChatMessageHandler:
|
|||||||
- 微信服务: {status_info['wechat']}
|
- 微信服务: {status_info['wechat']}
|
||||||
- 调度器: {status_info['scheduler']}
|
- 调度器: {status_info['scheduler']}
|
||||||
|
|
||||||
系统信息:
|
"""
|
||||||
- 版本: v2.0.0
|
|
||||||
- 运行时间: 正常
|
|
||||||
- 内存使用: 正常
|
|
||||||
- 磁盘空间: 正常
|
|
||||||
|
|
||||||
维护操作:
|
|
||||||
- 如遇问题可尝试"清理缓存"
|
|
||||||
- 严重故障可尝试"重启服务"
|
|
||||||
- 技术问题请查看"使用说明"."""
|
|
||||||
|
|
||||||
return self._create_text_response(response, from_user)
|
return self._create_text_response(response, from_user)
|
||||||
|
|
||||||
@@ -467,10 +608,15 @@ class WeChatMessageHandler:
|
|||||||
}
|
}
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from ..storage.postgresql import clear_database_cache
|
# 目前没有专门的数据库缓存清理功能
|
||||||
cache_cleared["database_cache"] = clear_database_cache()
|
# 可以在这里添加数据库维护逻辑,比如清理过期数据
|
||||||
|
from ..storage.postgresql import cleanup_storage
|
||||||
|
cleaned_count = cleanup_storage(days=30) # 清理30天前的数据
|
||||||
|
cache_cleared["database_cache"] = cleaned_count >= 0 # 如果清理成功,返回True
|
||||||
|
logger.info(f"清理了 {cleaned_count} 条过期数据")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warning(f"数据库缓存清理失败: {str(e)}")
|
logger.warning(f"数据库缓存清理失败: {str(e)}")
|
||||||
|
cache_cleared["database_cache"] = False
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import os
|
import os
|
||||||
@@ -515,17 +661,7 @@ class WeChatMessageHandler:
|
|||||||
try:
|
try:
|
||||||
logger.info(f"用户 {from_user} 请求使用说明")
|
logger.info(f"用户 {from_user} 请求使用说明")
|
||||||
|
|
||||||
help_text = """广西政府采购网公告监控助手 - 使用说明
|
help_text = """菜单功能详解:
|
||||||
|
|
||||||
功能概述:
|
|
||||||
我是一个智能的政府采购公告监控助手,能够自动监控广西政府采购网的最新公告,并根据您的需求推送相关信息。
|
|
||||||
|
|
||||||
快速开始:
|
|
||||||
1. 点击"立即搜索"获取最新公告
|
|
||||||
2. 发送关键词进行智能搜索
|
|
||||||
3. 查看"今日统计"了解数据概况
|
|
||||||
|
|
||||||
菜单功能详解:
|
|
||||||
|
|
||||||
监控操作:
|
监控操作:
|
||||||
- 立即搜索: 手动触发公告搜索,获取最新数据
|
- 立即搜索: 手动触发公告搜索,获取最新数据
|
||||||
@@ -550,28 +686,12 @@ class WeChatMessageHandler:
|
|||||||
智能推送:
|
智能推送:
|
||||||
系统会自动监控匹配关键词的公告,并通过企业微信实时推送。
|
系统会自动监控匹配关键词的公告,并通过企业微信实时推送。
|
||||||
|
|
||||||
安全提醒:
|
|
||||||
- 管理员功能需要相应权限
|
|
||||||
- 请妥善保管企业微信应用信息
|
|
||||||
- 定期检查系统运行状态
|
|
||||||
|
|
||||||
使用技巧:
|
使用技巧:
|
||||||
- 关键词支持中英文混合
|
- 关键词支持中英文混合
|
||||||
- 可同时搜索多个关键词
|
- 可同时搜索多个关键词
|
||||||
- 公告按时间倒序排列
|
- 公告按时间倒序排列
|
||||||
- 点击公告可查看详情
|
- 点击公告可查看详情
|
||||||
|
"""
|
||||||
常见问题:
|
|
||||||
Q: 为什么收不到推送?
|
|
||||||
A: 检查关键词设置和系统状态
|
|
||||||
|
|
||||||
Q: 数据不准确怎么办?
|
|
||||||
A: 尝试"立即搜索"更新数据
|
|
||||||
|
|
||||||
Q: 搜索不到结果?
|
|
||||||
A: 检查关键词拼写,尝试更通用的关键词
|
|
||||||
|
|
||||||
如有其他问题,请点击"使用说明"获取帮助."""
|
|
||||||
|
|
||||||
return self._create_text_response(help_text, from_user)
|
return self._create_text_response(help_text, from_user)
|
||||||
|
|
||||||
@@ -761,7 +881,7 @@ A: 检查关键词拼写,尝试更通用的关键词
|
|||||||
return self._create_text_response("搜索失败,请稍后重试", from_user)
|
return self._create_text_response("搜索失败,请稍后重试", from_user)
|
||||||
|
|
||||||
def _handle_keyword_search(self, content: str, from_user: str) -> Optional[str]:
|
def _handle_keyword_search(self, content: str, from_user: str) -> Optional[str]:
|
||||||
"""处理关键词搜索"""
|
"""处理关键词搜索 - 显示所有匹配公告的markdown格式"""
|
||||||
try:
|
try:
|
||||||
parts = content.split()
|
parts = content.split()
|
||||||
keywords = parts[1:] if len(parts) > 1 else parts
|
keywords = parts[1:] if len(parts) > 1 else parts
|
||||||
@@ -777,35 +897,114 @@ A: 检查关键词拼写,尝试更通用的关键词
|
|||||||
result = app.run_crawl(keywords=keywords, manual_crawl=True)
|
result = app.run_crawl(keywords=keywords, manual_crawl=True)
|
||||||
|
|
||||||
if result.get("success"):
|
if result.get("success"):
|
||||||
filtered = result.get("filtered", 0)
|
filtered_announcements = result.get("filtered_announcements", [])
|
||||||
|
|
||||||
if filtered > 0:
|
if filtered_announcements:
|
||||||
response = f"""搜索完成!
|
# 生成markdown格式的结果
|
||||||
|
markdown_content = self._generate_keyword_search_markdown(keywords, filtered_announcements)
|
||||||
|
|
||||||
关键词: {' '.join(keywords)}
|
# 发送markdown消息
|
||||||
发现匹配公告: {filtered} 条
|
try:
|
||||||
|
from ..notification.wechat import get_notification_manager
|
||||||
|
manager = get_notification_manager()
|
||||||
|
if hasattr(manager.wechat, 'send_system_notification'):
|
||||||
|
notify_success = manager.wechat.send_system_notification(
|
||||||
|
title="🔍 搜索完成",
|
||||||
|
content=markdown_content,
|
||||||
|
message_type="markdown"
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
# 如果不支持markdown,发送文本消息
|
||||||
|
notify_success = manager.send_system_notification(
|
||||||
|
title="🔍 搜索完成",
|
||||||
|
content=f"发现 {len(filtered_announcements)} 条匹配公告"
|
||||||
|
)
|
||||||
|
|
||||||
|
if notify_success:
|
||||||
|
# 返回简单的文本确认
|
||||||
|
return self._create_text_response("搜索完成!已发送详细结果到聊天窗口。", from_user)
|
||||||
|
else:
|
||||||
|
# 如果markdown发送失败,返回文本格式
|
||||||
|
return self._create_text_response(f"搜索完成!发现 {len(filtered_announcements)} 条匹配公告,已推送通知。", from_user)
|
||||||
|
|
||||||
|
except Exception as notify_error:
|
||||||
|
logger.warning(f"发送markdown通知失败: {str(notify_error)}")
|
||||||
|
# 返回文本格式的结果
|
||||||
|
return self._create_text_response(f"搜索完成!发现 {len(filtered_announcements)} 条匹配公告。", from_user)
|
||||||
|
|
||||||
如有匹配的公告,我会及时推送通知。"""
|
|
||||||
else:
|
else:
|
||||||
response = f"""搜索完成!
|
response = f"""🔍 搜索完成
|
||||||
|
|
||||||
关键词: {' '.join(keywords)}
|
关键词: {' '.join(keywords)}
|
||||||
|
总公告数: 0
|
||||||
|
|
||||||
未发现匹配的公告。
|
未发现匹配的公告。
|
||||||
|
|
||||||
建议:
|
💡 建议:
|
||||||
- 尝试更通用的关键词
|
• 尝试更通用的关键词
|
||||||
- 检查关键词拼写
|
• 检查关键词拼写
|
||||||
- 等待系统更新最新数据"""
|
• 等待系统更新最新数据"""
|
||||||
|
return self._create_text_response(response, from_user)
|
||||||
else:
|
else:
|
||||||
error = result.get("error", "未知错误")
|
error = result.get("error", "未知错误")
|
||||||
response = f"搜索失败: {error}"
|
response = f"❌ 搜索失败: {error}"
|
||||||
|
return self._create_text_response(response, from_user)
|
||||||
return self._create_text_response(response, from_user)
|
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"关键词搜索处理异常: {str(e)}")
|
logger.error(f"关键词搜索处理异常: {str(e)}")
|
||||||
return self._create_text_response("搜索失败,请稍后重试", from_user)
|
return self._create_text_response("搜索失败,请稍后重试", from_user)
|
||||||
|
|
||||||
|
def _generate_keyword_search_markdown(self, keywords: List[str], announcements: List) -> str:
|
||||||
|
"""生成关键词搜索结果的markdown格式"""
|
||||||
|
import datetime
|
||||||
|
|
||||||
|
# 按公告类型分组
|
||||||
|
type_groups = {}
|
||||||
|
for ann in announcements:
|
||||||
|
ann_type = ann.announcement_type.value
|
||||||
|
if ann_type not in type_groups:
|
||||||
|
type_groups[ann_type] = []
|
||||||
|
type_groups[ann_type].append(ann)
|
||||||
|
|
||||||
|
# 类型名称映射
|
||||||
|
type_name_map = {
|
||||||
|
'purchase': '采购公告',
|
||||||
|
'result': '结果公告',
|
||||||
|
'correction': '更正公告',
|
||||||
|
'contract': '合同公告',
|
||||||
|
'pre_announcement': '预公示',
|
||||||
|
'single_source': '单一来源',
|
||||||
|
'electronic_market': '电子卖场公示',
|
||||||
|
'acceptance': '履约验收',
|
||||||
|
'engineering': '工程公告',
|
||||||
|
'intention': '采购意向'
|
||||||
|
}
|
||||||
|
|
||||||
|
# 生成markdown内容
|
||||||
|
lines = [
|
||||||
|
f"关键词: `{' '.join(keywords)}` - 总公告数: `{len(announcements)}`\n\n",
|
||||||
|
f"更新时间: {datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n\n"
|
||||||
|
]
|
||||||
|
|
||||||
|
# 按类型输出
|
||||||
|
for ann_type, ann_list in type_groups.items():
|
||||||
|
type_name = type_name_map.get(ann_type, ann_type)
|
||||||
|
lines.append(f"**{type_name} - 共 {len(ann_list)} 条公告**\n\n")
|
||||||
|
|
||||||
|
for i, ann in enumerate(ann_list, 1):
|
||||||
|
title = ann.title
|
||||||
|
if len(title) > 40:
|
||||||
|
title = title[:40] + "..."
|
||||||
|
|
||||||
|
url = ann.content_url or "#"
|
||||||
|
date_str = ann.publish_date.strftime('%Y-%m-%d') if ann.publish_date else "未知"
|
||||||
|
purchaser = ann.purchase_name or "未知"
|
||||||
|
|
||||||
|
lines.append(f"{i}. [{title}]({url})\n\n")
|
||||||
|
lines.append(f" {date_str} | {purchaser} | {type_name}\n\n")
|
||||||
|
|
||||||
|
return "".join(lines)
|
||||||
|
|
||||||
def handle_other_message(self, msg_type: str, from_user: str) -> Optional[str]:
|
def handle_other_message(self, msg_type: str, from_user: str) -> Optional[str]:
|
||||||
"""处理其他类型的消息"""
|
"""处理其他类型的消息"""
|
||||||
try:
|
try:
|
||||||
@@ -822,6 +1021,28 @@ A: 检查关键词拼写,尝试更通用的关键词
|
|||||||
logger.error(f"其他消息处理异常: {str(e)}")
|
logger.error(f"其他消息处理异常: {str(e)}")
|
||||||
return self._create_text_response("处理失败,请稍后重试", from_user)
|
return self._create_text_response("处理失败,请稍后重试", from_user)
|
||||||
|
|
||||||
|
def _is_duplicate_request(self, user_id: str, content: str) -> bool:
|
||||||
|
"""检查是否为重复请求"""
|
||||||
|
import time
|
||||||
|
|
||||||
|
cache_key = f"{user_id}:{content}"
|
||||||
|
current_time = time.time()
|
||||||
|
|
||||||
|
# 清理过期的缓存
|
||||||
|
expired_keys = [k for k, v in self._request_cache.items() if current_time - v > self._cache_timeout]
|
||||||
|
for key in expired_keys:
|
||||||
|
del self._request_cache[key]
|
||||||
|
|
||||||
|
# 检查是否重复
|
||||||
|
if cache_key in self._request_cache:
|
||||||
|
last_time = self._request_cache[cache_key]
|
||||||
|
if current_time - last_time < self._cache_timeout:
|
||||||
|
return True
|
||||||
|
|
||||||
|
# 更新缓存
|
||||||
|
self._request_cache[cache_key] = current_time
|
||||||
|
return False
|
||||||
|
|
||||||
def _create_text_response(self, content: str, to_user: str) -> str:
|
def _create_text_response(self, content: str, to_user: str) -> str:
|
||||||
"""创建文本消息响应"""
|
"""创建文本消息响应"""
|
||||||
timestamp = str(int(time.time()))
|
timestamp = str(int(time.time()))
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
|||||||
📋 关键词搜索: `未知` - 总公告数: `0`
|
📋 关键词搜索: `未知` - 总公告数: `0`
|
||||||
|
|
||||||
**更新时间: 2026-01-08 23:41:28**
|
**更新时间: 2026-01-09 09:14:30**
|
||||||
|
|
||||||
|
|
||||||
## 无匹配公告
|
## 无匹配公告
|
||||||
|
|||||||
@@ -0,0 +1,65 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
测试最新公告两步流程功能
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
|
||||||
|
# 添加项目路径
|
||||||
|
sys.path.insert(0, os.path.dirname(__file__))
|
||||||
|
|
||||||
|
try:
|
||||||
|
from gx_gp_monitor.wechat.message_handler import WeChatMessageHandler
|
||||||
|
from gx_gp_monitor.core.config_manager import load_config
|
||||||
|
|
||||||
|
def demo_latest_news_flow():
|
||||||
|
"""演示最新公告功能流程"""
|
||||||
|
load_config()
|
||||||
|
handler = WeChatMessageHandler()
|
||||||
|
|
||||||
|
print("🚀 最新公告功能演示")
|
||||||
|
print("=" * 50)
|
||||||
|
|
||||||
|
# 步骤1: 点击"最新公告"菜单
|
||||||
|
print("📱 步骤1: 用户点击'最新公告'菜单")
|
||||||
|
step1_result = handler._handle_latest_news('demo_user')
|
||||||
|
print("✅ 系统响应: 显示公告来源选择菜单")
|
||||||
|
print()
|
||||||
|
|
||||||
|
# 步骤2: 用户选择采购公告
|
||||||
|
print("📱 步骤2: 用户发送'1'选择采购公告")
|
||||||
|
step2_result = handler._handle_latest_news_by_source('1', 'demo_user')
|
||||||
|
print("✅ 系统响应: 显示采购公告最新10条")
|
||||||
|
print()
|
||||||
|
|
||||||
|
# 步骤3: 用户选择查看全部
|
||||||
|
print("📱 步骤3: 用户发送'全部'查看所有公告")
|
||||||
|
step3_result = handler._handle_latest_news_by_source('全部', 'demo_user')
|
||||||
|
print("✅ 系统响应: 显示全部来源最新10条公告")
|
||||||
|
print()
|
||||||
|
|
||||||
|
print("🎯 功能特点:")
|
||||||
|
print("• 📋 两步交互: 先选择来源,再显示内容")
|
||||||
|
print("• 🎛️ 9种来源: 覆盖所有公告类型")
|
||||||
|
print("• 📊 智能排序: 按时间倒序显示")
|
||||||
|
print("• 💡 用户友好: 清晰的数字选择界面")
|
||||||
|
print()
|
||||||
|
|
||||||
|
print("📝 使用方法:")
|
||||||
|
print("1. 点击企业微信菜单中的'最新公告'")
|
||||||
|
print("2. 系统显示9种公告来源选项")
|
||||||
|
print("3. 发送对应数字(1-9)或'全部'查看")
|
||||||
|
print("4. 系统显示该来源的最新10条公告")
|
||||||
|
|
||||||
|
print("\n✅ 最新公告功能升级完成!")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
demo_latest_news_flow()
|
||||||
|
|
||||||
|
except ImportError as e:
|
||||||
|
print(f"❌ 导入失败: {e}", file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ 演示失败: {e}", file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
+1
-1
@@ -1 +1 @@
|
|||||||
1616302
|
1782404
|
||||||
|
|||||||
Reference in New Issue
Block a user