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,138 @@
# 代码仓库整理需求文档
## 简介
本文档定义了对现有知识库系统代码仓库进行整理和优化的需求。系统是一个基于 Laravel 11 和 Filament 3.X 构建的企业级文档管理平台,当前已实现核心功能,需要对代码结构、文档和配置进行系统性整理,以提高可维护性和可扩展性。
## 术语表
- **知识库系统Knowledge Base System**:本项目的主系统,用于管理和检索文档
- **代码仓库Code Repository**:存储项目源代码、配置和文档的 Git 仓库
- **目录结构Directory Structure**:项目文件和文件夹的组织方式
- **Laravel**PHP Web 应用框架
- **Filament**:基于 Laravel 的管理面板框架
- **Meilisearch**:全文搜索引擎
- **Composer**PHP 依赖管理工具
- **PSR-4**PHP 自动加载标准
## 需求
### 需求 1目录结构规范化
**用户故事**:作为开发者,我希望项目目录结构清晰规范,以便快速定位和理解代码组织方式。
#### 验收标准
1. WHEN 开发者查看项目根目录 THEN 系统 SHALL 提供清晰的目录结构文档说明每个主要目录的用途
2. WHEN 新文件需要添加到项目 THEN 系统 SHALL 提供明确的目录分类规则指导文件放置位置
3. WHEN 检查 app 目录 THEN 系统 SHALL 按照 Laravel 最佳实践组织所有应用代码
4. WHEN 检查服务类 THEN 系统 SHALL 将所有业务逻辑服务统一放置在 app/Services 目录
5. WHEN 检查测试文件 THEN 系统 SHALL 确保测试目录结构与源代码目录结构对应
### 需求 2文档完整性和一致性
**用户故事**:作为新加入的开发者,我希望有完整准确的文档,以便快速了解项目并开始贡献代码。
#### 验收标准
1. WHEN 开发者阅读 README.md THEN 系统 SHALL 提供项目概述、快速开始指南和核心功能说明
2. WHEN 开发者需要部署系统 THEN 系统 SHALL 提供详细的部署文档包含所有环境配置步骤
3. WHEN 开发者需要了解 API THEN 系统 SHALL 提供完整的 API 参考文档说明所有公共服务方法
4. WHEN 文档中引用配置项 THEN 系统 SHALL 确保配置项名称与实际代码一致
5. WHEN 文档描述功能特性 THEN 系统 SHALL 确保描述与当前实现的功能匹配
### 需求 3配置文件管理
**用户故事**:作为系统管理员,我希望配置文件清晰易懂,以便正确配置和部署系统。
#### 验收标准
1. WHEN 管理员查看 .env.example THEN 系统 SHALL 包含所有必需的配置项并提供清晰的注释说明
2. WHEN 配置文件包含敏感信息 THEN 系统 SHALL 确保这些文件在 .gitignore 中被正确排除
3. WHEN 系统使用自定义配置 THEN 系统 SHALL 在 config 目录中创建独立的配置文件
4. WHEN 配置项有默认值 THEN 系统 SHALL 在配置文件中明确标注默认值
5. WHEN 配置项之间有依赖关系 THEN 系统 SHALL 在注释中说明依赖关系
### 需求 4依赖管理规范
**用户故事**:作为开发者,我希望项目依赖清晰明确,以便正确安装和更新依赖包。
#### 验收标准
1. WHEN 检查 composer.json THEN 系统 SHALL 明确区分生产依赖和开发依赖
2. WHEN 检查 package.json THEN 系统 SHALL 列出所有前端依赖及其用途
3. WHEN 添加新依赖 THEN 系统 SHALL 在文档中说明该依赖的作用和必要性
4. WHEN 依赖包有版本要求 THEN 系统 SHALL 使用语义化版本约束
5. WHEN 系统依赖外部服务 THEN 系统 SHALL 在文档中明确说明外部服务的版本要求
### 需求 5代码组织和命名规范
**用户故事**:作为开发者,我希望代码遵循一致的命名和组织规范,以便提高代码可读性和可维护性。
#### 验收标准
1. WHEN 创建新的服务类 THEN 系统 SHALL 使用 Service 后缀并放置在 app/Services 目录
2. WHEN 创建新的策略类 THEN 系统 SHALL 使用 Policy 后缀并放置在 app/Policies 目录
3. WHEN 创建新的观察者类 THEN 系统 SHALL 使用 Observer 后缀并放置在 app/Observers 目录
4. WHEN 创建新的任务类 THEN 系统 SHALL 放置在 app/Jobs 目录并实现 ShouldQueue 接口
5. WHEN 命名类和方法 THEN 系统 SHALL 遵循 PSR-12 编码规范
### 需求 6测试文件组织
**用户故事**:作为开发者,我希望测试文件组织清晰,以便快速找到和运行相关测试。
#### 验收标准
1. WHEN 检查测试目录 THEN 系统 SHALL 将单元测试放置在 tests/Unit 目录
2. WHEN 检查测试目录 THEN 系统 SHALL 将功能测试放置在 tests/Feature 目录
3. WHEN 测试需要测试数据 THEN 系统 SHALL 将测试固件放置在 tests/fixtures 目录
4. WHEN 测试文件命名 THEN 系统 SHALL 使用 Test 后缀并与被测试的类名对应
5. WHEN 运行测试 THEN 系统 SHALL 提供清晰的测试输出显示通过和失败的测试
### 需求 7版本控制和忽略规则
**用户故事**:作为开发者,我希望版本控制配置合理,以便只跟踪必要的文件。
#### 验收标准
1. WHEN 检查 .gitignore THEN 系统 SHALL 排除所有生成的文件和目录
2. WHEN 检查 .gitignore THEN 系统 SHALL 排除所有包含敏感信息的文件
3. WHEN 检查 .gitignore THEN 系统 SHALL 排除所有依赖包目录
4. WHEN 检查 .gitignore THEN 系统 SHALL 排除所有 IDE 特定的配置文件
5. WHEN 检查 .gitignore THEN 系统 SHALL 保留必要的示例配置文件
### 需求 8脚本和自动化工具
**用户故事**:作为开发者,我希望有便捷的脚本工具,以便快速执行常见任务。
#### 验收标准
1. WHEN 需要启动开发环境 THEN 系统 SHALL 提供一键启动脚本
2. WHEN 需要运行测试 THEN 系统 SHALL 在 composer.json 中定义测试脚本
3. WHEN 需要代码格式化 THEN 系统 SHALL 提供格式化脚本使用 Laravel Pint
4. WHEN 需要验证安装 THEN 系统 SHALL 提供验证脚本检查所有依赖和配置
5. WHEN 脚本执行失败 THEN 系统 SHALL 提供清晰的错误信息和解决建议
### 需求 9存储目录结构
**用户故事**:作为系统管理员,我希望存储目录结构清晰,以便管理上传的文件和生成的内容。
#### 验收标准
1. WHEN 文档上传 THEN 系统 SHALL 将原始文档存储在 storage/app/private/documents 目录按日期分层
2. WHEN 文档转换完成 THEN 系统 SHALL 将 Markdown 文件存储在 storage/app/private/markdown 目录按日期分层
3. WHEN 检查存储目录 THEN 系统 SHALL 在每个存储子目录中包含 .gitignore 文件
4. WHEN 系统需要临时文件 THEN 系统 SHALL 使用 storage/app/temp 目录并定期清理
5. WHEN 检查存储权限 THEN 系统 SHALL 确保 storage 目录及其子目录具有正确的写入权限
### 需求 10规格文档管理
**用户故事**:作为项目经理,我希望功能规格文档组织良好,以便跟踪功能开发进度。
#### 验收标准
1. WHEN 检查规格目录 THEN 系统 SHALL 将所有功能规格放置在 .kiro/specs 目录
2. WHEN 创建新功能规格 THEN 系统 SHALL 为每个功能创建独立的子目录
3. WHEN 功能规格包含多个文档 THEN 系统 SHALL 包含 requirements.md、design.md 和 tasks.md
4. WHEN 规格文档更新 THEN 系统 SHALL 确保文档之间的引用保持一致
5. WHEN 功能开发完成 THEN 系统 SHALL 在规格文档中标记完成状态

View File

