This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
import { DetailsData, WeeklyData } from "~/utils/types"
|
||||
import { getAIAnalysis, getAIDetailData, getAIWeeklyData } from "../api"
|
||||
import { consumeJSONEventStream } from "~/utils/stream"
|
||||
import { getAIDetailData, getAIWeeklyData } from "../api"
|
||||
import { getCSRFToken } from "~/utils/functions"
|
||||
|
||||
export const useAIStore = defineStore("ai", () => {
|
||||
const duration = ref("months:6")
|
||||
@@ -22,6 +24,8 @@ export const useAIStore = defineStore("ai", () => {
|
||||
ai: false,
|
||||
})
|
||||
|
||||
const mdContent = ref("")
|
||||
|
||||
const theFirstPerson = computed(() => {
|
||||
return !!username.value ? username.value : "你"
|
||||
})
|
||||
@@ -55,13 +59,85 @@ export const useAIStore = defineStore("ai", () => {
|
||||
loading.weekly = false
|
||||
}
|
||||
|
||||
let aiController: AbortController | null = null
|
||||
|
||||
async function fetchAIAnalysis() {
|
||||
if (aiController) {
|
||||
aiController.abort()
|
||||
}
|
||||
const controller = new AbortController()
|
||||
aiController = controller
|
||||
|
||||
loading.ai = true
|
||||
const res = await getAIAnalysis(detailsData, weeklyData.value)
|
||||
console.log(res.data)
|
||||
loading.ai = false
|
||||
mdContent.value = ""
|
||||
|
||||
const headers: Record<string, string> = {
|
||||
"Content-Type": "application/json",
|
||||
}
|
||||
const csrfToken = getCSRFToken()
|
||||
if (csrfToken) {
|
||||
headers["X-CSRFToken"] = csrfToken
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch("/api/ai/analysis", {
|
||||
method: "POST",
|
||||
headers,
|
||||
body: JSON.stringify({
|
||||
details: detailsData,
|
||||
weekly: weeklyData.value,
|
||||
}),
|
||||
signal: controller.signal,
|
||||
})
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error("AI 分析生成失败")
|
||||
}
|
||||
|
||||
let hasStarted = false
|
||||
|
||||
await consumeJSONEventStream(response, {
|
||||
signal: controller.signal,
|
||||
onEvent(event) {
|
||||
if (event === "end" && !hasStarted) {
|
||||
loading.ai = false
|
||||
}
|
||||
},
|
||||
onMessage(payload) {
|
||||
const parsed = payload as {
|
||||
type?: string
|
||||
content?: string
|
||||
message?: string
|
||||
}
|
||||
|
||||
if (parsed.type === "delta" && parsed.content) {
|
||||
if (!hasStarted) {
|
||||
hasStarted = true
|
||||
loading.ai = false
|
||||
}
|
||||
mdContent.value += parsed.content
|
||||
} else if (parsed.type === "error") {
|
||||
throw new Error(parsed.message || "AI 服务异常")
|
||||
} else if (parsed.type === "done" && !hasStarted) {
|
||||
loading.ai = false
|
||||
}
|
||||
},
|
||||
})
|
||||
} catch (error: any) {
|
||||
if (controller.signal.aborted) {
|
||||
return
|
||||
}
|
||||
console.error("生成 AI 分析失败", error)
|
||||
const message = error?.message || "生成失败,请稍后再试"
|
||||
mdContent.value = `生成失败:${message}`
|
||||
} finally {
|
||||
if (aiController === controller) {
|
||||
aiController = null
|
||||
loading.ai = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return {
|
||||
fetchWeeklyData,
|
||||
fetchDetailsData,
|
||||
@@ -72,5 +148,6 @@ export const useAIStore = defineStore("ai", () => {
|
||||
username,
|
||||
theFirstPerson,
|
||||
loading,
|
||||
mdContent,
|
||||
}
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user