tien_nemo

test1

......@@ -84,9 +84,12 @@
<!-- Dropdown thủ công -->
<select v-if="selectBox.showDropdown"
:style="{ left: selectBox.x + 'px', top: (selectBox.y + selectBox.height) + 'px' }"
class="manual-select"
:style="{ left: selectBox.x + 'px', top: (selectBox.y + selectBox.height) + 'px', zIndex: 10000, position: 'absolute' }"
v-model="manualField"
@change="applyManualMapping"
@mousedown.stop
@mouseup.stop
@click.stop
>
<option disabled value="">-- Chọn trường dữ liệu --</option>
......@@ -127,7 +130,8 @@
hasCustomerNameXY: false,
ocrData: [],
selectBox: { show: false, showDropdown: false, x: 0, y: 0, width: 0, height: 0, startX: 0, startY: 0 },
manualIndex: null
manualIndex: null,
suppressNextDocumentClick: false
}
},
created() {
......@@ -138,14 +142,35 @@
},
mounted() {
this.loadOCRData();
//Thêm event listener để xóa focus khi click ra ngoài
// Thêm event listener để xử lý click ra ngoài
document.addEventListener('click', (e) => {
if (
!e.target.closest('.right-panel') &&
!e.target.closest('.bbox') &&
!e.target.closest('select')
) {
this.removeAllFocus();
// Bỏ qua click ngay sau khi thả chuột tạo box
if (this.suppressNextDocumentClick) {
this.suppressNextDocumentClick = false;
return;
}
// Nếu đang có box thủ công mới quét và chưa chọn field
if (this.manualIndex !== null) {
const currentIdx = this.manualIndex;
const currentBox = this.ocrData[currentIdx];
if (currentBox && currentBox.isManual && !currentBox.field && !currentBox.isDeleted) {
const bboxEl = e.target.closest('.bbox');
const manualSelectEl = e.target.closest('.manual-select');
const clickedInsideCurrentBox = bboxEl && String(bboxEl.getAttribute('data-index')) === String(currentIdx);
const clickedInsideManualSelect = !!manualSelectEl;
if (!clickedInsideCurrentBox && !clickedInsideManualSelect) {
// Click ra ngoài box/ select → xóa box thủ công vừa quét
this.deleteBox(currentIdx);
// Đóng dropdown thủ công nếu còn mở
this.selectBox.show = false;
this.selectBox.showDropdown = false;
this.isMappingManually = false;
this.manualField = "";
this.manualIndex = null;
this.activeIndex = null;
this.selectingIndex = null;
}
}
}
});
},
......@@ -283,6 +308,7 @@
this.manualIndex = null;
}
this.selectingIndex = null;
this.activeIndex = null;
}
},
// Xử lý data sau khi image đã load
......@@ -426,6 +452,9 @@
if (fieldValue && fieldValue.trim()) {
// Nếu có data từ DB, highlight và focus vào box tương ứng
this.highlightField(fieldName);
// Không ẩn nút xóa các box khác để tránh nhầm lẫn
// Chỉ highlight box tương ứng
}
},
// Xóa tất cả focus
......@@ -433,20 +462,28 @@
// Reset active index (chỉ mất màu xanh, không xóa box)
this.activeIndex = null;
this.selectingIndex = null;
// Đảm bảo tất cả box OCR đều hiển thị (chỉ ẩn border khi cần thiết)
this.ocrData.forEach(item => {
// if (!item.isManual && item.hideBorder) {
// item.hideBorder = true;
// }
if (item.isManual) {
if (!item.showDelete) {
item.isDeleted = true;
} else {
item.hideBorder = false;
}
// Hiển thị lại border cho manual box
// Không ẩn nút xóa các box để tránh nhầm lẫn
// Chỉ reset focus
},
// Xóa box quét chọn chưa hoàn thành
removeIncompleteBoxes() {
// Xóa box quét chọn chưa hoàn thành (chưa có field)
this.ocrData = this.ocrData.filter(item => {
if (item.isManual && !item.field && item.showDelete) {
// Chỉ xóa box manual chưa có field
return false;
}
return true;
});
// Reset trạng thái quét chọn
this.selectBox.show = false;
this.selectBox.showDropdown = false;
this.isMappingManually = false;
this.manualField = "";
this.manualIndex = null;
},
// Xử lý khi click vào box
onBoxClick(index) {
......@@ -459,11 +496,21 @@
const isDataOverridden = item.field && isFromDB &&
this.formData[item.field] !== this.dataMapping[item.field].text;
// Set active index và hiển thị nút xóa cho box được click
this.activeIndex = index;
// Hiển thị nút xóa cho box được click (nếu là manual box)
if (item.isManual) {
item.showDelete = true;
}
// Không ẩn nút xóa các box khác để tránh nhầm lẫn
// Chỉ hiển thị nút xóa cho box được click
if (item.isManual) {
// Manual box
if (isFromDB && !isDataOverridden) {
// Manual box từ DB chưa ghi đè, KHÔNG cho chọn option
this.activeIndex = index;
this.selectingIndex = null;
} else {
// Manual box từ DB có data ghi đè HOẶC manual box bình thường, CHO PHÉP chọn option
......@@ -473,7 +520,6 @@
// Box OCR có field
if (isFromDB && !isDataOverridden) {
// Box có field từ DB chưa ghi đè, KHÔNG cho chọn option
this.activeIndex = index;
this.selectingIndex = null;
} else {
// Box có field từ DB đã ghi đè HOẶC field mới, CHO PHÉP chọn option
......@@ -485,7 +531,9 @@
}
},
startSelect(e) {
if (this.isMappingManually || e.button !== 0) return;
if (e.button !== 0) return; // Chỉ cho phép left click
// Bỏ qua nếu click trên dropdown thủ công
if (e.target.closest && e.target.closest('.manual-select')) return;
this.isSelecting = true;
const rect = this.$refs.pdfContainer.getBoundingClientRect();
this.selectBox.startX = e.clientX - rect.left;
......@@ -550,7 +598,7 @@
bbox: origBbox,
field: "",
isManual: true,
showDelete: true,
showDelete: true, // Hiển thị nút xóa ngay khi quét chọn
isDeleted: false,
hideBorder: false
});
......@@ -559,8 +607,15 @@
this.isMappingManually = true;
this.selectBox.showDropdown = true;
e.stopPropagation();
e.preventDefault();
// Set active index cho box mới tạo
this.activeIndex = this.ocrData.length - 1;
// Sau khi thả chuột, bỏ qua click document kế tiếp
this.suppressNextDocumentClick = true;
// Không stopPropagation để event có thể lan truyền bình thường
// e.stopPropagation();
// e.preventDefault();
},
applyMapping() {
......@@ -649,6 +704,7 @@
const finalText = combinedText.join(" ");
this.ocrData[manualIndex].field = this.manualField;
// this.ocrData[manualIndex].showDelete = true; // Hiển thị nút xóa sau khi hoàn thành mapping
console.log('123',this.ocrData[manualIndex])
this.formData[this.manualField] = finalText.trim();
......@@ -670,6 +726,9 @@
this.manualField = "";
this.manualIndex = null;
// Giữ nguyên nút xóa cho box vừa hoàn thành
// Không ẩn nút xóa các box khác để tránh nhầm lẫn
},
isBoxInside(inner, outer) {
// inner: bbox của OCR item [x1, y1, x2, y2]
......