'commit'
This commit is contained in:
70
dsLightRag/Routes/RecognizeEduQuestion.py
Normal file
70
dsLightRag/Routes/RecognizeEduQuestion.py
Normal file
@@ -0,0 +1,70 @@
|
||||
import logging
|
||||
|
||||
from fastapi import APIRouter, Request, HTTPException
|
||||
|
||||
from Util.FormulaRecognizer import FormulaRecognizer
|
||||
from Util.ShiTiRecognizer import ShiTiRecognizer
|
||||
|
||||
# 创建路由路由器
|
||||
router = APIRouter(prefix="/api", tags=["教育场景识别"])
|
||||
|
||||
# 配置日志
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@router.post("/recognize-formula")
|
||||
async def recognize_formula(request: Request):
|
||||
"""
|
||||
公式识别接口
|
||||
参数:
|
||||
image_url: 图片URL
|
||||
返回:
|
||||
JSON响应,包含公式识别结果
|
||||
"""
|
||||
try:
|
||||
# 获取请求参数
|
||||
data = await request.json()
|
||||
image_url = data.get("image_url")
|
||||
|
||||
# 验证参数
|
||||
if not image_url:
|
||||
raise HTTPException(status_code=400, detail="缺少必要参数: image_url")
|
||||
|
||||
# 调用公式识别器
|
||||
recognizer = FormulaRecognizer()
|
||||
result = recognizer.recognize_formula(image_url)
|
||||
|
||||
return result
|
||||
except HTTPException as e:
|
||||
raise e
|
||||
except Exception as e:
|
||||
logger.error(f"公式识别接口异常: {str(e)}")
|
||||
raise HTTPException(status_code=500, detail=f"服务器内部错误: {str(e)}")
|
||||
|
||||
@router.post("/recognize-question")
|
||||
async def recognize_question(request: Request):
|
||||
"""
|
||||
试题识别接口
|
||||
参数:
|
||||
image_url: 图片URL
|
||||
返回:
|
||||
JSON响应,包含试题识别结果
|
||||
"""
|
||||
try:
|
||||
# 获取请求参数
|
||||
data = await request.json()
|
||||
image_url = data.get("image_url")
|
||||
|
||||
# 验证参数
|
||||
if not image_url:
|
||||
raise HTTPException(status_code=400, detail="缺少必要参数: image_url")
|
||||
|
||||
# 调用试题识别器
|
||||
recognizer = ShiTiRecognizer()
|
||||
result = recognizer.recognize_question(image_url)
|
||||
|
||||
return result
|
||||
except HTTPException as e:
|
||||
raise e
|
||||
except Exception as e:
|
||||
logger.error(f"试题识别接口异常: {str(e)}")
|
||||
raise HTTPException(status_code=500, detail=f"服务器内部错误: {str(e)}")
|
Binary file not shown.
@@ -1,33 +1,32 @@
|
||||
import uvicorn
|
||||
import asyncio
|
||||
from fastapi import FastAPI
|
||||
from starlette.staticfiles import StaticFiles
|
||||
from fastapi.middleware.cors import CORSMiddleware # 添加此导入
|
||||
import logging # 添加此导入
|
||||
from contextlib import asynccontextmanager
|
||||
|
||||
from Routes.TeachingModel.tasks.BackgroundTasks import train_document_task
|
||||
from Util.PostgreSQLUtil import init_postgres_pool, close_postgres_pool
|
||||
import uvicorn
|
||||
from fastapi import FastAPI
|
||||
from fastapi.middleware.cors import CORSMiddleware # 添加此导入
|
||||
from starlette.staticfiles import StaticFiles
|
||||
|
||||
from Routes.Ggb import router as ggb_router
|
||||
from Routes.Knowledge import router as knowledge_router
|
||||
from Routes.Oss import router as oss_router
|
||||
from Routes.Rag import router as rag_router
|
||||
from Routes.ZuoWen import router as zuowen_router
|
||||
from Routes.Llm import router as llm_router
|
||||
from Routes.TeachingModel.api.LoginController import router as login_router
|
||||
from Routes.TeachingModel.api.UserController import router as user_router
|
||||
from Routes.TeachingModel.api.DmController import router as dm_router
|
||||
from Routes.TeachingModel.api.ThemeController import router as theme_router
|
||||
from Routes.TeachingModel.api.DocumentController import router as document_router
|
||||
from Routes.TeachingModel.api.TeachingModelController import router as teaching_model_router
|
||||
from Routes.QA import router as qa_router
|
||||
from Routes.JiMengRoute import router as jimeng_router
|
||||
from Routes.SunoRoute import router as suno_router
|
||||
from Routes.XueBanRoute import router as xueban_router
|
||||
from Routes.Knowledge import router as knowledge_router
|
||||
from Routes.Llm import router as llm_router
|
||||
from Routes.MjRoute import router as mj_router
|
||||
from Routes.Oss import router as oss_router
|
||||
from Routes.QA import router as qa_router
|
||||
from Routes.QWenImageRoute import router as qwen_image_router
|
||||
from Util.LightRagUtil import *
|
||||
from contextlib import asynccontextmanager
|
||||
import logging # 添加此导入
|
||||
from Routes.Rag import router as rag_router
|
||||
from Routes.SunoRoute import router as suno_router
|
||||
from Routes.TeachingModel.api.DmController import router as dm_router
|
||||
from Routes.TeachingModel.api.DocumentController import router as document_router
|
||||
from Routes.TeachingModel.api.LoginController import router as login_router
|
||||
from Routes.TeachingModel.api.TeachingModelController import router as teaching_model_router
|
||||
from Routes.TeachingModel.api.ThemeController import router as theme_router
|
||||
from Routes.TeachingModel.api.UserController import router as user_router
|
||||
from Routes.TeachingModel.tasks.BackgroundTasks import train_document_task
|
||||
from Routes.XueBanRoute import router as xueban_router
|
||||
from Routes.ZuoWen import router as zuowen_router
|
||||
from Routes.RecognizeEduQuestion import router as ocr_router
|
||||
|
||||
# 控制日志输出
|
||||
logger = logging.getLogger('lightrag')
|
||||
@@ -39,8 +38,8 @@ logger.addHandler(handler)
|
||||
|
||||
@asynccontextmanager
|
||||
async def lifespan(_: FastAPI):
|
||||
#pool = await init_postgres_pool()
|
||||
#app.state.pool = pool
|
||||
# pool = await init_postgres_pool()
|
||||
# app.state.pool = pool
|
||||
|
||||
asyncio.create_task(train_document_task())
|
||||
|
||||
@@ -48,7 +47,7 @@ async def lifespan(_: FastAPI):
|
||||
yield
|
||||
finally:
|
||||
# 应用关闭时销毁连接池
|
||||
#await close_postgres_pool(pool)
|
||||
# await close_postgres_pool(pool)
|
||||
pass
|
||||
|
||||
|
||||
@@ -78,8 +77,8 @@ app.include_router(jimeng_router) # 即梦路由
|
||||
app.include_router(suno_router) # Suno路由
|
||||
app.include_router(xueban_router) # 学伴路由
|
||||
app.include_router(mj_router) # Midjourney路由
|
||||
app.include_router(qwen_image_router) # Qwen Image 路由
|
||||
|
||||
app.include_router(qwen_image_router) # Qwen Image 路由
|
||||
app.include_router(ocr_router) # 教育场景识别
|
||||
|
||||
# Teaching Model 相关路由
|
||||
# 登录相关(不用登录)
|
||||
|
@@ -88,6 +88,7 @@ class ShiTiRecognizer:
|
||||
response = self.client.recognize_edu_question_ocr_with_options(request, runtime)
|
||||
result = self._parse_response(response)
|
||||
logger.info("试题识别成功")
|
||||
print( result)
|
||||
return result
|
||||
except Exception as error:
|
||||
logger.error(f"试题识别失败: {str(error)}")
|
||||
|
BIN
dsLightRag/Util/__pycache__/FormulaRecognizer.cpython-310.pyc
Normal file
BIN
dsLightRag/Util/__pycache__/FormulaRecognizer.cpython-310.pyc
Normal file
Binary file not shown.
BIN
dsLightRag/Util/__pycache__/ShiTiRecognizer.cpython-310.pyc
Normal file
BIN
dsLightRag/Util/__pycache__/ShiTiRecognizer.cpython-310.pyc
Normal file
Binary file not shown.
461
dsLightRag/static/RecognizeEduQuestionOcr.html
Normal file
461
dsLightRag/static/RecognizeEduQuestionOcr.html
Normal file
@@ -0,0 +1,461 @@
|
||||
<!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>
|
2186
dsLightRag/static/ShiTi.json
Normal file
2186
dsLightRag/static/ShiTi.json
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user