diff --git a/.gitignore b/.gitignore index c84210b1..c31ae07d 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ data/ data1/ mongodb/ NapCat.Framework.Windows.Once/ +NapCat.Framework.Windows.OneKey/ log/ logs/ out/ diff --git a/src/chat/heart_flow/heartFC_chat.py b/src/chat/heart_flow/heartFC_chat.py index 779b6972..82c0289d 100644 --- a/src/chat/heart_flow/heartFC_chat.py +++ b/src/chat/heart_flow/heartFC_chat.py @@ -430,7 +430,7 @@ class HeartFChatting: asyncio.create_task(extract_and_store_jargon(self.stream_id)) # 添加聊天内容概括任务 - 累积、打包和压缩聊天记录 # 注意:后台循环已在start()中启动,这里作为额外触发点,在有思考时立即处理 - asyncio.create_task(self.chat_history_summarizer.process()) + # asyncio.create_task(self.chat_history_summarizer.process()) cycle_timers, thinking_id = self.start_cycle() diff --git a/src/chat/utils/chat_history_summarizer.py b/src/chat/utils/chat_history_summarizer.py index 07553460..abe02022 100644 --- a/src/chat/utils/chat_history_summarizer.py +++ b/src/chat/utils/chat_history_summarizer.py @@ -104,7 +104,6 @@ class ChatHistorySummarizer: if not new_messages: # 没有新消息,检查是否需要打包 - logger.info(f"{self.log_prefix} 无新增消息,尝试对现有批次执行打包检查") if self.current_batch and self.current_batch.messages: await self._check_and_package(current_time) self.last_check_time = current_time @@ -112,10 +111,6 @@ class ChatHistorySummarizer: # 有新消息,更新最后检查时间 self.last_check_time = current_time - - logger.info( - f"{self.log_prefix} 获取到 {len(new_messages)} 条新消息,最新消息时间戳: {new_messages[-1].time if new_messages else 'N/A'}" - ) # 如果有当前批次,添加新消息 if self.current_batch: @@ -123,7 +118,7 @@ class ChatHistorySummarizer: self.current_batch.messages.extend(new_messages) self.current_batch.end_time = current_time logger.info( - f"{self.log_prefix} 扩展现有批次: {before_count} -> {len(self.current_batch.messages)} 条消息,时间范围: {self.current_batch.start_time:.2f} - {self.current_batch.end_time:.2f}" + f"{self.log_prefix} 批次更新: {before_count} -> {len(self.current_batch.messages)} 条消息" ) else: # 创建新批次 @@ -133,7 +128,7 @@ class ChatHistorySummarizer: end_time=current_time, ) logger.info( - f"{self.log_prefix} 创建新批次: 消息数 {len(new_messages)},时间范围: {self.current_batch.start_time:.2f} - {self.current_batch.end_time:.2f}" + f"{self.log_prefix} 新建批次: {len(new_messages)} 条消息" ) # 检查是否需要打包 diff --git a/src/chat/utils/statistic.py b/src/chat/utils/statistic.py index c82c5df8..a9db1518 100644 --- a/src/chat/utils/statistic.py +++ b/src/chat/utils/statistic.py @@ -820,48 +820,70 @@ class StatisticOutputTask(AsyncTask): 统计时段: {start_time.strftime("%Y-%m-%d %H:%M:%S")} ~ {now.strftime("%Y-%m-%d %H:%M:%S")}

-

总在线时间: {_format_online_time(stat_data[ONLINE_TIME])}

-

总消息数: {stat_data[TOTAL_MSG_CNT]}

-

总请求数: {stat_data[TOTAL_REQ_CNT]}

-

总花费: {stat_data[TOTAL_COST]:.2f} ¥

+
+
+
总在线时间
+
{_format_online_time(stat_data[ONLINE_TIME])}
+
+
+
总消息数
+
{stat_data[TOTAL_MSG_CNT]}
+
+
+
总请求数
+
{stat_data[TOTAL_REQ_CNT]}
+
+
+
总花费
+
{stat_data[TOTAL_COST]:.2f} ¥
+
+

按模型分类统计

- - - - {model_rows} - -
模型名称调用次数输入Token输出TokenToken总量累计花费平均耗时(秒)标准差(秒)
+
+ + + + {model_rows} + +
模型名称调用次数输入Token输出TokenToken总量累计花费平均耗时(秒)标准差(秒)
+

按模块分类统计

- - - - - - {module_rows} - -
模块名称调用次数输入Token输出TokenToken总量累计花费平均耗时(秒)标准差(秒)
+
+ + + + + + {module_rows} + +
模块名称调用次数输入Token输出TokenToken总量累计花费平均耗时(秒)标准差(秒)
+

按请求类型分类统计

- - - - - - {type_rows} - -
请求类型调用次数输入Token输出TokenToken总量累计花费平均耗时(秒)标准差(秒)
+
+ + + + + + {type_rows} + +
请求类型调用次数输入Token输出TokenToken总量累计花费平均耗时(秒)标准差(秒)
+

聊天消息统计

- - - - - - {chat_rows_html} - -
联系人/群组名称消息数量
+
+ + + + + + {chat_rows_html} + +
联系人/群组名称消息数量
+

数据分布图表

