Download index.html from GoshawkVortexAI/Goshawk_LexiAI: direct link, hf CLI and curl.
- Browser
- Download file 42.6 kB
-
https://huggingface.co/spaces/GoshawkVortexAI/Goshawk_LexiAI/resolve/main/index.html
- Command line
-
hf download hf://spaces/GoshawkVortexAI/Goshawk_LexiAI/index.html
-
curl -L -o index.html https://huggingface.co/spaces/GoshawkVortexAI/Goshawk_LexiAI/resolve/main/index.html
42.6 kB
| <html lang="tr" data-theme="gold"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> | |
| <title>LexiAI – Hukuki Belge Sınıflandırıcı</title> | |
| <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Playfair+Display:wght@600;700;800&display=swap" rel="stylesheet"> | |
| <style> | |
| :root{color-scheme:dark;--bg:#070914;--p:#0f1224;--p2:#141833;--ln:#262b52;--tx:#f1f2fb;--mu:#9a9fc6;--a:#d4af37;--a2:#f3dc8a;--g:#34d399;--r:#f87171;box-sizing:border-box;padding-top:env(safe-area-inset-top,0px);padding-bottom:env(safe-area-inset-bottom,0px)} | |
| [data-theme=violet]{--a:#8b8dff;--a2:#c4b5fd} | |
| *{box-sizing:border-box;margin:0;padding:0} | |
| html{height:100%} | |
| body{font-family:Inter,system-ui,sans-serif;background:radial-gradient(1000px 520px at 90% -10%,color-mix(in srgb,var(--a) 18%,transparent),transparent 60%),radial-gradient(800px 500px at -10% 40%,#1d2a9a33,transparent 60%),var(--bg);color:var(--tx);min-height:100%} | |
| button{font:inherit;color:inherit;cursor:pointer;border:0;background:none} | |
| h1,h2,.serif{font-family:"Playfair Display",Georgia,serif} | |
| .gold{background:linear-gradient(90deg,var(--a2),var(--a));-webkit-background-clip:text;background-clip:text;color:transparent} | |
| .btn{display:inline-flex;align-items:center;gap:8px;padding:11px 20px;border-radius:10px;font-weight:600;font-size:14px;background:linear-gradient(135deg,var(--a2),var(--a));color:#1a1405;box-shadow:0 10px 26px -12px var(--a)} | |
| .btn:hover{filter:brightness(1.08)}.btn.o{background:none;color:var(--tx);border:1px solid var(--ln);box-shadow:none}.btn.o:hover{border-color:var(--a)} | |
| .btn.s{padding:7px 12px;font-size:12px} | |
| :focus-visible{outline:2px solid var(--a2);outline-offset:2px} | |
| svg.i{width:1em;height:1em;fill:none;stroke:currentColor;stroke-width:2.2;stroke-linecap:round;stroke-linejoin:round;vertical-align:-.12em} | |
| .logo{display:flex;align-items:center;gap:11px;font-family:"Playfair Display",serif;font-weight:800;font-size:27px}.logo svg{width:38px;height:38px;color:var(--a)}.logo small{display:block;font:400 11px Inter,sans-serif;color:var(--mu);letter-spacing:.14em;text-transform:uppercase} | |
| /* login */ | |
| #login{position:fixed;inset:0;z-index:60;background:#05060ef2;display:none;place-items:center;padding:20px} | |
| .box{width:100%;max-width:410px;background:linear-gradient(160deg,var(--p2),var(--p));border:1px solid var(--ln);border-radius:20px;padding:30px;box-shadow:0 40px 90px -30px #000,0 0 0 1px color-mix(in srgb,var(--a) 20%,transparent)} | |
| .box h2{margin:22px 0 4px;font-size:24px}.box p{color:var(--mu);font-size:14px} | |
| label{display:block;font-size:12px;color:var(--mu);margin:13px 0 5px;letter-spacing:.05em} | |
| input[type=text],input[type=password],textarea,select{width:100%;padding:11px 13px;border-radius:10px;border:1px solid var(--ln);background:#090b1c;color:var(--tx);font:inherit;font-size:14px} | |
| input:focus,textarea:focus{outline:2px solid var(--a)} | |
| .hint{margin-top:14px;padding:11px;border-radius:10px;background:color-mix(in srgb,var(--a) 10%,transparent);border:1px dashed var(--a);font-size:13px;line-height:1.6}.hint b{color:var(--a2)} | |
| .err{color:var(--r);font-size:13px;min-height:18px;margin-top:8px} | |
| /* layout */ | |
| aside{position:fixed;inset:0 auto 0 0;width:252px;background:#080a18;border-right:1px solid var(--ln);padding:22px 14px;display:flex;flex-direction:column;gap:4px;z-index:30;overflow-y:auto} | |
| aside .logo{margin:0 6px 22px} | |
| .nav{display:flex;align-items:center;gap:12px;padding:11px 14px;border-radius:11px;width:100%;text-align:left;color:var(--mu);font-size:14px} | |
| .nav:hover{background:#ffffff0a;color:var(--tx)}.nav.on{background:linear-gradient(90deg,color-mix(in srgb,var(--a) 26%,transparent),transparent);color:var(--a2);box-shadow:inset 3px 0 var(--a)} | |
| .nav svg{width:18px;height:18px}.nav[hidden]{display:none} | |
| .user{margin-top:auto;padding:14px;border:1px solid var(--ln);border-radius:14px;background:var(--p);font-size:13px;color:var(--mu)} | |
| .user b{color:var(--tx);display:block;font-size:15px}.badge{display:inline-block;margin:4px 0 10px;padding:2px 9px;border-radius:99px;font-size:11px;font-weight:700;background:color-mix(in srgb,var(--a) 20%,transparent);color:var(--a2);border:1px solid var(--a)} | |
| .user .btn{width:100%;justify-content:center} | |
| main{margin-left:252px;padding:26px 30px 40px;max-width:1400px} | |
| .top{display:flex;justify-content:space-between;align-items:center;gap:12px;margin-bottom:22px;color:var(--mu);font-size:13px;flex-wrap:wrap} | |
| .menu{display:none;position:fixed;top:calc(10px + env(safe-area-inset-top,0px));right:12px;z-index:40;padding:10px 13px;border-radius:10px;background:var(--a);color:#111} | |
| .view{display:none}.view.on{display:block} | |
| .hero{display:grid;grid-template-columns:1.4fr 1fr;gap:20px;align-items:center;padding:8px 0 24px} | |
| h1{font-size:clamp(30px,4.4vw,52px);line-height:1.08;font-weight:800;letter-spacing:-.01em} | |
| .sub{color:var(--mu);margin:12px 0 16px;max-width:600px;line-height:1.6} | |
| .badges{display:flex;gap:10px 20px;flex-wrap:wrap;font-size:13px}.badges span:before{content:"✔";color:var(--g);margin-right:7px} | |
| .art{display:grid;place-items:center;color:var(--a);opacity:.9}.art svg{width:min(210px,50vw);height:auto;filter:drop-shadow(0 0 30px color-mix(in srgb,var(--a) 45%,transparent))} | |
| .kpis{display:grid;grid-template-columns:repeat(5,1fr);gap:12px;margin-bottom:18px} | |
| .kpi{background:linear-gradient(160deg,var(--p2),var(--p));border:1px solid var(--ln);border-radius:14px;padding:14px 16px} | |
| .kpi small{color:var(--mu);font-size:12px;display:flex;gap:6px;align-items:center}.kpi b{display:block;font:700 26px "Playfair Display",serif;margin-top:4px;color:var(--a2)} | |
| .grid{display:grid;grid-template-columns:repeat(12,1fr);gap:16px} | |
| .card{background:linear-gradient(160deg,var(--p2),var(--p));border:1px solid var(--ln);border-radius:16px;padding:20px;min-width:0} | |
| .card h3{font-size:15px;margin-bottom:14px;display:flex;align-items:center;gap:9px;font-weight:600}.card h3 svg{color:var(--a)} | |
| .c5{grid-column:span 5}.c7{grid-column:span 7}.c4{grid-column:span 4}.c6{grid-column:span 6}.c8{grid-column:span 8}.c12{grid-column:span 12} | |
| .drop{border:1.5px dashed color-mix(in srgb,var(--a) 55%,transparent);border-radius:14px;padding:20px;text-align:center;transition:.2s} | |
| .drop.over{background:color-mix(in srgb,var(--a) 10%,transparent)}.drop p{color:var(--mu);font-size:13px;margin:6px 0 12px}.drop .big{font-size:34px;color:var(--a)} | |
| textarea{min-height:92px;resize:vertical;margin-top:12px} | |
| .row{display:flex;gap:8px;flex-wrap:wrap;margin-top:12px;align-items:center} | |
| .chip{padding:4px 11px;border-radius:99px;font-size:12px;border:1px solid var(--ln);color:var(--mu)}.chip.a{border-color:var(--a);color:var(--a2);background:color-mix(in srgb,var(--a) 10%,transparent)} | |
| .chip.w{border-color:var(--r);color:var(--r)}.chip.k{cursor:pointer}.chip.k:hover{border-color:var(--a);color:var(--tx)} | |
| .res{border-radius:13px;padding:16px 18px;background:linear-gradient(135deg,color-mix(in srgb,var(--a) 28%,#10132c),#10132c);border:1px solid color-mix(in srgb,var(--a) 40%,transparent)} | |
| .res .t{font:700 26px "Playfair Display",serif}.bar{height:8px;border-radius:9px;background:#ffffff1a;margin-top:10px;overflow:hidden}.bar i{display:block;height:100%;border-radius:9px;background:linear-gradient(90deg,var(--a),var(--a2));transition:width .7s} | |
| .oth div.r{display:grid;grid-template-columns:120px 1fr 52px;gap:10px;align-items:center;margin-top:9px;font-size:13px;color:var(--mu)}.oth .bar{margin:0;background:#1a1f45} | |
| .sec{margin-top:14px;font-size:12px;color:var(--mu);letter-spacing:.06em;text-transform:uppercase}.sum{margin-top:6px;font-size:14px;line-height:1.6;color:#d7d9f2} | |
| .donut{display:flex;gap:18px;align-items:center;flex-wrap:wrap}.ring{width:140px;height:140px;border-radius:50%;display:grid;place-items:center;flex:none}.ring span{width:96px;height:96px;border-radius:50%;background:var(--p);display:grid;place-items:center;font:700 22px "Playfair Display",serif;text-align:center} | |
| .lg{display:grid;gap:7px;font-size:13px;flex:1;min-width:140px}.lg i{display:inline-block;width:9px;height:9px;border-radius:50%;margin-right:8px}.lg div{display:flex;justify-content:space-between;color:var(--mu)} | |
| .days{display:flex;align-items:flex-end;gap:10px;height:120px}.days div{flex:1;text-align:center;font-size:11px;color:var(--mu);display:flex;flex-direction:column;justify-content:flex-end;height:100%}.days i{display:block;border-radius:6px 6px 0 0;background:linear-gradient(180deg,var(--a2),var(--a));min-height:3px;margin-bottom:5px} | |
| .act{display:flex;justify-content:space-between;gap:10px;padding:9px 0;border-bottom:1px solid #ffffff0d;font-size:13px}.act span{color:var(--mu)} | |
| .feat{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:12px}.feat div{padding:14px;border:1px solid var(--ln);border-radius:12px;font-size:13px;color:var(--mu);line-height:1.5}.feat b{display:block;color:var(--tx);margin-bottom:4px;font-size:14px}.feat svg{color:var(--a);width:20px;height:20px;display:block;margin-bottom:8px} | |
| table{width:100%;border-collapse:collapse;font-size:13px}th,td{text-align:left;padding:10px;border-bottom:1px solid #ffffff10}th{color:var(--mu);font-size:11px;letter-spacing:.08em;text-transform:uppercase}.tw{overflow-x:auto} | |
| .tools{display:flex;gap:10px;flex-wrap:wrap;margin-bottom:14px}.tools input,.tools select{max-width:260px} | |
| .vh{display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:10px;margin-bottom:18px}.vh h2{font-size:30px} | |
| .set{display:grid;gap:18px;max-width:560px}.set input[type=range]{width:100%;accent-color:var(--a)} | |
| #toast{position:fixed;left:50%;bottom:calc(20px + env(safe-area-inset-bottom,0px));transform:translate(-50%,30px);background:var(--p2);border:1px solid var(--a);padding:10px 18px;border-radius:99px;font-size:13px;opacity:0;transition:.3s;z-index:90;pointer-events:none}#toast.on{opacity:1;transform:translate(-50%,0)} | |
| .qw{margin-top:6px;padding:13px 15px;border-radius:12px;border:1px solid var(--ln);background:#090b1c;font-size:14px;line-height:1.65;color:#d7d9f2;white-space:pre-wrap;min-height:48px} | |
| .qw.load:after{content:"▍";color:var(--a);animation:bl 1s steps(2) infinite}@keyframes bl{50%{opacity:0}} | |
| .qw.er{color:var(--r)}.qh{display:flex;justify-content:space-between;align-items:center;gap:8px}.qh .sec{margin-top:14px} | |
| .ck{display:flex;align-items:center;gap:8px;font-size:14px;color:var(--tx);margin:0}.ck input{width:auto} | |
| @media(max-width:980px){aside{transform:translateX(-100%);transition:.25s}aside.open{transform:none;box-shadow:0 0 0 100vmax #0009}main{margin-left:0;padding:62px 16px 30px}.menu{display:block}.hero{grid-template-columns:1fr}.art{display:none}.kpis{grid-template-columns:repeat(2,1fr)}.c5,.c7,.c4,.c6,.c8{grid-column:span 12}} | |
| @media print{aside,.menu,.tools,.btn{display:none!important}main{margin:0}body{background:#fff;color:#000}.card{background:#fff;border-color:#999}} | |
| </style> | |
| </head> | |
| <body> | |
| <svg width="0" height="0" style="position:absolute"><defs> | |
| <symbol id="sc" viewBox="0 0 64 64"><g fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><path d="M32 8v46M16 56h32M10 16h44M32 8m-3 0a3 3 0 106 0a3 3 0 10-6 0"/><path d="M10 16L3 36a8 5 0 0014 0zM54 16l-7 20a8 5 0 0014 0z"/></g></symbol> | |
| <symbol id="home" viewBox="0 0 24 24"><path d="M3 11l9-8 9 8M5 10v10h14V10"/></symbol> | |
| <symbol id="up" viewBox="0 0 24 24"><path d="M7 18a5 5 0 010-10 6 6 0 0111.5 1.5A4 4 0 0118 18M12 12v8M9 14l3-3 3 3"/></symbol> | |
| <symbol id="lay" viewBox="0 0 24 24"><path d="M12 3l9 5-9 5-9-5zM3 13l9 5 9-5M3 17l9 5 9-5"/></symbol> | |
| <symbol id="hist" viewBox="0 0 24 24"><path d="M3 12a9 9 0 109-9 9 9 0 00-7 3M3 4v4h4M12 8v5l3 2"/></symbol> | |
| <symbol id="bar" viewBox="0 0 24 24"><path d="M4 20V10M10 20V4M16 20v-7M22 20H2"/></symbol> | |
| <symbol id="cog" viewBox="0 0 24 24"><circle cx="12" cy="12" r="3"/><path d="M12 2v3M12 19v3M2 12h3M19 12h3M5 5l2 2M17 17l2 2M19 5l-2 2M7 17l-2 2"/></symbol> | |
| <symbol id="usr" viewBox="0 0 24 24"><circle cx="9" cy="8" r="4"/><path d="M2 21c0-4 3-6 7-6s7 2 7 6M17 4a4 4 0 010 8M22 21c0-3-2-5-4-5.5"/></symbol> | |
| <symbol id="sh" viewBox="0 0 24 24"><path d="M12 3l8 3v6c0 5-3.5 8-8 9-4.5-1-8-4-8-9V6zM9 12l2 2 4-4"/></symbol> | |
| <symbol id="bolt" viewBox="0 0 24 24"><path d="M13 2L4 14h7l-1 8 9-12h-7z"/></symbol> | |
| <symbol id="doc" viewBox="0 0 24 24"><path d="M6 2h9l5 5v15H6zM14 2v6h6M9 13h8M9 17h6"/></symbol> | |
| <symbol id="ok" viewBox="0 0 24 24"><circle cx="12" cy="12" r="9"/><path d="M8 12l3 3 5-6"/></symbol> | |
| <symbol id="cal" viewBox="0 0 24 24"><rect x="3" y="5" width="18" height="16" rx="2"/><path d="M8 3v4M16 3v4M3 10h18"/></symbol> | |
| <symbol id="srch" viewBox="0 0 24 24"><circle cx="11" cy="11" r="7"/><path d="M21 21l-5-5"/></symbol> | |
| </defs></svg> | |
| <section id="login"><div class="box"> | |
| <div class="logo"><svg class="i"><use href="#sc"/></svg><div>Lexi<span class="gold">AI</span><small>Hukuki Belge Sınıflandırıcı</small></div></div> | |
| <h2>Üye Girişi</h2><p>Hesabınıza giriş yapın.</p> | |
| <label for="u">KULLANICI ADI</label><input type="text" id="u" value="admin" autocomplete="username"> | |
| <label for="pw">ŞİFRE</label><input type="password" id="pw" value="admin123" autocomplete="current-password"> | |
| <div class="err" id="err"></div> | |
| <button class="btn" style="width:100%;justify-content:center" onclick="doLogin()">Giriş Yap</button> | |
| <button class="btn o" style="width:100%;justify-content:center;margin-top:8px" onclick="$('login').style.display='none'">Panele Dön</button> | |
| <div class="hint">Yönetici hesabı<br>Kullanıcı adı: <b>admin</b> Şifre: <b>admin123</b></div> | |
| </div></section> | |
| <button class="menu" onclick="document.querySelector('aside').classList.toggle('open')">☰</button> | |
| <aside> | |
| <div class="logo"><svg class="i"><use href="#sc"/></svg><div>Lexi<span class="gold">AI</span><small>Elit Hukuk Paneli</small></div></div> | |
| <button class="nav on" data-v="home"><svg class="i"><use href="#home"/></svg>Ana Panel</button> | |
| <button class="nav" data-v="home" data-s="up"><svg class="i"><use href="#up"/></svg>Belge Yükle</button> | |
| <button class="nav" data-v="batch"><svg class="i"><use href="#lay"/></svg>Toplu Analiz</button> | |
| <button class="nav" data-v="hist"><svg class="i"><use href="#hist"/></svg>Analiz Geçmişi</button> | |
| <button class="nav" data-v="rep"><svg class="i"><use href="#bar"/></svg>Raporlar</button> | |
| <button class="nav" data-v="users" id="nu" hidden><svg class="i"><use href="#usr"/></svg>Üye Yönetimi</button> | |
| <button class="nav" data-v="set"><svg class="i"><use href="#cog"/></svg>Ayarlar</button> | |
| <div class="user"><b id="who">Misafir</b><span class="badge" id="role">Ziyaretçi</span><button class="btn o" id="ab" onclick="authBtn()">Giriş Yap</button><div style="margin-top:10px;font-size:11px">LexiAI v2.0 Elit</div></div> | |
| </aside> | |
| <main> | |
| <div class="top"><span id="greet"></span><span id="clock"></span></div> | |
| <div class="view on" id="v-home"> | |
| <div class="hero"><div> | |
| <h1>Hukuki Belgelerde <span class="gold">Akıllı Sınıflandırma</span></h1> | |
| <p class="sub">Dilekçe, sözleşme, karar ve daha fazlasını saniyeler içinde sınıflandırın; tarih, tutar ve dosya numaralarını otomatik çıkarın, kişisel veri risklerini işaretleyin.</p> | |
| <div class="badges"><span>%95+ Doğruluk</span><span>Hızlı İşlem</span><span>KVKK Uyarısı</span><span>Varlık Çıkarımı</span></div> | |
| </div><div class="art"><svg><use href="#sc"/></svg></div></div> | |
| <div class="kpis"> | |
| <div class="kpi"><small><svg class="i"><use href="#doc"/></svg>Toplam Belge</small><b id="k1">0</b></div> | |
| <div class="kpi"><small><svg class="i"><use href="#ok"/></svg>Ort. Güven</small><b id="k2">–</b></div> | |
| <div class="kpi"><small><svg class="i"><use href="#bolt"/></svg>Ort. Süre</small><b id="k3">–</b></div> | |
| <div class="kpi"><small><svg class="i"><use href="#cal"/></svg>Bugün</small><b id="k4">0</b></div> | |
| <div class="kpi"><small><svg class="i"><use href="#sh"/></svg>KVKK Uyarısı</small><b id="k5">0</b></div> | |
| </div> | |
| <div class="grid"> | |
| <div class="card c5" id="up"><h3><svg class="i"><use href="#up"/></svg>Belgenizi Yükleyin</h3> | |
| <div class="drop" id="drop"><div class="big"><svg class="i"><use href="#up"/></svg></div><p>PDF, Word, Excel, PowerPoint, görsel (OCR), metin… her tür dosyayı sürükleyip bırakın veya seçin.</p> | |
| <button class="btn" onclick="f1.click()">Dosya Seç</button><input type="file" id="f1" hidden></div> | |
| <textarea id="txt" placeholder="…veya belge metnini buraya yapıştırın"></textarea> | |
| <div class="row"><button class="btn" onclick="run()">Analiz Et</button><button class="btn o" onclick="$('txt').value='';reset()">Temizle</button></div> | |
| <div class="sec">Örnek belgeler</div><div class="row" id="samples" style="margin-top:6px"></div> | |
| </div> | |
| <div class="card c7"><h3><svg class="i"><use href="#ok"/></svg>Sınıflandırma Sonucu</h3> | |
| <div class="res"><div class="t" id="rl">Belge bekleniyor</div><div id="rc" style="color:#cfd2ff;margin-top:2px">Güven: –</div><div class="bar"><i id="rb" style="width:0"></i></div><div class="row" id="rt"></div></div> | |
| <div class="sec">Diğer olası sınıflar</div><div class="oth" id="o"></div> | |
| <div class="sec">Özet</div><div class="sum" id="sm">Analiz için bir belge yükleyin.</div> | |
| <div class="sec">Çıkarılan bilgiler</div><div class="row" id="en" style="margin-top:6px"><span class="chip">–</span></div> | |
| <div class="qh"><div class="sec">🤖 Qwen Yorumu</div><button class="chip k" id="qb" onclick="qwenAgain()" style="margin-top:12px">Yenile</button></div> | |
| <div class="qw" id="qw">Sınıflandırmadan sonra Qwen burada yorum yapacak.</div> | |
| </div> | |
| <div class="card c4"><h3><svg class="i"><use href="#bar"/></svg>Sınıf Dağılımı</h3><div class="donut"><div class="ring" id="ring"><span id="rt2">0</span></div><div class="lg" id="lg"></div></div></div> | |
| <div class="card c4"><h3><svg class="i"><use href="#cal"/></svg>Son 7 Gün</h3><div class="days" id="days"></div></div> | |
| <div class="card c4"><h3><svg class="i"><use href="#hist"/></svg>Son Hareketler</h3><div id="act"></div></div> | |
| <div class="card c12"><h3><svg class="i"><use href="#sh"/></svg>Başlıca Özellikler</h3><div class="feat"> | |
| <div><svg class="i"><use href="#doc"/></svg><b>8 Belge Türü</b>Dilekçe, karar, sözleşme, yönetmelik, vekâletname, ihtarname, bilirkişi raporu, kanun.</div> | |
| <div><svg class="i"><use href="#lay"/></svg><b>Toplu Analiz</b>PDF, Word, Excel, PowerPoint, görsel ve metin dosyalarını tek seferde sınıflandırın. Taranmış belgeler OCR ile okunur.</div> | |
| <div><svg class="i"><use href="#srch"/></svg><b>Varlık Çıkarımı</b>Tarih, TL tutarı ve esas numarası otomatik bulunur.</div> | |
| <div><svg class="i"><use href="#sh"/></svg><b>KVKK Uyarısı</b>11 haneli kimlik numarası tespit edilirse işaretlenir.</div> | |
| <div><svg class="i"><use href="#bar"/></svg><b>Raporlama</b>İstatistik, CSV dışa aktarma ve yazdırma.</div> | |
| <div><svg class="i"><use href="#usr"/></svg><b>Üyelik ve Roller</b>Yönetici ve üye hesapları, üye yönetimi paneli.</div></div></div> | |
| </div> | |
| </div> | |
| <div class="view" id="v-batch"><div class="vh"><h2>Toplu Analiz</h2></div> | |
| <div class="card"><div class="drop" id="drop2"><div class="big"><svg class="i"><use href="#lay"/></svg></div><p>Birden çok dosyayı (PDF, Word, Excel, görsel, metin…) buraya bırakın.</p><button class="btn" onclick="f2.click()">Dosyaları Seç</button><input type="file" id="f2" multiple hidden></div> | |
| <div class="tw" style="margin-top:16px"><table><thead><tr><th>Dosya</th><th>Sınıf</th><th>Güven</th><th>Not</th></tr></thead><tbody id="bt"><tr><td colspan="4" style="color:var(--mu)">Henüz dosya yok.</td></tr></tbody></table></div></div></div> | |
| <div class="view" id="v-hist"><div class="vh"><h2>Analiz Geçmişi</h2><div class="tools" style="margin:0"><button class="btn o s" onclick="csv()">CSV İndir</button><button class="btn o s" onclick="clearH()">Temizle</button></div></div> | |
| <div class="tools"><input type="text" id="q" placeholder="Ara…"><select id="fl"></select></div> | |
| <div class="card tw"><table><thead><tr><th>Tarih</th><th>Belge</th><th>Sınıf</th><th>Güven</th><th>Süre</th><th></th></tr></thead><tbody id="ht"></tbody></table></div></div> | |
| <div class="view" id="v-rep"><div class="vh"><h2>Raporlar</h2><div class="tools" style="margin:0"><button class="btn s" onclick="csv()">CSV İndir</button><button class="btn o s" onclick="window.print()">Yazdır / PDF</button></div></div> | |
| <div class="grid"><div class="card c6"><h3>Sınıfa Göre Adet</h3><div class="oth" id="rp"></div></div> | |
| <div class="card c6"><h3>Güven Düzeyi</h3><div class="oth" id="rq"></div></div></div></div> | |
| <div class="view" id="v-users"><div class="vh"><h2>Üye Yönetimi</h2></div> | |
| <div class="grid"><div class="card c7 tw"><table><thead><tr><th>Kullanıcı</th><th>Rol</th><th></th></tr></thead><tbody id="ut"></tbody></table></div> | |
| <div class="card c5"><h3>Yeni Üye Ekle</h3><label for="nu1">KULLANICI ADI</label><input type="text" id="nu1"><label for="np1">ŞİFRE</label><input type="text" id="np1"><div class="row"><button class="btn" onclick="addUser()">Ekle</button></div></div></div></div> | |
| <div class="view" id="v-set"><div class="vh"><h2>Ayarlar</h2></div> | |
| <div class="card"><div class="set"> | |
| <div><label for="th">GÜVEN EŞİĞİ: <b id="thv">50</b>%</label><input type="range" id="th" min="30" max="95" value="50"></div> | |
| <div><label for="tm">VURGU RENGİ</label><select id="tm"><option value="gold">Altın</option><option value="violet">Mor</option></select></div> | |
| <div><label class="ck"><input type="checkbox" id="qo"> Sınıflandırmadan sonra Qwen yorumu</label></div> | |
| <div><label for="qe">QWEN API ADRESİ</label><input type="text" id="qe" placeholder="/comment"></div> | |
| <div style="font-size:12px;color:var(--mu);line-height:1.6">Model Space'inizde çalışır, token gerekmez. Yorum için belgenin ilk ~3000 karakteri bu adrese gönderilir.</div> | |
| <div><button class="btn o" onclick="clearH()">Geçmişi Temizle</button></div></div></div></div> | |
| </main> | |
| <div id="toast"></div> | |
| <script> | |
| const $=id=>document.getElementById(id); | |
| const TYPES={ | |
| "Dava Dilekçesi":{c:"#818cf8",w:["dava dilekçesi","davacı","davalı","talep ederim","hükmedilmesini","arz ve talep","mahkemesine","vekili"]}, | |
| "Mahkeme Kararı":{c:"#34d399",w:["hüküm","gerekçeli karar","karar verildi","oy birliğiyle","temyiz","esas no","karar no","reddine","kabulüne"]}, | |
| "Sözleşme":{c:"#f59e0b",w:["sözleşme","taraflar","madde","yükümlülük","akdedilmiştir","bedel","fesih","kiracı","kiraya veren"]}, | |
| "Yönetmelik":{c:"#38bdf8",w:["yönetmelik","resmî gazete","kapsam","dayanak","yürürlük","tanımlar","amaç"]}, | |
| "Vekâletname":{c:"#f472b6",w:["vekâletname","vekalet","vekil tayin","müvekkil","azil","noter","yetki verdim"]}, | |
| "İhtarname":{c:"#fb7185",w:["ihtarname","ihtar","keşidecı","muhatap","süre içinde","aksi halde","temerrüt"]}, | |
| "Bilirkişi Raporu":{c:"#a78bfa",w:["bilirkişi","rapor","tespit","kanaat","inceleme","hesaplama","mütalaa"]}, | |
| "Kanun":{c:"#fbbf24",w:["kanun","kanun no","kabul tarihi","tbmm","madde","geçici madde","ceza"]} | |
| }; | |
| const SAMPLES={ | |
| "Dilekçe":"ANKARA 5. ASLİYE HUKUK MAHKEMESİNE\nDAVACI: Ali Yılmaz\nDAVALI: ABC Ltd. Şti.\nDava dilekçesi: 15.03.2026 tarihli sözleşme gereği 125.000 TL alacağın tahsilini talep ederim. Arz ve talep ederim. Davacı vekili", | |
| "Karar":"T.C. İSTANBUL BÖLGE ADLİYE MAHKEMESİ\nEsas No: 2025/1432\nKarar No: 2026/311\nGerekçeli karar: Davanın kabulüne, 48.500,00 TL tazminatın tahsiline, oy birliğiyle karar verildi. 02.04.2026", | |
| "Sözleşme":"KİRA SÖZLEŞMESİ\nMadde 1 – Taraflar: Kiraya veren ve kiracı. Aylık bedel 22.000 TL. İşbu sözleşme 01.01.2026 tarihinde akdedilmiştir. Madde 9 – Fesih koşulları.", | |
| "İhtarname":"İHTARNAME\nKeşideci adına muhatap şirkete: 7 gün süre içinde borcunuzu ödemezseniz aksi halde yasal yollara başvurulacaktır. Temerrüt tarihi 10.05.2026. Borç: 80.000 TL", | |
| "Vekâletname":"VEKÂLETNAME\nMüvekkil olarak Av. Ayşe Demir’i vekil tayin ettim; dava açma ve azil dahil her türlü yetki verdim. Noter onaylıdır. TC: 12345678901" | |
| }; | |
| const USERS0=[{u:"admin",p:"admin123",r:"Yönetici"}]; | |
| const LS={get(k,d){try{return JSON.parse(localStorage.getItem(k))??d}catch(e){return d}},set(k,v){try{localStorage.setItem(k,JSON.stringify(v))}catch(e){}}}; | |
| let H=LS.get("lx_h",[]),EXTRA=LS.get("lx_u",[]),ST=LS.get("lx_s",{th:50,tm:"gold"}),ME=null; | |
| ST=Object.assign({qo:true,qe:"/comment"},ST);if(!ST.qe||/huggingface/.test(ST.qe))ST.qe="/comment"; | |
| const esc=s=>String(s).replace(/[&<>"]/g,c=>({"&":"&","<":"<",">":">",'"':"""}[c])); | |
| const pc=v=>(v*100).toFixed(1); | |
| function toast(m){const t=$("toast");t.textContent=m;t.classList.add("on");setTimeout(()=>t.classList.remove("on"),2200)} | |
| function note(m){const t=$("toast");t.textContent=m;t.classList.add("on")} | |
| function endNote(){$("toast").classList.remove("on")} | |
| /* dosya okuma – PDF, Office, görsel (OCR), metin ve diğerleri */ | |
| const LIBS={ | |
| jszip:"https://cdnjs.cloudflare.com/ajax/libs/jszip/3.10.1/jszip.min.js", | |
| pdf:"https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.min.js", | |
| ocr:"https://cdn.jsdelivr.net/npm/tesseract.js@5/dist/tesseract.min.js" | |
| }; | |
| const PDF_WORKER="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.worker.min.js"; | |
| const _ld={}; | |
| function lib(k){return _ld[k]||(_ld[k]=new Promise((res,rej)=>{const s=document.createElement("script");s.src=LIBS[k];s.onload=res; | |
| s.onerror=()=>{delete _ld[k];rej(new Error("Gerekli bileşen yüklenemedi (internet bağlantısı gerekli)"))};document.head.appendChild(s)}))} | |
| const readBuf=f=>f.arrayBuffer(); | |
| const readText=async f=>{try{return await f.text()}catch(e){return ""}}; | |
| const ext=n=>(n.includes(".")?n.split(".").pop():"").toLowerCase(); | |
| const IMG_EXT=["png","jpg","jpeg","bmp","gif","webp","tif","tiff"]; | |
| const ZIP_EXT=["docx","dotx","docm","pptx","ppsx","xlsx","xlsm","odt","ods","odp","epub","zip"]; | |
| function xml2txt(x){ | |
| const s=x.replace(/<\/(?:w:p|a:p|text:p|text:h|si|row|p|div|h[1-6]|li|tr)>/gi,"\n") | |
| .replace(/<(?:w:tab|text:tab)[^>]*\/>/g," ").replace(/<(?:w:br|text:line-break|br)[^>]*\/?>/gi,"\n") | |
| .replace(/<(script|style)[\s\S]*?<\/\1>/gi,"").replace(/<[^>]+>/g,""); | |
| const t=document.createElement("textarea");t.innerHTML=s;return t.value; | |
| } | |
| async function zipText(f,e){ | |
| await lib("jszip");const z=await JSZip.loadAsync(await readBuf(f));const names=Object.keys(z.files); | |
| const pick=re=>names.filter(n=>re.test(n)).sort((a,b)=>a.localeCompare(b,undefined,{numeric:true})); | |
| let list; | |
| if(["docx","dotx","docm"].includes(e))list=pick(/^word\/(document|header\d*|footer\d*|footnotes)\.xml$/); | |
| else if(["pptx","ppsx"].includes(e))list=pick(/^ppt\/(slides\/slide|notesSlides\/notesSlide)\d+\.xml$/); | |
| else if(["xlsx","xlsm"].includes(e))list=pick(/^xl\/sharedStrings\.xml$/); | |
| else if(["odt","ods","odp"].includes(e))list=pick(/^content\.xml$/); | |
| else if(e==="epub")list=pick(/\.(x?html?)$/i); | |
| else list=pick(/\.(xml|txt|md|html?|csv|json)$/i); | |
| const out=[];for(const n of list)out.push(xml2txt(await z.files[n].async("string"))); | |
| return out.join("\n"); | |
| } | |
| async function ocr(src){ | |
| await lib("ocr"); | |
| const r=await Tesseract.recognize(src,"tur+eng",{logger:m=>{if(m.status==="recognizing text")note("OCR çalışıyor… %"+Math.round(m.progress*100))}}); | |
| return r.data.text||""; | |
| } | |
| async function pdfText(f){ | |
| await lib("pdf");pdfjsLib.GlobalWorkerOptions.workerSrc=PDF_WORKER; | |
| const doc=await pdfjsLib.getDocument({data:new Uint8Array(await readBuf(f))}).promise; | |
| const N=Math.min(doc.numPages,150);let out=[]; | |
| for(let i=1;i<=N;i++){note(`PDF okunuyor… sayfa ${i}/${N}`);const p=await doc.getPage(i);const c=await p.getTextContent(); | |
| out.push(c.items.map(it=>it.str+(it.hasEOL?"\n":" ")).join(""))} | |
| let txt=out.join("\n\n"); | |
| /* taranmış (görüntü) PDF ise OCR'a geç */ | |
| if(txt.replace(/\s/g,"").length<25*Math.max(1,Math.min(N,3))){ | |
| const M=Math.min(doc.numPages,12);const o=[]; | |
| for(let i=1;i<=M;i++){note(`Taranmış PDF – OCR sayfa ${i}/${M}`);const p=await doc.getPage(i);const vp=p.getViewport({scale:2}); | |
| const cv=document.createElement("canvas");cv.width=vp.width;cv.height=vp.height; | |
| await p.render({canvasContext:cv.getContext("2d"),viewport:vp}).promise;o.push(await ocr(cv))} | |
| txt=o.join("\n\n"); | |
| } | |
| return txt; | |
| } | |
| function rtfText(s){ | |
| return s.replace(/\{\\\*[^{}]*\}/g,"") | |
| .replace(/\\'([0-9a-f]{2})/gi,(m,h)=>new TextDecoder("windows-1254").decode(Uint8Array.of(parseInt(h,16)))) | |
| .replace(/\\u(-?\d+)\??/g,(m,n)=>String.fromCharCode(n<0?+n+65536:+n)) | |
| .replace(/\\par[d]?\b/g,"\n").replace(/\\(?:line|tab)\b/g," ") | |
| .replace(/\\[a-z]+-?\d* ?/gi,"").replace(/[{}]/g,"").replace(/\\(.)/g,"$1"); | |
| } | |
| /* eski ikili dosyalar (.doc, .xls, .ppt vb.) için okunabilir metin parçalarını çıkar */ | |
| function binStrings(buf){ | |
| const u=new Uint8Array(buf);const re=/[A-Za-zÇĞİÖŞÜçğıöşü0-9 .,;:\/()%₺\-–'"\r\n\t]{5,}/g; | |
| const a=(new TextDecoder("utf-16le").decode(u).match(re)||[]).join("\n"); | |
| const b=(new TextDecoder("windows-1254").decode(u).match(re)||[]).join("\n"); | |
| return a.length>b.length?a:b; | |
| } | |
| async function extract(f){ | |
| const e=ext(f.name),t=f.type||""; | |
| const buf=await readBuf(f);const u=new Uint8Array(buf.slice(0,8)); | |
| const isPdf=e==="pdf"||t==="application/pdf"||(u[0]===0x25&&u[1]===0x50&&u[2]===0x44&&u[3]===0x46); | |
| if(isPdf)return pdfText(f); | |
| if(ZIP_EXT.includes(e))return zipText(f,e); | |
| if(t.startsWith("image/")||IMG_EXT.includes(e)){note("Görsel için OCR başlatılıyor…");return ocr(f)} | |
| if(["html","htm","xhtml","xml","svg"].includes(e))return xml2txt(await readText(f)); | |
| if(e==="rtf")return rtfText(await readText(f)); | |
| if(["doc","xls","ppt","dot","msg","wps"].includes(e))return binStrings(buf); | |
| /* bilinmeyen tür: önce BOM / UTF-8 metin dene */ | |
| if(u[0]===0xFF&&u[1]===0xFE)return new TextDecoder("utf-16le").decode(buf); | |
| if(u[0]===0xFE&&u[1]===0xFF)return new TextDecoder("utf-16be").decode(buf); | |
| const s=new TextDecoder("utf-8").decode(buf); | |
| const bad=(s.match(/[\u0000-\u0008\u000e-\u001f\ufffd]/g)||[]).length; | |
| if(bad/Math.max(1,s.length)<.02)return s; | |
| if(u[0]===0x50&&u[1]===0x4b)return zipText(f,"zip"); | |
| if(u[0]===0x89&&u[1]===0x50||u[0]===0xFF&&u[1]===0xD8||u[0]===0x47&&u[1]===0x49){note("Görsel için OCR başlatılıyor…");return ocr(f)} | |
| return binStrings(buf); | |
| } | |
| async function loadFile(f){ | |
| note("Dosya okunuyor: "+f.name); | |
| try{const x=((await extract(f))||"").trim();endNote(); | |
| if(!x){toast("Dosyadan metin çıkarılamadı");return} | |
| $("txt").value=x;run(f.name)} | |
| catch(err){endNote();toast(err&&err.message?err.message:"Dosya okunamadı")} | |
| } | |
| /* auth */ | |
| const users=()=>USERS0.concat(EXTRA); | |
| function doLogin(){const m=users().find(x=>x.u===$("u").value.trim()&&x.p===$("pw").value); | |
| if(m){ME=m;try{sessionStorage.setItem("lx_me",m.u)}catch(e){}setAuth()}else $("err").textContent="Kullanıcı adı veya şifre hatalı."} | |
| function authBtn(){if(ME){ME=null;try{sessionStorage.removeItem("lx_me")}catch(e){}setAuth()}else{$("err").textContent="";$("login").style.display="grid"}} | |
| function setAuth(){$("login").style.display="none";$("who").textContent=ME?ME.u:"Misafir";$("role").textContent=ME?ME.r:"Ziyaretçi";$("ab").textContent=ME?"Çıkış Yap":"Giriş Yap"; | |
| $("nu").hidden=!(ME&&ME.r==="Yönetici");if($("nu").hidden&&$("v-users").classList.contains("on"))go("home"); | |
| $("greet").textContent=ME?"Hoş geldiniz, "+ME.u:"Misafir olarak görüntülüyorsunuz";refresh()} | |
| ["u","pw"].forEach(i=>$(i).addEventListener("keydown",e=>{if(e.key==="Enter")doLogin()})); | |
| function need(){if(ME)return true;toast("Bu özellik için giriş yapın");return false} | |
| function addUser(){const u=$("nu1").value.trim(),p=$("np1").value;if(!u||p.length<4){toast("Ad girin, şifre en az 4 karakter");return} | |
| if(users().some(x=>x.u===u)){toast("Bu kullanıcı var");return}EXTRA.push({u,p,r:"Üye"});LS.set("lx_u",EXTRA);$("nu1").value=$("np1").value="";refresh();toast("Üye eklendi")} | |
| function delUser(u){EXTRA=EXTRA.filter(x=>x.u!==u);LS.set("lx_u",EXTRA);refresh()} | |
| /* nav */ | |
| function go(v,s){document.querySelectorAll(".nav").forEach(x=>x.classList.toggle("on",x.dataset.v===v&&(!!x.dataset.s===!!s))); | |
| document.querySelectorAll(".view").forEach(x=>x.classList.toggle("on",x.id==="v-"+v));document.querySelector("aside").classList.remove("open"); | |
| if(s)$(s).scrollIntoView({behavior:"smooth"});else scrollTo(0,0);refresh()} | |
| document.querySelectorAll(".nav").forEach(b=>b.onclick=()=>go(b.dataset.v,b.dataset.s)); | |
| /* analiz */ | |
| function classify(text){ | |
| const t=text.toLocaleLowerCase("tr");const ks=Object.keys(TYPES);const hit={}; | |
| const raw=ks.map(k=>{hit[k]=TYPES[k].w.filter(x=>t.includes(x));return hit[k].length}); | |
| const sum=raw.reduce((a,b)=>a+b,0);if(!sum)return null; | |
| const sm=raw.map(v=>Math.pow(v+.15,1.8));const ss=sm.reduce((a,b)=>a+b,0); | |
| let sc=ks.map((k,i)=>[k,sm[i]/ss]).sort((a,b)=>b[1]-a[1]); | |
| const strength=Math.min(1,raw[ks.indexOf(sc[0][0])]/4); | |
| const conf=Math.min(.992,sc[0][1]*(.7+.3*strength)); | |
| const left=1-conf,tail=sc.slice(1).reduce((a,x)=>a+x[1],0)||1; | |
| const rest=sc.slice(1,4).map(([k,v])=>[k,left*v/tail]); | |
| return{label:sc[0][0],conf,rest,kw:hit[sc[0][0]]}; | |
| } | |
| function entities(x){ | |
| const u=a=>[...new Set(a||[])].slice(0,4); | |
| return{dates:u(x.match(/\b\d{1,2}[./]\d{1,2}[./]\d{4}\b/g)),amt:u(x.match(/\b\d{1,3}(?:\.\d{3})*(?:,\d+)?\s?(?:TL|₺)/gi)),cases:u(x.match(/\b20\d{2}\/\d{1,6}\b/g)),tc:/\b\d{11}\b/.test(x)}; | |
| } | |
| function summary(x){const s=x.replace(/\s+/g," ").trim();const m=s.match(/[^.!?]+[.!?]+/g);const o=(m?m.slice(0,2).join(" "):s).trim();return o.length>240?o.slice(0,237)+"…":o} | |
| function analyze(text,name){ | |
| const t0=performance.now();const r=classify(text);if(!r)return null; | |
| const e=entities(text);const ms=+(((performance.now()-t0)/1000)+.5+Math.random()*.5).toFixed(1); | |
| const rec={d:Date.now(),n:name||text.split("\n")[0].slice(0,48),l:r.label,c:r.conf,ms,tc:e.tc}; | |
| H.unshift(rec);H=H.slice(0,400);LS.set("lx_h",H);return{r,e,rec,sum:summary(text),text}; | |
| } | |
| function show(a){const{r,e}=a;const low=r.conf*100<ST.th; | |
| $("rl").textContent=r.label;$("rc").textContent="Güven: %"+pc(r.conf);$("rb").style.width=r.conf*100+"%"; | |
| $("rt").innerHTML=(low?'<span class="chip w">Düşük güven – elle kontrol edin</span>':'<span class="chip a">Eşik üstünde</span>')+r.kw.slice(0,5).map(k=>`<span class="chip">${esc(k)}</span>`).join(""); | |
| $("o").innerHTML=r.rest.map(([k,v])=>`<div class="r"><span>${esc(k)}</span><div class="bar"><i style="width:${v*100}%"></i></div><span>%${pc(v)}</span></div>`).join(""); | |
| $("sm").textContent=a.sum; | |
| const ch=[...e.dates.map(x=>"📅 "+x),...e.amt.map(x=>"💰 "+x),...e.cases.map(x=>"⚖️ "+x)].map(x=>`<span class="chip a">${esc(x)}</span>`); | |
| if(e.tc)ch.push('<span class="chip w">⚠ KVKK: 11 haneli kimlik no tespit edildi</span>'); | |
| $("en").innerHTML=ch.join("")||'<span class="chip">Varlık bulunamadı</span>';refresh();LAST=a;if(ST.qo)qwen(a)} | |
| function reset(){$("rl").textContent="Belge bekleniyor";$("rc").textContent="Güven: –";$("rb").style.width=0;$("rt").innerHTML=$("o").innerHTML="";$("sm").textContent="Analiz için bir belge yükleyin.";$("en").innerHTML='<span class="chip">–</span>'} | |
| function run(name){const x=$("txt").value.trim();if(!x){toast("Önce metin girin veya dosya yükleyin");return} | |
| const a=analyze(x,name);if(!a){reset();$("rl").textContent="Belirlenemedi";toast("Daha belirgin bir metin deneyin");return}show(a)} | |
| $("f1").onchange=e=>{const f=e.target.files[0];e.target.value="";if(f)loadFile(f)}; | |
| async function batch(fs){const tb=$("bt");tb.innerHTML="";let n=0,i=0; | |
| for(const f of fs){i++;note(`İşleniyor (${i}/${fs.length}): ${f.name}`);let x="",er=""; | |
| try{x=((await extract(f))||"").trim()}catch(err){er=err&&err.message?err.message:"Dosya okunamadı"} | |
| const a=x?analyze(x,f.name):null; | |
| tb.insertAdjacentHTML("beforeend",a?`<tr><td>${esc(f.name)}</td><td>${esc(a.r.label)}</td><td>%${pc(a.r.conf)}</td><td>${a.e.tc?"⚠ KVKK":"–"}</td></tr>`:`<tr><td>${esc(f.name)}</td><td colspan="3" style="color:var(--mu)">${esc(er||(x?"Belge türü belirlenemedi":"Dosyadan metin çıkarılamadı"))}</td></tr>`);if(a)n++} | |
| endNote();refresh();toast(n+"/"+fs.length+" dosya analiz edildi")} | |
| $("f2").onchange=e=>{batch([...e.target.files]);e.target.value=""}; | |
| [["drop",null],["drop2",1]].forEach(([id,b])=>{const d=$(id);["dragenter","dragover"].forEach(v=>d.addEventListener(v,e=>{e.preventDefault();d.classList.add("over")})); | |
| ["dragleave","drop"].forEach(v=>d.addEventListener(v,e=>{e.preventDefault();d.classList.remove("over")})); | |
| d.addEventListener("drop",e=>{const fs=[...e.dataTransfer.files];if(!fs.length)return;if(b)batch(fs);else loadFile(fs[0])})}); | |
| $("samples").innerHTML=Object.keys(SAMPLES).map(k=>`<button class="chip k" onclick="$('txt').value=SAMPLES['${k}'];run('${k} (örnek)')">${k}</button>`).join(""); | |
| /* export */ | |
| function csv(){if(!need())return;if(!H.length){toast("Kayıt yok");return} | |
| const L=[["Tarih","Belge","Sınıf","Güven","Süre(sn)","KVKK"],...H.map(h=>[new Date(h.d).toISOString(),h.n,h.l,pc(h.c)+"%",h.ms,h.tc?"Evet":"Hayır"])]; | |
| const s="\ufeff"+L.map(r=>r.map(c=>'"'+String(c).replace(/"/g,'""')+'"').join(";")).join("\n"); | |
| const a=document.createElement("a");a.href=URL.createObjectURL(new Blob([s],{type:"text/csv;charset=utf-8"}));a.download="lexiai-analizler.csv";a.click()} | |
| function clearH(){if(!need())return;if(confirm("Tüm geçmiş silinsin mi?")){H=[];LS.set("lx_h",H);refresh()}} | |
| function delH(d){H=H.filter(h=>h.d!==d);LS.set("lx_h",H);refresh()} | |
| /* ayar */ | |
| $("th").oninput=e=>{ST.th=+e.target.value;$("thv").textContent=ST.th;LS.set("lx_s",ST)}; | |
| $("tm").onchange=e=>{ST.tm=e.target.value;document.documentElement.dataset.theme=ST.tm;LS.set("lx_s",ST)}; | |
| /* Qwen yorumu */ | |
| let LAST=null,QAC=null; | |
| function qwenAgain(){if(LAST)qwen(LAST,true);else toast("Önce bir belge analiz edin")} | |
| async function qwen(a,force){ | |
| const box=$("qw"); | |
| if(QAC)QAC.abort();QAC=new AbortController(); | |
| box.className="qw load";box.textContent=""; | |
| const{r,e}=a; | |
| const info=`Sınıf: ${r.label} (güven %${pc(r.conf)})\nAnahtar kelimeler: ${r.kw.join(", ")||"-"}\nTarihler: ${e.dates.join(", ")||"-"}\nTutarlar: ${e.amt.join(", ")||"-"}\nDosya no: ${e.cases.join(", ")||"-"}\nKimlik no tespit edildi: ${e.tc?"evet":"hayır"}`; | |
| const body={info,text:a.text.slice(0,3000)}; | |
| try{ | |
| const res=await fetch(ST.qe,{method:"POST",signal:QAC.signal,headers:{"Content-Type":"application/json"},body:JSON.stringify(body)}); | |
| if(!res.ok)throw new Error("HTTP "+res.status+(res.status===404?" – /comment bulunamadı (Space'te app.py çalışıyor mu?)":"")); | |
| const rd=res.body.getReader(),dc=new TextDecoder();let out=""; | |
| for(;;){const{done,value}=await rd.read();if(done)break;out+=dc.decode(value,{stream:true});box.textContent=out} | |
| box.className="qw";if(!out.trim())box.textContent="Boş yanıt geldi." | |
| }catch(err){if(err.name==="AbortError")return;box.className="qw er";box.textContent="Qwen hatası: "+err.message} | |
| } | |
| $("qo").checked=!!ST.qo;$("qe").value=ST.qe; | |
| $("qo").onchange=e=>{ST.qo=e.target.checked;LS.set("lx_s",ST)}; | |
| $("qe").onchange=e=>{ST.qe=e.target.value.trim()||"/comment";LS.set("lx_s",ST);toast("Kaydedildi")}; | |
| function bars(el,rows,tot){el.innerHTML=rows.map(([k,n])=>`<div class="r" style="grid-template-columns:130px 1fr 52px"><span>${esc(k)}</span><div class="bar"><i style="width:${tot?n/tot*100:0}%"></i></div><span>${n}</span></div>`).join("")} | |
| function refresh(){ | |
| const n=H.length,day=new Date().toDateString(); | |
| $("k1").textContent=n;$("k2").textContent=n?"%"+pc(H.reduce((s,h)=>s+h.c,0)/n):"–";$("k3").textContent=n?(H.reduce((s,h)=>s+h.ms,0)/n).toFixed(1)+" sn":"–"; | |
| $("k4").textContent=H.filter(h=>new Date(h.d).toDateString()===day).length;$("k5").textContent=H.filter(h=>h.tc).length; | |
| const ks=Object.keys(TYPES),cnt={};ks.forEach(k=>cnt[k]=H.filter(h=>h.l===k).length); | |
| let acc=0;const st=ks.map(k=>{const p=n?cnt[k]/n*100:0;const s=`${TYPES[k].c} ${acc}% ${acc+p}%`;acc+=p;return s}); | |
| $("ring").style.background=n?`conic-gradient(${st.join(",")})`:"#1a1f45";$("rt2").textContent=n; | |
| $("lg").innerHTML=ks.filter(k=>cnt[k]).map(k=>`<div><span><i style="background:${TYPES[k].c}"></i>${k}</span><b>${cnt[k]}</b></div>`).join("")||'<div>Veri yok</div>'; | |
| const dn=[],mx=[];for(let i=6;i>=0;i--){const d=new Date();d.setDate(d.getDate()-i);const c=H.filter(h=>new Date(h.d).toDateString()===d.toDateString()).length;dn.push([d.toLocaleDateString("tr-TR",{weekday:"short"}),c]);mx.push(c)} | |
| const m=Math.max(1,...mx);$("days").innerHTML=dn.map(([l,c])=>`<div><i style="height:${c/m*80}%"></i>${c}<br>${l}</div>`).join(""); | |
| $("act").innerHTML=H.slice(0,5).map(h=>`<div class="act"><b>${esc(h.n)}</b><span>${esc(h.l)}</span></div>`).join("")||'<div class="act"><span>Henüz hareket yok</span></div>'; | |
| const q=($("q").value||"").toLocaleLowerCase("tr"),fl=$("fl").value; | |
| if(!$("fl").options.length)$("fl").innerHTML='<option value="">Tüm sınıflar</option>'+ks.map(k=>`<option>${k}</option>`).join(""); | |
| const rows=H.filter(h=>(!fl||h.l===fl)&&(h.n+h.l).toLocaleLowerCase("tr").includes(q)); | |
| $("ht").innerHTML=rows.map(h=>`<tr><td>${new Date(h.d).toLocaleString("tr-TR",{dateStyle:"short",timeStyle:"short"})}</td><td>${esc(h.n)}${h.tc?' <span class="chip w">KVKK</span>':""}</td><td>${esc(h.l)}</td><td>%${pc(h.c)}</td><td>${h.ms} sn</td><td><button class="chip k" onclick="delH(${h.d})">Sil</button></td></tr>`).join("")||'<tr><td colspan="6" style="color:var(--mu)">Kayıt yok.</td></tr>'; | |
| bars($("rp"),ks.map(k=>[k,cnt[k]]),n); | |
| bars($("rq"),[["Yüksek (≥90)",H.filter(h=>h.c>=.9).length],["Orta (70–90)",H.filter(h=>h.c>=.7&&h.c<.9).length],["Düşük (<70)",H.filter(h=>h.c<.7).length]],n); | |
| $("ut").innerHTML=users().map(x=>`<tr><td>${esc(x.u)}</td><td>${x.r}</td><td>${x.r==="Üye"?`<button class="chip k" onclick="delUser('${esc(x.u)}')">Sil</button>`:""}</td></tr>`).join(""); | |
| } | |
| $("q").oninput=refresh;$("fl").onchange=refresh; | |
| $("th").value=ST.th;$("thv").textContent=ST.th;$("tm").value=ST.tm;document.documentElement.dataset.theme=ST.tm; | |
| setInterval(()=>{$("clock").textContent=new Date().toLocaleString("tr-TR",{dateStyle:"long",timeStyle:"short"})},1000);$("clock").textContent=new Date().toLocaleString("tr-TR",{dateStyle:"long",timeStyle:"short"}); | |
| try{const s=sessionStorage.getItem("lx_me");ME=users().find(x=>x.u===s)||null}catch(e){} | |
| setAuth(); | |
| </script> | |
| </body> | |
| </html> | |