@qxs-bns/components 0.0.73 → 0.0.74

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,2 +1,2 @@
1
- var r="0.0.73";export{r as version};
1
+ var r="0.0.74";export{r as version};
2
2
  //# sourceMappingURL=package.json.mjs.map
@@ -1,2 +1,2 @@
1
- import{defineComponent as e,mergeModels as i,useAttrs as a,useModel as t,computed as l,ref as s,onUnmounted as r,resolveComponent as n,createElementBlock as u,openBlock as o,normalizeStyle as p,normalizeClass as d,unref as c,createVNode as m,createBlock as v,createCommentVNode as f,mergeProps as g,withCtx as b,renderSlot as h,createElementVNode as y,toDisplayString as w}from"vue";import{UploadImage as _,ZoomIn as $,Delete as x}from"@qxs-bns/icons";import{useNamespace as q,ElUpload as k,ElImageViewer as L,ElMessage as U}from"element-plus";const j={class:"image-slot"},V=["src","alt"],z=["onClick"],C=["onClick"],R={class:"tip-content"};var B=e({name:"QxsImageUpload",__name:"image-upload",props:i({action:{type:String,required:!0},headers:{type:null,required:!1},data:{type:null,required:!1},name:{type:String,required:!1,default:"file"},size:{type:Number,required:!1,default:20},width:{type:Number,required:!1,default:160},height:{type:Number,required:!1,default:90},accept:{type:String,required:!1,default:"image/jpeg,image/jpg,image/png,image/gif"},placeholder:{type:String,required:!1,default:"上传图片"},notip:{type:Boolean,required:!1,default:!1},tipText:{type:String,required:!1,default:""},beforeUpload:{type:null,required:!1},disabled:{type:Boolean,required:!1,default:!1},limit:{type:Number,required:!1,default:1}},{fileList:{type:Array,default:()=>[]},fileListModifiers:{}}),emits:i(["success","remove"],["update:fileList"]),setup(e,{emit:i}){const B=i,S=a(),I=t(e,"fileList");let M=0;const N=l({get:()=>I.value.map((e,i)=>e.name&&e.status&&e.uid?e:{...e,name:e.name||`image-${i+1}.jpg`,status:e.status||"success",uid:e.uid||`qxs-image-${Date.now()}-${++M}`}),set(e){I.value=e}}),D=q("image-upload"),O=s(0),T=s({imageViewerVisible:!1,progress:{preview:"",percent:0}}),P=l(()=>D.cssVarBlock({ns:D.namespace.value,width:`${e.width}px`,height:`${e.height}px`})),Q=l(()=>e.accept.split(",").map(e=>e.split("/").pop())),A=l(()=>{if(e.tipText)return e.tipText;return`上传图片支持 ${Q.value.join(" / ")} 格式,且图片大小不超过 ${e.size}MB`+(e.width&&e.height?`,建议图片尺寸为 ${e.width}×${e.height}`:"")});function E(i){e.disabled||(i.url?(O.value=N.value.findIndex(e=>e.uid===i.uid),T.value.imageViewerVisible=!0):console.warn("文件缺少 URL,无法预览:",i))}function F(i){if(e.disabled)return;const a=N.value.findIndex(e=>e.uid===i.uid);a>-1&&I.value.splice(a,1)}function G(){T.value.imageViewerVisible=!1}const H=i=>{if(!i||!i.name)return U.error("文件信息无效!"),!1;const a=i.name.split(".").pop()?.toLowerCase()??"";if(!Q.value.some(e=>e?.toLowerCase()===a))return U.error(`上传图片只支持 ${Q.value.join(" / ")} 格式!`),!1;if(i.size/1024/1024>e.size)return U.error(`上传图片大小不能超过 ${e.size}MB!`),!1;try{T.value.progress.preview=URL.createObjectURL(i)}catch(e){console.warn("创建预览失败:",e)}return!e.beforeUpload||e.beforeUpload(i)},J=e=>{T.value.progress.percent=Math.floor(e.percent)},K=(...e)=>{T.value.progress.preview&&URL.revokeObjectURL(T.value.progress.preview),T.value.progress={preview:"",percent:0},B("success",...e)};return r(()=>{T.value.progress.preview&&URL.revokeObjectURL(T.value.progress.preview)}),(i,a)=>{const t=n("QxsIcon");return o(),u("div",{class:d(c(D).e("container")),style:p(P.value)},[m(c(k),g(c(S),{"file-list":N.value,"onUpdate:fileList":a[0]||(a[0]=e=>N.value=e),drag:"",limit:i.limit,"list-type":"picture-card",headers:i.headers,action:i.action,data:i.data,name:i.name,accept:i.accept,"before-upload":H,"on-progress":J,"on-preview":E,"on-success":K,class:[c(D).e("control"),i.limit<=N.value.length?c(D).e("more-than-limit"):""],"on-remove":F}),{file:b(({file:a})=>[a.url?(o(),u("img",{key:0,class:d(`${c(D).namespace.value}-upload-list__item-thumbnail`),src:a.url,alt:a.name||"图片"},null,10,V)):(o(),u("div",{key:1,class:d(`${c(D).namespace.value}-upload-list__item-thumbnail`),style:{display:"flex","align-items":"center","justify-content":"center",color:"#909399",background:"#f5f7fa"}}," 无图片 ",2)),y("span",{class:d(`${c(D).namespace.value}-upload-list__item-actions`)},[a.url?(o(),u("span",{key:0,class:d([`${c(D).namespace.value}-upload-list__item-preview`,`${c(D).namespace.value}-image-upload__action-btn`,`${c(D).namespace.value}-image-upload__action-btn--preview`,i.disabled?"is-disabled":""]),onClick:i=>function(i,a){if(e.disabled)return a.preventDefault(),void a.stopPropagation();E(i)}(a,i)},[m(c($),{size:"14px"})],10,z)):f("v-if",!0),a.url?(o(),u("span",{key:1,class:d(`${c(D).namespace.value}-upload-list__item-divider`)},null,2)):f("v-if",!0),y("span",{class:d([`${c(D).namespace.value}-upload-list__item-delete`,`${c(D).namespace.value}-image-upload__action-btn`,`${c(D).namespace.value}-image-upload__action-btn--delete`,i.disabled?"is-disabled":""]),onClick:i=>function(i,a){if(e.disabled)return a.preventDefault(),void a.stopPropagation();F(i)}(a,i)},[m(c(x),{size:"14px"})],10,C)],2)]),tip:b(()=>[h(i.$slots,"tip",{},()=>[i.notip?f("v-if",!0):(o(),u("div",{key:0,class:d(`${c(D).namespace.value}-upload__tip-text`)},[y("div",R,w(A.value),1)],2))])]),default:b(()=>[h(i.$slots,"default",{},()=>[y("div",j,[m(t,{size:"32px",icon:c(_)},null,8,["icon"]),y("p",null,w(i.placeholder),1)])])]),_:3},16,["file-list","limit","headers","action","data","name","accept","class"]),T.value.imageViewerVisible?(o(),v(c(L),{key:0,"url-list":N.value.map(e=>e.url).filter(Boolean),"initial-index":O.value,"show-progress":N.value.length>1,teleported:"",onClose:G},null,8,["url-list","initial-index","show-progress"])):f("v-if",!0)],6)}}});export{B as default};
1
+ import{defineComponent as e,mergeModels as i,useAttrs as a,useModel as t,computed as l,ref as s,onUnmounted as r,resolveComponent as n,createElementBlock as u,openBlock as o,normalizeStyle as p,normalizeClass as d,unref as c,createVNode as m,createBlock as v,createCommentVNode as f,mergeProps as g,withCtx as h,renderSlot as b,createElementVNode as y,toDisplayString as w}from"vue";import{UploadImage as _,ZoomIn as $,Delete as x}from"@qxs-bns/icons";import{useNamespace as q,ElUpload as k,ElImageViewer as L,ElMessage as U}from"element-plus";const j={class:"image-slot"},V=["src","alt"],z=["onClick"],C=["onClick"],R={class:"tip-content"};var B=e({name:"QxsImageUpload",__name:"image-upload",props:i({action:{type:String,required:!0},headers:{type:null,required:!1},data:{type:null,required:!1},name:{type:String,required:!1,default:"file"},size:{type:Number,required:!1,default:20},width:{type:Number,required:!1,default:160},height:{type:Number,required:!1,default:90},accept:{type:String,required:!1,default:"image/jpeg,image/jpg,image/png,image/gif"},placeholder:{type:String,required:!1,default:"上传图片"},notip:{type:Boolean,required:!1,default:!1},tipText:{type:String,required:!1,default:""},beforeUpload:{type:null,required:!1},disabled:{type:Boolean,required:!1,default:!1},limit:{type:Number,required:!1,default:1}},{fileList:{type:Array,default:()=>[]},fileListModifiers:{}}),emits:i(["success","remove"],["update:fileList"]),setup(e,{emit:i}){const B=i,S=a(),I=t(e,"fileList");let M=0;const N=l({get:()=>I.value.map((e,i)=>e.name&&e.status&&e.uid?e:{...e,name:e.name||`image-${i+1}.jpg`,status:e.status||"success",uid:e.uid||`qxs-image-${Date.now()}-${++M}`}),set(e){I.value=e}}),O=q("image-upload"),T=s(0),D=s({imageViewerVisible:!1,progress:{preview:"",percent:0}}),Q=l(()=>O.cssVarBlock({ns:O.namespace.value,width:`${e.width}px`,height:`${e.height}px`})),A=l(()=>e.accept.split(",").map(e=>e.split("/").pop())),P=l(()=>{if(e.tipText)return e.tipText;return`上传图片支持 ${A.value.join(" / ")} 格式,且图片大小不超过 ${e.size}MB`+(e.width&&e.height?`,建议图片尺寸为 ${e.width}×${e.height}`:"")});function E(i){e.disabled||(i.url?(T.value=N.value.findIndex(e=>e.uid===i.uid),D.value.imageViewerVisible=!0):console.warn("文件缺少 URL,无法预览:",i))}function F(i){if(e.disabled)return;const a=N.value.findIndex(e=>e.uid===i.uid);a>-1&&I.value.splice(a,1)}function G(){D.value.imageViewerVisible=!1}const H=i=>{if(!i||!i.name)return U.error("文件信息无效!"),!1;const a=i.name.split(".").pop()?.toLowerCase()??"";if(!A.value.some(e=>e?.toLowerCase()===a))return U.error(`上传图片只支持 ${A.value.join(" / ")} 格式!`),!1;if(i.size/1024/1024>e.size)return U.error(`上传图片大小不能超过 ${e.size}MB!`),!1;try{D.value.progress.preview=URL.createObjectURL(i)}catch(e){console.warn("创建预览失败:",e)}return!e.beforeUpload||e.beforeUpload(i)},J=e=>{D.value.progress.percent=Math.floor(e.percent)},K=(...e)=>{D.value.progress.preview&&URL.revokeObjectURL(D.value.progress.preview),D.value.progress={preview:"",percent:0},B("success",...e)};return r(()=>{D.value.progress.preview&&URL.revokeObjectURL(D.value.progress.preview)}),(i,a)=>{const t=n("QxsIcon");return o(),u("div",{class:d(c(O).e("container")),style:p(Q.value)},[m(c(k),g(c(S),{"file-list":N.value,"onUpdate:fileList":a[0]||(a[0]=e=>N.value=e),drag:"",limit:i.limit,"list-type":"picture-card",headers:i.headers,action:i.action,data:i.data,name:i.name,accept:i.accept,"before-upload":H,"on-progress":J,"on-preview":E,"on-success":K,class:[c(O).e("control"),i.limit<=N.value.length?c(O).e("more-than-limit"):""],"on-remove":F}),{file:h(({file:a})=>[a.url?(o(),u("img",{key:0,class:d(`${c(O).namespace.value}-upload-list__item-thumbnail`),src:a.url,alt:a.name||"图片"},null,10,V)):(o(),u("div",{key:1,class:d(`${c(O).namespace.value}-upload-list__item-thumbnail`),style:{display:"flex","align-items":"center","justify-content":"center",color:"#909399",background:"#f5f7fa"}}," 无图片 ",2)),y("span",{class:d(`${c(O).namespace.value}-upload-list__item-actions`)},[a.url?(o(),u("span",{key:0,class:d([`${c(O).namespace.value}-upload-list__item-preview`,`${c(O).namespace.value}-image-upload__action-btn`,`${c(O).namespace.value}-image-upload__action-btn--preview`]),onClick:e=>E(a)},[m(c($),{size:"14px"})],10,z)):f("v-if",!0),a.url?(o(),u("span",{key:1,class:d(`${c(O).namespace.value}-upload-list__item-divider`)},null,2)):f("v-if",!0),y("span",{class:d([`${c(O).namespace.value}-upload-list__item-delete`,`${c(O).namespace.value}-image-upload__action-btn`,`${c(O).namespace.value}-image-upload__action-btn--delete`,i.disabled?"is-disabled":""]),onClick:i=>function(i,a){if(e.disabled)return a.preventDefault(),void a.stopPropagation();F(i)}(a,i)},[m(c(x),{size:"14px"})],10,C)],2)]),tip:h(()=>[b(i.$slots,"tip",{},()=>[i.notip?f("v-if",!0):(o(),u("div",{key:0,class:d(`${c(O).namespace.value}-upload__tip-text`)},[y("div",R,w(P.value),1)],2))])]),default:h(()=>[b(i.$slots,"default",{},()=>[y("div",j,[m(t,{size:"32px",icon:c(_)},null,8,["icon"]),y("p",null,w(i.placeholder),1)])])]),_:3},16,["file-list","limit","headers","action","data","name","accept","class"]),D.value.imageViewerVisible?(o(),v(c(L),{key:0,"url-list":N.value.map(e=>e.url).filter(Boolean),"initial-index":T.value,"show-progress":N.value.length>1,teleported:"",onClose:G},null,8,["url-list","initial-index","show-progress"])):f("v-if",!0)],6)}}});export{B as default};
2
2
  //# sourceMappingURL=image-upload.vue.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"image-upload.vue.mjs","sources":["../../../../../../packages/components/src/image-upload/src/image-upload.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { UploadFile, UploadFiles, UploadProps } from 'element-plus'\nimport { Delete, UploadImage, ZoomIn } from '@qxs-bns/icons'\nimport { ElImageViewer, ElMessage, ElUpload, useNamespace } from 'element-plus'\nimport { computed, onUnmounted, ref, useAttrs } from 'vue'\n\n// 类型定义\nexport interface ImageUploadProps {\n /** 上传地址(必需) */\n action: UploadProps['action']\n /** 请求头 */\n headers?: UploadProps['headers']\n /** 上传时附带的额外参数 */\n data?: UploadProps['data']\n /** 上传的文件字段名 */\n name?: UploadProps['name']\n /** 文件大小限制(MB) */\n size?: number\n /** 图片显示宽度(px) */\n width?: number\n /** 图片显示高度(px) */\n height?: number\n /** 接受的文件类型 */\n accept?: string\n /** 上传区域提示文字 */\n placeholder?: string\n /** 是否隐藏提示文字 */\n notip?: boolean\n /** 自定义提示文字 */\n tipText?: string\n /** 上传前的钩子函数 */\n beforeUpload?: UploadProps['beforeUpload']\n /** 是否禁用 */\n disabled?: boolean\n /** 最大上传数量 */\n limit?: number\n}\n\ninterface UploadProgress {\n preview: string\n percent: number\n}\n\n// 组件名称\ndefineOptions({\n name: 'QxsImageUpload',\n})\n\n// Props 定义\nconst {\n action,\n headers,\n data,\n name = 'file',\n size = 20,\n width = 160,\n height = 90,\n limit = 1,\n placeholder = '上传图片',\n notip = false,\n accept = 'image/jpeg,image/jpg,image/png,image/gif',\n beforeUpload,\n tipText = '',\n disabled = false,\n} = defineProps<ImageUploadProps>()\n\n// Emits 定义 - 统一事件命名\nconst emits = defineEmits<{\n success: [res: any, uploadFile: UploadFile, uploadFiles: UploadFiles]\n remove: [file: UploadFile]\n}>()\n\nconst attrs = useAttrs()\n\nconst fileList = defineModel('fileList', {\n type: Array as () => UploadFile[],\n default: () => [],\n})\n\n// 生成唯一 ID 的计数器\nlet uidCounter = 0\n\n// 处理不完整的文件对象,自动补全必要属性\nconst normalizedFileList = computed({\n get() {\n return fileList.value.map((file, index) => {\n // 如果文件对象不完整,自动补全必要属性\n if (!file.name || !file.status || !file.uid) {\n return {\n ...file, // 保留原有属性\n name: file.name || `image-${index + 1}.jpg`,\n status: file.status || 'success',\n uid: file.uid || `qxs-image-${Date.now()}-${++uidCounter}`, // 确保唯一性\n } as UploadFile\n }\n return file\n })\n },\n set(value: UploadFile[]) {\n fileList.value = value\n },\n})\n\n// 命名空间\nconst nsEl = useNamespace('image-upload')\n\nconst initialIndex = ref(0)\n// 响应式数据\nconst uploadData = ref<{\n imageViewerVisible: boolean\n progress: UploadProgress\n}>({\n imageViewerVisible: false,\n progress: {\n preview: '',\n percent: 0,\n },\n})\n\nconst cssVar = computed(() => {\n return nsEl.cssVarBlock({\n ns: nsEl.namespace.value,\n width: `${width}px`,\n height: `${height}px`,\n })\n})\n\n// 计算属性\nconst exts = computed(() =>\n accept.split(',').map(ext => ext.split('/').pop()),\n)\n\nconst tipMessage = computed(() => {\n if (tipText) {\n return tipText\n }\n\n const formatText = `上传图片支持 ${exts.value.join(' / ')} 格式,且图片大小不超过 ${size}MB`\n const sizeText = width && height ? `,建议图片尺寸为 ${width}×${height}` : ''\n\n return formatText + sizeText\n})\n\n// 方法\nfunction onPreview(file: UploadFile) {\n // 如果组件被禁用,阻止预览\n if (disabled) {\n return\n }\n\n // 确保文件有有效的 URL 才能预览\n if (!file.url) {\n console.warn('文件缺少 URL,无法预览:', file)\n return\n }\n\n // 使用 uid 作为唯一标识符来查找文件索引\n initialIndex.value = normalizedFileList.value.findIndex(item => item.uid === file.uid)\n uploadData.value.imageViewerVisible = true\n}\n\nfunction onRemove(file: UploadFile) {\n // 如果组件被禁用,阻止删除\n if (disabled) {\n return\n }\n\n // 使用 uid 作为唯一标识符来查找并删除文件\n const index = normalizedFileList.value.findIndex(item => item.uid === file.uid)\n if (index > -1) {\n fileList.value.splice(index, 1)\n }\n}\n\n// 处理手动点击事件(用于模板中的按钮)\nfunction handlePreviewClick(file: UploadFile, event: Event) {\n if (disabled) {\n event.preventDefault()\n event.stopPropagation()\n return\n }\n onPreview(file)\n}\n\nfunction handleRemoveClick(file: UploadFile, event: Event) {\n if (disabled) {\n event.preventDefault()\n event.stopPropagation()\n return\n }\n onRemove(file)\n}\n\nfunction previewClose() {\n uploadData.value.imageViewerVisible = false\n}\n\nconst handleBeforeUpload: UploadProps['beforeUpload'] = (file) => {\n // 参数校验\n if (!file || !file.name) {\n ElMessage.error('文件信息无效!')\n return false\n }\n\n // 文件类型校验\n const fileExt = file.name.split('.').pop()?.toLowerCase() ?? ''\n const isTypeOk = exts.value.some(ext => ext?.toLowerCase() === fileExt)\n\n if (!isTypeOk) {\n ElMessage.error(`上传图片只支持 ${exts.value.join(' / ')} 格式!`)\n return false\n }\n\n // 文件大小校验\n const fileSizeMB = file.size / 1024 / 1024\n if (fileSizeMB > size) {\n ElMessage.error(`上传图片大小不能超过 ${size}MB!`)\n return false\n }\n\n // 设置预览\n try {\n uploadData.value.progress.preview = URL.createObjectURL(file)\n }\n catch (error) {\n console.warn('创建预览失败:', error)\n }\n\n // 执行自定义校验\n return beforeUpload ? beforeUpload(file) : true\n}\n\nconst onProgress: UploadProps['onProgress'] = (evt) => {\n uploadData.value.progress.percent = Math.floor(evt.percent)\n}\n\nconst onSuccess: UploadProps['onSuccess'] = (...args) => {\n // 清理预览 URL,防止内存泄漏\n if (uploadData.value.progress.preview) {\n URL.revokeObjectURL(uploadData.value.progress.preview)\n }\n\n uploadData.value.progress = {\n preview: '',\n percent: 0,\n }\n emits('success', ...args)\n}\n\n// 组件卸载时清理资源\nonUnmounted(() => {\n if (uploadData.value.progress.preview) {\n URL.revokeObjectURL(uploadData.value.progress.preview)\n }\n})\n</script>\n\n<template>\n <div\n :class=\"nsEl.e('container')\"\n :style=\"cssVar\"\n >\n <ElUpload\n v-bind=\"attrs\"\n v-model:file-list=\"normalizedFileList\"\n drag\n :limit=\"limit\"\n list-type=\"picture-card\"\n :headers=\"headers\"\n :action=\"action\"\n :data=\"data\"\n :name=\"name\"\n :accept=\"accept\"\n :before-upload=\"handleBeforeUpload\"\n :on-progress=\"onProgress\"\n :on-preview=\"onPreview\"\n :on-success=\"onSuccess\"\n :class=\"[nsEl.e('control'), limit <= normalizedFileList.length ? nsEl.e('more-than-limit') : '']\"\n :on-remove=\"onRemove\"\n >\n <slot>\n <div class=\"image-slot\">\n <QxsIcon\n size=\"32px\"\n :icon=\"UploadImage\"\n />\n <p>{{ placeholder }}</p>\n </div>\n </slot>\n <template #file=\"{ file }\">\n <img\n v-if=\"file.url\"\n :class=\"`${nsEl.namespace.value}-upload-list__item-thumbnail`\"\n :src=\"file.url\"\n :alt=\"file.name || '图片'\"\n >\n <div\n v-else\n :class=\"`${nsEl.namespace.value}-upload-list__item-thumbnail`\"\n style=\"display: flex; align-items: center; justify-content: center; color: #909399; background: #f5f7fa;\"\n >\n 无图片\n </div>\n <span :class=\"`${nsEl.namespace.value}-upload-list__item-actions`\">\n <span\n v-if=\"file.url\"\n :class=\"[\n `${nsEl.namespace.value}-upload-list__item-preview`,\n `${nsEl.namespace.value}-image-upload__action-btn`,\n `${nsEl.namespace.value}-image-upload__action-btn--preview`,\n disabled ? 'is-disabled' : '',\n ]\"\n @click=\"handlePreviewClick(file, $event)\"\n >\n <ZoomIn size=\"14px\" />\n </span>\n <span\n v-if=\"file.url\"\n :class=\"`${nsEl.namespace.value}-upload-list__item-divider`\"\n />\n <span\n :class=\"[\n `${nsEl.namespace.value}-upload-list__item-delete`,\n `${nsEl.namespace.value}-image-upload__action-btn`,\n `${nsEl.namespace.value}-image-upload__action-btn--delete`,\n disabled ? 'is-disabled' : '',\n ]\"\n @click=\"handleRemoveClick(file, $event)\"\n >\n <Delete size=\"14px\" />\n </span>\n </span>\n </template>\n <template #tip>\n <slot name=\"tip\">\n <div\n v-if=\"!notip\"\n :class=\"`${nsEl.namespace.value}-upload__tip-text`\"\n >\n <div class=\"tip-content\">\n {{ tipMessage }}\n </div>\n </div>\n </slot>\n </template>\n </ElUpload>\n\n <ElImageViewer\n v-if=\"uploadData.imageViewerVisible\"\n :url-list=\"normalizedFileList.map((item: UploadFile) => item.url!).filter(Boolean)\"\n :initial-index=\"initialIndex\"\n :show-progress=\"normalizedFileList.length > 1\"\n teleported\n @close=\"previewClose\"\n />\n </div>\n</template>\n"],"names":["emits","__emit","attrs","useAttrs","fileList","_useModel","__props","uidCounter","normalizedFileList","computed","get","value","map","file","index","name","status","uid","Date","now","set","nsEl","useNamespace","initialIndex","ref","uploadData","imageViewerVisible","progress","preview","percent","cssVar","cssVarBlock","ns","namespace","width","height","exts","split","ext","pop","tipMessage","tipText","join","size","onPreview","disabled","url","findIndex","item","console","warn","onRemove","splice","previewClose","handleBeforeUpload","ElMessage","error","fileExt","toLowerCase","some","URL","createObjectURL","beforeUpload","onProgress","evt","Math","floor","onSuccess","args","revokeObjectURL","onUnmounted","_createElementBlock","class","_normalizeClass","_unref","e","style","_createVNode","ElUpload","_mergeProps","$event","drag","limit","headers","action","data","accept","length","_withCtx","src","alt","display","color","background","_createElementVNode","onClick","event","preventDefault","stopPropagation","handlePreviewClick","ZoomIn","handleRemoveClick","Delete","tip","_renderSlot","_ctx","notip","_hoisted_5","_toDisplayString","_hoisted_1","_component_QxsIcon","icon","UploadImage","placeholder","_createBlock","ElImageViewer","filter","Boolean","teleported","onClose"],"mappings":"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"}
