diff --git a/apps/web-antd/src/adapter/vxe-table.ts b/apps/web-antd/src/adapter/vxe-table.ts index 2b73ff29..44f867d2 100644 --- a/apps/web-antd/src/adapter/vxe-table.ts +++ b/apps/web-antd/src/adapter/vxe-table.ts @@ -259,6 +259,7 @@ setupVbenVxeTable({ // 这里可以自行扩展 vxe-table 的全局配置,比如自定义格式化 // vxeUI.formats.add + // add by 星语:数量格式化,例如说:金额 vxeUI.formats.add('formatAmount', { cellFormatMethod({ cellValue }, digits = 2) { if (cellValue === null || cellValue === undefined) { diff --git a/apps/web-antd/src/api/bpm/category/index.ts b/apps/web-antd/src/api/bpm/category/index.ts index 1519c758..0a558f6d 100644 --- a/apps/web-antd/src/api/bpm/category/index.ts +++ b/apps/web-antd/src/api/bpm/category/index.ts @@ -15,6 +15,7 @@ export namespace BpmCategoryApi { } /** 模型分类信息 */ + // TODO @jason:这个应该非 api 的,可以考虑抽到页面里哈。 export interface ModelCategoryInfo { id: number; name: string; diff --git a/apps/web-antd/src/api/bpm/model/index.ts b/apps/web-antd/src/api/bpm/model/index.ts index 06c444e0..72ae8e9f 100644 --- a/apps/web-antd/src/api/bpm/model/index.ts +++ b/apps/web-antd/src/api/bpm/model/index.ts @@ -2,6 +2,7 @@ import { requestClient } from '#/api/request'; export namespace BpmModelApi { /** 用户信息 TODO 这个是不是可以抽取出来定义在公共模块 */ + // TODO @芋艿:一起看看。 export interface UserInfo { id: number; nickname: string; @@ -9,6 +10,7 @@ export namespace BpmModelApi { deptId?: number; deptName?: string; } + /** 流程定义 VO */ export interface ProcessDefinitionVO { id: string; diff --git a/apps/web-antd/src/api/infra/file/index.ts b/apps/web-antd/src/api/infra/file/index.ts index 5f352432..a399db67 100644 --- a/apps/web-antd/src/api/infra/file/index.ts +++ b/apps/web-antd/src/api/infra/file/index.ts @@ -23,12 +23,13 @@ export namespace InfraFileApi { configId: number; // 文件配置编号 uploadUrl: string; // 文件上传 URL url: string; // 文件 URL + path: string; // 文件路径 } /** 上传文件 */ export interface FileUploadReqVO { file: globalThis.File; - path?: string; + directory?: string; } } @@ -45,11 +46,11 @@ export function deleteFile(id: number) { } /** 获取文件预签名地址 */ -export function getFilePresignedUrl(path: string) { +export function getFilePresignedUrl(name: string, directory?: string) { return requestClient.get( '/infra/file/presigned-url', { - params: { path }, + params: { name, directory }, }, ); } @@ -64,5 +65,9 @@ export function uploadFile( data: InfraFileApi.FileUploadReqVO, onUploadProgress?: AxiosProgressEvent, ) { + // 特殊:由于 upload 内部封装,即使 directory 为 undefined,也会传递给后端 + if (!data.directory) { + delete data.directory; + } return requestClient.upload('/infra/file/upload', data, { onUploadProgress }); } diff --git a/apps/web-antd/src/components/upload/file-upload.vue b/apps/web-antd/src/components/upload/file-upload.vue index 91d7cc66..3fbb727b 100644 --- a/apps/web-antd/src/components/upload/file-upload.vue +++ b/apps/web-antd/src/components/upload/file-upload.vue @@ -28,6 +28,8 @@ const props = withDefaults( file: File, onUploadProgress?: AxiosProgressEvent, ) => Promise>; + // 上传的目录 + directory?: string; disabled?: boolean; helpText?: string; // 最大数量的文件,Infinity不限制 @@ -44,13 +46,14 @@ const props = withDefaults( }>(), { value: () => [], + directory: undefined, disabled: false, helpText: '', maxSize: 2, maxNumber: 1, accept: () => [], multiple: false, - api: useUpload().httpRequest, + api: undefined, resultField: '', showDescription: false, }, @@ -141,10 +144,9 @@ const beforeUpload = async (file: File) => { }; async function customRequest(info: UploadRequestOption) { - const { api } = props; + let { api } = props; if (!api || !isFunction(api)) { - console.warn('upload api must exist and be a function'); - return; + api = useUpload(props.directory).httpRequest; } try { // 上传文件 diff --git a/apps/web-antd/src/components/upload/image-upload.vue b/apps/web-antd/src/components/upload/image-upload.vue index 412d9356..10da9086 100644 --- a/apps/web-antd/src/components/upload/image-upload.vue +++ b/apps/web-antd/src/components/upload/image-upload.vue @@ -30,6 +30,8 @@ const props = withDefaults( file: File, onUploadProgress?: AxiosProgressEvent, ) => Promise>; + // 上传的目录 + directory?: string; disabled?: boolean; helpText?: string; listType?: UploadListType; @@ -47,6 +49,7 @@ const props = withDefaults( }>(), { value: () => [], + directory: undefined, disabled: false, listType: 'picture-card', helpText: '', @@ -54,7 +57,7 @@ const props = withDefaults( maxNumber: 1, accept: () => defaultImageAccepts, multiple: false, - api: useUpload().httpRequest, + api: undefined, resultField: '', showDescription: true, }, @@ -177,10 +180,9 @@ const beforeUpload = async (file: File) => { }; async function customRequest(info: UploadRequestOption) { - const { api } = props; + let { api } = props; if (!api || !isFunction(api)) { - console.warn('upload api must exist and be a function'); - return; + api = useUpload(props.directory).httpRequest; } try { // 上传文件 diff --git a/apps/web-antd/src/components/upload/use-upload.ts b/apps/web-antd/src/components/upload/use-upload.ts index 94e238d1..9794f6fa 100644 --- a/apps/web-antd/src/components/upload/use-upload.ts +++ b/apps/web-antd/src/components/upload/use-upload.ts @@ -7,8 +7,7 @@ import { computed, unref } from 'vue'; import { useAppConfig } from '@vben/hooks'; import { $t } from '@vben/locales'; -import CryptoJS from 'crypto-js'; - +// import CryptoJS from 'crypto-js'; import { createFile, getFilePresignedUrl, uploadFile } from '#/api/infra/file'; import { baseRequestClient } from '#/api/request'; @@ -81,7 +80,7 @@ export function useUploadType({ } // TODO @芋艿:目前保持和 admin-vue3 一致,后续可能重构 -export const useUpload = () => { +export const useUpload = (directory?: string) => { // 后端上传地址 const uploadUrl = getUploadUrl(); // 是否使用前端直连上传 @@ -97,7 +96,7 @@ export const useUpload = () => { // 1.1 生成文件名称 const fileName = await generateFileName(file); // 1.2 获取文件预签名地址 - const presignedInfo = await getFilePresignedUrl(fileName); + const presignedInfo = await getFilePresignedUrl(fileName, directory); // 1.3 上传文件 return baseRequestClient .put(presignedInfo.uploadUrl, file, { @@ -107,13 +106,13 @@ export const useUpload = () => { }) .then(() => { // 1.4. 记录文件信息到后端(异步) - createFile0(presignedInfo, fileName, file); + createFile0(presignedInfo, file); // 通知成功,数据格式保持与后端上传的返回结果一致 return { data: presignedInfo.url }; }); } else { // 模式二:后端上传 - return uploadFile({ file }, onUploadProgress); + return uploadFile({ file, directory }, onUploadProgress); } }; @@ -134,18 +133,13 @@ export const getUploadUrl = (): string => { * 创建文件信息 * * @param vo 文件预签名信息 - * @param name 文件名称 * @param file 文件 */ -function createFile0( - vo: InfraFileApi.FilePresignedUrlRespVO, - name: string, - file: File, -) { +function createFile0(vo: InfraFileApi.FilePresignedUrlRespVO, file: File) { const fileVO = { configId: vo.configId, url: vo.url, - path: name, + path: vo.path, name: file.name, type: file.type, size: file.size, @@ -160,12 +154,13 @@ function createFile0( * @param file 要上传的文件 */ async function generateFileName(file: File) { - // 读取文件内容 - const data = await file.arrayBuffer(); - const wordArray = CryptoJS.lib.WordArray.create(data); - // 计算SHA256 - const sha256 = CryptoJS.SHA256(wordArray).toString(); - // 拼接后缀 - const ext = file.name.slice(Math.max(0, file.name.lastIndexOf('.'))); - return `${sha256}${ext}`; + // // 读取文件内容 + // const data = await file.arrayBuffer(); + // const wordArray = CryptoJS.lib.WordArray.create(data); + // // 计算SHA256 + // const sha256 = CryptoJS.SHA256(wordArray).toString(); + // // 拼接后缀 + // const ext = file.name.slice(Math.max(0, file.name.lastIndexOf('.'))); + // return `${sha256}${ext}`; + return file.name; } diff --git a/apps/web-antd/src/views/system/oauth2/client/data.ts b/apps/web-antd/src/views/system/oauth2/client/data.ts index 903da278..5eaa3204 100644 --- a/apps/web-antd/src/views/system/oauth2/client/data.ts +++ b/apps/web-antd/src/views/system/oauth2/client/data.ts @@ -48,11 +48,10 @@ export function useFormSchema(): VbenFormSchema[] { }, rules: 'required', }, - // TODO @芋艿:图片上传 { fieldName: 'logo', label: '应用图标', - component: 'UploadImage', + component: 'ImageUpload', componentProps: { limit: 1, },