Files
KnowledgeBase/app/Observers/DocumentObserver.php
Knowledge Base System acf549c43c feat: 初始化知识库系统项目
- 实现基于 Laravel 11 和 Filament 3.X 的文档管理系统
- 添加用户认证和分组管理功能
- 实现文档上传、分类和权限控制
- 集成 Word 文档自动转换为 Markdown
- 集成 Meilisearch 全文搜索引擎
- 实现文档在线预览功能
- 添加安全日志和审计功能
- 完整的简体中文界面
- 包含完整的项目文档和部署指南

技术栈:
- Laravel 11.x
- Filament 3.X
- Meilisearch 1.5+
- Pandoc 文档转换
- Redis 队列系统
- Pest PHP 测试框架
2025-12-05 14:44:44 +08:00

136 lines
4.2 KiB
PHP
Raw Permalink 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.

<?php
namespace App\Observers;
use App\Models\Document;
use App\Services\DocumentSearchService;
/**
* 文档观察者
* 监听文档模型事件,自动管理 Meilisearch 索引
*/
class DocumentObserver
{
protected DocumentSearchService $searchService;
public function __construct(DocumentSearchService $searchService)
{
$this->searchService = $searchService;
}
/**
* 处理文档 "created" 事件
* 注意:文档创建时不立即索引,等待转换完成后再索引
*/
public function created(Document $document): void
{
// 文档创建时不立即索引,因为 Markdown 内容还未生成
// 索引将在转换完成后通过 updated 事件触发
}
/**
* 处理文档 "updated" 事件
* 当文档更新时,检查转换状态并更新索引
*/
public function updated(Document $document): void
{
// 检查转换状态是否变为 completed
if ($document->wasChanged('conversion_status') && $document->conversion_status === 'completed') {
// 转换完成,创建或更新索引
$this->searchService->indexDocument($document);
} elseif ($document->wasChanged(['title', 'description', 'markdown_path', 'type', 'group_id'])) {
// 其他重要字段更新时,也更新索引
$this->searchService->updateDocumentIndex($document);
}
}
/**
* 处理文档 "deleting" 事件
* 在删除前清理相关文件
*/
public function deleting(Document $document): void
{
$this->cleanupDocumentFiles($document);
}
/**
* 处理文档 "deleted" 事件
* 从 Meilisearch 中移除文档索引
*/
public function deleted(Document $document): void
{
$this->searchService->removeDocumentFromIndex($document);
}
/**
* 处理文档 "restored" 事件
* 恢复文档时重新索引
*/
public function restored(Document $document): void
{
if ($document->shouldBeSearchable()) {
$this->searchService->indexDocument($document);
}
}
/**
* 处理文档 "force deleting" 事件
* 在强制删除前清理相关文件
*/
public function forceDeleting(Document $document): void
{
$this->cleanupDocumentFiles($document);
}
/**
* 处理文档 "force deleted" 事件
* 强制删除时也要移除索引
*/
public function forceDeleted(Document $document): void
{
$this->searchService->removeDocumentFromIndex($document);
}
/**
* 清理文档相关的所有文件
* 包括原始文档文件、Markdown 文件和媒体文件
*
* @param Document $document
* @return void
*/
protected function cleanupDocumentFiles(Document $document): void
{
try {
// 删除原始文档文件
if ($document->file_path && \Storage::disk('local')->exists($document->file_path)) {
\Storage::disk('local')->delete($document->file_path);
\Log::info('已删除原始文档文件', [
'document_id' => $document->id,
'file_path' => $document->file_path,
]);
}
// 删除 Markdown 文件和整个文档目录(包括 media
if ($document->markdown_path) {
// 获取文档目录例如2025/12/04/{uuid}
$documentDir = dirname($document->markdown_path);
// 删除整个文档目录(包括 Markdown 文件和 media 目录)
if (\Storage::disk('markdown')->exists($documentDir)) {
\Storage::disk('markdown')->deleteDirectory($documentDir);
\Log::info('已删除文档目录', [
'document_id' => $document->id,
'directory' => $documentDir,
]);
}
}
} catch (\Exception $e) {
\Log::error('清理文档文件失败', [
'document_id' => $document->id,
'error' => $e->getMessage(),
]);
// 不抛出异常,避免影响删除操作
}
}
}