v4: кликабельные ссылки на источники и Google News

This commit is contained in:
Ilyas_Dussenov 2026-06-01 05:20:59 +00:00
parent f257eaa273
commit 055a2a3043

View File

@ -57,7 +57,19 @@ body{font:15px/1.6 -apple-system,BlinkMacSystemFont,"Segoe UI",Inter,system-ui,s
.feed-info{flex:1;min-width:0}
.feed-title{font-weight:600;font-size:14px;line-height:1.3;margin-bottom:4px}
.feed-title a{color:var(--text);text-decoration:none}
.feed-title a:hover{color:var(--cyan)}
.feed-title a:hover{color:var(--cyan);text-decoration:underline}
.feed-meta a.src-link{color:var(--blue);text-decoration:none;font-size:12px}
.feed-meta a.src-link:hover{text-decoration:underline}
.feed-item.clickable{cursor:pointer;transition:background .15s;border-radius:8px;margin:0 -8px;padding:12px 8px}
.feed-item.clickable:hover{background:rgba(0,229,255,.04)}
.tl-item.clickable{cursor:pointer;transition:background .15s;border-radius:8px;margin:0 -8px;padding:14px 8px}
.tl-item.clickable:hover{background:rgba(0,229,255,.04)}
.tl-text a{color:var(--text);text-decoration:none}
.tl-text a:hover{color:var(--cyan);text-decoration:underline}
.source-card-link{text-decoration:none;color:inherit;display:block;transition:border-color .15s,transform .15s}
.source-card-link:hover{border-color:var(--cyan)!important;transform:translateY(-2px)}
.feed-item a{z-index:2;position:relative}
.feed-meta{font-size:12px;color:var(--text-dim);display:flex;gap:12px}
.sources-grid{display:grid;grid-template-columns:1fr 1fr;gap:12px}
.source-card{background:var(--bg);border:1px solid var(--border);border-radius:8px;padding:14px}
@ -273,20 +285,30 @@ const COMPANIES = [
const CATEGORIES = ['Экономика','Социальная сфера','Трудовые споры','Экология','Инфраструктура','Кадровые назначения','Финансы','Производство','Транспорт','Безопасность'];
const NEWS_SOURCES = [
{name:'Tengrinews',type:'news'},{name:'Zakon.kz',type:'news'},{name:'Informburo',type:'news'},
{name:'Kapital.kz',type:'news'},{name:'Forbes Kazakhstan',type:'news'},{name:'Orda.kz',type:'news'},
{name:'DKnews',type:'news'},{name:'Baigenews',type:'news'}
{name:'Tengrinews',type:'news',url:'https://tengrinews.kz'},
{name:'Zakon.kz',type:'news',url:'https://www.zakon.kz'},
{name:'Informburo',type:'news',url:'https://informburo.kz'},
{name:'Kapital.kz',type:'news',url:'https://kapital.kz'},
{name:'Forbes Kazakhstan',type:'news',url:'https://forbes.kz'},
{name:'Orda.kz',type:'news',url:'https://orda.kz'},
{name:'DKnews',type:'news',url:'https://dknews.kz'},
{name:'Baigenews',type:'news',url:'https://baigenews.kz'}
];
const SOCIAL_SOURCES = [
{name:'Telegram-каналы',type:'social'},{name:'Facebook',type:'social'},
{name:'Instagram',type:'social'},{name:'X (Twitter)',type:'social'}
{name:'Telegram-каналы',type:'social',url:'https://t.me'},
{name:'Facebook',type:'social',url:'https://facebook.com'},
{name:'Instagram',type:'social',url:'https://instagram.com'},
{name:'X (Twitter)',type:'social',url:'https://x.com'}
];
const GOV_SOURCES = [
{name:'Самрук-Казына (оф. сайт)',type:'gov'},{name:'KASE (биржа)',type:'gov'},
{name:'Правительство РК',type:'gov'},{name:'Минэнерго РК',type:'gov'},
{name:'Минтранс РК',type:'gov'},{name:'Агентство по финмониторингу',type:'gov'}
{name:'Самрук-Казына (оф. сайт)',type:'gov',url:'https://sk.kz'},
{name:'KASE (биржа)',type:'gov',url:'https://kase.kz'},
{name:'Правительство РК',type:'gov',url:'https://www.gov.kz'},
{name:'Минэнерго РК',type:'gov',url:'https://www.gov.kz/memleket/entities/energo'},
{name:'Минтранс РК',type:'gov',url:'https://www.gov.kz/memleket/entities/transport'},
{name:'Агентство по финмониторингу',type:'gov',url:'https://www.gov.kz/memleket/entities/afm'}
];
const ALL_SOURCES = [...NEWS_SOURCES,...SOCIAL_SOURCES,...GOV_SOURCES];
@ -359,32 +381,39 @@ function typeLabel(type){
function renderAll(){
const feed=generateFeed(6);
document.getElementById('feedList').innerHTML=feed.map(f=>`
<div class="feed-item">
document.getElementById('feedList').innerHTML=feed.map(f=>{
const q=encodeURIComponent(f.company||'Самрук-Казына');
const searchUrl='https://news.google.com/search?q='+q+'&hl=ru';
const srcUrl=f.source.url||('https://news.google.com/search?q='+encodeURIComponent(f.source.name+' '+f.company)+'&hl=ru');
return `
<div class="feed-item clickable" data-href="${searchUrl}">
<div class="feed-source ${srcClass(f.type)}">${srcIcon(f.type)}</div>
<div class="feed-info">
<div class="feed-title">${f.text}</div>
<div class="feed-meta"><span>${f.source.name}</span><span>${f.time}</span><span>${f.category}</span></div>
<div class="feed-title"><a href="${searchUrl}" target="_blank" title="Искать в Google News">${f.text}</a></div>
<div class="feed-meta"><a href="${srcUrl}" target="_blank" class="src-link" title="Перейти к источнику">${f.source.name}</a><span>${f.time}</span><span>${f.category}</span></div>
</div>
</div>`).join('');
</div>`}).join('');
const tl=generateTimeline(12);
document.getElementById('timelineList').innerHTML=tl.map(f=>`
<div class="tl-item">
document.getElementById('timelineList').innerHTML=tl.map(f=>{
const q=encodeURIComponent(f.company||'Самрук-Казына');
const searchUrl='https://news.google.com/search?q='+q+'&hl=ru';
return `
<div class="tl-item clickable" data-href="${searchUrl}">
<span class="tl-time">${f.time}</span>
<span class="tl-dot ${priorityDot(f.priority)}"></span>
<div class="tl-content">
<div class="tl-text">${f.text}</div>
<div class="tl-text"><a href="${searchUrl}" target="_blank" title="Искать в Google News">${f.text}</a></div>
<span class="tl-tag ${typeTag(f.type)}">${typeLabel(f.type)}</span>
</div>
</div>`).join('');
</div>`}).join('');
document.getElementById('sourcesGrid').innerHTML=ALL_SOURCES.map(s=>`
<div class="source-card">
<a href="${s.url}" target="_blank" class="source-card source-card-link" title="Перейти на ${s.name}">
<div class="source-name">${srcIcon(s.type)} ${s.name}</div>
<div class="source-status"><span class="dot dot-active"></span> Активен</div>
<div class="source-count">${r(5,50)}</div>
</div>`).join('');
</a>`).join('');
document.getElementById('stat24h').textContent=r(45,120);
document.getElementById('stat24hChange').innerHTML='&#9650; '+r(5,25)+'%';
@ -401,59 +430,74 @@ function renderAll(){
document.getElementById('statCompanies').textContent=COMPANIES.length;
const newsFeed=generateFeed(10).filter(f=>f.type==='news');
document.getElementById('newsTabContent').innerHTML=newsFeed.length?newsFeed.map(f=>`
<div class="feed-item">
document.getElementById('newsTabContent').innerHTML=newsFeed.length?newsFeed.map(f=>{
const q=encodeURIComponent(f.company||'Самрук-Казына');
const searchUrl='https://news.google.com/search?q='+q+'&hl=ru';
const srcUrl=f.source.url||'#';
return `
<div class="feed-item clickable" data-href="${searchUrl}">
<div class="feed-source src-news">📰</div>
<div class="feed-info">
<div class="feed-title">${f.text}</div>
<div class="feed-meta"><span>${f.source.name}</span><span>${f.time}</span><span>${f.category}</span></div>
<div class="feed-title"><a href="${searchUrl}" target="_blank" title="Искать в Google News">${f.text}</a></div>
<div class="feed-meta"><a href="${srcUrl}" target="_blank" class="src-link" title="Перейти к источнику">${f.source.name}</a><span>${f.time}</span><span>${f.category}</span></div>
</div>
</div>`).join(''):'<div class="empty"><div class="empty-icon">📭</div>Нет данных</div>';
</div>`}).join(''):'<div class="empty"><div class="empty-icon">📭</div>Нет данных</div>';
const socFeed=generateFeed(10).filter(f=>f.type==='social');
document.getElementById('socialTabContent').innerHTML=socFeed.length?socFeed.map(f=>`
<div class="feed-item">
document.getElementById('socialTabContent').innerHTML=socFeed.length?socFeed.map(f=>{
const q=encodeURIComponent(f.company||'Самрук-Казына');
const searchUrl='https://news.google.com/search?q='+q+'&hl=ru';
const srcUrl=f.source.url||'#';
return `
<div class="feed-item clickable" data-href="${searchUrl}">
<div class="feed-source src-social">💬</div>
<div class="feed-info">
<div class="feed-title">${f.text}</div>
<div class="feed-meta"><span>${f.source.name}</span><span>${f.time}</span><span>${f.category}</span></div>
<div class="feed-title"><a href="${searchUrl}" target="_blank" title="Искать в Google News">${f.text}</a></div>
<div class="feed-meta"><a href="${srcUrl}" target="_blank" class="src-link" title="Перейти к источнику">${f.source.name}</a><span>${f.time}</span><span>${f.category}</span></div>
</div>
</div>`).join(''):'<div class="empty"><div class="empty-icon">📭</div>Нет данных</div>';
</div>`}).join(''):'<div class="empty"><div class="empty-icon">📭</div>Нет данных</div>';
const govFeed=generateFeed(10).filter(f=>f.type==='gov');
document.getElementById('officialTabContent').innerHTML=govFeed.length?govFeed.map(f=>`
<div class="feed-item">
document.getElementById('officialTabContent').innerHTML=govFeed.length?govFeed.map(f=>{
const q=encodeURIComponent(f.company||'Самрук-Казына');
const searchUrl='https://news.google.com/search?q='+q+'&hl=ru';
const srcUrl=f.source.url||'#';
return `
<div class="feed-item clickable" data-href="${searchUrl}">
<div class="feed-source src-gov">🏛</div>
<div class="feed-info">
<div class="feed-title">${f.text}</div>
<div class="feed-meta"><span>${f.source.name}</span><span>${f.time}</span><span>${f.category}</span></div>
<div class="feed-title"><a href="${searchUrl}" target="_blank" title="Искать в Google News">${f.text}</a></div>
<div class="feed-meta"><a href="${srcUrl}" target="_blank" class="src-link" title="Перейти к источнику">${f.source.name}</a><span>${f.time}</span><span>${f.category}</span></div>
</div>
</div>`).join(''):'<div class="empty"><div class="empty-icon">📭</div>Нет данных</div>';
</div>`}).join(''):'<div class="empty"><div class="empty-icon">📭</div>Нет данных</div>';
document.getElementById('analyticsTabContent').innerHTML=`
<div style="font-size:14px;color:var(--text-dim);margin-bottom:16px">
Всего компаний в периметре мониторинга: <b style="color:var(--text)">${COMPANIES.length}</b>
</div>
<div class="sources-grid" style="grid-template-columns:repeat(3,1fr)">
${COMPANIES.map(c=>`
<div class="source-card">
${COMPANIES.map(c=>{
const q=encodeURIComponent(c);
const searchUrl='https://news.google.com/search?q='+q+'&hl=ru';
return `
<a href="${searchUrl}" target="_blank" class="source-card source-card-link" title="Искать в Google News: ${c}">
<div class="source-name">${c}</div>
<div class="source-status"><span class="dot dot-active"></span> Упоминаний: <b>${r(10,80)}</b></div>
<div style="margin-top:8px;font-size:12px;color:var(--text-dim)">
📰 Новости: ${r(3,20)} &nbsp; 💬 Соцсети: ${r(5,40)} &nbsp; 🏛 Офиц: ${r(1,10)}
</div>
</div>`).join('')}
</a>`}).join('')}
</div>`;
document.getElementById('allSourcesTabContent').innerHTML=`
<div class="sources-grid" style="grid-template-columns:repeat(3,1fr)">
${ALL_SOURCES.map(s=>`
<div class="source-card">
<a href="${s.url}" target="_blank" class="source-card source-card-link" title="Перейти на ${s.name}">
<div class="source-name">${srcIcon(s.type)} ${s.name}</div>
<div class="source-status"><span class="dot dot-active"></span> Мониторинг активен</div>
<div class="source-count">${r(5,50)} упоминаний</div>
<div style="margin-top:6px;font-size:11px;color:var(--text-dim)">Обновлено: ${r(1,59)} мин. назад</div>
</div>`).join('')}
</a>`).join('')}
</div>`;
}
@ -467,6 +511,13 @@ updateClock();
setInterval(()=>{updateClock();},1000);
setInterval(()=>{renderAll();},30000);
document.addEventListener('click',function(e){
const row=e.target.closest('.clickable[data-href]');
if(row&&e.target.tagName!=='A'){
window.open(row.dataset.href,'_blank');
}
});
document.querySelectorAll('.nav-item').forEach(el=>{
el.addEventListener('click',()=>{
document.querySelectorAll('.nav-item').forEach(e=>e.classList.remove('active'));