Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 | 1x 1x | import { defineStore } from 'pinia'
import request from '@/utils/request'
import { message } from 'ant-design-vue'
export interface Message {
id: number
forum_id: number
persona_id: number
moderator_id?: number | null
speaker_name: string
content: string
timestamp: string
}
export interface Moderator {
id: number
name: string
title: string
bio: string
system_prompt?: string
greeting_template?: string
closing_template?: string
summary_template?: string
creator_id: number
created_at: string
}
export interface Forum {
id: number
topic: string
creator_id: number
moderator_id?: number | null
moderator?: Moderator | null
status: string
start_time: string
summary_history: string[]
participants?: any[]
duration_minutes?: number
}
export interface SystemLog {
timestamp: string
level: 'info' | 'warning' | 'error' | 'thought' | 'speech'
content: string
source?: string
}
export const useForumStore = defineStore('forum', {
state: () => ({
forums: [] as Forum[],
currentForum: null as Forum | null,
messages: [] as Message[],
moderators: [] as Moderator[],
systemLogs: [] as SystemLog[],
loading: false,
thinking: false
}),
actions: {
async fetchSystemLogs(forumId: number) {
try {
const res = await request.get(`/forums/${forumId}/logs`)
this.systemLogs = res.data
} catch (error) {
console.error('Failed to fetch system logs:', error)
}
},
addSystemLog(log: SystemLog) {
this.systemLogs.push(log)
},
updateStreamingMessage(chunk: {
speaker_name: string,
content: string,
persona_id: number | null,
moderator_id?: number | null,
stream_id?: string,
timestamp: string
}) {
// Robust logic: Use stream_id if available to find the message
// If stream_id is missing, fallback to last message match (legacy behavior)
let targetMsg: Message | undefined
if (chunk.stream_id) {
targetMsg = this.messages.find(m => (m as any).stream_id === chunk.stream_id)
} else {
// Fallback: Check last message
const lastMsg = this.messages[this.messages.length - 1]
if (lastMsg && lastMsg.speaker_name === chunk.speaker_name && (lastMsg as any).isStreaming) {
targetMsg = lastMsg
}
}
if (targetMsg) {
targetMsg.content += chunk.content
} else {
// Start new streaming message
const newMsg: Message = {
id: Date.now(), // Temp ID, will be replaced by final message
forum_id: this.currentForum?.id || 0,
persona_id: chunk.persona_id || 0,
moderator_id: chunk.moderator_id || null,
speaker_name: chunk.speaker_name,
content: chunk.content,
timestamp: chunk.timestamp,
}
;(newMsg as any).isStreaming = true
;(newMsg as any).stream_id = chunk.stream_id // Store stream_id for future chunks
this.messages.push(newMsg)
}
},
addMessage(msg: Message & { stream_id?: string }) {
// When the full message arrives (type: 'new_message'), replace the streaming one
// Match by stream_id if available, otherwise fallback
let streamingMsgIndex = -1
if (msg.stream_id) {
streamingMsgIndex = this.messages.findIndex(m => (m as any).stream_id === msg.stream_id)
}
// Fallback match if stream_id not found or not provided
if (streamingMsgIndex === -1) {
streamingMsgIndex = this.messages.findIndex(m => m.speaker_name === msg.speaker_name && (m as any).isStreaming)
}
if (streamingMsgIndex !== -1) {
// Replace streaming message with the final one
this.messages.splice(streamingMsgIndex, 1, msg)
} else {
// Check if message already exists by ID to prevent duplicates
const exists = this.messages.find(m => m.id === msg.id)
if (!exists) {
this.messages.push(msg)
}
}
// Auto-scroll logic could be triggered here or in component watcher
},
async fetchForums() {
this.loading = true
try {
const res = await request.get('/forums/')
this.forums = res.data
} catch (error) {
console.error('Failed to fetch forums:', error)
this.forums = []
} finally {
this.loading = false
}
},
async fetchForum(id: number) {
this.loading = true
this.currentForum = null
try {
const res = await request.get(`/forums/${id}`)
this.currentForum = res.data
await this.fetchMessages(id)
} catch (error) {
console.error(`Failed to fetch forum ${id}:`, error)
} finally {
this.loading = false
}
},
async fetchMessages(forumId: number) {
try {
const res = await request.get(`/forums/${forumId}/messages`)
this.messages = res.data
} catch (error) {
console.error(`Failed to fetch messages for forum ${forumId}:`, error)
this.messages = []
}
},
async fetchModerators() {
try {
const res = await request.get('/moderators/')
this.moderators = res.data
} catch (error) {
console.error('Failed to fetch moderators:', error)
this.moderators = []
}
},
async createForum(topic: string, participantIds: number[], duration: number, moderatorId?: number) {
this.loading = true
try {
const res = await request.post('/forums/', {
topic,
participant_ids: participantIds,
moderator_id: moderatorId,
duration_minutes: duration
})
message.success('论坛创建成功')
await this.fetchForums()
return res.data
} catch (error) {
console.error('Failed to create forum:', error)
throw error
} finally {
this.loading = false
}
},
async startForum(id: number) {
try {
await request.post(`/forums/${id}/start`)
message.success('论坛已开始')
if (this.currentForum && this.currentForum.id === id) {
this.currentForum.status = 'running'
}
} catch (error) {
console.error('Failed to start forum:', error)
message.error('启动失败')
}
},
async deleteForum(id: number) {
try {
await request.delete(`/forums/${id}`)
message.success('论坛已删除')
if (this.currentForum && this.currentForum.id === id) {
this.currentForum = null
}
this.forums = this.forums.filter(f => f.id !== id)
} catch (error) {
console.error('Failed to delete forum:', error)
message.error('删除失败')
}
},
leaveForum() {
this.messages = []
this.systemLogs = []
this.currentForum = null
this.thinking = false
this.loading = false
}
}
})
|