| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189 |
- <!DOCTYPE html>
- <html lang="zh-CN">
- <head>
- <meta charset="UTF-8">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>题目预览验证工具 - Math CMS</title>
- <!-- KaTeX CSS -->
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.css">
- <!-- Tailwind CSS CDN -->
- <script src="https://cdn.tailwindcss.com"></script>
- <!-- KaTeX JS -->
- <script src="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.js"></script>
- <style>
- [x-cloak] { display: none !important; }
- .math-preview {
- font-family: "SimSun", "Songti SC", serif;
- line-height: 1.8;
- }
- .math-preview .katex {
- font-size: 1.1em;
- }
- .math-preview .katex-display {
- margin: 0.5em 0;
- }
- /* 题目样式 */
- .question-stem {
- margin-bottom: 1rem;
- }
- .question-options {
- margin-left: 1rem;
- }
- .question-option {
- margin: 0.5rem 0;
- }
- .question-answer {
- margin-top: 1rem;
- padding-top: 0.5rem;
- border-top: 1px dashed #ccc;
- }
- .question-solution {
- margin-top: 1rem;
- padding: 0.75rem;
- background: #f9f9f9;
- border-radius: 4px;
- }
- </style>
- <!-- Livewire Styles -->
- <style>
- [wire\:loading], [wire\:loading\.delay], [wire\:loading\.inline-block], [wire\:loading\.inline], [wire\:loading\.block], [wire\:loading\.flex], [wire\:loading\.table], [wire\:loading\.grid], [wire\:loading\.inline-flex] {
- display: none;
- }
- [wire\:loading\.delay\.shortest], [wire\:loading\.delay\.shorter], [wire\:loading\.delay\.short], [wire\:loading\.delay\.long], [wire\:loading\.delay\.longer], [wire\:loading\.delay\.longest] {
- display: none;
- }
- [wire\:offline] {
- display: none;
- }
- [wire\:dirty]:not(textarea):not(input):not(select) {
- display: none;
- }
- </style>
- @livewireStyles
- </head>
- <body class="bg-gray-100 min-h-screen">
- {{ $slot }}
- <!-- Livewire Scripts -->
- @livewireScripts
- <script>
- /**
- * 数学公式渲染器
- * 与前端 MathText.tsx 逻辑保持一致
- */
- const MathRenderer = {
- /**
- * 预处理文本:处理双反斜杠、换行符等
- */
- preprocessText(text) {
- let result = text;
- // 1. 处理公式内的双反斜杠 -> 单反斜杠
- // 块级公式 $$...$$
- result = result.replace(/\$\$([\s\S]*?)\$\$/g, (_, tex) => {
- return '$$' + tex.replace(/\\\\/g, '\\') + '$$';
- });
- // 行内公式 $...$
- result = result.replace(/\$([^$\n]+?)\$/g, (_, tex) => {
- return '$' + tex.replace(/\\\\/g, '\\') + '$';
- });
- // 2. 换行符处理:\n -> <br>,但保护 LaTeX 命令如 \neq, \nu
- result = result.replace(/\\n(?![a-zA-Z])/g, '<br>');
- // 3. 统一 LaTeX 分隔符格式
- result = result.replace(/\\\[([\s\S]*?)\\\]/g, (_, tex) => `$$${tex}$$`);
- result = result.replace(/\\\(([\s\S]*?)\\\)/g, (_, tex) => `$${tex}$`);
- return result;
- },
- /**
- * 渲染数学公式
- */
- render(text) {
- if (!text) return '';
- let result = this.preprocessText(text);
- // 渲染块级公式 $$...$$
- result = result.replace(/\$\$([\s\S]*?)\$\$/g, (_, tex) => {
- try {
- return katex.renderToString(tex.trim(), {
- displayMode: true,
- throwOnError: false,
- strict: false,
- });
- } catch (e) {
- console.error('KaTeX render error:', e);
- return `<span class="text-red-500">$$${tex}$$</span>`;
- }
- });
- // 渲染行内公式 $...$
- result = result.replace(/\$([^$\n]+?)\$/g, (_, tex) => {
- try {
- return katex.renderToString(tex.trim(), {
- displayMode: false,
- throwOnError: false,
- strict: false,
- });
- } catch (e) {
- console.error('KaTeX render error:', e);
- return `<span class="text-red-500">$${tex}$</span>`;
- }
- });
- return result;
- },
- /**
- * 渲染指定元素内的所有数学公式
- */
- renderElement(element) {
- const mathElements = element.querySelectorAll('[data-math]');
- mathElements.forEach(el => {
- const rawText = el.getAttribute('data-math');
- if (rawText) {
- el.innerHTML = this.render(rawText);
- }
- });
- }
- };
- // 监听 Livewire 事件
- document.addEventListener('livewire:init', () => {
- Livewire.on('render-math', () => {
- setTimeout(() => {
- const previewArea = document.getElementById('web-preview-area');
- if (previewArea) {
- MathRenderer.renderElement(previewArea);
- }
- }, 100);
- });
- });
- // 页面加载完成后渲染
- document.addEventListener('DOMContentLoaded', () => {
- const previewArea = document.getElementById('web-preview-area');
- if (previewArea) {
- MathRenderer.renderElement(previewArea);
- }
- });
- </script>
- </body>
- </html>
|