Skip to content

Instantly share code, notes, and snippets.

@dansp89
Last active February 29, 2024 21:32
Show Gist options
  • Save dansp89/e6b0105a03edf24d97b4a1d2d864ed03 to your computer and use it in GitHub Desktop.
Save dansp89/e6b0105a03edf24d97b4a1d2d864ed03 to your computer and use it in GitHub Desktop.
Apagar depois
<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