| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270 |
- import { Injectable, OnDestroy, Injector } from '@angular/core';
- import { HttpClient } from '@angular/common/http';
- import { BehaviorSubject, Observable, of, Subscription } from 'rxjs';
- import { map, tap } from 'rxjs/operators';
- import {
- Session,
- SessionCreateRequest,
- SessionCreateApiResponse,
- SessionListResponse,
- ProjectCreateRequest,
- ProjectCreateApiResponse
- } from '../models/session.model';
- import { AuthService } from './auth.service';
- import { EventService } from './event.service';
- import { SessionUpdatedEvent } from '../models/event.model';
-
- @Injectable({
- providedIn: 'root'
- })
- export class SessionService implements OnDestroy {
- private activeSession = new BehaviorSubject<Session | null>(null);
- activeSession$ = this.activeSession.asObservable();
-
- private sessions: Session[] = [];
- private sessionsSubject = new BehaviorSubject<Session[]>([]);
- sessions$ = this.sessionsSubject.asObservable();
-
- private eventSubscription: Subscription = new Subscription();
-
- private injector: Injector;
- private _eventService: EventService | null = null;
-
- constructor(
- private http: HttpClient,
- private authService: AuthService,
- injector: Injector
- ) {
- this.injector = injector;
- // 延迟设置事件订阅,在EventService可用时进行
- setTimeout(() => this.setupEventSubscriptions(), 0);
- }
-
- private get eventService(): EventService | null {
- if (!this._eventService) {
- try {
- this._eventService = this.injector.get(EventService, null);
- } catch (error) {
- console.warn('无法获取EventService:', error);
- return null;
- }
- }
- return this._eventService;
- }
-
- // 获取会话列表(需要认证)- 使用新API端点
- getSessions(): Observable<Session[]> {
- // 检查用户是否已认证
- if (!this.authService.isAuthenticated()) {
- console.warn('用户未认证,无法获取会话列表,返回空数组');
- return of([]);
- }
-
- return this.http.get<any>('/api/sessions').pipe(
- map(response => {
- console.log('🔍 [SessionService] 获取会话列表响应:', response);
-
- if (response.success && response.data) {
- // 处理嵌套的 sessions 字段(后端返回 { data: { sessions: [], ...pagination } })
- let sessionsArray: any[] = [];
-
- if (response.data.sessions && Array.isArray(response.data.sessions)) {
- // 新格式:response.data.sessions 是数组
- sessionsArray = response.data.sessions;
- console.log('🔍 [SessionService] 从嵌套 sessions 字段获取数据,数量:', sessionsArray.length);
- } else if (Array.isArray(response.data)) {
- // 兼容旧格式:response.data 直接是数组
- sessionsArray = response.data;
- console.log('🔍 [SessionService] 从 data 字段直接获取数组,数量:', sessionsArray.length);
- } else {
- console.warn('🔍 [SessionService] 无法识别响应数据格式,使用空数组');
- sessionsArray = [];
- }
-
- // 确保每个会话都有 project_id 字段(向后兼容)
- const sessions = sessionsArray.map(session => ({
- ...session,
- project_id: session.project_id || session.id // 如果没有 project_id,使用 id 作为默认
- }));
-
- this.sessions = sessions;
- this.sessionsSubject.next(this.sessions);
- console.log('🔍 [SessionService] 会话列表处理完成,数量:', sessions.length);
- return sessions;
- } else {
- console.error('🔍 [SessionService] 获取会话列表失败:', response.message);
- throw new Error(response.message || '获取会话列表失败');
- }
- }),
- tap(sessions => {
- // 如果没有活动会话,设置第一个为活动会话
- if (sessions.length > 0 && !this.activeSession.value) {
- this.setActiveSession(sessions[0]);
- }
- })
- );
- }
-
- // 创建新会话(向后兼容,建议使用createProject)
- createSession(title: string, menuItemId: string): Observable<Session> {
- console.warn('createSession已过时,请使用createProject方法');
- // 尝试使用默认智能体创建项目
- const defaultAgent = 'report'; // 默认智能体
- return this.createProject({
- title,
- agent_name: defaultAgent,
- description: `由旧会话创建,菜单项: ${menuItemId}`
- });
- }
-
- // 创建新项目
- createProject(request: ProjectCreateRequest): Observable<Session> {
- // 检查用户是否已认证
- if (!this.authService.isAuthenticated()) {
- console.error('用户未认证,无法创建项目');
- throw new Error('用户未认证,请先登录');
- }
-
- // 生成项目ID(如果未提供)
- const projectRequest = {
- ...request,
- project_id: request.project_id || `proj_${crypto.randomUUID()}`
- };
-
- return this.http.post<ProjectCreateApiResponse>('/api/session/create', projectRequest).pipe(
- map(response => {
- console.log('🔍 [SessionService] 创建项目响应:', response);
- if (response.success && response.data) {
- const sessionData = response.data;
- // 确保有project_id字段
- const newSession: Session = {
- ...sessionData,
- project_id: sessionData.project_id || projectRequest.project_id
- };
-
- this.sessions.unshift(newSession);
- this.sessionsSubject.next([...this.sessions]);
- this.setActiveSession(newSession);
-
- return newSession;
- } else {
- throw new Error(response.message || '创建项目失败');
- }
- })
- );
- }
-
- // 设置活动会话
- setActiveSession(session: Session | null) {
- this.activeSession.next(session);
- }
-
- // 获取当前活动会话
- getActiveSession(): Session | null {
- return this.activeSession.value;
- }
-
- // 根据ID获取会话
- getSessionById(id: string): Session | undefined {
- return this.sessions.find(session => session.id === id);
- }
-
- // 加载会话列表(公共方法,供组件调用)
- loadSessions(): void {
- if (!this.authService.isAuthenticated()) {
- console.warn('用户未认证,跳过会话列表加载');
- this.sessionsSubject.next([]);
- return;
- }
-
- console.log('🔍 [SessionService] 开始加载会话列表...');
- this.getSessions().subscribe({
- next: (sessions) => {
- console.log('🔍 [SessionService] 会话列表加载成功,数量:', sessions.length);
- },
- error: (error) => {
- console.error('🔍 [SessionService] 加载会话列表失败:', error);
- // 如果API不可用,使用空列表
- this.sessionsSubject.next([]);
- }
- });
- }
-
- // 删除会话(如果后端支持)
- deleteSession(sessionId: string): Observable<boolean> {
- // 注意:后端可能没有删除API,这里只是示例
- return of(true).pipe(
- tap(() => {
- this.sessions = this.sessions.filter(s => s.id !== sessionId);
- this.sessionsSubject.next([...this.sessions]);
-
- // 如果删除的是活动会话,清空活动会话
- if (this.activeSession.value?.id === sessionId) {
- this.setActiveSession(null);
- }
- })
- );
- }
-
- // 设置事件订阅
- private setupEventSubscriptions() {
- const eventService = this.eventService;
- if (!eventService) {
- console.warn('EventService不可用,跳过事件订阅设置');
- return;
- }
-
- // 订阅会话更新事件
- this.eventSubscription.add(
- eventService.sessionUpdated$.subscribe(event => {
- this.handleSessionUpdated(event);
- })
- );
- }
-
- // 处理会话更新事件
- private handleSessionUpdated(event: SessionUpdatedEvent) {
- const sessionInfo = event.properties.info;
- console.log('SessionService: 处理会话更新事件', sessionInfo.id, sessionInfo.title);
-
- // 查找现有会话
- const existingSessionIndex = this.sessions.findIndex(s => s.id === sessionInfo.id);
-
- if (existingSessionIndex !== -1) {
- // 更新现有会话
- const updatedSession: Session = {
- ...this.sessions[existingSessionIndex],
- title: sessionInfo.title,
- agent_name: sessionInfo.agent_name || this.sessions[existingSessionIndex].agent_name,
- description: sessionInfo.description || this.sessions[existingSessionIndex].description,
- status: sessionInfo.status || this.sessions[existingSessionIndex].status,
- // 保留其他字段
- };
- this.sessions[existingSessionIndex] = updatedSession;
- console.log('SessionService: 更新现有会话', updatedSession.title);
- } else {
- // 添加新会话到列表开头
- const newSession: Session = {
- id: sessionInfo.id,
- project_id: sessionInfo.project_id || sessionInfo.projectID || sessionInfo.id,
- title: sessionInfo.title,
- agent_name: sessionInfo.agent_name || 'report',
- description: sessionInfo.description || '',
- status: sessionInfo.status || 'requirement_document',
- // port和baseURL可能在后端创建会话时提供,这里使用默认值
- // 实际使用中,可以从事件或后续API调用中获取
- port: 8020, // 默认端口,可根据需要调整
- baseURL: `http://localhost:8020`, // 默认baseURL
- };
- this.sessions.unshift(newSession);
- console.log('SessionService: 添加新会话', newSession.title);
- }
-
- // 通知订阅者
- this.sessionsSubject.next([...this.sessions]);
- }
-
- ngOnDestroy() {
- this.eventSubscription.unsubscribe();
- }
- }
|