@@ -0,0 +1,993 @@
# 设计文档
## 概述
知识库系统是一个基于 Laravel Filament 3.X 构建的文档管理平台。系统采用 Laravel 的 MVC 架构模式,利用 Filament 的管理面板功能提供直观的中文用户界面。核心功能包括文档上传、分类管理、基于分组的权限控制、文档格式转换和全文搜索。
系统使用 Laravel 的 Eloquent ORM 进行数据库操作,利用 Filament 的资源Resources和表单构建器创建管理界面通过策略Policies和作用域Scopes实现细粒度的权限控制。文档上传后自动转换为 Markdown 格式,并通过 Meilisearch 搜索引擎实现快速的全文搜索功能。用户可以在线预览 Markdown 渲染内容,也可以下载原始 Word 文档。
## 架构
### 技术栈
- **后端框架**: Laravel 10.x/11.x
- **管理面板**: Filament 3.X
- **数据库**: MySQL 8.0+ / PostgreSQL 13+
- **文件存储**: Laravel Storage (支持本地和云存储)
- **认证**: Laravel Breeze/Jetstream + Filament Auth
- **搜索引擎**: Meilisearch 1.5+
- **文档转换**: Pandoc 或 PHPWord
- **Markdown 渲染**: CommonMark PHP 或 Laravel Markdown
- **队列系统**: Redis Queue (用于异步文档转换)
### 架构模式
系统采用分层架构:
```
┌─────────────────────────────────────┐
│ Filament UI Layer (视图层) │
│ - Resources │
│ - Forms & Tables │
│ - Actions & Filters │
└─────────────────────────────────────┘
┌─────────────────────────────────────┐
│ Application Layer (应用层) │
│ - Controllers │
│ - Policies │
│ - Form Requests │
└─────────────────────────────────────┘
┌─────────────────────────────────────┐
│ Domain Layer (领域层) │
│ - Models │
│ - Services │
│ - Repositories (可选) │
└─────────────────────────────────────┘
┌─────────────────────────────────────┐
│ Infrastructure Layer (基础设施层) │
│ - Database │
│ - File Storage │
│ - Cache │
└─────────────────────────────────────┘
```
## 组件和接口
### 核心模型
#### User (用户模型)
```php
class User extends Authenticatable
{
// 关联关系
public function groups(): BelongsToMany;
public function uploadedDocuments(): HasMany;
public function downloadLogs(): HasMany;
}
```
#### Group (分组模型)
```php
class Group extends Model
{
// 关联关系
public function users(): BelongsToMany;
public function documents(): HasMany;
}
```
#### Document (文档模型)
```php
class Document extends Model
{
use Searchable; // Laravel Scout trait for Meilisearch
// 属性
protected $fillable = [
'title',
'file_path',
'file_name',
'file_size',
'mime_type',
'type', // 'global' 或 'dedicated'
'group_id',
'uploaded_by',
'description',
'markdown_path', // Markdown 文件路径
'markdown_preview', // Markdown 内容摘要
'conversion_status' // 'pending', 'processing', 'completed', 'failed'
];
// 关联关系
public function group(): BelongsTo;
public function uploader(): BelongsTo;
public function downloadLogs(): HasMany;
// 作用域
public function scopeAccessibleBy(Builder $query, User $user): Builder;
public function scopeGlobal(Builder $query): Builder;
public function scopeDedicated(Builder $query): Builder;
// Meilisearch 配置
public function toSearchableArray(): array;
public function shouldBeSearchable(): bool;
// 辅助方法
public function getMarkdownContent(): ?string; // 从文件读取完整 Markdown 内容
public function hasMarkdown(): bool; // 检查是否已转换
}
```
#### DownloadLog (下载日志模型)
```php
class DownloadLog extends Model
{
protected $fillable = [
'document_id',
'user_id',
'downloaded_at',
'ip_address'
];
public function document(): BelongsTo;
public function user(): BelongsTo;
}
```
### Filament 资源
#### DocumentResource
负责文档的 CRUD 操作界面:
- 列表页:显示文档列表,支持搜索和筛选
- 创建页:上传文档并设置分类
- 编辑页:修改文档信息和分类
- 查看页:查看文档详情和下载
#### GroupResource
负责分组管理界面:
- 列表页:显示所有分组
- 创建页:创建新分组
- 编辑页:编辑分组信息和成员
- 关系管理器:管理分组成员和文档
#### UserResource
负责用户管理界面:
- 列表页:显示所有用户
- 编辑页:编辑用户信息和分组归属
- 关系管理器:管理用户的分组关系
### 服务类
#### DocumentService
```php
class DocumentService
{
public function uploadDocument(
UploadedFile $file,
string $title,
string $type,
?int $groupId,
int $uploaderId
): Document;
public function validateDocumentAccess(Document $document, User $user): bool;
public function downloadDocument(Document $document, User $user): StreamedResponse;
public function logDownload(Document $document, User $user): void;
}
```
#### DocumentConversionService
```php
class DocumentConversionService
{
public function convertToMarkdown(Document $document): string;
public function queueConversion(Document $document): void;
public function saveMarkdownToFile(Document $document, string $markdown): string; // 返回文件路径
public function updateDocumentMarkdown(Document $document, string $markdownPath): void;
public function handleConversionFailure(Document $document, Exception $e): void;
public function getMarkdownPreview(string $markdown, int $length = 500): string;
}
```
#### DocumentSearchService
```php
class DocumentSearchService
{
public function search(string $query, User $user, array $filters = []): Collection;
public function indexDocument(Document $document): void; // 读取 Markdown 文件并索引
public function updateDocumentIndex(Document $document): void;
public function removeDocumentFromIndex(Document $document): void;
public function filterByUserPermissions(Collection $results, User $user): Collection;
public function prepareSearchableData(Document $document): array; // 准备索引数据,包含完整 Markdown 内容
}
```
#### MarkdownRenderService
```php
class MarkdownRenderService
{
public function render(string $markdown): string;
public function sanitize(string $html): string;
public function extractPreview(string $markdown, int $length = 200): string;
}
```
### 策略类
#### DocumentPolicy
```php
class DocumentPolicy
{
public function viewAny(User $user): bool;
public function view(User $user, Document $document): bool;
public function create(User $user): bool;
public function update(User $user, Document $document): bool;
public function delete(User $user, Document $document): bool;
public function download(User $user, Document $document): bool;
}
```
## 数据模型
### 数据库表结构
#### users 表
```sql
- id: bigint (主键)
- name: varchar(255)
- email: varchar(255) (唯一)
- password: varchar(255)
- created_at: timestamp
- updated_at: timestamp
```
#### groups 表
```sql
- id: bigint (主键)
- name: varchar(255)
- description: text (可空)
- created_at: timestamp
- updated_at: timestamp
```
#### group_user 表 (多对多中间表)
```sql
- id: bigint (主键)
- group_id: bigint (外键)
- user_id: bigint (外键)
- created_at: timestamp
- updated_at: timestamp
- 唯一索引: (group_id, user_id)
```
#### documents 表
```sql
- id: bigint (主键)
- title: varchar(255)
- description: text (可空)
- file_path: varchar(500) -- 原始 Word 文档路径
- file_name: varchar(255)
- file_size: bigint
- mime_type: varchar(100)
- type: enum('global', 'dedicated')
- group_id: bigint (外键, 可空)
- uploaded_by: bigint (外键)
- markdown_path: varchar(500) (可空) -- Markdown 文件存储路径
- markdown_preview: text (可空) -- Markdown 内容摘要(前 500 字符),用于快速预览
- conversion_status: enum('pending', 'processing', 'completed', 'failed') -- 转换状态
- conversion_error: text (可空) -- 转换失败时的错误信息
- created_at: timestamp
- updated_at: timestamp
- 索引: type, group_id, uploaded_by, conversion_status
```
**存储策略说明**
- 原始 Word 文档存储在 `storage/app/private/documents/` 目录
- 转换后的 Markdown 文件存储在 `storage/app/private/markdown/` 目录
- 数据库中只保存文件路径和内容摘要
- Meilisearch 索引包含完整的 Markdown 内容用于搜索
- 这种设计减少数据库体积,同时保持搜索性能
#### download_logs 表
```sql
- id: bigint (主键)
- document_id: bigint (外键)
- user_id: bigint (外键)
- ip_address: varchar(45)
- downloaded_at: timestamp
- 索引: document_id, user_id, downloaded_at
```
### 实体关系图
```mermaid
erDiagram
User ||--o{ Document : uploads
User }o--o{ Group : belongs_to
Group ||--o{ Document : owns
Document ||--o{ DownloadLog : has
User ||--o{ DownloadLog : creates
User {
bigint id PK
string name
string email UK
string password
timestamp created_at
timestamp updated_at
}
Group {
bigint id PK
string name
text description
timestamp created_at
timestamp updated_at
}
Document {
bigint id PK
string title
text description
string file_path
string file_name
bigint file_size
string mime_type
enum type
bigint group_id FK
bigint uploaded_by FK
timestamp created_at
timestamp updated_at
}
DownloadLog {
bigint id PK
bigint document_id FK
bigint user_id FK
string ip_address
timestamp downloaded_at
}
```
## 正确性属性
*属性是指在系统的所有有效执行中都应该成立的特征或行为——本质上是关于系统应该做什么的正式声明。属性作为人类可读规范和机器可验证正确性保证之间的桥梁。*
基于需求文档中的验收标准,我们识别出以下可测试的正确性属性:
### 属性 1文件格式验证
*对于任何*上传的文件,系统应该正确识别其是否为有效的 Word 文档格式(.doc 或 .docx并且只接受有效格式的文件
**验证需求1.1, 1.4**
### 属性 2文档存储完整性
*对于任何*成功上传的文档系统应该将文件存储到指定位置并在数据库中记录完整的元数据标题、文件路径、文件大小、MIME 类型、上传者等)
**验证需求1.2**
### 属性 3上传事务一致性
*对于任何*文档上传操作,如果过程中发生错误,系统应该回滚所有更改,确保数据库记录和文件系统保持一致状态
**验证需求1.5**
### 属性 4专用文档必须关联分组
*对于任何*类型为"专用知识库"的文档,系统应该要求并验证其关联了有效的分组 ID
**验证需求2.2**
### 属性 5全局文档对所有用户可见
*对于任何*全局知识库文档和任何已认证用户,该用户应该能够查看和访问该文档
**验证需求2.3**
### 属性 6文档分类持久化
*对于任何*文档,当其分类信息(类型和分组)被保存后,从数据库查询应该返回相同的分类信息
**验证需求2.4**
### 属性 7用户文档列表权限过滤
*对于任何*用户,当查询其可访问的文档列表时,返回的结果应该只包含:(1) 所有全局知识库文档,以及 (2) 该用户所属分组的专用知识库文档
**验证需求3.1, 3.2, 3.3**
### 属性 8其他分组文档隔离
*对于任何*用户和任何不属于该用户分组的专用知识库文档,该文档不应该出现在用户的可访问文档列表中
**验证需求3.4**
### 属性 9有权限文档可下载
*对于任何*用户和该用户有权限访问的文档,系统应该允许用户成功下载该文档
**验证需求4.1**
### 属性 10无权限文档访问拒绝
*对于任何*用户和该用户无权限访问的文档(其他分组的专用文档),系统应该拒绝访问请求
**验证需求4.2**
### 属性 11下载日志记录
*对于任何*文档下载操作,系统应该在 download_logs 表中创建一条记录,包含文档 ID、用户 ID、下载时间和 IP 地址
**验证需求4.3**
### 属性 12文档下载往返一致性
*对于任何*上传的文档,下载后的文件内容应该与原始上传的文件内容完全一致
**验证需求4.4**
### 属性 13分组数据持久化
*对于任何*新创建的分组,系统应该在数据库中保存分组名称和描述信息,并且查询应该返回相同的数据
**验证需求5.1**
### 属性 14用户分组关联
*对于任何*用户和分组,当用户被分配到该分组时,系统应该在 group_user 表中创建关联记录
**验证需求5.2**
### 属性 15分组分配授予权限
*对于任何*用户,当该用户被分配到某个分组后,该用户应该能够访问该分组的所有专用知识库文档
**验证需求5.3**
### 属性 16分组移除撤销权限
*对于任何*用户,当该用户从某个分组中移除后,该用户应该无法再访问该分组的专用知识库文档
**验证需求5.4**
### 属性 17分组删除级联处理
*对于任何*分组,当该分组被删除时,系统应该正确处理该分组的专用文档(设置为孤立状态或重新分配)
**验证需求5.5**
### 属性 18关键词搜索匹配
*对于任何*搜索关键词,系统返回的文档列表应该只包含标题或描述中包含该关键词的文档
**验证需求6.1**
### 属性 19分类筛选准确性
*对于任何*选定的文档分类(全局或专用),系统返回的文档列表应该只包含该分类的文档
**验证需求6.2**
### 属性 20分组筛选准确性
*对于任何*选定的分组,系统返回的文档列表应该只包含属于该分组的专用文档
**验证需求6.3**
### 属性 21组合筛选交集
*对于任何*多个筛选条件的组合(如分类 + 分组 + 关键词),系统返回的文档应该同时满足所有筛选条件
**验证需求6.5**
### 属性 22权限检查验证用户和分组
*对于任何*文档访问请求,系统应该验证请求用户的身份和该用户的分组归属
**验证需求7.1**
### 属性 23数据返回前权限验证
*对于任何*文档查询操作,系统应该在返回数据前执行权限检查,确保用户有权访问
**验证需求7.2**
### 属性 24未授权访问日志记录
*对于任何*权限验证失败的访问尝试,系统应该在安全日志中记录该事件
**验证需求7.3**
### 属性 25查询结果数据隔离
*对于任何*用户的文档查询,返回的结果集应该只包含该用户有权访问的文档,不包含其他用户的私有数据
**验证需求7.4**
### 属性 26错误消息中文化
*对于任何*系统操作产生的错误或成功消息,消息文本应该使用简体中文
**验证需求8.3**
### 属性 27日期格式中文化
*对于任何*需要显示的日期时间值,系统应该使用中文日期格式进行格式化
**验证需求8.5**
### 属性 28文档上传触发转换
*对于任何*成功上传的 Word 文档,系统应该自动触发 Markdown 转换流程
**验证需求9.1**
### 属性 29Markdown 内容持久化
*对于任何*转换完成的文档,系统应该将 Markdown 内容正确存储到文件系统,并在数据库中记录文件路径和内容摘要,读取文件应该返回相同的内容
**验证需求9.2**
### 属性 30转换失败不影响文档可用性
*对于任何*转换失败的文档,系统应该记录错误信息,但文档记录应该保持有效状态,用户仍然可以下载原始文件
**验证需求9.3**
### 属性 31原始文档保留
*对于任何*转换成功的文档,原始 Word 文件应该仍然存在于文件系统中,并且可以被下载
**验证需求9.4**
### 属性 32文档更新重新转换
*对于任何*已存在的文档,当其被更新或重新上传时,系统应该重新执行转换流程,并且新的 Markdown 内容应该替换旧内容
**验证需求9.5**
### 属性 33搜索匹配 Markdown 内容
*对于任何*包含特定关键词的文档 Markdown 内容,使用该关键词搜索应该返回该文档(假设用户有权限)
**验证需求10.1**
### 属性 34搜索覆盖多个字段
*对于任何*关键词,如果该关键词出现在文档的标题、描述或 Markdown 内容中的任何一个字段,搜索应该返回该文档
**验证需求10.2**
### 属性 35搜索结果权限过滤
*对于任何*搜索查询和用户,返回的搜索结果应该只包含该用户有权限访问的文档(全局文档和用户分组的专用文档)
**验证需求10.3**
### 属性 36搜索结果包含必需信息
*对于任何*搜索结果项,应该包含文档标题、内容片段、文档类型和上传时间等信息
**验证需求10.4**
### 属性 37有权限文档可预览
*对于任何*用户有权限访问的文档,该用户应该能够获取该文档的 Markdown 渲染后的 HTML 内容
**验证需求11.1**
### 属性 38Markdown 渲染正确性
*对于任何*包含标准 Markdown 元素(标题、列表、表格等)的 Markdown 内容,渲染后的 HTML 应该正确表示这些元素
**验证需求11.2**
### 属性 39无权限文档预览拒绝
*对于任何*用户无权限访问的文档,该用户尝试预览时应该被拒绝访问
**验证需求11.3**
### 属性 40转换完成触发索引
*对于任何*Markdown 转换完成的文档,系统应该自动将该文档索引到 Meilisearch
**验证需求12.1**
### 属性 41索引数据完整性
*对于任何*索引到 Meilisearch 的文档,索引数据应该包含文档 ID、标题、描述、Markdown 内容、类型和分组 ID
**验证需求12.2**
### 属性 42文档更新同步索引
*对于任何*已索引的文档当文档被更新时Meilisearch 中的索引数据应该同步更新
**验证需求12.3**
### 属性 43文档删除移除索引
*对于任何*已索引的文档,当文档被删除时,该文档应该从 Meilisearch 索引中移除
**验证需求12.4**
### 属性 44索引失败不影响文档保存
*对于任何*文档,即使 Meilisearch 索引操作失败,文档仍应该成功保存到数据库,并且可以正常使用
**验证需求12.5**
## 错误处理
### 文件上传错误
- **无效文件格式**: 返回 422 状态码,提示"文件格式不支持,请上传 Word 文档(.doc 或 .docx"
- **文件过大**: 返回 413 状态码,提示"文件大小超过限制(最大 XX MB"
- **存储失败**: 返回 500 状态码,提示"文件上传失败,请稍后重试",并回滚数据库操作
### 权限错误
- **未认证访问**: 返回 401 状态码,重定向到登录页面
- **无权限访问**: 返回 403 状态码,提示"您没有权限访问此文档"
- **文档不存在**: 返回 404 状态码,提示"文档不存在或已被删除"
### 数据验证错误
- **必填字段缺失**: 返回 422 状态码,提示具体缺失的字段
- **专用文档未指定分组**: 返回 422 状态码,提示"专用知识库文档必须指定所属分组"
- **无效的分组 ID**: 返回 422 状态码,提示"指定的分组不存在"
### 数据库错误
- **外键约束失败**: 返回 500 状态码,记录错误日志,提示"操作失败,请联系管理员"
- **唯一约束冲突**: 返回 422 状态码,提示"该记录已存在"
- **连接超时**: 返回 503 状态码,提示"服务暂时不可用,请稍后重试"
### 文档转换错误
- **转换工具不可用**: 返回 500 状态码,记录错误日志,文档状态设置为 'failed'
- **Word 文档损坏**: 返回 422 状态码,提示"文档文件损坏,无法转换"
- **转换超时**: 记录错误日志,文档状态设置为 'failed',提示"文档转换超时,请稍后重试"
- **Markdown 内容过大**: 记录警告日志,截断内容或使用外部存储
### 搜索相关错误
- **Meilisearch 服务不可用**: 返回 503 状态码,提示"搜索服务暂时不可用,请稍后重试"
- **搜索查询语法错误**: 返回 400 状态码,提示"搜索关键词格式不正确"
- **索引操作失败**: 记录错误日志,不影响文档的正常保存和使用
- **搜索超时**: 返回 504 状态码,提示"搜索请求超时,请简化搜索条件"
### 预览相关错误
- **Markdown 内容为空**: 返回 200 状态码,显示提示信息和下载按钮
- **Markdown 渲染失败**: 返回 500 状态码,提示"内容渲染失败,请下载原始文档"
- **预览权限不足**: 返回 403 状态码,提示"您没有权限预览此文档"
### 错误处理策略
1. **用户友好的错误消息**: 所有错误消息使用简体中文,避免技术术语
2. **详细的日志记录**: 在服务器端记录完整的错误堆栈和上下文信息
3. **事务回滚**: 对于涉及多个操作的流程,确保失败时完全回滚
4. **安全考虑**: 不在错误消息中暴露敏感信息(如数据库结构、文件路径等)
5. **优雅降级**: 转换或搜索功能失败时,不影响文档的基本上传和下载功能
6. **异步重试**: 对于转换和索引失败的文档,支持后台重试机制
## 测试策略
### 单元测试
使用 PHPUnit 进行单元测试,覆盖以下组件:
1. **模型测试**
- 测试模型关联关系是否正确定义
- 测试作用域Scopes逻辑
- 测试模型验证规则
2. **服务类测试**
- 测试 DocumentService 的文档上传逻辑
- 测试权限验证逻辑
- 测试文件存储和检索
3. **策略测试**
- 测试 DocumentPolicy 的各种权限判断
- 测试边缘情况(如文档无分组、用户无分组等)
4. **表单请求测试**
- 测试验证规则是否正确
- 测试自定义验证逻辑
### 属性基础测试Property-Based Testing
使用 **Pest PHP** 的属性测试功能进行属性基础测试。每个属性测试应该:
- 配置为运行至少 **100 次迭代**
- 使用注释明确标注对应的设计文档中的正确性属性
- 标注格式:`// Feature: knowledge-base-system, Property X: [属性描述]`
- 每个正确性属性对应一个独立的属性测试
属性测试覆盖范围:
1. **文件格式验证属性**(属性 1
2. **文档存储完整性属性**(属性 2
3. **事务一致性属性**(属性 3
4. **权限过滤属性**(属性 7, 8
5. **往返一致性属性**(属性 12
6. **权限授予和撤销属性**(属性 15, 16
7. **搜索和筛选属性**(属性 18-21
8. **数据隔离属性**(属性 25
9. **文档转换属性**(属性 28-32
10. **全文搜索属性**(属性 33-36
11. **Markdown 预览属性**(属性 37-39
12. **Meilisearch 索引属性**(属性 40-44
### 功能测试
使用 Laravel 的功能测试框架测试完整的用户流程:
1. **文档上传流程**
- 管理员上传全局文档
- 管理员上传专用文档并指定分组
- 上传无效格式文件被拒绝
2. **权限控制流程**
- 用户查看自己分组的专用文档
- 用户无法查看其他分组的专用文档
- 用户可以查看所有全局文档
3. **分组管理流程**
- 创建分组并分配用户
- 用户从分组移除后失去权限
- 删除分组后文档状态正确处理
4. **搜索和筛选流程**
- 按关键词搜索文档
- 按分类筛选文档
- 组合多个筛选条件
5. **文档转换流程**
- 上传 Word 文档后自动触发转换
- 转换完成后 Markdown 内容正确存储
- 转换失败时文档仍然可用
- 更新文档时重新转换
6. **全文搜索流程**
- 搜索 Markdown 内容中的关键词
- 搜索结果遵循权限控制
- 搜索结果包含内容片段
- 空搜索关键词的处理
7. **文档预览流程**
- 有权限用户可以预览 Markdown 内容
- 无权限用户无法预览
- Markdown 正确渲染为 HTML
- 预览页面提供下载按钮
8. **Meilisearch 索引流程**
- 文档转换后自动索引
- 文档更新时同步索引
- 文档删除时移除索引
- 索引失败不影响文档保存
### 测试数据生成
使用 Laravel Factories 生成测试数据:
```php
// UserFactory - 生成随机用户
// GroupFactory - 生成随机分组
// DocumentFactory - 生成随机文档(包括全局和专用)
// 使用 Faker 生成随机的中文文本
```
### 测试覆盖率目标
- 代码覆盖率:≥ 80%
- 关键业务逻辑覆盖率:≥ 95%
- 所有正确性属性都有对应的属性测试
### 持续集成
- 在 CI/CD 管道中自动运行所有测试
- 测试失败时阻止代码合并
- 生成测试覆盖率报告
## 性能考虑
### 数据库优化
1. **索引策略**
- documents 表:在 type, group_id, uploaded_by 字段上创建索引
- download_logs 表:在 document_id, user_id, downloaded_at 上创建索引
- 在 group_user 表的 (group_id, user_id) 上创建唯一复合索引
2. **查询优化**
- 使用 Eager Loading 避免 N+1 查询问题
- 对文档列表查询使用分页
- 使用数据库视图或查询作用域简化复杂权限查询
3. **缓存策略**
- 缓存用户的分组信息TTL: 1小时
- 缓存文档元数据TTL: 30分钟
- 使用 Redis 存储会话和缓存数据
### 文件存储优化
1. **存储策略**
- 使用 Laravel Storage 抽象层,支持本地和云存储切换
- 按日期组织文件目录结构:`documents/YYYY/MM/DD/``markdown/YYYY/MM/DD/`
- 使用 UUID 作为文件名避免冲突
- Markdown 文件单独存储,便于管理和备份
- 数据库中保存 Markdown 摘要500 字符)用于快速预览
2. **大文件处理**
- 配置合理的上传大小限制(建议 50MB
- 使用流式下载避免内存溢出
- 使用队列异步处理文档转换
- 大 Markdown 文件(> 1MB分块读取和索引
3. **缓存策略**
- 缓存已读取的 Markdown 内容TTL: 1小时
- 缓存渲染后的 HTMLTTL: 30分钟
- 使用 Redis 存储热门文档的 Markdown 内容
### 并发控制
- 使用数据库事务确保数据一致性
- 对关键操作使用乐观锁或悲观锁
- 使用队列处理耗时操作(如文件处理、日志记录)
## 安全考虑
### 认证和授权
1. **认证机制**
- 使用 Laravel Sanctum 或 Jetstream 提供认证
- 实施会话超时机制
- 支持记住我功能
2. **授权机制**
- 使用 Laravel Policy 实现细粒度权限控制
- 在控制器和 Filament 资源中强制执行策略
- 使用 Gate 定义全局权限规则
### 数据安全
1. **文件安全**
- 文件存储在非公开目录
- 通过控制器验证权限后提供文件下载
- 验证文件 MIME 类型,防止恶意文件上传
2. **SQL 注入防护**
- 使用 Eloquent ORM 和参数化查询
- 避免使用原始 SQL 查询
- 对用户输入进行验证和清理
3. **XSS 防护**
- 使用 Blade 模板引擎自动转义输出
- 对富文本内容使用 HTML Purifier
- 设置适当的 Content Security Policy
### 审计日志
1. **操作日志**
- 记录所有文档的创建、修改、删除操作
- 记录用户的登录、登出活动
- 记录权限变更操作
2. **安全日志**
- 记录所有权限验证失败的尝试
- 记录异常的访问模式
- 定期审查安全日志
## 部署和配置
### 环境要求
- PHP 8.1+
- MySQL 8.0+ 或 PostgreSQL 13+
- Redis 6.0+(用于缓存和队列)
- Composer 2.x
- Node.js 18+ 和 npm用于前端资源编译
- Meilisearch 1.5+(搜索引擎服务)
- Pandoc 2.x+(用于文档转换,可选)或 PHPWord 库
### Filament 配置
1. **中文化配置**
```php
// config/app.php
'locale' => 'zh_CN',
'fallback_locale' => 'zh_CN',
// 安装 Filament 中文语言包
composer require filament/filament-zh-cn
```
2. **面板配置**
```php
// app/Providers/Filament/AdminPanelProvider.php
public function panel(Panel $panel): Panel
{
return $panel
->default()
->id('admin')
->path('admin')
->login()
->colors([
'primary' => Color::Blue,
])
->discoverResources(in: app_path('Filament/Resources'), for: 'App\\Filament\\Resources')
->discoverPages(in: app_path('Filament/Pages'), for: 'App\\Filament\\Pages')
->pages([])
->discoverWidgets(in: app_path('Filament/Widgets'), for: 'App\\Filament\\Widgets')
->widgets([])
->middleware([
EncryptCookies::class,
AddQueuedCookiesToResponse::class,
StartSession::class,
AuthenticateSession::class,
ShareErrorsFromSession::class,
VerifyCsrfToken::class,
SubstituteBindings::class,
DisableBladeIconComponents::class,
DispatchServingFilamentEvent::class,
])
->authMiddleware([
Authenticate::class,
]);
}
```
### 文件存储配置
```php
// config/filesystems.php
'disks' => [
'documents' => [
'driver' => 'local',
'root' => storage_path('app/private/documents'),
'visibility' => 'private',
],
'markdown' => [
'driver' => 'local',
'root' => storage_path('app/private/markdown'),
'visibility' => 'private',
],
],
```
**文件组织结构**
```
storage/app/private/
├── documents/ # 原始 Word 文档
│ └── YYYY/MM/DD/
│ └── {uuid}.docx
└── markdown/ # 转换后的 Markdown 文件
└── YYYY/MM/DD/
└── {uuid}.md
```
### 队列配置
```php
// .env
QUEUE_CONNECTION=redis
// 启动队列工作进程
php artisan queue:work --queue=default,documents
```
### Meilisearch 配置
```php
// .env
MEILISEARCH_HOST=http://127.0.0.1:7700
MEILISEARCH_KEY=your-master-key
SCOUT_DRIVER=meilisearch
// config/scout.php
'meilisearch' => [
'host' => env('MEILISEARCH_HOST', 'http://127.0.0.1:7700'),
'key' => env('MEILISEARCH_KEY'),
'index-settings' => [
'documents' => [
'filterableAttributes' => ['type', 'group_id', 'uploaded_by'],
'sortableAttributes' => ['created_at', 'title'],
'searchableAttributes' => ['title', 'description', 'markdown_content'],
],
],
],
// 启动 Meilisearch 服务
meilisearch --master-key="your-master-key"
```
### 文档转换配置
```php
// .env
DOCUMENT_CONVERSION_DRIVER=pandoc // 或 phpword
PANDOC_PATH=/usr/local/bin/pandoc
CONVERSION_TIMEOUT=300 // 秒
// config/documents.php
return [
'conversion' => [
'driver' => env('DOCUMENT_CONVERSION_DRIVER', 'pandoc'),
'pandoc_path' => env('PANDOC_PATH', '/usr/bin/pandoc'),
'timeout' => env('CONVERSION_TIMEOUT', 300),
'queue' => 'documents',
],
'markdown' => [
'renderer' => 'commonmark', // 或 'parsedown'
'sanitize' => true,
],
];
```
## 扩展性考虑
### 未来功能扩展
1. **文档版本控制**
- 支持文档多版本管理
- 版本比较和回滚功能
- 保留每个版本的 Markdown 内容
2. **增强的文档转换**
- 支持更多文档格式PDF、Excel、PPT
- 保留文档中的图片和格式
- 支持 OCR 识别扫描文档
3. **高级搜索功能**
- 支持搜索语法AND、OR、NOT
- 按日期范围筛选
- 搜索结果高亮显示
- 搜索建议和自动补全
4. **文档标签系统**
- 为文档添加多个标签
- 按标签筛选和搜索
- 标签云展示
5. **文档评论和协作**
- 用户可以对文档添加评论
- 支持文档收藏和分享
- 文档阅读统计
6. **AI 增强功能**
- 文档内容摘要生成
- 智能问答(基于文档内容)
- 相关文档推荐
### 架构扩展性
1. **微服务化**
- 文档存储服务可以独立部署
- 使用消息队列解耦服务
2. **多租户支持**
- 支持多个组织独立使用系统
- 数据完全隔离
3. **API 接口**
- 提供 RESTful API
- 支持第三方系统集成
## 总结
本设计文档详细描述了基于 Laravel Filament 3.X 的知识库系统的架构、组件、数据模型和正确性属性。系统采用分层架构,通过 Eloquent ORM 和 Filament 资源实现数据管理,使用策略和作用域实现细粒度的权限控制。系统集成了文档格式转换和 Meilisearch 全文搜索功能,提供强大的文档管理和检索能力。
关键设计决策包括:
1. 使用枚举类型区分全局和专用知识库
2. 通过多对多关系管理用户和分组
3. 使用查询作用域实现权限过滤
4. 采用属性基础测试验证核心业务逻辑
5. 全面的中文化支持
6. 异步队列处理文档转换,避免阻塞用户操作
7. 使用 Meilisearch 实现快速全文搜索,搜索结果遵循权限控制
8. Markdown 格式存储支持在线预览和内容检索
9. 优雅降级策略,转换或搜索失败不影响核心功能
系统设计充分考虑了安全性、性能和可扩展性,为后续的实施提供了清晰的指导。文档转换和搜索功能的引入大大提升了知识库的可用性和检索效率。

View File

@@ -0,0 +1,168 @@
# 需求文档
## 简介
知识库系统是一个基于 Laravel Filament 3.X 的文档管理平台,允许用户上传和管理 Word 文档。系统支持文档分类为全局知识库和专用知识库,并根据用户所属分组控制访问权限。用户只能查看全局知识库和自己分组的专用知识库,无法访问其他分组的专用知识库。
系统具备文档格式转换功能,自动将上传的 Word 文档(.doc/.docx转换为 Markdown 格式存储,并通过 Meilisearch 搜索引擎提供强大的全文搜索能力。用户可以通过关键词快速检索文档内容,也可以在线预览文档的 Markdown 渲染内容,无需下载即可查看文档信息。
## 术语表
- **系统System**: 指知识库管理系统
- **用户User**: 使用系统的人员
- **分组Group**: 用户所属的组织单位
- **文档Document**: 用户上传的 Word 文件
- **全局知识库Global Knowledge Base**: 所有用户都可以查看的知识库
- **专用知识库Dedicated Knowledge Base**: 仅特定分组用户可以查看的知识库
- **文档分类Document Category**: 文档的类型标签,用于组织和检索
- **Markdown 内容Markdown Content**: 从 Word 文档转换后的 Markdown 格式文本
- **文档转换Document Conversion**: 将 Word 文档转换为 Markdown 格式的过程
- **全文搜索Full-Text Search**: 在文档内容中搜索关键词的功能
- **Meilisearch**: 用于实现全文搜索的搜索引擎
- **文档索引Document Index**: 在 Meilisearch 中存储的文档搜索数据
- **文档预览Document Preview**: 在线查看文档 Markdown 内容的功能
## 需求
### 需求 1
**用户故事:** 作为系统管理员,我想要上传 Word 文档到知识库,以便为用户提供知识资源
#### 验收标准
1. WHEN 管理员选择 Word 文档并点击上传按钮 THEN 系统 SHALL 验证文件格式为 .doc 或 .docx
2. WHEN 文档格式验证通过 THEN 系统 SHALL 将文档存储到服务器并记录文档元数据
3. WHEN 文档上传成功 THEN 系统 SHALL 显示成功消息并返回文档列表页面
4. IF 上传的文件不是 Word 格式 THEN 系统 SHALL 拒绝上传并显示错误提示信息
5. WHEN 文档上传过程中发生错误 THEN 系统 SHALL 回滚操作并保持数据一致性
### 需求 2
**用户故事:** 作为系统管理员,我想要为文档设置分类,以便组织和管理知识库内容
#### 验收标准
1. WHEN 管理员创建或编辑文档 THEN 系统 SHALL 提供选项将文档分类为全局知识库或专用知识库
2. WHERE 文档被分类为专用知识库 THEN 系统 SHALL 要求管理员指定关联的分组
3. WHEN 文档被分类为全局知识库 THEN 系统 SHALL 允许所有用户查看该文档
4. WHEN 文档分类信息被保存 THEN 系统 SHALL 更新数据库中的文档分类字段
5. WHEN 文档已关联分组 THEN 系统 SHALL 在文档列表中显示关联的分组名称
### 需求 3
**用户故事:** 作为普通用户,我想要查看知识库文档列表,以便找到我需要的知识资源
#### 验收标准
1. WHEN 用户访问知识库页面 THEN 系统 SHALL 显示该用户有权限查看的所有文档列表
2. WHEN 系统过滤文档列表 THEN 系统 SHALL 包含所有全局知识库文档
3. WHEN 系统过滤文档列表 THEN 系统 SHALL 包含用户所属分组的专用知识库文档
4. WHEN 系统过滤文档列表 THEN 系统 SHALL 排除其他分组的专用知识库文档
5. WHEN 文档列表显示 THEN 系统 SHALL 展示文档标题、分类类型、上传时间和所属分组信息
### 需求 4
**用户故事:** 作为普通用户,我想要下载或查看文档内容,以便获取知识信息
#### 验收标准
1. WHEN 用户点击有权限的文档 THEN 系统 SHALL 允许用户下载该文档
2. WHEN 用户尝试访问无权限的文档 THEN 系统 SHALL 拒绝访问并显示权限不足提示
3. WHEN 用户下载文档 THEN 系统 SHALL 记录下载日志包含用户信息和时间戳
4. WHEN 文档被下载 THEN 系统 SHALL 保持原始文件格式和内容完整性
### 需求 5
**用户故事:** 作为系统管理员,我想要管理用户分组,以便控制专用知识库的访问权限
#### 验收标准
1. WHEN 管理员创建新分组 THEN 系统 SHALL 保存分组名称和描述信息
2. WHEN 管理员将用户分配到分组 THEN 系统 SHALL 更新用户的分组关联关系
3. WHEN 用户被分配到分组 THEN 系统 SHALL 自动授予该用户访问该分组专用知识库的权限
4. WHEN 用户从分组中移除 THEN 系统 SHALL 撤销该用户访问该分组专用知识库的权限
5. WHEN 分组被删除 THEN 系统 SHALL 将该分组的专用知识库文档转换为孤立状态或重新分配
### 需求 6
**用户故事:** 作为系统管理员,我想要搜索和筛选文档,以便快速找到特定的知识资源
#### 验收标准
1. WHEN 管理员在搜索框输入关键词 THEN 系统 SHALL 在文档标题和内容中搜索匹配项
2. WHEN 管理员选择分类筛选器 THEN 系统 SHALL 仅显示选定分类的文档
3. WHEN 管理员选择分组筛选器 THEN 系统 SHALL 仅显示选定分组的文档
4. WHEN 搜索结果为空 THEN 系统 SHALL 显示无结果提示信息
5. WHEN 应用多个筛选条件 THEN 系统 SHALL 返回同时满足所有条件的文档
### 需求 7
**用户故事:** 作为系统,我想要确保数据安全和权限隔离,以便保护敏感知识资源
#### 验收标准
1. WHEN 系统执行权限检查 THEN 系统 SHALL 验证用户身份和分组归属
2. WHEN 用户尝试访问文档 THEN 系统 SHALL 在返回数据前验证访问权限
3. WHEN 权限验证失败 THEN 系统 SHALL 记录未授权访问尝试到安全日志
4. WHEN 文档数据被查询 THEN 系统 SHALL 应用行级安全策略确保数据隔离
5. WHEN 用户会话过期 THEN 系统 SHALL 要求重新认证后才能访问知识库
### 需求 8
**用户故事:** 作为系统,我想要提供中文界面,以便中文用户能够流畅使用系统
#### 验收标准
1. WHEN 系统加载任何页面 THEN 系统 SHALL 以简体中文显示所有界面元素
2. WHEN 系统显示表单标签 THEN 系统 SHALL 使用中文标签和占位符文本
3. WHEN 系统显示错误或成功消息 THEN 系统 SHALL 使用中文提示信息
4. WHEN 系统显示数据表格 THEN 系统 SHALL 使用中文列标题和操作按钮
5. WHEN 系统显示日期时间 THEN 系统 SHALL 使用中文日期格式
### 需求 9
**用户故事:** 作为系统管理员,我想要系统自动将上传的 Word 文档转换为 Markdown 格式,以便实现文档内容的全文搜索和在线预览
#### 验收标准
1. WHEN 用户上传 Word 文档并保存成功 THEN 系统 SHALL 自动将文档内容转换为 Markdown 格式
2. WHEN 文档转换完成 THEN 系统 SHALL 将 Markdown 内容存储到数据库的 markdown_content 字段
3. WHEN 文档转换失败 THEN 系统 SHALL 记录错误日志并保留原始文档,不影响文档的正常使用
4. WHEN 文档转换成功 THEN 系统 SHALL 保留原始 Word 文档供用户下载
5. WHEN 文档被更新或重新上传 THEN 系统 SHALL 重新执行转换流程并更新 Markdown 内容
### 需求 10
**用户故事:** 作为普通用户,我想要通过关键词搜索文档内容,以便快速找到包含特定信息的文档
#### 验收标准
1. WHEN 用户在搜索页面输入关键词 THEN 系统 SHALL 使用 Meilisearch 在文档的 Markdown 内容中搜索匹配项
2. WHEN 系统执行搜索 THEN 系统 SHALL 同时搜索文档标题、描述和 Markdown 内容
3. WHEN 搜索返回结果 THEN 系统 SHALL 只显示用户有权限访问的文档(全局文档和用户分组的专用文档)
4. WHEN 搜索结果显示 THEN 系统 SHALL 展示文档标题、匹配的内容片段、文档类型和上传时间
5. WHEN 搜索关键词为空 THEN 系统 SHALL 显示提示信息要求输入搜索关键词
### 需求 11
**用户故事:** 作为普通用户,我想要在线预览文档的 Markdown 内容,以便无需下载即可查看文档内容
#### 验收标准
1. WHEN 用户点击有权限的文档查看按钮 THEN 系统 SHALL 显示文档的 Markdown 内容渲染后的 HTML 页面
2. WHEN 系统渲染 Markdown 内容 THEN 系统 SHALL 正确处理标题、列表、表格、图片等 Markdown 元素
3. WHEN 用户尝试预览无权限的文档 THEN 系统 SHALL 拒绝访问并显示权限不足提示
4. WHEN 文档的 Markdown 内容为空 THEN 系统 SHALL 显示提示信息并提供下载原始文档的选项
5. WHEN 预览页面显示 THEN 系统 SHALL 提供下载原始 Word 文档的按钮
### 需求 12
**用户故事:** 作为系统,我想要将文档内容索引到 Meilisearch以便提供快速准确的全文搜索功能
#### 验收标准
1. WHEN 文档的 Markdown 转换完成 THEN 系统 SHALL 将文档信息索引到 Meilisearch
2. WHEN 索引文档到 Meilisearch THEN 系统 SHALL 包含文档 ID、标题、描述、Markdown 内容、类型和分组 ID
3. WHEN 文档被更新 THEN 系统 SHALL 更新 Meilisearch 中对应的索引
4. WHEN 文档被删除 THEN 系统 SHALL 从 Meilisearch 中删除对应的索引
5. WHEN Meilisearch 索引操作失败 THEN 系统 SHALL 记录错误日志但不影响文档的正常保存和使用

View File

@@ -0,0 +1,670 @@
# 实施计划
- [x] 1. 初始化 Laravel 项目和安装 Filament
- 创建新的 Laravel 项目或在现有项目中安装 Filament 3.X
- 配置数据库连接
- 安装 Filament 中文语言包
- 配置应用语言为简体中文
- _需求8.1, 8.2, 8.3, 8.4, 8.5_
- [x] 2. 创建数据库迁移和模型
- [x] 2.1 创建 groups 表迁移和 Group 模型
- 编写迁移文件创建 groups 表id, name, description, timestamps
- 创建 Group 模型并定义关联关系
- _需求5.1_
- [x] 2.2 创建 group_user 中间表迁移
- 编写迁移文件创建 group_user 表id, group_id, user_id, timestamps
- 添加外键约束和唯一索引
- _需求5.2_
- [x] 2.3 更新 User 模型添加分组关联
- 在 User 模型中添加 groups() 关联方法
- 添加 uploadedDocuments() 和 downloadLogs() 关联方法
- _需求5.2_
- [x] 2.4 创建 documents 表迁移和 Document 模型
- 编写迁移文件创建 documents 表(包含所有必需字段和索引)
- 创建 Document 模型并定义 fillable 属性
- 定义与 Group、User 的关联关系
- _需求1.2, 2.1, 2.2, 2.4_
- [x] 2.5 创建 download_logs 表迁移和 DownloadLog 模型
- 编写迁移文件创建 download_logs 表
- 创建 DownloadLog 模型并定义关联关系
- _需求4.3_
- [x] 2.6 运行迁移创建数据库表
- 执行 php artisan migrate 命令
- 验证所有表和索引创建成功
- _需求所有数据模型相关需求_
- [ ] 3. 实现文档权限查询作用域
- [x] 3.1 在 Document 模型中实现 accessibleBy 作用域
- 编写 scopeAccessibleBy 方法实现权限过滤逻辑
- 包含全局文档和用户分组的专用文档
- 排除其他分组的专用文档
- _需求3.1, 3.2, 3.3, 3.4_
- [x] 3.2 编写属性测试验证权限过滤逻辑
- **属性 7用户文档列表权限过滤**
- **属性 8其他分组文档隔离**
- **验证需求3.1, 3.2, 3.3, 3.4**
- [x] 3.3 实现 global 和 dedicated 查询作用域
- 编写 scopeGlobal 方法过滤全局文档
- 编写 scopeDedicated 方法过滤专用文档
- _需求2.3, 6.2_
- [x] 4. 创建 DocumentService 服务类
- [x] 4.1 实现文档上传方法
- 编写 uploadDocument 方法处理文件上传
- 验证文件格式(.doc 或 .docx
- 存储文件到指定位置
- 创建数据库记录
- 实现事务处理确保一致性
- _需求1.1, 1.2, 1.4, 1.5_
- [ ]* 4.2 编写属性测试验证文件上传逻辑
- **属性 1文件格式验证**
- **属性 2文档存储完整性**
- **属性 3上传事务一致性**
- **验证需求1.1, 1.2, 1.4, 1.5**
- [x] 4.3 实现文档访问权限验证方法
- 编写 validateDocumentAccess 方法
- 检查用户是否有权访问指定文档
- _需求4.1, 4.2, 7.1, 7.2_
- [x] 4.4 实现文档下载方法
- 编写 downloadDocument 方法
- 验证用户权限
- 返回文件流式响应
- _需求4.1, 4.4_
- [ ]* 4.5 编写属性测试验证文档下载
- **属性 9有权限文档可下载**
- **属性 10无权限文档访问拒绝**
- **属性 12文档下载往返一致性**
- **验证需求4.1, 4.2, 4.4**
- [x] 4.6 实现下载日志记录方法
- 编写 logDownload 方法
- 记录用户、文档、时间和 IP 地址
- _需求4.3_
- [ ]* 4.7 编写属性测试验证下载日志
- **属性 11下载日志记录**
- **验证需求4.3**
- [ ] 5. 创建 DocumentPolicy 策略类
- [x] 5.1 实现文档策略的各种权限方法
- 编写 viewAny、view、create、update、delete 方法
- 编写 download 方法验证下载权限
- 实现基于分组的权限判断逻辑
- _需求3.1, 3.4, 4.1, 4.2, 7.1, 7.2_
- [ ]* 5.2 编写单元测试验证策略逻辑
- 测试各种权限场景(有权限、无权限、边缘情况)
- 测试全局文档和专用文档的权限差异
- _需求3.1, 3.4, 4.1, 4.2_
- [x] 6. 创建 Filament 资源 - GroupResource
- [x] 6.1 创建 GroupResource 基础结构
- 使用 Filament 命令生成 GroupResource
- 配置中文导航标签和标题
- _需求5.1, 8.1, 8.2_
- [x] 6.2 定义 Group 表单字段
- 添加名称字段(必填,中文标签)
- 添加描述字段(可选,中文标签)
- 配置验证规则
- _需求5.1, 8.2_
- [x] 6.3 定义 Group 表格列
- 添加 ID、名称、描述、创建时间列
- 配置中文列标题
- 添加搜索和排序功能
- _需求5.1, 8.4_
- [x] 6.4 添加用户关系管理器
- 创建 RelationManager 管理分组成员
- 配置用户添加和移除功能
- 使用中文标签
- _需求5.2, 5.3, 5.4_
- [ ]* 6.5 编写属性测试验证分组管理
- **属性 13分组数据持久化**
- **属性 14用户分组关联**
- **属性 15分组分配授予权限**
- **属性 16分组移除撤销权限**
- **验证需求5.1, 5.2, 5.3, 5.4**
- [x] 7. 创建 Filament 资源 - DocumentResource
- [x] 7.1 创建 DocumentResource 基础结构
- 使用 Filament 命令生成 DocumentResource
- 配置中文导航标签和标题
- _需求1.1, 8.1, 8.2_
- [x] 7.2 定义 Document 表单字段
- 添加标题字段(必填,中文标签)
- 添加描述字段(可选,中文标签)
- 添加文件上传字段(限制 .doc 和 .docx 格式)
- 添加类型选择字段(全局/专用,中文选项)
- 添加分组选择字段(当类型为专用时必填)
- 配置验证规则
- _需求1.1, 1.4, 2.1, 2.2, 8.2_
- [x] 7.3 实现文件上传处理逻辑
- 在表单中集成 DocumentService 的上传方法
- 处理文件验证和存储
- 显示中文成功/错误消息
- _需求1.1, 1.2, 1.3, 1.4, 8.3_
- [ ]* 7.4 编写属性测试验证专用文档分组要求
- **属性 4专用文档必须关联分组**
- **验证需求2.2**
- [x] 7.5 定义 Document 表格列
- 添加标题、类型、分组、上传者、上传时间列
- 配置中文列标题
- 使用中文日期格式
- 添加搜索功能
- _需求3.5, 8.4, 8.5_
- [x] 7.6 实现表格查询权限过滤
- 在 getEloquentQuery 方法中应用 accessibleBy 作用域
- 确保用户只能看到有权限的文档
- _需求3.1, 3.2, 3.3, 3.4_
- [x] 7.7 添加文档下载操作
- 创建自定义 Action 用于下载文档
- 集成 DocumentService 的下载方法
- 验证权限并记录日志
- 使用中文按钮标签
- _需求4.1, 4.2, 4.3, 8.2_
- [x] 7.8 添加筛选器
- 添加类型筛选器(全局/专用,中文标签)
- 添加分组筛选器(中文标签)
- 添加上传者筛选器
- _需求6.2, 6.3, 8.2_
- [ ]* 7.9 编写属性测试验证搜索和筛选
- **属性 18关键词搜索匹配**
- **属性 19分类筛选准确性**
- **属性 20分组筛选准确性**
- **属性 21组合筛选交集**
- **验证需求6.1, 6.2, 6.3, 6.5**
- [ ] 8. 更新 UserResource 添加分组管理
- [x] 8.1 在 UserResource 中添加分组关系管理器
- 创建 RelationManager 管理用户所属分组
- 配置分组添加和移除功能
- 使用中文标签
- _需求5.2, 5.3, 5.4_
- [x] 8.2 在用户表单中添加分组选择字段
- 添加多选分组字段
- 配置中文标签
- _需求5.2_
- [x] 9. 配置文件存储
- [x] 9.1 配置 documents 存储磁盘
- 在 config/filesystems.php 中添加 documents 磁盘配置
- 设置为 private 可见性
- _需求1.2, 4.4_
- [x] 9.2 创建文档存储目录
- 创建 storage/app/documents 目录
- 配置适当的权限
- _需求1.2_
- [x] 10. 实现安全日志记录
- [x] 10.1 创建安全日志记录功能
- 创建 SecurityLog 模型和迁移(可选)
- 或使用 Laravel 日志系统记录安全事件
- 记录未授权访问尝试
- _需求7.3_
- [ ]* 10.2 编写属性测试验证安全日志
- **属性 24未授权访问日志记录**
- **验证需求7.3**
- [x] 10.3 在 DocumentPolicy 中集成安全日志
- 在权限验证失败时记录日志
- 包含用户信息、文档信息和时间戳
- _需求7.3_
- [x] 11. 实现分组删除级联处理
- [x] 11.1 在 Group 模型中添加删除事件监听器
- 使用 Model Events 监听 deleting 事件
- 处理关联的专用文档(设置 group_id 为 null 或删除)
- _需求5.5_
- [ ]* 11.2 编写属性测试验证级联处理
- **属性 17分组删除级联处理**
- **验证需求5.5**
- [x] 12. 配置 Filament 面板中文化
- [x] 12.1 配置应用语言设置
- 在 config/app.php 中设置 locale 为 zh_CN
- 配置 fallback_locale
- _需求8.1, 8.2, 8.3, 8.4, 8.5_
- [x] 12.2 发布和配置 Filament 语言文件
- 发布 Filament 语言文件
- 自定义翻译文本以符合业务需求
- _需求8.1, 8.2, 8.3, 8.4_
- [x] 12.3 配置日期时间格式
- 在 Filament 配置中设置中文日期格式
- 配置 Carbon 使用中文语言
- _需求8.5_
- [ ]* 12.4 编写属性测试验证中文化
- **属性 26错误消息中文化**
- **属性 27日期格式中文化**
- **验证需求8.3, 8.5**
- [x] 13. 创建测试工厂Factories
- [x] 13.1 创建 GroupFactory
- 生成随机分组名称和描述
- 使用 Faker 生成中文文本
- _需求测试数据生成_
- [x] 13.2 创建 DocumentFactory
- 生成随机文档数据
- 支持生成全局和专用文档
- 关联随机分组和上传者
- _需求测试数据生成_
- [x] 13.3 创建 DownloadLogFactory
- 生成随机下载日志数据
- 关联随机文档和用户
- _需求测试数据生成_
- [ ] 14. 编写剩余的属性测试
- [ ]* 14.1 编写全局文档访问属性测试
- **属性 5全局文档对所有用户可见**
- **验证需求2.3**
- [ ]* 14.2 编写文档分类持久化属性测试
- **属性 6文档分类持久化**
- **验证需求2.4**
- [ ]* 14.3 编写权限检查属性测试
- **属性 22权限检查验证用户和分组**
- **属性 23数据返回前权限验证**
- **验证需求7.1, 7.2**
- [ ]* 14.4 编写数据隔离属性测试
- **属性 25查询结果数据隔离**
- **验证需求7.4**
- [ ] 15. 编写功能测试
- [ ]* 15.1 编写文档上传流程测试
- 测试管理员上传全局文档
- 测试管理员上传专用文档
- 测试上传无效格式文件被拒绝
- _需求1.1, 1.2, 1.4, 2.1, 2.2_
- [ ]* 15.2 编写权限控制流程测试
- 测试用户查看自己分组的专用文档
- 测试用户无法查看其他分组的专用文档
- 测试用户可以查看所有全局文档
- _需求3.1, 3.2, 3.3, 3.4_
- [ ]* 15.3 编写分组管理流程测试
- 测试创建分组并分配用户
- 测试用户从分组移除后失去权限
- 测试删除分组后文档状态
- _需求5.1, 5.2, 5.3, 5.4, 5.5_
- [ ]* 15.4 编写搜索和筛选流程测试
- 测试按关键词搜索文档
- 测试按分类筛选文档
- 测试组合多个筛选条件
- _需求6.1, 6.2, 6.3, 6.5_
- [ ] 16. 配置错误处理和验证消息
- [ ] 16.1 自定义验证错误消息
- 在语言文件中添加自定义验证消息
- 确保所有消息使用简体中文
- _需求8.3_
- [ ] 16.2 实现全局异常处理
- 在 Handler.php 中自定义异常响应
- 为不同类型的错误返回友好的中文消息
- _需求错误处理策略_
- [ ] 16.3 配置文件上传限制
- 在 php.ini 或 .htaccess 中配置上传大小限制
- 在表单验证中添加文件大小验证
- 显示中文错误提示
- _需求1.1, 错误处理_
- [ ] 17. 性能优化
- [ ] 17.1 添加数据库索引
- 验证所有必要的索引已创建
- 使用 EXPLAIN 分析查询性能
- _需求性能考虑_
- [ ] 17.2 实现查询优化
- 在 Filament 资源中使用 Eager Loading
- 避免 N+1 查询问题
- _需求性能考虑_
- [ ] 17.3 配置缓存
- 配置 Redis 缓存驱动
- 缓存用户分组信息
- 缓存文档元数据
- _需求性能考虑_
- [x] 18. 创建种子数据Seeders
- [x] 18.1 创建演示数据 Seeder
- 创建示例用户
- 创建示例分组
- 创建示例文档
- 建立关联关系
- _需求开发和演示_
- [x] 18.2 运行 Seeder 生成测试数据
- 执行 php artisan db:seed
- 验证数据正确生成
- _需求开发和演示_
- [x] 19. 安装和配置 Meilisearch
- [x] 19.1 安装 Meilisearch 服务
- 安装 Meilisearch 服务器Docker 或本地安装)
- 配置 Meilisearch 主密钥
- 启动 Meilisearch 服务
- _需求10.1, 12.1_
- [x] 19.2 安装 Laravel Scout 和 Meilisearch 驱动
- 安装 laravel/scout 包
- 安装 meilisearch/meilisearch-php 包
- 发布 Scout 配置文件
- _需求10.1, 12.1_
- [x] 19.3 配置 Scout 和 Meilisearch
- 在 .env 中配置 Meilisearch 连接信息
- 在 config/scout.php 中配置索引设置
- 配置可过滤、可排序和可搜索属性
- _需求10.1, 12.1_
- [ ] 20. 添加文档转换功能的数据库字段
- [x] 20.1 创建数据库迁移添加新字段
- 添加 markdown_path 字段varchar 500
- 添加 markdown_preview 字段text
- 添加 conversion_status 字段enum
- 添加 conversion_error 字段text
- 添加相应的索引
- _需求9.1, 9.2_
- [x] 20.2 运行迁移更新数据库
- 执行 php artisan migrate
- 验证新字段创建成功
- _需求9.1, 9.2_
- [x] 20.3 更新 Document 模型
- 添加新字段到 fillable 数组
- 添加 Searchable trait
- 实现 toSearchableArray 方法
- 实现 shouldBeSearchable 方法
- 添加 getMarkdownContent 辅助方法
- _需求9.2, 12.2_
- [x] 21. 安装和配置文档转换工具
- [x] 21.1 选择并安装转换工具
- 安装 Pandoc推荐或 phpoffice/phpword 包
- 验证 Pandoc 可执行文件路径
- 测试转换功能是否正常
- _需求9.1_
- [x] 21.2 创建文档转换配置文件
- 创建 config/documents.php 配置文件
- 配置转换驱动pandoc 或 phpword
- 配置转换超时时间
- 配置队列名称
- _需求9.1_
- [x] 21.3 配置 markdown 存储磁盘
- 在 config/filesystems.php 中添加 markdown 磁盘
- 设置为 private 可见性
- 创建 storage/app/private/markdown 目录
- _需求9.2_
- [x] 22. 实现 DocumentConversionService
- [x] 22.1 创建 DocumentConversionService 类
- 创建服务类文件
- 实现 convertToMarkdown 方法(调用 Pandoc 或 PHPWord
- 实现 saveMarkdownToFile 方法
- 实现 getMarkdownPreview 方法(提取前 500 字符)
- _需求9.1, 9.2_
- [x] 22.2 实现转换队列任务
- 创建 ConvertDocumentToMarkdown Job
- 在 Job 中调用 DocumentConversionService
- 实现转换成功后的处理逻辑
- 实现转换失败后的错误处理
- _需求9.1, 9.3_
- [x] 22.3 实现 queueConversion 方法
- 创建队列任务分发方法
- 更新文档状态为 'processing'
- 分发到 documents 队列
- _需求9.1_
- [ ]* 22.4 编写属性测试验证文档转换
- **属性 28文档上传触发转换**
- **属性 29Markdown 内容持久化**
- **属性 30转换失败不影响文档可用性**
- **属性 31原始文档保留**
- **属性 32文档更新重新转换**
- **验证需求9.1, 9.2, 9.3, 9.4, 9.5**
- [x] 23. 集成文档转换到上传流程
- [x] 23.1 更新 DocumentService 的 uploadDocument 方法
- 在文档保存成功后调用 queueConversion
- 设置初始 conversion_status 为 'pending'
- 确保事务正确处理
- _需求9.1_
- [x] 23.2 更新 DocumentResource 表单
- 在表格中显示转换状态
- 添加转换状态的中文标签
- 添加转换状态筛选器
- _需求9.1_
- [x] 23.3 处理文档更新时的重新转换
- 在文档更新时检测文件是否变更
- 如果文件变更,触发重新转换
- 删除旧的 Markdown 文件
- _需求9.5_
- [x] 24. 实现 DocumentSearchService
- [x] 24.1 创建 DocumentSearchService 类
- 创建服务类文件
- 实现 search 方法(使用 Scout 搜索)
- 实现 filterByUserPermissions 方法
- 实现 prepareSearchableData 方法
- _需求10.1, 10.2, 10.3_
- [x] 24.2 实现索引管理方法
- 实现 indexDocument 方法(读取 Markdown 文件并索引)
- 实现 updateDocumentIndex 方法
- 实现 removeDocumentFromIndex 方法
- 处理 Meilisearch 操作失败的情况
- _需求12.1, 12.3, 12.4, 12.5_
- [x] 24.3 集成索引到文档生命周期
- 在转换完成后自动索引文档
- 在文档更新时更新索引
- 在文档删除时移除索引
- 使用模型事件或观察者模式
- _需求12.1, 12.3, 12.4_
- [ ]* 24.4 编写属性测试验证搜索功能
- **属性 33搜索匹配 Markdown 内容**
- **属性 34搜索覆盖多个字段**
- **属性 35搜索结果权限过滤**
- **属性 36搜索结果包含必需信息**
- **验证需求10.1, 10.2, 10.3, 10.4**
- [ ]* 24.5 编写属性测试验证索引管理
- **属性 40转换完成触发索引**
- **属性 41索引数据完整性**
- **属性 42文档更新同步索引**
- **属性 43文档删除移除索引**
- **属性 44索引失败不影响文档保存**
- **验证需求12.1, 12.2, 12.3, 12.4, 12.5**
- [x] 25. 创建搜索页面
- [x] 25.1 创建 Filament 自定义页面 - SearchPage
- 使用 Filament 命令生成自定义页面
- 配置中文导航标签
- 添加到导航菜单
- _需求10.1_
- [x] 25.2 实现搜索表单
- 添加搜索关键词输入框
- 添加文档类型筛选器
- 添加分组筛选器
- 配置中文标签和占位符
- _需求10.1, 10.5_
- [x] 25.3 实现搜索结果展示
- 创建搜索结果表格或列表
- 显示文档标题、内容片段、类型、上传时间
- 添加下载原始文档操作(不提供 Markdown 预览)
- 实现分页
- 使用中文标签
- _需求10.4_
- [x] 25.4 集成 DocumentSearchService
- 在页面中调用搜索服务
- 应用用户权限过滤
- 处理空搜索关键词
- 显示中文提示信息
- _需求10.1, 10.3, 10.5_
- [x] 26. 实现 MarkdownRenderService
- [x] 26.1 安装 Markdown 渲染库
- 安装 league/commonmark 包
- 或安装其他 Markdown 渲染库
- _需求11.1, 11.2_
- [x] 26.2 创建 MarkdownRenderService 类
- 创建服务类文件
- 实现 render 方法Markdown 转 HTML
- 实现 sanitize 方法(清理 HTML防止 XSS
- 实现 extractPreview 方法(提取摘要)
- _需求11.1, 11.2_
- [x] 26.3 配置 Markdown 渲染选项
- 配置支持的 Markdown 扩展(表格、代码高亮等)
- 配置 HTML 清理规则
- 配置代码高亮样式
- _需求11.2_
- [ ]* 26.4 编写属性测试验证 Markdown 渲染
- **属性 38Markdown 渲染正确性**
- **验证需求11.2**
- [x] 27. 实现文档 Markdown 预览功能(仅在文档管理中)
- [x] 27.1 在 DocumentResource 中添加 Markdown 预览操作
- 在文档列表和详情页添加"预览 Markdown"按钮
- 创建自定义 Action 用于预览 Markdown 内容
- 验证用户权限
- 使用中文按钮标签(如"预览 Markdown"
- 注意:其他地方(如搜索结果)只提供下载原始文档功能
- _需求11.1, 11.3_
- [x] 27.2 创建 Markdown 预览页面
- 创建独立的预览页面或使用 Filament 模态框
- 显示渲染后的 Markdown HTML
- 添加下载原始 Word 文档按钮
- 使用响应式布局,支持移动端查看
- _需求11.1, 11.5_
- [x] 27.3 实现预览控制器方法
- 创建控制器方法处理预览请求
- 验证用户权限(使用 DocumentPolicy
- 读取 Markdown 文件并使用 MarkdownRenderService 渲染
- 处理 Markdown 内容为空的情况(显示提示并提供下载按钮)
- 返回渲染后的 HTML 视图
- _需求11.1, 11.3, 11.4_
- [ ]* 27.4 编写属性测试验证预览功能
- **属性 37有权限文档可预览**
- **属性 39无权限文档预览拒绝**
- **验证需求11.1, 11.3**
- [ ] 28. 编写功能测试 - 文档转换和搜索
- [ ]* 28.1 编写文档转换流程测试
- 测试上传文档后自动触发转换
- 测试转换完成后 Markdown 文件存在
- 测试转换失败时文档仍可用
- 测试更新文档时重新转换
- _需求9.1, 9.2, 9.3, 9.5_
- [ ]* 28.2 编写全文搜索流程测试
- 测试搜索 Markdown 内容中的关键词
- 测试搜索结果遵循权限控制
- 测试搜索多个字段(标题、描述、内容)
- 测试空搜索关键词的处理
- _需求10.1, 10.2, 10.3, 10.5_
- [ ]* 28.3 编写文档预览流程测试
- 测试有权限用户可以预览
- 测试无权限用户无法预览
- 测试 Markdown 正确渲染为 HTML
- 测试预览页面包含下载按钮
- _需求11.1, 11.2, 11.3, 11.5_
- [ ]* 28.4 编写 Meilisearch 索引流程测试
- 测试文档转换后自动索引
- 测试文档更新时同步索引
- 测试文档删除时移除索引
- 测试索引失败不影响文档保存
- _需求12.1, 12.3, 12.4, 12.5_
- [ ] 29. 检查点 - 确保转换和搜索功能正常
- 运行所有新增的测试
- 手动测试文档上传和转换流程
- 手动测试搜索功能
- 手动测试预览功能
- 验证 Meilisearch 索引正常工作
- 如有问题请咨询用户
- _需求9.1-9.5, 10.1-10.5, 11.1-11.5, 12.1-12.5_
- [ ] 30. 最终检查点 - 确保所有测试通过
- 运行所有单元测试、属性测试和功能测试
- 验证测试覆盖率达到目标
- 修复任何失败的测试
- 如有问题请咨询用户
- _需求所有需求_
- [ ] 31. 文档和部署准备
- [ ] 31.1 更新 README 文档
- 添加文档转换和搜索功能说明
- 添加 Meilisearch 安装和配置步骤
- 添加 Pandoc 安装说明
- 更新使用说明
- 使用简体中文编写
- _需求部署和配置_
- [ ] 31.2 更新环境配置示例
- 在 .env.example 中添加 Meilisearch 配置项
- 添加文档转换配置项
- 添加必要的配置项注释
- _需求部署和配置_
- [ ] 31.3 更新部署脚本
- 添加 Meilisearch 服务启动步骤
- 添加队列工作进程启动步骤
- 添加 Markdown 存储目录创建步骤
- 包含数据库迁移步骤
- 包含文件权限配置
- _需求部署和配置_

View File

@@ -0,0 +1,484 @@
# 设计文档
## 概述
本设计文档描述了知识库系统UI界面美化的技术实现方案。通过集成Alpine.js和Tailwind CSS我们将为现有的Filament界面添加现代化的视觉效果和流畅的交互动画提升用户体验。
设计遵循以下原则:
- **渐进增强**:在不破坏现有功能的基础上添加视觉增强
- **性能优先**使用CSS动画和轻量级JavaScript避免性能问题
- **响应式设计**:确保在所有设备上都有良好的显示效果
- **无障碍访问**遵循WCAG 2.1标准,支持键盘导航和屏幕阅读器
- **主题一致性**与Filament的设计语言保持一致
## 架构
### 技术栈
- **Alpine.js 3.x**:用于添加交互行为和状态管理
- **Tailwind CSS 3.x**:用于样式设计和响应式布局
- **Filament 3.x**:现有的管理面板框架
- **Laravel Blade**:模板引擎
- **CSS Transitions/Animations**:用于动画效果
### 组件层次
```
┌─────────────────────────────────────┐
│ Blade Templates │
│ (搜索页面、预览模态框、文档列表) │
└──────────────┬──────────────────────┘
┌──────────────┴──────────────────────┐
│ Alpine.js Components │
│ (交互逻辑、状态管理、事件处理) │
└──────────────┬──────────────────────┘
┌──────────────┴──────────────────────┐
│ Tailwind CSS Classes │
│ (样式、动画、响应式布局) │
└─────────────────────────────────────┘
```
### 文件结构
```
resources/
├── views/
│ ├── filament/
│ │ ├── pages/
│ │ │ ├── search-page.blade.php (增强版搜索页面)
│ │ │ └── document-preview-modal.blade.php (增强版预览模态框)
│ │ └── resources/
│ │ └── document/
│ │ └── card.blade.php (新增:文档卡片组件)
│ └── components/
│ ├── ui/
│ │ ├── button.blade.php (新增:增强按钮组件)
│ │ ├── input.blade.php (新增:增强输入框组件)
│ │ ├── card.blade.php (新增:卡片组件)
│ │ └── badge.blade.php (新增:徽章组件)
│ └── animations/
│ ├── fade-in.blade.php (新增:淡入动画)
│ └── slide-in.blade.php (新增:滑入动画)
├── css/
│ └── custom/
│ ├── animations.css (新增:自定义动画)
│ ├── components.css (新增:组件样式)
│ └── utilities.css (新增:工具类)
└── js/
└── alpine/
├── search.js (新增:搜索页面逻辑)
├── preview.js (新增:预览模态框逻辑)
└── filters.js (新增:筛选器逻辑)
```
## 组件和接口
### 1. 搜索页面组件
**职责**:提供美化的搜索界面和结果展示
**Alpine.js数据结构**
```javascript
{
// 搜索状态
searchQuery: '',
isSearching: false,
hasSearched: false,
// 筛选器状态
filters: {
type: null,
groupId: null
},
showFilters: false,
// 结果状态
results: [],
resultCount: 0,
// UI状态
viewMode: 'grid', // 'grid' 或 'list'
sortBy: 'created_at',
sortOrder: 'desc'
}
```
**方法**
- `search()`:执行搜索
- `clearSearch()`:清空搜索
- `toggleFilters()`:切换筛选器显示
- `applyFilter(key, value)`:应用筛选条件
- `removeFilter(key)`:移除筛选条件
- `toggleViewMode()`:切换视图模式
- `sortResults(field)`:排序结果
### 2. 文档卡片组件
**职责**:以卡片形式展示文档信息
**Props**
- `document`:文档对象
- `showActions`:是否显示操作按钮
- `compact`:是否使用紧凑模式
**样式类**
- `document-card`:基础卡片样式
- `document-card-hover`:悬停效果
- `document-card-compact`:紧凑模式
### 3. 预览模态框组件
**职责**:提供优雅的文档预览体验
**Alpine.js数据结构**
```javascript
{
// 模态框状态
isOpen: false,
isLoading: true,
// 内容状态
content: null,
error: null,
// UI状态
scrollProgress: 0,
showScrollTop: false
}
```
**方法**
- `open()`:打开模态框
- `close()`:关闭模态框
- `loadContent()`:加载内容
- `scrollToTop()`:滚动到顶部
- `updateScrollProgress()`:更新滚动进度
### 4. 增强按钮组件
**职责**:提供统一的按钮样式和交互效果
**Props**
- `variant`按钮变体primary, secondary, danger等
- `size`按钮大小sm, md, lg
- `loading`:加载状态
- `disabled`:禁用状态
- `icon`:图标名称
**样式类**
- `btn-enhanced`:基础增强样式
- `btn-loading`:加载状态
- `btn-pulse`:脉冲效果
### 5. 增强输入框组件
**职责**:提供友好的输入交互效果
**Props**
- `label`:标签文本
- `placeholder`:占位符
- `maxLength`:最大长度
- `showCounter`:显示字符计数
- `validation`:验证规则
**Alpine.js数据结构**
```javascript
{
value: '',
isFocused: false,
hasError: false,
errorMessage: '',
charCount: 0
}
```
## 数据模型
本功能主要涉及UI增强不需要修改现有数据模型。所有数据仍使用现有的Document、Group等模型。
## 正确性属性
*属性是一个特征或行为,应该在系统的所有有效执行中保持为真。属性作为人类可读规范和机器可验证正确性保证之间的桥梁。*
### 属性 1文档类型徽章颜色一致性
*对于任何*文档,当显示为卡片时,全局文档应该使用绿色徽章,专用文档应该使用蓝色徽章
**验证需求2.3**
### 属性 2ARIA标签完整性
*对于任何*可交互元素该元素应该包含适当的ARIA标签或role属性
**验证需求10.2**
### 属性 3颜色对比度合规性
*对于任何*文本元素其前景色和背景色的对比度应该至少为4.5:1普通文本或3:1大文本
**验证需求10.5**
## 错误处理
### 1. 动画性能问题
**场景**:在低性能设备上动画可能导致卡顿
**处理策略**
- 检测设备性能,在低性能设备上禁用复杂动画
- 使用CSS `will-change`属性优化动画性能
- 遵循用户的`prefers-reduced-motion`设置
### 2. Alpine.js加载失败
**场景**CDN不可用或网络问题导致Alpine.js加载失败
**处理策略**
- 使用本地备份的Alpine.js文件
- 确保核心功能在没有JavaScript的情况下仍可用
- 显示友好的降级界面
### 3. 深色模式切换问题
**场景**:主题切换时可能出现闪烁
**处理策略**
- 在页面加载前检测主题偏好
- 使用CSS变量实现平滑过渡
- 将主题偏好保存到localStorage
### 4. 响应式布局问题
**场景**:某些设备上布局可能错乱
**处理策略**
- 使用Tailwind的响应式断点
- 在多种设备上测试
- 提供最小宽度限制
## 测试策略
### 单元测试
使用PHPUnit和Pest进行后端测试
1. **组件渲染测试**
- 测试Blade组件是否正确渲染
- 测试props是否正确传递
- 测试条件渲染逻辑
2. **样式类测试**
- 测试CSS类是否正确应用
- 测试响应式类是否存在
### 前端测试
使用Jest和Testing Library进行前端测试
1. **Alpine.js组件测试**
- 测试数据绑定
- 测试事件处理
- 测试状态变化
2. **交互测试**
- 测试按钮点击
- 测试表单输入
- 测试键盘导航
3. **视觉回归测试**
- 使用Percy或Chromatic进行截图对比
- 测试不同主题下的显示效果
- 测试不同屏幕尺寸下的布局
### 无障碍测试
1. **自动化测试**
- 使用axe-core进行无障碍扫描
- 测试ARIA标签
- 测试键盘导航
2. **手动测试**
- 使用屏幕阅读器测试
- 测试键盘完整导航
- 测试颜色对比度
### 性能测试
1. **动画性能**
- 使用Chrome DevTools测试FPS
- 测试动画是否触发重排
- 测试低性能设备表现
2. **加载性能**
- 测试CSS和JS文件大小
- 测试首次内容绘制时间
- 测试交互就绪时间
### 浏览器兼容性测试
测试以下浏览器:
- Chrome最新版本和前一版本
- Firefox最新版本和前一版本
- Safari最新版本
- Edge最新版本
- 移动浏览器iOS Safari、Chrome Mobile
## 实现细节
### 1. Tailwind CSS配置
扩展Tailwind配置以支持自定义动画和颜色
```javascript
// tailwind.config.js
module.exports = {
theme: {
extend: {
animation: {
'fade-in': 'fadeIn 0.3s ease-in-out',
'slide-in': 'slideIn 0.3s ease-out',
'scale-in': 'scaleIn 0.2s ease-out',
'shake': 'shake 0.5s ease-in-out',
},
keyframes: {
fadeIn: {
'0%': { opacity: '0' },
'100%': { opacity: '1' },
},
slideIn: {
'0%': { transform: 'translateY(-10px)', opacity: '0' },
'100%': { transform: 'translateY(0)', opacity: '1' },
},
scaleIn: {
'0%': { transform: 'scale(0.95)', opacity: '0' },
'100%': { transform: 'scale(1)', opacity: '1' },
},
shake: {
'0%, 100%': { transform: 'translateX(0)' },
'25%': { transform: 'translateX(-10px)' },
'75%': { transform: 'translateX(10px)' },
},
},
},
},
}
```
### 2. Alpine.js集成
在Blade模板中集成Alpine.js
```html
<div x-data="searchComponent()" x-init="init()">
<!-- 组件内容 -->
</div>
<script>
function searchComponent() {
return {
// 数据和方法
}
}
</script>
```
### 3. 自定义CSS动画
创建可复用的动画类:
```css
/* animations.css */
.animate-stagger > * {
animation: fadeIn 0.3s ease-in-out;
animation-fill-mode: both;
}
.animate-stagger > *:nth-child(1) { animation-delay: 0.05s; }
.animate-stagger > *:nth-child(2) { animation-delay: 0.1s; }
.animate-stagger > *:nth-child(3) { animation-delay: 0.15s; }
/* ... */
.hover-lift {
transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.hover-lift:hover {
transform: translateY(-4px);
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.15);
}
```
### 4. 深色模式支持
使用Tailwind的深色模式类
```html
<div class="bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100">
<!-- 内容 -->
</div>
```
### 5. 响应式设计
使用Tailwind的响应式前缀
```html
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
<!-- 卡片 -->
</div>
```
### 6. 无障碍支持
添加适当的ARIA属性
```html
<button
aria-label="搜索文档"
aria-pressed="false"
role="button"
tabindex="0"
>
搜索
</button>
```
### 7. 性能优化
- 使用CSS `contain`属性隔离动画
- 使用`will-change`提示浏览器优化
- 延迟加载非关键动画
- 使用`requestAnimationFrame`优化JavaScript动画
```css
.animated-card {
contain: layout style paint;
will-change: transform;
}
```
## 部署考虑
### 1. 资源打包
- 使用Laravel Mix或Vite打包CSS和JS
- 启用CSS和JS压缩
- 使用版本控制避免缓存问题
### 2. CDN配置
- 考虑使用CDN加速Alpine.js加载
- 提供本地备份文件
### 3. 浏览器支持
- 添加必要的polyfills
- 提供降级方案
### 4. 监控
- 监控动画性能
- 收集用户反馈
- 跟踪错误日志

View File

@@ -0,0 +1,138 @@
# 需求文档
## 简介
本文档定义了知识库系统UI界面美化的需求。系统当前使用Filament框架构建需要通过Alpine.js和Tailwind CSS增强用户界面的视觉效果和交互体验使界面更加现代化、美观和易用。
## 术语表
- **知识库系统Knowledge Base System**基于Laravel和Filament构建的文档管理系统
- **Alpine.js**轻量级JavaScript框架用于添加交互行为
- **Tailwind CSS**实用优先的CSS框架用于样式设计
- **Filament**Laravel的管理面板框架
- **搜索页面Search Page**:用户搜索文档的界面
- **文档预览Document Preview**:在模态框中显示文档内容的功能
- **文档列表Document List**:显示文档资源的表格界面
- **响应式设计Responsive Design**:适配不同屏幕尺寸的界面设计
## 需求
### 需求 1
**用户故事:** 作为用户,我希望搜索页面具有现代化的视觉设计,以便获得更好的使用体验。
#### 验收标准
1. WHEN 用户访问搜索页面 THEN 系统应当显示具有渐变背景和阴影效果的搜索表单卡片
2. WHEN 用户将鼠标悬停在搜索按钮上 THEN 系统应当显示平滑的过渡动画效果
3. WHEN 用户输入搜索关键词 THEN 系统应当在输入框获得焦点时显示高亮边框效果
4. WHEN 搜索表单加载完成 THEN 系统应当显示淡入动画效果
5. WHEN 用户在移动设备上访问 THEN 系统应当显示适配移动端的响应式布局
### 需求 2
**用户故事:** 作为用户,我希望搜索结果以卡片形式展示,以便更直观地浏览文档信息。
#### 验收标准
1. WHEN 搜索返回结果 THEN 系统应当以卡片网格布局显示文档列表
2. WHEN 用户将鼠标悬停在文档卡片上 THEN 系统应当显示卡片上浮和阴影增强效果
3. WHEN 文档卡片包含类型标签 THEN 系统应当使用不同颜色的徽章区分全局和专用文档
4. WHEN 搜索结果加载完成 THEN 系统应当显示交错淡入动画效果
5. WHEN 文档卡片显示内容片段 THEN 系统应当使用渐变遮罩处理文本溢出
### 需求 3
**用户故事:** 作为用户,我希望文档预览模态框具有优雅的设计,以便舒适地阅读文档内容。
#### 验收标准
1. WHEN 用户点击预览按钮 THEN 系统应当显示带有缩放淡入动画的模态框
2. WHEN 模态框打开时 THEN 系统应当显示半透明背景遮罩和模糊效果
3. WHEN 文档内容较长 THEN 系统应当提供带有自定义滚动条样式的滚动区域
4. WHEN 文档包含代码块 THEN 系统应当使用语法高亮和圆角边框样式
5. WHEN 文档包含表格 THEN 系统应当使用斑马纹和悬停高亮效果
### 需求 4
**用户故事:** 作为用户,我希望操作按钮具有清晰的视觉反馈,以便明确操作状态。
#### 验收标准
1. WHEN 用户将鼠标悬停在按钮上 THEN 系统应当显示颜色加深和轻微缩放效果
2. WHEN 用户点击按钮 THEN 系统应当显示按下动画效果
3. WHEN 按钮处于加载状态 THEN 系统应当显示旋转的加载图标
4. WHEN 按钮处于禁用状态 THEN 系统应当显示降低透明度和禁用鼠标指针
5. WHEN 操作成功完成 THEN 系统应当显示带有图标的成功通知动画
### 需求 5
**用户故事:** 作为用户,我希望表单输入具有友好的交互效果,以便更好地完成输入操作。
#### 验收标准
1. WHEN 输入框获得焦点 THEN 系统应当显示边框颜色变化和标签上移动画
2. WHEN 用户输入内容 THEN 系统应当实时显示字符计数或验证状态
3. WHEN 输入验证失败 THEN 系统应当显示红色边框和抖动动画效果
4. WHEN 下拉选择框展开 THEN 系统应当显示下滑淡入动画
5. WHEN 用户清空输入 THEN 系统应当显示清除按钮的淡入淡出效果
### 需求 6
**用户故事:** 作为用户,我希望页面加载和状态变化具有流畅的过渡效果,以便获得连贯的使用体验。
#### 验收标准
1. WHEN 页面首次加载 THEN 系统应当显示骨架屏加载动画
2. WHEN 搜索正在执行 THEN 系统应当显示加载指示器和脉冲动画
3. WHEN 内容状态改变 THEN 系统应当使用淡入淡出过渡效果
4. WHEN 列表项添加或删除 THEN 系统应当显示滑入滑出动画
5. WHEN 错误发生 THEN 系统应当显示带有图标的错误提示和抖动效果
### 需求 7
**用户故事:** 作为用户,我希望界面支持深色模式,以便在不同光线环境下舒适使用。
#### 验收标准
1. WHEN 系统检测到深色模式偏好 THEN 系统应当自动切换到深色主题
2. WHEN 深色模式激活 THEN 系统应当使用深色背景和浅色文字
3. WHEN 深色模式下显示卡片 THEN 系统应当使用深色卡片背景和适当的边框
4. WHEN 深色模式下显示按钮 THEN 系统应当调整按钮颜色以保持对比度
5. WHEN 主题切换时 THEN 系统应当显示平滑的颜色过渡动画
### 需求 8
**用户故事:** 作为用户,我希望界面元素具有微交互效果,以便获得更生动的使用体验。
#### 验收标准
1. WHEN 用户将鼠标悬停在图标上 THEN 系统应当显示图标旋转或缩放动画
2. WHEN 用户点击收藏按钮 THEN 系统应当显示心形填充动画
3. WHEN 通知消息出现 THEN 系统应当从右侧滑入并自动淡出
4. WHEN 用户滚动页面 THEN 系统应当显示返回顶部按钮的淡入效果
5. WHEN 用户拖拽元素 THEN 系统应当显示拖拽阴影和位置指示器
### 需求 9
**用户故事:** 作为用户,我希望文档列表具有高级筛选和排序界面,以便快速找到目标文档。
#### 验收标准
1. WHEN 用户点击筛选按钮 THEN 系统应当显示侧边栏滑入动画
2. WHEN 用户选择筛选条件 THEN 系统应当实时更新结果数量徽章
3. WHEN 用户应用筛选 THEN 系统应当显示已选筛选条件的标签
4. WHEN 用户点击排序选项 THEN 系统应当显示排序图标的旋转动画
5. WHEN 筛选结果为空 THEN 系统应当显示友好的空状态插图和提示
### 需求 10
**用户故事:** 作为用户,我希望界面具有无障碍访问支持,以便所有用户都能使用系统。
#### 验收标准
1. WHEN 用户使用键盘导航 THEN 系统应当显示清晰的焦点指示器
2. WHEN 屏幕阅读器访问页面 THEN 系统应当提供适当的ARIA标签
3. WHEN 用户使用Tab键切换 THEN 系统应当按逻辑顺序聚焦可交互元素
4. WHEN 动画效果播放 THEN 系统应当遵循用户的减少动画偏好设置
5. WHEN 界面显示颜色信息 THEN 系统应当确保足够的颜色对比度

View File

@@ -0,0 +1,334 @@
# 实施计划
- [ ] 1. 配置开发环境和依赖
- [ ] 1.1 确认Alpine.js和Tailwind CSS已安装
- 检查package.json中的依赖
- 如需要则安装Alpine.js 3.x
- 确认Tailwind CSS 3.x已配置
- _需求所有需求的基础_
- [ ] 1.2 扩展Tailwind配置文件
- 在tailwind.config.js中添加自定义动画
- 添加自定义关键帧fadeIn, slideIn, scaleIn, shake
- 配置动画时长和缓动函数
- _需求1.2, 1.4, 2.2, 2.4, 3.1, 4.1, 5.1, 5.3, 6.1-6.5, 8.1-8.5_
- [ ] 1.3 创建自定义CSS文件结构
- 创建resources/css/custom/animations.css
- 创建resources/css/custom/components.css
- 创建resources/css/custom/utilities.css
- 在app.css中导入自定义CSS文件
- _需求所有需求_
- [ ] 2. 创建可复用的UI组件
- [ ] 2.1 创建增强按钮组件
- 创建resources/views/components/ui/button.blade.php
- 实现按钮变体primary, secondary, danger等
- 添加悬停效果(颜色加深、轻微缩放)
- 添加点击动画效果
- 添加加载状态(旋转图标)
- 添加禁用状态样式
- _需求4.1, 4.2, 4.3, 4.4_
- [ ]* 2.2 编写属性测试验证按钮组件
- **属性 1文档类型徽章颜色一致性**
- **验证需求2.3**
- [ ] 2.3 创建增强输入框组件
- 创建resources/views/components/ui/input.blade.php
- 实现焦点状态(边框颜色变化、标签上移)
- 添加字符计数功能
- 添加验证错误状态(红色边框、抖动动画)
- 添加清除按钮(淡入淡出效果)
- _需求5.1, 5.2, 5.3, 5.5_
- [ ] 2.4 创建卡片组件
- 创建resources/views/components/ui/card.blade.php
- 实现基础卡片样式(渐变背景、阴影)
- 添加悬停效果(上浮、阴影增强)
- 支持深色模式样式
- _需求1.1, 2.1, 2.2, 7.3_
- [ ] 2.5 创建徽章组件
- 创建resources/views/components/ui/badge.blade.php
- 实现不同颜色变体success, info, warning, danger
- 为全局文档使用绿色徽章
- 为专用文档使用蓝色徽章
- 支持深色模式
- _需求2.3, 7.4_
- [ ] 3. 增强搜索页面UI
- [ ] 3.1 更新搜索表单样式
- 修改resources/views/filament/pages/search-page.blade.php
- 应用渐变背景和阴影效果到搜索卡片
- 添加表单加载时的淡入动画
- 使用增强输入框组件替换原有输入框
- 使用增强按钮组件替换原有按钮
- _需求1.1, 1.2, 1.3, 1.4_
- [ ] 3.2 实现响应式搜索表单布局
- 添加移动端适配样式
- 使用Tailwind响应式类sm:, md:, lg:
- 测试不同屏幕尺寸下的显示效果
- _需求1.5_
- [ ] 3.3 创建文档卡片视图组件
- 创建resources/views/filament/resources/document/card.blade.php
- 实现卡片网格布局
- 添加文档标题、类型徽章、内容片段
- 添加悬停效果(卡片上浮、阴影增强)
- 使用渐变遮罩处理文本溢出
- _需求2.1, 2.2, 2.3, 2.5_
- [ ] 3.4 添加搜索结果动画
- 实现交错淡入动画stagger animation
- 为每个卡片添加延迟动画
- 添加加载骨架屏
- _需求2.4, 6.1_
- [ ] 3.5 集成Alpine.js到搜索页面
- 创建resources/js/alpine/search.js
- 实现搜索状态管理isSearching, hasSearched
- 实现筛选器切换逻辑
- 实现视图模式切换(网格/列表)
- 添加搜索加载指示器
- _需求6.2, 9.1, 9.2_
- [ ] 3.6 实现高级筛选器界面
- 添加筛选按钮和侧边栏
- 实现侧边栏滑入动画
- 显示已选筛选条件的标签
- 实时更新结果数量徽章
- 添加清空筛选按钮
- _需求9.1, 9.2, 9.3_
- [ ] 3.7 实现空状态UI
- 创建友好的空状态插图
- 添加提示文本
- 提供建议操作
- _需求9.5_
- [ ] 4. 增强文档预览模态框
- [ ] 4.1 更新预览模态框样式
- 修改resources/views/filament/pages/document-preview-modal.blade.php
- 添加模态框打开动画(缩放淡入)
- 添加半透明背景遮罩和模糊效果
- 优化内容区域样式
- _需求3.1, 3.2_
- [ ] 4.2 自定义滚动条样式
- 为预览内容区域添加自定义滚动条
- 使用Tailwind的scrollbar插件或自定义CSS
- 支持深色模式滚动条
- _需求3.3_
- [ ] 4.3 增强Markdown内容样式
- 优化代码块样式(语法高亮、圆角边框)
- 优化表格样式(斑马纹、悬停高亮)
- 优化标题、列表、引用样式
- 优化图片显示(响应式、圆角)
- _需求3.4, 3.5_
- [ ] 4.4 集成Alpine.js到预览模态框
- 创建resources/js/alpine/preview.js
- 实现模态框状态管理isOpen, isLoading
- 实现滚动进度跟踪
- 添加返回顶部按钮(滚动时淡入)
- _需求8.4_
- [ ] 5. 实现深色模式支持
- [ ] 5.1 配置深色模式检测
- 在主布局中添加深色模式检测脚本
- 检测系统偏好prefers-color-scheme
- 从localStorage读取用户偏好
- 应用深色模式类到html元素
- _需求7.1_
- [ ] 5.2 更新所有组件的深色模式样式
- 为搜索页面添加深色模式样式
- 为文档卡片添加深色模式样式
- 为预览模态框添加深色模式样式
- 为按钮和输入框添加深色模式样式
- 确保颜色对比度符合标准
- _需求7.2, 7.3, 7.4_
- [ ] 5.3 实现主题切换动画
- 添加主题切换时的颜色过渡效果
- 使用CSS变量实现平滑过渡
- 避免切换时的闪烁
- _需求7.5_
- [ ] 6. 添加微交互效果
- [ ] 6.1 实现图标动画
- 为搜索图标添加悬停旋转效果
- 为下载图标添加悬停缩放效果
- 为筛选图标添加点击动画
- _需求8.1_
- [ ] 6.2 实现通知动画
- 优化Filament通知的显示动画
- 实现从右侧滑入效果
- 实现自动淡出效果
- 添加成功/错误图标动画
- _需求4.5, 8.3_
- [ ] 6.3 实现排序动画
- 为排序图标添加旋转动画
- 添加排序方向指示器
- 实现列表重排动画
- _需求9.4_
- [ ] 7. 实现页面过渡和加载状态
- [ ] 7.1 创建骨架屏组件
- 创建搜索结果骨架屏
- 创建文档卡片骨架屏
- 添加脉冲动画效果
- _需求6.1_
- [ ] 7.2 实现加载指示器
- 为搜索按钮添加加载状态
- 为预览模态框添加加载指示器
- 使用旋转动画和脉冲效果
- _需求6.2_
- [ ] 7.3 实现内容过渡动画
- 为内容状态变化添加淡入淡出效果
- 为列表项添加滑入滑出动画
- 优化动画时序
- _需求6.3, 6.4_
- [ ] 7.4 实现错误状态UI
- 创建错误提示组件
- 添加抖动动画效果
- 显示错误图标
- _需求6.5_
- [ ] 8. 实现无障碍访问支持
- [ ] 8.1 添加键盘导航支持
- 为所有交互元素添加tabindex
- 实现清晰的焦点指示器样式
- 测试Tab键导航顺序
- 添加键盘快捷键如Esc关闭模态框
- _需求10.1, 10.3_
- [ ] 8.2 添加ARIA标签
- 为按钮添加aria-label
- 为模态框添加role和aria-modal
- 为加载状态添加aria-busy
- 为展开/折叠元素添加aria-expanded
- _需求10.2_
- [ ]* 8.3 编写属性测试验证ARIA标签
- **属性 2ARIA标签完整性**
- **验证需求10.2**
- [ ] 8.4 实现动画偏好支持
- 检测prefers-reduced-motion设置
- 在用户偏好减少动画时禁用动画
- 提供静态替代方案
- _需求10.4_
- [ ] 8.5 验证颜色对比度
- 使用工具检查所有文本的对比度
- 确保至少4.5:1普通文本或3:1大文本
- 调整不符合标准的颜色
- _需求10.5_
- [ ]* 8.6 编写属性测试验证颜色对比度
- **属性 3颜色对比度合规性**
- **验证需求10.5**
- [ ] 9. 优化性能
- [ ] 9.1 优化CSS
- 移除未使用的Tailwind类
- 压缩CSS文件
- 使用PurgeCSS减小文件大小
- _需求性能优化_
- [ ] 9.2 优化JavaScript
- 延迟加载非关键JavaScript
- 使用代码分割
- 压缩JavaScript文件
- _需求性能优化_
- [ ] 9.3 优化动画性能
- 使用CSS transform和opacity避免重排
- 添加will-change提示
- 使用contain属性隔离动画
- 在低性能设备上禁用复杂动画
- _需求性能优化_
- [ ] 10. 测试和验证
- [ ]* 10.1 编写组件单元测试
- 测试按钮组件的各种状态
- 测试输入框组件的交互
- 测试卡片组件的渲染
- 测试徽章组件的颜色逻辑
- _需求所有组件相关需求_
- [ ]* 10.2 编写Alpine.js组件测试
- 测试搜索组件的状态管理
- 测试筛选器逻辑
- 测试预览模态框逻辑
- _需求所有交互相关需求_
- [ ]* 10.3 进行无障碍测试
- 使用axe-core进行自动化扫描
- 使用屏幕阅读器测试
- 测试键盘完整导航
- _需求10.1-10.5_
- [ ]* 10.4 进行视觉回归测试
- 截图对比测试使用Percy或Chromatic
- 测试深色模式显示
- 测试响应式布局
- _需求所有视觉相关需求_
- [ ]* 10.5 进行性能测试
- 使用Chrome DevTools测试动画FPS
- 测试首次内容绘制时间
- 测试交互就绪时间
- 在低性能设备上测试
- _需求性能相关需求_
- [ ]* 10.6 进行浏览器兼容性测试
- 在Chrome、Firefox、Safari、Edge上测试
- 在移动浏览器上测试
- 修复兼容性问题
- _需求所有需求_
- [ ] 11. 文档和部署
- [ ] 11.1 更新开发文档
- 记录新增的UI组件使用方法
- 记录Alpine.js组件的API
- 记录自定义CSS类的用法
- 添加样式指南
- _需求文档需求_
- [ ] 11.2 创建组件演示页面
- 创建Storybook或类似的组件展示页面
- 展示所有UI组件的各种状态
- 提供代码示例
- _需求文档需求_
- [ ] 11.3 优化生产构建
- 配置Laravel Mix或Vite进行生产构建
- 启用CSS和JS压缩
- 配置资源版本控制
- 测试生产环境构建
- _需求部署需求_
- [ ] 11.4 准备部署清单
- 列出需要部署的文件
- 列出需要运行的命令
- 列出需要检查的配置
- 创建回滚计划
- _需求部署需求_
- [ ] 12. 最终检查点
- 确保所有UI增强功能正常工作
- 验证在不同设备和浏览器上的显示效果
- 确认无障碍访问功能正常
- 验证性能指标达标
- 如有问题请咨询用户
- _需求所有需求_