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

## 概述

本系统为 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 资源

```bash
# 下载 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` 或主布局文件中添加：

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

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

## 使用方法

### 1. 基本用法 - Blade 组件

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

**参数：**
- `content`: 包含 LaTeX 公式的文本
- `class`: 可选的自定义 CSS 类
- `inline`: 是否为行内模式（默认 false）

### 2. 在表格中使用

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

### 3. 在 Livewire 组件中使用

```php
<?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');
    }
}
```

```blade
{{-- 在 Livewire 视图中 --}}
<div class="math-render">
    {{ $this->getMathContent($question['content']) }}
</div>
```

### 4. 使用自定义 Filament 字段

```php
<?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 格式

### 行内公式
```latex
已知函数 $f(x) = ax^2 + bx + c$

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

### 块级公式
```latex
计算定积分：
$$
\int_0^\infty e^{-x^2} dx = \frac{\sqrt{\pi}}{2}
$$

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

### 常用符号示例

```latex
分数：$\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. 手动触发渲染

```javascript
// 触发所有数学公式重新渲染
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. 监听渲染事件

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

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

### 3. 自定义配置

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

### 4. 错误处理

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

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

## API 参考

### MathRender.blade.php

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

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

### MathEditor 字段

**可用方法：**
- `columns(int $columns)`: 设置网格列数
- `helperText(string $text)`: 设置帮助文本

**示例：**
```php
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 事件，如果仍有问题：

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

### Q: 如何添加自定义宏

**A:** 在配置文件中添加：

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

### Q: 如何禁用自动初始化

**A:** 设置环境变量：

```env
KATEX_AUTO_INIT=false
```

或 JavaScript：

```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 许可证。

## 支持

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