Files
dsProject/dsLightRag/static/RecognizeEduQuestionOcr.html
2025-09-01 09:48:42 +08:00

461 lines
16 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!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>