package server // chat_export_api.go — P3 聊天记录导出查询 API // // GET /api/v1/chat/export/messages?session_id=...&date_from=...&date_to=...&category=... // // 返回按条件过滤后的消息列表,支持客户端导出为 docx/xlsx 等格式。 import ( "net/http" "strings" "chat-agent-system/internal/ctxmgr" "chat-agent-system/internal/replyexport" ) func (s *Server) handleChatExportMessages(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodGet { http.Error(w, "Method Not Allowed", http.StatusMethodNotAllowed) return } user, ok := s.requireAuthenticatedUser(w, r) if !ok { return } sessionID := strings.TrimSpace(r.URL.Query().Get("session_id")) if sessionID == "" { http.Error(w, "missing required query param 'session_id'", http.StatusBadRequest) return } if s.svc == nil || s.svc.ContextManager() == nil { http.Error(w, "context manager not initialized", http.StatusServiceUnavailable) return } if !s.assertSessionOwnedByUser(w, r, sessionID, user.ID) { return } dateFrom := strings.TrimSpace(r.URL.Query().Get("date_from")) dateTo := strings.TrimSpace(r.URL.Query().Get("date_to")) category := strings.TrimSpace(r.URL.Query().Get("category")) // 查询该会话的历史消息(上限 5000 条) msgs, err := s.svc.ContextManager().GetChatHistory(r.Context(), sessionID, 5000, 0) if err != nil { http.Error(w, "query chat history failed: "+err.Error(), http.StatusInternalServerError) return } // 过滤 + 导出策略脱敏 filtered := make([]ctxmgr.ChatMessageRecord, 0, len(msgs)) for _, m := range msgs { dk := m.DayKey if dk == "" && !m.CreatedAt.IsZero() { dk = m.CreatedAt.Format("2006-01-02") } if dateFrom != "" && dk < dateFrom { continue } if dateTo != "" && dk > dateTo { continue } if category != "" && category != "all" && m.Category != category { continue } hasCard := false if m.Metadata != nil { if _, exists := m.Metadata["interactive_card"]; exists { hasCard = true } } _, cap := replyexport.EvaluatePolicy(replyexport.PolicyOptions{ Role: m.Role, Status: "completed", Content: m.Content, HasInteractiveCard: hasCard, Revision: m.ContentRevision, }) if cap.Policy == replyexport.PolicyNone { continue } filtered = append(filtered, m) } writeJSONResponse(w, http.StatusOK, filtered) }