diff --git a/src/api.ts b/src/api.ts index 21a51c0..494faf2 100644 --- a/src/api.ts +++ b/src/api.ts @@ -1,6 +1,13 @@ import axios from "axios" import { router } from "./router" -import type { TutorialIn, ChallengeIn, FlagType, SubmissionOut, PromptMessage, TaskStatsOut } from "./utils/type" +import type { + TutorialIn, + ChallengeIn, + FlagType, + SubmissionOut, + PromptMessage, + TaskStatsOut, +} from "./utils/type" import { BASE_URL, STORAGE_KEY } from "./utils/const" const http = axios.create({ @@ -227,7 +234,6 @@ export const Submission = { const res = await http.get(`/submission/stats/${taskId}`, { params }) return res.data as TaskStatsOut }, - } export const Prompt = { @@ -240,7 +246,9 @@ export const Prompt = { async getMessages(conversationId: string): Promise { return ( - await http.get(`/prompt/conversations/${conversationId}/messages/`) + await http.get( + `/prompt/conversations/${conversationId}/messages/`, + ) ).data }, } diff --git a/src/components/Login.vue b/src/components/Login.vue index 8b81cc1..36aada9 100644 --- a/src/components/Login.vue +++ b/src/components/Login.vue @@ -180,7 +180,10 @@ async function submitStudent() { studentLoading.value = true showStudentError.value = false try { - const data = await Account.login(selectedUsername.value, studentPassword.value) + const data = await Account.login( + selectedUsername.value, + studentPassword.value, + ) user.username = data.username user.role = data.role user.loaded = true diff --git a/src/components/Preview.vue b/src/components/Preview.vue index a34122e..e8ae3c4 100644 --- a/src/components/Preview.vue +++ b/src/components/Preview.vue @@ -5,7 +5,12 @@ 下载 全屏 清空 - 代码 + 代码 链接 diff --git a/src/components/PromptPanel.vue b/src/components/PromptPanel.vue index f0d1d83..cca4ea6 100644 --- a/src/components/PromptPanel.vue +++ b/src/components/PromptPanel.vue @@ -6,7 +6,7 @@ 加载历史记录…
-
{{ msg.role === 'user' ? '我' : 'AI' }}
+
{{ msg.role === "user" ? "我" : "AI" }}
@@ -14,7 +14,11 @@
-
+
AI 正在思考中…
@@ -28,7 +32,12 @@ @keydown.enter.exact.prevent="send" /> - + 新对话 = { - html: { bg: "#fff5f0", fg: "#e05020", dot: "#e05020", border: "#f0d0c0", shimmer: "#fff5f0, #ffeee5, #fff5f0" }, - css: { bg: "#f0f0ff", fg: "#6060d0", dot: "#6060d0", border: "#d0d0f0", shimmer: "#f0f0ff, #e8e8fa, #f0f0ff" }, - js: { bg: "#fffbf0", fg: "#c0960a", dot: "#c0960a", border: "#f0e0b0", shimmer: "#fffbf0, #fff5e0, #fffbf0" }, - javascript: { bg: "#fffbf0", fg: "#c0960a", dot: "#c0960a", border: "#f0e0b0", shimmer: "#fffbf0, #fff5e0, #fffbf0" }, + const colors: Record< + string, + { bg: string; fg: string; dot: string; border: string; shimmer: string } + > = { + html: { + bg: "#fff5f0", + fg: "#e05020", + dot: "#e05020", + border: "#f0d0c0", + shimmer: "#fff5f0, #ffeee5, #fff5f0", + }, + css: { + bg: "#f0f0ff", + fg: "#6060d0", + dot: "#6060d0", + border: "#d0d0f0", + shimmer: "#f0f0ff, #e8e8fa, #f0f0ff", + }, + js: { + bg: "#fffbf0", + fg: "#c0960a", + dot: "#c0960a", + border: "#f0e0b0", + shimmer: "#fffbf0, #fff5e0, #fffbf0", + }, + javascript: { + bg: "#fffbf0", + fg: "#c0960a", + dot: "#c0960a", + border: "#f0e0b0", + shimmer: "#fffbf0, #fff5e0, #fffbf0", + }, + } + const c = colors[(lang ?? "").toLowerCase()] ?? { + bg: "#f0f7ff", + fg: "#2080f0", + dot: "#2080f0", + border: "#e0eaf5", + shimmer: "#f0f7ff, #e8f4f8, #f0f7ff", } - const c = colors[(lang ?? "").toLowerCase()] ?? { bg: "#f0f7ff", fg: "#2080f0", dot: "#2080f0", border: "#e0eaf5", shimmer: "#f0f7ff, #e8f4f8, #f0f7ff" } return `
${label}代码已自动应用到预览区
` } @@ -88,16 +130,13 @@ function renderContent(msg: { role: string; content: string }): string { } // Auto-scroll to bottom on new messages -watch( - [() => messages.value.length, streamingContent], - () => { - nextTick(() => { - if (messagesRef.value) { - messagesRef.value.scrollTop = messagesRef.value.scrollHeight - } - }) - } -) +watch([() => messages.value.length, streamingContent], () => { + nextTick(() => { + if (messagesRef.value) { + messagesRef.value.scrollTop = messagesRef.value.scrollHeight + } + }) +}) diff --git a/src/components/Task.vue b/src/components/Task.vue index 8b729f6..1fa9e33 100644 --- a/src/components/Task.vue +++ b/src/components/Task.vue @@ -38,15 +38,11 @@
- + diff --git a/src/components/TaskStatsModal.vue b/src/components/TaskStatsModal.vue index 79a9de1..2ceb0e5 100644 --- a/src/components/TaskStatsModal.vue +++ b/src/components/TaskStatsModal.vue @@ -16,24 +16,38 @@ - + @@ -49,7 +66,14 @@ import Preview from "../components/Preview.vue" import { Challenge, Submission } from "../api" import { html, css, js } from "../store/editors" import { taskId } from "../store/task" -import { connectPrompt, disconnectPrompt, conversationId, streaming, setOnCodeComplete, loadHistory } from "../store/prompt" +import { + connectPrompt, + disconnectPrompt, + conversationId, + streaming, + setOnCodeComplete, + loadHistory, +} from "../store/prompt" const route = useRoute() const router = useRouter() @@ -71,7 +95,7 @@ async function loadChallenge() { taskId.value = data.task_ptr challengeTitle.value = `#${data.display} ${data.title}` challengeContent.value = await marked.parse(data.content, { async: true }) - loadHistory(data.task_ptr) // HTTP preload — async, non-blocking + loadHistory(data.task_ptr) // HTTP preload — async, non-blocking connectPrompt(data.task_ptr) // WebSocket — synchronous open setOnCodeComplete(async (code) => { if (!conversationId.value) return diff --git a/src/pages/Submissions.vue b/src/pages/Submissions.vue index 903b529..8ccc247 100644 --- a/src/pages/Submissions.vue +++ b/src/pages/Submissions.vue @@ -7,7 +7,10 @@ :max="0.8" >