From 124444671aef05ef4896e87f002c126eef1bd454 Mon Sep 17 00:00:00 2001 From: huangpeng <1764183241@qq.com> Date: Sun, 21 Sep 2025 21:19:26 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=A8=A1=E6=8B=9F=E9=9D=A2?= =?UTF-8?q?=E8=AF=95=E7=9A=84=E7=9B=B8=E5=85=B3=E5=86=85=E5=AE=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package-lock.json | 64 ++++ package.json | 2 + src/api/index.js | 2 +- src/api/interview-message.js | 12 + src/api/interview.js | 34 +- src/views/interview-history/index.vue | 13 +- src/views/interview-report/index.vue | 241 ++++++++---- src/views/interview/chat.vue | 504 ++++++++++++++++++++++++-- src/views/interview/home.vue | 3 +- src/views/interview/index.vue | 31 +- vite.config.js | 18 +- 11 files changed, 787 insertions(+), 137 deletions(-) create mode 100644 src/api/interview-message.js diff --git a/package-lock.json b/package-lock.json index a958b41..cb8526e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,8 @@ "axios": "^1.11.0", "echarts": "^6.0.0", "element-plus": "^2.11.1", + "highlight.js": "^11.11.1", + "markdown-it": "^14.1.0", "normalize.css": "^8.0.1", "vue": "^3.5.18", "vue-router": "^4.5.1" @@ -1095,6 +1097,12 @@ } } }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "license": "Python-2.0" + }, "node_modules/async-validator": { "version": "4.2.5", "resolved": "https://registry.npmjs.org/async-validator/-/async-validator-4.2.5.tgz", @@ -1491,6 +1499,24 @@ "node": ">= 0.4" } }, + "node_modules/highlight.js": { + "version": "11.11.1", + "resolved": "https://registry.npmmirror.com/highlight.js/-/highlight.js-11.11.1.tgz", + "integrity": "sha512-Xwwo44whKBVCYoliBQwaPvtd/2tYFkRQtXDWj1nackaV2JPXx3L0+Jvd8/qCJ2p+ML0/XVkJ2q+Mr+UVdpJK5w==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", + "license": "MIT", + "dependencies": { + "uc.micro": "^2.0.0" + } + }, "node_modules/lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", @@ -1523,6 +1549,23 @@ "@jridgewell/sourcemap-codec": "^1.5.5" } }, + "node_modules/markdown-it": { + "version": "14.1.0", + "resolved": "https://registry.npmmirror.com/markdown-it/-/markdown-it-14.1.0.tgz", + "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1", + "entities": "^4.4.0", + "linkify-it": "^5.0.0", + "mdurl": "^2.0.0", + "punycode.js": "^2.3.1", + "uc.micro": "^2.1.0" + }, + "bin": { + "markdown-it": "bin/markdown-it.mjs" + } + }, "node_modules/math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", @@ -1532,6 +1575,12 @@ "node": ">= 0.4" } }, + "node_modules/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", + "license": "MIT" + }, "node_modules/memoize-one": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz", @@ -1642,6 +1691,15 @@ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", "license": "MIT" }, + "node_modules/punycode.js": { + "version": "2.3.1", + "resolved": "https://registry.npmmirror.com/punycode.js/-/punycode.js-2.3.1.tgz", + "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/rollup": { "version": "4.49.0", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.49.0.tgz", @@ -1714,6 +1772,12 @@ "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==", "license": "0BSD" }, + "node_modules/uc.micro": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/uc.micro/-/uc.micro-2.1.0.tgz", + "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", + "license": "MIT" + }, "node_modules/vite": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/vite/-/vite-7.1.3.tgz", diff --git a/package.json b/package.json index 518f2df..2a87768 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,8 @@ "axios": "^1.11.0", "echarts": "^6.0.0", "element-plus": "^2.11.1", + "highlight.js": "^11.11.1", + "markdown-it": "^14.1.0", "normalize.css": "^8.0.1", "vue": "^3.5.18", "vue-router": "^4.5.1" diff --git a/src/api/index.js b/src/api/index.js index 7e37eb0..9af1274 100644 --- a/src/api/index.js +++ b/src/api/index.js @@ -3,7 +3,7 @@ import { ElMessage } from 'element-plus'; // Create an Axios instance with a base configuration const apiClient = axios.create({ - baseURL: '/api', + baseURL: 'http://interview.qingqiu.online/api', timeout: 600000, // 10 min timeout }); diff --git a/src/api/interview-message.js b/src/api/interview-message.js new file mode 100644 index 0000000..9945a5e --- /dev/null +++ b/src/api/interview-message.js @@ -0,0 +1,12 @@ +import apiClient from "@/api/index.js"; + +/** + * 获取会话消息列表 + * @param sessionId + * @returns {Promise>} + */ +export const getMessageListBySessionId = (sessionId) => { + return apiClient.get( + `/interview-message/list-by-session-id/${sessionId}` + ); +} \ No newline at end of file diff --git a/src/api/interview.js b/src/api/interview.js index 9d698dd..4e5af68 100644 --- a/src/api/interview.js +++ b/src/api/interview.js @@ -14,12 +14,34 @@ export const startInterview = (formData) => { }; /** - * 继续面试(发送回答) - * @param {object} data - 包含sessionId和userAnswer的数据 + * 结束面试 + * @param sessionId + * @returns {Promise>} */ -export const continueInterview = (data) => { - return apiClient.post('/interview/chat', data); -}; +export const endInterview = (sessionId) => { + return apiClient.post( + `/interview/${sessionId}/end` + ); +} + +/** + * 提交答案 + * @param data + * @returns {Promise>} + */ +export const submitAnswer = (data) => { + return apiClient.post('/interview/submit-answer', data); +} + +/** + * 获取下一道题 + * @param sessionId 会话id + * @param progressId 进度id + * @returns {Promise>} + */ +export const getNextQuestion = (sessionId, progressId) => { + return apiClient.get(`/interview/next-question/${sessionId}/${progressId}`); +} /** * 获取面试历史列表 @@ -33,5 +55,5 @@ export const getInterviewHistoryList = () => { * @param {string} sessionId - 面试会话ID */ export const getInterviewReportDetail = (sessionId) => { - return apiClient.post('/interview/get-report-detail', { sessionId }); + return apiClient.post(`/interview/get-report-detail/${sessionId}`); }; \ No newline at end of file diff --git a/src/views/interview-history/index.vue b/src/views/interview-history/index.vue index e681688..71800d6 100644 --- a/src/views/interview-history/index.vue +++ b/src/views/interview-history/index.vue @@ -47,7 +47,7 @@ 查看复盘报告 继续答题 + @click="continueInterview(session)">继续答题 @@ -91,6 +91,17 @@ const viewReport = (sessionId) => { router.push({ name: 'InterviewReport', params: { sessionId } }); }; +const continueInterview = (data) => { + console.log(data) + router.push({ + path: '/interview-chat', + query: { + sessionId: data.sessionId, + mode: data.model + } + }); +} + // --- 生命周期钩子 --- onMounted(() => { diff --git a/src/views/interview-report/index.vue b/src/views/interview-report/index.vue index d42d005..1d63221 100644 --- a/src/views/interview-report/index.vue +++ b/src/views/interview-report/index.vue @@ -1,82 +1,88 @@ \ No newline at end of file diff --git a/src/views/interview/chat.vue b/src/views/interview/chat.vue index e4db5ca..bdfeeaa 100644 --- a/src/views/interview/chat.vue +++ b/src/views/interview/chat.vue @@ -1,53 +1,491 @@ \ No newline at end of file diff --git a/src/views/interview/home.vue b/src/views/interview/home.vue index 4262836..8af9f31 100644 --- a/src/views/interview/home.vue +++ b/src/views/interview/home.vue @@ -6,6 +6,7 @@
+
diff --git a/src/views/interview/index.vue b/src/views/interview/index.vue index 51ee9e1..85dbf1a 100644 --- a/src/views/interview/index.vue +++ b/src/views/interview/index.vue @@ -144,7 +144,7 @@ import {useRouter} from 'vue-router' import {ElMessage} from 'element-plus' import {Cpu, Collection, Check} from '@element-plus/icons-vue' import QuestionBankSection from '@/components/QuestionBankSection.vue' -import {startInterview, continueInterview, getInterviewReportDetail} from '@/api/interview.js'; +import {startInterview} from '@/api/interview.js'; const router = useRouter() @@ -183,10 +183,7 @@ const startInterviewAction = async () => { } isLoading.value = true; const sendFormData = new FormData(); - const selectionResult = questionBankSectionRef.value.getSelectionResult() - if (!selectionResult.selectedNodes) { - selectionResult.selectedNodes = [] - } + const sendData = { candidateName: formData.value.candidateName, aiModel: formData.value.aiModel, @@ -194,16 +191,22 @@ const startInterviewAction = async () => { model: selectedMode.value, selectedNodes: [] } - if (selectionResult.selectedNodes && selectionResult.selectedNodes.length > 0) { - const sendNodes = [] - selectionResult.selectedNodes.forEach(node => { - sendNodes.push({ - id: node.id, - name: node.name, - type: node.type, + if (selectedMode.value === 'local') { + const selectionResult = questionBankSectionRef.value.getSelectionResult() + if (!selectionResult.selectedNodes) { + selectionResult.selectedNodes = [] + } + if (selectionResult.selectedNodes && selectionResult.selectedNodes.length > 0) { + const sendNodes = [] + selectionResult.selectedNodes.forEach(node => { + sendNodes.push({ + id: node.id, + name: node.name, + type: node.type, + }) }) - }) - sendData.selectedNodes = sendNodes + sendData.selectedNodes = sendNodes + } } sendFormData.append('interviewStartDto', new Blob([JSON.stringify(sendData)], { diff --git a/vite.config.js b/vite.config.js index 8a0fc1e..1e44f6d 100644 --- a/vite.config.js +++ b/vite.config.js @@ -13,14 +13,14 @@ export default defineConfig({ }, server: { host: '0.0.0.0', - proxy: { - // Proxy API requests to the backend server - '/api': { - target: 'http://localhost:8080', - changeOrigin: true, // Needed for virtual hosted sites - secure: false, // Optional: if you are using https - rewrite: (path) => path.replace(/^\/api/, ''), - }, - }, + // proxy: { + // // Proxy API requests to the backend server + // '/api': { + // target: 'http://localhost:8080', + // changeOrigin: true, // Needed for virtual hosted sites + // secure: false, // Optional: if you are using https + // rewrite: (path) => path.replace(/^\/api/, ''), + // }, + // }, }, })