سلام وقت این کد های منه ولی خطا دارم
بخش vue.js
<template>
<div>
<!-- Drop Zone -->
<div
id="dropZone"
class="w-60 h-44 bg-picUploadBG border rounded-lg flex flex-col justify-center items-center p-4 text-SMLink cursor-pointer"
@drop.prevent="handleDrop"
@dragover.prevent
@click="triggerFileInput"
>
<span class="text-center">
برای آپلود، تصویر را اینجا بکشید یا کلیک کنید
</span>
</div>
<input
ref="fileInput"
type="file"
multiple
accept="image/*"
@change="handleFileChange"
class="hidden"
/>
<!-- Preview Section -->
<div class="grid grid-cols-4 max-sm:grid-cols-1 gap-4 mt-6">
<div
v-for="(image, index) in images"
:key="image.tempId"
class="relative group rounded-lg overflow-hidden border"
>
<!-- Preview Image -->
<img
v-if="image.previewUrl"
:src="image.previewUrl"
class="w-full h-40 object-cover"
/>
<!-- Loading Indicator -->
<div
v-if="image.uploading"
class="absolute inset-0 bg-black bg-opacity-50 flex items-center justify-center text-white"
>
در حال بارگذاری...
</div>
<!-- Progress Bar -->
<div
v-if="image.uploading"
class="absolute bottom-0 left-0 w-full"
>
<div
class="h-1 bg-blue-600"
:style="{ width: image.uploadProgress + '%' }"
></div>
</div>
<!-- Delete Button -->
<div
@click="removeImage(index, image.url)"
class="absolute top-2 right-2 bg-red-500 text-white p-1 rounded-full cursor-pointer opacity-0 group-hover:opacity-100"
>
<span class="text-xl">X</span>
</div>
<!-- Set Main Image -->
<span
v-if="!image.isMain && !image.uploading"
@click="setMainImage(index)"
class="absolute bottom-2 left-2 bg-blue-600 text-white p-1 rounded-full cursor-pointer opacity-0 group-hover:opacity-100"
>
تصویر اصلی
</span>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
images: [], // فهرست تصاویر آپلود شده
};
},
methods: {
// فعال کردن فایل input
triggerFileInput() {
this.$refs.fileInput.click();
},
// مدیریت تغییرات فایل
handleFileChange(event) {
this.addToUploadQueue(event.target.files);
},
// مدیریت دراگ و دراپ فایلها
handleDrop(event) {
this.addToUploadQueue(event.dataTransfer.files);
},
// افزودن تصاویر به صف آپلود
addToUploadQueue(files) {
Array.from(files).forEach((file) => {
const previewUrl = URL.createObjectURL(file);
const image = {
file,
previewUrl,
uploading: true,
uploadProgress: 0,
isMain: false,
url: null,
tempId: Math.random().toString(36).substring(2, 15), // شناسه منحصر به فرد
};
this.images.push(image);
this.uploadImage(image);
});
},
// آپلود تصویر به سرور
async uploadImage(image) {
const formData = new FormData();
formData.append("AdPhote[]", image.file);
formData.append("tempId", image.tempId); // شناسه منحصر به فرد
formData.append("isMain", image.isMain); // آیا تصویر اصلی است؟
try {
const response = await axios.post(
"/Ads/upload-images",
formData,
{
headers: { "Content-Type": "multipart/form-data" },
onUploadProgress: (progressEvent) => {
if (progressEvent.lengthComputable) {
image.uploadProgress = Math.round(
(progressEvent.loaded * 100) /
progressEvent.total
);
}
},
}
);
console.log("Server Response:", response.data);
if (response.data.success && response.data.images.length > 0) {
response.data.images.forEach((uploadedImage) => {
const matchingImage = this.images.find(
(img) => img.tempId === uploadedImage.tempId
);
if (matchingImage) {
matchingImage.uploading = false;
matchingImage.url = uploadedImage.url;
matchingImage.previewUrl = uploadedImage.url;
matchingImage.serverId = uploadedImage.serverId;
}
});
} else {
console.error("Unexpected response format:", response.data);
throw new Error("Invalid server response");
}
} catch (error) {
console.error(
"Error uploading image:",
error.response || error.message
);
this.removeImage(this.images.indexOf(image)); // حذف تصویر در صورت خطا
}
},
// حذف تصویر از صف آپلود
removeImage(index, imageUrl = null) {
console.log("Deleting image with URL:", imageUrl);
if (imageUrl) {
axios
.delete("/Ads/delete-image", { data: { imageUrl } })
.then((response) => {
if (response.data.success) {
console.log(
"Image successfully deleted from server."
);
} else {
console.error("Image deletion failed on server.");
}
})
.catch((error) => {
console.error("Error deleting image:", error);
});
}
this.images.splice(index, 1); // حذف تصویر از آرایه
},
// تنظیم تصویر اصلی
setMainImage(index) {
this.images.forEach((image, i) => {
image.isMain = i === index;
});
},
},
};
</script>
بخش کنترل
public function uploadImages(Request $request)
{
// بررسی وجود فایل در درخواست
if (!$request->hasFile('AdPhote')) {
Log::error('No files uploaded');
return response()->json(['success' => false, 'message' => 'No files uploaded']);
}
// دریافت فایلها از درخواست
$files = $request->file('AdPhote');
// بررسی اینکه فایلها در فرمت آرایه باشند
if (!is_array($files)) {
Log::error('Files are not in an array format');
return response()->json(['success' => false, 'message' => 'Invalid file format']);
}
// محدودیت تعداد فایلها
if (count($files) > 10) { // فرضاً محدودیت 10 فایل
return response()->json(['success' => false, 'message' => 'Too many files']);
}
// محدودیت حجم فایلها
$maxFileSize = 1024 * 1024 * 10; // 10MB
foreach ($files as $file) {
if ($file->getSize() > $maxFileSize) {
return response()->json(['success' => false, 'message' => 'File size exceeds the maximum limit']);
}
}
// فرمتهای مجاز فایلها
$allowedExtensions = ['jpg', 'jpeg', 'png', 'gif'];
foreach ($files as $file) {
if (!in_array($file->getClientOriginalExtension(), $allowedExtensions)) {
return response()->json(['success' => false, 'message' => 'Invalid file format']);
}
}
// دریافت دادههای اضافی از درخواست
$tempIds = $request->input('tempIds', []);
$isMains = $request->input('isMains', []);
// آرایه برای ذخیره اطلاعات فایلهای آپلود شده
$uploadedImages = [];
// حلقه برای آپلود فایلها
foreach ($files as $index => $file) {
try {
// مسیر ذخیرهسازی فایل
$path = 'Image/Ad/' . date('Y') . '/' . date('m') . '/' . date('d');
$fileName = "Z-ad-" . date('Ymd') . "-" . Str::random(10) . "." . $file->getClientOriginalExtension();
// ذخیره فایل موقت در پوشه 'temp'
$tempPath = $file->storeAs('temp', $fileName);
// مسیر فایل در سرور FTP
$ftpPath = $path . '/' . $fileName;
// آپلود فایل به سرور FTP
if (!Storage::disk('ftp')->put($ftpPath, Storage::get($tempPath))) {
throw new \Exception('FTP upload failed');
}
// حذف فایل موقت از سرور
Storage::delete($tempPath);
// گرفتن دادههای اضافی
$tempId = $tempIds[$index] ?? null;
$isMain = filter_var($isMains[$index] ?? false, FILTER_VALIDATE_BOOLEAN);
// ذخیره اطلاعات فایل در آرایه
$uploadedImages[] = [
'path' => $ftpPath,
'fileName' => $fileName,
'url' => 'https://img.zoomila.com/' . $ftpPath,
'format' => $file->getClientOriginalExtension(),
'tempId' => $tempId,
'isMain' => $isMain,
];
} catch (\Exception $e) {
// در صورت بروز خطا، لاگ کرده و پیام خطا ارسال میشود
Log::error('Error uploading file: ' . $e->getMessage());
return response()->json(['success' => false, 'message' => $e->getMessage()]);
}
}
// بازگشت اطلاعات فایلهای آپلود شده
return response()->json(['success' => true, 'images' => $uploadedImages]);
}
public function store(Request $request)
{
// اعتبارسنجی دادههای فرم
$validatedData = $request->validate([
'title' => 'required|string|max:255',
'description' => 'required|string',
'price' => 'required|numeric',
'images' => 'array',
'images.*' => 'image|max:2048', // محدودیت تصویر
]);
DB::beginTransaction();
try {
// ذخیره اطلاعات اصلی آگهی
$ad = Ad::create([
'title' => $validatedData['title'],
'description' => $validatedData['description'],
'price' => $validatedData['price'],
]);
// آپلود و ذخیره تصاویر
$uploadedImages = $this->uploadImages($request);
$this->saveImageData($uploadedImages, $ad->id);
DB::commit();
return response()->json([
'success' => true,
'message' => 'آگهی و تصاویر با موفقیت ذخیره شدند.',
'ad' => $ad,
]);
} catch (\Exception $e) {
DB::rollBack();
return response()->json([
'success' => false,
'message' => 'خطایی در ذخیرهسازی رخ داده است.',
'error' => $e->getMessage(),
], 500);
}
}
آیا مایل به ارسال نوتیفیکیشن و اخبار از طرف راکت هستید ؟