Files
dsProject/dsLightRag/static/RecognizeEduQuestionOcr.html

461 lines
16 KiB
HTML
Raw Normal View History

2025-09-01 09:48:42 +08:00
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>教育场景识别</title>
<link rel="icon" href="data:">
<!-- 新增引入MathJax库 -->
<script src="https://gcore.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
<!-- 新增MathJax配置 -->
<script>
MathJax = {
tex: {
inlineMath: [['$', '$'], ['\\(', '\\)']],
displayMath: [['$$', '$$'], ['\\[', '\\]']],
processEscapes: true
}
};
</script>
<style>
body {
font-family: 'Microsoft YaHei', sans-serif;
margin: 0;
padding: 0;
background-color: #f5f5f5;
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 20px;
}
h1 {
color: #333;
text-align: center;
}
.tab-container {
display: flex;
margin-bottom: 20px;
}
.tab-button {
flex: 1;
padding: 12px;
background-color: #e0e0e0;
border: none;
cursor: pointer;
font-size: 16px;
transition: background-color 0.3s;
}
.tab-button.active {
background-color: #4CAF50;
color: white;
}
.tab-button:first-child {
border-top-left-radius: 8px;
border-bottom-left-radius: 8px;
}
.tab-button:last-child {
border-top-right-radius: 8px;
border-bottom-right-radius: 8px;
}
.tab-content {
display: none;
background-color: white;
border-radius: 8px;
padding: 20px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
.tab-content.active {
display: block;
}
.example-section {
margin-bottom: 30px;
}
.example-section h2 {
color: #333;
border-bottom: 2px solid #4CAF50;
padding-bottom: 10px;
}
.example-images {
display: flex;
flex-wrap: wrap;
gap: 20px;
margin-top: 15px;
}
.example-image-card {
width: 200px;
border: 1px solid #ddd;
border-radius: 8px;
overflow: hidden;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
transition: transform 0.2s;
}
.example-image-card:hover {
transform: translateY(-5px);
}
.example-image-card img {
width: 100%;
height: 150px;
object-fit: contain;
background-color: #f9f9f9;
}
.example-image-card .description {
padding: 10px;
text-align: center;
font-size: 14px;
color: #666;
}
.recognize-section {
margin-top: 30px;
}
.recognize-section h2 {
color: #333;
border-bottom: 2px solid #4CAF50;
padding-bottom: 10px;
}
.input-area {
margin-top: 15px;
}
.input-group {
display: flex;
gap: 10px;
margin-bottom: 15px;
}
.input-group input {
flex: 1;
padding: 10px;
border: 1px solid #ddd;
border-radius: 4px;
}
.input-group button {
padding: 10px 15px;
background-color: #4CAF50;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
.input-group button:hover {
background-color: #45a049;
}
.option-item {
display: inline-block; /* 保持行内块级特性 */
padding-right: 15px; /* 序号与内容间距 */
font-weight: bold; /* 突出显示选项序号 */
}
.result-area {
margin-top: 20px;
min-height: 200px;
padding: 15px;
border: 1px solid #ddd;
border-radius: 4px;
background-color: #f9f9f9;
line-height: 1.8; /* 优化行高 */
}
.option-item {
margin: 8px 0; /* 为选项添加上下间距 */
background-color: #f9f9f9;
}
.loading-animation {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 1000;
display: flex !important;
flex-direction: column;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
min-height: 200px;
color: #666;
background-color: rgba(249, 249, 249, 0.7); /* 调整透明度为0.7 */
}
.spinner {
width: 40px;
height: 40px;
border: 4px solid #f3f3f3;
border-top: 4px solid #3498db;
border-radius: 50%;
animation: spin 1s linear infinite !important;
margin-bottom: 10px;
}
.result-area {
margin-top: 20px;
min-height: 200px;
padding: 15px;
border: 1px solid #ddd;
border-radius: 4px;
background-color: #f9f9f9;
line-height: 1.8;
position: relative; /* 关键:作为动画容器的定位基准 */
overflow: hidden; /* 防止动画溢出 */
}
.option-item {
margin: 8px 0; /* 为选项添加上下间距 */
background-color: #f9f9f9;
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
</style>
</head>
<body>
<div class="container">
<h1>教育场景识别</h1>
<div class="tab-container">
<button class="tab-button active" onclick="switchTab('formula')">公式识别</button>
<button class="tab-button" onclick="switchTab('question')">试题识别</button>
</div>
<!-- 公式识别标签页 -->
<div id="formula-tab" class="tab-content active">
<div class="example-section">
<h2>示例公式图片</h2>
<div class="example-images">
<div class="example-image-card">
<img src="https://dsideal.obs.cn-north-1.myhuaweicloud.com/HuangHai/Backup/GongShi.jpg" alt="公式示例1">
<div class="description">数学公式示例</div>
</div>
</div>
</div>
<div class="recognize-section">
<h2>公式识别</h2>
<div class="input-area">
<div class="input-group">
<input type="text" id="formulaImageUrl" placeholder="请输入图片URL或使用示例图片" value="https://dsideal.obs.cn-north-1.myhuaweicloud.com/HuangHai/Backup/GongShi.jpg">
<button onclick="recognizeFormula()">识别公式</button>
</div>
<div id="formulaResult" class="result-area">
<div style="color:#666; text-align:center; padding:20px;">识别结果将在此处显示</div>
</div>
</div>
</div>
</div>
<!-- 试题识别标签页 -->
<div id="question-tab" class="tab-content">
<div class="example-section">
<h2>示例试题图片</h2>
<div class="example-images">
<div class="example-image-card">
<img src="https://dsideal.obs.cn-north-1.myhuaweicloud.com/HuangHai/Backup/ShiTi.jpg" alt="试题示例1">
<div class="description">试题示例</div>
</div>
</div>
</div>
<div class="recognize-section">
<h2>试题识别</h2>
<div class="input-area">
<div class="input-group">
<input type="text" id="questionImageUrl" placeholder="请输入图片URL或使用示例图片" value="https://dsideal.obs.cn-north-1.myhuaweicloud.com/HuangHai/Backup/ShiTi.jpg">
<button onclick="recognizeQuestion()">识别试题</button>
</div>
<div id="questionResult" class="result-area">
<div style="color:#666; text-align:center; padding:20px;">识别结果将在此处显示</div>
</div>
</div>
</div>
</div>
</div>
<script>
// MathJax 配置
window.MathJax = {
tex: {
inlineMath: [['$', '$'], ['\(', '\)']],
displayMath: [['$$', '$$'], ['\[', '\]']],
processEscapes: true,
packages: {'[+]': ['ams']}
},
svg: { fontCache: 'global' },
startup: { pageReady: pageReady }
};
// MathJax 加载完成后执行
function pageReady() {
return MathJax.startup.defaultPageReady().then(function() {
console.log('MathJax 3 加载完成');
});
}
</script>
<script src="https://gcore.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js" id="MathJax-script"></script>
<script>
// 切换标签页
function switchTab(tabName) {
document.querySelectorAll('.tab-button').forEach(button => button.classList.remove('active'));
document.querySelectorAll('.tab-content').forEach(content => content.classList.remove('active'));
if (tabName === 'formula') {
document.querySelectorAll('.tab-button')[0].classList.add('active');
document.getElementById('formula-tab').classList.add('active');
} else {
document.querySelectorAll('.tab-button')[1].classList.add('active');
document.getElementById('question-tab').classList.add('active');
}
}
// 识别公式
function recognizeFormula() {
const imageUrl = document.getElementById('formulaImageUrl').value.trim();
const resultArea = document.getElementById('formulaResult');
if (!imageUrl) { alert('请输入图片URL'); return; }
resultArea.innerHTML = '<div class="loading-animation"><div class="spinner"></div><div>正在识别公式...</div></div>';
fetch('/api/recognize-formula', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ image_url: imageUrl })
})
.then(response => response.json())
.then(data => {
if (data.error) { resultArea.innerHTML = `<div style="color:red">识别失败: ${data.error}</div>`; return; }
const content = data.Data?.content || '';
if (!content) { resultArea.innerHTML = '<div>未识别到公式内容</div>'; return; }
try {
resultArea.innerHTML = `<div class="tex2jax_process">$$${content}$$</div>`;
renderWithMathJax(resultArea);
} catch (error) {
console.error('公式处理错误:', error);
resultArea.innerHTML = `<div style="color:red">公式处理失败: ${error.message}</div>`;
}
})
.catch(error => {
console.error('请求错误:', error);
resultArea.innerHTML = `<div style="color:red">请求出错,请重试</div>`;
});
}
// 识别试题
function recognizeQuestion() {
const imageUrl = document.getElementById('questionImageUrl').value.trim();
const resultArea = document.getElementById('questionResult');
if (!imageUrl) { alert('请输入图片URL'); return; }
// 立即显示加载动画(关键修复)
console.log('显示加载动画');
resultArea.innerHTML = '<div class="loading-animation"><div class="spinner"></div><div>正在识别试题...</div></div>';
// 添加延迟模拟API调用
setTimeout(() => {
// 读取本地JSON文件
fetch('ShiTi.json')
.then(response => {
console.log('JSON请求响应:', response);
if (!response.ok) throw new Error('无法加载本地JSON文件');
return response.json();
})
.then(data => {
if (data.error) { resultArea.innerHTML = `<div style="color:red">识别失败: ${data.error}</div>`; return; }
let content = data.Data?.content || '';
console.log("处理前:"+content);
try {
// 处理选项格式 - 序号与内容同行,选项间换行
content = content.replace(/([A-D])\s*\.\s*/g, '<span class="option-item">$$$1. </span><br>');
console.log("处理后:"+content);
// 确保不替换已添加的<br>标签
const latexContainer = document.createElement('div');
latexContainer.className = 'tex2jax_process';
latexContainer.innerHTML = content;
console.log('预处理后的内容:', latexContainer.innerHTML);
resultArea.innerHTML = '';
resultArea.appendChild(latexContainer);
renderWithMathJax(resultArea);
} catch (error) {
console.error('试题处理错误:', error);
resultArea.innerHTML = `<div style="color:red">试题处理失败: ${error.message}</div>`;
}
})
.catch(error => {
console.error('请求错误:', error);
const errorMsg = '加载本地JSON失败: ' + error.message;
resultArea.innerHTML = `<div style="color:red">${errorMsg}</div>`;
});
}, 1000); // 1秒延迟
}
// MathJax渲染函数
function renderWithMathJax(element) {
if (!window.MathJax) {
console.error('MathJax未加载5秒后重试');
setTimeout(() => renderWithMathJax(element), 5000);
return;
}
try {
MathJax.typesetPromise([element]).then(() => {
console.log('MathJax渲染完成');
}).catch((e) => {
console.error('MathJax渲染错误:', e);
fallbackRender(element);
});
} catch (e) {
console.error('MathJax调用错误:', e);
fallbackRender(element);
}
}
// 渲染失败时的回退方法
function fallbackRender(element) {
const originalContent = element.querySelector('.tex2jax_process')?.textContent || '';
if (originalContent) {
element.innerHTML = `<div style="font-family: monospace; white-space: pre-wrap;">${escapeHtml(originalContent)}</div><div style="color:orange">提示MathJax渲染失败显示原始公式代码</div>`;
}
}
// HTML转义函数
function escapeHtml(text) {
const div = document.createElement('div');
div.textContent = text;
return div.innerHTML;
}
</script>
</body>
</html>