Spaces:
Running
Running
Update app.js
Browse files
app.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
| 1 |
-
|
| 2 |
|
| 3 |
const EXPORT_COLUMNS = [
|
| 4 |
"التصنيف","نوع المشكلة","وقت حدوث المشكلة","اسم صاحب المشكلة",
|
|
@@ -7,7 +7,7 @@ const EXPORT_COLUMNS = [
|
|
| 7 |
|
| 8 |
const FIELD_ALIASES = {
|
| 9 |
"نوع المشكلة": ["نوع المشكله","نوع المشكلة","المشكلة"],
|
| 10 |
-
"وقت حدوث المشكلة": ["وقت حدوث المشكله","وقت حدوث المشكلة","وقت المشكلة","وقت حدوث"],
|
| 11 |
"اسم صاحب المشكلة": ["اسم صاحب المشكله","اسم صاحب المشكلة","اسم صاحب البلاغ","الاسم"],
|
| 12 |
"رقم الهوية": ["رقم الهويه","رقم الهوية","الهوية"],
|
| 13 |
"رقم الجهاز": ["رقم الجهاز","الجهاز"],
|
|
@@ -17,6 +17,8 @@ const FIELD_ALIASES = {
|
|
| 17 |
};
|
| 18 |
|
| 19 |
const START_LABELS = Array.from(new Set(Object.values(FIELD_ALIASES).flat()));
|
|
|
|
|
|
|
| 20 |
|
| 21 |
const CLASS_RULES = {
|
| 22 |
"استفسار": ["استفسار","سؤال","استعلام","معلومة","استفسارات"],
|
|
@@ -39,11 +41,6 @@ const CLASS_PRIORITY = [
|
|
| 39 |
"النظام المكتبي","تناقل البيانات","استفسار",
|
| 40 |
];
|
| 41 |
|
| 42 |
-
|
| 43 |
-
const TICKET_SEP = /\n\s*(?:\n|—+|-{3,}|={3,}|🔴+)+\s*\n/;
|
| 44 |
-
|
| 45 |
-
const MIN_SPLIT_SPAN = 40;
|
| 46 |
-
|
| 47 |
const arabicDigitsMap = {"٠":"0","١":"1","٢":"2","٣":"3","٤":"4","٥":"5","٦":"6","٧":"7","٨":"8","٩":"9"};
|
| 48 |
function normalizeText(s){
|
| 49 |
if(typeof s!=="string") return "";
|
|
@@ -135,23 +132,34 @@ function findBlockAfterLabel(text, labels, allLabels = START_LABELS){
|
|
| 135 |
return m ? m[1].trim() : "";
|
| 136 |
}
|
| 137 |
|
|
|
|
| 138 |
function splitTickets(raw){
|
| 139 |
const text = normalizeText(raw);
|
| 140 |
if(!text) return [];
|
| 141 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 142 |
if(TICKET_SEP.test(text)){
|
| 143 |
return text.split(TICKET_SEP).map(p=>p.trim()).filter(Boolean);
|
| 144 |
}
|
| 145 |
|
| 146 |
const startsAll = findStartsByLabels(text, START_LABELS).sort((a,b)=>a-b);
|
| 147 |
const filtered = startsAll.filter((pos,i,arr)=> i===0 || (pos - arr[i-1]) >= MIN_SPLIT_SPAN);
|
| 148 |
-
|
| 149 |
-
|
| 150 |
-
if(useThese.length >= 2){
|
| 151 |
const parts=[];
|
| 152 |
-
for(let i=0;i<
|
| 153 |
-
const s =
|
| 154 |
-
const e = i+1<
|
| 155 |
const slice = text.slice(s,e).trim();
|
| 156 |
if(slice) parts.push(slice);
|
| 157 |
}
|
|
@@ -161,18 +169,6 @@ function splitTickets(raw){
|
|
| 161 |
const blocks = text.split(/\n\s*\n+/).map(p=>p.trim()).filter(Boolean);
|
| 162 |
if(blocks.length > 1) return blocks;
|
| 163 |
|
| 164 |
-
const niu = findStartsByLabels(text, ["نوع المشكلة","نوع المشكله"]).sort((a,b)=>a-b);
|
| 165 |
-
if(niu.length >= 2){
|
| 166 |
-
const parts=[];
|
| 167 |
-
for(let i=0;i<niu.length;i++){
|
| 168 |
-
const s = niu[i];
|
| 169 |
-
const e = i+1<niu.length ? niu[i+1] : text.length;
|
| 170 |
-
const slice = text.slice(s,e).trim();
|
| 171 |
-
if(slice) parts.push(slice);
|
| 172 |
-
}
|
| 173 |
-
if(parts.length) return parts;
|
| 174 |
-
}
|
| 175 |
-
|
| 176 |
return [text];
|
| 177 |
}
|
| 178 |
|
|
@@ -402,8 +398,7 @@ async function exportExcel(){
|
|
| 402 |
});
|
| 403 |
|
| 404 |
const ts = new Date().toISOString().replace(/\D/g,"").slice(0,14);
|
| 405 |
-
const
|
| 406 |
-
const filename = `${base}_${ts}.xlsx`;
|
| 407 |
|
| 408 |
const buffer = await wb.xlsx.writeBuffer();
|
| 409 |
const blob = new Blob([buffer], { type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" });
|
|
@@ -452,10 +447,10 @@ const SAMPLE = `نوع المشكلة : لا استطيع اكمال الاست
|
|
| 452 |
اسم المسح: الخبر 2025
|
| 453 |
اسم المنطقة: الشرقية`;
|
| 454 |
|
| 455 |
-
const STATE_KEY = "
|
| 456 |
const ALL_STATE_KEYS = [
|
| 457 |
"ticketParserState_v8","ticketParserState_v9","ticketParserState_v10",
|
| 458 |
-
"ticketParserState_v10_1","ticketParserState_v10_2","ticketParserState_v10_3"
|
| 459 |
];
|
| 460 |
|
| 461 |
function ensureColumns(rows, agentName, defaultRegion){
|
|
@@ -475,20 +470,18 @@ function ensureColumns(rows, agentName, defaultRegion){
|
|
| 475 |
function saveState(){
|
| 476 |
try{
|
| 477 |
const raw = document.getElementById("raw")?.value || "";
|
| 478 |
-
const fname = document.getElementById("fname")?.value || "Ticket";
|
| 479 |
const agent = document.getElementById("agentName")?.value || "";
|
| 480 |
const region= document.getElementById("regionDefault")?.value || "";
|
| 481 |
const rows = readTable();
|
| 482 |
-
localStorage.setItem(STATE_KEY, JSON.stringify({ raw,
|
| 483 |
}catch{}
|
| 484 |
}
|
| 485 |
function loadState(){
|
| 486 |
try{
|
| 487 |
const s = localStorage.getItem(STATE_KEY);
|
| 488 |
if(!s) return false;
|
| 489 |
-
let { raw,
|
| 490 |
if(typeof raw === "string"){ const el=document.getElementById("raw"); if(el) el.value = raw; }
|
| 491 |
-
if(typeof fname === "string"){ const el=document.getElementById("fname"); if(el) el.value = fname; }
|
| 492 |
if(typeof agent === "string"){ const el=document.getElementById("agentName"); if(el) el.value = agent; }
|
| 493 |
if(typeof region === "string"){ const el=document.getElementById("regionDefault"); if(el) el.value = region; }
|
| 494 |
rows = ensureColumns(rows, agent, region);
|
|
@@ -502,12 +495,10 @@ function loadState(){
|
|
| 502 |
function clearAll(){
|
| 503 |
const rawEl = document.getElementById("raw");
|
| 504 |
const tbody = document.getElementById("tbody");
|
| 505 |
-
const fnameEl = document.getElementById("fname");
|
| 506 |
const agentEl = document.getElementById("agentName");
|
| 507 |
const regionEl= document.getElementById("regionDefault");
|
| 508 |
if(rawEl) rawEl.value = "";
|
| 509 |
if(tbody) tbody.innerHTML = "";
|
| 510 |
-
if(fnameEl) fnameEl.value = "Ticket";
|
| 511 |
if(agentEl) agentEl.value = "";
|
| 512 |
if(regionEl) regionEl.value = "";
|
| 513 |
updateBadge(0); setButtonsEnabled(false);
|
|
@@ -515,80 +506,17 @@ function clearAll(){
|
|
| 515 |
toast("تم مسح كل البيانات والتخزين.");
|
| 516 |
}
|
| 517 |
|
| 518 |
-
function normalizeForPaste(text){
|
| 519 |
-
const norm = normalizeText(text||"");
|
| 520 |
-
const parts = splitTickets(norm);
|
| 521 |
-
return parts.length ? parts.join("\n\n🔴🔴🔴\n") : norm;
|
| 522 |
-
}
|
| 523 |
-
|
| 524 |
-
async function smartPasteInto(el){
|
| 525 |
-
try{
|
| 526 |
-
const txt = await navigator.clipboard.readText();
|
| 527 |
-
if(txt && txt.trim()){
|
| 528 |
-
const formatted = normalizeForPaste(txt);
|
| 529 |
-
if(el.value && el.value.trim()){
|
| 530 |
-
el.value = el.value.trimEnd() + "\n\n🔴🔴🔴\n" + formatted;
|
| 531 |
-
}else{
|
| 532 |
-
el.value = formatted;
|
| 533 |
-
}
|
| 534 |
-
saveState();
|
| 535 |
-
toast("تم اللصق والتنظيم.");
|
| 536 |
-
return;
|
| 537 |
-
}
|
| 538 |
-
openPasteModal(el);
|
| 539 |
-
}catch{
|
| 540 |
-
openPasteModal(el);
|
| 541 |
-
}
|
| 542 |
-
}
|
| 543 |
-
|
| 544 |
-
function openPasteModal(targetEl){
|
| 545 |
-
const modal = document.getElementById("pasteModal");
|
| 546 |
-
const input = document.getElementById("pasteInput");
|
| 547 |
-
const add = document.getElementById("pasteAdd");
|
| 548 |
-
const cancel= document.getElementById("pasteCancel");
|
| 549 |
-
input.value = "";
|
| 550 |
-
modal.hidden = false;
|
| 551 |
-
input.focus();
|
| 552 |
-
|
| 553 |
-
function close(){ modal.hidden = true; add.removeEventListener("click", onAdd); cancel.removeEventListener("click", onCancel); document.removeEventListener("keydown", onEsc); }
|
| 554 |
-
function onAdd(){
|
| 555 |
-
const txt = input.value || "";
|
| 556 |
-
const formatted = normalizeForPaste(txt);
|
| 557 |
-
if(formatted.trim()){
|
| 558 |
-
if(targetEl.value && targetEl.value.trim()){
|
| 559 |
-
targetEl.value = targetEl.value.trimEnd() + "\n\n🔴🔴🔴\n" + formatted;
|
| 560 |
-
}else{
|
| 561 |
-
targetEl.value = formatted;
|
| 562 |
-
}
|
| 563 |
-
saveState();
|
| 564 |
-
toast("تمت الإضافة.");
|
| 565 |
-
}
|
| 566 |
-
close();
|
| 567 |
-
}
|
| 568 |
-
function onCancel(){ close(); }
|
| 569 |
-
function onEsc(e){ if(e.key === "Escape"){ e.preventDefault(); close(); } }
|
| 570 |
-
|
| 571 |
-
add.addEventListener("click", onAdd);
|
| 572 |
-
cancel.addEventListener("click", onCancel);
|
| 573 |
-
document.addEventListener("keydown", onEsc);
|
| 574 |
-
}
|
| 575 |
-
|
| 576 |
function init(){
|
| 577 |
const parseBtn = document.getElementById("btn-parse");
|
| 578 |
const exportBtn = document.getElementById("btn-export");
|
| 579 |
const copyBtn = document.getElementById("btn-copy");
|
| 580 |
const clearBtn = document.getElementById("btn-clear");
|
| 581 |
-
const sampleBtn = document.getElementById("btn-sample");
|
| 582 |
-
const smartPaste = document.getElementById("btn-smartpaste");
|
| 583 |
const rawEl = document.getElementById("raw");
|
| 584 |
-
const fnameEl = document.getElementById("fname");
|
| 585 |
const agentEl = document.getElementById("agentName");
|
| 586 |
const regionEl = document.getElementById("regionDefault");
|
| 587 |
|
| 588 |
loadState();
|
| 589 |
|
| 590 |
-
smartPaste.addEventListener("click", ()=> smartPasteInto(rawEl));
|
| 591 |
-
|
| 592 |
parseBtn.addEventListener("click", ()=>{
|
| 593 |
const raw = (rawEl.value || "").trim();
|
| 594 |
if(!raw){ toast("فضلاً الصق/ي تذاكر أولاً."); return; }
|
|
@@ -604,10 +532,8 @@ function init(){
|
|
| 604 |
exportBtn.addEventListener("click", exportExcel);
|
| 605 |
copyBtn.addEventListener("click", copyToClipboardTSV);
|
| 606 |
clearBtn.addEventListener("click", clearAll);
|
| 607 |
-
sampleBtn.addEventListener("click", ()=>{ rawEl.value = SAMPLE; saveState(); });
|
| 608 |
|
| 609 |
rawEl.addEventListener("input", saveState);
|
| 610 |
-
fnameEl.addEventListener("input", saveState);
|
| 611 |
agentEl.addEventListener("input", saveState);
|
| 612 |
regionEl.addEventListener("change", saveState);
|
| 613 |
|
|
|
|
| 1 |
+
|
| 2 |
|
| 3 |
const EXPORT_COLUMNS = [
|
| 4 |
"التصنيف","نوع المشكلة","وقت حدوث المشكلة","اسم صاحب المشكلة",
|
|
|
|
| 7 |
|
| 8 |
const FIELD_ALIASES = {
|
| 9 |
"نوع المشكلة": ["نوع المشكله","نوع المشكلة","المشكلة"],
|
| 10 |
+
"وقت حدوث المشكلة": ["وقت حدوث المشكله","وقت حدوث المشكلة","وقت المشكلة","وقت حدوث","وقت حدوث المشكله:"],
|
| 11 |
"اسم صاحب المشكلة": ["اسم صاحب المشكله","اسم صاحب المشكلة","اسم صاحب البلاغ","الاسم"],
|
| 12 |
"رقم الهوية": ["رقم الهويه","رقم الهوية","الهوية"],
|
| 13 |
"رقم الجهاز": ["رقم الجهاز","الجهاز"],
|
|
|
|
| 17 |
};
|
| 18 |
|
| 19 |
const START_LABELS = Array.from(new Set(Object.values(FIELD_ALIASES).flat()));
|
| 20 |
+
const TICKET_SEP = /\n\s*(?:\n|—+|-{3,}|={3,}|🔴+)+\s*\n/;
|
| 21 |
+
const MIN_SPLIT_SPAN = 40;
|
| 22 |
|
| 23 |
const CLASS_RULES = {
|
| 24 |
"استفسار": ["استفسار","سؤال","استعلام","معلومة","استفسارات"],
|
|
|
|
| 41 |
"النظام المكتبي","تناقل البيانات","استفسار",
|
| 42 |
];
|
| 43 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 44 |
const arabicDigitsMap = {"٠":"0","١":"1","٢":"2","٣":"3","٤":"4","٥":"5","٦":"6","٧":"7","٨":"8","٩":"9"};
|
| 45 |
function normalizeText(s){
|
| 46 |
if(typeof s!=="string") return "";
|
|
|
|
| 132 |
return m ? m[1].trim() : "";
|
| 133 |
}
|
| 134 |
|
| 135 |
+
|
| 136 |
function splitTickets(raw){
|
| 137 |
const text = normalizeText(raw);
|
| 138 |
if(!text) return [];
|
| 139 |
|
| 140 |
+
const niu = findStartsByLabels(text, ["نوع المشكلة","نوع المشكله"]).sort((a,b)=>a-b);
|
| 141 |
+
if(niu.length >= 2){
|
| 142 |
+
const parts=[];
|
| 143 |
+
for(let i=0;i<niu.length;i++){
|
| 144 |
+
const s = niu[i];
|
| 145 |
+
const e = i+1<niu.length ? niu[i+1] : text.length;
|
| 146 |
+
const slice = text.slice(s,e).trim();
|
| 147 |
+
if(slice) parts.push(slice);
|
| 148 |
+
}
|
| 149 |
+
if(parts.length) return parts;
|
| 150 |
+
}
|
| 151 |
+
|
| 152 |
if(TICKET_SEP.test(text)){
|
| 153 |
return text.split(TICKET_SEP).map(p=>p.trim()).filter(Boolean);
|
| 154 |
}
|
| 155 |
|
| 156 |
const startsAll = findStartsByLabels(text, START_LABELS).sort((a,b)=>a-b);
|
| 157 |
const filtered = startsAll.filter((pos,i,arr)=> i===0 || (pos - arr[i-1]) >= MIN_SPLIT_SPAN);
|
| 158 |
+
if(filtered.length >= 2){
|
|
|
|
|
|
|
| 159 |
const parts=[];
|
| 160 |
+
for(let i=0;i<filtered.length;i++){
|
| 161 |
+
const s = filtered[i];
|
| 162 |
+
const e = i+1<filtered.length ? filtered[i+1] : text.length;
|
| 163 |
const slice = text.slice(s,e).trim();
|
| 164 |
if(slice) parts.push(slice);
|
| 165 |
}
|
|
|
|
| 169 |
const blocks = text.split(/\n\s*\n+/).map(p=>p.trim()).filter(Boolean);
|
| 170 |
if(blocks.length > 1) return blocks;
|
| 171 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 172 |
return [text];
|
| 173 |
}
|
| 174 |
|
|
|
|
| 398 |
});
|
| 399 |
|
| 400 |
const ts = new Date().toISOString().replace(/\D/g,"").slice(0,14);
|
| 401 |
+
const filename = `Ticket_${ts}.xlsx`; // اسم ثابت Ticket
|
|
|
|
| 402 |
|
| 403 |
const buffer = await wb.xlsx.writeBuffer();
|
| 404 |
const blob = new Blob([buffer], { type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" });
|
|
|
|
| 447 |
اسم المسح: الخبر 2025
|
| 448 |
اسم المنطقة: الشرقية`;
|
| 449 |
|
| 450 |
+
const STATE_KEY = "ticketParserState_v10_5";
|
| 451 |
const ALL_STATE_KEYS = [
|
| 452 |
"ticketParserState_v8","ticketParserState_v9","ticketParserState_v10",
|
| 453 |
+
"ticketParserState_v10_1","ticketParserState_v10_2","ticketParserState_v10_3","ticketParserState_v10_5"
|
| 454 |
];
|
| 455 |
|
| 456 |
function ensureColumns(rows, agentName, defaultRegion){
|
|
|
|
| 470 |
function saveState(){
|
| 471 |
try{
|
| 472 |
const raw = document.getElementById("raw")?.value || "";
|
|
|
|
| 473 |
const agent = document.getElementById("agentName")?.value || "";
|
| 474 |
const region= document.getElementById("regionDefault")?.value || "";
|
| 475 |
const rows = readTable();
|
| 476 |
+
localStorage.setItem(STATE_KEY, JSON.stringify({ raw, agent, region, rows }));
|
| 477 |
}catch{}
|
| 478 |
}
|
| 479 |
function loadState(){
|
| 480 |
try{
|
| 481 |
const s = localStorage.getItem(STATE_KEY);
|
| 482 |
if(!s) return false;
|
| 483 |
+
let { raw, agent, region, rows } = JSON.parse(s);
|
| 484 |
if(typeof raw === "string"){ const el=document.getElementById("raw"); if(el) el.value = raw; }
|
|
|
|
| 485 |
if(typeof agent === "string"){ const el=document.getElementById("agentName"); if(el) el.value = agent; }
|
| 486 |
if(typeof region === "string"){ const el=document.getElementById("regionDefault"); if(el) el.value = region; }
|
| 487 |
rows = ensureColumns(rows, agent, region);
|
|
|
|
| 495 |
function clearAll(){
|
| 496 |
const rawEl = document.getElementById("raw");
|
| 497 |
const tbody = document.getElementById("tbody");
|
|
|
|
| 498 |
const agentEl = document.getElementById("agentName");
|
| 499 |
const regionEl= document.getElementById("regionDefault");
|
| 500 |
if(rawEl) rawEl.value = "";
|
| 501 |
if(tbody) tbody.innerHTML = "";
|
|
|
|
| 502 |
if(agentEl) agentEl.value = "";
|
| 503 |
if(regionEl) regionEl.value = "";
|
| 504 |
updateBadge(0); setButtonsEnabled(false);
|
|
|
|
| 506 |
toast("تم مسح كل البيانات والتخزين.");
|
| 507 |
}
|
| 508 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 509 |
function init(){
|
| 510 |
const parseBtn = document.getElementById("btn-parse");
|
| 511 |
const exportBtn = document.getElementById("btn-export");
|
| 512 |
const copyBtn = document.getElementById("btn-copy");
|
| 513 |
const clearBtn = document.getElementById("btn-clear");
|
|
|
|
|
|
|
| 514 |
const rawEl = document.getElementById("raw");
|
|
|
|
| 515 |
const agentEl = document.getElementById("agentName");
|
| 516 |
const regionEl = document.getElementById("regionDefault");
|
| 517 |
|
| 518 |
loadState();
|
| 519 |
|
|
|
|
|
|
|
| 520 |
parseBtn.addEventListener("click", ()=>{
|
| 521 |
const raw = (rawEl.value || "").trim();
|
| 522 |
if(!raw){ toast("فضلاً الصق/ي تذاكر أولاً."); return; }
|
|
|
|
| 532 |
exportBtn.addEventListener("click", exportExcel);
|
| 533 |
copyBtn.addEventListener("click", copyToClipboardTSV);
|
| 534 |
clearBtn.addEventListener("click", clearAll);
|
|
|
|
| 535 |
|
| 536 |
rawEl.addEventListener("input", saveState);
|
|
|
|
| 537 |
agentEl.addEventListener("input", saveState);
|
| 538 |
regionEl.addEventListener("change", saveState);
|
| 539 |
|