Commit ad5cf1dd authored by liujiangnan's avatar liujiangnan

feat

parent 72bbd208
......@@ -31,7 +31,7 @@
<div id="app" v-loading.fullscreen.lock="loading">
<el-button style="position: absolute; top: 10px; right: 10px;" @click="tryAI">AI重新匹配</el-button>
<!-- AI 分析遮罩层 -->
<!-- AI 分析遮罩层 -->
<el-dialog
title="AI 分析中..."
:visible.sync="showAIAnalysis"
......@@ -59,19 +59,21 @@
<!-- 文本显示区域 -->
<div class="ai-text-area">
<el-input
ref="aiTextArea"
type="textarea"
v-model="aiAnalysisText"
:rows="12"
:rows="24"
readonly
placeholder="AI 分析结果将在这里显示..."
style="font-family: 'Courier New', monospace; font-size: 14px;"
@scroll="handleTextAreaScroll"
></el-input>
</div>
</div>
<span slot="footer" class="dialog-footer">
<el-button
v-if="aiAnalysisProgress === 100 || aiAnalysisText.includes('失败')"
:disabled="aiAnalysisProgress < 100 && !aiAnalysisText.includes('失败')"
@click="showAIAnalysis = false"
type="primary"
>
......
......@@ -115,6 +115,9 @@ new Vue({
aiAnalysisText: '',
aiAnalysisStatus: '',
aiAnalysisProgress: 0,
// 滚动控制相关
shouldAutoScroll: true,
userScrolled: false,
},
mounted() {
......@@ -134,70 +137,6 @@ new Vue({
methods: {
// 公共的 POST 请求方法
async postRequest(endpoint, data, options = {}) {
const {
loadingText = '请求中,请稍候...',
successMessage = '请求成功',
errorMessage = '请求失败',
showLoading = true,
showSuccessMessage = true,
showErrorMessage = true
} = options;
let loading = null;
if (showLoading) {
loading = this.$loading({
lock: true,
text: loadingText,
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)'
});
}
try {
const result = await new Promise((resolve, reject) => {
$.ajax({
url: this.AI_SERVER_URL + endpoint,
type: 'POST',
contentType: 'application/json',
data: JSON.stringify(data),
success: function (response) {
resolve(response);
},
error: function (xhr, status, error) {
reject(new Error(error || '请求失败'));
}
});
});
if (result.code === 200) {
if (showSuccessMessage) {
this.$message.success(successMessage);
}
return result;
} else {
const errorMsg = result.message || errorMessage;
if (showErrorMessage) {
this.$message.error(errorMsg);
}
throw new Error(errorMsg);
}
} catch (error) {
console.error('请求失败:', error);
if (showErrorMessage) {
this.$message.error(error.message || errorMessage);
}
throw error;
} finally {
if (loading) {
loading.close();
}
}
},
async tryAI() {
const urlParams = new URLSearchParams(window.location.search);
const coursewareId = urlParams.get('course_id');
......@@ -207,6 +146,10 @@ new Vue({
this.aiAnalysisText = '';
this.aiAnalysisStatus = '正在连接服务器...';
this.aiAnalysisProgress = 0;
// 重置滚动状态
this.shouldAutoScroll = true;
this.userScrolled = false;
try {
this.aiAnalysisStatus = '正在发送请求...';
......@@ -215,96 +158,104 @@ new Vue({
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);
await new Promise((resolve, reject) => {
// 使用 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;
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;
// 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) => {
if (newData) {
this.aiAnalysisText += newData;
this.aiAnalysisProgress = Math.min(90, Math.floor(40 + (this.aiAnalysisText.length / 100)));
this.aiAnalysisStatus = `正在接收数据... (${this.aiAnalysisText.length} 字符)`;
// 自动滚动到底部
this.scrollAITextToBottom();
}
}
};
xhr.onload = () => {
if (xhr.status >= 200 && xhr.status < 300) {
resolve();
this.aiAnalysisStatus = 'AI 分析完成,正在重新加载数据...';
this.aiAnalysisProgress = 95;
// 重新加载数据
this.loadDefaultData().then(() => {
this.aiAnalysisStatus = 'AI 分析完成!';
this.aiAnalysisProgress = 100;
resolve();
});
} else {
reject(new Error(`HTTP error! status: ${xhr.status}`));
}
};
xhr.onerror = () => reject(new Error('Network error'));
xhr.onerror = () => {
reject(new Error('Network error'));
};
xhr.send(JSON.stringify(requestData));
});
this.aiAnalysisStatus = 'AI 分析完成,正在重新加载数据...';
this.aiAnalysisProgress = 95;
// 重新加载数据
await this.loadDefaultData();
// 显示完成消息
this.aiAnalysisStatus = 'AI 分析完成!';
this.aiAnalysisProgress = 100;
// 2秒后自动关闭遮罩层
setTimeout(() => {
this.showAIAnalysis = false;
}, 2000);
} catch (error) {
console.error('AI 分析失败:', error);
// 显示错误信息
this.aiAnalysisText = `AI 分析失败: ${error.message}`;
this.aiAnalysisStatus = '分析失败,请重试';
this.aiAnalysisProgress = 0;
// 5秒后自动关闭遮罩层
this.aiAnalysisProgress = 0;
}
},
// 处理文本区域滚动
handleTextAreaScroll(event) {
const textarea = event.target;
const isAtBottom = textarea.scrollTop + textarea.clientHeight >= textarea.scrollHeight - 5;
// 如果用户手动滚动到底部,恢复自动滚动
if (isAtBottom) {
this.userScrolled = false;
this.shouldAutoScroll = true;
} else {
// 如果用户向上滚动,暂停自动滚动
this.userScrolled = true;
this.shouldAutoScroll = false;
}
},
// 滚动AI文本区域到底部
scrollAITextToBottom() {
console.log('尝试滚动到底部,shouldAutoScroll:', this.shouldAutoScroll);
if (this.$refs.aiTextArea && this.shouldAutoScroll) {
// 使用setTimeout确保DOM完全更新
setTimeout(() => {
this.showAIAnalysis = false;
}, 5000);
// 尝试多种方式获取textarea元素
let textarea = this.$refs.aiTextArea.$el.querySelector('textarea');
if (!textarea) {
textarea = this.$refs.aiTextArea.$el.querySelector('.el-textarea__inner');
}
if (!textarea) {
textarea = this.$refs.aiTextArea.$el.querySelector('textarea, .el-textarea__inner');
}
console.log('找到textarea:', !!textarea);
if (textarea) {
console.log('设置scrollTop:', textarea.scrollHeight);
textarea.scrollTop = textarea.scrollHeight;
} else {
console.log('未找到textarea元素');
}
}, 10);
}
},
// 心跳实时查询异步处理进度及信息
async checkProcess(_data) {
let data = _data;
......
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