From 418cc798dfea4af139ddf971a5073312cac7cb51 Mon Sep 17 00:00:00 2001 From: spdis Date: Wed, 4 Mar 2026 19:54:20 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E4=BA=86=E5=9B=BE=E8=A1=A8[0?= =?UTF-8?q?.2.7.2][ci]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- elastic/es_connect.py | 21 ++++++++++ main/templates/main/home.html | 75 +++++++++++++++++++++++++++++++---- 2 files changed, 88 insertions(+), 8 deletions(-) diff --git a/elastic/es_connect.py b/elastic/es_connect.py index cd4e0f7..dcd1a39 100644 --- a/elastic/es_connect.py +++ b/elastic/es_connect.py @@ -589,6 +589,25 @@ def analytics_recent(limit: int = 10, gte: str = None, lte: str = None): pass return "" + def _extract_detail(s: str): + if not s: + return "" + try: + obj = json.loads(s) + if isinstance(obj, dict): + # 尝试获取常见的标题字段 + for key in ["标题", "名称", "项目名称", "成果名称", "软件名称", "专利名称", "获奖名称", "证书名称", "姓名"]: + v = obj.get(key) + if isinstance(v, str) and v: + return v + # 如果没有找到常见标题,尝试获取第一个非"数据类型"的字符串值 + for k, v in obj.items(): + if k != "数据类型" and isinstance(v, str) and v and len(v) < 50: + return v + except Exception: + pass + return "" + search = AchievementDocument.search() body = { "size": max(1, min(limit, 100)), @@ -619,11 +638,13 @@ def analytics_recent(limit: int = 10, gte: str = None, lte: str = None): except Exception: uname = None tval = _extract_type(getattr(hit, 'data', '')) + dval = _extract_detail(getattr(hit, 'data', '')) results.append({ "_id": hit.meta.id, "writer_id": w, "username": uname or "", "type": tval or "", + "detail": dval or "", "time": getattr(hit, 'time', None) }) return results diff --git a/main/templates/main/home.html b/main/templates/main/home.html index 315f619..782f121 100644 --- a/main/templates/main/home.html +++ b/main/templates/main/home.html @@ -67,7 +67,10 @@
-

类型占比(近30天)

+
+

类型占比(近30天)

+ +
@@ -170,19 +173,74 @@ }); } + let typesChartData = []; + let currentChartType = 'pie'; + let typesChartInterval = null; + async function loadTypes(){ const url = '/elastic/analytics/types/?' + qs({ from:'now-30d', to:'now', size:10 }); const res = await fetchJSON(url); if(res.status!=='success') return; const buckets = res.data || []; - const data = buckets.map(b=>({ name: String(b.key||'未知'), value: b.doc_count||0 })); - typesChart.setOption({ - tooltip:{trigger:'item'}, - legend:{type:'scroll'}, - series:[{ type:'pie', radius:['40%','70%'], data }] - }); + typesChartData = buckets.map(b=>({ name: String(b.key||'未知'), value: b.doc_count||0 })); + renderTypesChart(); + startTypesChartRotation(); } + function renderTypesChart() { + if (currentChartType === 'pie') { + typesChart.setOption({ + tooltip:{trigger:'item'}, + legend:{type:'scroll', top:'bottom'}, + grid: { top: 0, bottom: 0, left: 0, right: 0 }, + xAxis: { show: false }, + yAxis: { show: false }, + series:[{ + type:'pie', + radius:['40%','70%'], + center: ['50%', '50%'], + data: typesChartData, + label: { show: false }, + itemStyle: { borderRadius: 10, borderColor: '#fff', borderWidth: 2 } + }] + }, true); + } else { + const names = typesChartData.map(d => d.name); + const values = typesChartData.map(d => d.value); + typesChart.setOption({ + tooltip:{trigger:'axis', axisPointer:{type:'shadow'}}, + legend:{show: false}, + grid: { left: '3%', right: '4%', bottom: '3%', containLabel: true }, + xAxis: { type: 'category', data: names, show: true }, + yAxis: { type: 'value', show: true }, + series: [{ + type: 'bar', + data: values, + itemStyle: { color: '#5470c6' }, + barWidth: '60%' + }] + }, true); + } + } + + function toggleChartType() { + currentChartType = currentChartType === 'pie' ? 'bar' : 'pie'; + renderTypesChart(); + } + + function startTypesChartRotation() { + if (typesChartInterval) clearInterval(typesChartInterval); + typesChartInterval = setInterval(() => { + toggleChartType(); + }, 5000); + } + + document.getElementById('toggleTypesChartBtn').addEventListener('click', () => { + toggleChartType(); + // Reset timer on manual interaction + startTypesChartRotation(); + }); + async function loadTypesTrend(){ const url = '/elastic/analytics/types_trend/?' + qs({ from:'now-180d', to:'now', interval:'week', size:6 }); const res = await fetchJSON(url); @@ -233,7 +291,8 @@ const t = formatTime(it.time); const u = it.username || ''; const ty = it.type || '未知'; - li.textContent = `${t},${u},${ty}`; + const de = it.detail ? `,${it.detail}` : ''; + li.textContent = `${t},${u},${ty}${de}`; listEl.appendChild(li); }); }