实现 MinIO 对象存储图片流水线(可迁移 OSS)

- 新增 S3 兼容 Storage 抽象与 MinIO 实现,compose 启动 MinIO
- 上传接口:校验 → 缩放 → WebP → 主图/缩略图入库
- 消息图片 content 改为对象 URL,拒绝 base64
- 工作台/访客端改为先上传再发消息
This commit is contained in:
yml2213
2026-07-15 12:21:31 +08:00
parent 85b407fddf
commit ec2f12c6ed
20 changed files with 907 additions and 108 deletions
+33 -1
View File
@@ -1,4 +1,4 @@
import { get, post, put, del, getList } from './request'
import { get, post, put, del, getList, postForm } from './request'
export interface LoginParams { username: string; password: string }
export interface LoginResult { token: string; user_id: number; tenant_id: number; nickname: string; role: string }
@@ -107,6 +107,38 @@ export const addSessionNote = (id: number, content: string) => post<SessionEvent
export const sendSessionMessage = (id: number, content: string, type: 'text' | 'image' = 'text') => post<Message>(`/sessions/${id}/messages`, { content, type })
export const getAvailableAgents = () => get<AvailableAgent[]>('/agents/available')
export interface UploadImageResult {
url: string
thumb_url: string
content_type: string
width: number
height: number
size: number
}
/** 客服端上传图片 → 返回对象存储 URL */
export const uploadImage = (file: File) => {
const form = new FormData()
form.append('file', file)
return postForm<UploadImageResult>('/uploads', form)
}
/** 访客端上传图片 */
export const uploadWidgetImage = async (file: File, sessionId: number, visitorToken: string) => {
const form = new FormData()
form.append('file', file)
form.append('session_id', String(sessionId))
form.append('visitor_token', visitorToken)
const res = await fetch('/api/widget/upload', {
method: 'POST',
headers: { 'X-Visitor-Token': visitorToken },
body: form,
})
const json = await res.json()
if (json.code !== 0) throw new Error(json.message || '上传失败')
return json as { code: number; data: UploadImageResult }
}
// Customers
export const getCustomers = (params?: { search?: string; status?: string; source?: string; page?: number; pageSize?: number }) => {
const search = new URLSearchParams()