feat(m8): P1 MinIO 对象存储与文件管理
- 迁移 000023 gateway.file_objects(personal/system 归属隔离 + 部分索引) - internal/platform/storage:minio-go 适配(端点 scheme 剥离、流式 PutObject/Open/Delete) - internal/workbench/files.go:FileService(sha256 校验、PutObject-then-insert 回滚、delete 先删行再删对象) - admin /api/v1/admin/files + portal /api/v1/portal/files 处理器(流式上传下载、Content-Disposition) - RBAC file:read/file:manage;菜单加文件管理 + 门户文件仓库 - compose 增 minio 服务(S3_* anchor、不暴露端口);nginx client_max_body_size 32m→256m - 管理端文件管理页 + 门户个人文件仓;集成测试 TestFileObjectLifecycle 连真 MinIO 通过 - healthz object_storage:true;README/PRODUCTION/进展文档同步 Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
import axios from 'axios'
|
||||
import request from '@/utils/http'
|
||||
import { useUserStore } from '@/store/modules/user'
|
||||
|
||||
export interface Application { id:string;code:string;name:string;description:string;published_version?:number }
|
||||
export interface Knowledge { id:string;name:string;description:string;document_count:number;chunk_count:number }
|
||||
@@ -21,6 +23,31 @@ export const fetchStats=(days:number)=>request.get<Stats>({url:'/api/v1/portal/s
|
||||
export const fetchLogs=(days:number,limit=50)=>request.get<{items:AuditEvent[]}>({url:'/api/v1/portal/logs',params:{days,limit}})
|
||||
export const changePassword=(params:{old_password:string;new_password:string})=>request.post({url:'/api/v1/portal/password',params})
|
||||
|
||||
// --- 个人文件仓库(M8 对象存储)---
|
||||
export interface FileObject { id:string;original_name:string;content_type:string;size_bytes:number;content_sha256:string;scope:string;created_at:string;updated_at:string }
|
||||
export const fetchMyFiles=()=>request.get<FileObject[]>({url:'/api/v1/portal/files'})
|
||||
export const uploadMyFile=(file:File)=>{
|
||||
const form=new FormData()
|
||||
form.append('file',file)
|
||||
return request.post<FileObject>({url:'/api/v1/portal/files',data:form,timeout:120000})
|
||||
}
|
||||
export const deleteMyFile=(id:string)=>request.del({url:`/api/v1/portal/files/${id}`})
|
||||
export async function downloadMyFile(id:string,filename:string){
|
||||
const { accessToken } = useUserStore()
|
||||
const token = accessToken.startsWith('Bearer ')?accessToken:`Bearer ${accessToken}`
|
||||
const res = await axios.get(`/api/v1/portal/files/${id}/download`,{
|
||||
baseURL:import.meta.env.VITE_API_URL,
|
||||
headers:{Authorization:token},
|
||||
responseType:'blob'
|
||||
})
|
||||
const url = URL.createObjectURL(res.data)
|
||||
const anchor = document.createElement('a')
|
||||
anchor.href = url
|
||||
anchor.download = filename
|
||||
anchor.click()
|
||||
URL.revokeObjectURL(url)
|
||||
}
|
||||
|
||||
|
||||
// --- 资源市场 ---
|
||||
export interface MarketItem { type:string;code:string;name:string;description:string;category_id?:string;category_name:string;tags:string[];department_ids:string[];updated_at:string }
|
||||
|
||||
Reference in New Issue
Block a user