1 line
58 KiB
Plaintext
1 line
58 KiB
Plaintext
{"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(\"Sorry,The uploader component is not ready yet\");\n throw new Error(\"Sorry,The 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(\"Sorry,The uploader component is not ready yet\");\n throw new Error(\"Sorry,The 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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"} |