diff --git a/backend/app/api/ai_analysis.py b/backend/app/api/ai_analysis.py index 945d7615..df4b077c 100644 --- a/backend/app/api/ai_analysis.py +++ b/backend/app/api/ai_analysis.py @@ -8,7 +8,7 @@ from app.deps import get_entity_id from app.auth_middleware import require_auth, require_role from app.models import KPIDefinition, KPIValue, KPIAlert, StrategicMap, User, ActionPlan, BudgetPlan, AISuggestion from app.utils.cache import get as cache_get, set as cache_set -import json, hashlib, httpx, os, urllib.request +import json, hashlib, httpx, os, urllib.request, urllib.parse from datetime import datetime, date router = APIRouter(prefix="/api/cma/ai", tags=["AI分析"], dependencies=[Depends(require_role("ceo", "finance", "business", "it"))], @@ -188,9 +188,11 @@ _TYPE_LABELS = {"kpi_target": "KPI目标", "budget_adjust": "预算调整", "act def _push_decision_suggestion(s: AISuggestion) -> bool: - """决策类建议推送到企微(8800 relay,与 lead.py 同款已验证) + """决策类建议推送到企微(8800 relay 公司群中继) 仅 decision 类;预警类不进推送流。失败不影响主流程(try/except)。 + 8800/send 只接受 form-encoded 参数(msg/source/msgtype/touser), + 勿用 JSON body(relay 会返回 msg is required,lead.py 的 JSON 写法是错的)。 """ if getattr(s, "category", "decision") != "decision": return False @@ -203,17 +205,21 @@ def _push_decision_suggestion(s: AISuggestion) -> bool: f"---\n" f"⏰ {datetime.now().strftime('%Y-%m-%d %H:%M')}" ) - msg = {"msgtype": "markdown", "markdown": {"content": content}} try: - data = json.dumps(msg, ensure_ascii=False).encode("utf-8") + data = urllib.parse.urlencode({ + "msg": content, + "source": "管理会计OS", + "msgtype": "markdown", + }).encode("utf-8") req = urllib.request.Request( "http://127.0.0.1:8800/send", data=data, - headers={"Content-Type": "application/json"}, + headers={"Content-Type": "application/x-www-form-urlencoded"}, method="POST", ) - urllib.request.urlopen(req, timeout=5) - return True + with urllib.request.urlopen(req, timeout=5) as resp: + body = resp.read().decode("utf-8") + return '"ok": true' in body or '"ok":true' in body except Exception: return False