From 1e160d192bd2fc3ea5ee44830844e67efd193285 Mon Sep 17 00:00:00 2001
From: yuetsh <517252939@qq.com>
Date: Thu, 7 May 2026 09:51:54 -0600
Subject: [PATCH] add prompt assistant
---
src/components/ai/GuidancePanel.vue | 244 ++++++++++++++++++++++++++++
src/components/ai/PromptPanel.vue | 25 +++
src/pages/Submissions.vue | 17 +-
src/store/guidance.ts | 111 +++++++++++++
src/store/prompt.ts | 4 +
5 files changed, 385 insertions(+), 16 deletions(-)
create mode 100644 src/components/ai/GuidancePanel.vue
create mode 100644 src/store/guidance.ts
diff --git a/src/components/ai/GuidancePanel.vue b/src/components/ai/GuidancePanel.vue
new file mode 100644
index 0000000..e92ddb3
--- /dev/null
+++ b/src/components/ai/GuidancePanel.vue
@@ -0,0 +1,244 @@
+
+
+
+
+
+
{{ msg.role === "user" ? "你" : "AI" }}
+
+
+
+
+
+
+
+
+ 提示词已优化,可以生成代码了!
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/ai/PromptPanel.vue b/src/components/ai/PromptPanel.vue
index bc038ed..82b9878 100644
--- a/src/components/ai/PromptPanel.vue
+++ b/src/components/ai/PromptPanel.vue
@@ -44,6 +44,7 @@
AI 正在思考中…
+
+
+
+
+
+
-
-
- goHome(
- $router,
- taskTab,
- taskTab === TASK_TYPE.Challenge ? challengeDisplay : step,
- )
- "
- >
- 首页
-
-
+
-
([])
+export const connected = ref(false)
+export const streaming = ref(false)
+export const streamingContent = ref("")
+export const isReady = ref(false)
+export const isOpen = ref(false)
+export const initialPrompt = ref("")
+
+let ws: WebSocket | null = null
+let _taskId = 0
+
+function setupHandlers(socket: WebSocket) {
+ socket.onopen = () => {
+ connected.value = true
+ if (initialPrompt.value) {
+ sendToSocket(initialPrompt.value)
+ }
+ }
+
+ socket.onmessage = (event) => {
+ const data = JSON.parse(event.data)
+ if (data.type === "init") {
+ streaming.value = false
+ streamingContent.value = ""
+ } else if (data.type === "stream") {
+ streaming.value = true
+ streamingContent.value += data.content
+ } else if (data.type === "complete") {
+ streaming.value = false
+ const content = streamingContent.value.replace(/^\[READY\]\n?/, "")
+ messages.value.push({ role: "assistant", content, id: data.message_id })
+ streamingContent.value = ""
+ if (data.is_ready) isReady.value = true
+ } else if (data.type === "error") {
+ streaming.value = false
+ streamingContent.value = ""
+ messages.value.push({ role: "assistant", content: data.content })
+ }
+ }
+
+ socket.onclose = () => {
+ connected.value = false
+ }
+}
+
+function sendToSocket(content: string) {
+ if (!ws || ws.readyState !== WebSocket.OPEN) return
+ streaming.value = true
+ messages.value.push({ role: "user", content })
+ ws.send(JSON.stringify({ type: "message", content }))
+}
+
+export function openGuidance(taskId: number, prompt: string) {
+ if (!taskId) return
+
+ _taskId = taskId
+ initialPrompt.value = prompt
+ messages.value = []
+ isReady.value = false
+ streamingContent.value = ""
+ isOpen.value = true
+
+ if (ws) ws.close()
+ ws = new WebSocket(`${WS_BASE_URL}/ws/guidance/${taskId}/`)
+ setupHandlers(ws)
+}
+
+export function sendGuidance(content: string) {
+ sendToSocket(content)
+}
+
+export function stopGuidance() {
+ if (
+ messages.value.length > 0 &&
+ messages.value[messages.value.length - 1].role === "user"
+ ) {
+ messages.value.pop()
+ }
+ streaming.value = false
+ streamingContent.value = ""
+ if (_taskId) {
+ if (ws) ws.close()
+ ws = new WebSocket(`${WS_BASE_URL}/ws/guidance/${_taskId}/`)
+ initialPrompt.value = ""
+ setupHandlers(ws)
+ }
+}
+
+export function closeGuidance() {
+ if (ws) {
+ ws.close()
+ ws = null
+ }
+ isOpen.value = false
+ messages.value = []
+ isReady.value = false
+ connected.value = false
+ streaming.value = false
+ streamingContent.value = ""
+ initialPrompt.value = ""
+ _taskId = 0
+}
diff --git a/src/store/prompt.ts b/src/store/prompt.ts
index 0da0781..3b4ec28 100644
--- a/src/store/prompt.ts
+++ b/src/store/prompt.ts
@@ -15,6 +15,7 @@ export const conversationId = ref("")
export const connected = ref(false)
export const streaming = ref(false)
export const streamingContent = ref("")
+export const currentTaskId = ref(0)
let _onCodeComplete:
| ((
code: { html: string | null; css: string | null; js: string | null },
@@ -31,6 +32,7 @@ let _currentTaskId = 0
export function connectPrompt(taskId: number) {
_currentTaskId = taskId
+ currentTaskId.value = taskId
if (ws) ws.close()
ws = new WebSocket(`${WS_BASE_URL}/ws/prompt/${taskId}/`)
@@ -99,6 +101,8 @@ export function disconnectPrompt() {
connected.value = false
streaming.value = false
streamingContent.value = ""
+ currentTaskId.value = 0
+ _currentTaskId = 0
_onCodeComplete = null
}