improve person inport excell

This commit is contained in:
Hesabix 2025-08-16 13:58:19 +00:00
parent 33cf15dedc
commit 789618927d

View file

@ -1,109 +1,343 @@
<script lang="ts">
import axios from 'axios';
import Swal from 'sweetalert2';
import { defineComponent } from 'vue'
<script setup lang="ts">
import { ref } from 'vue'
export default defineComponent({
name: "person-import-excel",
props: {
windowsState: Object
},
data: () => {
return {
loading: ref(false),
file: null
}
},
methods: {
addFile(e) {
this.file = e.target.files[0];
},
submit() {
if (this.file === null) {
Swal.fire({
text: 'فایل انتخاب نشده است',
icon: 'error',
confirmButtonText: 'قبول'
});
}
else {
//send excel file to server
let formData = new FormData();
formData.append('file', this.file);
axios.post('/api/person/import/excel', formData,
{
headers: {
'Content-Type': 'multipart/form-data'
}
}).then(() => {
Swal.fire({
text: 'فایل با موفقیت ثبت شد.',
icon: 'success',
confirmButtonText: 'قبول'
}).then((resp) => {
this.$refs.Close.click();
this.$props.windowsState.submited = true;
});
})
.catch(() => {
Swal.fire({
text: 'متاسفانه خطایی به وجود آمد.',
icon: 'error',
confirmButtonText: 'قبول'
});
});
}
import axios from 'axios'
import Swal from 'sweetalert2'
interface Props {
windowsState: {
submited: boolean
}
}
const props = defineProps<Props>()
const loading = ref(false)
const file = ref<File | null>(null)
const fileInput = ref<HTMLInputElement | null>(null)
const dialog = ref(false)
const dragOver = ref(false)
const addFile = (event: Event) => {
const target = event.target as HTMLInputElement
if (target.files && target.files.length > 0) {
file.value = target.files[0]
}
}
const handleDrop = (event: DragEvent) => {
event.preventDefault()
dragOver.value = false
const dataTransfer = event.dataTransfer
if (dataTransfer?.files && dataTransfer.files.length > 0) {
const droppedFile = dataTransfer.files[0]
if (droppedFile.type.includes('excel') || droppedFile.type.includes('spreadsheet') ||
droppedFile.name.endsWith('.xlsx') || droppedFile.name.endsWith('.xls')) {
file.value = droppedFile
} else {
Swal.fire({
text: 'فقط فایل‌های Excel قابل قبول هستند',
icon: 'warning',
confirmButtonText: 'قبول'
})
}
}
})
}
const handleDragOver = (event: DragEvent) => {
event.preventDefault()
dragOver.value = true
}
const handleDragLeave = (event: DragEvent) => {
event.preventDefault()
dragOver.value = false
}
const downloadTemplate = () => {
const apiUrl = window.location.origin
const link = document.createElement('a')
link.href = `${apiUrl}/imports/persons-import.xlsx`
link.download = 'persons-import-template.xlsx'
link.target = '_blank'
if (document.body) {
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
}
}
const submit = async () => {
if (!file.value) {
await Swal.fire({
text: 'فایل انتخاب نشده است',
icon: 'warning',
confirmButtonText: 'قبول'
})
return
}
// Validate file type
const validTypes = [
'application/vnd.ms-excel',
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
'application/vnd.ms-excel.sheet.macroEnabled.12'
]
if (!validTypes.includes(file.value.type) &&
!file.value.name.endsWith('.xlsx') &&
!file.value.name.endsWith('.xls')) {
await Swal.fire({
text: 'فقط فایل‌های Excel قابل قبول هستند',
icon: 'error',
confirmButtonText: 'قبول'
})
return
}
loading.value = true
const formData = new FormData()
formData.append('file', file.value)
try {
await axios.post('/api/person/import/excel', formData, {
headers: {
'Content-Type': 'multipart/form-data'
}
})
const result = await Swal.fire({
text: 'فایل با موفقیت وارد شد و اطلاعات اشخاص ثبت گردید.',
icon: 'success',
confirmButtonText: 'قبول'
})
if (result.isConfirmed) {
props.windowsState.submited = true
dialog.value = false
file.value = null
if (fileInput.value) fileInput.value.value = ''
}
} catch (error: any) {
console.error('Import error:', error)
const errorMessage = error.response?.data?.message || 'متاسفانه خطایی در وارد کردن فایل به وجود آمد.'
await Swal.fire({
text: errorMessage,
icon: 'error',
confirmButtonText: 'قبول'
})
} finally {
loading.value = false
}
}
const closeDialog = () => {
if (!loading.value) {
dialog.value = false
file.value = null
if (fileInput.value) fileInput.value.value = ''
}
}
</script>
<template>
<!-- Button trigger modal -->
<v-tooltip :text="$t('dialog.import_excel')" location="bottom">
<template v-slot:activator="{ props }">
<v-btn v-bind="props" icon="mdi-table-arrow-left" color="primary" data-bs-toggle="modal"
data-bs-target="#importexcel">
</v-btn>
</template>
</v-tooltip>
<div>
<!-- Import Button -->
<v-tooltip :text="$t('dialog.import_excel')" location="bottom">
<template v-slot:activator="{ props }">
<v-btn
v-bind="props"
icon="mdi-table-arrow-left"
color="primary"
@click="dialog = true"
/>
</template>
</v-tooltip>
<!-- Modal -->
<div class="modal modal-lg fade" id="importexcel" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1"
aria-labelledby="importexcelLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header bg-primary-light text-white">
<h1 class="modal-title fs-5" id="importexcelLabel">وارد کردن از اکسل</h1>
<div class="block-options">
<button type="button" class="btn-close text-white" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
</div>
<div class="modal-body">
<ul>
<li>برای وارد کردن لیست افراد در اکسل ابتدا فایل نمونه را دریافت نمایید سپس مطابق الگو اطلاعات را تکمیل کنید
در مرحله بعدی با انتخاب فایل نسبت به ورود از لیست اقدام کنید</li>
<li>
<a :href="this.$filters.getApiUrl() + '/imports/persons-import.xlsx'" target="_blank">دریافت فایل
نمونه</a>
</li>
</ul>
<form @submit.prevent="submit()">
<div class="mb-3">
<label for="formFileSm" class="form-label">انتخاب فایل</label>
<input @change="addFile" class="custom-file-input form-control" id="formFileSm" type="file"
accept="application/vnd.ms-excel,application/vnd.ms-excel.sheet.macroEnabled.12,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet">
</div>
<div class="mb-3">
<button type="submit" class="btn btn-primary">
وارد کردن
</button>
</div>
</form>
</div>
</div>
</div>
<!-- Import Dialog -->
<v-dialog v-model="dialog" max-width="700" persistent>
<v-card>
<!-- Dialog Header -->
<v-toolbar color="primary" title="درون ریزی اشخاص از اکسل">
<v-spacer />
<v-btn
icon="mdi-close"
variant="text"
color="white"
@click="closeDialog"
:disabled="loading"
/>
</v-toolbar>
<v-card-text class="pt-6">
<!-- Instructions Section -->
<v-card variant="outlined" class="mb-6">
<v-card-text>
<v-list density="compact">
<v-list-item prepend-icon="mdi-numeric-1-circle" class="px-0">
<v-list-item-title class="text-body-2">
ابتدا فایل نمونه را دریافت کنید و مطابق الگو اطلاعات را تکمیل نمایید
</v-list-item-title>
</v-list-item>
<v-list-item prepend-icon="mdi-numeric-2-circle" class="px-0">
<v-list-item-title class="text-body-2">
فایل تکمیل شده را انتخاب کرده و روی دکمه "وارد کردن" کلیک کنید
</v-list-item-title>
</v-list-item>
<v-list-item prepend-icon="mdi-numeric-3-circle" class="px-0">
<v-list-item-title class="text-body-2">
سیستم اطلاعات را بررسی کرده و در صورت صحت، اشخاص را ثبت میکند
</v-list-item-title>
</v-list-item>
</v-list>
</v-card-text>
</v-card>
<!-- Template Download Section -->
<v-card variant="outlined" class="mb-6">
<v-card-text>
<div class="d-flex align-center justify-space-between">
<div class="d-flex align-center">
<div>
<h4 class="text-subtitle-1 font-weight-medium">فایل نمونه</h4>
<p class="text-body-2 text-grey-darken-1 mb-0">
فایل نمونه شامل ستونهای مورد نیاز برای وارد کردن اشخاص
</p>
</div>
</div>
<v-btn
color="success"
variant="outlined"
prepend-icon="mdi-download"
@click="downloadTemplate"
:disabled="loading"
>
دریافت فایل نمونه
</v-btn>
</div>
</v-card-text>
</v-card>
<!-- File Upload Section -->
<v-card variant="outlined">
<v-card-title>
<h4 class="text-subtitle-1 font-weight-medium">انتخاب فایل</h4>
</v-card-title>
<v-card-text>
<!-- Drag & Drop Area -->
<div
class="upload-area"
:class="{ 'drag-over': dragOver }"
@drop="handleDrop"
@dragover="handleDragOver"
@dragleave="handleDragLeave"
>
<v-file-input
ref="fileInput"
v-model="file"
label="فایل Excel را انتخاب کنید یا اینجا رها کنید"
accept=".xls,.xlsx,.xlsm"
@change="addFile"
variant="outlined"
prepend-icon="mdi-file-excel"
show-size
counter
:disabled="loading"
hide-details
class="upload-input"
/>
<div v-if="!file" class="upload-placeholder">
<v-icon size="48" color="grey-lighten-1">mdi-cloud-upload</v-icon>
<p class="text-body-2 text-grey-darken-1 mt-2">
فایل Excel را اینجا بکشید و رها کنید یا کلیک کنید
</p>
</div>
</div>
<!-- File Info -->
<div v-if="file" class="mt-4">
<v-alert type="info" variant="tonal" class="mb-0">
<div class="d-flex align-center">
<v-icon class="mr-2">mdi-file-check</v-icon>
<div>
<strong>{{ file.name }}</strong>
<div class="text-caption">
اندازه: {{ (file.size / 1024).toFixed(1) }} KB
</div>
</div>
</div>
</v-alert>
</div>
</v-card-text>
</v-card>
</v-card-text>
<!-- Dialog Actions -->
<v-card-actions class="pa-6 pt-0">
<v-spacer />
<v-btn
color="grey-darken-1"
variant="text"
@click="closeDialog"
:disabled="loading"
>
انصراف
</v-btn>
<v-btn
color="primary"
@click="submit"
:loading="loading"
:disabled="!file || loading"
prepend-icon="mdi-upload"
>
وارد کردن
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</div>
</template>
<style scoped></style>
<style scoped>
.upload-area {
position: relative;
border: 2px dashed #e0e0e0;
border-radius: 8px;
padding: 20px;
text-align: center;
transition: all 0.3s ease;
background-color: #fafafa;
}
.upload-area.drag-over {
border-color: #1976d2;
background-color: #e3f2fd;
}
.upload-input {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
opacity: 0;
cursor: pointer;
}
.upload-placeholder {
pointer-events: none;
}
.v-list-item {
min-height: 40px;
}
.v-list-item-title {
font-size: 0.875rem;
line-height: 1.25;
}
</style>