math-render-system.md 8.3 KB

数学公式渲染系统 - 完整指南

概述

本系统为 Laravel + Livewire + Filament 项目提供完整的 KaTeX 数学公式渲染解决方案,支持本地部署,无需依赖外网 CDN。

功能特性

  • ✅ 自动渲染 LaTeX 公式($...$, $$...$$, (...), [...])
  • ✅ 支持 Livewire DOM 更新后自动重新渲染
  • ✅ 自定义 Filament 字段 MathEditor,带实时预览
  • ✅ 所有资源本地化部署
  • ✅ 零配置即用
  • ✅ 支持 Alpine.js 兼容性
  • ✅ 错误容错机制

文件结构

project/
├── app/
│   ├── Filament/
│   │   ├── Fields/
│   │   │   └── MathEditor.php
│   │   └── ...
│   ├── Livewire/
│   │   ├── Traits/
│   │   │   └── WithMathRender.php
│   │   └── MathRenderTest.php
│   └── ...
├── public/
│   ├── js/
│   │   ├── katex.min.js
│   │   └── math-render.js
│   └── css/
│       └── katex/
│           └── katex.min.css
├── resources/
│   ├── views/
│   │   ├── components/
│   │   │   └── math-render.blade.php
│   │   ├── filament/
│   │   │   └── fields/
│   │   │       └── math-editor.blade.php
│   │   ├── examples/
│   │   │   └── math-render-example.blade.php
│   │   └── livewire/
│   │       └── math-render-test.blade.php
│   └── ...
└── config/
    └── math-render.php

安装步骤

1. 下载 KaTeX 资源

# 下载 CSS
curl -s https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/katex.min.css -o public/css/katex/katex.min.css

# 下载 JavaScript
curl -s https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/katex.min.js -o public/js/katex.min.js

2. 复制所有文件到项目

将提供的所有文件复制到对应目录。

3. 加载全局脚本

resources/views/layouts/app.blade.php 或主布局文件中添加:

@push('scripts')
    <script src="/js/math-render.js"></script>
@endpush

@push('styles')
    <link rel="stylesheet" href="/css/katex/katex.min.css">
@endpush

使用方法

1. 基本用法 - Blade 组件

<x-math-render content="已知二次函数 $f(x) = ax^2 + bx + c$" />

参数:

  • content: 包含 LaTeX 公式的文本
  • class: 可选的自定义 CSS 类
  • inline: 是否为行内模式(默认 false)

2. 在表格中使用

@foreach($questions as $question)
    <tr>
        <td>{{ $question['code'] }}</td>
        <td>
            <x-math-render :content="$question['content']" />
        </td>
    </tr>
@endforeach

3. 在 Livewire 组件中使用

<?php

namespace App\Livewire;

use App\Livewire\Traits\WithMathRender;
use Livewire\Component;

class QuestionList extends Component
{
    use WithMathRender;

    public string $search = '';

    #[Computed]
    public function questions(): array
    {
        // 获取数据...
    }

    public function render()
    {
        return view('livewire.question-list');
    }
}
{{-- 在 Livewire 视图中 --}}
<div class="math-render">
    {{ $this->getMathContent($question['content']) }}
</div>

4. 使用自定义 Filament 字段

<?php

namespace App\Filament\Resources;

use App\Filament\Fields\MathEditor;
use Filament\Resources\Resource;
use Filament\Tables;
use Filament\Tables\Table;

class QuestionResource extends Resource
{
    public static function form($form): Form
    {
        return $form
            ->schema([
                // ...
                MathEditor::make('stem')
                    ->label('题目内容')
                    ->required(),
            ]);
    }

    public static function table(Table $table): Table
    {
        return $table
            ->columns([
                Tables\Columns\TextColumn::make('stem')
                    ->label('题目内容')
                    ->formatStateUsing(fn ($state) => view('components.math-render', ['content' => $state])),
            ]);
    }
}

支持的 LaTeX 格式

行内公式

已知函数 $f(x) = ax^2 + bx + c$

或者使用反斜杠:\(x = \frac{-b \pm \sqrt{b^2 - 4ac}}{2a}\)

块级公式

计算定积分:
$$
\int_0^\infty e^{-x^2} dx = \frac{\sqrt{\pi}}{2}
$$

