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/app/chatflow" "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 { writeSafeError(w, r, http.StatusMethodNotAllowed, "Method Not Allowed") return } user, ok := s.requireAuthenticatedUser(w, r) if !ok { return } sessionID := strings.TrimSpace(r.URL.Query().Get("session_id")) if sessionID == "" { writeSafeError(w, r, http.StatusBadRequest, "missing required query param 'session_id'") return } if s.chatLog == nil { writeSafeError(w, r, http.StatusServiceUnavailable, "context manager not initialized") return } msgs, err := s.chatLog.Export(r.Context(), s.chatPrincipal(user, chatflow.ActionExport), chatflow.ExportQuery{ SessionID: sessionID, 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")), }) if err != nil { s.writeChatLogError(w, err) return } filtered := make([]ctxmgr.ChatMessageRecord, 0, len(msgs)) for _, m := range msgs { 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) }