Commit 72bbd208 authored by liujiangnan's avatar liujiangnan

feat: 暂存流式接口

parent 45e477f7
......@@ -1166,3 +1166,110 @@ html, body {
font-size: 12px;
}
}
/* AI 分析遮罩层样式 */
.ai-analysis-dialog .el-dialog {
border-radius: 8px;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
}
.ai-analysis-dialog .el-dialog__header {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
border-radius: 8px 8px 0 0;
padding: 15px 20px;
}
.ai-analysis-dialog .el-dialog__title {
color: white;
font-size: 18px;
font-weight: 600;
}
.ai-analysis-dialog .el-dialog__body {
padding: 30px 20px;
background: #f8f9fa;
}
.ai-analysis-content {
text-align: center;
}
.ai-status {
font-size: 14px;
font-weight: 500;
margin-bottom: 20px;
padding: 10px;
background: #e8f4fd;
border-radius: 4px;
border-left: 4px solid #409eff;
}
.ai-text-area {
margin-top: 20px;
}
.ai-text-area .el-textarea__inner {
font-family: 'Courier New', monospace;
font-size: 13px;
line-height: 1.6;
background: #fafafa;
border: 1px solid #e4e7ed;
border-radius: 4px;
resize: none;
}
.ai-text-area .el-textarea__inner:focus {
border-color: #409eff;
box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.2);
}
.ai-analysis-dialog .el-dialog__footer {
background: #f8f9fa;
border-radius: 0 0 8px 8px;
padding: 15px 20px;
text-align: center;
}
.ai-analysis-dialog .dialog-footer .el-button {
min-width: 100px;
border-radius: 20px;
}
/* 进度条样式优化 */
.ai-analysis-content .el-progress {
margin-bottom: 25px;
}
.ai-analysis-content .el-progress__text {
font-size: 14px;
font-weight: 600;
color: #409eff;
}
.ai-analysis-content .el-progress-bar__outer {
background-color: #e4e7ed;
border-radius: 10px;
}
.ai-analysis-content .el-progress-bar__inner {
border-radius: 10px;
background: linear-gradient(90deg, #409eff 0%, #67c23a 100%);
transition: all 0.3s ease;
}
/* 响应式设计 */
@media (max-width: 768px) {
.ai-analysis-dialog .el-dialog {
width: 90% !important;
margin: 5vh auto;
}
.ai-analysis-dialog .el-dialog__body {
padding: 20px 15px;
}
.ai-text-area .el-textarea__inner {
font-size: 12px;
}
}
\ No newline at end of file
......@@ -30,6 +30,55 @@
<body>
<div id="app" v-loading.fullscreen.lock="loading">
<el-button style="position: absolute; top: 10px; right: 10px;" @click="tryAI">AI重新匹配</el-button>
<!-- AI 分析遮罩层 -->
<el-dialog
title="AI 分析中..."
:visible.sync="showAIAnalysis"
:close-on-click-modal="false"
:close-on-press-escape="false"
:show-close="false"
width="60%"
center
class="ai-analysis-dialog"
>
<div class="ai-analysis-content">
<!-- 进度条 -->
<el-progress
:percentage="aiAnalysisProgress"
:status="aiAnalysisProgress === 100 ? 'success' : ''"
:stroke-width="8"
style="margin-bottom: 20px;"
></el-progress>
<!-- 状态信息 -->
<div class="ai-status" style="margin-bottom: 15px; text-align: center; color: #666;">
{{ aiAnalysisStatus }}
</div>
<!-- 文本显示区域 -->
<div class="ai-text-area">
<el-input
type="textarea"
v-model="aiAnalysisText"
:rows="12"
readonly
placeholder="AI 分析结果将在这里显示..."
style="font-family: 'Courier New', monospace; font-size: 14px;"
></el-input>
</div>
</div>
<span slot="footer" class="dialog-footer">
<el-button
v-if="aiAnalysisProgress === 100 || aiAnalysisText.includes('失败')"
@click="showAIAnalysis = false"
type="primary"
>
关闭
</el-button>
</span>
</el-dialog>
<!-- 文件上传界面 -->
<div class="upload-container" v-if="!hasData">
<!-- 处理进度界面 -->
......
......@@ -11,14 +11,14 @@ const callServerMethod = (method, data) => {
});
}
// window.courseware.getData = function (fun, key) {
// $.getJSON('../play/defaultData_1.json', function(defaultData) {
// console.log('加载默认数据:', defaultData);
// fun(defaultData);
// }).fail(function() {
// console.error('默认数据加载失败!');
// });
// }
window.courseware.getData = function (fun, key) {
$.getJSON('../play/defaultData_1.json', function(defaultData) {
console.log('加载默认数据:', defaultData);
fun(defaultData);
}).fail(function() {
console.error('默认数据加载失败!');
});
}
new Vue({
......@@ -107,7 +107,14 @@ new Vue({
// 新增:上传类型
uploadType: 'pdf',
AI_SERVER_URL: 'https://stagingopensource.iteachabc.com',
AI_SERVER_URL: 'http://localhost:1339',
// AI_SERVER_URL: 'https://stagingopensource.iteachabc.com',
// AI 分析遮罩层相关
showAIAnalysis: false,
aiAnalysisText: '',
aiAnalysisStatus: '',
aiAnalysisProgress: 0,
},
mounted() {
......@@ -157,10 +164,10 @@ new Vue({
type: 'POST',
contentType: 'application/json',
data: JSON.stringify(data),
success: function(response) {
success: function (response) {
resolve(response);
},
error: function(xhr, status, error) {
error: function (xhr, status, error) {
reject(new Error(error || '请求失败'));
}
});
......@@ -195,21 +202,107 @@ new Vue({
const urlParams = new URLSearchParams(window.location.search);
const coursewareId = urlParams.get('course_id');
// 显示遮罩层
this.showAIAnalysis = true;
this.aiAnalysisText = '';
this.aiAnalysisStatus = '正在连接服务器...';
this.aiAnalysisProgress = 0;
try {
await this.postRequest('/open/api/ai/dpe/v1/pagerepair', {
courseware_id: coursewareId || 1,
page_number: this.currentPageIndex
}, {
loadingText: 'AI 分析中,请稍候...',
successMessage: 'AI 分析完成',
errorMessage: 'AI 分析失败,请稍后重试'
this.aiAnalysisStatus = '正在发送请求...';
this.aiAnalysisProgress = 20;
const requestUrl = this.AI_SERVER_URL + '/open/api/ai/dpe/v1/pagerepair';
const requestData = { courseware_id: coursewareId || 1783332, page_number: this.currentPageIndex };
console.log('请求URL:', requestUrl);
console.log('请求数据:', requestData);
// 使用 XMLHttpRequest 来处理流式响应
const xhr = new XMLHttpRequest();
xhr.open('POST', requestUrl, true);
xhr.setRequestHeader('Content-Type', 'application/json');
let lastResponseLength = 0;
xhr.onprogress = (event) => {
if (xhr.readyState === 3 || xhr.readyState === 4) {
const newData = xhr.responseText.substring(lastResponseLength);
lastResponseLength = xhr.responseText.length;
if (newData) {
this.aiAnalysisText += newData;
this.aiAnalysisProgress = Math.min(90, 40 + (this.aiAnalysisText.length / 100));
this.aiAnalysisStatus = `正在接收数据... (${this.aiAnalysisText.length} 字符)`;
}
}
};
xhr.onload = () => {
if (xhr.status >= 200 && xhr.status < 300) {
this.aiAnalysisStatus = 'AI 分析完成,正在重新加载数据...';
this.aiAnalysisProgress = 95;
// 重新加载数据
this.loadDefaultData().then(() => {
this.aiAnalysisStatus = 'AI 分析完成!';
this.aiAnalysisProgress = 100;
// 2秒后自动关闭遮罩层
setTimeout(() => {
this.showAIAnalysis = false;
}, 2000);
});
} else {
throw new Error(`HTTP error! status: ${xhr.status}`);
}
};
xhr.onerror = () => {
throw new Error('Network error');
};
xhr.send(JSON.stringify(requestData));
// 等待 XHR 完成
await new Promise((resolve, reject) => {
xhr.onload = () => {
if (xhr.status >= 200 && xhr.status < 300) {
resolve();
} else {
reject(new Error(`HTTP error! status: ${xhr.status}`));
}
};
xhr.onerror = () => reject(new Error('Network error'));
});
this.aiAnalysisStatus = 'AI 分析完成,正在重新加载数据...';
this.aiAnalysisProgress = 95;
// 重新加载数据
await this.loadDefaultData();
// 显示完成消息
this.aiAnalysisStatus = 'AI 分析完成!';
this.aiAnalysisProgress = 100;
// 2秒后自动关闭遮罩层
setTimeout(() => {
this.showAIAnalysis = false;
}, 2000);
} catch (error) {
// 错误已在 postRequest 中处理
console.error('AI 分析失败:', error);
// 显示错误信息
this.aiAnalysisText = `AI 分析失败: ${error.message}`;
this.aiAnalysisStatus = '分析失败,请重试';
this.aiAnalysisProgress = 0;
// 5秒后自动关闭遮罩层
setTimeout(() => {
this.showAIAnalysis = false;
}, 5000);
}
},
// 心跳实时查询异步处理进度及信息
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment