diff --git a/client/shared/index.tsx b/client/shared/index.tsx index 12789960..13312900 100644 --- a/client/shared/index.tsx +++ b/client/shared/index.tsx @@ -272,6 +272,6 @@ export { applyDefaultFallbackGroupPermission, } from './utils/role-helper'; export { uploadFile } from './utils/upload-helper'; -export type { UploadFileResult } from './utils/upload-helper'; +export type { UploadFileResult, UploadFileUsage } from './utils/upload-helper'; export { parseUrlStr } from './utils/url-helper'; export { sleep } from './utils/utils'; diff --git a/client/shared/utils/upload-helper.ts b/client/shared/utils/upload-helper.ts index 968480a9..a9e7119a 100644 --- a/client/shared/utils/upload-helper.ts +++ b/client/shared/utils/upload-helper.ts @@ -5,7 +5,10 @@ import { getGlobalConfig } from '../model/config'; import { showErrorToasts } from '../manager/ui'; import filesize from 'filesize'; +export type UploadFileUsage = 'chat' | 'group' | 'user' | 'unknown'; + interface UploadFileOptions { + usage?: UploadFileUsage; onProgress?: (percent: number, progressEvent: unknown) => void; } export interface UploadFileResult { @@ -23,6 +26,7 @@ export async function uploadFile( ): Promise { const form = new FormData(); form.append('file', file); + form.append('usage', options.usage ?? 'unknown'); const uploadFileLimit = getGlobalConfig().uploadFileLimit; if (file.size > uploadFileLimit) { diff --git a/client/web/src/components/ChatBox/ChatInputBox/utils.tsx b/client/web/src/components/ChatBox/ChatInputBox/utils.tsx index b8d65875..629f2320 100644 --- a/client/web/src/components/ChatBox/ChatInputBox/utils.tsx +++ b/client/web/src/components/ChatBox/ChatInputBox/utils.tsx @@ -39,7 +39,9 @@ export function uploadMessageImage(image: File): Promise<{ }%(${originImageSize} -> ${compressedImageSize})` ); } - const fileInfo = await uploadFile(uploadImage); + const fileInfo = await uploadFile(uploadImage, { + usage: 'chat', + }); const imageRemoteUrl = fileInfo.url; resolve({ @@ -62,7 +64,9 @@ export async function uploadMessageFile(file: File): Promise<{ name: string; url: string; }> { - const fileInfo = await uploadFile(file); + const fileInfo = await uploadFile(file, { + usage: 'chat', + }); return { name: file.name || fileInfo.etag, diff --git a/client/web/src/components/ImageUploader.tsx b/client/web/src/components/ImageUploader.tsx index a0c2effc..f3ac2d06 100644 --- a/client/web/src/components/ImageUploader.tsx +++ b/client/web/src/components/ImageUploader.tsx @@ -1,13 +1,19 @@ import { blobUrlToFile } from '@/utils/file-helper'; import clsx from 'clsx'; import React, { PropsWithChildren, useState } from 'react'; -import { uploadFile, UploadFileResult, useAsyncRequest } from 'tailchat-shared'; +import { + uploadFile, + UploadFileResult, + UploadFileUsage, + useAsyncRequest, +} from 'tailchat-shared'; import { ImagePicker } from './ImagePicker'; interface ImageUploaderProps extends PropsWithChildren { circle?: boolean; aspect?: number; className?: string; + usage?: UploadFileUsage; onUploadSuccess: (fileInfo: UploadFileResult) => void; } @@ -20,6 +26,7 @@ export const ImageUploader: React.FC = React.memo( const file = await blobUrlToFile(blobUrl); const fileInfo = await uploadFile(file, { + usage: props.usage, onProgress(percent) { const uploadProgress = Number((percent * 100).toFixed()); console.log(`进度:${uploadProgress}`); diff --git a/client/web/src/components/modals/GroupDetail/Config.tsx b/client/web/src/components/modals/GroupDetail/Config.tsx index 7d30114e..38f6af37 100644 --- a/client/web/src/components/modals/GroupDetail/Config.tsx +++ b/client/web/src/components/modals/GroupDetail/Config.tsx @@ -92,6 +92,7 @@ export const GroupConfig: React.FC<{ <> { handleModifyConfig('groupBackgroundImage', fileInfo.url); }} diff --git a/client/web/src/components/modals/GroupDetail/Summary.tsx b/client/web/src/components/modals/GroupDetail/Summary.tsx index 02c593d0..1df08242 100644 --- a/client/web/src/components/modals/GroupDetail/Summary.tsx +++ b/client/web/src/components/modals/GroupDetail/Summary.tsx @@ -65,6 +65,7 @@ export const GroupSummary: React.FC<{
diff --git a/client/web/src/components/modals/SettingsView/Account.tsx b/client/web/src/components/modals/SettingsView/Account.tsx index 15e87611..3b4c94ad 100644 --- a/client/web/src/components/modals/SettingsView/Account.tsx +++ b/client/web/src/components/modals/SettingsView/Account.tsx @@ -95,6 +95,7 @@ export const SettingsAccount: React.FC = React.memo(() => {
diff --git a/server/admin/src/client/fields.ts b/server/admin/src/client/fields.ts index 6dfc2682..100c77c7 100644 --- a/server/admin/src/client/fields.ts +++ b/server/admin/src/client/fields.ts @@ -163,6 +163,11 @@ export const fileFields = [ width: 140, }, }), + createTextField('usage', { + list: { + width: 100, + }, + }), createFileSizeField('size', { list: { width: 120, @@ -170,12 +175,17 @@ export const fileFields = [ }, }), createTextField('metaData.content-type'), - createTextField('etag'), + createTextField('etag', { + list: { + width: 300, + }, + }), createUserField('userId', { reference: 'users', displayField: 'nickname', list: { - width: 80, + width: 200, + ellipsis: true, }, }), createDateTimeField('createdAt', { diff --git a/server/admin/src/client/i18n/zh.ts b/server/admin/src/client/i18n/zh.ts index 15f73c68..a950a9ab 100644 --- a/server/admin/src/client/i18n/zh.ts +++ b/server/admin/src/client/i18n/zh.ts @@ -58,6 +58,7 @@ export const zhTranslation = { objectName: '对象存储名', url: '文件路径', size: '文件大小', + usage: '使用场景', 'metaData.content-type': '文件类型', userId: '存储用户', createdAt: '创建时间', diff --git a/server/admin/src/client/resources/file.tsx b/server/admin/src/client/resources/file.tsx index 805c3a4d..a4e8de18 100644 --- a/server/admin/src/client/resources/file.tsx +++ b/server/admin/src/client/resources/file.tsx @@ -51,7 +51,7 @@ export const FileList: React.FC = React.memo(() => { ]} tableProps={{ scroll: { - x: 1200, + x: 1600, }, }} fields={fileFields} diff --git a/server/admin/src/client/routes/system/index.tsx b/server/admin/src/client/routes/system/index.tsx index cc397595..51af0b79 100644 --- a/server/admin/src/client/routes/system/index.tsx +++ b/server/admin/src/client/routes/system/index.tsx @@ -61,6 +61,7 @@ export const SystemConfig: React.FC = React.memo(() => { if (file) { const formdata = new FormData(); formdata.append('file', file); + formdata.append('usage', 'server'); const { data } = await request.put('/file/upload', formdata, { headers: { diff --git a/server/models/file.ts b/server/models/file.ts index b559625c..5f2439af 100644 --- a/server/models/file.ts +++ b/server/models/file.ts @@ -56,6 +56,15 @@ export class File extends TimeStamps implements Base { @prop() metaData: object; + + /** + * 这个文件是用于哪里 + * for example: chat, group, user + */ + @prop({ + default: 'unknown', + }) + usage: string; } export type FileDocument = DocumentType; diff --git a/server/services/core/file.service.ts b/server/services/core/file.service.ts index 3c939f14..4cb666ab 100644 --- a/server/services/core/file.service.ts +++ b/server/services/core/file.service.ts @@ -112,6 +112,7 @@ class FileService extends TcService { ctx: TcContext< {}, { + $multipart: any; $params: any; filename: any; } @@ -129,6 +130,7 @@ class FileService extends TcService { } const originFilename = String(ctx.meta.filename); + const usage = _.get(ctx, 'meta.$multipart.usage', 'unknown'); const stream = ctx.params as NodeJS.ReadableStream; (stream as any).on('error', (err) => { @@ -142,7 +144,8 @@ class FileService extends TcService { const { etag, objectName, url } = await this.saveFileStream( ctx, originFilename, - stream + stream, + usage ); resolve({ @@ -211,7 +214,8 @@ class FileService extends TcService { async saveFileStream( ctx: TcContext, filename: string, - fileStream: NodeJS.ReadableStream + fileStream: NodeJS.ReadableStream, + usage = 'unknown' ): Promise<{ etag: string; url: string; objectName: string }> { const span = ctx.startSpan('file.saveFileStream'); const ext = path.extname(filename); @@ -234,7 +238,8 @@ class FileService extends TcService { ctx, tmpObjectName, etag, - ext + ext, + usage ); span.finish(); @@ -253,7 +258,8 @@ class FileService extends TcService { ctx: TcContext, tmpObjectName: string, etag: string, - ext: string + ext: string, + usage = 'unknown' ): Promise<{ url: string; objectName: string; @@ -299,6 +305,7 @@ class FileService extends TcService { url, size: stat.size, metaData: stat.metaData, + usage, }, { upsert: true,