2024-11-01 17:18:24 +07:00
|
|
|
<script lang="ts" setup>
|
2024-12-25 11:59:49 +07:00
|
|
|
import { ref } from 'vue';
|
2024-11-01 17:18:24 +07:00
|
|
|
import { QFile } from 'quasar';
|
|
|
|
|
|
|
|
|
|
import { baseUrl } from 'stores/utils';
|
|
|
|
|
|
|
|
|
|
import UploadFileCard from './UploadFileCard.vue';
|
|
|
|
|
|
|
|
|
|
const props = withDefaults(
|
|
|
|
|
defineProps<{
|
|
|
|
|
readonly?: boolean;
|
|
|
|
|
label?: string;
|
|
|
|
|
multiple?: boolean;
|
2024-12-25 11:59:49 +07:00
|
|
|
layout?: 'row' | 'column';
|
2024-11-01 17:18:24 +07:00
|
|
|
transformUrl?: (url: string) => string | Promise<string>;
|
|
|
|
|
}>(),
|
|
|
|
|
{
|
2024-12-25 11:59:49 +07:00
|
|
|
layout: 'row',
|
2024-11-01 17:18:24 +07:00
|
|
|
label: 'Upload',
|
|
|
|
|
readonly: false,
|
|
|
|
|
multiple: false,
|
|
|
|
|
},
|
|
|
|
|
);
|
|
|
|
|
defineEmits<{
|
|
|
|
|
(e: 'close', name: string): void;
|
|
|
|
|
(e: 'update:file', file: File): void;
|
|
|
|
|
}>();
|
|
|
|
|
|
|
|
|
|
const fileData = defineModel<
|
|
|
|
|
{
|
|
|
|
|
name: string;
|
|
|
|
|
progress: number;
|
|
|
|
|
loaded: number;
|
|
|
|
|
total: number;
|
|
|
|
|
url?: string;
|
|
|
|
|
}[]
|
|
|
|
|
>('fileData', { required: true });
|
|
|
|
|
|
|
|
|
|
const file = ref<File[]>([]);
|
|
|
|
|
const refQFile = ref<InstanceType<typeof QFile>>();
|
|
|
|
|
|
2024-11-26 15:37:50 +07:00
|
|
|
async function triggerViewFile(url: string) {
|
2024-11-01 17:18:24 +07:00
|
|
|
window.open(
|
|
|
|
|
props.transformUrl ? await props.transformUrl(url) : `${baseUrl}/${url}`,
|
|
|
|
|
'_blank',
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function pickFile() {
|
|
|
|
|
if (!refQFile.value) return;
|
|
|
|
|
refQFile.value.pickFiles();
|
|
|
|
|
}
|
|
|
|
|
</script>
|
|
|
|
|
<template>
|
2024-12-25 11:59:49 +07:00
|
|
|
<div :class="{ row: layout === 'column' }">
|
2024-11-01 17:18:24 +07:00
|
|
|
<div
|
2024-12-25 11:59:49 +07:00
|
|
|
class="upload-section column rounded q-py-md items-center justify-center no-wrap surface-2 col"
|
2024-11-01 17:18:24 +07:00
|
|
|
>
|
|
|
|
|
<q-img src="/images/upload.png" width="150px" />
|
|
|
|
|
{{ label }}
|
|
|
|
|
<q-btn
|
|
|
|
|
v-if="!readonly"
|
|
|
|
|
unelevated
|
|
|
|
|
:label="$t('general.upload')"
|
|
|
|
|
rounded
|
|
|
|
|
class="app-bg-info q-mt-sm"
|
|
|
|
|
@click.stop="() => pickFile()"
|
|
|
|
|
/>
|
|
|
|
|
<q-file
|
|
|
|
|
ref="refQFile"
|
|
|
|
|
:multiple
|
|
|
|
|
v-show="false"
|
|
|
|
|
v-model="file"
|
|
|
|
|
@update:model-value="(f) => $emit('update:file', f)"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- upload card -->
|
2024-12-25 11:59:49 +07:00
|
|
|
<section class="row col" :class="{ 'q-pl-md': layout === 'column' }">
|
2024-11-01 17:18:24 +07:00
|
|
|
<div
|
|
|
|
|
v-for="(d, j) in fileData"
|
|
|
|
|
:key="j"
|
|
|
|
|
class="col-12"
|
|
|
|
|
:class="{
|
2024-12-25 11:59:49 +07:00
|
|
|
'q-pt-md': layout === 'row' && j === 0,
|
2024-11-01 17:18:24 +07:00
|
|
|
'q-pt-sm': j > 0,
|
|
|
|
|
}"
|
|
|
|
|
>
|
|
|
|
|
<UploadFileCard
|
|
|
|
|
:name="d.name"
|
|
|
|
|
:progress="d.progress"
|
|
|
|
|
:uploading="{ loaded: d.loaded, total: d.total }"
|
|
|
|
|
:url="d.url"
|
|
|
|
|
icon="mdi-file-image-outline"
|
|
|
|
|
color="hsl(var(--text-mute))"
|
|
|
|
|
clickable
|
|
|
|
|
:closeable="!readonly"
|
2024-11-26 15:37:50 +07:00
|
|
|
@click="triggerViewFile(d.url || '')"
|
2024-11-01 17:18:24 +07:00
|
|
|
@close="$emit('close', d.name)"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</section>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
<style scoped>
|
|
|
|
|
.upload-section {
|
|
|
|
|
border: 3px solid var(--border-color);
|
|
|
|
|
border-style: dashed;
|
|
|
|
|
}
|
|
|
|
|
</style>
|