OcrController.php 7.62 KB
<?php

namespace App\Http\Controllers;

use App\Models\DtTemplate;
use App\Models\MstTemplate;
use Illuminate\Http\Request;

class OcrController extends Controller
{
    public function index()
    {
        return view('ocr.index');
    }


    public function store(Request $request)
    {

//        dd($request->all());
        $request->validate([
            'customer_name_text' => 'required|string',
            'customer_name_xy' => 'required|string',
            'template_name' => 'required|string|unique:mst_template,tpl_name',
        ]);

        try {
            // Lưu vào bảng mst_template
            $mst = MstTemplate::create([
                'tpl_name' => $request->template_name,
                'tpl_text' => $request->customer_name_text,
                'tpl_xy'   => $request->customer_name_xy,
            ]);

            // Lưu các field khác vào dt_template
            foreach ($request->fields as $field => $value) {
                DtTemplate::create([
                    'tpl_id'     => $mst->id,
                    'field_name' => $field,
                    'field_xy'   => is_array($value['coords']) ? implode(',', $value['coords']) : $value['coords'],
                ]);
            }

            return response()->json([
                'success' => true,
                'message' => 'Lưu template thành công',
                'template_id' => $mst->id
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'Lỗi khi lưu template: ' . $e->getMessage()
            ], 500);
        }
    }


    public function getData(Request $request)
    {
        try {
            // Lấy template name từ request hoặc mặc định
            $templateName = $request->get('template_name', '');

            // Giả sử file OCR JSON & ảnh nằm trong storage/app/public/image/
            $jsonPath = public_path("image/data_picking_detail_1754967679.json");
            $imgPath = ("image/data_picking_detail_1754967679.jpg");

            if (!file_exists($jsonPath)) {
                return response()->json(['error' => 'File OCR JSON không tìm thấy'], 404);
            }

            $ocrData = json_decode(file_get_contents($jsonPath), true);
            if (json_last_error() !== JSON_ERROR_NONE) {
                return response()->json(['error' => 'File OCR JSON không hợp lệ'], 400);
            }

            $formData = [];
            $dataMapping = [];

            if ($templateName) {
                $mst = MstTemplate::where('tpl_name', $templateName)->first();

                if ($mst) {
                    // Lấy detail của template
                    $details = DtTemplate::where('tpl_id', $mst->id)->get();

                    foreach ($details as $detail) {
                        $coords = array_map('intval', explode(',', $detail->field_xy));
                        // coords = [x1, y1, x2, y2]

                        // Tìm text OCR nằm trong bbox này (cải thiện để gộp text)
                        $text = $this->findTextInBBox($ocrData, $coords);

                        // field_name => text
                        $formData[$detail->field_name] = $text;

                        $dataMapping[$detail->field_name] = [
                            'text' => $text,
                            'coords' => $coords
                        ];
                    }
                } else {
                    $formData = [
                        'export_date'   => "",
                        'order_code'    => "",
                        'customer'      => "",
                        'address'       => "",
                        'staff'         => "",
                        'customer_name' => ""
                    ];
                }
            }
//            dd($formData, $dataMapping);

            return response()->json([
                'success' => true,
                'ocrData'      => $ocrData,
                'pdfImageUrl'  => $imgPath,
                'formData'     => $formData,
                'dataMapping'  => $dataMapping,
                'fieldOptions' => [
                    [ 'value' => 'template_name',  'label' => 'Tên Mẫu PDF' ],
                    [ 'value' => 'customer_name',  'label' => 'Tên khách hàng' ],
                    [ 'value' => 'export_date',    'label' => 'Ngày xuất' ],
                    [ 'value' => 'order_code',     'label' => 'Mã đơn hàng' ],
                    [ 'value' => 'customer',       'label' => 'Khách hàng' ],
                    [ 'value' => 'address',        'label' => 'Địa chỉ' ],
                    [ 'value' => 'staff',          'label' => 'Nhân viên' ],
                ],
                'template_name' => $templateName
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'error' => 'Lỗi khi load data: ' . $e->getMessage()
            ], 500);
        }
    }

    private function findTextInBBox($ocrData, $coords)
    {
        [$x1, $y1, $x2, $y2] = $coords;
        $foundItems = [];

        foreach ($ocrData as $item) {
            [$ix1, $iy1, $ix2, $iy2] = $item['bbox'];

            // Kiểm tra xem box OCR có nằm trong vùng bbox template không
            if ($ix1 >= $x1 && $iy1 >= $y1 && $ix2 <= $x2 && $iy2 <= $y2) {
                $foundItems[] = [
                    'text' => $item['text'],
                    'bbox' => $item['bbox'],
                    'x' => $ix1,
                    'y' => $iy1
                ];
            }
        }

        if (empty($foundItems)) {
            return '';
        }

        // Sắp xếp các item theo vị trí (từ trái sang phải, từ trên xuống dưới)
        usort($foundItems, function($a, $b) {
            // Ưu tiên theo Y trước (hàng), sau đó theo X (cột)
            if (abs($a['y'] - $b['y']) < 20) { // Cùng hàng (toler$foundItems = {array[2]} ance 20px)
                return $a['x'] - $b['x']; // Sắp xếp theo X
            }
            return $a['y'] - $b['y']; // Sắp xếp theo Y
        });

        // Gộp text theo thứ tự đã sắp xếp
        $combinedText = [];
        foreach ($foundItems as $item) {
            $combinedText[] = trim($item['text']);
        }

        return implode(' ', $combinedText);
    }

    /**
     * Lấy danh sách template
     */
    public function getTemplateList()
    {
        try {
            $templates = MstTemplate::select('id', 'tpl_name', 'tpl_text', 'in_date')
                ->orderBy('created_at', 'desc')
                ->get();

            return response()->json([
                'success' => true,
                'templates' => $templates
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'error' => 'Lỗi khi lấy danh sách template: ' . $e->getMessage()
            ], 500);
        }
    }

    /**
     * Xóa template
     */
    public function deleteTemplate($id)
    {
        try {
            $template = MstTemplate::findOrFail($id);

            // Xóa các field detail trước
            DtTemplate::where('tpl_id', $id)->delete();

            // Xóa template chính
            $template->delete();

            return response()->json([
                'success' => true,
                'message' => 'Xóa template thành công'
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'error' => 'Lỗi khi xóa template: ' . $e->getMessage()
            ], 500);
        }
    }
}