| HTML |
|---|
<!-- فونت وزیر --> <link href="https://cdn.jsdelivr.net/gh/rastikerdar/vazir-font@v30.1.0/dist/font-face.css" rel="stylesheet" type="text/css" /> <h1 style="text-align:center; font-family:Vazir, Tahoma; color:#333; font-weight:600;">مستندات:700; margin-top:10px;"> مستندات اعتبار بخشی<بخشی </h1> <!-- ردیف جستجو و فیلترها --> <div id="search-filters" style=" display:flex; justify-content:center; flex-wrap:wrap; gap:10px; margin:30px 0; direction:rtl; "> <input type="text" id="search" placeholder="جستجو بر اساس عنوان" style=" style="flex:1 1 300px320px; max-width:400px420px; padding:10px 15px; border:none; background:#f3f3f3; min-width:220px; padding:10px 16px; border:none; background:#f7f1f5; border-radius:30px; font-size:14px; outline:none; text-align:right; font-family:Vazir, Tahoma; min-width:150px;"> <select id color:#333; " > <select id="filter-mahvar" style=" flex:0 1 150px170px; padding:10px 15px; border-radius:25px; border:1px solid #ccc#e2b6cf; font-family:Vazir, Tahoma; font-size:14px; background:#fff; cursor:pointer; "> <option value="">انتخاب محور</option> </select> <select id="filter-zirmohvar" style=" flex:0 1 150px170px; padding:10px 15px; border-radius:25px; border:1px solid #ccc#e2b6cf; font-family:Vazir, Tahoma; font-size:14px; background:#fff; cursor:pointer; "> <option value="">انتخاب زیرمحور</option> </select> </div> <!-- کانتینر سه بخش --> <div <select id="sectionsfilter-noe-containersanad" style="padding flex:0 40px1 60px170px; direction:rtl;"></div> <!-- پیام وقتی چیزی پیدا نشد --> <div id="no-result" style="display:none; text-align:center; color:#b40074; font-weight:600; font-size:16px; margin-top:20px;"> هیچ سندی پیدا نشد. </div> <style> .card { padding:10px 15px; border-radius:25px; border:1px solid #e2b6cf; font-family:Vazir, Tahoma; font-size:14px; background:#fff; border-radius:18px; box-shadow:0 4px 10px rgba(0,0,0,0.1); padding:20px; display:flex; align-items:center; justify-content:space-between; flex-direction:row-reverse; font-family:Vazir, Tahoma; transition:all 0.3s ease; } .card-content { flex:1; text-align:right; padding-right:15px; } .card-content h3 { margin:0 0 8px; font-weight:600; font-size:14px; color:#333; } .card-content ul { margin:0; padding-right:15px; list-style:disc; font-size:13px; color:#555; } .open-btn { display:inline-block; background:#00A9C3; color:#fff; border:none; border-radius:25px; padding:4px 18px; font-size:13px; text-decoration:none; margin-top:12px; cursor:pointer; } .open-btn:hover { background:#0090a8; } .card-icon { background:#f7f7f7; border-radius:16px; padding:12px; display:flex; align-items:center; justify-content:center; } .card-icon img { width:2cm; height:2cm; } .card:hover { transform:scale(1.03); background:#fdfdfd; } @media(max-width:900px){ .section-grid{grid-template-columns:1fr;} #search-filters { flex-direction:column; align-items:center; } #search-filters input, #search-filters select { flex:1 1 auto; max-width:300px; } } </style> <script> const pageId = "92538739"; const fileName = "form-data.json"; let docs = []; const sections = [ { title: "رهبری و مدیریت", value: "رهبری و مدیریت" }, { title: "مراقبت و درمان", value: "مراقبت و درمان" }, { title: "حمایت از گیرنده خدمت", value: "حمایت از گیرنده خدمت" } ]; // زیرمحورها const zirmohvarOptions = { "رهبری و مدیریت": [ "رهبری و مدیریت کیفیت", "مدیریت خطر، حوادث و بلایا", "مدیریت منابع انسانی و سلامت حرفهای", "مدیریت خدمات پرستاری", "فناوری و مدیریت اطلاعات سلامت", "بهداشت محیط", "مدیریت تجهیزات پزشکی" ], "مراقبت و درمان": [ "مراقبتهای عمومی بالینی", "مراقبتهای حاد و اورژانس", "مراقبتهای جراحی و بیهوشی", "مراقبتهای مادر و نوزاد", "پیشگیری و کنترل عفونت", "مدیریت دارویی", "خدمات تصویربرداری", "خدمات آزمایشگاه", "طب انتقال خون", "خدمات سرپایی" ], "حمایت از گیرنده خدمت": [ "تأمین تسهیلات برای گیرنده خدمت", "احترام به حقوق گیرنده خدمت" ] }; // آیکنها const sanadIcons = { "آیین نامه": "https://kb.h-soft.ir/download/thumbnails/85045112/%D8%A7%DB%8C%DB%8C%D9%86%20%D9%86%D8%A7%D9%85%D9%87.png?api=v2&nonce=1765664452835", "پروتکل": "https://kb.h-soft.ir/download/thumbnails/85045112/%D9%BE%D8%B1%D9%88%D8%AA%DA%A9%D9%84.png?api=v2&nonce=1765664452833", "خطمشی و روش": "https://kb.h-soft.ir/download/thumbnails/85045112/%D8%AE%D8%B7%20%D9%85%D8%B4%DB%8C.png?api=v2&nonce=1765664452830", "دستورالعمل": "https://kb.h-soft.ir/download/thumbnails/85045112/%D8%AF%D8%B3%D8%AA%D9%88%D8%B1%D8%A7%D9%84%D8%B9%D9%85%D9%84.png?api=v2&nonce=1765664452829", "راهنما": "https://kb.h-soft.ir/download/thumbnails/85045112/%D8%B1%D8%A7%D9%87%D9%86%D9%85%D8%A7.png?api=v2&nonce=1765664452826", "روش اجرایی": "https://kb.h-soft.ir/download/thumbnails/85045112/%D8%B1%D9%88%D8%B4%20%D8%A7%D8%AC%D8%B1%D8%A7%DB%8C%DB%8C.png?api=v2&nonce=1765664452825", "سند": "https://kb.h-soft.ir/download/thumbnails/85045112/%D8%B3%D9%86%D8%AF.png?api=v2&nonce=1765664452823", "فلوچارت": "https://kb.h-soft.ir/download/thumbnails/85045112/%D9%81%D9%84%D9%88%DA%86%D8%A7%D8%B1%D8%AA.png?api=v2&nonce=1765664452822", "کتابچه": "https://kb.h-soft.ir/download/thumbnails/85045112/%DA%A9%D8%AA%D8%A7%D8%A8%DA%86%D9%87.png?api=v2&nonce=1765664452819" }; // نرمالسازی نوع سند function normalizeSanadType(type){ if (!type) return ""; return type .trim() .replace(/\u200c/g, " ") // حذف نیمفاصله .replace(/\s+/g, " ") // یکسانسازی فاصلهها .toLowerCase(); } // تشخیص هوشمند آیکن function detectSanadIcon(type){ const t = normalizeSanadType(type); if (t.includes("آیین")) return sanadIcons["آیین نامه"]; if (t.includes("پروتکل")) return sanadIcons["پروتکل"]; if (t.includes("خط مشی")) return sanadIcons["خطمشی و روش"]; if (t.includes("دستورالعمل")) return sanadIcons["دستورالعمل"]; if (t.includes("راهنما")) return sanadIcons["راهنما"]; if (t.includes("روش اجرایی")) return sanadIcons["روش اجرایی"]; if (t.includes("فلوچارت")) return sanadIcons["فلوچارت"]; if (t.includes("کتابچه")) return sanadIcons["کتابچه"]; return sanadIcons["سند"]; } // دریافت JSON async function loadJSON(){ const attRes = await fetch(`/rest/api/content/${pageId}/child/attachment`, { credentials: "include" }); const attData = await attRes.json(); const file = attData.results.find(a => a.title === fileName); if (!file) return; const downloadUrl = new URL(file._links.download, window.location.origin).href; const jsonText = await fetch(downloadUrl, { credentials:"include" }).then(r => r.text()); docs = JSON.parse(jsonText); populateMahvarFilter(); renderSections(); } // فیلتر محور function populateMahvarFilter(){ const sel = document.getElementById("filter-mahvar"); sections.forEach(s => { const o = document.createElement("option"); o.value = s.value; o.textContent = s.title; sel.appendChild(o); }); } // فیلتر زیرمحور function updateZirmohvarFilter(){ const mahvar = document.getElementById("filter-mahvar").value; const sel = document.getElementById("filter-zirmohvar"); sel.innerHTML = '<option value="">انتخاب زیرمحور</option>'; (zirmohvarOptions[mahvar] || []).forEach(z => { const o = document.createElement("option"); o.value = z; o.textContent = z; sel.appendChild(o); }); } // کارت // تابع دریافت لینک فایل از Confluence function getAttachmentUrl(fileName) { if (!fileName) return null; return `/download/attachments/${pageId}/${encodeURIComponent(fileName)}?api=v2`; } // کارت function createCard(doc){ const card = document.createElement("div"); card.className = "card"; const fileUrl = getAttachmentUrl(doc.document_file_name); // لینک واقعی فایل const iconUrl = detectSanadIcon(doc.noe_sanad); card.innerHTML = ` <div class="card-content"> <h3><b>${doc.document_name || doc.title || ""}</b></h3> <ul> <li>زیرمحور: ${doc.zirmohvar || "-"}</li> <li>نوع سند: ${doc.noe_sanad || "-"}</li> <li>شماره استاندارد: ${doc.standard_no || "-"}</li> <li>تاریخ آخرین بازنگری: ${doc.date || "-"}</li> </ul> ${ fileUrl ? `<a href="${fileUrl}" target="_blank" class="open-btn">مشاهده</a>` : `<span class="open-btn" style="background:#ccc;cursor:not-allowed">فایل ندارد</span>` } </div> <div class="card-icon"> <img src="${iconUrl}" alt="سند"> </div> `; return card; } // رندر کل بخشها بدون تغییر function renderSections(){ const searchText = document.getElementById("search").value.toLowerCase(); const m = document.getElementById("filter-mahvar").value; const z = document.getElementById("filter-zirmohvar").value; const container = document.getElementById("sections-container"); container.innerHTML = ""; let found = false; sections.forEach(sec => { const list = docs.filter(d => d.mahvar === sec.value && (!searchText || ((d.document_name || d.title || "").toLowerCase().includes(searchText))) && (!m || d.mahvar === m) && (!z || d.zirmohvar === z) ); if(!list.length) return; found = true; const grid = document.createElement("div"); grid.className = "section-grid"; grid.style.display = "grid"; grid.style.gridTemplateColumns = "repeat(2,1fr)"; grid.style.gap = "20px"; [...list].reverse().forEach(d => grid.appendChild(createCard(d))); const h2 = document.createElement("h2"); h2.style.textAlign = "center"; h2.textContent = sec.title; const hr = document.createElement("hr"); hr.style.border = "3px solid #b40074"; hr.style.width = "80px"; hr.style.margin = "0 auto 20px"; container.append(h2, hr, grid); }); cursor:pointer; "> <option value="">همه نوع سندها</option> <option value="دستورالعمل">دستورالعمل</option> <option value="خطمشی و روش">خطمشی و روش</option> <option value="روش اجرایی">روش اجرایی</option> <option value="فلوچارت">فلوچارت</option> <option value="آییننامه">آییننامه</option> <option value="راهنما">راهنما</option> <option value="پروتکل">پروتکل</option> <option value="کتابچه">کتابچه</option> <option value="سند">سند</option> </select> </div> <div id="cards-loading" style=" display:none; font-family:Vazir, Tahoma; direction:rtl; text-align:center; color:#bd2b76; padding:15px; font-weight:600; "> در حال بارگذاری مستندات... </div> <div id="sections-container" style="padding:0 35px 60px; direction:rtl;"></div> <div id="no-result" style=" display:none; text-align:center; color:#bd2b76; font-weight:700; font-size:16px; margin-top:20px; font-family:Vazir, Tahoma; "> هیچ سندی پیدا نشد. </div> <style> @font-face { font-family: "Vazir"; src: url("/download/attachments/92538739/Vazir-Regular.woff2") format("woff2"); } :root{ --pink-main:#bd2b76; --pink-dark:#a82466; --pink-soft:#fff5fb; --pink-soft-2:#fdebf4; --pink-border:#f1c7dc; --text-main:#333; --text-sub:#555; --gray-soft:#f7f7f7; } #sections-container, #search-filters, #cards-loading, #no-result{ font-family:Vazir, Tahoma !important; } .section-title-docs{ text-align:center; color:var(--text-main); margin-top:35px; margin-bottom:8px; font-size:18px; font-weight:700; } .section-hr-docs{ border:none; height:4px; width:86px; margin:0 auto 20px; background:var(--pink-main); border-radius:20px; } .section-grid{ display:grid; grid-template-columns:repeat(2,1fr); gap:20px; margin-bottom:8px; } .card{ background:#fff; border:1px solid var(--pink-border); border-radius:20px; box-shadow:0 4px 14px rgba(0,0,0,0.08); padding:20px; display:flex; align-items:center; justify-content:space-between; flex-direction:row-reverse; transition:all .25s ease; min-height:155px; } .card:hover{ transform:translateY(-2px); box-shadow:0 8px 20px rgba(0,0,0,0.10); background:var(--pink-soft); } .card-content{ flex:1; text-align:right; padding-right:14px; } .card-content h3{ margin:0 0 10px; font-size:15px; font-weight:700; color:var(--text-main); line-height:1.9; } .card-content ul{ margin:0; padding-right:18px; list-style:disc; font-size:13px; color:var(--text-sub); line-height:2; } .card-icon{ background:var(--gray-soft); border-radius:18px; padding:12px; display:flex; align-items:center; justify-content:center; flex-shrink:0; border:1px solid #f0f0f0; } .card-icon img{ width:2cm; height:2cm; object-fit:contain; } .open-btn{ display:inline-block; background:var(--pink-main); color:#fff; border:none; border-radius:24px; padding:6px 18px; font-size:13px; text-decoration:none; margin-top:12px; cursor:pointer; font-family:Vazir, Tahoma; transition:all .2s ease; } .open-btn:hover{ background:var(--pink-dark); } .open-btn.disabled{ background:#cfcfcf !important; color:#fff !important; cursor:not-allowed !important; } .show-more-btn{ display:block; margin:18px 0 35px auto; padding:8px 26px; background:transparent; color:var(--pink-main); border:2px solid var(--pink-main); border-radius:25px; font-family:Vazir, Tahoma; font-size:14px; cursor:pointer; transition:all .25s ease; } .show-more-btn:hover{ background:var(--pink-main); color:#fff; } @media (max-width: 900px){ .section-grid{ grid-template-columns:1fr; } #search-filters{ flex-direction:column; align-items:center; } #search-filters input, #search-filters select{ width:100%; max-width:320px; } #sections-container{ padding:0 15px 50px !important; } } @font-face { font-family: "Vazir"; src: url("/download/attachments/92538739/Vazir-Regular.woff2") format("woff2"); font-weight: 400; font-style: normal; font-display: swap; } /* اعمال فونت وزیر روی کل بخش */ #sv-root, #sv-root *, #search-filters, #search-filters *, #sections-container, #sections-container *, #cards-loading, #cards-loading *, #no-result, #no-result * { font-family: "Vazir", Tahoma, Arial, sans-serif !important; } </style> <script> const pageId = "92538739"; const fileName = "form-data.json"; let docs = []; const sections = [ { title: "رهبری و مدیریت", value: "رهبری و مدیریت" }, { title: "مراقبت و درمان", value: "مراقبت و درمان" }, { title: "حمایت از گیرنده خدمت", value: "حمایت از گیرنده خدمت" } ]; const zirmohvarOptions = { "رهبری و مدیریت": [ "رهبری و مدیریت کیفیت", "مدیریت خطر، حوادث و بلایا", "مدیریت منابع انسانی و سلامت حرفهای", "مدیریت خدمات پرستاری", "فناوری و مدیریت اطلاعات سلامت", "بهداشت محیط", "مدیریت تجهیزات پزشکی" ], "مراقبت و درمان": [ "مراقبتهای عمومی بالینی", "مراقبتهای حاد و اورژانس", "مراقبتهای جراحی و بیهوشی", "مراقبتهای مادر و نوزاد", "پیشگیری و کنترل عفونت", "مدیریت دارویی", "خدمات تصویربرداری", "خدمات آزمایشگاه", "طب انتقال خون", "خدمات سرپایی" ], "حمایت از گیرنده خدمت": [ "تأمین تسهیلات برای گیرنده خدمت", "احترام به حقوق گیرنده خدمت" ] }; const sanadIcons = { "آییننامه": "https://kb.h-soft.ir/download/thumbnails/92538739/%D8%A7%DB%8C%DB%8C%D9%86%20%D9%86%D8%A7%D9%85%D9%87.png?api=v2", "پروتکل": "https://kb.h-soft.ir/download/thumbnails/92538739/%D9%BE%D8%B1%D9%88%D8%AA%DA%A9%D9%84.png?api=v2", "خطمشی و روش": "https://kb.h-soft.ir/download/thumbnails/92538739/%D8%AE%D8%B7%20%D9%85%D8%B4%DB%8C.png?api=v2", "دستورالعمل": "https://kb.h-soft.ir/download/thumbnails/92538739/%D8%AF%D8%B3%D8%AA%D9%88%D8%B1%D8%A7%D9%84%D8%B9%D9%85%D9%84.png?api=v2", "راهنما": "https://kb.h-soft.ir/download/thumbnails/92538739/%D8%B1%D8%A7%D9%87%D9%86%D9%85%D8%A7.png?api=v2", "روش اجرایی": "https://kb.h-soft.ir/download/thumbnails/92538739/%D8%B1%D9%88%D8%B4%20%D8%A7%D8%AC%D8%B1%D8%A7%DB%8C%DB%8C.png?api=v2", "سند": "https://kb.h-soft.ir/download/thumbnails/92538739/%D8%B3%D9%86%D8%AF.png?api=v2", "فلوچارت": "https://kb.h-soft.ir/download/thumbnails/92538739/%D9%81%D9%84%D9%88%DA%86%D8%A7%D8%B1%D8%AA.png?api=v2", "کتابچه": "https://kb.h-soft.ir/download/thumbnails/92538739/%DA%A9%D8%AA%D8%A7%D8%A8%DA%86%D9%87.png?api=v2" }; function normalizeDigits(str) { const fa = "۰۱۲۳۴۵۶۷۸۹"; const ar = "٠١٢٣٤٥٦٧٨٩"; return String(str || "") .replace(/[۰-۹]/g, d => String(fa.indexOf(d))) .replace(/[٠-٩]/g, d => String(ar.indexOf(d))); } function normalizeText(v) { return normalizeDigits(v) .trim() .replace(/ي/g, "ی") .replace(/ك/g, "ک") .replace(/ۀ/g, "ه") .replace(/ة/g, "ه") .replace(/ؤ/g, "و") .replace(/إ/g, "ا") .replace(/أ/g, "ا") .replace(/آ/g, "ا") .replace(/\u200c/g, " ") .replace(/[ـ]/g, "") .replace(/[()()]/g, " ") .replace(/\s+/g, " ") .toLowerCase(); } function sameText(a, b) { return normalizeText(a) === normalizeText(b); } function looseTextMatch(a, b) { const aa = normalizeText(a); const bb = normalizeText(b); if (!aa || !bb) return false; return aa === bb || aa.includes(bb) || bb.includes(aa); } function safeText(v) { return String(v || "") .replace(/&/g, "&") .replace(/</g, "<") .replace(/>/g, ">"); } function getField(obj, keys) { if (!obj) return ""; for (const k of keys) { if (Object.prototype.hasOwnProperty.call(obj, k)) { const val = obj[k]; if (val !== undefined && val !== null && String(val).trim() !== "") { return String(val).trim(); } } } return ""; } function getDocTitle(doc) { return getField(doc, ["document_name", "documentName", "title", "name", "عنوان سند", "عنوان", "نام سند"]); } function getDocMahvarRaw(doc) { return getField(doc, ["mahvar", "محور", "mainAxis", "main_axis", "axis"]); } function getDocZirmohvar(doc) { return getField(doc, ["zirmohvar", "zirMohvar", "zir_mohvar", "subAxis", "sub_axis", "زیرمحور", "زیر محور"]); } function getDocNoeSanad(doc) { return getField(doc, ["noe_sanad", "noeSanad", "type", "document_type", "نوع سند", "نوع"]); } function getDocStandardNo(doc) { return getField(doc, ["standard_no", "standardNo", "document_no", "documentNo", "shomare_sanad", "شماره استاندارد", "شماره سند", "شماره"]); } function getDocDate(doc) { return getField(doc, ["date", "review_date", "last_review_date", "lastUpdate", "last_update", "تاریخ آخرین بازنگری", "تاریخ آخرین بروزرسانی", "تاریخ"]); } function getDocPageId(doc) { return getField(doc, ["pageId", "page_id", "createdPageId", "created_page_id", "confluencePageId", "contentId", "content_id"]); } function getDocPageUrl(doc) { return getField(doc, ["pageUrl", "page_url", "createdPageUrl", "created_page_url", "viewUrl", "view_url", "url", "link", "pageLink"]); } function getDocFileUrl(doc) { return getField(doc, ["fileUrl", "file_url", "pdfUrl", "pdf_url", "attachmentUrl", "attachment_url", "downloadUrl", "download_url"]); } function getDocBase64(doc) { return getField(doc, ["file_base64", "base64", "pdf_base64", "fileBase64"]); } function resolveMahvar(doc) { const rawMahvar = getDocMahvarRaw(doc); const zirmohvar = getDocZirmohvar(doc); const directSection = sections.find(sec => looseTextMatch(rawMahvar, sec.value)); if (directSection) return directSection.value; for (const sec of sections) { const list = zirmohvarOptions[sec.value] || []; if (list.some(z => looseTextMatch(zirmohvar, z))) { return sec.value; } } for (const sec of sections) { const list = zirmohvarOptions[sec.value] || []; if (list.some(z => looseTextMatch(rawMahvar, z))) { return sec.value; } } return rawMahvar; } function detectSanadIcon(type) { const t = normalizeText(type); if (t.includes("ایین")) return sanadIcons["آیین نامه"]; if (t.includes("پروتکل")) return sanadIcons["پروتکل"]; if (t.includes("خط مشی")) return sanadIcons["خطمشی و روش"]; if (t.includes("دستورالعمل")) return sanadIcons["دستورالعمل"]; if (t.includes("راهنما")) return sanadIcons["راهنما"]; if (t.includes("روش اجرایی")) return sanadIcons["روش اجرایی"]; if (t.includes("فلوچارت")) return sanadIcons["فلوچارت"]; if (t.includes("کتابچه")) return sanadIcons["کتابچه"]; return sanadIcons["سند"]; } function toAbsoluteUrl(url) { url = String(url || "").trim(); if (!url) return ""; if (/^https?:\/\//i.test(url)) return url; if (url.startsWith("/")) return location.origin + url; return location.origin + "/" + url; } function getBestViewUrl(doc) { const pageUrl = getDocPageUrl(doc); if (pageUrl) return toAbsoluteUrl(pageUrl); const docPageId = getDocPageId(doc); if (docPageId) { return location.origin + "/pages/viewpage.action?pageId=" + encodeURIComponent(docPageId); } const fileUrl = getDocFileUrl(doc); if (fileUrl) return toAbsoluteUrl(fileUrl); return ""; } function base64ToPdfBlob(base64) { const cleaned = String(base64 || "") .replace(/^data:.*;base64,/, "") .replace(/\s/g, ""); const binary = atob(cleaned); const len = binary.length; const buffer = new ArrayBuffer(len); const view = new Uint8Array(buffer); for (let i = 0; i < len; i++) { view[i] = binary.charCodeAt(i); } return new Blob([buffer], { type: "application/pdf" }); } function openPdfFromRecord(base64) { if (!base64) { alert("فایل در JSON موجود نیست."); return; } try { const blob = base64ToPdfBlob(base64); const url = URL.createObjectURL(blob); window.open(url, "_blank"); setTimeout(() => URL.revokeObjectURL(url), 60000); } catch (e) { console.error(e); alert("خطا در باز کردن فایل. احتمالاً فایل ذخیرهشده معتبر نیست."); } } function openDocument(doc) { const bestUrl = getBestViewUrl(doc); if (bestUrl) { window.open(bestUrl, "_blank"); return; } const base64 = getDocBase64(doc); if (base64) { openPdfFromRecord(base64); return; } alert("برای این سند نه صفحه ثبت شده، نه لینک فایل، نه فایل داخل JSON موجود است."); } async function loadJSON() { const loading = document.getElementById("cards-loading"); try { if (loading) loading.style.display = "block"; const res = await fetch(`/rest/api/content/${pageId}/child/attachment?filename=${encodeURIComponent(fileName)}&cb=${Date.now()}`, { credentials: "include", headers: { Accept: "application/json" }, cache: "no-store" }); const data = await res.json(); if (!data.results || !data.results.length) { docs = []; populateMahvarFilter(); renderSections(); if (loading) loading.style.display = "none"; return; } const downloadUrl = toAbsoluteUrl(data.results[0]._links.download); const joiner = downloadUrl.includes("?") ? "&" : "?"; const txt = await fetch(downloadUrl + joiner + "cb=" + Date.now(), { credentials: "include", cache: "no-store" }).then(r => r.text()); docs = JSON.parse(txt || "[]"); if (!Array.isArray(docs)) docs = []; populateMahvarFilter(); renderSections(); } catch (e) { console.error("خطا در خواندن JSON:", e); docs = []; populateMahvarFilter(); renderSections(); } finally { if (loading) loading.style.display = "none"; } } function populateMahvarFilter() { const sel = document.getElementById("filter-mahvar"); if (sel.dataset.loaded === "1") return; sections.forEach(s => { const o = document.createElement("option"); o.value = s.value; o.textContent = s.title; sel.appendChild(o); }); sel.dataset.loaded = "1"; } function updateZirmohvarFilter() { const mahvar = document.getElementById("filter-mahvar").value; const sel = document.getElementById("filter-zirmohvar"); sel.innerHTML = '<option value="">انتخاب زیرمحور</option>'; if (!mahvar) return; const foundKey = Object.keys(zirmohvarOptions).find(k => sameText(k, mahvar)); const list = foundKey ? zirmohvarOptions[foundKey] : []; list.forEach(z => { const o = document.createElement("option"); o.value = z; o.textContent = z; sel.appendChild(o); }); } function createCard(doc, docIndex) { const card = document.createElement("div"); card.className = "card"; const title = getDocTitle(doc); const zirmohvar = getDocZirmohvar(doc); const noeSanad = getDocNoeSanad(doc); const standardNo = getDocStandardNo(doc); const date = getDocDate(doc); const iconUrl = detectSanadIcon(noeSanad); const hasView = !!getBestViewUrl(doc) || !!getDocBase64(doc); card.innerHTML = ` <div class="card-content"> <h3><b>${safeText(title || "")}</b></h3> <ul> <li>زیرمحور: ${safeText(zirmohvar || "-")}</li> <li>نوع سند: ${safeText(noeSanad || "-")}</li> <li>شماره استاندارد: ${safeText(standardNo || "-")}</li> <li>تاریخ آخرین بازنگری: ${safeText(date || "-")}</li> </ul> ${ hasView ? `<button type="button" class="open-btn" data-doc-index="${docIndex}">مشاهده</button>` : `<span class="open-btn" style="background:#ccc;cursor:not-allowed">لینک ندارد</span>` } </div> <div class="card-icon"> <img src="${iconUrl}" alt="سند"> </div> `; const btn = card.querySelector(".open-btn[data-doc-index]"); if (btn) { btn.addEventListener("click", function () { const i = Number(this.dataset.docIndex); if (!Number.isNaN(i) && docs[i]) { openDocument(docs[i]); } }); } return card; } function toggleSection(sectionKey, btn) { const hiddenCards = document.querySelectorAll(`.card[data-section-key="${sectionKey}"].hidden-card`); const isOpen = btn.dataset.open === "1"; if (isOpen) { hiddenCards.forEach(card => { card.style.display = "none"; }); btn.textContent = "مشاهده بیشتر"; btn.dataset.open = "0"; } else { hiddenCards.forEach(card => { card.style.display = "flex"; }); btn.textContent = "بستن"; btn.dataset.open = "1"; } } function renderSections() { const searchText = document.getElementById("search").value; const selectedMahvar = document.getElementById("filter-mahvar").value; const selectedZirmohvar = document.getElementById("filter-zirmohvar").value; const selectedNoeSanad = document.getElementById("filter-noe-sanad").value; const container = document.getElementById("sections-container"); container.innerHTML = ""; let found = false; sections.forEach(sec => { const list = docs .map((doc, index) => ({ doc, index })) .filter(item => { const d = item.doc; const title = getDocTitle(d); const resolvedMahvar = resolveMahvar(d); const zirmohvar = getDocZirmohvar(d); const noeSanad = getDocNoeSanad(d); return ( sameText(resolvedMahvar, sec.value) && (!searchText || normalizeText(title).includes(normalizeText(searchText))) && (!selectedMahvar || sameText(resolvedMahvar, selectedMahvar)) && (!selectedZirmohvar || looseTextMatch(zirmohvar, selectedZirmohvar)) && (!selectedNoeSanad || looseTextMatch(noeSanad, selectedNoeSanad)) ); }); if (!list.length) return; found = true; const h2 = document.createElement("h2"); h2.className = "section-title-docs"; h2.textContent = sec.title; const hr = document.createElement("hr"); hr.className = "section-hr-docs"; const grid = document.createElement("div"); grid.className = "section-grid"; const reversedList = [...list].reverse(); const sectionKey = normalizeText(sec.value).replace(/\s+/g, "-"); reversedList.forEach((item, displayIndex) => { const card = createCard(item.doc, item.index); card.setAttribute("data-section-key", sectionKey); if (displayIndex >= 4) { card.classList.add("hidden-card"); card.style.display = "none"; } grid.appendChild(card); }); container.append(h2, hr, grid); if (reversedList.length > 4) { const btn = document.createElement("button"); btn.className = "show-more-btn"; btn.textContent = "مشاهده بیشتر"; btn.dataset.open = "0"; btn.onclick = function () { toggleSection(sectionKey, this); }; container.appendChild(btn); } }); document.getElementById("no-result").style.display = found ? "none" : "block"; } // رویدادها document.getElementById("search").addEventListener("input", renderSections); document.getElementById("filter-mahvar").addEventListener("change", () => { updateZirmohvarFilter(); renderSections(); }); document.getElementById("filter-zirmohvar").addEventListener("change", renderSections); document.getElementById("filter-noe-sanad").addEventListener("change", renderSections); loadJSON(); </script> |
Page History
Overview
Content Tools
Apps
Tasks