瀏覽代碼

added upload and remove photos

Alexander Musikhin 7 月之前
父節點
當前提交
6215487a41

+ 24 - 0
app/Http/Controllers/OrderController.php

@@ -5,6 +5,7 @@ namespace App\Http\Controllers;
 use App\Http\Requests\Order\StoreOrderRequest;
 use App\Models\Dictionary\Area;
 use App\Models\Dictionary\District;
+use App\Models\File;
 use App\Models\MafOrder;
 use App\Models\ObjectType;
 use App\Models\Order;
@@ -12,8 +13,10 @@ use App\Models\OrderStatus;
 use App\Models\ProductSKU;
 use App\Models\Role;
 use App\Models\User;
+use App\Services\FileService;
 use Illuminate\Http\RedirectResponse;
 use Illuminate\Http\Request;
+use Illuminate\Support\Facades\Storage;
 
 class OrderController extends Controller
 {
@@ -245,4 +248,25 @@ class OrderController extends Controller
         return $ret;
     }
 
+    public function uploadPhoto(Request $request, Order $order, FileService $fileService)
+    {
+        $data = $request->validate([
+            'photo.*' => 'mimes:jpeg,jpg,png|max:8192',
+        ]);
+        $f = [];
+        foreach ($data['photo'] as $photo) {
+            $f[] = $fileService->saveUploadedFile( $order->id . '/photo', $photo);
+        }
+        $order->photos()->syncWithoutDetaching($f);
+
+        return redirect()->route('order.show', $order);
+    }
+
+    public function deletePhoto(Order $order, File $file, FileService $fileService)
+    {
+        $order->photos()->detach($file);
+        Storage::disk('public')->delete($file->path);
+        return redirect()->route('order.show', $order);
+    }
+
 }

+ 1 - 0
app/Models/File.php

@@ -12,6 +12,7 @@ class File extends Model
         'original_name',
         'mime_type',
         'path',
+        'link',
     ];
 
     public function user(): BelongsTo

+ 1 - 1
app/Models/Order.php

@@ -135,7 +135,7 @@ class Order extends Model
 
     public function photos(): BelongsToMany
     {
-        return $this->belongsToMany(File::class, 'order_file', 'order_id', 'file_id');
+        return $this->belongsToMany(File::class, 'order_file');
     }
 
     public function documents(): BelongsToMany

+ 26 - 0
app/Services/FileService.php

@@ -0,0 +1,26 @@
+<?php
+
+namespace App\Services;
+
+use App\Models\File;
+use Illuminate\Support\Facades\Storage;
+
+class FileService
+{
+    /**
+     * @param $path
+     * @param $file
+     * @return File
+     */
+    public function saveUploadedFile($path, $file): File
+    {
+        Storage::disk('public')->put($path . '/' .$file->getClientOriginalName(), $file->getContent());
+        return File::query()->updateOrCreate([
+            'link' => url('/storage/') . '/' . $path . '/' .$file->getClientOriginalName(),
+            'path' => $path . '/' .$file->getClientOriginalName(),
+            'user_id' => auth()->user()->id,
+            'original_name' => $file->getClientOriginalName(),
+            'mime_type' => $file->getClientMimeType(),
+        ]);
+    }
+}

+ 1 - 0
database/migrations/2025_04_25_194007_create_files_table.php

@@ -17,6 +17,7 @@ return new class extends Migration
             $table->string('original_name');
             $table->string('mime_type');
             $table->string('path');
+            $table->string('link');
             $table->timestamps();
         });
     }

+ 13 - 2
package-lock.json

