Last active
February 29, 2024 21:32
-
-
Save dansp89/e6b0105a03edf24d97b4a1d2d864ed03 to your computer and use it in GitHub Desktop.
Apagar depois
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<template> | |
<el-upload | |
v-model:file-list="fileList" | |
class="photo-wall-uploader" | |
:list-type="listType" | |
:drag="true" | |
:name="name" | |
:action="uploadMetas.url" | |
:method="uploadMetas.method" | |
:headers="uploadMetas.headers" | |
:accept="accept" | |
:multiple="multiple" | |
:show-file-list="true" | |
:on-success="handleDragSuccess" | |
:on-remove="handleDragRemove" | |
:on-exceed="handleExceed" | |
:before-remove="beforeRemove" | |
:before-upload="beforeDragUpload" | |
:auto-upload="true" | |
:limit="limit" | |
> | |
<!-- :disabled="fileList.length >= limit" --> | |
<el-icon class="el-icon--upload"><upload-filled /></el-icon> | |
<div class="el-upload__text"> | |
Solte o arquivo aqui ou | |
<em>clique para fazer upload</em> | |
</div> | |
<template #tip> | |
<div class="el-upload__tip" v-html="instructions"></div> | |
</template> | |
</el-upload> | |
<el-dialog v-model="dialogVisible"> | |
<img :src="dialogImageUrl" alt="Preview Image" /> | |
</el-dialog> | |
</template> | |
<script lang="ts"> | |
/** | |
* @source Basic Usage <https://element-plus.org/en-US/component/upload.html#photo-wall> | |
*/ | |
import { | |
defineComponent, | |
ref, | |
watchEffect, | |
watch, | |
type PropType, | |
onMounted | |
} from "vue"; | |
import { ElMessage, ElMessageBox } from "element-plus"; | |
import type { UploadProps, UploadUserFile } from "element-plus"; | |
import { UploadFilled } from "@element-plus/icons-vue"; | |
import { getToken } from "@/core/services/JwtService"; | |
import ApiService from "@/core/services/ApiService"; | |
import { getAssetPath } from "@/core/helpers/assets"; | |
export default defineComponent({ | |
name: "campo-upload-photowall", | |
components: { UploadFilled }, | |
props: { | |
buttonText: { | |
type: String, | |
default: "Clique para upload" | |
}, | |
accept: { | |
type: String, | |
default: "*" | |
}, | |
multiple: { | |
type: Boolean, | |
default: false | |
}, | |
name: { | |
type: String, | |
default: "files" // ( Nome da chave para o arquivo carregado. )Padrão usado no STRAPI 4 | |
}, | |
withCredentials: { | |
type: Boolean, | |
default: false | |
}, | |
showFileList: { | |
type: Boolean, | |
default: true | |
}, | |
drag: { | |
type: Boolean, | |
default: false | |
}, | |
listType: { | |
type: String as PropType<"text" | "picture" | "picture-card">, | |
default: "text", | |
validator: (value: string) => | |
["text", "picture", "picture-card"].includes(value) | |
}, | |
disabled: { | |
type: Boolean, | |
default: false | |
}, | |
limit: { | |
type: Number, | |
default: 1 | |
}, | |
limitSize: { | |
type: Number, | |
default: 2 | |
}, | |
modelValue: { | |
type: Array, // ou o tipo apropriado | |
default: () => [] | |
} | |
}, | |
emits: ["update:modelValue", "change", "input"], | |
setup(props, { emit }) { | |
const imageUrl = ref(""); | |
const fileList = ref<UploadUserFile[]>([]); | |
const dialogImageUrl = ref(""); | |
const dialogVisible = ref(false); | |
const imageUrls = ref([]); | |
const valor = ref(props.modelValue) as any; | |
const instructions = ref(""); | |
const uploadFileId = ref(); | |
const uploadData = {} as ImageData; // Resposta do servidor | |
const uploadMetas = { | |
url: import.meta.env.VITE_APP_API_URL + "/upload", | |
method: "POST", | |
headers: { | |
Authorization: `Bearer ${getToken()}` | |
} | |
}; | |
const loadImageById = async (ids: Array<number | string>) => { | |
// Reset imageUrls array | |
imageUrls.value = []; | |
const IDs = JSON.parse(JSON.stringify(ids)); | |
console.log("[loadImageById]::", IDs); | |
// Loop through each id and fetch its URL | |
for (const id of IDs) { | |
try { | |
const { data } = await ApiService.get(`/upload/files/${id}`); | |
const response = data; | |
// Assuming the response has a data object with a url property | |
// console.log("[loadImageById]::response", valor.value); | |
if (response.data && response.data.url) { | |
imageUrls.value.push( | |
import.meta.env.VITE_APP_API_URL.replace("/api", "") + | |
response.data.url | |
); | |
} | |
} catch (error) { | |
console.error("Error loading image with id:", id, error); | |
} | |
} | |
valor.value = IDs; | |
}; | |
watchEffect(() => { | |
if (props.accept === "*") { | |
instructions.value = `Permitido ${props.limit} arquivo de todos os formatos, até ${props.limitSize}mb`; | |
} else { | |
const filesExts = props.accept.split(",").map((a) => { | |
return `*.${a.split("/")[1]}`; | |
}); | |
const archive = props.limit < 2 ? "arquivo" : "arquivos"; | |
instructions.value = `Permitido <strong>${props.limit}</strong> ${archive} <strong>${filesExts}</strong> até <strong>${props.limitSize}mb</strong>`; | |
} | |
console.log("[Drag]::watchEffect", valor.value); | |
}); | |
const handleExceed: UploadProps["onExceed"] = (files, uploadFiles) => { | |
console.log("[handleExceed]", files, uploadFiles); | |
ElMessage.warning( | |
`O limite é de ${props.limit}, Você selecionou ${files.length} arquivos de uma vez.` | |
); | |
}; | |
watch( | |
() => props.modelValue, | |
(newValue, oldValue) => { | |
console.log("modelValue alterado:", newValue); | |
valor.value = newValue; | |
// Para imprimir as diferenças entre os valores antigo e novo | |
console.log("Valores antigos:", oldValue); | |
console.log("Novos valores:", newValue); | |
emit("update:modelValue", newValue); | |
emit("change", newValue); | |
emit("input", newValue); | |
loadImageById(newValue as any[]); | |
}, | |
{ deep: true, immediate: true } | |
); // { deep: true } para observação profunda, { immediate: true } para rodar na inicialização | |
const beforeRemove: UploadProps["beforeRemove"] = ( | |
uploadFile, | |
uploadFiles | |
) => { | |
console.log("[beforeRemove]", uploadFile, uploadFiles); | |
return ElMessageBox.confirm( | |
`Cancelar a transferência de ${uploadFile.name} ?` | |
).then( | |
() => true, | |
() => false | |
); | |
}; | |
const handleDragRemove: UploadProps["onRemove"] = async ( | |
uploadFile, | |
uploadFiles | |
) => { | |
console.log("[handleDragRemove]", uploadFile, uploadFiles); | |
let id = JSON.parse(JSON.stringify(uploadFile)); | |
console.log("[handleDragRemove]::FILES IDS:", id); | |
try { | |
id = id.response[0].id; | |
console.log("[handleDragRemove]::FILES IDS::toRemove:", id); | |
ApiService.setHeader(); | |
const deletar = await ApiService.delete(`/upload/files/${id}`); | |
console.log("[handleDragRemove]::deletar", deletar); | |
if (deletar?.status === 200) { | |
ElMessage.success("Eliminado com sucesso!"); | |
valor.value = valor.value?.filter((item) => item !== id); | |
updateValue(); | |
} else { | |
ElMessage.error("Falha ao eliminar!"); | |
} | |
} catch { | |
console.log(""); | |
} | |
}; | |
const handleDragCardPreview: UploadProps["onPreview"] = (uploadFile) => { | |
console.log("[handleDragCardPreview]", uploadFile); | |
const ext = uploadFile.raw.type.split("/")[1]; | |
console.log("EXT FILE::", ext); | |
if (uploadFile.raw.type.includes("image")) { | |
dialogImageUrl.value = URL.createObjectURL(uploadFile.raw!); | |
} else if (ext.includes("pdf")) { | |
dialogImageUrl.value = | |
window.location.origin + getAssetPath(`media/svg/files/${ext}.svg`); | |
} else { | |
dialogImageUrl.value = | |
window.location.origin + getAssetPath(`media/svg/files/upload.svg`); | |
} | |
// dialogImageUrl.value = uploadFile.url!; | |
dialogImageUrl.value = | |
window.location.origin + getAssetPath(`media/svg/files/upload.svg`); | |
dialogVisible.value = true; | |
valor.value = []; | |
updateValue(); | |
}; | |
const handleDragSuccess: UploadProps["onSuccess"] = ( | |
response, | |
uploadFile, | |
uploadFiles | |
) => { | |
const filesIds = uploadFiles | |
.map((a) => { | |
try { | |
a.response[0]?.id; | |
} catch { | |
a; | |
} | |
}) | |
.filter(Boolean); | |
console.log("[handleDragSuccess]::\n", response, uploadFile, filesIds); | |
const ext = uploadFile.raw.type.split("/")[1]; | |
console.log("EXT FILE::", ext); | |
if (uploadFile.raw.type.includes("image")) { | |
imageUrl.value = URL.createObjectURL(uploadFile.raw!); | |
} else if (ext.includes("pdf")) { | |
imageUrl.value = | |
window.location.origin + getAssetPath(`media/svg/files/${ext}.svg`); | |
} else { | |
imageUrl.value = | |
window.location.origin + getAssetPath(`media/svg/files/upload.svg`); | |
} | |
valor.value = filesIds; | |
console.log( | |
"[handleDragSuccess]::valor:", | |
JSON.parse(JSON.stringify(valor.value)), | |
"URL IMAGE:", | |
imageUrl.value | |
); | |
emit("update:modelValue", valor.value); | |
emit("change", valor.value); | |
emit("input", valor.value); | |
}; | |
const beforeDragUpload: UploadProps["beforeUpload"] = (rawFile) => { | |
if (valor.value.length >= props.limit) { | |
ElMessage.error(`Permitido no máximo até ${props.limit} arquivo(s).`); | |
return false; | |
} | |
if ( | |
!props.accept | |
.split(",") | |
.map((a) => a.trim()) | |
.includes(rawFile.type) | |
) { | |
ElMessage.error( | |
`Permitido ${props.limit} arquivo de todos os formatos, até ${props.limitSize}mb` | |
); | |
return false; | |
} | |
if (rawFile.size / 1024 / 1024 > props.limitSize) { | |
const filesExts = props.accept.split(",").map((a) => { | |
return `*.${a.split("/")[1]}`; | |
}); | |
const archive = props.limit < 2 ? "arquivo" : "arquivos"; | |
instructions.value = `Permitido <strong>${props.limit}</strong> ${archive} <strong>${filesExts}</strong> até <strong>${props.limitSize}mb</strong>`; | |
ElMessage.error({ | |
message: `Permitido ${props.limit} ${archive} ${filesExts} até ${props.limitSize}mb`, | |
duration: 5000 | |
}); | |
return false; | |
} | |
return true; | |
}; | |
onMounted(() => { | |
return loadImageById(valor.value); | |
}); | |
const updateValue = () => { | |
emit("update:modelValue", valor.value); | |
}; | |
return { | |
dialogImageUrl, | |
dialogVisible, | |
imageUrl, | |
fileList, | |
instructions, | |
uploadFileId, | |
uploadData, | |
uploadMetas, | |
valor, | |
updateValue, | |
handleExceed, | |
beforeRemove, | |
handleDragRemove, | |
handleDragCardPreview, | |
handleDragSuccess, | |
beforeDragUpload, | |
loadImageById, | |
imageUrls | |
}; | |
} | |
}); | |
</script> | |
<style scoped> | |
.el-dialog__body img { | |
width: 100%; | |
} | |
</style> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment