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 @@
@@ -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);
});
}