1 line
35 KiB
Plaintext
1 line
35 KiB
Plaintext
{"version":3,"file":"fs-cropper-uploader-c3fbe88c.mjs","sources":["../src/uploader/components/fs-cropper-uploader.vue","../src/uploader/components/fs-cropper-uploader.vue"],"sourcesContent":["<template>\n <div class=\"fs-cropper-uploader\" :class=\"{ 'is-disabled': computedProps.disabled }\">\n <div class=\"image-list\">\n <component :is=\"ui.imageGroup.name\">\n <div v-for=\"(item, index) in listRef\" :key=\"index\" class=\"image-item\">\n <component :is=\"ui.image.name\" class=\"image\" :src=\"getImageSrc(item)\" v-bind=\"computedProps.img\">\n <template #placeholder>\n <div class=\"image-slot\">\n <fs-loading :loading=\"true\" />\n </div>\n </template>\n </component>\n <div class=\"delete\">\n <fs-icon v-if=\"!computedProps.disabled\" :icon=\"ui.icons.remove\" @click=\"removeImage(index as number)\" />\n <fs-icon :icon=\"ui.icons.search\" @click=\"preview(item)\" />\n </div>\n <div v-if=\"item.status === 'uploading'\" class=\"status-uploading\">\n <component :is=\"ui.progress.name\" type=\"circle\" :percentage=\"item.progress\" :width=\"70\" />\n </div>\n <div v-else-if=\"item.status === 'done'\" class=\"status-done\">\n <fs-icon :icon=\"ui.icons.check\" class=\"status-down-icon\" />\n </div>\n </div>\n <div\n v-if=\"computedProps.limit <= 0 || computedProps.limit > listRef.length\"\n class=\"image-item image-plus\"\n @click=\"addNewImage\"\n >\n <fs-icon :icon=\"ui.icons.plus\" class=\"cropper-uploader-icon\" />\n </div>\n </component>\n </div>\n <fs-cropper\n ref=\"cropperRef\"\n :title=\"computedProps.title\"\n :cropper-height=\"computedProps.cropperHeight\"\n :dialog-width=\"computedProps.dialogWidth\"\n :accept=\"computedProps.accept\"\n :upload-tip=\"computedProps.uploadTip\"\n :max-size=\"computedProps.maxSize\"\n :cropper=\"computedProps.cropper\"\n :compress-quality=\"computedProps.compressQuality\"\n output=\"all\"\n @done=\"cropComplete\"\n @ready=\"doReady\"\n />\n <div class=\"fs-cropper-preview\" :class=\"{ open: previewVisible }\" @click=\"closePreview\">\n <div class=\"fs-cropper-preview-content\">\n <img v-if=\"previewUrl\" :src=\"previewUrl\" class=\"preview-image\" />\n </div>\n </div>\n </div>\n</template>\n\n<script lang=\"ts\">\nimport { computed, defineComponent, getCurrentInstance, reactive, ref, Ref, watch } from \"vue\";\nimport { useUi } from \"@fast-crud/fast-crud\";\nimport { FsUploaderDoUploadOptions } from \"../d/type\";\nimport { useUploader } from \"./utils\";\n\n/**\n * 图片裁剪上传组件,封装了fs-cropper\n * fs-cropper内部封装了[cropperjs](https://github.com/fengyuanchen/cropperjs)\n */\nexport default defineComponent({\n name: \"FsCropperUploader\",\n props: {\n /**\n * 初始图片url,或者是数组\n */\n modelValue: {\n type: [String, Object, Array]\n },\n img: {},\n /**\n * 上传后端类型,[form, cos, qiniu , alioss]\n */\n type: {\n type: String\n },\n /**\n * 上传提示\n */\n uploadTip: {\n type: String\n },\n /**\n * 对话框标题\n */\n title: String,\n /**\n * cropper的高度,默认为浏览器可视窗口高度的40%,最小270\n */\n cropperHeight: {\n type: [String, Number]\n },\n /**\n * 对话框宽度,默认50%\n */\n dialogWidth: {\n type: [String, Number],\n default: \"50%\"\n },\n /**\n * 图片大小限制,单位MB\n */\n maxSize: {\n type: Number,\n default: 5\n },\n /**\n * 图片数量限制,0为不限制\n */\n limit: {\n type: Number,\n default: 1\n },\n /**\n * 可接收的文件后缀\n */\n accept: {\n type: String,\n default: \".jpg, .jpeg, .png, .gif, .webp\"\n },\n /**\n * [cropperjs的参数](https://github.com/fengyuanchen/cropperjs)\n */\n cropper: {\n type: Object\n },\n /**\n * FsUploaderXXX的配置,会临时覆盖全局上传配置参数\n */\n uploader: {\n type: Object\n },\n /**\n * 压缩质量\n */\n compressQuality: {\n type: Number,\n default: 0.8\n },\n /**\n * 构建下载url方法,不影响提交的value\n */\n buildUrl: {\n type: Function,\n default: async function (value: any) {\n return typeof value === \"object\" ? value.url : value;\n }\n },\n /**\n * 返回值类型\n * 支持:`[url,key,object]`\n */\n valueType: {\n type: String, // url ,key, object\n default: \"url\"\n },\n /**\n * 是否禁用\n */\n disabled: {}\n },\n emits: [\"update:modelValue\", \"change\", \"ready\"],\n setup(props: any, ctx: any) {\n const { ui } = useUi();\n const cropperRef: Ref = ref();\n const uploaderImplRef: Ref = ref();\n\n const indexRef: Ref = ref();\n const listRef: Ref = ref([]);\n const formValidator = ui.formItem.injectFormItemContext();\n // eslint-disable-next-line vue/no-setup-props-destructure\n // @ts-ignore\n let emitValue: any = props.modelValue;\n // eslint-disable-next-line vue/no-setup-props-destructure\n // @ts-ignore\n initValue(props.modelValue);\n\n async function initValue(value: any) {\n const list: any = [];\n if (value == null || value === \"\") {\n listRef.value = list;\n return;\n }\n if (typeof value === \"string\") {\n // @ts-ignore\n list.push({ url: await props.buildUrl(value), value: value, status: \"done\" });\n } else if (Array.isArray(value)) {\n for (const item of value) {\n // @ts-ignore\n list.push({ url: await props.buildUrl(item), value: item, status: \"done\" });\n }\n } else if (typeof value === \"object\") {\n // @ts-ignore\n list.push({ url: await props.buildUrl(value), value, status: \"done\" });\n } else {\n for (const item of value) {\n // @ts-ignore\n list.push({ url: await props.buildUrl(item), value: item, status: \"done\" });\n }\n }\n listRef.value = list;\n }\n function addNewImage() {\n // @ts-ignore\n if (props.disabled) {\n return;\n }\n indexRef.value = undefined;\n cropperRef.value.clear();\n cropperRef.value.open();\n }\n function removeImage(index: number) {\n listRef.value.splice(index, 1);\n doEmit();\n }\n function hasUploading() {\n const fileList: any = listRef.value;\n if (fileList && fileList.length > 0) {\n for (const item of fileList) {\n if (item.status === \"uploading\") {\n return true;\n }\n }\n }\n return false;\n }\n async function cropComplete(ret: any) {\n const blob = ret.blob;\n const dataUrl = ret.dataUrl;\n const file = ret.file;\n const filename = file.name;\n const blobFile = new File([blob], filename, { type: blob.type });\n\n // 开始上传\n const item: any = reactive({\n url: undefined,\n dataUrl: dataUrl,\n status: \"uploading\",\n progress: 0\n });\n const onProgress = (e: any) => {\n item.progress = e.percent;\n };\n const onError = (e: any) => {\n item.status = \"error\";\n item.message = \"文件上传出错:\" + e.message;\n console.error(e);\n };\n const option = {\n file: blobFile,\n onProgress,\n onError,\n fileName: filename\n };\n listRef.value.push(item);\n try {\n const uploaded = await doUpload(option);\n let value = uploaded;\n // @ts-ignore\n if (props.valueType !== \"object\") {\n // @ts-ignore\n value = uploaded[props.valueType];\n }\n // @ts-ignore\n item.url = await props.buildUrl(value);\n item.value = value;\n item.status = \"done\";\n doEmit();\n } catch (e) {\n onError(e);\n }\n }\n\n async function doUpload(option: FsUploaderDoUploadOptions) {\n // @ts-ignore\n option.options = props.uploader || {};\n const { getUploaderImpl } = useUploader();\n let uploaderRef = await getUploaderImpl(option.options.type);\n if (uploaderRef == null) {\n throw new Error(\"Sorry,The component is not ready yet\");\n }\n return await uploaderRef?.upload(option);\n }\n\n async function doEmit() {\n const list = [];\n for (const item of listRef.value) {\n if (typeof item === \"string\") {\n list.push(item);\n } else {\n list.push(item.value);\n }\n }\n let ret = list;\n // @ts-ignore\n if (props.limit === 1) {\n ret = list && list.length > 0 ? list[0] : undefined;\n }\n emitValue = ret;\n ctx.emit(\"update:modelValue\", ret);\n await formValidator.onChange();\n await formValidator.onBlur();\n }\n\n function getImageSrc(item: any) {\n return item.dataUrl ? item.dataUrl : item.url;\n }\n\n const previewVisible = ref(false);\n const previewUrl = ref();\n function preview(item: any) {\n previewVisible.value = true;\n previewUrl.value = getImageSrc(item);\n }\n function closePreview() {\n previewVisible.value = false;\n previewUrl.value = null;\n }\n watch(\n () => {\n // @ts-ignore\n return props.modelValue;\n },\n async (val: any) => {\n ctx.emit(\"change\", val);\n if (val === emitValue) {\n return;\n }\n await initValue(val);\n }\n );\n const current = getCurrentInstance();\n function doReady(context: any) {\n ctx.emit(\"ready\", {\n uploaderRef: current,\n ...context\n });\n }\n\n const computedProps = computed(() => {\n return {\n ...props\n };\n });\n return {\n ui,\n cropperRef,\n uploaderImplRef,\n indexRef,\n listRef,\n addNewImage,\n hasUploading,\n cropComplete,\n doUpload,\n removeImage,\n getImageSrc,\n previewUrl,\n previewVisible,\n preview,\n closePreview,\n doReady,\n computedProps\n };\n }\n});\n</script>\n\n<style lang=\"less\">\n.fs-cropper-uploader {\n .fs-box {\n display: flex;\n flex-wrap: wrap;\n }\n .el-image-viewer__close {\n color: #fff;\n }\n &.is-disabled {\n .image-list {\n .image-item {\n cursor: not-allowed;\n }\n }\n i {\n cursor: not-allowed;\n }\n }\n .image-list {\n display: flex;\n justify-content: left;\n align-items: center;\n flex-wrap: wrap;\n .image-item {\n width: 100px;\n height: 100px;\n display: flex;\n justify-content: center;\n align-items: center;\n background-color: #fbfdff;\n border: 1px solid #c0ccda;\n border-radius: 6px;\n position: relative;\n margin-right: 8px;\n margin-bottom: 8px;\n cursor: pointer;\n overflow: hidden;\n &.image-plus {\n border: 1px dashed #c0ccda;\n }\n .cropper-uploader-icon {\n vertical-align: top;\n font-size: 28px;\n color: #8c939d;\n }\n .image {\n width: 100px;\n }\n\n .delete {\n border-radius: 6px;\n position: absolute;\n width: 100%;\n height: 100%;\n left: 0;\n top: 0;\n cursor: default;\n text-align: center;\n color: #fff;\n opacity: 0;\n font-size: 20px;\n background-color: rgba(0, 0, 0, 0.9);\n -webkit-transition: opacity 0.3s;\n transition: opacity 0.3s;\n &:hover {\n opacity: 0.9;\n }\n display: flex;\n justify-content: center;\n align-items: center;\n i {\n cursor: pointer;\n }\n\n display: flex;\n > * {\n margin: 5px;\n }\n }\n .status-uploading {\n border-radius: 6px;\n position: absolute;\n width: 100%;\n height: 100%;\n left: 0;\n top: 0;\n cursor: default;\n text-align: center;\n color: #fff;\n opacity: 1;\n font-size: 20px;\n background-color: rgba(0, 0, 0, 0.5);\n -webkit-transition: opacity 0.3s;\n transition: opacity 0.3s;\n display: flex;\n justify-content: center;\n align-items: center;\n .el-progress {\n width: 70px;\n height: 70px;\n .el-progress__text {\n color: #fff;\n }\n }\n }\n .status-done {\n position: absolute;\n right: -15px;\n top: -6px;\n width: 40px;\n height: 24px;\n background: #13ce66;\n text-align: center;\n -webkit-transform: rotate(45deg);\n transform: rotate(45deg);\n -webkit-box-shadow: 0 0 1pc 1px rgba(0, 0, 0, 0.2);\n box-shadow: 0 0 1pc 1px rgba(0, 0, 0, 0.2);\n display: flex;\n justify-content: center;\n align-items: center;\n .status-down-icon {\n font-size: 12px;\n margin-top: 11px;\n color: #fff;\n -webkit-transform: rotate(-45deg);\n transform: rotate(-45deg);\n }\n }\n }\n }\n\n .fs-cropper-preview {\n position: fixed;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n background-color: rgba(183, 180, 180, 0.7);\n display: flex;\n justify-content: center;\n align-items: center;\n visibility: hidden;\n z-index: 10000;\n &.open {\n visibility: visible;\n }\n .fs-cropper-preview-content {\n max-height: 800px;\n max-width: 800px;\n img {\n max-height: 800px;\n max-width: 800px;\n object-fit: contain;\n }\n }\n }\n}\n</style>\n","<template>\n <div class=\"fs-cropper-uploader\" :class=\"{ 'is-disabled': computedProps.disabled }\">\n <div class=\"image-list\">\n <component :is=\"ui.imageGroup.name\">\n <div v-for=\"(item, index) in listRef\" :key=\"index\" class=\"image-item\">\n <component :is=\"ui.image.name\" class=\"image\" :src=\"getImageSrc(item)\" v-bind=\"computedProps.img\">\n <template #placeholder>\n <div class=\"image-slot\">\n <fs-loading :loading=\"true\" />\n </div>\n </template>\n </component>\n <div class=\"delete\">\n <fs-icon v-if=\"!computedProps.disabled\" :icon=\"ui.icons.remove\" @click=\"removeImage(index as number)\" />\n <fs-icon :icon=\"ui.icons.search\" @click=\"preview(item)\" />\n </div>\n <div v-if=\"item.status === 'uploading'\" class=\"status-uploading\">\n <component :is=\"ui.progress.name\" type=\"circle\" :percentage=\"item.progress\" :width=\"70\" />\n </div>\n <div v-else-if=\"item.status === 'done'\" class=\"status-done\">\n <fs-icon :icon=\"ui.icons.check\" class=\"status-down-icon\" />\n </div>\n </div>\n <div\n v-if=\"computedProps.limit <= 0 || computedProps.limit > listRef.length\"\n class=\"image-item image-plus\"\n @click=\"addNewImage\"\n >\n <fs-icon :icon=\"ui.icons.plus\" class=\"cropper-uploader-icon\" />\n </div>\n </component>\n </div>\n <fs-cropper\n ref=\"cropperRef\"\n :title=\"computedProps.title\"\n :cropper-height=\"computedProps.cropperHeight\"\n :dialog-width=\"computedProps.dialogWidth\"\n :accept=\"computedProps.accept\"\n :upload-tip=\"computedProps.uploadTip\"\n :max-size=\"computedProps.maxSize\"\n :cropper=\"computedProps.cropper\"\n :compress-quality=\"computedProps.compressQuality\"\n output=\"all\"\n @done=\"cropComplete\"\n @ready=\"doReady\"\n />\n <div class=\"fs-cropper-preview\" :class=\"{ open: previewVisible }\" @click=\"closePreview\">\n <div class=\"fs-cropper-preview-content\">\n <img v-if=\"previewUrl\" :src=\"previewUrl\" class=\"preview-image\" />\n </div>\n </div>\n </div>\n</template>\n\n<script lang=\"ts\">\nimport { computed, defineComponent, getCurrentInstance, reactive, ref, Ref, watch } from \"vue\";\nimport { useUi } from \"@fast-crud/fast-crud\";\nimport { FsUploaderDoUploadOptions } from \"../d/type\";\nimport { useUploader } from \"./utils\";\n\n/**\n * 图片裁剪上传组件,封装了fs-cropper\n * fs-cropper内部封装了[cropperjs](https://github.com/fengyuanchen/cropperjs)\n */\nexport default defineComponent({\n name: \"FsCropperUploader\",\n props: {\n /**\n * 初始图片url,或者是数组\n */\n modelValue: {\n type: [String, Object, Array]\n },\n img: {},\n /**\n * 上传后端类型,[form, cos, qiniu , alioss]\n */\n type: {\n type: String\n },\n /**\n * 上传提示\n */\n uploadTip: {\n type: String\n },\n /**\n * 对话框标题\n */\n title: String,\n /**\n * cropper的高度,默认为浏览器可视窗口高度的40%,最小270\n */\n cropperHeight: {\n type: [String, Number]\n },\n /**\n * 对话框宽度,默认50%\n */\n dialogWidth: {\n type: [String, Number],\n default: \"50%\"\n },\n /**\n * 图片大小限制,单位MB\n */\n maxSize: {\n type: Number,\n default: 5\n },\n /**\n * 图片数量限制,0为不限制\n */\n limit: {\n type: Number,\n default: 1\n },\n /**\n * 可接收的文件后缀\n */\n accept: {\n type: String,\n default: \".jpg, .jpeg, .png, .gif, .webp\"\n },\n /**\n * [cropperjs的参数](https://github.com/fengyuanchen/cropperjs)\n */\n cropper: {\n type: Object\n },\n /**\n * FsUploaderXXX的配置,会临时覆盖全局上传配置参数\n */\n uploader: {\n type: Object\n },\n /**\n * 压缩质量\n */\n compressQuality: {\n type: Number,\n default: 0.8\n },\n /**\n * 构建下载url方法,不影响提交的value\n */\n buildUrl: {\n type: Function,\n default: async function (value: any) {\n return typeof value === \"object\" ? value.url : value;\n }\n },\n /**\n * 返回值类型\n * 支持:`[url,key,object]`\n */\n valueType: {\n type: String, // url ,key, object\n default: \"url\"\n },\n /**\n * 是否禁用\n */\n disabled: {}\n },\n emits: [\"update:modelValue\", \"change\", \"ready\"],\n setup(props: any, ctx: any) {\n const { ui } = useUi();\n const cropperRef: Ref = ref();\n const uploaderImplRef: Ref = ref();\n\n const indexRef: Ref = ref();\n const listRef: Ref = ref([]);\n const formValidator = ui.formItem.injectFormItemContext();\n // eslint-disable-next-line vue/no-setup-props-destructure\n // @ts-ignore\n let emitValue: any = props.modelValue;\n // eslint-disable-next-line vue/no-setup-props-destructure\n // @ts-ignore\n initValue(props.modelValue);\n\n async function initValue(value: any) {\n const list: any = [];\n if (value == null || value === \"\") {\n listRef.value = list;\n return;\n }\n if (typeof value === \"string\") {\n // @ts-ignore\n list.push({ url: await props.buildUrl(value), value: value, status: \"done\" });\n } else if (Array.isArray(value)) {\n for (const item of value) {\n // @ts-ignore\n list.push({ url: await props.buildUrl(item), value: item, status: \"done\" });\n }\n } else if (typeof value === \"object\") {\n // @ts-ignore\n list.push({ url: await props.buildUrl(value), value, status: \"done\" });\n } else {\n for (const item of value) {\n // @ts-ignore\n list.push({ url: await props.buildUrl(item), value: item, status: \"done\" });\n }\n }\n listRef.value = list;\n }\n function addNewImage() {\n // @ts-ignore\n if (props.disabled) {\n return;\n }\n indexRef.value = undefined;\n cropperRef.value.clear();\n cropperRef.value.open();\n }\n function removeImage(index: number) {\n listRef.value.splice(index, 1);\n doEmit();\n }\n function hasUploading() {\n const fileList: any = listRef.value;\n if (fileList && fileList.length > 0) {\n for (const item of fileList) {\n if (item.status === \"uploading\") {\n return true;\n }\n }\n }\n return false;\n }\n async function cropComplete(ret: any) {\n const blob = ret.blob;\n const dataUrl = ret.dataUrl;\n const file = ret.file;\n const filename = file.name;\n const blobFile = new File([blob], filename, { type: blob.type });\n\n // 开始上传\n const item: any = reactive({\n url: undefined,\n dataUrl: dataUrl,\n status: \"uploading\",\n progress: 0\n });\n const onProgress = (e: any) => {\n item.progress = e.percent;\n };\n const onError = (e: any) => {\n item.status = \"error\";\n item.message = \"文件上传出错:\" + e.message;\n console.error(e);\n };\n const option = {\n file: blobFile,\n onProgress,\n onError,\n fileName: filename\n };\n listRef.value.push(item);\n try {\n const uploaded = await doUpload(option);\n let value = uploaded;\n // @ts-ignore\n if (props.valueType !== \"object\") {\n // @ts-ignore\n value = uploaded[props.valueType];\n }\n // @ts-ignore\n item.url = await props.buildUrl(value);\n item.value = value;\n item.status = \"done\";\n doEmit();\n } catch (e) {\n onError(e);\n }\n }\n\n async function doUpload(option: FsUploaderDoUploadOptions) {\n // @ts-ignore\n option.options = props.uploader || {};\n const { getUploaderImpl } = useUploader();\n let uploaderRef = await getUploaderImpl(option.options.type);\n if (uploaderRef == null) {\n throw new Error(\"Sorry,The component is not ready yet\");\n }\n return await uploaderRef?.upload(option);\n }\n\n async function doEmit() {\n const list = [];\n for (const item of listRef.value) {\n if (typeof item === \"string\") {\n list.push(item);\n } else {\n list.push(item.value);\n }\n }\n let ret = list;\n // @ts-ignore\n if (props.limit === 1) {\n ret = list && list.length > 0 ? list[0] : undefined;\n }\n emitValue = ret;\n ctx.emit(\"update:modelValue\", ret);\n await formValidator.onChange();\n await formValidator.onBlur();\n }\n\n function getImageSrc(item: any) {\n return item.dataUrl ? item.dataUrl : item.url;\n }\n\n const previewVisible = ref(false);\n const previewUrl = ref();\n function preview(item: any) {\n previewVisible.value = true;\n previewUrl.value = getImageSrc(item);\n }\n function closePreview() {\n previewVisible.value = false;\n previewUrl.value = null;\n }\n watch(\n () => {\n // @ts-ignore\n return props.modelValue;\n },\n async (val: any) => {\n ctx.emit(\"change\", val);\n if (val === emitValue) {\n return;\n }\n await initValue(val);\n }\n );\n const current = getCurrentInstance();\n function doReady(context: any) {\n ctx.emit(\"ready\", {\n uploaderRef: current,\n ...context\n });\n }\n\n const computedProps = computed(() => {\n return {\n ...props\n };\n });\n return {\n ui,\n cropperRef,\n uploaderImplRef,\n indexRef,\n listRef,\n addNewImage,\n hasUploading,\n cropComplete,\n doUpload,\n removeImage,\n getImageSrc,\n previewUrl,\n previewVisible,\n preview,\n closePreview,\n doReady,\n computedProps\n };\n }\n});\n</script>\n\n<style lang=\"less\">\n.fs-cropper-uploader {\n .fs-box {\n display: flex;\n flex-wrap: wrap;\n }\n .el-image-viewer__close {\n color: #fff;\n }\n &.is-disabled {\n .image-list {\n .image-item {\n cursor: not-allowed;\n }\n }\n i {\n cursor: not-allowed;\n }\n }\n .image-list {\n display: flex;\n justify-content: left;\n align-items: center;\n flex-wrap: wrap;\n .image-item {\n width: 100px;\n height: 100px;\n display: flex;\n justify-content: center;\n align-items: center;\n background-color: #fbfdff;\n border: 1px solid #c0ccda;\n border-radius: 6px;\n position: relative;\n margin-right: 8px;\n margin-bottom: 8px;\n cursor: pointer;\n overflow: hidden;\n &.image-plus {\n border: 1px dashed #c0ccda;\n }\n .cropper-uploader-icon {\n vertical-align: top;\n font-size: 28px;\n color: #8c939d;\n }\n .image {\n width: 100px;\n }\n\n .delete {\n border-radius: 6px;\n position: absolute;\n width: 100%;\n height: 100%;\n left: 0;\n top: 0;\n cursor: default;\n text-align: center;\n color: #fff;\n opacity: 0;\n font-size: 20px;\n background-color: rgba(0, 0, 0, 0.9);\n -webkit-transition: opacity 0.3s;\n transition: opacity 0.3s;\n &:hover {\n opacity: 0.9;\n }\n display: flex;\n justify-content: center;\n align-items: center;\n i {\n cursor: pointer;\n }\n\n display: flex;\n > * {\n margin: 5px;\n }\n }\n .status-uploading {\n border-radius: 6px;\n position: absolute;\n width: 100%;\n height: 100%;\n left: 0;\n top: 0;\n cursor: default;\n text-align: center;\n color: #fff;\n opacity: 1;\n font-size: 20px;\n background-color: rgba(0, 0, 0, 0.5);\n -webkit-transition: opacity 0.3s;\n transition: opacity 0.3s;\n display: flex;\n justify-content: center;\n align-items: center;\n .el-progress {\n width: 70px;\n height: 70px;\n .el-progress__text {\n color: #fff;\n }\n }\n }\n .status-done {\n position: absolute;\n right: -15px;\n top: -6px;\n width: 40px;\n height: 24px;\n background: #13ce66;\n text-align: center;\n -webkit-transform: rotate(45deg);\n transform: rotate(45deg);\n -webkit-box-shadow: 0 0 1pc 1px rgba(0, 0, 0, 0.2);\n box-shadow: 0 0 1pc 1px rgba(0, 0, 0, 0.2);\n display: flex;\n justify-content: center;\n align-items: center;\n .status-down-icon {\n font-size: 12px;\n margin-top: 11px;\n color: #fff;\n -webkit-transform: rotate(-45deg);\n transform: rotate(-45deg);\n }\n }\n }\n }\n\n .fs-cropper-preview {\n position: fixed;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n background-color: rgba(183, 180, 180, 0.7);\n display: flex;\n justify-content: center;\n align-items: center;\n visibility: hidden;\n z-index: 10000;\n &.open {\n visibility: visible;\n }\n .fs-cropper-preview-content {\n max-height: 800px;\n max-width: 800px;\n img {\n max-height: 800px;\n max-width: 800px;\n object-fit: contain;\n }\n }\n }\n}\n</style>\n"],"names":["_sfc_main","defineComponent","value","props","ctx","ui","useUi","cropperRef","ref","uploaderImplRef","indexRef","listRef","formValidator","emitValue","initValue","list","item","addNewImage","removeImage","index","doEmit","hasUploading","fileList","cropComplete","ret","blob","dataUrl","filename","blobFile","reactive","onProgress","e","onError","option","uploaded","doUpload","getUploaderImpl","useUploader","uploaderRef","getImageSrc","previewVisible","previewUrl","preview","closePreview","watch","val","current","getCurrentInstance","doReady","context","computedProps","computed","_hoisted_1","_hoisted_4","_hoisted_5","_resolveComponent","_normalizeClass","_ctx","_createElementVNode","_openBlock","_createBlock","_resolveDynamicComponent","_withCtx","_createElementBlock","_Fragment","_renderList","_mergeProps","_hoisted_2","_hoisted_3","_createCommentVNode","_component_fs_icon","_createVNode","_cache","args","_hoisted_6"],"mappings":"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"} |