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:
138
.kiro/specs/code-repository-organization/requirements.md
Normal file
138
.kiro/specs/code-repository-organization/requirements.md
Normal 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 在规格文档中标记完成状态
|
||||
993
.kiro/specs/knowledge-base-system/design.md
Normal file
993
.kiro/specs/knowledge-base-system/design.md
Normal 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**
|
||||
|
||||
### 属性 29:Markdown 内容持久化
|
||||
*对于任何*转换完成的文档,系统应该将 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**
|
||||
|
||||
### 属性 38:Markdown 渲染正确性
|
||||
*对于任何*包含标准 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小时)
|
||||
- 缓存渲染后的 HTML(TTL: 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. 优雅降级策略,转换或搜索失败不影响核心功能
|
||||
|
||||
系统设计充分考虑了安全性、性能和可扩展性,为后续的实施提供了清晰的指导。文档转换和搜索功能的引入大大提升了知识库的可用性和检索效率。
|
||||
168
.kiro/specs/knowledge-base-system/requirements.md
Normal file
168
.kiro/specs/knowledge-base-system/requirements.md
Normal 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 记录错误日志但不影响文档的正常保存和使用
|
||||
670
.kiro/specs/knowledge-base-system/tasks.md
Normal file
670
.kiro/specs/knowledge-base-system/tasks.md
Normal 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:文档上传触发转换**
|
||||
- **属性 29:Markdown 内容持久化**
|
||||
- **属性 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 渲染
|
||||
- **属性 38:Markdown 渲染正确性**
|
||||
- **验证需求: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 存储目录创建步骤
|
||||
- 包含数据库迁移步骤
|
||||
- 包含文件权限配置
|
||||
- _需求:部署和配置_
|
||||
484
.kiro/specs/ui-enhancement/design.md
Normal file
484
.kiro/specs/ui-enhancement/design.md
Normal 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**
|
||||
|
||||
### 属性 2:ARIA标签完整性
|
||||
|
||||
*对于任何*可交互元素,该元素应该包含适当的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. 监控
|
||||
|
||||
- 监控动画性能
|
||||
- 收集用户反馈
|
||||
- 跟踪错误日志
|
||||
138
.kiro/specs/ui-enhancement/requirements.md
Normal file
138
.kiro/specs/ui-enhancement/requirements.md
Normal 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 系统应当确保足够的颜色对比度
|
||||
334
.kiro/specs/ui-enhancement/tasks.md
Normal file
334
.kiro/specs/ui-enhancement/tasks.md
Normal 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标签
|
||||
- **属性 2:ARIA标签完整性**
|
||||
- **验证需求: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增强功能正常工作
|
||||
- 验证在不同设备和浏览器上的显示效果
|
||||
- 确认无障碍访问功能正常
|
||||
- 验证性能指标达标
|
||||
- 如有问题请咨询用户
|
||||
- _需求:所有需求_
|
||||
Reference in New Issue
Block a user