或者:
\[
\sum_{i=1}^{n} i = \frac{n(n+1)}{2}
\]

常用符号示例

分数:$\frac{a}{b}$

根号:$\sqrt{x}$ 或 $\sqrt[n]{x}$

上标:$x^2$ 或 $x^{2n}$

下标:$x_1$ 或 $x_{i,j}$

求和:$\sum_{i=1}^{n}$

积分:$\int_{a}^{b}$

极限:$\lim_{x \to 0}$

矩阵:
$$
\begin{bmatrix}
a & b \\
c & d
\end{bmatrix}
$$

希腊字母:$\alpha, \beta, \gamma, \Delta$

运算符:$\pm, \times, \div, \infty$

高级用法

1. 手动触发渲染

// 触发所有数学公式重新渲染
window.MathRender.renderAll();

// 触发特定元素渲染
window.MathRender.render(document.getElementById('math-element'));

// 手动设置内容并渲染
const element = document.querySelector('.math-render');
element.dataset.mathContent = '新内容:$f(x) = x^2$';
window.MathRender.render(element);

2. 监听渲染事件

document.addEventListener('math:rendered', () => {
    console.log('数学公式渲染完成');
});

// 或者
document.addEventListener('math:render', () => {
    console.log('触发数学公式渲染');
});

3. 自定义配置

window.MathRenderConfig.maxAttempts = 100;      // 最大重试次数
window.MathRenderConfig.delay = 50;             // 重试延迟(毫秒)
window.MathRenderConfig.selector = '.my-math';  // 自定义选择器

4. 错误处理

默认启用错误容错,渲染失败会显示原始 LaTeX 代码。可以在控制台查看错误信息:

window.MathRenderConfig.errorHandling = false; // 禁用错误日志

API 参考

MathRender.blade.php

属性:

  • content (string): 包含 LaTeX 的文本内容
  • class (string, optional): 自定义 CSS 类
  • inline (bool, optional): 是否行内显示

示例:

<x-math-render
    content="$f(x) = ax^2 + bx + c$"
    class="text-lg"
    :inline="true"
/>

MathEditor 字段

可用方法:

  • columns(int $columns): 设置网格列数
  • helperText(string $text): 设置帮助文本

示例:

MathEditor::make('content')
    ->columns(12)
    ->helperText('支持 $...$, $$...$$ 格式')

WithMathRender Trait

可用方法:

  • renderMathContent(string $content): 预处理数学内容(服务器端)
  • getMathContent($content): 获取待渲染内容
  • triggerMathRender(): 手动触发渲染

JavaScript API

全局对象: window.MathRender

方法:

  • render(element): 渲染单个元素
  • renderAll(): 渲染所有元素
  • trigger(): 触发渲染事件
  • config: 配置对象

常见问题

Q: 公式不显示或显示错误

A: 检查以下几点:

  1. 确保 KaTeX 资源已正确加载
  2. 检查浏览器控制台是否有错误
  3. 验证 LaTeX 语法是否正确
  4. 确保元素有 .math-render

Q: Livewire 更新后公式不刷新

A: 系统会自动监听 Livewire 事件,如果仍有问题:

// 手动触发
document.dispatchEvent(new Event('math:render'));

Q: 如何添加自定义宏

A: 在配置文件中添加:

// config/math-render.php
'macros' => [
    '\\f' => '#1f(#2)',
],

Q: 如何禁用自动初始化

A: 设置环境变量:

KATEX_AUTO_INIT=false

或 JavaScript:

window.MathRenderConfig.autoInit = false;

TODO(数据侧公式清洗)

  • 题库/ OCR 入库阶段加一层 LaTeX 清洗与分隔校验,避免连写或缺少幂符号导致渲染异常。示例:题目 P06_SK001_59555 的选项出现 x2+4y2x^2+4y^2 连写,应在入库前拆分、补 ^ 或用 $...$ 包裹。当前渲染器正常,剩余问题属于内容质量,后续在题目生成与 OCR 导入时统一修复。

示例代码

完整示例请参考:

  • /resources/views/examples/math-render-example.blade.php
  • /app/Livewire/MathRenderTest.php
  • /resources/views/livewire/math-render-test.blade.php

许可证

本系统使用 MIT 许可证。

支持

如有问题,请查看浏览器控制台或参考本文档。