قسم الإحصائيات في الصفحة الرئيسية من أكثر الأقسام التي تعكس حيوية المنتدى، فهو يعرض عدد الأعضاء والمواضيع والمساهمات والمتواجدين، لكن تصميمه الافتراضي في النسخة الأخيرة بسيط ولا يبرز هذه الأرقام كما ينبغي. يقدم هذا الموضوع شكلين جديدين لإحصائيات المنتدى بتصميم عصري ومرتب، الشكل الأول يعيد تنظيم الإحصائيات في بطاقات أنيقة، والشكل الثاني يضيف إليها بعض التفاصيل والاختلافات الإضافية. ويمكنك اختيار الشكل الذي يناسب ذوقك وتصميم منتداك.
من لوحة الإدارة توجه إلى: عناصر إضافية ← إدارة أكواد Javascript
أنشئ كودًا جديدًا وحدد وضعه في جميع الصفحات:
طريقة تركيب الشكل الثاني
اذهب إلى التومبلايتات والقوالب، وابحث في قالب index_body عن الجزء الذي يبدأ بـ:
وينتهي بـ:
احذف هذا الجزء كاملًا، واستبدله بالتالي:
ثم اضغط سجّل وانشر القالب.
بهذين الشكلين تتحول الإحصائيات من أرقام جامدة إلى واجهة جذابة تعكس نشاط منتداك بأفضل صورة. كتب الشكل الأول وطوّره العضو Lufy، وطوّر الشكل الثاني العضو كونان2000.
صاحب الكود: Lufy (الشكل الأول) و كونان2000 (الشكل الثاني)
مثال على الكود
شرح تركيب الكود
طريقة تركيب الشكل الأولمن لوحة الإدارة توجه إلى: عناصر إضافية ← إدارة أكواد Javascript
أنشئ كودًا جديدًا وحدد وضعه في جميع الصفحات:
JavaScript:
$(function() {
const config = {
primaryColor: '#007bff',
gradient: 'linear-gradient(45deg, #007bff, #1a9cff)',
textColor: '#343a40',
subtleTextColor: '#6c757d',
cardBg: '#ffffff',
bodyBg: '#f8f9fa',
borderColor: '#dee2e6',
borderRadius: '1rem',
boxShadow: '0 0.5rem 1rem rgba(0, 0, 0, 0.15)'
};
const icons = {
users: `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"></path><circle cx="9" cy="7" r="4"></circle></svg>`,
posts: `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"></path></svg>`,
pm: `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"></path><polyline points="22,6 12,13 2,6"></polyline></svg>`,
latest: `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M16 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"></path><circle cx="9" cy="7" r="4"></circle><line x1="19" x2="19" y1="8" y2="14"></line><line x1="22" x2="16" y1="11" y2="11"></line></svg>`,
online: `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 22c5.523 0 10-4.477 10-10S17.523 2 12 2 2 6.477 2 12s4.477 10 10 10z"></path><path d="m9 12 2 2 4-4"></path></svg>`
};
const generatedStyles = `
body { background-color: ${config.bodyBg} !important; }
#gemini-new-horizon-dashboard {
padding: 20px 15px; max-width: 1280px; margin: 24px auto;
font-family: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
}
.nh-grid {
display: grid;
grid-template-columns: repeat(12, 1fr);
gap: 24px;
}
.nh-card {
background-color: ${config.cardBg}; border-radius: ${config.borderRadius}; box-shadow: ${config.boxShadow};
padding: 24px; border: 1px solid ${config.borderColor};
transition: transform 0.3s ease, box-shadow 0.3s ease;
}
.nh-card:hover { transform: translateY(-5px); box-shadow: 0 1rem 2rem rgba(0, 0, 0, 0.1); }
.nh-card-header { display: flex; align-items: center; gap: 10px; margin-bottom: 20px; color: ${config.subtleTextColor}; font-weight: 500; }
.nh-card-header svg { width: 18px; height: 18px; stroke-width: 2.5px; }
.nh-card-title { font-size: 1.2rem; color: ${config.textColor}; font-weight: 600; }
.welcome-card {
grid-column: span 12; display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 20px;
background: ${config.gradient}; color: white;
}
.welcome-card:hover { transform: translateY(0); box-shadow: ${config.boxShadow}; }
.welcome-content { display: flex; align-items: center; gap: 16px; }
.welcome-avatar { width: 60px; height: 60px; border-radius: 50%; border: 3px solid rgba(255,255,255,0.5); }
.welcome-text h2 { margin: 0; font-size: 2rem; font-weight: 700; }
.welcome-personal-stats { display: flex; align-items: center; gap: 24px; color: color: #1a9cff; }
.personal-stat-item { display: flex; align-items: center; gap: 8px; font-size: 1.1rem; }
.personal-stat-item .value { font-weight: 600; color: white; }
.online-card { grid-column: span 12; }
@media(min-width: 1024px) { .online-card { grid-column: span 8; } }
.online-summary { display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap: 20px; text-align: center; }
.summary-item .value { font-size: 3rem; font-weight: 700; color: ${config.textColor}; line-height: 1; }
.summary-item .label { font-size: 1rem; color: ${config.subtleTextColor}; margin-top: 5px; }
.user-lists-container { border-top: 1px solid ${config.borderColor}; padding-top: 20px; margin-top: 20px; font-size: 1rem; line-height: 1.9; color: ${config.subtleTextColor}; }
.user-lists-container strong { color: ${config.textColor}; }
.user-lists-container a { font-weight: 500; text-decoration: none !important; }
.user-lists-container a:hover { text-decoration: underline !important; }
.user-lists-container .online-user { font-weight: bold !important; }
.group-legend b { display: inline-block; margin: 0 4px; }
.stats-card { grid-column: span 12; }
@media(min-width: 1024px) { .stats-card { grid-column: span 4; } }
.stats-list { display: flex; flex-direction: column; gap: 24px; }
.stat-item { display: flex; align-items: center; gap: 16px; }
.stat-icon {
width: 48px; height: 48px; border-radius: 12px; display: flex; align-items: center; justify-content: center;
background: ${config.primaryColor}1a; color: ${config.primaryColor};
}
.stat-details .value { font-size: 1.5rem; font-weight: 600; color: ${config.textColor}; }
.stat-details .value a { color: ${config.textColor} !important; text-decoration: none; border-bottom: 2px solid transparent; padding-bottom: 2px; transition: border-color 0.2s; }
.stat-details .value a:hover { border-color: ${config.primaryColor}; }
.stat-details .label { font-size: 1rem; color: ${config.subtleTextColor}; }
`;
$('<style type="text/css">').text(generatedStyles).appendTo('head');
const $onlineBlock = $('#block-online');
const $footerBlock = $('#forum-statistics');
if (!$onlineBlock.length || !$footerBlock.length) return;
const onlineHTML = $onlineBlock.html();
const statsHTML = $footerBlock.html();
const safeUserdata = (typeof _userdata !== 'undefined') ? _userdata : {};
const extract = (text, regex) => parseInt(text.match(regex)?.[1]?.replace(/,/g, '') || '0');
const extractHtml = (text, regex) => text.match(regex)?.[1]?.trim() || '';
const parseAndCountUsers = (html) => {
if (!html) return { html: 'لا يوجد', count: 0 };
const allUserLinks = html.match(/<a href="\/u\d+.*?<\/a>/g);
if (!allUserLinks) return { html: 'لا يوجد', count: 0 };
const styledLinks = allUserLinks.map(linkHtml => {
const coloredMatch = linkHtml.match(/<a href="(\/u\d+)">\s*<span style="color:\s*(#[0-9a-fA-F]{6})">\s*<strong>(.*?)<\/strong>/);
if (coloredMatch) return `<a href="${coloredMatch[1]}" class="online-user" style="color: ${coloredMatch[2]} !important;">${coloredMatch[3]}</a>`;
const plainMatch = linkHtml.match(/<a href="(\/u\d+)"[^>]*>(.*?)<\/a>/);
if (plainMatch) {
const tempDiv = document.createElement('div');
tempDiv.innerHTML = plainMatch[2];
return `<a href="${plainMatch[1]}" class="online-user">${tempDiv.innerText || tempDiv.textContent}</a>`;
}
return '';
}).join(', ');
return { html: styledLinks, count: allUserLinks.length };
};
const data = {
loggedIn: safeUserdata.session_logged_in ?? 0,
username: safeUserdata.username ?? 'زائر',
avatar: safeUserdata.avatar_link ?? 'https://2img.net/i/fa/prosilver/icon_user_profile.gif',
userPosts: safeUserdata.user_posts ?? 0,
userPMs: safeUserdata.user_nb_privmsg ?? 0,
onlineTotal: extract(onlineHTML, /<strong>(\d+)<\/strong>\s*عُضو متصل حالياً/),
onlineMembers: extract(onlineHTML, /::\s*(\d+)\s*عُضو/),
onlineGuests: extract(onlineHTML, /و\s*(\d+)\s*زائر/),
onlineUsersHTML: extractHtml(onlineHTML, /الأعضاء المتواجدون في المنتدى\s*: (.*?)(?:<br\s*\/?>\s*<br|الأعضاء الذين تواجدوا)/s),
usersLast24hHTML: extractHtml(onlineHTML, /الأعضاء الذين تواجدوا في 24 ساعة الماضية\.\s*(.*?)(?:<br\s*\/?>\s*<br|لا احد يحتفل)/s),
groupLegend: extractHtml(onlineHTML, /<em>المفتاح : (.*?)<\/em>/s),
totalPosts: extract(statsHTML, /قدموا\s*<strong>(\d+)<\/strong>\s*مساهمة/),
totalMembers: extract(statsHTML, /يتوفر على\s*<strong>(\d+)<\/strong>\s*عُضو/),
latestMember: extractHtml(statsHTML, /آخر عُضو مُسجل هو\s*<strong>(.*?)<\/strong>/s)
};
const onlineUsersResult = parseAndCountUsers(data.onlineUsersHTML);
const users24hResult = parseAndCountUsers(data.usersLast24hHTML);
const calculatedTotal = onlineUsersResult.count + data.onlineGuests;
const $container = $('<div id="gemini-new-horizon-dashboard"></div>');
const $grid = $('<div class="nh-grid"></div>').appendTo($container);
if (data.loggedIn) {
$(`
<div class="nh-card welcome-card">
<div class="welcome-content">
<img src="${data.avatar}" alt="Avatar" class="welcome-avatar">
<div class="welcome-text">
<h2>أهلاً بعودتك، ${data.username}!</h2>
</div>
</div>
<div class="welcome-personal-stats">
<div class="personal-stat-item">${icons.posts}<span class="value" data-counter="${data.userPosts}">0</span><span>مساهمة</span></div>
<div class="personal-stat-item">${icons.pm}<span class="value" data-counter="${data.userPMs}">0</span><span>رسالة خاصة</span></div>
</div>
</div>
`).appendTo($grid);
}
$(`
<div class="nh-card online-card">
<div class="online-summary">
<div class="summary-item">
<div class="value" data-counter="${calculatedTotal}">0</div>
<div class="label">الإجمالي أونلاين</div>
</div>
<div class="summary-item">
<div class="value" data-counter="${onlineUsersResult.count}">0</div>
<div class="label">الأعضاء</div>
</div>
<div class="summary-item">
<div class="value" data-counter="${data.onlineGuests}">0</div>
<div class="label">الزوار</div>
</div>
</div>
<div class="user-lists-container">
<p><strong>الأعضاء المتواجدون:</strong> ${onlineUsersResult.html}</p>
${users24hResult.count > 0 ? `<p><strong>تواجدوا خلال 24 ساعة :</strong> ${users24hResult.html}</p>` : ''}
${data.groupLegend ? `<p class="group-legend"><strong>المفتاح:</strong> ${data.groupLegend}</p>` : ''}
</div>
</div>
`).appendTo($grid);
$(`
<div class="nh-card stats-card">
<div class="nh-card-header"><span class="nh-card-title">إحصائيات المنتدى</span></div>
<div class="stats-list">
<div class="stat-item">
<div class="stat-icon">${icons.posts}</div>
<div class="stat-details">
<div class="value" data-counter="${data.totalPosts}">0</div>
<div class="label">إجمالي المساهمات</div>
</div>
</div>
<div class="stat-item">
<div class="stat-icon">${icons.users}</div>
<div class="stat-details">
<div class="value" data-counter="${data.totalMembers}">0</div>
<div class="label">إجمالي الأعضاء</div>
</div>
</div>
<div class="stat-item">
<div class="stat-icon">${icons.latest}</div>
<div class="stat-details">
<div class="value">${data.latestMember}</div>
<div class="label">أحدث عضو</div>
</div>
</div>
</div>
</div>
`).appendTo($grid);
$onlineBlock.before($container);
$onlineBlock.hide();
$footerBlock.hide();
$container.find('[data-counter]').each(function() {
const $this = $(this);
const target = parseInt($this.data('counter'));
if (!isNaN(target)) {
$this.prop('Counter', 0).animate({
Counter: target
}, {
duration: 2000,
easing: 'swing',
step: function(now) {
$this.text(Math.ceil(now).toLocaleString('ar'));
}
});
}
});
});طريقة تركيب الشكل الثاني
اذهب إلى التومبلايتات والقوالب، وابحث في قالب index_body عن الجزء الذي يبدأ بـ:
HTML:
<!-- BEGIN disable_viewonline -->وينتهي بـ:
HTML:
<!-- END disable_viewonline -->احذف هذا الجزء كاملًا، واستبدله بالتالي:
HTML:
<!-- BEGIN disable_viewonline -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css" /> <style>
.stats-box ul {
margin: 0;
}
span.headline {
position: relative;
top: 12px;
font-size: medium;
}
.action-bar-bottom {
background-color: #30648d;
margin-top: 22px;
margin-bottom: 0;
border-radius: 20px 20px 0px 0px;
}
.action-bar li {
float: left;
margin-bottom: 13px;
margin-right: 0;
margin-left: 22px;
display: inline-block;
top: 12px;
position: relative;
}
.user-bar {
background-color: #0000;
display: block;
margin: 0;
padding: 0;
}
.user-info {
float: right;
display: block;
margin-left: 11px;
vertical-align: sub;
}
.user-info img {
width: 50px;
height: 50px;
border-radius: 50%;
}
.main-container {
display: flex;
gap: 8px;
padding: 0;
flex-wrap: wrap;
flex-direction: row;
}
.stats-box, .online-box {
background-color: #fff9f9;
padding: 20px;
border-radius: 12px;
box-shadow: 0 2px 6px rgba(0,0,0,0.1);
}
.stats-box {
width: 300px;
padding: 3px;
padding-top: 17px;
}
.online-box {
flex: 1;
}
.stats-box h3, .online-box h3 {
margin-bottom: 15px;
}
.stats-box li {
margin-bottom: 10px;
font-size: 16px;
display: flex;
padding: 11px;
}
.stats-box li {
margin-bottom: 10px;
font-size: 16px;
display: flex;
}
.stats-box i {
margin-left: 8px;
color: #0094ff;
}
.online-box .numbers {
display: flex;
justify-content: space-between;
flex-wrap: wrap;
font-size: 14px;
margin-bottom: 10px;
}
.online-box .stat-item {
display: flex;
flex-direction: column;
align-items: center;
font-size: 16px;
}
.online-box .stat-item .value {
font-size: 20px;
font-weight: bold;
color: #0094ff;
}
.online-box hr {
border: 1px solid #ccc;
margin: 10px 0;
}
.member {
color: #0033ff;
font-weight: bold;
}
.key {
display: inline-block;
padding: 2px 6px;
margin: 2px;
border-radius: 4px;
font-family: monospace;
}
.fa-classic, .fa-regular, .fa-solid, .far, .fas {
font-family: "Font Awesome 6 Free";
margin-left: 7px;
color: #2196F3;
}
.stats-h1 strong {
font-size: 18px;
}
.stats-h1 {
font-size: 0;
margin-right: 5px;
}
span.USERS-GROUP {
background: #d3d3d33b;
display: flex;
font-size: 0;
margin: 11px -20px -20px -20px;
padding: 7px;
}
span.USERS-GROUP a {
margin-right: 16px;
border: none;
display: inline;
}
em.fa-solid.fa-eye {
position: relative;
right: 2px;
margin-left: 11px;
}
em.fa-solid.fa-user-plus, em.fa-solid.fa-eye {
margin-left: 6px;
position: relative;
left: 4px;
}
@media (max-width: 800px) {
.online-box {
flex: 1;
}
.stats-box {
width: 100%;
}
}
</style>
<script>
$(function () {
function extractNumbers(text) {
return text.match(/\d+/g);
}
$('.USERS-1').each(function() {
let numbers = extractNumbers($(this).text());
$(this).text(numbers?.[0] ?? '0');
});
$('.USERS-2').each(function() {
let numbers = extractNumbers($(this).text());
$(this).text(numbers?.[1] ?? '0');
});
$('.USERS-3').each(function() {
let numbers = extractNumbers($(this).text());
$(this).text(numbers?.[3] ?? '0');
});
$('.USERS-4').each(function() {
let numbers = extractNumbers($(this).text());
$(this).text(numbers?.[4] ?? '0');
});
});
</script>
<!-- شريط العضو -->
<div class="user-bar">
<ul class="action-bar action-bar-bottom">
<div class="user-info">
<img src="https://2img.net/s/t/20/50/24/i_whosonline.png" alt="صورة العضو" />
</div>
<span class="headline"><a href="{U_VIEWONLINE}" style="color: #fff;" rel="nofollow">{L_WHO_IS_ONLINE}</a></span>
<li>
<a href="{U_TODAY_ACTIVE}">{L_TODAY_ACTIVE}</a>
</li>
<li>
<a href="{U_TODAY_POSTERS}">{L_TODAY_POSTERS}</a>
</li>
<li class="last">
<a href="{U_OVERALL_POSTERS}">{L_OVERALL_POSTERS}</a>
</li>
</ul>
</div>
<!-- المحتوى الرئيسي -->
<div class="main-container">
<!-- إحصائيات الأعضاء والزوار -->
<div class="online-box">
<div class="numbers">
<div class="stat-item">
<div class="value">
<span class="USERS-1">{TOTAL_USERS_ONLINE}</span>
</div>
<div>
الإجمالي أونلاين
</div>
</div>
<div class="stat-item">
<div class="value">
<span class="USERS-2">{TOTAL_USERS_ONLINE}</span>
</div>
<div>
الأعضاء
</div>
</div>
<div class="stat-item">
<div class="value">
<span class="USERS-3">{TOTAL_USERS_ONLINE}</span>
</div>
<div>
الزوار
</div>
</div>
<div class="stat-item">
<div class="value">
<span class="USERS-4">{TOTAL_USERS_ONLINE}</span>
</div>
<div>
محركات البحث
</div>
</div>
</div>
<hr />
{LOGGED_IN_USER_LIST}<br />
{L_ONLINE_USERS}<br />
{L_CONNECTED_MEMBERS} <br />
{L_WHOSBIRTHDAY_TODAY}{L_WHOSBIRTHDAY_WEEK}
<br />
<!-- BEGIN switch_group_legend -->
<span class="USERS-GROUP"> <em>{LEGEND} : {GROUP_LEGEND}</em></span>
<!-- END switch_group_legend -->
</div>
<!-- إحصائيات المنتدى -->
<div class="stats-box">
<h3>
إحصائيات المنتدى
</h3>
<ul>
<li>
<em class="fa-regular fa-comment"> </em> إجمالي المساهمات: <div class="stats-h1">{TOTAL_POSTS} </div>
</li>
<li>
<em class="fa-regular fa-user"> </em> إجمالي الأعضاء: <div class="stats-h1">{TOTAL_USERS} </div>
</li>
<li>
<em class="fa-solid fa-user-plus"> </em> أحدث عضو: <div class="stats-h1">{NEWEST_USER}</div>
</li>
<li>
<em class="fa-solid fa-eye"> </em> أكثر تواجد: <div class="stats-h1">{RECORD_USERS} </div>
</li>
</ul>
</div>
</div>
<!-- END disable_viewonline -->ثم اضغط سجّل وانشر القالب.
بهذين الشكلين تتحول الإحصائيات من أرقام جامدة إلى واجهة جذابة تعكس نشاط منتداك بأفضل صورة. كتب الشكل الأول وطوّره العضو Lufy، وطوّر الشكل الثاني العضو كونان2000.
صاحب الكود: Lufy (الشكل الأول) و كونان2000 (الشكل الثاني)