First Version

This commit is contained in:
aliakbar
2026-06-27 07:52:17 +03:30
commit f3d28cea99
97 changed files with 54562 additions and 0 deletions
@@ -0,0 +1,573 @@
<!DOCTYPE html>
<html lang="fa" dir="rtl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>نمایشگر معیار مقالات</title>
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<script src="https://cdn.tailwindcss.com"></script>
<script>
tailwind.config = {
theme: {
extend: {
colors: {
primary: {
50: '#eff6ff',
100: '#dbeafe',
200: '#bfdbfe',
300: '#93c5fd',
400: '#60a5fa',
500: '#3b82f6',
600: '#2563eb',
700: '#1d4ed8',
800: '#1e40af',
900: '#1e3a8a',
},
secondary: {
50: '#f0fdf4',
100: '#dcfce7',
200: '#bbf7d0',
300: '#86efac',
400: '#4ade80',
500: '#22c55e',
600: '#16a34a',
700: '#15803d',
800: '#166534',
900: '#14532d',
},
accent: {
50: '#fdf2f8',
100: '#fce7f3',
200: '#fbcfe8',
300: '#f9a8d4',
400: '#f472b6',
500: '#ec4899',
600: '#db2777',
700: '#be185d',
800: '#9d174d',
900: '#831843',
}
},
fontFamily: {
'vazir': ['Vazir', 'Tahoma', 'sans-serif'],
},
boxShadow: {
'soft': '0 4px 20px rgba(0, 0, 0, 0.08)',
'medium': '0 8px 30px rgba(0, 0, 0, 0.12)',
'hard': '0 15px 50px rgba(0, 0, 0, 0.2)',
},
animation: {
'float': 'float 6s ease-in-out infinite',
'glow': 'glow 2s ease-in-out infinite alternate',
},
keyframes: {
float: {
'0%, 100%': { transform: 'translateY(0)' },
'50%': { transform: 'translateY(-10px)' },
},
glow: {
'0%': { boxShadow: '0 0 5px rgba(59, 130, 246, 0.5)' },
'100%': { boxShadow: '0 0 20px rgba(59, 130, 246, 0.8)' },
}
}
}
}
}
</script>
<style>
@import url('https://fonts.googleapis.com/css2?family=Vazir&display=swap');
body {
font-family: 'Vazir', Tahoma, sans-serif;
}
/* استایل زیبا برای select با نمایش چند گزینه */
select[size] {
background-image: none;
padding: 0.5rem;
}
select[size] option {
padding: 0.75rem 1rem;
border-bottom: 1px solid #f3f4f6;
cursor: pointer;
transition: all 0.2s ease;
}
select[size] option:hover {
background-color: #eff6ff;
}
select[size] option:checked {
background-color: #3b82f6;
color: white;
}
/* گرادیان های زیبا */
.gradient-bg {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}
.gradient-card {
background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
}
.gradient-success {
background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
}
.gradient-danger {
background: linear-gradient(135deg, #fa709a 0%, #fee140 100%);
}
/* انیمیشن های اضافی */
@keyframes slideIn {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.animate-slide-in {
animation: slideIn 0.5s ease-out;
}
/* استایل برای اسکرول بار زیبا */
select[size]::-webkit-scrollbar {
width: 6px;
}
select[size]::-webkit-scrollbar-track {
background: #f1f5f9;
border-radius: 10px;
}
select[size]::-webkit-scrollbar-thumb {
background: #cbd5e1;
border-radius: 10px;
}
select[size]::-webkit-scrollbar-thumb:hover {
background: #94a3b8;
}
</style>
</head>
<body class="font-vazir bg-gradient-to-br from-blue-50 to-indigo-100 min-h-screen">
<div class="container mx-auto px-4 py-8">
<!-- هدر زیبا -->
<header class="text-center mb-12 animate-slide-in">
<div class="inline-block p-1 rounded-2xl bg-gradient-to-r from-primary-500 to-accent-500 mb-6 shadow-hard">
<div class="bg-white rounded-xl py-4 px-8">
<h1 class="text-4xl font-bold bg-gradient-to-r from-primary-600 to-accent-600 bg-clip-text text-transparent">
<i class="fas fa-file-alt text-primary-500 mr-3"></i>
نمایشگر معیار مقالات
</h1>
</div>
</div>
<p class="text-xl text-gray-600 max-w-2xl mx-auto leading-relaxed">
ابزاری پیشرفته برای ارزیابی و نمایش معیارهای مقالات علمی با قابلیت‌های تحلیلی کامل
</p>
</header>
<!-- کارت بارگذاری فایل -->
<div class="max-w-4xl mx-auto mb-8 animate-slide-in" style="animation-delay: 0.1s;">
<div class="bg-white rounded-2xl shadow-soft overflow-hidden border border-gray-100 transition-all duration-300 hover:shadow-medium">
<div class="p-1 bg-gradient-to-r from-primary-500 to-accent-500">
<div class="bg-white rounded-xl p-6">
<h2 class="text-2xl font-bold text-gray-800 mb-6 flex items-center">
<i class="fas fa-folder-open text-primary-500 ml-3 text-xl"></i>
بارگذاری فایل داده
</h2>
<div class="mb-4">
<label for="fileInput" class="block text-lg font-medium text-gray-700 mb-3">فایل JSON حاوی اطلاعات مقالات</label>
<div class="border-2 border-dashed border-gray-300 rounded-xl p-8 text-center transition-all duration-300 hover:border-primary-400 hover:bg-primary-50 cursor-pointer">
<input type="file" id="fileInput" accept=".json" class="absolute top-0 right-0 w-full h-full opacity-0 cursor-pointer" />
<div class="flex flex-col items-center justify-center">
<i class="fas fa-cloud-upload-alt text-4xl text-primary-500 mb-4"></i>
<span class="text-xl font-medium text-gray-700">برای بارگذاری فایل JSON اینجا کلیک کنید</span>
<p class="text-gray-500 mt-2">یا فایل را به این منطقه بکشید و رها کنید</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- کارت انتخاب مقاله -->
<div class="max-w-4xl mx-auto mb-8 hidden" id="articleSelectionCard">
<div class="bg-white rounded-2xl shadow-soft overflow-hidden border border-gray-100 transition-all duration-300 hover:shadow-medium">
<div class="p-1 bg-gradient-to-r from-secondary-500 to-primary-500">
<div class="bg-white rounded-xl p-6">
<h2 class="text-2xl font-bold text-gray-800 mb-6 flex items-center">
<i class="fas fa-book text-secondary-500 ml-3 text-xl"></i>
انتخاب مقاله
</h2>
<div class="mb-4">
<label for="articleSelect" class="block text-lg font-medium text-gray-700 mb-3">مقاله مورد نظر</label>
<select
id="articleSelect"
size="6"
class="w-full border-2 border-gray-300 rounded-xl p-2 focus:border-primary-500 focus:ring-2 focus:ring-primary-200 transition-all duration-300 bg-white shadow-sm"
>
<option value="" disabled selected>لطفا مقاله را انتخاب کنید</option>
</select>
<p class="text-sm text-gray-500 mt-2">حداقل 6 مقاله به طور همزمان نمایش داده می‌شود</p>
</div>
</div>
</div>
</div>
</div>
<!-- کارت اطلاعات مقاله -->
<div class="max-w-4xl mx-auto mb-8 hidden" id="articleInfoCard">
<div class="bg-white rounded-2xl shadow-soft overflow-hidden border border-gray-100 transition-all duration-300 hover:shadow-medium">
<div class="p-1 bg-gradient-to-r from-accent-500 to-purple-500">
<div class="bg-white rounded-xl p-6">
<h2 class="text-2xl font-bold text-gray-800 mb-6 flex items-center">
<i class="fas fa-info-circle text-accent-500 ml-3 text-xl"></i>
اطلاعات مقاله
</h2>
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<div class="info-item">
<div class="info-label text-lg font-bold text-primary-600 mb-2 flex items-center">
<i class="fas fa-file-signature ml-2"></i>
نام مقاله
</div>
<div class="info-value bg-gray-50 p-4 rounded-xl border-r-4 border-primary-500 min-h-[60px] flex items-center text-gray-700" id="articleName">-</div>
</div>
<div class="info-item">
<div class="info-label text-lg font-bold text-primary-600 mb-2 flex items-center">
<i class="fas fa-university ml-2"></i>
نام مجموعه
</div>
<div class="info-value bg-gray-50 p-4 rounded-xl border-r-4 border-primary-500 min-h-[60px] flex items-center text-gray-700" id="articleInstitute">-</div>
</div>
<div class="info-item md:col-span-2">
<div class="info-label text-lg font-bold text-primary-600 mb-2 flex items-center">
<i class="fas fa-align-left ml-2"></i>
چکیده
</div>
<div class="info-value bg-gray-50 p-4 rounded-xl border-r-4 border-primary-500 min-h-[100px] text-gray-700 leading-relaxed" id="articleAbstract">-</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- کارت انتخاب معیار -->
<div class="max-w-4xl mx-auto mb-8 hidden" id="measureSelectionCard">
<div class="bg-white rounded-2xl shadow-soft overflow-hidden border border-gray-100 transition-all duration-300 hover:shadow-medium">
<div class="p-1 bg-gradient-to-r from-yellow-500 to-orange-500">
<div class="bg-white rounded-xl p-6">
<h2 class="text-2xl font-bold text-gray-800 mb-6 flex items-center">
<i class="fas fa-tasks text-yellow-500 ml-3 text-xl"></i>
انتخاب معیار
</h2>
<div class="mb-4">
<label for="responseIndexSelect" class="block text-lg font-medium text-gray-700 mb-3">شماره معیار مورد نظر</label>
<select
id="responseIndexSelect"
size="6"
class="w-full border-2 border-gray-300 rounded-xl p-2 focus:border-primary-500 focus:ring-2 focus:ring-primary-200 transition-all duration-300 bg-white shadow-sm"
>
<option value="" disabled selected>لطفا معیار را انتخاب کنید</option>
</select>
<p class="text-sm text-gray-500 mt-2">حداقل 6 معیار به طور همزمان نمایش داده می‌شود</p>
</div>
</div>
</div>
</div>
</div>
<!-- کارت جزئیات معیار -->
<div class="max-w-6xl mx-auto mb-8 hidden" id="measuresCard">
<div class="bg-white rounded-2xl shadow-soft overflow-hidden border border-gray-100 transition-all duration-300 hover:shadow-medium">
<div class="p-1 bg-gradient-to-r from-green-500 to-blue-500">
<div class="bg-white rounded-xl p-6">
<h2 class="text-2xl font-bold text-gray-800 mb-6 flex items-center">
<i class="fas fa-chart-bar text-green-500 ml-3 text-xl"></i>
جزئیات معیار
</h2>
<div class="grid grid-cols-1 lg:grid-cols-2 gap-8">
<!-- معیار مطلوب -->
<div class="measure-box p-6 rounded-2xl bg-gradient-to-br from-green-50 to-blue-50 border-t-4 border-green-500 shadow-soft transition-all duration-300 hover:shadow-medium">
<div class="measure-header flex items-center mb-6">
<div class="w-12 h-12 rounded-full bg-green-100 flex items-center justify-center mr-4">
<i class="fas fa-thumbs-up text-green-600 text-xl"></i>
</div>
<div>
<div class="measure-title font-bold text-xl text-gray-800">معیار مطلوب</div>
<div class="text-green-600 text-sm">Positive Measure</div>
</div>
</div>
<div class="measure-content mb-5">
<div class="info-label font-bold text-green-700 mb-2 flex items-center">
<i class="fas fa-ruler ml-2"></i>
معیار:
</div>
<div class="info-value bg-white p-4 rounded-xl border border-green-200 text-gray-700 min-h-[80px] shadow-sm" id="posMeasure">-</div>
</div>
<div class="measure-content mb-5">
<div class="info-label font-bold text-green-700 mb-2 flex items-center">
<i class="fas fa-comment-dots ml-2"></i>
پاسخ:
</div>
<div class="info-value bg-white p-4 rounded-xl border border-green-200 text-gray-700 min-h-[80px] shadow-sm" id="posResponse">-</div>
</div>
<div class="measure-content">
<div class="info-label font-bold text-green-700 mb-2 flex items-center">
<i class="fas fa-star ml-2"></i>
امتیاز رعایت:
</div>
<div class="score inline-flex items-center px-4 py-2 rounded-full text-white font-bold text-lg bg-gradient-to-r from-green-500 to-green-600 shadow-md" id="posScore">-</div>
</div>
</div>
<!-- معیار معکوس -->
<div class="measure-box p-6 rounded-2xl bg-gradient-to-br from-red-50 to-pink-50 border-t-4 border-red-500 shadow-soft transition-all duration-300 hover:shadow-medium">
<div class="measure-header flex items-center mb-6">
<div class="w-12 h-12 rounded-full bg-red-100 flex items-center justify-center mr-4">
<i class="fas fa-thumbs-down text-red-600 text-xl"></i>
</div>
<div>
<div class="measure-title font-bold text-xl text-gray-800">معیار معکوس</div>
<div class="text-red-600 text-sm">Negative Measure</div>
</div>
</div>
<div class="measure-content mb-5">
<div class="info-label font-bold text-red-700 mb-2 flex items-center">
<i class="fas fa-ruler ml-2"></i>
معیار:
</div>
<div class="info-value bg-white p-4 rounded-xl border border-red-200 text-gray-700 min-h-[80px] shadow-sm" id="negMeasure">-</div>
</div>
<div class="measure-content mb-5">
<div class="info-label font-bold text-red-700 mb-2 flex items-center">
<i class="fas fa-comment-dots ml-2"></i>
پاسخ:
</div>
<div class="info-value bg-white p-4 rounded-xl border border-red-200 text-gray-700 min-h-[80px] shadow-sm" id="negResponse">-</div>
</div>
<div class="measure-content">
<div class="info-label font-bold text-red-700 mb-2 flex items-center">
<i class="fas fa-star ml-2"></i>
امتیاز رعایت:
</div>
<div class="score inline-flex items-center px-4 py-2 rounded-full text-white font-bold text-lg bg-gradient-to-r from-red-500 to-red-600 shadow-md" id="negScore">-</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- وضعیت خالی -->
<div class="max-w-2xl mx-auto" id="emptyState">
<div class="bg-white rounded-2xl shadow-soft overflow-hidden border border-gray-100 p-8 text-center">
<div class="w-24 h-24 rounded-full bg-gradient-to-r from-primary-100 to-accent-100 flex items-center justify-center mx-auto mb-6 animate-float">
<i class="fas fa-file-import text-4xl text-primary-500"></i>
</div>
<h3 class="text-2xl font-bold text-gray-800 mb-4">هنوز فایلی بارگذاری نشده است</h3>
<p class="text-gray-600 text-lg mb-6">لطفاً یک فایل JSON حاوی اطلاعات مقالات را بارگذاری کنید</p>
<div class="w-16 h-1 bg-gradient-to-r from-primary-500 to-accent-500 rounded-full mx-auto"></div>
</div>
</div>
<!-- فوتر -->
<footer class="text-center mt-12 pt-8 border-t border-gray-200">
<p class="text-gray-600">
نمایشگر معیار مقالات - طراحی شده با
<i class="fas fa-heart text-red-500 mx-1 animate-pulse"></i>
و قدرت Tailwind CSS
</p>
<div class="flex justify-center space-x-4 space-x-reverse mt-4">
<div class="w-2 h-2 rounded-full bg-primary-500"></div>
<div class="w-2 h-2 rounded-full bg-secondary-500"></div>
<div class="w-2 h-2 rounded-full bg-accent-500"></div>
</div>
</footer>
</div>
<script>
let articles = [];
document.getElementById('fileInput').addEventListener('change', function (e) {
const file = e.target.files[0];
if (!file) return;
// نمایش وضعیت بارگذاری
document.getElementById('emptyState').classList.add('hidden');
const loadingHTML = `
<div class="text-center py-12">
<div class="w-16 h-16 border-4 border-primary-500 border-t-transparent rounded-full animate-spin mx-auto mb-4"></div>
<p class="text-lg text-gray-700">در حال بارگذاری و پردازش فایل...</p>
</div>
`;
// ذخیره المنت اصلی قبل از جایگزینی
const articleSelectionCard = document.getElementById('articleSelectionCard');
const originalContent = articleSelectionCard.innerHTML;
articleSelectionCard.innerHTML = loadingHTML;
articleSelectionCard.classList.remove('hidden');
const reader = new FileReader();
reader.onload = function (e) {
try {
articles = JSON.parse(e.target.result);
setTimeout(() => {
// بازگرداندن محتوای اصلی
articleSelectionCard.innerHTML = originalContent;
populateArticleDropdown();
document.getElementById('emptyState').classList.add('hidden');
}, 800);
} catch (err) {
alert("خطا در خواندن فایل JSON: " + err.message);
resetUI();
}
};
reader.onerror = function() {
alert("خطا در خواندن فایل");
resetUI();
};
reader.readAsText(file);
});
function resetUI() {
document.getElementById('emptyState').classList.remove('hidden');
document.getElementById('articleSelectionCard').classList.add('hidden');
document.getElementById('articleInfoCard').classList.add('hidden');
document.getElementById('measureSelectionCard').classList.add('hidden');
document.getElementById('measuresCard').classList.add('hidden');
}
function populateArticleDropdown() {
const select = document.getElementById('articleSelect');
if (!select) {
console.error("Element with ID 'articleSelect' not found!");
return;
}
// حذف گزینه پیش‌فرض
select.innerHTML = '';
if (articles.length === 0) {
const option = document.createElement('option');
option.textContent = 'مقاله‌ای یافت نشد';
option.disabled = true;
select.appendChild(option);
return;
}
articles.forEach((article, index) => {
const option = document.createElement('option');
option.value = index;
// ایجاد متن قابل نمایش برای مقاله
const articleId = article["article id"] !== undefined ? article["article id"] : index;
const articleName = article["article name"] || 'بدون نام';
option.textContent = `مقاله ${1 + articleId}: ${articleName}`;
select.appendChild(option);
});
// تنظیم event listener برای تغییر انتخاب
select.addEventListener('change', () => {
const idx = select.value;
if (articles[idx]) {
loadArticle(articles[idx]);
}
});
// انتخاب و نمایش اولین مقاله به صورت پیش‌فرض
if (articles.length > 0) {
select.selectedIndex = 0;
loadArticle(articles[0]);
}
}
function loadArticle(article) {
// نمایش کارت اطلاعات مقاله
document.getElementById('articleInfoCard').classList.remove('hidden');
document.getElementById('articleName').textContent = article["article name"] || 'نامشخص';
document.getElementById('articleInstitute').textContent = article["article institute"] || 'نامشخص';
document.getElementById('articleAbstract').textContent = article["article abstract"] || 'چکیده‌ای موجود نیست';
const responseCount = Math.max(
article.measures_positive?.length || 0,
article.responses_positive?.length || 0,
article.scores_positive?.length || 0
);
const responseSelect = document.getElementById('responseIndexSelect');
if (!responseSelect) {
console.error("Element with ID 'responseIndexSelect' not found!");
return;
}
// حذف گزینه‌های قبلی
responseSelect.innerHTML = '';
for (let i = 0; i < responseCount; i++) {
const option = document.createElement('option');
option.value = i;
option.textContent = `معیار ${i + 1}`;
responseSelect.appendChild(option);
}
// تنظیم event listener برای تغییر انتخاب معیار
responseSelect.addEventListener('change', () => {
const i = parseInt(responseSelect.value);
displayResponse(article, i);
});
// نمایش کارت انتخاب معیار
document.getElementById('measureSelectionCard').classList.remove('hidden');
if (responseCount > 0) {
// انتخاب اولین معیار به صورت پیش‌فرض
responseSelect.selectedIndex = 0;
displayResponse(article, 0);
document.getElementById('measuresCard').classList.remove('hidden');
} else {
// اگر معیاری وجود ندارد
const option = document.createElement('option');
option.textContent = 'معیاری یافت نشد';
option.disabled = true;
responseSelect.appendChild(option);
document.getElementById('measuresCard').classList.add('hidden');
}
}
function displayResponse(article, i) {
const posMeasure = article.measures_positive?.[i] || 'معیاری تعریف نشده';
const posResponse = article.responses_positive?.[i] || 'پاسخی موجود نیست';
const posScore = article.scores_positive?.[i] !== undefined ? article.scores_positive?.[i] : 'نامشخص';
const negMeasure = article.measures_negative?.[i] || 'معیاری تعریف نشده';
const negResponse = article.responses_negative?.[i] || 'پاسخی موجود نیست';
const negScore = article.scores_negative?.[i] !== undefined ? article.scores_negative?.[i] : 'نامشخص';
document.getElementById('posMeasure').innerHTML = marked.parse(posMeasure);
document.getElementById('posResponse').innerHTML = marked.parse(posResponse);
document.getElementById('posScore').textContent = posScore;
document.getElementById('negMeasure').innerHTML = marked.parse(negMeasure);
document.getElementById('negResponse').innerHTML = marked.parse(negResponse);
document.getElementById('negScore').textContent = negScore;
}
</script>
</body>
</html>