feat(admin): Implement System Knowledge Base management module
Features:
- Backend: SystemKbService with full CRUD (knowledge bases + documents)
- Backend: 8 RESTful API endpoints (list/detail/create/update/delete/upload/download)
- Backend: OSS storage integration (system/knowledge-bases/{kbId}/{docId})
- Backend: RAG engine integration (document parsing, chunking, vectorization)
- Frontend: SystemKbListPage with card-based layout
- Frontend: SystemKbDetailPage with document management table
- Frontend: Master-Detail UX pattern for better user experience
- Document upload (single/batch), download (preserving original filename), delete
Technical:
- Database migration for system_knowledge_bases and system_kb_documents tables
- OSSAdapter.getSignedUrl with Content-Disposition for original filename
- Reuse RAG engine from common/rag for document processing
Tested: Local environment verified, all features working
This commit is contained in:
@@ -91,10 +91,18 @@ export class OSSAdapter implements StorageAdapter {
|
||||
try {
|
||||
const normalizedKey = this.normalizeKey(key)
|
||||
|
||||
// 使用 put 方法上传 Buffer(适合 < 30MB 文件)
|
||||
const result = await this.client.put(normalizedKey, buffer)
|
||||
// 根据文件扩展名设置 Content-Type
|
||||
const contentType = this.getMimeType(normalizedKey)
|
||||
|
||||
console.log(`[OSSAdapter] Upload success: ${normalizedKey}, size=${buffer.length}`)
|
||||
// 使用 put 方法上传 Buffer(适合 < 30MB 文件)
|
||||
// 必须设置正确的 headers,否则二进制文件可能损坏
|
||||
const result = await this.client.put(normalizedKey, buffer, {
|
||||
headers: {
|
||||
'Content-Type': contentType,
|
||||
},
|
||||
})
|
||||
|
||||
console.log(`[OSSAdapter] Upload success: ${normalizedKey}, size=${buffer.length}, contentType=${contentType}`)
|
||||
|
||||
// 返回签名URL(假设是私有Bucket)
|
||||
return this.getSignedUrl(normalizedKey)
|
||||
@@ -104,6 +112,37 @@ export class OSSAdapter implements StorageAdapter {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据文件扩展名获取 MIME 类型
|
||||
*/
|
||||
private getMimeType(key: string): string {
|
||||
const ext = key.toLowerCase().split('.').pop()
|
||||
const mimeTypes: Record<string, string> = {
|
||||
// 文档类型
|
||||
pdf: 'application/pdf',
|
||||
doc: 'application/msword',
|
||||
docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
||||
xls: 'application/vnd.ms-excel',
|
||||
xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
||||
ppt: 'application/vnd.ms-powerpoint',
|
||||
pptx: 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
|
||||
txt: 'text/plain',
|
||||
md: 'text/markdown',
|
||||
// 图片类型
|
||||
jpg: 'image/jpeg',
|
||||
jpeg: 'image/jpeg',
|
||||
png: 'image/png',
|
||||
gif: 'image/gif',
|
||||
webp: 'image/webp',
|
||||
svg: 'image/svg+xml',
|
||||
// 其他
|
||||
json: 'application/json',
|
||||
xml: 'application/xml',
|
||||
zip: 'application/zip',
|
||||
}
|
||||
return mimeTypes[ext || ''] || 'application/octet-stream'
|
||||
}
|
||||
|
||||
/**
|
||||
* 流式上传(适合大文件 > 30MB)
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user