Showing
1 changed file
with
170 additions
and
70 deletions
| ... | @@ -20,103 +20,203 @@ class OcrController extends Controller | ... | @@ -20,103 +20,203 @@ class OcrController extends Controller |
| 20 | $request->validate([ | 20 | $request->validate([ |
| 21 | 'customer_name_text' => 'required|string', | 21 | 'customer_name_text' => 'required|string', |
| 22 | 'customer_name_xy' => 'required|string', | 22 | 'customer_name_xy' => 'required|string', |
| 23 | - 'template_name' => 'unique:mst_template,tpl_name', | 23 | + 'template_name' => 'required|string|unique:mst_template,tpl_name', |
| 24 | + 'fields' => 'required|array', | ||
| 25 | + 'fields.*.name' => 'required|string', | ||
| 26 | + 'fields.*.xy' => 'required|string', | ||
| 24 | ]); | 27 | ]); |
| 25 | 28 | ||
| 26 | - // Lưu vào bảng mst_template | 29 | + try { |
| 27 | - $mst = MstTemplate::create([ | 30 | + // Lưu vào bảng mst_template |
| 28 | - 'tpl_name' => $request->template_name, | 31 | + $mst = MstTemplate::create([ |
| 29 | - 'tpl_text' => $request->customer_name_text, | 32 | + 'tpl_name' => $request->template_name, |
| 30 | - 'tpl_xy' => $request->customer_name_xy, | 33 | + 'tpl_text' => $request->customer_name_text, |
| 31 | - ]); | 34 | + 'tpl_xy' => $request->customer_name_xy, |
| 35 | + ]); | ||
| 32 | 36 | ||
| 33 | - // Lưu các field khác vào dt_template | 37 | + // Lưu các field khác vào dt_template |
| 34 | - foreach ($request->fields as $field) { | 38 | + foreach ($request->fields as $field) { |
| 35 | - DtTemplate::create([ | 39 | + DtTemplate::create([ |
| 36 | - 'tpl_id' => $mst->id, | 40 | + 'tpl_id' => $mst->id, |
| 37 | - 'field_name' => $field['name'], | 41 | + 'field_name' => $field['name'], |
| 38 | - 'field_xy' => $field['xy'], | 42 | + 'field_xy' => $field['xy'], |
| 43 | + ]); | ||
| 44 | + } | ||
| 45 | + | ||
| 46 | + return response()->json([ | ||
| 47 | + 'success' => true, | ||
| 48 | + 'message' => 'Lưu template thành công', | ||
| 49 | + 'template_id' => $mst->id | ||
| 39 | ]); | 50 | ]); |
| 51 | + } catch (\Exception $e) { | ||
| 52 | + return response()->json([ | ||
| 53 | + 'success' => false, | ||
| 54 | + 'message' => 'Lỗi khi lưu template: ' . $e->getMessage() | ||
| 55 | + ], 500); | ||
| 40 | } | 56 | } |
| 41 | - | ||
| 42 | - return response()->json(['success' => true, 'message' => 'Lưu template thành công']); | ||
| 43 | } | 57 | } |
| 44 | 58 | ||
| 45 | 59 | ||
| 46 | - public function getData() | 60 | + public function getData(Request $request) |
| 47 | { | 61 | { |
| 48 | - // Giả sử file OCR JSON & ảnh nằm trong storage/app/public/image/ | 62 | + try { |
| 49 | - $jsonPath = public_path("image/data_picking_detail_1754967679.json"); | 63 | + // Lấy template name từ request hoặc mặc định |
| 50 | - $imgPath = ("image/data_picking_detail_1754967679.jpg"); | 64 | + $templateName = $request->get('template_name', 'nemo'); |
| 51 | - | ||
| 52 | - | ||
| 53 | - $templateName = 'nemo'; | ||
| 54 | - /// Lấy từ request hoặc mặc định | ||
| 55 | - | ||
| 56 | - | ||
| 57 | - if (!file_exists($jsonPath)) { | ||
| 58 | - return response()->json(['error' => 'File not found'], 404); | ||
| 59 | - } | ||
| 60 | 65 | ||
| 61 | - $ocrData = json_decode(file_get_contents($jsonPath), true); | 66 | + // Giả sử file OCR JSON & ảnh nằm trong storage/app/public/image/ |
| 62 | - $formData = []; | 67 | + $jsonPath = public_path("image/data_picking_detail_1754967679.json"); |
| 68 | + $imgPath = ("image/data_picking_detail_1754967679.jpg"); | ||
| 63 | 69 | ||
| 64 | - if ($templateName) { | 70 | + if (!file_exists($jsonPath)) { |
| 65 | - $mst = MstTemplate::where('tpl_name', $templateName)->first(); | 71 | + return response()->json(['error' => 'File OCR JSON không tìm thấy'], 404); |
| 66 | - | 72 | + } |
| 67 | - if ($mst) { | ||
| 68 | - // Lấy detail của template | ||
| 69 | - $details = DtTemplate::where('tpl_id', $mst->id)->get(); | ||
| 70 | - | ||
| 71 | - foreach ($details as $detail) { | ||
| 72 | - $coords = array_map('intval', explode(',', $detail->field_xy)); | ||
| 73 | - // coords = [x1, y1, x2, y2] | ||
| 74 | 73 | ||
| 75 | - // Tìm text OCR nằm trong bbox này | 74 | + $ocrData = json_decode(file_get_contents($jsonPath), true); |
| 76 | - $text = $this->findTextInBBox($ocrData, $coords); | 75 | + if (json_last_error() !== JSON_ERROR_NONE) { |
| 76 | + return response()->json(['error' => 'File OCR JSON không hợp lệ'], 400); | ||
| 77 | + } | ||
| 77 | 78 | ||
| 78 | - // field_name => text | 79 | + $formData = []; |
| 79 | - $formData[$detail->field_name] = $text; | 80 | + |
| 81 | + if ($templateName) { | ||
| 82 | + $mst = MstTemplate::where('tpl_name', $templateName)->first(); | ||
| 83 | + | ||
| 84 | + if ($mst) { | ||
| 85 | + // Lấy detail của template | ||
| 86 | + $details = DtTemplate::where('tpl_id', $mst->id)->get(); | ||
| 87 | + | ||
| 88 | + foreach ($details as $detail) { | ||
| 89 | + $coords = array_map('intval', explode(',', $detail->field_xy)); | ||
| 90 | + // coords = [x1, y1, x2, y2] | ||
| 91 | + | ||
| 92 | + // Tìm text OCR nằm trong bbox này (cải thiện để gộp text) | ||
| 93 | + $text = $this->findTextInBBox($ocrData, $coords); | ||
| 94 | + | ||
| 95 | + // field_name => text | ||
| 96 | + $formData[$detail->field_name] = $text; | ||
| 97 | + } | ||
| 98 | + } else { | ||
| 99 | + $formData = [ | ||
| 100 | + 'export_date' => "", | ||
| 101 | + 'order_code' => "", | ||
| 102 | + 'customer' => "", | ||
| 103 | + 'address' => "", | ||
| 104 | + 'staff' => "", | ||
| 105 | + 'customer_name' => "" | ||
| 106 | + ]; | ||
| 80 | } | 107 | } |
| 81 | - } else{ | ||
| 82 | - $formData = [ | ||
| 83 | - 'export_date' => "", | ||
| 84 | - 'order_code' => "", | ||
| 85 | - 'customer' => "", | ||
| 86 | - 'address' => "", | ||
| 87 | - 'staff' => "", | ||
| 88 | - 'customer_name' => "" | ||
| 89 | - ]; | ||
| 90 | } | 108 | } |
| 109 | + | ||
| 110 | + return response()->json([ | ||
| 111 | + 'success' => true, | ||
| 112 | + 'ocrData' => $ocrData, | ||
| 113 | + 'pdfImageUrl' => $imgPath, | ||
| 114 | + 'formData' => $formData, | ||
| 115 | + 'fieldOptions' => [ | ||
| 116 | + [ 'value' => 'template_name', 'label' => 'Tên Mẫu PDF' ], | ||
| 117 | + [ 'value' => 'customer_name', 'label' => 'Tên khách hàng' ], | ||
| 118 | + [ 'value' => 'export_date', 'label' => 'Ngày xuất' ], | ||
| 119 | + [ 'value' => 'order_code', 'label' => 'Mã đơn hàng' ], | ||
| 120 | + [ 'value' => 'customer', 'label' => 'Khách hàng' ], | ||
| 121 | + [ 'value' => 'address', 'label' => 'Địa chỉ' ], | ||
| 122 | + [ 'value' => 'staff', 'label' => 'Nhân viên' ], | ||
| 123 | + ], | ||
| 124 | + 'template_name' => $templateName | ||
| 125 | + ]); | ||
| 126 | + } catch (\Exception $e) { | ||
| 127 | + return response()->json([ | ||
| 128 | + 'success' => false, | ||
| 129 | + 'error' => 'Lỗi khi load data: ' . $e->getMessage() | ||
| 130 | + ], 500); | ||
| 91 | } | 131 | } |
| 92 | - return response()->json([ | ||
| 93 | - 'ocrData' => $ocrData, | ||
| 94 | - 'pdfImageUrl' => $imgPath, | ||
| 95 | - 'formData' => $formData, | ||
| 96 | - 'fieldOptions' => [ | ||
| 97 | - [ 'value' => 'template_name', 'label' => 'Tên Mẫu PDF' ], | ||
| 98 | - [ 'value' => 'customer_name', 'label' => 'Tên khách hàng' ], | ||
| 99 | - [ 'value' => 'export_date', 'label' => 'Ngày xuất' ], | ||
| 100 | - [ 'value' => 'order_code', 'label' => 'Mã đơn hàng' ], | ||
| 101 | - [ 'value' => 'customer', 'label' => 'Khách hàng' ], | ||
| 102 | - [ 'value' => 'address', 'label' => 'Địa chỉ' ], | ||
| 103 | - [ 'value' => 'staff', 'label' => 'Nhân viên' ], | ||
| 104 | - ] | ||
| 105 | - ]); | ||
| 106 | } | 132 | } |
| 107 | 133 | ||
| 108 | private function findTextInBBox($ocrData, $coords) | 134 | private function findTextInBBox($ocrData, $coords) |
| 109 | { | 135 | { |
| 110 | [$x1, $y1, $x2, $y2] = $coords; | 136 | [$x1, $y1, $x2, $y2] = $coords; |
| 137 | + $foundItems = []; | ||
| 138 | + | ||
| 111 | foreach ($ocrData as $item) { | 139 | foreach ($ocrData as $item) { |
| 112 | [$ix1, $iy1, $ix2, $iy2] = $item['bbox']; | 140 | [$ix1, $iy1, $ix2, $iy2] = $item['bbox']; |
| 113 | - // Kiểm tra nếu bbox OCR nằm trong vùng bbox template | 141 | + |
| 142 | + // Kiểm tra xem box OCR có nằm trong vùng bbox template không | ||
| 114 | if ($ix1 >= $x1 && $iy1 >= $y1 && $ix2 <= $x2 && $iy2 <= $y2) { | 143 | if ($ix1 >= $x1 && $iy1 >= $y1 && $ix2 <= $x2 && $iy2 <= $y2) { |
| 115 | - return $item['text']; | 144 | + $foundItems[] = [ |
| 145 | + 'text' => $item['text'], | ||
| 146 | + 'bbox' => $item['bbox'], | ||
| 147 | + 'x' => $ix1, | ||
| 148 | + 'y' => $iy1 | ||
| 149 | + ]; | ||
| 150 | + } | ||
| 151 | + } | ||
| 152 | + | ||
| 153 | + if (empty($foundItems)) { | ||
| 154 | + return ''; | ||
| 155 | + } | ||
| 156 | + | ||
| 157 | + // Sắp xếp các item theo vị trí (từ trái sang phải, từ trên xuống dưới) | ||
| 158 | + usort($foundItems, function($a, $b) { | ||
| 159 | + // Ưu tiên theo Y trước (hàng), sau đó theo X (cột) | ||
| 160 | + if (abs($a['y'] - $b['y']) < 20) { // Cùng hàng (toler$foundItems = {array[2]} ance 20px) | ||
| 161 | + return $a['x'] - $b['x']; // Sắp xếp theo X | ||
| 116 | } | 162 | } |
| 163 | + return $a['y'] - $b['y']; // Sắp xếp theo Y | ||
| 164 | + }); | ||
| 165 | + | ||
| 166 | + // Gộp text theo thứ tự đã sắp xếp | ||
| 167 | + $combinedText = []; | ||
| 168 | + foreach ($foundItems as $item) { | ||
| 169 | + $combinedText[] = trim($item['text']); | ||
| 117 | } | 170 | } |
| 118 | - return ''; | 171 | + |
| 172 | + return implode(' ', $combinedText); | ||
| 119 | } | 173 | } |
| 120 | 174 | ||
| 175 | + /** | ||
| 176 | + * Lấy danh sách template | ||
| 177 | + */ | ||
| 178 | + public function getTemplateList() | ||
| 179 | + { | ||
| 180 | + try { | ||
| 181 | + $templates = MstTemplate::select('id', 'tpl_name', 'tpl_text', 'in_date') | ||
| 182 | + ->orderBy('created_at', 'desc') | ||
| 183 | + ->get(); | ||
| 184 | + | ||
| 185 | + return response()->json([ | ||
| 186 | + 'success' => true, | ||
| 187 | + 'templates' => $templates | ||
| 188 | + ]); | ||
| 189 | + } catch (\Exception $e) { | ||
| 190 | + return response()->json([ | ||
| 191 | + 'success' => false, | ||
| 192 | + 'error' => 'Lỗi khi lấy danh sách template: ' . $e->getMessage() | ||
| 193 | + ], 500); | ||
| 194 | + } | ||
| 195 | + } | ||
| 196 | + | ||
| 197 | + /** | ||
| 198 | + * Xóa template | ||
| 199 | + */ | ||
| 200 | + public function deleteTemplate($id) | ||
| 201 | + { | ||
| 202 | + try { | ||
| 203 | + $template = MstTemplate::findOrFail($id); | ||
| 204 | + | ||
| 205 | + // Xóa các field detail trước | ||
| 206 | + DtTemplate::where('tpl_id', $id)->delete(); | ||
| 121 | 207 | ||
| 208 | + // Xóa template chính | ||
| 209 | + $template->delete(); | ||
| 210 | + | ||
| 211 | + return response()->json([ | ||
| 212 | + 'success' => true, | ||
| 213 | + 'message' => 'Xóa template thành công' | ||
| 214 | + ]); | ||
| 215 | + } catch (\Exception $e) { | ||
| 216 | + return response()->json([ | ||
| 217 | + 'success' => false, | ||
| 218 | + 'error' => 'Lỗi khi xóa template: ' . $e->getMessage() | ||
| 219 | + ], 500); | ||
| 220 | + } | ||
| 221 | + } | ||
| 122 | } | 222 | } | ... | ... |
-
Please register or sign in to post a comment