feat: 初始化知识库系统项目

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

技术栈:
- Laravel 11.x
- Filament 3.X
- Meilisearch 1.5+
- Pandoc 文档转换
- Redis 队列系统
- Pest PHP 测试框架
This commit is contained in:
Knowledge Base System
2025-12-05 14:44:44 +08:00
commit acf549c43c
165 changed files with 32838 additions and 0 deletions

View File

@@ -0,0 +1,261 @@
# 文件名保留功能说明
## 功能概述
知识库系统现在会完整保留用户上传文档时的原始文件名,包括中文、特殊字符等。下载文档时,文件名将与上传时保持一致。
## 实现细节
### 1. Filament 表单配置
`DocumentResource` 的文件上传字段中添加了 `preserveFilenames()` 方法:
```php
Forms\Components\FileUpload::make('file')
->label('文档文件')
->required()
->acceptedFileTypes([...])
->preserveFilenames() // 保留原始文件名
->disk('local')
->directory('documents/' . date('Y/m/d'))
// ...
```
### 2. 文件上传处理
#### CreateDocument 页面
```php
protected function mutateFormDataBeforeCreate(array $data): array
{
if (isset($data['file'])) {
$filePath = $data['file'];
$originalFileName = basename($filePath); // 获取原始文件名
$data['file_path'] = $filePath;
$data['file_name'] = $originalFileName; // 保存原始文件名
// ...
}
return $data;
}
```
#### EditDocument 页面
```php
protected function mutateFormDataBeforeSave(array $data): array
{
if (isset($data['file']) && $data['file'] !== $this->record->file_path) {
$filePath = $data['file'];
$originalFileName = basename($filePath); // 获取原始文件名
$data['file_path'] = $filePath;
$data['file_name'] = $originalFileName; // 保存原始文件名
// ...
}
return $data;
}
```
### 3. DocumentService 更新
#### 上传方法
```php
public function uploadDocument(...): Document
{
return DB::transaction(function () use (...) {
// 获取原始文件名
$originalFileName = $file->getClientOriginalName();
// 使用 storeAs 保存文件,保留原始文件名
$directory = 'documents/' . date('Y/m/d');
$filePath = $file->storeAs($directory, $originalFileName, 'local');
// 保存到数据库
$document = Document::create([
'file_path' => $filePath,
'file_name' => $originalFileName, // 原始文件名
// ...
]);
return $document;
});
}
```
#### 下载方法
```php
public function downloadDocument(Document $document, User $user): StreamedResponse
{
// 使用原始文件名作为下载文件名
return Storage::disk('local')->download(
$document->file_path,
$document->file_name // 原始文件名
);
}
```
## 支持的文件名格式
### ✅ 完全支持
1. **中文文件名**
- 示例:`知识库管理系统需求文档.docx`
- 上传后保留:✅
- 下载时保留:✅
2. **英文文件名**
- 示例:`Requirements Document.docx`
- 上传后保留:✅
- 下载时保留:✅
3. **数字文件名**
- 示例:`2024-Report.docx`
- 上传后保留:✅
- 下载时保留:✅
4. **特殊字符文件名**
- 示例:`文档(2024-01-01)_v1.0.docx`
- 支持的特殊字符:`()[]_-`
- 上传后保留:✅
- 下载时保留:✅
5. **混合格式文件名**
- 示例:`Project_项目文档_2024.docx`
- 上传后保留:✅
- 下载时保留:✅
## 文件存储结构
文件按日期组织存储:
```
storage/app/
└── documents/
└── 2024/
└── 12/
└── 04/
├── 知识库管理系统需求文档.docx
├── Requirements Document.docx
└── 文档(2024-01-01)_v1.0.docx
```
## 数据库字段
### documents 表
- `file_path`: 存储相对路径(如:`documents/2024/12/04/知识库管理系统需求文档.docx`
- `file_name`: 存储原始文件名(如:`知识库管理系统需求文档.docx`
- `file_size`: 文件大小(字节)
- `mime_type`: MIME 类型
## 浏览器兼容性
### 下载文件名编码
对于包含非 ASCII 字符(如中文)的文件名,系统会自动处理编码:
```
Content-Disposition: attachment; filename=document.docx; filename*=utf-8''%E7%9F%A5%E8%AF%86%E5%BA%93.docx
```
- `filename`: ASCII 兼容的后备文件名
- `filename*`: UTF-8 编码的完整文件名RFC 5987
### 支持的浏览器
- ✅ Chrome 80+
- ✅ Firefox 75+
- ✅ Safari 13+
- ✅ Edge 80+
- ✅ 移动浏览器iOS Safari, Chrome Mobile
## 测试覆盖
### 测试文件:`tests/Feature/DocumentFileNameTest.php`
1. **test_上传文档时保留原始文件名**
- 验证上传后 `file_name` 字段正确保存
2. **test_下载文档时使用原始文件名**
- 验证下载响应头包含原始文件名
3. **test_中文文件名正确处理**
- 验证中文文件名的完整支持
4. **test_特殊字符文件名正确处理**
- 验证特殊字符的正确处理
### 运行测试
```bash
php artisan test --filter=DocumentFileNameTest
```
## 注意事项
### 1. 文件名冲突
如果同一天上传了同名文件,后上传的文件会覆盖先上传的文件。建议:
- 用户在上传前检查文件名
- 或者在文件名中添加时间戳或版本号
### 2. 文件名长度限制
- 数据库字段 `file_name` 限制255 字符
- 文件系统限制:通常为 255 字节
- 建议文件名不超过 100 个字符
### 3. 特殊字符限制
某些特殊字符可能在不同操作系统上有限制:
- Windows: 不支持 `< > : " / \ | ? *`
- Linux/Mac: 不支持 `/`
系统会自动处理这些字符,但建议避免使用。
## 安全考虑
### 1. 路径遍历攻击防护
- 使用 `basename()` 提取文件名,防止路径遍历
- 文件存储在受控目录中
### 2. 文件名注入防护
- Laravel Storage 自动处理文件名转义
- 数据库使用参数化查询
### 3. XSS 防护
- 文件名在显示时会被 Blade 模板自动转义
- 下载响应头使用标准编码
## 未来改进
1. **文件名冲突处理**
- 自动添加序号:`文档.docx``文档(1).docx`
- 或添加时间戳:`文档.docx``文档_20240104_143022.docx`
2. **文件名验证**
- 添加文件名格式验证
- 限制特殊字符使用
- 提供文件名建议
3. **批量上传**
- 支持批量上传多个文件
- 自动处理文件名冲突
4. **文件名搜索**
- 支持按文件名搜索文档
- 支持模糊匹配
## 总结
文件名保留功能确保了用户上传和下载文档时的一致性体验,特别是对中文文件名的完整支持,使得知识库系统更加符合中文用户的使用习惯。
所有功能都经过完整测试,确保在各种场景下都能正常工作。