1
+ {"version":3,"file":"image-upload.vue.mjs","sources":["../../../../../../packages/components/src/image-upload/src/image-upload.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { UploadFile, UploadFiles, UploadProps } from 'element-plus'\nimport { Delete, UploadImage, ZoomIn } from '@qxs-bns/icons'\nimport { ElImageViewer, ElMessage, ElUpload, useNamespace } from 'element-plus'\nimport { computed, onUnmounted, ref, useAttrs } from 'vue'\n\n// 类型定义\nexport interface ImageUploadProps {\n /** 上传地址(必需) */\n action: UploadProps['action']\n /** 请求头 */\n headers?: UploadProps['headers']\n /** 上传时附带的额外参数 */\n data?: UploadProps['data']\n /** 上传的文件字段名 */\n name?: UploadProps['name']\n /** 文件大小限制(MB) */\n size?: number\n /** 图片显示宽度(px) */\n width?: number\n /** 图片显示高度(px) */\n height?: number\n /** 接受的文件类型 */\n accept?: string\n /** 上传区域提示文字 */\n placeholder?: string\n /** 是否隐藏提示文字 */\n notip?: boolean\n /** 自定义提示文字 */\n tipText?: string\n /** 上传前的钩子函数 */\n beforeUpload?: UploadProps['beforeUpload']\n /** 是否禁用 */\n disabled?: boolean\n /** 最大上传数量 */\n limit?: number\n}\n\ninterface UploadProgress {\n preview: string\n percent: number\n}\n\n// 组件名称\ndefineOptions({\n name: 'QxsImageUpload',\n})\n\n// Props 定义\nconst {\n action,\n headers,\n data,\n name = 'file',\n size = 20,\n width = 160,\n height = 90,\n limit = 1,\n placeholder = '上传图片',\n notip = false,\n accept = 'image/jpeg,image/jpg,image/png,image/gif',\n beforeUpload,\n tipText = '',\n disabled = false,\n} = defineProps<ImageUploadProps>()\n\n// Emits 定义 - 统一事件命名\nconst emits = defineEmits<{\n success: [res: any, uploadFile: UploadFile, uploadFiles: UploadFiles]\n remove: [file: UploadFile]\n}>()\n\nconst attrs = useAttrs()\n\nconst fileList = defineModel('fileList', {\n type: Array as () => UploadFile[],\n default: () => [],\n})\n\n// 生成唯一 ID 的计数器\nlet uidCounter = 0\n\n// 处理不完整的文件对象,自动补全必要属性\nconst normalizedFileList = computed({\n get() {\n return fileList.value.map((file, index) => {\n // 如果文件对象不完整,自动补全必要属性\n if (!file.name || !file.status || !file.uid) {\n return {\n ...file, // 保留原有属性\n name: file.name || `image-${index + 1}.jpg`,\n status: file.status || 'success',\n uid: file.uid || `qxs-image-${Date.now()}-${++uidCounter}`, // 确保唯一性\n } as UploadFile\n }\n return file\n })\n },\n set(value: UploadFile[]) {\n fileList.value = value\n },\n})\n\n// 命名空间\nconst nsEl = useNamespace('image-upload')\n\nconst initialIndex = ref(0)\n// 响应式数据\nconst uploadData = ref<{\n imageViewerVisible: boolean\n progress: UploadProgress\n}>({\n imageViewerVisible: false,\n progress: {\n preview: '',\n percent: 0,\n },\n})\n\nconst cssVar = computed(() => {\n return nsEl.cssVarBlock({\n ns: nsEl.namespace.value,\n width: `${width}px`,\n height: `${height}px`,\n })\n})\n\n// 计算属性\nconst exts = computed(() =>\n accept.split(',').map(ext => ext.split('/').pop()),\n)\n\nconst tipMessage = computed(() => {\n if (tipText) {\n return tipText\n }\n\n const formatText = `上传图片支持 ${exts.value.join(' / ')} 格式,且图片大小不超过 ${size}MB`\n const sizeText = width && height ? `,建议图片尺寸为 ${width}×${height}` : ''\n\n return formatText + sizeText\n})\n\n// 方法\nfunction onPreview(file: UploadFile) {\n // 如果组件被禁用,阻止预览\n if (disabled) {\n return\n }\n\n // 确保文件有有效的 URL 才能预览\n if (!file.url) {\n console.warn('文件缺少 URL,无法预览:', file)\n return\n }\n\n // 使用 uid 作为唯一标识符来查找文件索引\n initialIndex.value = normalizedFileList.value.findIndex(item => item.uid === file.uid)\n uploadData.value.imageViewerVisible = true\n}\n\nfunction onRemove(file: UploadFile) {\n // 如果组件被禁用,阻止删除\n if (disabled) {\n return\n }\n\n // 使用 uid 作为唯一标识符来查找并删除文件\n const index = normalizedFileList.value.findIndex(item => item.uid === file.uid)\n if (index > -1) {\n fileList.value.splice(index, 1)\n }\n}\n\nfunction handleRemoveClick(file: UploadFile, event: Event) {\n if (disabled) {\n event.preventDefault()\n event.stopPropagation()\n return\n }\n onRemove(file)\n}\n\nfunction previewClose() {\n uploadData.value.imageViewerVisible = false\n}\n\nconst handleBeforeUpload: UploadProps['beforeUpload'] = (file) => {\n // 参数校验\n if (!file || !file.name) {\n ElMessage.error('文件信息无效!')\n return false\n }\n\n // 文件类型校验\n const fileExt = file.name.split('.').pop()?.toLowerCase() ?? ''\n const isTypeOk = exts.value.some(ext => ext?.toLowerCase() === fileExt)\n\n if (!isTypeOk) {\n ElMessage.error(`上传图片只支持 ${exts.value.join(' / ')} 格式!`)\n return false\n }\n\n // 文件大小校验\n const fileSizeMB = file.size / 1024 / 1024\n if (fileSizeMB > size) {\n ElMessage.error(`上传图片大小不能超过 ${size}MB!`)\n return false\n }\n\n // 设置预览\n try {\n uploadData.value.progress.preview = URL.createObjectURL(file)\n }\n catch (error) {\n console.warn('创建预览失败:', error)\n }\n\n // 执行自定义校验\n return beforeUpload ? beforeUpload(file) : true\n}\n\nconst onProgress: UploadProps['onProgress'] = (evt) => {\n uploadData.value.progress.percent = Math.floor(evt.percent)\n}\n\nconst onSuccess: UploadProps['onSuccess'] = (...args) => {\n // 清理预览 URL,防止内存泄漏\n if (uploadData.value.progress.preview) {\n URL.revokeObjectURL(uploadData.value.progress.preview)\n }\n\n uploadData.value.progress = {\n preview: '',\n percent: 0,\n }\n emits('success', ...args)\n}\n\n// 组件卸载时清理资源\nonUnmounted(() => {\n if (uploadData.value.progress.preview) {\n URL.revokeObjectURL(uploadData.value.progress.preview)\n }\n})\n</script>\n\n<template>\n <div\n :class=\"nsEl.e('container')\"\n :style=\"cssVar\"\n >\n <ElUpload\n v-bind=\"attrs\"\n v-model:file-list=\"normalizedFileList\"\n drag\n :limit=\"limit\"\n list-type=\"picture-card\"\n :headers=\"headers\"\n :action=\"action\"\n :data=\"data\"\n :name=\"name\"\n :accept=\"accept\"\n :before-upload=\"handleBeforeUpload\"\n :on-progress=\"onProgress\"\n :on-preview=\"onPreview\"\n :on-success=\"onSuccess\"\n :class=\"[nsEl.e('control'), limit <= normalizedFileList.length ? nsEl.e('more-than-limit') : '']\"\n :on-remove=\"onRemove\"\n >\n <slot>\n <div class=\"image-slot\">\n <QxsIcon\n size=\"32px\"\n :icon=\"UploadImage\"\n />\n <p>{{ placeholder }}</p>\n </div>\n </slot>\n <template #file=\"{ file }\">\n <img\n v-if=\"file.url\"\n :class=\"`${nsEl.namespace.value}-upload-list__item-thumbnail`\"\n :src=\"file.url\"\n :alt=\"file.name || '图片'\"\n >\n <div\n v-else\n :class=\"`${nsEl.namespace.value}-upload-list__item-thumbnail`\"\n style=\"display: flex; align-items: center; justify-content: center; color: #909399; background: #f5f7fa;\"\n >\n 无图片\n </div>\n <span :class=\"`${nsEl.namespace.value}-upload-list__item-actions`\">\n <span\n v-if=\"file.url\"\n :class=\"[\n `${nsEl.namespace.value}-upload-list__item-preview`,\n `${nsEl.namespace.value}-image-upload__action-btn`,\n `${nsEl.namespace.value}-image-upload__action-btn--preview`,\n ]\"\n @click=\"onPreview(file)\"\n >\n <ZoomIn size=\"14px\" />\n </span>\n <span\n v-if=\"file.url\"\n :class=\"`${nsEl.namespace.value}-upload-list__item-divider`\"\n />\n <span\n :class=\"[\n `${nsEl.namespace.value}-upload-list__item-delete`,\n `${nsEl.namespace.value}-image-upload__action-btn`,\n `${nsEl.namespace.value}-image-upload__action-btn--delete`,\n disabled ? 'is-disabled' : '',\n ]\"\n @click=\"handleRemoveClick(file, $event)\"\n >\n <Delete size=\"14px\" />\n </span>\n </span>\n </template>\n <template #tip>\n <slot name=\"tip\">\n <div\n v-if=\"!notip\"\n :class=\"`${nsEl.namespace.value}-upload__tip-text`\"\n >\n <div class=\"tip-content\">\n {{ tipMessage }}\n </div>\n </div>\n </slot>\n </template>\n </ElUpload>\n\n <ElImageViewer\n v-if=\"uploadData.imageViewerVisible\"\n :url-list=\"normalizedFileList.map((item: UploadFile) => item.url!).filter(Boolean)\"\n :initial-index=\"initialIndex\"\n :show-progress=\"normalizedFileList.length > 1\"\n teleported\n @close=\"previewClose\"\n />\n </div>\n</template>\n"],"names":["emits","__emit","attrs","useAttrs","fileList","_useModel","__props","uidCounter","normalizedFileList","computed","get","value","map","file","index","name","status","uid","Date","now","set","nsEl","useNamespace","initialIndex","ref","uploadData","imageViewerVisible","progress","preview","percent","cssVar","cssVarBlock","ns","namespace","width","height","exts","split","ext","pop","tipMessage","tipText","join","size","onPreview","disabled","url","findIndex","item","console","warn","onRemove","splice","previewClose","handleBeforeUpload","ElMessage","error","fileExt","toLowerCase","some","URL","createObjectURL","beforeUpload","onProgress","evt","Math","floor","onSuccess","args","revokeObjectURL","onUnmounted","_createElementBlock","class","_normalizeClass","_unref","e","style","_createVNode","ElUpload","_mergeProps","$event","drag","limit","headers","action","data","accept","length","_withCtx","src","alt","display","color","background","_createElementVNode","onClick","ZoomIn","event","preventDefault","stopPropagation","handleRemoveClick","Delete","tip","_renderSlot","_ctx","notip","_hoisted_5","_toDisplayString","_hoisted_1","_component_QxsIcon","icon","UploadImage","placeholder","_createBlock","ElImageViewer","filter","Boolean","teleported","onClose"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- "use strict";exports.version="0.0.73";
1
+ "use strict";exports.version="0.0.74";
2
2
  //# sourceMappingURL=package.json.cjs.map
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("vue"),a=require("@qxs-bns/icons"),t=require("element-plus");const l={class:"image-slot"},i=["src","alt"],r=["onClick"],s=["onClick"],n={class:"tip-content"};var o=e.defineComponent({name:"QxsImageUpload",__name:"image-upload",props:e.mergeModels({action:{type:String,required:!0},headers:{type:null,required:!1},data:{type:null,required:!1},name:{type:String,required:!1,default:"file"},size:{type:Number,required:!1,default:20},width:{type:Number,required:!1,default:160},height:{type:Number,required:!1,default:90},accept:{type:String,required:!1,default:"image/jpeg,image/jpg,image/png,image/gif"},placeholder:{type:String,required:!1,default:"上传图片"},notip:{type:Boolean,required:!1,default:!1},tipText:{type:String,required:!1,default:""},beforeUpload:{type:null,required:!1},disabled:{type:Boolean,required:!1,default:!1},limit:{type:Number,required:!1,default:1}},{fileList:{type:Array,default:()=>[]},fileListModifiers:{}}),emits:e.mergeModels(["success","remove"],["update:fileList"]),setup(o,{emit:u}){const p=u,c=e.useAttrs(),d=e.useModel(o,"fileList");let m=0;const f=e.computed({get:()=>d.value.map((e,a)=>e.name&&e.status&&e.uid?e:{...e,name:e.name||`image-${a+1}.jpg`,status:e.status||"success",uid:e.uid||`qxs-image-${Date.now()}-${++m}`}),set(e){d.value=e}}),v=t.useNamespace("image-upload"),g=e.ref(0),b=e.ref({imageViewerVisible:!1,progress:{preview:"",percent:0}}),h=e.computed(()=>v.cssVarBlock({ns:v.namespace.value,width:`${o.width}px`,height:`${o.height}px`})),y=e.computed(()=>o.accept.split(",").map(e=>e.split("/").pop())),w=e.computed(()=>{if(o.tipText)return o.tipText;return`上传图片支持 ${y.value.join(" / ")} 格式,且图片大小不超过 ${o.size}MB`+(o.width&&o.height?`,建议图片尺寸为 ${o.width}×${o.height}`:"")});function k(e){o.disabled||(e.url?(g.value=f.value.findIndex(a=>a.uid===e.uid),b.value.imageViewerVisible=!0):console.warn("文件缺少 URL,无法预览:",e))}function _(e){if(o.disabled)return;const a=f.value.findIndex(a=>a.uid===e.uid);a>-1&&d.value.splice(a,1)}function C(){b.value.imageViewerVisible=!1}const $=e=>{if(!e||!e.name)return t.ElMessage.error("文件信息无效!"),!1;const a=e.name.split(".").pop()?.toLowerCase()??"";if(!y.value.some(e=>e?.toLowerCase()===a))return t.ElMessage.error(`上传图片只支持 ${y.value.join(" / ")} 格式!`),!1;if(e.size/1024/1024>o.size)return t.ElMessage.error(`上传图片大小不能超过 ${o.size}MB!`),!1;try{b.value.progress.preview=URL.createObjectURL(e)}catch(e){console.warn("创建预览失败:",e)}return!o.beforeUpload||o.beforeUpload(e)},x=e=>{b.value.progress.percent=Math.floor(e.percent)},V=(...e)=>{b.value.progress.preview&&URL.revokeObjectURL(b.value.progress.preview),b.value.progress={preview:"",percent:0},p("success",...e)};return e.onUnmounted(()=>{b.value.progress.preview&&URL.revokeObjectURL(b.value.progress.preview)}),(u,p)=>{const d=e.resolveComponent("QxsIcon");return e.openBlock(),e.createElementBlock("div",{class:e.normalizeClass(e.unref(v).e("container")),style:e.normalizeStyle(h.value)},[e.createVNode(e.unref(t.ElUpload),e.mergeProps(e.unref(c),{"file-list":f.value,"onUpdate:fileList":p[0]||(p[0]=e=>f.value=e),drag:"",limit:u.limit,"list-type":"picture-card",headers:u.headers,action:u.action,data:u.data,name:u.name,accept:u.accept,"before-upload":$,"on-progress":x,"on-preview":k,"on-success":V,class:[e.unref(v).e("control"),u.limit<=f.value.length?e.unref(v).e("more-than-limit"):""],"on-remove":_}),{file:e.withCtx(({file:t})=>[t.url?(e.openBlock(),e.createElementBlock("img",{key:0,class:e.normalizeClass(`${e.unref(v).namespace.value}-upload-list__item-thumbnail`),src:t.url,alt:t.name||"图片"},null,10,i)):(e.openBlock(),e.createElementBlock("div",{key:1,class:e.normalizeClass(`${e.unref(v).namespace.value}-upload-list__item-thumbnail`),style:{display:"flex","align-items":"center","justify-content":"center",color:"#909399",background:"#f5f7fa"}}," 无图片 ",2)),e.createElementVNode("span",{class:e.normalizeClass(`${e.unref(v).namespace.value}-upload-list__item-actions`)},[t.url?(e.openBlock(),e.createElementBlock("span",{key:0,class:e.normalizeClass([`${e.unref(v).namespace.value}-upload-list__item-preview`,`${e.unref(v).namespace.value}-image-upload__action-btn`,`${e.unref(v).namespace.value}-image-upload__action-btn--preview`,u.disabled?"is-disabled":""]),onClick:e=>function(e,a){if(o.disabled)return a.preventDefault(),void a.stopPropagation();k(e)}(t,e)},[e.createVNode(e.unref(a.ZoomIn),{size:"14px"})],10,r)):e.createCommentVNode("v-if",!0),t.url?(e.openBlock(),e.createElementBlock("span",{key:1,class:e.normalizeClass(`${e.unref(v).namespace.value}-upload-list__item-divider`)},null,2)):e.createCommentVNode("v-if",!0),e.createElementVNode("span",{class:e.normalizeClass([`${e.unref(v).namespace.value}-upload-list__item-delete`,`${e.unref(v).namespace.value}-image-upload__action-btn`,`${e.unref(v).namespace.value}-image-upload__action-btn--delete`,u.disabled?"is-disabled":""]),onClick:e=>function(e,a){if(o.disabled)return a.preventDefault(),void a.stopPropagation();_(e)}(t,e)},[e.createVNode(e.unref(a.Delete),{size:"14px"})],10,s)],2)]),tip:e.withCtx(()=>[e.renderSlot(u.$slots,"tip",{},()=>[u.notip?e.createCommentVNode("v-if",!0):(e.openBlock(),e.createElementBlock("div",{key:0,class:e.normalizeClass(`${e.unref(v).namespace.value}-upload__tip-text`)},[e.createElementVNode("div",n,e.toDisplayString(w.value),1)],2))])]),default:e.withCtx(()=>[e.renderSlot(u.$slots,"default",{},()=>[e.createElementVNode("div",l,[e.createVNode(d,{size:"32px",icon:e.unref(a.UploadImage)},null,8,["icon"]),e.createElementVNode("p",null,e.toDisplayString(u.placeholder),1)])])]),_:3},16,["file-list","limit","headers","action","data","name","accept","class"]),b.value.imageViewerVisible?(e.openBlock(),e.createBlock(e.unref(t.ElImageViewer),{key:0,"url-list":f.value.map(e=>e.url).filter(Boolean),"initial-index":g.value,"show-progress":f.value.length>1,teleported:"",onClose:C},null,8,["url-list","initial-index","show-progress"])):e.createCommentVNode("v-if",!0)],6)}}});exports.default=o;
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("vue"),a=require("@qxs-bns/icons"),t=require("element-plus");const l={class:"image-slot"},i=["src","alt"],r=["onClick"],s=["onClick"],n={class:"tip-content"};var o=e.defineComponent({name:"QxsImageUpload",__name:"image-upload",props:e.mergeModels({action:{type:String,required:!0},headers:{type:null,required:!1},data:{type:null,required:!1},name:{type:String,required:!1,default:"file"},size:{type:Number,required:!1,default:20},width:{type:Number,required:!1,default:160},height:{type:Number,required:!1,default:90},accept:{type:String,required:!1,default:"image/jpeg,image/jpg,image/png,image/gif"},placeholder:{type:String,required:!1,default:"上传图片"},notip:{type:Boolean,required:!1,default:!1},tipText:{type:String,required:!1,default:""},beforeUpload:{type:null,required:!1},disabled:{type:Boolean,required:!1,default:!1},limit:{type:Number,required:!1,default:1}},{fileList:{type:Array,default:()=>[]},fileListModifiers:{}}),emits:e.mergeModels(["success","remove"],["update:fileList"]),setup(o,{emit:u}){const p=u,c=e.useAttrs(),d=e.useModel(o,"fileList");let m=0;const f=e.computed({get:()=>d.value.map((e,a)=>e.name&&e.status&&e.uid?e:{...e,name:e.name||`image-${a+1}.jpg`,status:e.status||"success",uid:e.uid||`qxs-image-${Date.now()}-${++m}`}),set(e){d.value=e}}),v=t.useNamespace("image-upload"),g=e.ref(0),h=e.ref({imageViewerVisible:!1,progress:{preview:"",percent:0}}),y=e.computed(()=>v.cssVarBlock({ns:v.namespace.value,width:`${o.width}px`,height:`${o.height}px`})),b=e.computed(()=>o.accept.split(",").map(e=>e.split("/").pop())),w=e.computed(()=>{if(o.tipText)return o.tipText;return`上传图片支持 ${b.value.join(" / ")} 格式,且图片大小不超过 ${o.size}MB`+(o.width&&o.height?`,建议图片尺寸为 ${o.width}×${o.height}`:"")});function k(e){o.disabled||(e.url?(g.value=f.value.findIndex(a=>a.uid===e.uid),h.value.imageViewerVisible=!0):console.warn("文件缺少 URL,无法预览:",e))}function _(e){if(o.disabled)return;const a=f.value.findIndex(a=>a.uid===e.uid);a>-1&&d.value.splice(a,1)}function C(){h.value.imageViewerVisible=!1}const $=e=>{if(!e||!e.name)return t.ElMessage.error("文件信息无效!"),!1;const a=e.name.split(".").pop()?.toLowerCase()??"";if(!b.value.some(e=>e?.toLowerCase()===a))return t.ElMessage.error(`上传图片只支持 ${b.value.join(" / ")} 格式!`),!1;if(e.size/1024/1024>o.size)return t.ElMessage.error(`上传图片大小不能超过 ${o.size}MB!`),!1;try{h.value.progress.preview=URL.createObjectURL(e)}catch(e){console.warn("创建预览失败:",e)}return!o.beforeUpload||o.beforeUpload(e)},x=e=>{h.value.progress.percent=Math.floor(e.percent)},V=(...e)=>{h.value.progress.preview&&URL.revokeObjectURL(h.value.progress.preview),h.value.progress={preview:"",percent:0},p("success",...e)};return e.onUnmounted(()=>{h.value.progress.preview&&URL.revokeObjectURL(h.value.progress.preview)}),(u,p)=>{const d=e.resolveComponent("QxsIcon");return e.openBlock(),e.createElementBlock("div",{class:e.normalizeClass(e.unref(v).e("container")),style:e.normalizeStyle(y.value)},[e.createVNode(e.unref(t.ElUpload),e.mergeProps(e.unref(c),{"file-list":f.value,"onUpdate:fileList":p[0]||(p[0]=e=>f.value=e),drag:"",limit:u.limit,"list-type":"picture-card",headers:u.headers,action:u.action,data:u.data,name:u.name,accept:u.accept,"before-upload":$,"on-progress":x,"on-preview":k,"on-success":V,class:[e.unref(v).e("control"),u.limit<=f.value.length?e.unref(v).e("more-than-limit"):""],"on-remove":_}),{file:e.withCtx(({file:t})=>[t.url?(e.openBlock(),e.createElementBlock("img",{key:0,class:e.normalizeClass(`${e.unref(v).namespace.value}-upload-list__item-thumbnail`),src:t.url,alt:t.name||"图片"},null,10,i)):(e.openBlock(),e.createElementBlock("div",{key:1,class:e.normalizeClass(`${e.unref(v).namespace.value}-upload-list__item-thumbnail`),style:{display:"flex","align-items":"center","justify-content":"center",color:"#909399",background:"#f5f7fa"}}," 无图片 ",2)),e.createElementVNode("span",{class:e.normalizeClass(`${e.unref(v).namespace.value}-upload-list__item-actions`)},[t.url?(e.openBlock(),e.createElementBlock("span",{key:0,class:e.normalizeClass([`${e.unref(v).namespace.value}-upload-list__item-preview`,`${e.unref(v).namespace.value}-image-upload__action-btn`,`${e.unref(v).namespace.value}-image-upload__action-btn--preview`]),onClick:e=>k(t)},[e.createVNode(e.unref(a.ZoomIn),{size:"14px"})],10,r)):e.createCommentVNode("v-if",!0),t.url?(e.openBlock(),e.createElementBlock("span",{key:1,class:e.normalizeClass(`${e.unref(v).namespace.value}-upload-list__item-divider`)},null,2)):e.createCommentVNode("v-if",!0),e.createElementVNode("span",{class:e.normalizeClass([`${e.unref(v).namespace.value}-upload-list__item-delete`,`${e.unref(v).namespace.value}-image-upload__action-btn`,`${e.unref(v).namespace.value}-image-upload__action-btn--delete`,u.disabled?"is-disabled":""]),onClick:e=>function(e,a){if(o.disabled)return a.preventDefault(),void a.stopPropagation();_(e)}(t,e)},[e.createVNode(e.unref(a.Delete),{size:"14px"})],10,s)],2)]),tip:e.withCtx(()=>[e.renderSlot(u.$slots,"tip",{},()=>[u.notip?e.createCommentVNode("v-if",!0):(e.openBlock(),e.createElementBlock("div",{key:0,class:e.normalizeClass(`${e.unref(v).namespace.value}-upload__tip-text`)},[e.createElementVNode("div",n,e.toDisplayString(w.value),1)],2))])]),default:e.withCtx(()=>[e.renderSlot(u.$slots,"default",{},()=>[e.createElementVNode("div",l,[e.createVNode(d,{size:"32px",icon:e.unref(a.UploadImage)},null,8,["icon"]),e.createElementVNode("p",null,e.toDisplayString(u.placeholder),1)])])]),_:3},16,["file-list","limit","headers","action","data","name","accept","class"]),h.value.imageViewerVisible?(e.openBlock(),e.createBlock(e.unref(t.ElImageViewer),{key:0,"url-list":f.value.map(e=>e.url).filter(Boolean),"initial-index":g.value,"show-progress":f.value.length>1,teleported:"",onClose:C},null,8,["url-list","initial-index","show-progress"])):e.createCommentVNode("v-if",!0)],6)}}});exports.default=o;
2
2
  //# sourceMappingURL=image-upload.vue.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"image-upload.vue.cjs","sources":["../../../../../../packages/components/src/image-upload/src/image-upload.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { UploadFile, UploadFiles, UploadProps } from 'element-plus'\nimport { Delete, UploadImage, ZoomIn } from '@qxs-bns/icons'\nimport { ElImageViewer, ElMessage, ElUpload, useNamespace } from 'element-plus'\nimport { computed, onUnmounted, ref, useAttrs } from 'vue'\n\n// 类型定义\nexport interface ImageUploadProps {\n /** 上传地址(必需) */\n action: UploadProps['action']\n /** 请求头 */\n headers?: UploadProps['headers']\n /** 上传时附带的额外参数 */\n data?: UploadProps['data']\n /** 上传的文件字段名 */\n name?: UploadProps['name']\n /** 文件大小限制(MB) */\n size?: number\n /** 图片显示宽度(px) */\n width?: number\n /** 图片显示高度(px) */\n height?: number\n /** 接受的文件类型 */\n accept?: string\n /** 上传区域提示文字 */\n placeholder?: string\n /** 是否隐藏提示文字 */\n notip?: boolean\n /** 自定义提示文字 */\n tipText?: string\n /** 上传前的钩子函数 */\n beforeUpload?: UploadProps['beforeUpload']\n /** 是否禁用 */\n disabled?: boolean\n /** 最大上传数量 */\n limit?: number\n}\n\ninterface UploadProgress {\n preview: string\n percent: number\n}\n\n// 组件名称\ndefineOptions({\n name: 'QxsImageUpload',\n})\n\n// Props 定义\nconst {\n action,\n headers,\n data,\n name = 'file',\n size = 20,\n width = 160,\n height = 90,\n limit = 1,\n placeholder = '上传图片',\n notip = false,\n accept = 'image/jpeg,image/jpg,image/png,image/gif',\n beforeUpload,\n tipText = '',\n disabled = false,\n} = defineProps<ImageUploadProps>()\n\n// Emits 定义 - 统一事件命名\nconst emits = defineEmits<{\n success: [res: any, uploadFile: UploadFile, uploadFiles: UploadFiles]\n remove: [file: UploadFile]\n}>()\n\nconst attrs = useAttrs()\n\nconst fileList = defineModel('fileList', {\n type: Array as () => UploadFile[],\n default: () => [],\n})\n\n// 生成唯一 ID 的计数器\nlet uidCounter = 0\n\n// 处理不完整的文件对象,自动补全必要属性\nconst normalizedFileList = computed({\n get() {\n return fileList.value.map((file, index) => {\n // 如果文件对象不完整,自动补全必要属性\n if (!file.name || !file.status || !file.uid) {\n return {\n ...file, // 保留原有属性\n name: file.name || `image-${index + 1}.jpg`,\n status: file.status || 'success',\n uid: file.uid || `qxs-image-${Date.now()}-${++uidCounter}`, // 确保唯一性\n } as UploadFile\n }\n return file\n })\n },\n set(value: UploadFile[]) {\n fileList.value = value\n },\n})\n\n// 命名空间\nconst nsEl = useNamespace('image-upload')\n\nconst initialIndex = ref(0)\n// 响应式数据\nconst uploadData = ref<{\n imageViewerVisible: boolean\n progress: UploadProgress\n}>({\n imageViewerVisible: false,\n progress: {\n preview: '',\n percent: 0,\n },\n})\n\nconst cssVar = computed(() => {\n return nsEl.cssVarBlock({\n ns: nsEl.namespace.value,\n width: `${width}px`,\n height: `${height}px`,\n })\n})\n\n// 计算属性\nconst exts = computed(() =>\n accept.split(',').map(ext => ext.split('/').pop()),\n)\n\nconst tipMessage = computed(() => {\n if (tipText) {\n return tipText\n }\n\n const formatText = `上传图片支持 ${exts.value.join(' / ')} 格式,且图片大小不超过 ${size}MB`\n const sizeText = width && height ? `,建议图片尺寸为 ${width}×${height}` : ''\n\n return formatText + sizeText\n})\n\n// 方法\nfunction onPreview(file: UploadFile) {\n // 如果组件被禁用,阻止预览\n if (disabled) {\n return\n }\n\n // 确保文件有有效的 URL 才能预览\n if (!file.url) {\n console.warn('文件缺少 URL,无法预览:', file)\n return\n }\n\n // 使用 uid 作为唯一标识符来查找文件索引\n initialIndex.value = normalizedFileList.value.findIndex(item => item.uid === file.uid)\n uploadData.value.imageViewerVisible = true\n}\n\nfunction onRemove(file: UploadFile) {\n // 如果组件被禁用,阻止删除\n if (disabled) {\n return\n }\n\n // 使用 uid 作为唯一标识符来查找并删除文件\n const index = normalizedFileList.value.findIndex(item => item.uid === file.uid)\n if (index > -1) {\n fileList.value.splice(index, 1)\n }\n}\n\n// 处理手动点击事件(用于模板中的按钮)\nfunction handlePreviewClick(file: UploadFile, event: Event) {\n if (disabled) {\n event.preventDefault()\n event.stopPropagation()\n return\n }\n onPreview(file)\n}\n\nfunction handleRemoveClick(file: UploadFile, event: Event) {\n if (disabled) {\n event.preventDefault()\n event.stopPropagation()\n return\n }\n onRemove(file)\n}\n\nfunction previewClose() {\n uploadData.value.imageViewerVisible = false\n}\n\nconst handleBeforeUpload: UploadProps['beforeUpload'] = (file) => {\n // 参数校验\n if (!file || !file.name) {\n ElMessage.error('文件信息无效!')\n return false\n }\n\n // 文件类型校验\n const fileExt = file.name.split('.').pop()?.toLowerCase() ?? ''\n const isTypeOk = exts.value.some(ext => ext?.toLowerCase() === fileExt)\n\n if (!isTypeOk) {\n ElMessage.error(`上传图片只支持 ${exts.value.join(' / ')} 格式!`)\n return false\n }\n\n // 文件大小校验\n const fileSizeMB = file.size / 1024 / 1024\n if (fileSizeMB > size) {\n ElMessage.error(`上传图片大小不能超过 ${size}MB!`)\n return false\n }\n\n // 设置预览\n try {\n uploadData.value.progress.preview = URL.createObjectURL(file)\n }\n catch (error) {\n console.warn('创建预览失败:', error)\n }\n\n // 执行自定义校验\n return beforeUpload ? beforeUpload(file) : true\n}\n\nconst onProgress: UploadProps['onProgress'] = (evt) => {\n uploadData.value.progress.percent = Math.floor(evt.percent)\n}\n\nconst onSuccess: UploadProps['onSuccess'] = (...args) => {\n // 清理预览 URL,防止内存泄漏\n if (uploadData.value.progress.preview) {\n URL.revokeObjectURL(uploadData.value.progress.preview)\n }\n\n uploadData.value.progress = {\n preview: '',\n percent: 0,\n }\n emits('success', ...args)\n}\n\n// 组件卸载时清理资源\nonUnmounted(() => {\n if (uploadData.value.progress.preview) {\n URL.revokeObjectURL(uploadData.value.progress.preview)\n }\n})\n</script>\n\n<template>\n <div\n :class=\"nsEl.e('container')\"\n :style=\"cssVar\"\n >\n <ElUpload\n v-bind=\"attrs\"\n v-model:file-list=\"normalizedFileList\"\n drag\n :limit=\"limit\"\n list-type=\"picture-card\"\n :headers=\"headers\"\n :action=\"action\"\n :data=\"data\"\n :name=\"name\"\n :accept=\"accept\"\n :before-upload=\"handleBeforeUpload\"\n :on-progress=\"onProgress\"\n :on-preview=\"onPreview\"\n :on-success=\"onSuccess\"\n :class=\"[nsEl.e('control'), limit <= normalizedFileList.length ? nsEl.e('more-than-limit') : '']\"\n :on-remove=\"onRemove\"\n >\n <slot>\n <div class=\"image-slot\">\n <QxsIcon\n size=\"32px\"\n :icon=\"UploadImage\"\n />\n <p>{{ placeholder }}</p>\n </div>\n </slot>\n <template #file=\"{ file }\">\n <img\n v-if=\"file.url\"\n :class=\"`${nsEl.namespace.value}-upload-list__item-thumbnail`\"\n :src=\"file.url\"\n :alt=\"file.name || '图片'\"\n >\n <div\n v-else\n :class=\"`${nsEl.namespace.value}-upload-list__item-thumbnail`\"\n style=\"display: flex; align-items: center; justify-content: center; color: #909399; background: #f5f7fa;\"\n >\n 无图片\n </div>\n <span :class=\"`${nsEl.namespace.value}-upload-list__item-actions`\">\n <span\n v-if=\"file.url\"\n :class=\"[\n `${nsEl.namespace.value}-upload-list__item-preview`,\n `${nsEl.namespace.value}-image-upload__action-btn`,\n `${nsEl.namespace.value}-image-upload__action-btn--preview`,\n disabled ? 'is-disabled' : '',\n ]\"\n @click=\"handlePreviewClick(file, $event)\"\n >\n <ZoomIn size=\"14px\" />\n </span>\n <span\n v-if=\"file.url\"\n :class=\"`${nsEl.namespace.value}-upload-list__item-divider`\"\n />\n <span\n :class=\"[\n `${nsEl.namespace.value}-upload-list__item-delete`,\n `${nsEl.namespace.value}-image-upload__action-btn`,\n `${nsEl.namespace.value}-image-upload__action-btn--delete`,\n disabled ? 'is-disabled' : '',\n ]\"\n @click=\"handleRemoveClick(file, $event)\"\n >\n <Delete size=\"14px\" />\n </span>\n </span>\n </template>\n <template #tip>\n <slot name=\"tip\">\n <div\n v-if=\"!notip\"\n :class=\"`${nsEl.namespace.value}-upload__tip-text`\"\n >\n <div class=\"tip-content\">\n {{ tipMessage }}\n </div>\n </div>\n </slot>\n </template>\n </ElUpload>\n\n <ElImageViewer\n v-if=\"uploadData.imageViewerVisible\"\n :url-list=\"normalizedFileList.map((item: UploadFile) => item.url!).filter(Boolean)\"\n :initial-index=\"initialIndex\"\n :show-progress=\"normalizedFileList.length > 1\"\n teleported\n @close=\"previewClose\"\n />\n </div>\n</template>\n"],"names":["emits","__emit","attrs","useAttrs","fileList","_useModel","__props","uidCounter","normalizedFileList","computed","get","value","map","file","index","name","status","uid","Date","now","set","nsEl","useNamespace","initialIndex","ref","uploadData","imageViewerVisible","progress","preview","percent","cssVar","cssVarBlock","ns","namespace","width","height","exts","split","ext","pop","tipMessage","tipText","join","size","onPreview","disabled","url","findIndex","item","console","warn","onRemove","splice","previewClose","handleBeforeUpload","ElMessage","error","fileExt","toLowerCase","some","URL","createObjectURL","beforeUpload","onProgress","evt","Math","floor","onSuccess","args","revokeObjectURL","onUnmounted","_createElementBlock","class","_normalizeClass","_unref","e","style","_createVNode","ElUpload","_mergeProps","$event","drag","limit","headers","action","data","accept","length","_withCtx","src","alt","display","color","background","_createElementVNode","onClick","event","preventDefault","stopPropagation","handlePreviewClick","ZoomIn","handleRemoveClick","Delete","tip","_renderSlot","_ctx","notip","_hoisted_5","_toDisplayString","_hoisted_1","_component_QxsIcon","icon","UploadImage","placeholder","_createBlock","ElImageViewer","filter","Boolean","teleported","onClose"],"mappings":"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"}
1
+ {"version":3,"file":"image-upload.vue.cjs","sources":["../../../../../../packages/components/src/image-upload/src/image-upload.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { UploadFile, UploadFiles, UploadProps } from 'element-plus'\nimport { Delete, UploadImage, ZoomIn } from '@qxs-bns/icons'\nimport { ElImageViewer, ElMessage, ElUpload, useNamespace } from 'element-plus'\nimport { computed, onUnmounted, ref, useAttrs } from 'vue'\n\n// 类型定义\nexport interface ImageUploadProps {\n /** 上传地址(必需) */\n action: UploadProps['action']\n /** 请求头 */\n headers?: UploadProps['headers']\n /** 上传时附带的额外参数 */\n data?: UploadProps['data']\n /** 上传的文件字段名 */\n name?: UploadProps['name']\n /** 文件大小限制(MB) */\n size?: number\n /** 图片显示宽度(px) */\n width?: number\n /** 图片显示高度(px) */\n height?: number\n /** 接受的文件类型 */\n accept?: string\n /** 上传区域提示文字 */\n placeholder?: string\n /** 是否隐藏提示文字 */\n notip?: boolean\n /** 自定义提示文字 */\n tipText?: string\n /** 上传前的钩子函数 */\n beforeUpload?: UploadProps['beforeUpload']\n /** 是否禁用 */\n disabled?: boolean\n /** 最大上传数量 */\n limit?: number\n}\n\ninterface UploadProgress {\n preview: string\n percent: number\n}\n\n// 组件名称\ndefineOptions({\n name: 'QxsImageUpload',\n})\n\n// Props 定义\nconst {\n action,\n headers,\n data,\n name = 'file',\n size = 20,\n width = 160,\n height = 90,\n limit = 1,\n placeholder = '上传图片',\n notip = false,\n accept = 'image/jpeg,image/jpg,image/png,image/gif',\n beforeUpload,\n tipText = '',\n disabled = false,\n} = defineProps<ImageUploadProps>()\n\n// Emits 定义 - 统一事件命名\nconst emits = defineEmits<{\n success: [res: any, uploadFile: UploadFile, uploadFiles: UploadFiles]\n remove: [file: UploadFile]\n}>()\n\nconst attrs = useAttrs()\n\nconst fileList = defineModel('fileList', {\n type: Array as () => UploadFile[],\n default: () => [],\n})\n\n// 生成唯一 ID 的计数器\nlet uidCounter = 0\n\n// 处理不完整的文件对象,自动补全必要属性\nconst normalizedFileList = computed({\n get() {\n return fileList.value.map((file, index) => {\n // 如果文件对象不完整,自动补全必要属性\n if (!file.name || !file.status || !file.uid) {\n return {\n ...file, // 保留原有属性\n name: file.name || `image-${index + 1}.jpg`,\n status: file.status || 'success',\n uid: file.uid || `qxs-image-${Date.now()}-${++uidCounter}`, // 确保唯一性\n } as UploadFile\n }\n return file\n })\n },\n set(value: UploadFile[]) {\n fileList.value = value\n },\n})\n\n// 命名空间\nconst nsEl = useNamespace('image-upload')\n\nconst initialIndex = ref(0)\n// 响应式数据\nconst uploadData = ref<{\n imageViewerVisible: boolean\n progress: UploadProgress\n}>({\n imageViewerVisible: false,\n progress: {\n preview: '',\n percent: 0,\n },\n})\n\nconst cssVar = computed(() => {\n return nsEl.cssVarBlock({\n ns: nsEl.namespace.value,\n width: `${width}px`,\n height: `${height}px`,\n })\n})\n\n// 计算属性\nconst exts = computed(() =>\n accept.split(',').map(ext => ext.split('/').pop()),\n)\n\nconst tipMessage = computed(() => {\n if (tipText) {\n return tipText\n }\n\n const formatText = `上传图片支持 ${exts.value.join(' / ')} 格式,且图片大小不超过 ${size}MB`\n const sizeText = width && height ? `,建议图片尺寸为 ${width}×${height}` : ''\n\n return formatText + sizeText\n})\n\n// 方法\nfunction onPreview(file: UploadFile) {\n // 如果组件被禁用,阻止预览\n if (disabled) {\n return\n }\n\n // 确保文件有有效的 URL 才能预览\n if (!file.url) {\n console.warn('文件缺少 URL,无法预览:', file)\n return\n }\n\n // 使用 uid 作为唯一标识符来查找文件索引\n initialIndex.value = normalizedFileList.value.findIndex(item => item.uid === file.uid)\n uploadData.value.imageViewerVisible = true\n}\n\nfunction onRemove(file: UploadFile) {\n // 如果组件被禁用,阻止删除\n if (disabled) {\n return\n }\n\n // 使用 uid 作为唯一标识符来查找并删除文件\n const index = normalizedFileList.value.findIndex(item => item.uid === file.uid)\n if (index > -1) {\n fileList.value.splice(index, 1)\n }\n}\n\nfunction handleRemoveClick(file: UploadFile, event: Event) {\n if (disabled) {\n event.preventDefault()\n event.stopPropagation()\n return\n }\n onRemove(file)\n}\n\nfunction previewClose() {\n uploadData.value.imageViewerVisible = false\n}\n\nconst handleBeforeUpload: UploadProps['beforeUpload'] = (file) => {\n // 参数校验\n if (!file || !file.name) {\n ElMessage.error('文件信息无效!')\n return false\n }\n\n // 文件类型校验\n const fileExt = file.name.split('.').pop()?.toLowerCase() ?? ''\n const isTypeOk = exts.value.some(ext => ext?.toLowerCase() === fileExt)\n\n if (!isTypeOk) {\n ElMessage.error(`上传图片只支持 ${exts.value.join(' / ')} 格式!`)\n return false\n }\n\n // 文件大小校验\n const fileSizeMB = file.size / 1024 / 1024\n if (fileSizeMB > size) {\n ElMessage.error(`上传图片大小不能超过 ${size}MB!`)\n return false\n }\n\n // 设置预览\n try {\n uploadData.value.progress.preview = URL.createObjectURL(file)\n }\n catch (error) {\n console.warn('创建预览失败:', error)\n }\n\n // 执行自定义校验\n return beforeUpload ? beforeUpload(file) : true\n}\n\nconst onProgress: UploadProps['onProgress'] = (evt) => {\n uploadData.value.progress.percent = Math.floor(evt.percent)\n}\n\nconst onSuccess: UploadProps['onSuccess'] = (...args) => {\n // 清理预览 URL,防止内存泄漏\n if (uploadData.value.progress.preview) {\n URL.revokeObjectURL(uploadData.value.progress.preview)\n }\n\n uploadData.value.progress = {\n preview: '',\n percent: 0,\n }\n emits('success', ...args)\n}\n\n// 组件卸载时清理资源\nonUnmounted(() => {\n if (uploadData.value.progress.preview) {\n URL.revokeObjectURL(uploadData.value.progress.preview)\n }\n})\n</script>\n\n<template>\n <div\n :class=\"nsEl.e('container')\"\n :style=\"cssVar\"\n >\n <ElUpload\n v-bind=\"attrs\"\n v-model:file-list=\"normalizedFileList\"\n drag\n :limit=\"limit\"\n list-type=\"picture-card\"\n :headers=\"headers\"\n :action=\"action\"\n :data=\"data\"\n :name=\"name\"\n :accept=\"accept\"\n :before-upload=\"handleBeforeUpload\"\n :on-progress=\"onProgress\"\n :on-preview=\"onPreview\"\n :on-success=\"onSuccess\"\n :class=\"[nsEl.e('control'), limit <= normalizedFileList.length ? nsEl.e('more-than-limit') : '']\"\n :on-remove=\"onRemove\"\n >\n <slot>\n <div class=\"image-slot\">\n <QxsIcon\n size=\"32px\"\n :icon=\"UploadImage\"\n />\n <p>{{ placeholder }}</p>\n </div>\n </slot>\n <template #file=\"{ file }\">\n <img\n v-if=\"file.url\"\n :class=\"`${nsEl.namespace.value}-upload-list__item-thumbnail`\"\n :src=\"file.url\"\n :alt=\"file.name || '图片'\"\n >\n <div\n v-else\n :class=\"`${nsEl.namespace.value}-upload-list__item-thumbnail`\"\n style=\"display: flex; align-items: center; justify-content: center; color: #909399; background: #f5f7fa;\"\n >\n 无图片\n </div>\n <span :class=\"`${nsEl.namespace.value}-upload-list__item-actions`\">\n <span\n v-if=\"file.url\"\n :class=\"[\n `${nsEl.namespace.value}-upload-list__item-preview`,\n `${nsEl.namespace.value}-image-upload__action-btn`,\n `${nsEl.namespace.value}-image-upload__action-btn--preview`,\n ]\"\n @click=\"onPreview(file)\"\n >\n <ZoomIn size=\"14px\" />\n </span>\n <span\n v-if=\"file.url\"\n :class=\"`${nsEl.namespace.value}-upload-list__item-divider`\"\n />\n <span\n :class=\"[\n `${nsEl.namespace.value}-upload-list__item-delete`,\n `${nsEl.namespace.value}-image-upload__action-btn`,\n `${nsEl.namespace.value}-image-upload__action-btn--delete`,\n disabled ? 'is-disabled' : '',\n ]\"\n @click=\"handleRemoveClick(file, $event)\"\n >\n <Delete size=\"14px\" />\n </span>\n </span>\n </template>\n <template #tip>\n <slot name=\"tip\">\n <div\n v-if=\"!notip\"\n :class=\"`${nsEl.namespace.value}-upload__tip-text`\"\n >\n <div class=\"tip-content\">\n {{ tipMessage }}\n </div>\n </div>\n </slot>\n </template>\n </ElUpload>\n\n <ElImageViewer\n v-if=\"uploadData.imageViewerVisible\"\n :url-list=\"normalizedFileList.map((item: UploadFile) => item.url!).filter(Boolean)\"\n :initial-index=\"initialIndex\"\n :show-progress=\"normalizedFileList.length > 1\"\n teleported\n @close=\"previewClose\"\n />\n </div>\n</template>\n"],"names":["emits","__emit","attrs","useAttrs","fileList","_useModel","__props","uidCounter","normalizedFileList","computed","get","value","map","file","index","name","status","uid","Date","now","set","nsEl","useNamespace","initialIndex","ref","uploadData","imageViewerVisible","progress","preview","percent","cssVar","cssVarBlock","ns","namespace","width","height","exts","split","ext","pop","tipMessage","tipText","join","size","onPreview","disabled","url","findIndex","item","console","warn","onRemove","splice","previewClose","handleBeforeUpload","ElMessage","error","fileExt","toLowerCase","some","URL","createObjectURL","beforeUpload","onProgress","evt","Math","floor","onSuccess","args","revokeObjectURL","onUnmounted","_createElementBlock","class","_normalizeClass","_unref","e","style","_createVNode","ElUpload","_mergeProps","$event","drag","limit","headers","action","data","accept","length","_withCtx","src","alt","display","color","background","_createElementVNode","onClick","ZoomIn","event","preventDefault","stopPropagation","handleRemoveClick","Delete","tip","_renderSlot","_ctx","notip","_hoisted_5","_toDisplayString","_hoisted_1","_component_QxsIcon","icon","UploadImage","placeholder","_createBlock","ElImageViewer","filter","Boolean","teleported","onClose"],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@qxs-bns/components",
3
3
  "type": "module",
4
- "version": "0.0.73",
4
+ "version": "0.0.74",
5
5
  "description": "Vue 3 Component Library",
6
6
  "license": "MIT",
7
7
  "homepage": "https://qxs-bns.pages.dev/guide/components/overview.html",
@@ -1 +1 @@
1
- {"version":3,"file":"image-upload.vue.d.ts","sourceRoot":"","sources":["../../../../../../packages/components/src/image-upload/src/image-upload.vue"],"names":[],"mappings":"AAAA,OAuWO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAMxE,MAAM,WAAW,gBAAgB;IAC/B,eAAe;IACf,MAAM,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAA;IAC7B,UAAU;IACV,OAAO,CAAC,EAAE,WAAW,CAAC,SAAS,CAAC,CAAA;IAChC,iBAAiB;IACjB,IAAI,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAA;IAC1B,eAAe;IACf,IAAI,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAA;IAC1B,iBAAiB;IACjB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,iBAAiB;IACjB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,iBAAiB;IACjB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,cAAc;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,eAAe;IACf,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,eAAe;IACf,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,cAAc;IACd,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,eAAe;IACf,YAAY,CAAC,EAAE,WAAW,CAAC,cAAc,CAAC,CAAA;IAC1C,WAAW;IACX,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,aAAa;IACb,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAaD,KAAK,WAAW,GAAG,gBAAgB,CAAC;AA2BpC,QAAA,MAAM,QAAQ,0EAGZ,CAAA;AAwLF,KAAK,iBAAiB,GAAG,WAAW,GAAG;IACvC,UAAU,CAAC,EAAE,OAAO,QAAQ,CAAC,OAAO,CAAC,CAAC;CACrC,CAAC;AAwLF,QAAA,IAAI,OAAO,IAAU,EAAE,QAAQ,IAAY,CAAE;AAC7C,KAAK,WAAW,GAAG,EAAE,GACnB;IAAE,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,OAAO,KAAK,GAAG,CAAA;CAAE,GAC5C;IAAE,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,QAAQ,KAAK,GAAG,CAAA;CAAE,CAAC;AAwC5C,QAAA,MAAM,eAAe;;;;;;;;kFAOnB,CAAC;wBACkB,eAAe,CAAC,OAAO,eAAe,EAAE,WAAW,CAAC;AAAzE,wBAA0E;AAQ1E,KAAK,eAAe,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG;IAChC,QAAO;QACN,MAAM,EAAE,CAAC,CAAC;KAEV,CAAA;CACD,CAAC"}
1
+ {"version":3,"file":"image-upload.vue.d.ts","sourceRoot":"","sources":["../../../../../../packages/components/src/image-upload/src/image-upload.vue"],"names":[],"mappings":"AAAA,OA4VO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAMxE,MAAM,WAAW,gBAAgB;IAC/B,eAAe;IACf,MAAM,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAA;IAC7B,UAAU;IACV,OAAO,CAAC,EAAE,WAAW,CAAC,SAAS,CAAC,CAAA;IAChC,iBAAiB;IACjB,IAAI,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAA;IAC1B,eAAe;IACf,IAAI,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAA;IAC1B,iBAAiB;IACjB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,iBAAiB;IACjB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,iBAAiB;IACjB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,cAAc;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,eAAe;IACf,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,eAAe;IACf,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,cAAc;IACd,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,eAAe;IACf,YAAY,CAAC,EAAE,WAAW,CAAC,cAAc,CAAC,CAAA;IAC1C,WAAW;IACX,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,aAAa;IACb,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAaD,KAAK,WAAW,GAAG,gBAAgB,CAAC;AA2BpC,QAAA,MAAM,QAAQ,0EAGZ,CAAA;AA8KF,KAAK,iBAAiB,GAAG,WAAW,GAAG;IACvC,UAAU,CAAC,EAAE,OAAO,QAAQ,CAAC,OAAO,CAAC,CAAC;CACrC,CAAC;AAuLF,QAAA,IAAI,OAAO,IAAU,EAAE,QAAQ,IAAY,CAAE;AAC7C,KAAK,WAAW,GAAG,EAAE,GACnB;IAAE,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,OAAO,KAAK,GAAG,CAAA;CAAE,GAC5C;IAAE,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,QAAQ,KAAK,GAAG,CAAA;CAAE,CAAC;AAuC5C,QAAA,MAAM,eAAe;;;;;;;;kFAOnB,CAAC;wBACkB,eAAe,CAAC,OAAO,eAAe,EAAE,WAAW,CAAC;AAAzE,wBAA0E;AAQ1E,KAAK,eAAe,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG;IAChC,QAAO;QACN,MAAM,EAAE,CAAC,CAAC;KAEV,CAAA;CACD,CAAC"}