完成了LLM的适配,DIfy暂时不用

This commit is contained in:
pengGgxp 2025-05-01 18:14:28 +08:00
parent ec4cb87ed7
commit 365b8a488c
21 changed files with 4757 additions and 260 deletions

View File

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-#
# -------------------------------------------------------------------------------
# Name: utils.py
# Name: api_utils.py
# Description:
# Author: xaoyaoo
# Date: 2023/12/03

View File

View File

@ -0,0 +1,14 @@
# 接入dify工作流,用来制作微信聊天记录可视化
class Dify(object):
def __init__(self):
api_key = ""
api_base_url = ""
#TODO: 文件上传
def file_upload(self):
pass
#TODO: 运行工作流
def run_workflows(self):
pass

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@ -161,12 +161,12 @@ def export_json_mini_time_limit(wxid, outpath, db_config, my_wxid="我",
start_part = start_createtime.replace(" ", "_").replace(":", "-") if start_createtime else "all"
end_part = end_createtime.replace(" ", "_").replace(":", "-") if end_createtime else "now"
time_suffix = f"_{start_part}_to_{end_part}"
save_path = os.path.join(outpath, f"{wxid}_mini{time_suffix}.json")
filename = f"{wxid}_mini{time_suffix}.json"
save_path = os.path.join(outpath, filename)
with open(save_path, "w", encoding="utf-8") as f:
json.dump(mini_data, f, ensure_ascii=False, indent=indent)
return True, f"导出成功: {save_path}"
return True, f"导出成功: {save_path}", filename

View File

@ -13,6 +13,7 @@ from collections import Counter
from urllib.parse import quote, unquote
from typing import List, Optional
import fastapi.requests
from pydantic import BaseModel
from fastapi import APIRouter, Response, Body, Query, Request
from starlette.responses import StreamingResponse, FileResponse
@ -21,12 +22,15 @@ import pywxdump
from pywxdump import decrypt_merge, get_core_db
from pywxdump.db import DBHandler
from pywxdump.db.utils import download_file, dat2img
from .api_utils.html import HtmlController
from .export import export_csv, export_json, export_html
from .export.exportJSON import export_json_mini, export_json_mini_time_limit
from .rjson import ReJson, RqJson
from .utils import error9999, gc, asyncError9999, rs_loger
rs_api = APIRouter()
@ -466,13 +470,49 @@ def get_export_json(wxid: str = Body(..., embed=True)):
if not os.path.exists(outpath):
os.makedirs(outpath)
code, ret = export_json_mini_time_limit(wxid, outpath, db_config, my_wxid=my_wxid,start_createtime="2025-4-29 00:00:00", end_createtime="2025-4-30 00:00:00")
code, ret = export_json(wxid, outpath, db_config, my_wxid=my_wxid)
if code:
return ReJson(0, ret)
else:
return ReJson(2001, body=ret)
class ExportJsonMiniRequest(BaseModel):
start_createtime: str
end_createtime: str
@rs_api.api_route('/export_json_mini_select_time', methods=["GET", 'POST'])
def get_export_json(wxid: str = Body(..., embed=True),time: ExportJsonMiniRequest = Body(..., embed=True)):
"""
导出json,选择时间迷你版本
:return:
"""
my_wxid = gc.get_conf(gc.at, "last")
if not my_wxid: return ReJson(1001, body="my_wxid is required")
db_config = gc.get_conf(my_wxid, "db_config")
if not wxid:
return ReJson(1002, body=f"username is required: {wxid}")
outpath = os.path.join(gc.work_path, "export", my_wxid, "json", wxid)
if not os.path.exists(outpath):
os.makedirs(outpath)
start_createtime = time.start_createtime # 格式为 "2025-05-01 18:06:00"
end_createtime = time.end_createtime
code, ret,filename = export_json_mini_time_limit(wxid, outpath, db_config, my_wxid=my_wxid,start_createtime=start_createtime, end_createtime=end_createtime)
if code:
# 成功创建,执行生成可视化页面的逻辑
# with open(os.path.join(gc.work_path, "export", my_wxid, "html", wxid, filename), "w", encoding="utf-8") as f:
# f.write(
# #现在是fake
# HtmlController().create_html(json_data=None)
# )
return ReJson(0, ret)
else:
return ReJson(2001, body=ret)
@ -671,4 +711,61 @@ def get_readme():
else:
return ReJson(2001, body="status_code is not 200")
class DifyApiModel(BaseModel):
api_key:str
base_url:str
@rs_api.api_route('/dify_setting', methods=["GET", 'POST'])
@error9999
def dify_setting(request: Request = None, dify: DifyApiModel = Body(None, embed=True)):
"""
dify设置
"""
if request.method == "GET":
my_wxid = gc.get_conf(gc.at, "last")
if not my_wxid: return ReJson(1001, body="my_wxid is required")
gc.get_conf(my_wxid, "dify_setting")
return ReJson(0, body=gc.get_conf(my_wxid, "dify_setting"))
elif request.method == "POST":
my_wxid = gc.get_conf(gc.at, "last")
if not my_wxid: return ReJson(1001, body="my_wxid is required")
if not dify.api_key and not dify.base_url:
return ReJson(1002, body="dify_setting is required")
gc.set_conf(my_wxid, "dify_setting", {"API_KEY": dify.api_key, "BASE_URL": dify.base_url})
return ReJson(0, body=gc.get_conf(my_wxid, "dify_setting"))
return ReJson(2001, body="status_code is not 200")
class DeepSeekApiModel(BaseModel):
api_key:str
@rs_api.api_route('/deepseek_setting', methods=["GET", 'POST'])
@error9999
def deepseek_setting(request: Request = None, deepseek: DeepSeekApiModel = Body(None, embed=True)):
"""
deepseek设置
"""
if request.method == "GET":
my_wxid = gc.get_conf(gc.at, "last")
if not my_wxid: return ReJson(1001, body="my_wxid is required")
gc.get_conf(my_wxid, "deepseek_setting")
return ReJson(0, body=gc.get_conf(my_wxid, "deepseek_setting"))
elif request.method == "POST":
my_wxid = gc.get_conf(gc.at, "last")
if not my_wxid: return ReJson(1001, body="my_wxid is required")
if not deepseek or not deepseek.api_key:
return ReJson(1002, body="deepseek_setting is required")
gc.set_conf(my_wxid, "deepseek_setting", {"API_KEY": deepseek.api_key})
return ReJson(0, body=gc.get_conf(my_wxid, "deepseek_setting"))
return ReJson(2001, body="status_code is not 200")
# END 关于、帮助、设置 ***************************************************************************************************

View File

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-#
# -------------------------------------------------------------------------------
# Name: utils.py
# Name: api_utils.py
# Description:
# Author: xaoyaoo
# Date: 2024/01/16

View File

@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-#
# -------------------------------------------------------------------------------
# Name: __init__.py.py
# Description: db.utils
# Description: db.api_utils
# Author: xaoyaoo
# Date: 2024/07/23
# -------------------------------------------------------------------------------

View File

@ -35,6 +35,20 @@
--section-gap: 160px;
}
/* 可视化页面的css*/
:root {
--bg-ui-s-primary: #0f0e17;
--bg-ui-s-secondary: #1a1925;
--bg-ui-s-tertiary: #252336;
--text-ui-s-primary: #fffffe;
--text-ui-s-secondary: #a7a9be;
--accent-ui-s-primary: #ff8906;
--accent-ui-s-secondary: #f25f4c;
--accent-ui-s-tertiary: #e53170;
--accent-ui-s-blue: #3da9fc;
--accent-ui-s-purple: #7209b7;
--accent-ui-s-cyan: #00b4d8;
}
/* @media (prefers-color-scheme: dark) {
:root {

View File

@ -11,6 +11,7 @@ import ExportJSON from "@/components/chatBackup/ExportJSON.vue";
import ExportHTML from "@/components/chatBackup/ExportHTML.vue";
import ExportPDF from "@/components/chatBackup/ExportPDF.vue";
import ExportDOCX from "@/components/chatBackup/ExportDOCX.vue";
import ExportJSONMini from './ExportJSONMini.vue';
const props = defineProps({
wxid: {
@ -44,6 +45,10 @@ const setting = {
brief: 'json',
detail: "只包含文本,可用于数据分析,情感分析等方面。",
},
'json-mini': {
brief: 'json-mini',
detail: "只包含文本只有最小化的json格式。支持选择时间注意不要选择太多时间会导致导出数据过大影响AI分析。",
},
'html': {
brief: 'html-测试中',
detail: "主要用于浏览器可视化查看。",
@ -91,6 +96,7 @@ const setting = {
<ExportDEDB v-if="exportType=='dedb'" :wxid="props.wxid"/>
<ExportCSV v-if="exportType=='csv'" :wxid="props.wxid"/>
<ExportJSON v-if="exportType=='json'" :wxid="props.wxid"/>
<ExportJSONMini v-if="exportType=='json-mini'" :wxid="props.wxid"/>
<ExportHTML v-if="exportType=='html'" :wxid="props.wxid"/>
<ExportPDF v-if="exportType=='pdf'" :wxid="props.wxid"/>
<ExportDOCX v-if="exportType=='docx'" :wxid="props.wxid"/>

View File

@ -0,0 +1,65 @@
<script setup lang="ts">
import {defineProps, ref, watch} from "vue";
import http from "@/utils/axios.js";
import DateTimeSelect from "@/components/utils/DateTimeSelect.vue";
const props = defineProps({
wxid: {
type: String,
required: true,
}
});
watch(() => props.wxid, (newVal: string, oldVal: String) => {
console.log(newVal);
});
// props.wxidprops.wxid
const datetime = ref([]);
const Result = ref("");
const requestExport = async () => {
Result.value = "正在处理中...";
try {
Result.value = await http.post('/api/rs/export_json_mini_select_time', {
'wxid': props.wxid,
// 'datetime': datetime.value,
"time":{
"start_time":datetime.value[0],
"end_time":datetime.value[1]
}
});
} catch (error) {
console.error('Error fetching data msg_count:', error);
Result.value = "请求失败\n" + error;
return [];
}
}
//
const handDatetimeChildData = (val: any) => {
datetime.value = val;
}
</script>
<template>
<div>
<!-- <div>-->
<!-- <strong>时间(默认全部)</strong>-->
<!-- <DateTimeSelect @datetime="handDatetimeChildData"/>-->
<!-- </div>-->
<div style="position: relative;">
<el-button type="primary" @click="requestExport()">导出</el-button>
</div>
<el-divider/>
<!-- 结果显示 -->
<el-input type="textarea" :rows="6" readonly placeholder="" v-model="Result"
style="width: 100%;"></el-input>
</div>
</template>
<style scoped>
</style>

View File

@ -23,6 +23,11 @@ const router = createRouter({
name: 'chat',
component: () => import((`@/views/ChatView.vue`))
},
{
path: '/chat2ui',
name: 'chat2ui',
component: () => import((`@/views/Chat2UiView.vue`))
},
{
path: '/contacts',
name: 'contacts',

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-#
# -------------------------------------------------------------------------------
# Name: utils.py
# Name: api_utils.py
# Description:
# Author: xaoyaoo
# Date: 2023/12/25

View File

@ -45,17 +45,17 @@ setup(
license='MIT',
# packages=find_packages(exclude=[]),
packages=['pywxdump', 'pywxdump.ui', 'pywxdump.wx_core', 'pywxdump.wx_core.utils', 'pywxdump.analyzer',
'pywxdump.api', 'pywxdump.api.export', 'pywxdump.db', 'pywxdump.db.utils'],
packages=['pywxdump', 'pywxdump.ui', 'pywxdump.wx_core', 'pywxdump.wx_core.api_utils', 'pywxdump.analyzer',
'pywxdump.api', 'pywxdump.api.export', 'pywxdump.db', 'pywxdump.db.api_utils'],
package_dir={'pywxdump': 'pywxdump',
'pywxdump.wx_core': 'pywxdump/wx_core',
'pywxdump.wx_core.utils': 'pywxdump/wx_core/utils',
'pywxdump.wx_core.api_utils': 'pywxdump/wx_core/api_utils',
'pywxdump.analyzer': 'pywxdump/analyzer',
'pywxdump.ui': 'pywxdump/ui',
'pywxdump.api': 'pywxdump/api',
'pywxdump.api.export': 'pywxdump/api/export',
'pywxdump.db': 'pywxdump/db',
'pywxdump.db.utils': 'pywxdump/db/utils'
'pywxdump.db.api_utils': 'pywxdump/db/api_utils'
},
# include_package_data=True,
package_data={

5
temp.md Normal file
View File

@ -0,0 +1,5 @@
- 导出json可选时间
- 单独导航栏 Ai可视化
- 可以进行可视化的文件列表
- 已经可视化的列表
- 查看

380
test.html
View File

@ -1,8 +1,9 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>aaaaaaaaaa紧急事件报告日报 - 2025-04-27至2025-04-29</title>
<title>恋爱报告报告 - 2025-04-29 至 2025-04-30</title>
<style>
/* 严格定义的CSS样式确保风格一致性 */
:root {
@ -459,260 +460,405 @@
.disclaimer {
margin-top: 15px;
font-style: italic;
}
/* 新增头像相关样式 */
.user-avatar {
width: 50px;
height: 50px;
border-radius: 50%;
object-fit: cover;
transition: transform 0.3s ease;
position: relative;
cursor: pointer;
border: 2px solid var(--accent-primary);
}
/* 头像悬停效果 */
.user-avatar:hover {
transform: scale(1.1) rotate(5deg);
z-index: 100;
}
/* 头像tooltip */
.avatar-tooltip {
visibility: hidden;
background-color: var(--bg-tertiary);
color: var(--text-primary);
text-align: center;
padding: 5px 10px;
border-radius: 6px;
position: absolute;
z-index: 1000;
bottom: 125%;
left: 50%;
transform: translateX(-50%);
white-space: nowrap;
opacity: 0;
transition: opacity 0.3s;
font-size: 14px;
box-shadow: 0 3px 10px rgba(0,0,0,0.2);
}
.user-avatar:hover .avatar-tooltip {
visibility: visible;
opacity: 1;
}
/* 热度用户专区 */
.hot-users {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(80px, 1fr));
gap: 20px;
margin-top: 20px;
}
.hot-user-item {
position: relative;
text-align: center;
}
/* 皇冠标识 */
.hot-crown {
position: absolute;
top: -10px;
right: -5px;
font-size: 24px;
color: #ffd700;
filter: drop-shadow(0 2px 2px rgba(0,0,0,0.3));
}
</style>
</head>
<body>
<header>
<h1>aaaaaaaaaa紧急事件报告日报</h1>
<p class="date">2025-04-27至2025-04-29</p>
<h1>恋爱报告报告</h1>
<p class="date">2025-04-29 至 2025-04-30</p>
<div class="meta-info">
<span>总消息数302</span>
<span>活跃用户4</span>
<span>时间范围2025-04-27 11:33:20至2025-04-29 19:25:36</span>
<span>总消息数:500+</span>
<span>活跃用户:2</span>
<span>时间范围:00:05:04 至 22:20:26</span>
</div>
</header>
<!-- 今日讨论热点 -->
<!-- 1. 今日讨论热点 -->
<section class="hot-topics">
<h2>今日讨论热点</h2>
<div class="topics-container">
<!-- 在这里填充讨论热点内容严格按照以下格式保留3-5个话题 -->
<div class="topic-card">
<h3>计算机设计大赛项目准备</h3>
<div class="topic-category">学术竞赛</div>
<p class="topic-summary">群成员围绕中国大学生计算机设计大赛参赛作品《文书宝典——智能公文库与写作平台》展开密集讨论涉及文档编写、PPT制作、答辩视频准备等工作。</p>
<h3>恋爱沟通</h3>
<div class="topic-category">情感交流</div>
<p class="topic-summary">双方围绕情感需求、沟通方式和相互理解展开多次对话,涉及'控制欲''陪伴需求''表达方式'等核心矛盾点。典型对话如'你就不能说话吗'-'不困了,跟我聊聊天',体现双方对沟通频率的认知差异</p>
<div class="topic-keywords">
<span class="keyword">PPT制作</span>
<span class="keyword">技术展示</span>
<span class="keyword">文档格式</span>
<span class="keyword">控制</span><span class="keyword">陪伴</span><span class="keyword">理解</span>
</div>
<div class="topic-mentions">提及次数287</div>
<div class="topic-mentions">提及次数30+</div>
</div>
<div class="topic-card">
<h3>项目合作</h3>
<div class="topic-category">学业协作</div>
<p class="topic-summary">4月29日上午集中讨论服务设计项目开发事宜涉及原型设计、比赛规划、老师对接等具体内容。昏沉沉的提出开发支持意愿要哄宝宝开心则负责团队协调双方就'高保真原型''互联网+大赛'等专业概念进行多次确认。</p>
<div class="topic-keywords">
<span class="keyword">原型</span><span class="keyword">开发</span><span class="keyword">比赛</span>
</div>
<div class="topic-mentions">提及次数50+</div>
</div>
<!-- 复制上述卡片结构添加更多话题 -->
</div>
</section>
<!-- 实用教程与资源分享 -->
<!-- 2. 实用教程与资源分享 -->
<section class="tutorials">
<h2>实用教程与资源分享</h2>
<div class="tutorials-container">
<!-- 在这里填充教程和资源内容,严格按照以下格式 -->
<div class="tutorial-card">
<div class="tutorial-type">RESOURCE</div>
<h3>CSDN技术博客计算机大赛经验</h3>
<h3>产品设计开发流程</h3>
<div class="tutorial-meta">
<span class="shared-by">分享者:昏沉沉的</span>
<span class="share-time">时间2025-04-27 11:47:14</span>
<span class="share-time">时间2025-04-29 09:42:26</span>
</div>
<p class="tutorial-summary">关于计算机设计大赛的技术实现参考文章</p>
<p class="tutorial-summary">讨论软件产品开发各阶段要点,强调从调研到高保真原型的设计闭环</p>
<div class="key-points">
<h4>要点:</h4>
<ul>
<li>获奖项目技术分析</li>
<li>功能实现方案</li>
</ul>
<ul><li>功能闭环</li><li>UI完善</li><li>比赛适配</li></ul>
</div>
<div class="tutorial-link">
<a href="https://blog.csdn.net/youcans/article/details/123948442" class="link valid">查看原文: csdn.net</a>
<a href="" class="link valid">查看原文: 微信聊天</a>
</div>
<div class="tutorial-category">分类:技术参考</div>
</div>
<div class="tutorial-card">
<div class="tutorial-type">TUTORIAL</div>
<h3>在线文档:技术要点整理</h3>
<div class="tutorial-meta">
<span class="shared-by">分享者:昏沉沉的</span>
<span class="share-time">时间2025-04-27 11:49:52</span>
</div>
<p class="tutorial-summary">项目核心技术要点汇总文档</p>
<div class="key-points">
<h4>要点:</h4>
<ul>
<li>前端技术</li>
<li>后端架构</li>
<li>AI应用</li>
</ul>
</div>
<div class="tutorial-link">
<a href="https://www.kdocs.cn/l/cjm4CnSfuV9K" class="link valid">查看原文: kdocs.cn</a>
</div>
<div class="tutorial-category">分类:技术文档</div>
<div class="tutorial-category">分类:产品设计</div>
</div>
<!-- 复制上述卡片结构添加更多资源 -->
</div>
</section>
<!-- 重要消息汇总 -->
<!-- 3. 重要消息汇总 -->
<section class="important-messages">
<h2>重要消息汇总</h2>
<div class="messages-container">
<!-- 在这里填充重要消息内容,严格按照以下格式 -->
<div class="message-card">
<div class="message-meta">
<span class="time">2025-04-28 21:18:13</span>
<span class="sender">杨莅沅老师</span>
<span class="message-type">NOTICE</span>
<span class="priority priority-high">优先级:高</span>
<span class="time">2025-04-29 00:29:04</span>
<span class="sender">要哄宝宝开心,宝宝开心我就开心</span>
<span class="message-type">OTHER</span>
<span class="priority priority-高">优先级:高</span>
</div>
<p class="message-content">秦大拿,现在进度怎么样了,今晚能交上吗</p>
<p class="message-content">只要你做的不论是我,还是外人看来是爱我的</p>
<div class="message-full-content">
<p>完整情感需求表达</p>
</div>
</div>
<div class="message-card">
<div class="message-meta">
<span class="time">2025-04-29 17:06:55</span>
<span class="sender">杨莅沅老师</span>
<span class="message-type">ANNOUNCEMENT</span>
<span class="priority priority-high">优先级:高</span>
<span class="time">2025-04-29 10:15:17</span>
<span class="sender">昏沉沉的</span>
<span class="message-type">EVENT</span>
<span class="priority priority-中">优先级:中</span>
</div>
<p class="message-content">秦大拿看一遍ppt内容还有要修正的吗</p>
<p class="message-content">你说你男朋友做开发的 做出来原型的话可以让你男朋友看一下 可以开发</p>
<div class="message-full-content">
<p>项目合作具体提案</p>
</div>
</div>
<!-- 复制上述卡片结构添加更多消息 -->
</div>
</section>
<!-- 有趣对话或金句 -->
<!-- 4. 有趣对话或金句 -->
<section class="interesting-dialogues">
<h2>有趣对话或金句</h2>
<div class="dialogues-container">
<!-- 在这里填充对话内容,严格按照以下格式 -->
<div class="dialogue-card">
<div class="dialogue-type">DIALOGUE</div>
<div class="dialogue-content">
<div class="message">
<div class="message-meta">
<span class="speaker">杨莅沅老师</span>
<span class="time">2025-04-29 06:15:34</span>
<span class="speaker">要哄宝宝开心,宝宝开心我就开心</span>
<span class="time">2025-04-29 00:07:44</span>
</div>
<p class="message-content">那你硬拖着,看我挨骂啊</p>
<p class="message-content">不困了,跟我聊聊天</p>
</div>
<div class="message">
<div class="message-meta">
<span class="speaker">数媒技术春季班冯圣磊</span>
<span class="time">2025-04-29 06:16:08</span>
<span class="speaker">昏沉沉的</span>
<span class="time">2025-04-29 00:07:42</span>
</div>
<p class="message-content">[呲牙]</p>
<p class="message-content">不能跟你说话吗</p>
</div>
</div>
<div class="dialogue-highlight">关于PPT制作进度的幽默对峙</div>
<div class="dialogue-topic">相关话题:项目时间管理</div>
<div class="dialogue-highlight">沟通需求 vs 陪伴需求</div>
<div class="dialogue-topic">相关话题:情感表达差异</div>
</div>
<!-- 复制上述卡片结构添加更多对话 -->
</div>
</section>
<!-- 问题与解答 -->
<!-- 5. 问题与解答 -->
<section class="questions-answers">
<h2>问题与解答</h2>
<div class="qa-container">
<!-- 在这里填充问答内容,严格按照以下格式 -->
<div class="qa-card">
<div class="question">
<div class="question-meta">
<span class="asker">昏沉沉的</span>
<span class="time">2025-04-29 08:26:44</span>
<span class="asker">要哄宝宝开心,宝宝开心我就开心</span>
<span class="time">2025-04-29 10:33:25</span>
</div>
<p class="question-content">用ai直接生成的</p>
<p class="question-content">开发要钱</p>
<div class="question-tags">
<span class="tag">PPT制作</span>
<span class="tag">AI应用</span>
<span class="tag">项目</span><span class="tag">费用</span>
</div>
</div>
<div class="answers">
<div class="answer">
<div class="answer-meta">
<span class="responder">数媒技术春季班冯圣磊</span>
<span class="time">2025-04-29 08:27:21</span>
<span class="accepted-badge">最佳回答</span>
<span class="responder">昏沉沉的</span>
<span class="time">2025-04-29 10:45:18</span>
<span class='accepted-badge'>最佳回答</span>
</div>
<p class="answer-content">不完全是,有些是昨晚提取的,今早列上</p>
<p class="answer-content">那不就完了</p>
</div>
</div>
</div>
<!-- 复制上述卡片结构添加更多问答 -->
</div>
</section>
<!-- 群内数据可视化 -->
<!-- 6. 群内数据可视化 -->
<section class="analytics">
<h2>群内数据可视化</h2>
<!-- 话题热度 -->
<h3>话题热度</h3>
<div class="heatmap-container">
<!-- 在这里填充话题热度数据,严格按照以下格式 -->
<!-- 复制上述结构添加更多热度项,每项使用不同颜色 -->
<div class="heat-item">
<div class="heat-topic">文档修改</div>
<div class="heat-percentage">35%</div>
<div class="heat-topic">情感交流</div>
<div class="heat-percentage">45%%</div>
<div class="heat-bar">
<div class="heat-fill" style="width: 35%; background-color: #3da9fc;"></div>
</div>
<div class="heat-count">42条消息</div>
</div>
<div class="heat-item">
<div class="heat-topic">PPT制作</div>
<div class="heat-percentage">30%</div>
<div class="heat-bar">
<div class="heat-fill" style="width: 30%; background-color: #4361ee;"></div>
</div>
<div class="heat-count">36条消息</div>
<div class="heat-fill" style="width: 45%%; background-color: #3da9fc;"></div>
</div>
<div class="heat-count">200+条消息</div>
</div>
<div class="heat-item">
<div class="heat-topic">项目讨论</div>
<div class="heat-percentage">30%%</div>
<div class="heat-bar">
<div class="heat-fill" style="width: 30%%; background-color: #f25f4c;"></div>
</div>
<div class="heat-count">150+条消息</div>
</div>
<!-- 可用的颜色: #3da9fc, #f25f4c, #7209b7, #e53170, #00b4d8, #4cc9f0 -->
</div>
<!-- 话唠榜 -->
<!-- 在话唠榜添加头像 -->
<section class="analytics">
<h3>话唠榜</h3>
<div class="participants-container">
<div class="participant-item">
<div class="participant-rank">1</div>
<div class="participant-info">
<div class="participant-name">昏沉沉的</div>
<div class="participant-count">128 条消息</div>
<div class="participant-name">要哄宝宝开心,宝宝开心我就开心</div>
<div class="participant-count">发言数300+</div>
<div class="participant-characteristics">
<span class="characteristic">技术主导</span>
<span class="characteristic">进度督促</span>
</div>
</div>
</div>
<div class="participant-item">
<div class="participant-rank">2</div>
<div class="participant-info">
<div class="participant-name">杨莅沅老师</div>
<div class="participant-count">87 条消息</div>
<div class="participant-characteristics">
<span class="characteristic">质量把控</span>
<span class="characteristic">格式要求</span>
<span class="characteristic">情感表达</span><span class="characteristic">细节追问</span>
</div>
<div class="participant-words">
<span class="word"></span><span class="word">OK</span><span class="word"></span>
</div>
</div>
</div>
</div>
</section>
<!-- 熬夜冠军 -->
<h3>熬夜冠军</h3>
<div class="night-owls-container">
<!-- 在这里填充熬夜冠军数据,严格按照以下格式 -->
<div class="night-owl-item">
<div class="owl-crown" title="熬夜冠军">👑</div>
<div class="owl-info">
<div class="owl-name">刘蕴萱</div>
<div class="owl-title">深夜文档侠</div>
<div class="owl-time">最晚活跃时间2025-04-28 04:01:13</div>
<div class="owl-messages">深夜消息数5</div>
<div class="owl-name">昏沉沉的</div>
<div class="owl-title">深夜程序员</div>
<div class="owl-time">最晚活跃时间01:42:38</div>
<div class="owl-messages">深夜消息数50+</div>
<div class="owl-last-message">对不起</div>
<div class="owl-note">熬夜时段定义为23:00-06:00已考虑不同时区</div>
</div>
</div>
</div>
</section>
<!-- 词云 -->
<!-- 7. 词云 -->
<section class="word-cloud">
<h2>热门词云</h2>
<div class="cloud-container">
<!-- 词云容器 - 现在是云朵样式 -->
<div class="cloud-wordcloud" id="word-cloud">
<span class="cloud-word" style="left: 300px; top: 120px; font-size: 38px; color: #00b4d8; transform: rotate(-15deg);">PPT</span>
<span class="cloud-word" style="left: 180px; top: 150px; font-size: 32px; color: #00b4d8; transform: rotate(5deg);">文档</span>
<!-- 为每个词创建一个span元素使用绝对定位放置 -->
<!-- 以下是一些示例请根据实际内容生成40-60个词 -->
<span class="cloud-word" style="left: 300px; top: 120px;
font-size: 38px; color: #00b4d8;
transform: rotate(-15deg);">开发</span>
<span class="cloud-word" style="left: 300px; top: 120px;
font-size: 32px; color: #00b4d8;
transform: rotate(15deg);">睡觉</span>
<!-- 继续添加更多词 -->
</div>
<div class="cloud-legend">
<div class="legend-item">
<span class="legend-color" style="background-color: #00b4d8;"></span>
<span class="legend-label">项目材料 相关词汇</span>
<span class="legend-label">项目 相关词汇</span>
</div>
<div class="legend-item">
<span class="legend-color" style="background-color: #4361ee;"></span>
<span class="legend-label">技术术语 相关词汇</span>
<span class="legend-label">情感 相关词汇</span>
</div>
</div>
</div>
</section>
<!-- 8. 页面底部 -->
<footer>
<p>数据来源:aaaaaaaaaa紧急事件聊天记录</p>
<p>生成时间:2025-04-30 10:00:00</p>
<p>统计周期2025-04-27 11:33:20 至 2025-04-29 19:25:36</p>
<p>数据来源:恋爱私聊记录聊天记录</p>
<p>生成时间:<span class="generation-time">2025-05-01 10:00:00</span></p>
<p>统计周期2025-04-29 至 2025-04-30 [时间范围]</p>
<p class="disclaimer">免责声明:本报告内容基于群聊公开讨论,如有不当内容或侵权问题请联系管理员处理。</p>
</footer>
</body>
<script>
document.addEventListener('DOMContentLoaded', function() {
// 获取所有词云元素
const cloudWords = document.querySelectorAll('.cloud-word');
const container = document.querySelector('.cloud-wordcloud');
const containerWidth = container.offsetWidth;
const containerHeight = container.offsetHeight;
// 为每个词云元素设置随机位置
cloudWords.forEach(word => {
const wordWidth = word.offsetWidth;
const wordHeight = word.offsetHeight;
// 计算随机位置,确保词云元素不会超出容器边界
const randomLeft = Math.random() * (containerWidth - wordWidth);
const randomTop = Math.random() * (containerHeight - wordHeight);
// 设置位置
word.style.left = `${randomLeft}px`;
word.style.top = `${randomTop}px`;
// 添加悬停效果
word.addEventListener('mouseover', function() {
this.style.transform = 'scale(1.1)';
this.style.zIndex = '10';
});
word.addEventListener('mouseout', function() {
this.style.transform = 'scale(1)';
this.style.zIndex = '1';
});
});
});
</script>
</html>

38
test.py

File diff suppressed because one or more lines are too long

View File

@ -153,7 +153,7 @@ if package_path:
hidden_imports = f.read().splitlines()
hidden_imports = [i.replace('-', '_').split("=")[0].split("~")[0] for i in hidden_imports if
i and i not in ["setuptools", "wheel"]] # 去掉setuptools、wheel
hidden_imports += ["pywxdump", "pywxdump.db", "pywxdump.db.__init__.utils"]
hidden_imports += ["pywxdump", "pywxdump.db", "pywxdump.db.__init__.api_utils"]
# 获取 ui 文件夹下的所有文件 用于打包
root_path = os.path.join(package_path, 'pywxdump')

1078
text.html Normal file

File diff suppressed because it is too large Load Diff