django-vue3-admin-web/node_modules/@fast-crud/fast-extends/dist/fs-file-uploader-506e96b9.mjs.map
2025-10-20 21:21:14 +08:00

1 line
58 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{"version":3,"file":"fs-file-uploader-506e96b9.mjs","sources":["../src/uploader/components/fs-file-uploader.vue","../src/uploader/components/fs-file-uploader.vue"],"sourcesContent":["<template>\n <div class=\"fs-file-uploader\" :class=\"{ 'fs-file-uploader-limit': computedOnLimit() }\">\n <component :is=\"ui.upload.name\" ref=\"fileUploaderRef\" v-model:file-list=\"fileList\" v-bind=\"computedBinding\">\n <component :is=\"computedFileSelectBtn.is\" v-bind=\"computedFileSelectBtn\" />\n </component>\n <component\n :is=\"ui.dialog.name\"\n v-if=\"isPicture()\"\n v-model:[ui.dialog.visible]=\"previewVisible\"\n v-bind=\"computedPreview\"\n >\n <img style=\"max-width: 100%; max-height: 100%\" :src=\"previewImage\" />\n </component>\n </div>\n</template>\n\n<script lang=\"ts\">\nimport { computed, defineComponent, nextTick, Ref, ref, watch } from \"vue\";\nimport { useI18n, useUi } from \"@fast-crud/fast-crud\";\nimport { merge, cloneDeep } from \"lodash-es\";\nimport { FileItem, FsUploaderDoUploadOptions } from \"../d/type\";\nimport { useUploader } from \"./utils\";\nimport type { PropType } from \"vue\";\n\n/**\n * 限制上传图片的像素尺寸\n */\ntype PixelLimit = { width?: number; height?: number; tip?: string } | [number, number?, string?];\n/**\n * 文件上传组件\n * 支持对应ui库的[x]-file-uploader组件的配置\n */\nexport default defineComponent({\n name: \"FsFileUploader\",\n inheritAttrs: false,\n props: {\n /**\n * value\n */\n modelValue: {},\n /**\n * 限制文件数量\n * 当限制数量>1时返回值为数组\n */\n limit: {\n type: Number\n },\n /**\n * 文件大小限制,单位:字节\n * 可以直接传一个数字,也可以传 `{limit:number,tip:'自定义提示文本'}`\n */\n sizeLimit: {\n type: [Number, Object]\n },\n /**\n * 限制上传图片的像素尺寸\n * 可以传数组会对象{ width?: number, height?: number, tip?: string } | [number, number?, string?]\n */\n pixelLimit: {\n type: Object as PropType<PixelLimit>,\n required: false\n },\n /**\n * 是否显示限制提示\n */\n showLimitTip: {\n type: Boolean,\n default: true\n },\n /**\n * 构建url的方法\n * 后台返回key之后将其build成一个可访问的url用于反显\n * 如果successHandle返回的object中已包含url此配置将不会执行\n */\n buildUrl: {\n default() {\n return (value: any) => {\n return value;\n };\n }\n },\n /**\n * 多个value值构建多个url\n * 如果successHandle 返回的object中已包含url此方法将不会执行\n */\n buildUrls: {},\n /**\n * 上传按钮配置参考FsButton参数\n */\n button: {\n type: Object\n },\n /**\n * 展示模式,对应[x]-uploader组件的 listType参数\n */\n listType: {\n type: String\n },\n /**\n * 上传前的判断操作\n */\n beforeUpload: {\n type: Function\n },\n\n /**\n * 上传请求前的操作可以压缩图片等替换掉context中的file\n * type: `async (context)=>void`\n */\n beforeUploadRequest: {\n type: Function\n },\n /**\n * FsUploaderXXX的配置\n * 可以覆盖全局配置里各个上传类型对应的配置\n * 例如: `{action:'xxx',bucket:'xxx',...}`\n */\n uploader: {\n type: Object\n },\n /**\n * 预览配置\n */\n preview: {\n type: Object\n },\n /**\n * 上传成功后从结果中取值类型\n * 支持:`[object,url,key,其他successHandle返回的object内要有该字段不要用'id']`\n * 如果配置了非url则需要配置buildUrl用于反显\n */\n valueType: {\n type: String, // url ,key, object\n default: \"url\"\n },\n /**\n * 根据value获取文件名用于显示在fileList里面\n */\n getFileName: {}\n },\n emits: [\"change\", \"update:modelValue\", \"success\", \"exceed\", \"remove\"],\n setup(props: any, ctx: any) {\n const { ui } = useUi();\n const { t } = useI18n();\n // uploader 的 modelValue\n const fileList: Ref = ref([]);\n const currentValue: Ref = ref();\n const fileUploaderRef: Ref = ref();\n\n const pickFileName = computed(() => {\n return (\n props.getFileName ||\n (async (url: string) => {\n if (typeof url !== \"string\") {\n console.warn(\"获取文件名失败请配置getFileName\");\n return url;\n }\n const suffix = url.substring(url.lastIndexOf(\"/\") + 1);\n const wenIndex = suffix.indexOf(\"?\");\n if (wenIndex >= 0) {\n return suffix.substring(0, wenIndex);\n }\n return suffix;\n })\n );\n });\n\n function getValueByValueType(item: any) {\n if (props.valueType === \"object\") {\n return item;\n }\n return item[props.valueType];\n }\n\n function getValueByValueTypeFromList(list: any[]) {\n const values = [];\n for (let item of list) {\n values.push(getValueByValueType(item));\n }\n return values;\n }\n\n async function buildListToFile(list: any[]) {\n const arr = [];\n for (let value of list) {\n let fileValue: any;\n if (\n typeof value === \"string\" ||\n typeof value === \"number\" ||\n typeof value === \"boolean\" ||\n value instanceof Date\n ) {\n fileValue = {\n url: undefined,\n key: value,\n value\n };\n if (props.valueType !== \"object\") {\n fileValue[props.valueType] = value;\n }\n } else {\n fileValue = value;\n }\n if (!fileValue[ui.upload.id]) {\n fileValue[ui.upload.id] = Math.random() + \"\";\n }\n if (!fileValue.status) {\n fileValue.status = ui.upload.status.success;\n }\n arr.push(fileValue);\n }\n await buildFileItemUrls(arr);\n for (const item of arr) {\n if (!item.name) {\n const url = item.url || item.value;\n item.name = await pickFileName.value(url, item);\n }\n }\n return arr;\n }\n\n async function buildListToValue(list: any[]) {\n const arr: any = [];\n for (let file of list) {\n const res = file.response || file.fsRes;\n const value: FileItem = {\n size: file.size,\n name: file.name,\n uid: file.uid,\n ...(res != null ? res : file)\n };\n arr.push(value);\n }\n await buildFileItemUrls(arr);\n return getValueByValueTypeFromList(arr);\n }\n\n async function initFileList(value: any) {\n const array: any = [];\n if (value == null || value.length === 0) {\n fileList.value = array;\n return;\n }\n if (value instanceof Array) {\n for (let item of value) {\n array.push(item);\n }\n } else {\n array.push(value);\n }\n\n const list = await buildListToFile(array);\n updateFileList(list);\n }\n\n async function onFormValueChanged() {\n await formValidator.onChange();\n await formValidator.onBlur();\n }\n\n async function emitValue(list: FileItem[]) {\n let value = await buildEmitValue(list);\n onInput(value);\n nextTick(async () => {\n await onFormValueChanged();\n });\n }\n\n async function buildEmitValue(fList: FileItem[]) {\n if (fList == null || fList.length === 0) {\n return props.limit === 1 ? null : [];\n }\n\n if (props.limit === 1) {\n const list: any = await buildListToValue(fList);\n return list[0];\n }\n const array: any = [];\n for (let item of fList) {\n if (ui.upload.isSuccess(item)) {\n array.push(item);\n }\n }\n return await buildListToValue(array);\n }\n\n async function buildFileItemUrls(list: any[]) {\n let needUrlItems = list.filter((item) => {\n return item.url == null;\n });\n if (props.buildUrls) {\n const values = needUrlItems.map((item) => {\n return getValueByValueType(item);\n });\n const urls = await props.buildUrls(values);\n for (let i = 0; i < needUrlItems.length; i++) {\n needUrlItems[i].url = urls[i];\n }\n } else if (props.buildUrl) {\n for (let needUrlItem of needUrlItems) {\n needUrlItem.url = await props.buildUrl(getValueByValueType(needUrlItem));\n }\n } else {\n for (let needUrlItem of needUrlItems) {\n needUrlItem.url = needUrlItem.value || needUrlItem.key;\n }\n }\n }\n\n function onChange(value: any) {\n ctx.emit(\"change\", value);\n }\n\n function onInput(value: any) {\n currentValue.value = value;\n ctx.emit(\"update:modelValue\", value);\n }\n\n const formValidator = ui.formItem.injectFormItemContext();\n watch(\n () => {\n return props.modelValue;\n },\n async (value) => {\n onChange(value);\n if (value === currentValue.value) {\n return;\n }\n await initFileList(value);\n }\n );\n //@ts-ignore\n // eslint-disable-next-line vue/no-setup-props-destructure\n initFileList(props.modelValue);\n\n function hasUploading() {\n const uploading = fileList.value.filter((item: any) => {\n return item.status === ui.upload.status.uploading;\n });\n return uploading.length > 0;\n }\n\n function handleChange(file: any, list: any) {\n updateFileList(list);\n emitValue(list);\n }\n\n function handleSuccess(res: any, file: any, list: any) {\n ctx.emit(\"success\", { res, file, fileList: list });\n handleChange(file, list);\n }\n\n function formatFileSize(fileSize: number) {\n let sizeTip;\n if (fileSize > 1024 * 1024 * 1024) {\n sizeTip = (fileSize / (1024 * 1024 * 1024)).toFixed(2) + \"G\";\n } else if (fileSize > 1024 * 1024) {\n sizeTip = (fileSize / (1024 * 1024)).toFixed(2) + \"M\";\n } else {\n sizeTip = Math.round(fileSize / 1024) + \"K\";\n }\n return sizeTip;\n }\n\n const computedOnLimit = (isCheck = false) => {\n const add = isCheck ? ui.upload.limitAdd : 0;\n return props.limit > 0 && fileList.value.length >= props.limit + add;\n };\n\n function showLimitTip() {\n if (props.showLimitTip) {\n ui.message.warn(t(\"fs.extends.fileUploader.limitTip\", [props.limit]));\n }\n }\n\n function checkLimit() {\n if (computedOnLimit(true)) {\n showLimitTip();\n ctx.emit(\"exceed\", { fileList: fileList.value, limit: props.limit });\n throw new Error(\"文件数量超限\");\n }\n }\n\n function checkSizeLimit(file: any) {\n if (props.sizeLimit != null) {\n let limit = props.sizeLimit;\n let showMessage: any = null;\n if (typeof props.sizeLimit === \"number\") {\n showMessage = (fileSize: number, limit: number) => {\n const limitTip = formatFileSize(limit);\n const fileSizeTip = formatFileSize(file.size);\n ui.message.warn(t(\"fs.extends.fileUploader.sizeLimitTip\", [limitTip, fileSizeTip]));\n };\n } else {\n limit = props.sizeLimit.limit;\n showMessage = props.sizeLimit.tip;\n }\n if (file.size > limit) {\n let message = \"文件大小超过限制,当前文件大小:\" + file.size / 1024 + \"k\";\n showMessage(file.size, limit);\n throw new Error(message);\n }\n }\n }\n\n /**\n * 图片上传前判断图片像素尺寸是否符合\n * @param file\n */\n const checkPixelLimit = (file: File): Promise<boolean> => {\n let imageMaxWidth = 0;\n let imageMaxHeight = 0;\n let tip = \"\";\n if (!props.pixelLimit) {\n return Promise.resolve(true);\n } else if (Array.isArray(props.pixelLimit)) {\n imageMaxWidth = props.pixelLimit[0];\n imageMaxHeight = props.pixelLimit[1] || props.pixelLimit[0] || 0;\n tip = props.pixelLimit[2] || \"\";\n } else if (typeof props.pixelLimit == \"object\") {\n imageMaxWidth = props.pixelLimit.width || 0;\n imageMaxHeight = props.pixelLimit.height || 0;\n tip = props.pixelLimit.tip || \"\";\n }\n let errMsg = tip || t(\"fs.extends.fileUploader.pixelLimitTip\", [imageMaxWidth, imageMaxHeight]);\n return new Promise((resolve, reject) => {\n let reader = new FileReader();\n reader.onload = (e) => {\n let src = e.target?.result;\n let image = new Image();\n image.onload = function () {\n if (imageMaxWidth && image.width > imageMaxWidth) {\n ui.message.warn(errMsg);\n reject(errMsg);\n } else if (imageMaxHeight && image.height > imageMaxHeight) {\n ui.message.warn(errMsg);\n reject(errMsg);\n } else {\n resolve(true);\n }\n };\n image.onerror = function (e) {\n ui.message.warn(t(\"fs.extends.fileUploader.loadError\"));\n reject(t(\"fs.extends.fileUploader.loadError\"));\n };\n if (src) {\n image.src = src as string;\n }\n };\n reader.readAsDataURL(file);\n });\n };\n const beforeUpload = async (file: any, list = fileList.value) => {\n if (props.beforeUpload) {\n const ret = await props.beforeUpload({ file, fileList: fileList.value });\n if (ret === false) {\n return false;\n }\n }\n try {\n checkLimit();\n checkSizeLimit(file);\n if (isPicture()) {\n await checkPixelLimit(file);\n }\n } catch (e) {\n return false;\n }\n };\n\n function updateFileList(list: any) {\n fileList.value = list;\n }\n\n async function doUpload(option: FsUploaderDoUploadOptions) {\n option.options = props.uploader || {};\n const { getUploaderImpl } = useUploader();\n let uploaderRef = await getUploaderImpl(option.options.type);\n if (uploaderRef == null) {\n ui.message.warn(\"SorryThe uploader component is not ready yet\");\n throw new Error(\"SorryThe component is not ready yet\");\n }\n return await uploaderRef?.upload(option);\n }\n\n async function customRequest(context: any) {\n if (props.beforeUploadRequest) {\n await props.beforeUploadRequest(context);\n }\n\n const { file, onProgress, onSuccess, onError } = context;\n\n const option = {\n file,\n fileName: file.name,\n onProgress\n };\n try {\n const ret = await doUpload(option);\n onSuccess(ret);\n } catch (e) {\n console.error(\"上传失败\", e);\n onError(e);\n }\n }\n\n const computedFileSelectBtn = computed(() => {\n if (isPictureCard()) {\n return {\n is: \"FsIcon\",\n icon: ui.icons.plus\n };\n }\n return {\n is: \"FsButton\",\n icon: ui.icons.upload,\n text: t(\"fs.extends.fileUploader.text\"),\n ...props.button\n };\n });\n\n const previewVisible: Ref = ref(false);\n const previewImage: Ref = ref();\n const computedPreview = computed(() => {\n return {\n ...ui.dialog.footer(),\n ...props.preview\n };\n });\n\n function getBase64(file: File) {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.readAsDataURL(file);\n reader.onload = () => resolve(reader.result);\n reader.onerror = (error) => reject(error);\n });\n }\n\n function isPicture() {\n return props.listType === ui.upload.typeImageCard || props.listType === ui.upload.typeImage;\n }\n\n function isPictureCard() {\n return props.listType === ui.upload.typeImageCard;\n }\n\n const handlePreview = async (file: any) => {\n if (!isPicture()) {\n let url;\n if (file.url) {\n url = file.url;\n } else {\n if (ui.type === \"antdv\") {\n url = file.response?.url;\n } else if (ui.type === \"element\") {\n url = file.fsRes?.url;\n } else {\n url = file.url;\n }\n }\n window.open(url, \"_blank\");\n }\n if (!file.url && !file.preview && file.originFileObj) {\n file.preview = await getBase64(file.originFileObj);\n }\n previewImage.value = file.url || file.preview;\n previewVisible.value = true;\n };\n\n function buildAntdvBinding() {\n const res: any = {\n customRequest,\n beforeUpload,\n limit: props.limit,\n listType: props.listType,\n onChange: (change: any) => {\n const { file, fileList } = change;\n handleChange(file, fileList);\n if (file.status === \"done\") {\n handleSuccess(file.response, file, fileList);\n }\n },\n onPreview: handlePreview\n };\n\n if (props.limit != null && ctx.attrs.maxCount == null) {\n res.maxCount = props.limit;\n }\n return res;\n }\n\n function buildElementBinding() {\n return {\n action: \"\",\n listType: props.listType,\n limit: props.limit,\n beforeUpload: beforeUpload,\n httpRequest: customRequest,\n onExceed: (event) => {\n ctx.emit(\"exceed\", event, fileList);\n },\n onRemove: (file: any, fileList: any) => {\n handleChange(file, fileList);\n ctx.emit(\"remove\", file, fileList);\n },\n onChange: (file: any, fileList: any) => {\n handleChange(file, fileList);\n },\n onSuccess: (res: any, file: any, fileList: any) => {\n if (res == null) {\n return;\n }\n file.response = res;\n file.fsRes = res;\n handleSuccess(res, file, fileList);\n },\n // \"on-error\": \"handleUploadFileError\",\n // \"on-progress\": \"handleUploadProgress\"\n onPreview: handlePreview\n };\n }\n\n const naiveExtraCache: any = {};\n\n function buildNaiveBinding() {\n function appendExtra(fileList: any) {\n let list = fileList.value || fileList;\n list = cloneDeep(list);\n for (let item of list) {\n const extra = naiveExtraCache[item.id];\n if (extra) {\n merge(item, extra);\n }\n }\n return list;\n }\n\n return {\n action: \"\",\n limit: props.limit,\n listType: props.listType,\n onBeforeUpload: async ({ file, fileList }: any) => {\n return beforeUpload(file, fileList);\n },\n customRequest: (context: any) => {\n const fileInfo = context.file;\n customRequest({\n ...context,\n file: fileInfo.file,\n onSuccess: async (res: any) => {\n //TODO native upload 会清空多余自定义的属性比如key、md5\n const value = props.valueType === \"object\" ? res : res[props.valueType];\n res.url = await props.buildUrl(value);\n merge(fileInfo, res);\n naiveExtraCache[fileInfo.id] = {\n ...res,\n fsRes: res\n };\n context.onFinish(fileInfo);\n },\n onProgress: (opts: any) => {\n context.onProgress(opts);\n }\n });\n },\n onExceed: (event) => {\n ctx.emit(\"exceed\", event);\n },\n onRemove: (opts: any) => {\n const { file, fileList } = opts;\n // handleChange(file, [...fileList]);\n ctx.emit(\"remove\", opts);\n },\n onChange: (opts: any) => {\n const { event, file, fileList } = opts;\n const list = appendExtra(fileList);\n handleChange(file, [...list]);\n },\n onFinish: (file: any) => {\n const extra = naiveExtraCache[file.id];\n if (extra) {\n merge(file, extra);\n }\n const list = appendExtra(fileList);\n handleSuccess(extra, file, list);\n },\n onPreview: handlePreview\n };\n }\n\n const computedBinding = computed(() => {\n let binding: any = null;\n if (ui.type === \"antdv\") {\n binding = buildAntdvBinding();\n } else if (ui.type === \"element\") {\n binding = buildElementBinding();\n } else {\n binding = buildNaiveBinding();\n }\n return {\n ...binding,\n ...ctx.attrs\n };\n });\n\n return {\n ui,\n fileList,\n fileUploaderRef,\n initValue: initFileList,\n onChange,\n onInput,\n hasUploading,\n isPicture,\n computedFileSelectBtn,\n previewVisible,\n previewImage,\n computedPreview,\n computedOnLimit,\n computedBinding,\n emitValue\n };\n }\n});\n</script>\n<style lang=\"less\">\n.fs-file-uploader {\n // antdv\n &.fs-file-uploader-limit {\n .ant-upload-select-picture-card {\n display: none;\n }\n }\n\n .ant-upload-list-item-actions {\n display: flex;\n justify-content: center;\n align-items: center;\n\n > a {\n display: flex;\n align-items: center;\n justify-content: center;\n }\n }\n\n .el-upload {\n justify-content: left;\n }\n\n // element\n .el-upload-list--picture-card .el-upload-list__item {\n width: 100px;\n height: 100px;\n //line-height: 100px;\n }\n\n .el-upload--picture-card {\n width: 100px;\n height: 100px;\n justify-content: center;\n }\n\n &.fs-file-uploader-limit {\n .el-upload--picture-card {\n display: none;\n }\n }\n\n .el-upload--text {\n width: 100%;\n text-align: left;\n\n .el-upload-dragger {\n width: 100%;\n\n .el-button {\n width: 100%;\n height: 100%;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n\n .el-icon-upload {\n margin: 0;\n margin-bottom: 10px;\n }\n }\n }\n }\n}\n</style>\n","<template>\n <div class=\"fs-file-uploader\" :class=\"{ 'fs-file-uploader-limit': computedOnLimit() }\">\n <component :is=\"ui.upload.name\" ref=\"fileUploaderRef\" v-model:file-list=\"fileList\" v-bind=\"computedBinding\">\n <component :is=\"computedFileSelectBtn.is\" v-bind=\"computedFileSelectBtn\" />\n </component>\n <component\n :is=\"ui.dialog.name\"\n v-if=\"isPicture()\"\n v-model:[ui.dialog.visible]=\"previewVisible\"\n v-bind=\"computedPreview\"\n >\n <img style=\"max-width: 100%; max-height: 100%\" :src=\"previewImage\" />\n </component>\n </div>\n</template>\n\n<script lang=\"ts\">\nimport { computed, defineComponent, nextTick, Ref, ref, watch } from \"vue\";\nimport { useI18n, useUi } from \"@fast-crud/fast-crud\";\nimport { merge, cloneDeep } from \"lodash-es\";\nimport { FileItem, FsUploaderDoUploadOptions } from \"../d/type\";\nimport { useUploader } from \"./utils\";\nimport type { PropType } from \"vue\";\n\n/**\n * 限制上传图片的像素尺寸\n */\ntype PixelLimit = { width?: number; height?: number; tip?: string } | [number, number?, string?];\n/**\n * 文件上传组件\n * 支持对应ui库的[x]-file-uploader组件的配置\n */\nexport default defineComponent({\n name: \"FsFileUploader\",\n inheritAttrs: false,\n props: {\n /**\n * value\n */\n modelValue: {},\n /**\n * 限制文件数量\n * 当限制数量>1时返回值为数组\n */\n limit: {\n type: Number\n },\n /**\n * 文件大小限制,单位:字节\n * 可以直接传一个数字,也可以传 `{limit:number,tip:'自定义提示文本'}`\n */\n sizeLimit: {\n type: [Number, Object]\n },\n /**\n * 限制上传图片的像素尺寸\n * 可以传数组会对象{ width?: number, height?: number, tip?: string } | [number, number?, string?]\n */\n pixelLimit: {\n type: Object as PropType<PixelLimit>,\n required: false\n },\n /**\n * 是否显示限制提示\n */\n showLimitTip: {\n type: Boolean,\n default: true\n },\n /**\n * 构建url的方法\n * 后台返回key之后将其build成一个可访问的url用于反显\n * 如果successHandle返回的object中已包含url此配置将不会执行\n */\n buildUrl: {\n default() {\n return (value: any) => {\n return value;\n };\n }\n },\n /**\n * 多个value值构建多个url\n * 如果successHandle 返回的object中已包含url此方法将不会执行\n */\n buildUrls: {},\n /**\n * 上传按钮配置参考FsButton参数\n */\n button: {\n type: Object\n },\n /**\n * 展示模式,对应[x]-uploader组件的 listType参数\n */\n listType: {\n type: String\n },\n /**\n * 上传前的判断操作\n */\n beforeUpload: {\n type: Function\n },\n\n /**\n * 上传请求前的操作可以压缩图片等替换掉context中的file\n * type: `async (context)=>void`\n */\n beforeUploadRequest: {\n type: Function\n },\n /**\n * FsUploaderXXX的配置\n * 可以覆盖全局配置里各个上传类型对应的配置\n * 例如: `{action:'xxx',bucket:'xxx',...}`\n */\n uploader: {\n type: Object\n },\n /**\n * 预览配置\n */\n preview: {\n type: Object\n },\n /**\n * 上传成功后从结果中取值类型\n * 支持:`[object,url,key,其他successHandle返回的object内要有该字段不要用'id']`\n * 如果配置了非url则需要配置buildUrl用于反显\n */\n valueType: {\n type: String, // url ,key, object\n default: \"url\"\n },\n /**\n * 根据value获取文件名用于显示在fileList里面\n */\n getFileName: {}\n },\n emits: [\"change\", \"update:modelValue\", \"success\", \"exceed\", \"remove\"],\n setup(props: any, ctx: any) {\n const { ui } = useUi();\n const { t } = useI18n();\n // uploader 的 modelValue\n const fileList: Ref = ref([]);\n const currentValue: Ref = ref();\n const fileUploaderRef: Ref = ref();\n\n const pickFileName = computed(() => {\n return (\n props.getFileName ||\n (async (url: string) => {\n if (typeof url !== \"string\") {\n console.warn(\"获取文件名失败请配置getFileName\");\n return url;\n }\n const suffix = url.substring(url.lastIndexOf(\"/\") + 1);\n const wenIndex = suffix.indexOf(\"?\");\n if (wenIndex >= 0) {\n return suffix.substring(0, wenIndex);\n }\n return suffix;\n })\n );\n });\n\n function getValueByValueType(item: any) {\n if (props.valueType === \"object\") {\n return item;\n }\n return item[props.valueType];\n }\n\n function getValueByValueTypeFromList(list: any[]) {\n const values = [];\n for (let item of list) {\n values.push(getValueByValueType(item));\n }\n return values;\n }\n\n async function buildListToFile(list: any[]) {\n const arr = [];\n for (let value of list) {\n let fileValue: any;\n if (\n typeof value === \"string\" ||\n typeof value === \"number\" ||\n typeof value === \"boolean\" ||\n value instanceof Date\n ) {\n fileValue = {\n url: undefined,\n key: value,\n value\n };\n if (props.valueType !== \"object\") {\n fileValue[props.valueType] = value;\n }\n } else {\n fileValue = value;\n }\n if (!fileValue[ui.upload.id]) {\n fileValue[ui.upload.id] = Math.random() + \"\";\n }\n if (!fileValue.status) {\n fileValue.status = ui.upload.status.success;\n }\n arr.push(fileValue);\n }\n await buildFileItemUrls(arr);\n for (const item of arr) {\n if (!item.name) {\n const url = item.url || item.value;\n item.name = await pickFileName.value(url, item);\n }\n }\n return arr;\n }\n\n async function buildListToValue(list: any[]) {\n const arr: any = [];\n for (let file of list) {\n const res = file.response || file.fsRes;\n const value: FileItem = {\n size: file.size,\n name: file.name,\n uid: file.uid,\n ...(res != null ? res : file)\n };\n arr.push(value);\n }\n await buildFileItemUrls(arr);\n return getValueByValueTypeFromList(arr);\n }\n\n async function initFileList(value: any) {\n const array: any = [];\n if (value == null || value.length === 0) {\n fileList.value = array;\n return;\n }\n if (value instanceof Array) {\n for (let item of value) {\n array.push(item);\n }\n } else {\n array.push(value);\n }\n\n const list = await buildListToFile(array);\n updateFileList(list);\n }\n\n async function onFormValueChanged() {\n await formValidator.onChange();\n await formValidator.onBlur();\n }\n\n async function emitValue(list: FileItem[]) {\n let value = await buildEmitValue(list);\n onInput(value);\n nextTick(async () => {\n await onFormValueChanged();\n });\n }\n\n async function buildEmitValue(fList: FileItem[]) {\n if (fList == null || fList.length === 0) {\n return props.limit === 1 ? null : [];\n }\n\n if (props.limit === 1) {\n const list: any = await buildListToValue(fList);\n return list[0];\n }\n const array: any = [];\n for (let item of fList) {\n if (ui.upload.isSuccess(item)) {\n array.push(item);\n }\n }\n return await buildListToValue(array);\n }\n\n async function buildFileItemUrls(list: any[]) {\n let needUrlItems = list.filter((item) => {\n return item.url == null;\n });\n if (props.buildUrls) {\n const values = needUrlItems.map((item) => {\n return getValueByValueType(item);\n });\n const urls = await props.buildUrls(values);\n for (let i = 0; i < needUrlItems.length; i++) {\n needUrlItems[i].url = urls[i];\n }\n } else if (props.buildUrl) {\n for (let needUrlItem of needUrlItems) {\n needUrlItem.url = await props.buildUrl(getValueByValueType(needUrlItem));\n }\n } else {\n for (let needUrlItem of needUrlItems) {\n needUrlItem.url = needUrlItem.value || needUrlItem.key;\n }\n }\n }\n\n function onChange(value: any) {\n ctx.emit(\"change\", value);\n }\n\n function onInput(value: any) {\n currentValue.value = value;\n ctx.emit(\"update:modelValue\", value);\n }\n\n const formValidator = ui.formItem.injectFormItemContext();\n watch(\n () => {\n return props.modelValue;\n },\n async (value) => {\n onChange(value);\n if (value === currentValue.value) {\n return;\n }\n await initFileList(value);\n }\n );\n //@ts-ignore\n // eslint-disable-next-line vue/no-setup-props-destructure\n initFileList(props.modelValue);\n\n function hasUploading() {\n const uploading = fileList.value.filter((item: any) => {\n return item.status === ui.upload.status.uploading;\n });\n return uploading.length > 0;\n }\n\n function handleChange(file: any, list: any) {\n updateFileList(list);\n emitValue(list);\n }\n\n function handleSuccess(res: any, file: any, list: any) {\n ctx.emit(\"success\", { res, file, fileList: list });\n handleChange(file, list);\n }\n\n function formatFileSize(fileSize: number) {\n let sizeTip;\n if (fileSize > 1024 * 1024 * 1024) {\n sizeTip = (fileSize / (1024 * 1024 * 1024)).toFixed(2) + \"G\";\n } else if (fileSize > 1024 * 1024) {\n sizeTip = (fileSize / (1024 * 1024)).toFixed(2) + \"M\";\n } else {\n sizeTip = Math.round(fileSize / 1024) + \"K\";\n }\n return sizeTip;\n }\n\n const computedOnLimit = (isCheck = false) => {\n const add = isCheck ? ui.upload.limitAdd : 0;\n return props.limit > 0 && fileList.value.length >= props.limit + add;\n };\n\n function showLimitTip() {\n if (props.showLimitTip) {\n ui.message.warn(t(\"fs.extends.fileUploader.limitTip\", [props.limit]));\n }\n }\n\n function checkLimit() {\n if (computedOnLimit(true)) {\n showLimitTip();\n ctx.emit(\"exceed\", { fileList: fileList.value, limit: props.limit });\n throw new Error(\"文件数量超限\");\n }\n }\n\n function checkSizeLimit(file: any) {\n if (props.sizeLimit != null) {\n let limit = props.sizeLimit;\n let showMessage: any = null;\n if (typeof props.sizeLimit === \"number\") {\n showMessage = (fileSize: number, limit: number) => {\n const limitTip = formatFileSize(limit);\n const fileSizeTip = formatFileSize(file.size);\n ui.message.warn(t(\"fs.extends.fileUploader.sizeLimitTip\", [limitTip, fileSizeTip]));\n };\n } else {\n limit = props.sizeLimit.limit;\n showMessage = props.sizeLimit.tip;\n }\n if (file.size > limit) {\n let message = \"文件大小超过限制,当前文件大小:\" + file.size / 1024 + \"k\";\n showMessage(file.size, limit);\n throw new Error(message);\n }\n }\n }\n\n /**\n * 图片上传前判断图片像素尺寸是否符合\n * @param file\n */\n const checkPixelLimit = (file: File): Promise<boolean> => {\n let imageMaxWidth = 0;\n let imageMaxHeight = 0;\n let tip = \"\";\n if (!props.pixelLimit) {\n return Promise.resolve(true);\n } else if (Array.isArray(props.pixelLimit)) {\n imageMaxWidth = props.pixelLimit[0];\n imageMaxHeight = props.pixelLimit[1] || props.pixelLimit[0] || 0;\n tip = props.pixelLimit[2] || \"\";\n } else if (typeof props.pixelLimit == \"object\") {\n imageMaxWidth = props.pixelLimit.width || 0;\n imageMaxHeight = props.pixelLimit.height || 0;\n tip = props.pixelLimit.tip || \"\";\n }\n let errMsg = tip || t(\"fs.extends.fileUploader.pixelLimitTip\", [imageMaxWidth, imageMaxHeight]);\n return new Promise((resolve, reject) => {\n let reader = new FileReader();\n reader.onload = (e) => {\n let src = e.target?.result;\n let image = new Image();\n image.onload = function () {\n if (imageMaxWidth && image.width > imageMaxWidth) {\n ui.message.warn(errMsg);\n reject(errMsg);\n } else if (imageMaxHeight && image.height > imageMaxHeight) {\n ui.message.warn(errMsg);\n reject(errMsg);\n } else {\n resolve(true);\n }\n };\n image.onerror = function (e) {\n ui.message.warn(t(\"fs.extends.fileUploader.loadError\"));\n reject(t(\"fs.extends.fileUploader.loadError\"));\n };\n if (src) {\n image.src = src as string;\n }\n };\n reader.readAsDataURL(file);\n });\n };\n const beforeUpload = async (file: any, list = fileList.value) => {\n if (props.beforeUpload) {\n const ret = await props.beforeUpload({ file, fileList: fileList.value });\n if (ret === false) {\n return false;\n }\n }\n try {\n checkLimit();\n checkSizeLimit(file);\n if (isPicture()) {\n await checkPixelLimit(file);\n }\n } catch (e) {\n return false;\n }\n };\n\n function updateFileList(list: any) {\n fileList.value = list;\n }\n\n async function doUpload(option: FsUploaderDoUploadOptions) {\n option.options = props.uploader || {};\n const { getUploaderImpl } = useUploader();\n let uploaderRef = await getUploaderImpl(option.options.type);\n if (uploaderRef == null) {\n ui.message.warn(\"SorryThe uploader component is not ready yet\");\n throw new Error(\"SorryThe component is not ready yet\");\n }\n return await uploaderRef?.upload(option);\n }\n\n async function customRequest(context: any) {\n if (props.beforeUploadRequest) {\n await props.beforeUploadRequest(context);\n }\n\n const { file, onProgress, onSuccess, onError } = context;\n\n const option = {\n file,\n fileName: file.name,\n onProgress\n };\n try {\n const ret = await doUpload(option);\n onSuccess(ret);\n } catch (e) {\n console.error(\"上传失败\", e);\n onError(e);\n }\n }\n\n const computedFileSelectBtn = computed(() => {\n if (isPictureCard()) {\n return {\n is: \"FsIcon\",\n icon: ui.icons.plus\n };\n }\n return {\n is: \"FsButton\",\n icon: ui.icons.upload,\n text: t(\"fs.extends.fileUploader.text\"),\n ...props.button\n };\n });\n\n const previewVisible: Ref = ref(false);\n const previewImage: Ref = ref();\n const computedPreview = computed(() => {\n return {\n ...ui.dialog.footer(),\n ...props.preview\n };\n });\n\n function getBase64(file: File) {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.readAsDataURL(file);\n reader.onload = () => resolve(reader.result);\n reader.onerror = (error) => reject(error);\n });\n }\n\n function isPicture() {\n return props.listType === ui.upload.typeImageCard || props.listType === ui.upload.typeImage;\n }\n\n function isPictureCard() {\n return props.listType === ui.upload.typeImageCard;\n }\n\n const handlePreview = async (file: any) => {\n if (!isPicture()) {\n let url;\n if (file.url) {\n url = file.url;\n } else {\n if (ui.type === \"antdv\") {\n url = file.response?.url;\n } else if (ui.type === \"element\") {\n url = file.fsRes?.url;\n } else {\n url = file.url;\n }\n }\n window.open(url, \"_blank\");\n }\n if (!file.url && !file.preview && file.originFileObj) {\n file.preview = await getBase64(file.originFileObj);\n }\n previewImage.value = file.url || file.preview;\n previewVisible.value = true;\n };\n\n function buildAntdvBinding() {\n const res: any = {\n customRequest,\n beforeUpload,\n limit: props.limit,\n listType: props.listType,\n onChange: (change: any) => {\n const { file, fileList } = change;\n handleChange(file, fileList);\n if (file.status === \"done\") {\n handleSuccess(file.response, file, fileList);\n }\n },\n onPreview: handlePreview\n };\n\n if (props.limit != null && ctx.attrs.maxCount == null) {\n res.maxCount = props.limit;\n }\n return res;\n }\n\n function buildElementBinding() {\n return {\n action: \"\",\n listType: props.listType,\n limit: props.limit,\n beforeUpload: beforeUpload,\n httpRequest: customRequest,\n onExceed: (event) => {\n ctx.emit(\"exceed\", event, fileList);\n },\n onRemove: (file: any, fileList: any) => {\n handleChange(file, fileList);\n ctx.emit(\"remove\", file, fileList);\n },\n onChange: (file: any, fileList: any) => {\n handleChange(file, fileList);\n },\n onSuccess: (res: any, file: any, fileList: any) => {\n if (res == null) {\n return;\n }\n file.response = res;\n file.fsRes = res;\n handleSuccess(res, file, fileList);\n },\n // \"on-error\": \"handleUploadFileError\",\n // \"on-progress\": \"handleUploadProgress\"\n onPreview: handlePreview\n };\n }\n\n const naiveExtraCache: any = {};\n\n function buildNaiveBinding() {\n function appendExtra(fileList: any) {\n let list = fileList.value || fileList;\n list = cloneDeep(list);\n for (let item of list) {\n const extra = naiveExtraCache[item.id];\n if (extra) {\n merge(item, extra);\n }\n }\n return list;\n }\n\n return {\n action: \"\",\n limit: props.limit,\n listType: props.listType,\n onBeforeUpload: async ({ file, fileList }: any) => {\n return beforeUpload(file, fileList);\n },\n customRequest: (context: any) => {\n const fileInfo = context.file;\n customRequest({\n ...context,\n file: fileInfo.file,\n onSuccess: async (res: any) => {\n //TODO native upload 会清空多余自定义的属性比如key、md5\n const value = props.valueType === \"object\" ? res : res[props.valueType];\n res.url = await props.buildUrl(value);\n merge(fileInfo, res);\n naiveExtraCache[fileInfo.id] = {\n ...res,\n fsRes: res\n };\n context.onFinish(fileInfo);\n },\n onProgress: (opts: any) => {\n context.onProgress(opts);\n }\n });\n },\n onExceed: (event) => {\n ctx.emit(\"exceed\", event);\n },\n onRemove: (opts: any) => {\n const { file, fileList } = opts;\n // handleChange(file, [...fileList]);\n ctx.emit(\"remove\", opts);\n },\n onChange: (opts: any) => {\n const { event, file, fileList } = opts;\n const list = appendExtra(fileList);\n handleChange(file, [...list]);\n },\n onFinish: (file: any) => {\n const extra = naiveExtraCache[file.id];\n if (extra) {\n merge(file, extra);\n }\n const list = appendExtra(fileList);\n handleSuccess(extra, file, list);\n },\n onPreview: handlePreview\n };\n }\n\n const computedBinding = computed(() => {\n let binding: any = null;\n if (ui.type === \"antdv\") {\n binding = buildAntdvBinding();\n } else if (ui.type === \"element\") {\n binding = buildElementBinding();\n } else {\n binding = buildNaiveBinding();\n }\n return {\n ...binding,\n ...ctx.attrs\n };\n });\n\n return {\n ui,\n fileList,\n fileUploaderRef,\n initValue: initFileList,\n onChange,\n onInput,\n hasUploading,\n isPicture,\n computedFileSelectBtn,\n previewVisible,\n previewImage,\n computedPreview,\n computedOnLimit,\n computedBinding,\n emitValue\n };\n }\n});\n</script>\n<style lang=\"less\">\n.fs-file-uploader {\n // antdv\n &.fs-file-uploader-limit {\n .ant-upload-select-picture-card {\n display: none;\n }\n }\n\n .ant-upload-list-item-actions {\n display: flex;\n justify-content: center;\n align-items: center;\n\n > a {\n display: flex;\n align-items: center;\n justify-content: center;\n }\n }\n\n .el-upload {\n justify-content: left;\n }\n\n // element\n .el-upload-list--picture-card .el-upload-list__item {\n width: 100px;\n height: 100px;\n //line-height: 100px;\n }\n\n .el-upload--picture-card {\n width: 100px;\n height: 100px;\n justify-content: center;\n }\n\n &.fs-file-uploader-limit {\n .el-upload--picture-card {\n display: none;\n }\n }\n\n .el-upload--text {\n width: 100%;\n text-align: left;\n\n .el-upload-dragger {\n width: 100%;\n\n .el-button {\n width: 100%;\n height: 100%;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n\n .el-icon-upload {\n margin: 0;\n margin-bottom: 10px;\n }\n }\n }\n }\n}\n</style>\n"],"names":["_sfc_main","defineComponent","value","props","ctx","ui","useUi","t","useI18n","fileList","ref","currentValue","fileUploaderRef","pickFileName","computed","url","suffix","wenIndex","getValueByValueType","item","getValueByValueTypeFromList","list","values","buildListToFile","arr","fileValue","buildFileItemUrls","buildListToValue","file","res","initFileList","array","updateFileList","onFormValueChanged","formValidator","emitValue","buildEmitValue","onInput","nextTick","fList","needUrlItems","urls","i","needUrlItem","onChange","watch","hasUploading","handleChange","handleSuccess","formatFileSize","fileSize","sizeTip","computedOnLimit","isCheck","add","showLimitTip","checkLimit","checkSizeLimit","limit","showMessage","limitTip","fileSizeTip","message","checkPixelLimit","imageMaxWidth","imageMaxHeight","tip","errMsg","resolve","reject","reader","e","src","_a","image","beforeUpload","isPicture","doUpload","option","getUploaderImpl","useUploader","uploaderRef","customRequest","context","onProgress","onSuccess","onError","ret","computedFileSelectBtn","isPictureCard","previewVisible","previewImage","computedPreview","getBase64","error","handlePreview","_b","buildAntdvBinding","change","buildElementBinding","event","naiveExtraCache","buildNaiveBinding","appendExtra","cloneDeep","extra","merge","fileInfo","opts","computedBinding","binding","_sfc_render","_ctx","_cache","$props","$setup","$data","$options","_openBlock","_resolveDynamicComponent","_mergeProps","$event","_withCtx","_createElementVNode"],"mappings":"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"}