@@ -1085,21 +1107,22 @@ class StatisticOutputTask(AsyncTask): font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; margin: 0; padding: 20px; - background-color: #f4f7f6; - color: #333; + background-color: #faf7ff; + color: #3a2f57; line-height: 1.6; } .container { max-width: 900px; margin: 20px auto; - background-color: #fff; + background-color: #ffffff; padding: 25px; - border-radius: 8px; - box-shadow: 0 2px 10px rgba(0,0,0,0.1); + border-radius: 10px; + box-shadow: 0 10px 28px rgba(122, 98, 182, 0.12); + border: 1px solid #e5dcff; } h1, h2 { - color: #2c3e50; - border-bottom: 2px solid #3498db; + color: #473673; + border-bottom: 2px solid #9f8efb; padding-bottom: 10px; margin-top: 0; } @@ -1115,33 +1138,62 @@ class StatisticOutputTask(AsyncTask): margin-bottom: 10px; } .info-item { - background-color: #ecf0f1; + background-color: #f3eeff; padding: 8px 12px; - border-radius: 4px; + border-radius: 6px; margin-bottom: 8px; font-size: 0.95em; } .info-item strong { - color: #2980b9; + color: #7162bf; } + /* 新增:顶部工具条与按钮 */ + .toolbar { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 8px; } + .toolbar .right { display: flex; gap: 8px; align-items: center; } + .btn { + border: 1px solid #e3daff; + background-color: #fbf9ff; + color: #4a3c75; + padding: 8px 12px; + border-radius: 6px; + cursor: pointer; + transition: all .2s ease; + } + .btn:hover { border-color: #9f8efb; color: #7c6bcf; background-color: #f1ecff; } + /* 新增:KPI 卡片 */ + .kpi-cards { display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; margin: 12px 0 6px; } + .kpi-card { + background: linear-gradient(145deg, #ffffff 0%, #f6f2ff 100%); + border: 1px solid #e3dbff; + border-radius: 10px; + padding: 14px 16px; + box-shadow: 0 6px 16px rgba(113, 98, 191, 0.1); + } + .kpi-title { font-size: 12px; color: #8579a6; letter-spacing: .3px; margin-bottom: 6px; } + .kpi-value { font-size: 20px; font-weight: 700; letter-spacing: .2px; color: #8b5cf6; } table { width: 100%; border-collapse: collapse; margin-top: 15px; font-size: 0.9em; } + /* 新增:表格包裹容器,支持横向滚动 */ + .table-wrap { width: 100%; overflow-x: auto; border-radius: 6px; } th, td { - border: 1px solid #ddd; + border: 1px solid #e6ddff; padding: 10px; text-align: left; } th { - background-color: #3498db; + background-color: #9f8efb; color: white; font-weight: bold; + position: sticky; + top: 0; + z-index: 1; } tr:nth-child(even) { - background-color: #f9f9f9; + background-color: #f6f1ff; } .footer { text-align: center; @@ -1151,25 +1203,32 @@ class StatisticOutputTask(AsyncTask): } .tabs { overflow: hidden; - background: #ecf0f1; + background: #f9f6ff; display: flex; + border: 1px solid #e4dcff; + border-radius: 10px; + box-shadow: 0 8px 18px rgba(120, 101, 179, 0.08); } .tabs button { background: inherit; border: none; outline: none; - padding: 14px 16px; cursor: pointer; - transition: 0.3s; font-size: 16px; + padding: 12px 14px; cursor: pointer; + transition: 0.2s; font-size: 15px; + color: #52467a; } .tabs button:hover { - background-color: #d4dbdc; + background-color: #efe9ff; } .tabs button.active { - background-color: #b3bbbd; + background-color: rgba(159, 142, 251, 0.25); + color: #6253a9; } .tab-content { display: none; padding: 20px; - background-color: #fff; - border: 1px solid #ccc; + background-color: #fefcff; + border: 1px solid #e4dcff; + border-top: none; + border-radius: 0 0 10px 10px; } .tab-content.active { display: block; @@ -1180,14 +1239,19 @@ class StatisticOutputTask(AsyncTask): """ + f"""
-

MaiBot运行统计报告

-

统计截止时间: {now.strftime("%Y-%m-%d %H:%M:%S")}

+
+

MaiBot运行统计报告

+
+ 统计截止时间: {now.strftime("%Y-%m-%d %H:%M:%S")} +
+
{joined_tab_list}
{joined_tab_content} +
""" + """ @@ -1321,16 +1385,16 @@ class StatisticOutputTask(AsyncTask): # 生成不同颜色的调色板 colors = [ - "#3498db", - "#e74c3c", - "#2ecc71", - "#f39c12", - "#9b59b6", - "#1abc9c", - "#34495e", - "#e67e22", - "#95a5a6", - "#f1c40f", + "#8b5cf6", + "#9f8efb", + "#b5a6ff", + "#c7bbff", + "#d9ceff", + "#a78bfa", + "#9073d8", + "#bfaefc", + "#cabdfd", + "#e6e0ff", ] # 默认使用24小时数据生成数据集 @@ -1512,7 +1576,7 @@ class StatisticOutputTask(AsyncTask): function createChart(chartType, data, timeRange) {{ const config = chartConfigs[chartType]; - const colors = ['#3498db', '#e74c3c', '#2ecc71', '#f39c12', '#9b59b6', '#1abc9c', '#34495e', '#e67e22', '#95a5a6', '#f1c40f']; + const colors = ['#8b5cf6', '#9f8efb', '#b5a6ff', '#c7bbff', '#d9ceff', '#a78bfa', '#9073d8', '#bfaefc', '#cabdfd', '#e6e0ff']; let datasets = [];