@@ -6,6 +6,7 @@
         "": {
             "dependencies": {
                 "bootstrap-icons": "^1.11.3",
+                "bs5-lightbox": "^1.8.5",
                 "jquery": "^3.7.1"
             },
             "devDependencies": {
@@ -488,7 +489,6 @@
             "version": "2.11.8",
             "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz",
             "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==",
-            "dev": true,
             "license": "MIT",
             "funding": {
                 "type": "opencollective",
@@ -905,7 +905,6 @@
             "version": "5.3.3",
             "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.3.tgz",
             "integrity": "sha512-8HLCdWgyoMguSO9o+aH+iuZ+aht+mzW0u3HIMzVu7Srrpv7EBBxTnrFlSCskwdY1+EOFQSm7uMJhNQHkdPcmjg==",
-            "dev": true,
             "funding": [
                 {
                     "type": "github",
@@ -993,6 +992,18 @@
                 "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
             }
         },
+        "node_modules/bs5-lightbox": {
+            "version": "1.8.5",
+            "resolved": "https://registry.npmjs.org/bs5-lightbox/-/bs5-lightbox-1.8.5.tgz",
+            "integrity": "sha512-GBVQgpzjVdLnkD8956bXHhX76IDtIYO9qUJH4Pl0JSyI3nuJvLbe3vmgBEmXloCgXzbfEqKqBM+OpVC7/DGA9Q==",
+            "license": "MIT",
+            "funding": {
+                "url": "https://github.com/sponsors/trvswgnr"
+            },
+            "peerDependencies": {
+                "bootstrap": "^5.0.0"
+            }
+        },
         "node_modules/camelcase-css": {
             "version": "2.0.1",
             "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz",

+ 1 - 0
package.json

@@ -19,6 +19,7 @@
     },
     "dependencies": {
         "bootstrap-icons": "^1.11.3",
+        "bs5-lightbox": "^1.8.5",
         "jquery": "^3.7.1"
     },
     "optionalDependencies": {

+ 3 - 0
resources/js/bootstrap.js

@@ -16,3 +16,6 @@ window.$ = $;
 
 import * as bootstrap from 'bootstrap'
 window.bootstrap = bootstrap;
+
+import Lightbox from 'bs5-lightbox';
+window.lightbox = Lightbox;

+ 5 - 0
resources/sass/app.scss

@@ -68,3 +68,8 @@
   background-color: yellow;
 }
 
+.rm-but {
+  position: fixed;
+  margin-left: -18px;
+  margin-top: 1px;
+}

+ 25 - 5
resources/views/orders/show.blade.php

@@ -37,14 +37,34 @@
                 <div>Менеджер: {{ $order->user->name }}, тел. {{ $order->user->phone }}</div>
                 <div>Название группы в ТГ: {{ $order->tg_group_name }}</div>
                 <div>Ссылка на группу в ТГ: {{ $order->tg_group_link }}</div>
+                <hr>
                 <div class="photo">
-                    Фотографии
-                    <form action="" enctype="multipart/form-data" method="post">
+                    Фотографии <button class="btn btn-sm text-success" onclick="$('#upl-photo').trigger('click');"><i class="bi bi-plus-circle-fill"></i> Загрузить</button>
+                    <form action="{{ route('order.upload-photo', $order) }}" enctype="multipart/form-data" method="post" class="visually-hidden">
                         @csrf
-                        <input type="file" multiple name="photo[]" class="form-control form-control-sm" accept="jpg,jpeg,png">
-                        <button type="submit" class="btn btn-sm btn-primary">Загрузить</button>
+                        <input required type="file" id="upl-photo" onchange="$(this).parent().submit()" multiple name="photo[]" class="form-control form-control-sm" accept=".jpg,.jpeg,.png">
                     </form>
-                    @dump($order->photo)
+                    <div class="row my-2 g-1">
+                        @foreach($order->photos as $photo)
+                            <div class="col-4">
+                                <a href="{{ $photo->link }}"
+                                   data-toggle="lightbox" data-gallery="photos" data-size="fullscreen">
+                                    <img class="img-thumbnail" src="{{ $photo->link }}" alt="">
+                                </a>
+                                @if(hasRole('admin'))
+                                    <i class="bi bi-x-circle-fill fs-6 text-danger cursor-pointer rm-but"
+                                       onclick="if(confirm('Удалить фото?')) $('#photo-{{ $photo->id }}').submit()"
+                                       title="Удалить"></i>
+                                @endif
+                                <form action="{{ route('order.delete-photo', [$order, $photo]) }}" method="POST" id="photo-{{ $photo->id }}" class="visually-hidden">
+                                    @csrf
+                                    @method('DELETE')
+                                </form>
+                            </div>
+                        @endforeach
+
+                    </div>
+
                 </div>
 
             </div>

+ 3 - 1
routes/web.php

@@ -86,7 +86,9 @@ Route::middleware('auth:web')->group(function () {
     Route::get('order/revert-maf/{order}', [OrderController::class, 'revertMaf'])->name('order.revert-maf');
     Route::post('order/move-maf', [OrderController::class, 'moveMaf'])->name('order.move-maf');
 
-
+    Route::post('order/{order}/upload-photo', [OrderController::class, 'uploadPhoto'])->name('order.upload-photo');
+    // admin?
+    Route::delete('order/delete-photo/{order}/{file}', [OrderController::class, 'deletePhoto'])->name('order.delete-photo');
 
     // Склад (МАФ)
     Route::get('product_sku', [ProductSKUController::class, 'index'])->name('product_sku.index');