新增导出联系人功能

This commit is contained in:
shuaikangzhou 2023-12-07 20:35:51 +08:00
parent 92d0314b7c
commit 206a41fda6
8 changed files with 318 additions and 301 deletions

View File

@ -6,6 +6,7 @@ labels: ''
assignees: ''
---
**是否检查过issues没有相同问题**
**bug描述**
A clear and concise description of what the bug is.

View File

@ -104,7 +104,6 @@ class Msg:
lock.release()
return result[0]
def get_message_by_num(self, username_, local_id):
sql = '''
select localId,TalkerId,Type,SubType,IsSender,CreateTime,Status,StrContent,strftime('%Y-%m-%d %H:%M:%S',CreateTime,'unixepoch','localtime') as StrTime
@ -205,7 +204,7 @@ class Msg:
finally:
lock.release()
return result
def get_messages_by_month(self, username_, year_='2023'):
sql = '''
SELECT strftime('%Y-%m',CreateTime,'unixepoch','localtime') as days,count(MsgSvrID)
@ -226,7 +225,6 @@ class Msg:
lock.release()
# result.sort(key=lambda x: x[5])
return result
def get_first_time_of_message(self, username_):
if not self.open_flag:
@ -271,4 +269,4 @@ if __name__ == '__main__':
pprint(msg.get_message_by_num('wxid_0o18ef858vnu22', local_id))
print(msg.get_messages_by_keyword(wxid, '干嘛'))
pprint(msg.get_messages_by_keyword(wxid, '干嘛')[0])
print(msg.get_first_time_of_message('wxid_0o18ef858vnu22'))
print(msg.get_first_time_of_message('wxid_0o18ef858vnu22'))

View File

@ -3,8 +3,9 @@ import html
import os
from PyQt5.QtCore import pyqtSignal, QThread
from PyQt5.QtWidgets import QFileDialog
from . import msg_db
from . import msg_db, micro_msg_db
from .package_msg import PackageMsg
from ..DataBase import hard_link_db
from ..person_pc import MePC
@ -14,7 +15,7 @@ os.makedirs('./data/聊天记录', exist_ok=True)
def makedirs(path):
os.makedirs(path,exist_ok=True)
os.makedirs(path, exist_ok=True)
os.makedirs(os.path.join(path, 'image'), exist_ok=True)
os.makedirs(os.path.join(path, 'emoji'), exist_ok=True)
os.makedirs(os.path.join(path, 'video'), exist_ok=True)
@ -52,6 +53,7 @@ class Output(QThread):
DOCX = 1
HTML = 2
CSV_ALL = 3
CONTACT_CSV = 4
def __init__(self, contact, parent=None, type_=DOCX):
super().__init__(parent)
@ -71,12 +73,15 @@ class Output(QThread):
def to_csv_all(self):
origin_docx_path = f"{os.path.abspath('.')}/data/聊天记录/"
os.makedirs(origin_docx_path, exist_ok=True)
filename = f"{os.path.abspath('.')}/data/聊天记录/messages.csv"
filename = QFileDialog.getSaveFileName(None, "save file", os.path.join(os.getcwd(),'messages.csv'), "csv files (*.csv);;all files(*.*)")
if not filename:
return
filename = filename[0]
# columns = ["用户名", "消息内容", "发送时间", "发送状态", "消息类型", "isSend", "msgId"]
columns = ['localId', 'TalkerId', 'Type', 'SubType',
'IsSender', 'CreateTime', 'Status', 'StrContent',
'StrTime', 'Remark', 'NickName', 'Sender']
# messages = msg_db.get_messages_all()
packagemsg = PackageMsg()
messages = packagemsg.get_package_message_all()
# 写入CSV文件
@ -87,11 +92,29 @@ class Output(QThread):
writer.writerows(messages)
self.okSignal.emit(1)
def contact_to_csv(self):
filename = QFileDialog.getSaveFileName(None, "save file", os.path.join(os.getcwd(),'contacts.csv'), "csv files (*.csv);;all files(*.*)")
if not filename:
return
filename = filename[0]
# columns = ["用户名", "消息内容", "发送时间", "发送状态", "消息类型", "isSend", "msgId"]
columns = ['UserName','Alias', 'Type', 'Remark', 'NickName', 'PYInitial', 'RemarkPYInitial', 'smallHeadImgUrl', 'bigHeadImgUrl']
contacts = micro_msg_db.get_contact()
# 写入CSV文件
with open(filename, mode='w', newline='', encoding='utf-8') as file:
writer = csv.writer(file)
writer.writerow(columns)
# 写入数据
writer.writerows(contacts)
self.okSignal.emit(1)
def run(self):
if self.output_type == self.DOCX:
return
elif self.output_type == self.CSV_ALL:
self.to_csv_all()
elif self.output_type == self.CONTACT_CSV:
self.contact_to_csv()
else:
self.Child = ChildThread(self.contact, type_=self.output_type)
self.Child.progressSignal.connect(self.progress)

View File

@ -6,10 +6,8 @@ import sys
sys.path.append('.')
from app.DataBase import msg_db, MsgType
from app.person_pc import ContactPC
import jieba
from pyecharts import options as opts
from pyecharts.charts import Pie, WordCloud, Calendar, Bar, Line, Timeline, Grid
from pyecharts.charts import WordCloud, Calendar, Bar
from app.resources import resource_rc
var = resource_rc.qt_resource_name

View File

@ -102,6 +102,8 @@ class MainWinController(QMainWindow, mainwindow.Ui_MainWindow):
self.menu_output.setIcon(Icon.Output)
self.action_output_CSV.setIcon(Icon.ToCSV)
self.action_output_CSV.triggered.connect(self.output)
self.action_output_contacts.setIcon(Icon.Output)
self.action_output_contacts.triggered.connect(self.output)
self.action_desc.setIcon(Icon.Help_Icon)
self.action_help_contact.triggered.connect(
lambda: QDesktopServices.openUrl(QUrl("https://blog.lc044.love/post/5")))
@ -192,7 +194,12 @@ class MainWinController(QMainWindow, mainwindow.Ui_MainWindow):
if self.sender() == self.action_output_CSV:
self.outputThread = Output(None, type_=Output.CSV_ALL)
self.outputThread.okSignal.connect(
lambda x: self.message('聊天记录导出成功\n./data/聊天记录/messages.csv'))
lambda x: self.message('聊天记录导出成功'))
self.outputThread.start()
elif self.sender() == self.action_output_contacts:
self.outputThread = Output(None, type_=Output.CONTACT_CSV)
self.outputThread.okSignal.connect(
lambda x: self.message('联系人导出成功'))
self.outputThread.start()
def message(self, msg):

View File

@ -16,31 +16,31 @@ class Ui_MainWindow(object):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(1280, 779)
MainWindow.setStyleSheet("\n"
" /*去掉item虚线边框*/\n"
" QListWidget, QListView, QTreeWidget, QTreeView {\n"
" outline: 0px;\n"
" }\n"
" /*设置左侧选项的最小最大宽度,文字颜色和背景颜色*/\n"
" QListWidget {\n"
" min-width: 120px;\n"
" max-width: 120px;\n"
" color: black;\n"
" background: white;\n"
" border:none;\n"
" }\n"
" QListWidget::item{\n"
" height:80;\n"
" }\n"
" /*被选中时的背景颜色和左边框颜色*/\n"
" QListWidget::item:selected {\n"
" background: rgb(204, 204, 204);\n"
" border-left: 4px solid rgb(9, 187, 7);\n"
" }\n"
" /*鼠标悬停颜色*/\n"
" HistoryPanel::item:hover {\n"
" background: rgb(52, 52, 52);\n"
" }\n"
" ")
" /*去掉item虚线边框*/\n"
" QListWidget, QListView, QTreeWidget, QTreeView {\n"
" outline: 0px;\n"
" }\n"
" /*设置左侧选项的最小最大宽度,文字颜色和背景颜色*/\n"
" QListWidget {\n"
" min-width: 120px;\n"
" max-width: 120px;\n"
" color: black;\n"
" background: white;\n"
" border:none;\n"
" }\n"
" QListWidget::item{\n"
" height:80;\n"
" }\n"
" /*被选中时的背景颜色和左边框颜色*/\n"
" QListWidget::item:selected {\n"
" background: rgb(204, 204, 204);\n"
" border-left: 4px solid rgb(9, 187, 7);\n"
" }\n"
" /*鼠标悬停颜色*/\n"
" HistoryPanel::item:hover {\n"
" background: rgb(52, 52, 52);\n"
" }\n"
" ")
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.horizontalLayout = QtWidgets.QHBoxLayout(self.centralwidget)
@ -124,12 +124,15 @@ class Ui_MainWindow(object):
self.action_help_contact.setObjectName("action_help_contact")
self.action_output_CSV = QtWidgets.QAction(MainWindow)
self.action_output_CSV.setObjectName("action_output_CSV")
self.action_output_contacts = QtWidgets.QAction(MainWindow)
self.action_output_contacts.setObjectName("action_output_contacts")
self.menu_F.addSeparator()
self.menu_F.addSeparator()
self.menu_F.addAction(self.action_3)
self.menu_F.addAction(self.action_4)
self.menu_output.addAction(self.action_output_CSV)
self.menu_data.addAction(self.menu_output.menuAction())
self.menu_data.addAction(self.action_output_contacts)
self.menu_2.addAction(self.action_help_decrypt)
self.menu_2.addAction(self.action_help_chat)
self.menu_2.addAction(self.action_help_contact)
@ -173,3 +176,4 @@ class Ui_MainWindow(object):
self.action_help_chat.setText(_translate("MainWindow", "聊天相关"))
self.action_help_contact.setText(_translate("MainWindow", "好友相关"))
self.action_output_CSV.setText(_translate("MainWindow", "CSV"))
self.action_output_contacts.setText(_translate("MainWindow", "导出联系人"))

View File

@ -1,20 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1280</width>
<height>779</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<property name="styleSheet">
<string notr="true">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1280</width>
<height>779</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<property name="styleSheet">
<string notr="true">
/*去掉item虚线边框*/
QListWidget, QListView, QTreeWidget, QTreeView {
outline: 0px;
@ -40,233 +40,239 @@
background: rgb(52, 52, 52);
}
</string>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QFrame" name="frame_info">
<property name="minimumSize">
<size>
<width>80</width>
<height>500</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>80</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">background-color:rgb(240,240,240)</string>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
<widget class="QLabel" name="myavatar">
<property name="geometry">
<rect>
<x>10</x>
<y>40</y>
<width>60</width>
<height>60</height>
</rect>
</property>
<property name="text">
<string>avatar</string>
</property>
</widget>
<widget class="QListWidget" name="listWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>230</y>
<width>120</width>
<height>331</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>120</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>120</width>
<height>16777215</height>
</size>
</property>
<property name="verticalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<property name="sizeAdjustPolicy">
<enum>QAbstractScrollArea::AdjustIgnored</enum>
</property>
<item>
<property name="text">
<string>新建项目</string>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QFrame" name="frame_info">
<property name="minimumSize">
<size>
<width>80</width>
<height>500</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>80</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">background-color:rgb(240,240,240)</string>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
<widget class="QLabel" name="myavatar">
<property name="geometry">
<rect>
<x>10</x>
<y>40</y>
<width>60</width>
<height>60</height>
</rect>
</property>
<property name="text">
<string>avatar</string>
</property>
</widget>
<widget class="QListWidget" name="listWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>230</y>
<width>120</width>
<height>331</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>120</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>120</width>
<height>16777215</height>
</size>
</property>
<property name="verticalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<property name="sizeAdjustPolicy">
<enum>QAbstractScrollArea::AdjustIgnored</enum>
</property>
<item>
<property name="text">
<string>新建项目</string>
</property>
</item>
<item>
<property name="text">
<string>新建项目</string>
</property>
</item>
<item>
<property name="text">
<string>新建项目</string>
</property>
</item>
<item>
<property name="text">
<string>新建项目</string>
</property>
</item>
<item>
<property name="text">
<string>新建项目</string>
</property>
</item>
</widget>
</widget>
</item>
<item>
<widget class="QStackedWidget" name="stackedWidget">
<property name="font">
<font>
<family>微软雅黑</family>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1280</width>
<height>23</height>
</rect>
</property>
<widget class="QMenu" name="menu_F">
<property name="title">
<string>文件(F)</string>
</property>
<addaction name="separator"/>
<addaction name="separator"/>
<addaction name="action_3"/>
<addaction name="action_4"/>
</widget>
<widget class="QMenu" name="menu_data">
<property name="font">
<font>
<family>微软雅黑</family>
</font>
</property>
<property name="title">
<string>数据</string>
</property>
<widget class="QMenu" name="menu_output">
<property name="title">
<string>导出聊天记录(全部)</string>
</property>
<addaction name="action_output_CSV"/>
</widget>
<addaction name="menu_output"/>
</widget>
<widget class="QMenu" name="menu_2">
<property name="title">
<string>帮助</string>
</property>
<addaction name="action_help_decrypt"/>
<addaction name="action_help_chat"/>
<addaction name="action_help_contact"/>
</widget>
<widget class="QMenu" name="menu_about">
<property name="title">
<string>关于</string>
</property>
<addaction name="action_desc"/>
</widget>
<widget class="QMenu" name="menu_3">
<property name="title">
<string>不显示或者显示异常请重启应用、没反应那就多等一会儿</string>
</property>
</widget>
<addaction name="menu_F"/>
<addaction name="menu_data"/>
<addaction name="menu_2"/>
<addaction name="menu_about"/>
<addaction name="menu_3"/>
</widget>
<widget class="QStatusBar" name="statusbar"/>
<action name="action_3">
<property name="text">
<string>保存</string>
</property>
</action>
<action name="action_4">
<property name="text">
<string>退出</string>
</property>
</action>
<action name="action_help_decrypt">
<property name="text">
<string>解密教程</string>
</property>
<property name="font">
<font>
<family>Microsoft YaHei UI</family>
</font>
</property>
</action>
<action name="action_desc">
<property name="text">
<string>说明</string>
</property>
</action>
<action name="action_help_chat">
<property name="text">
<string>聊天相关</string>
</property>
</action>
<action name="action_help_contact">
<property name="text">
<string>好友相关</string>
</property>
</action>
<action name="action_output_CSV">
<property name="text">
<string>CSV</string>
</property>
</action>
</item>
<item>
<property name="text">
<string>新建项目</string>
</property>
</item>
<item>
<property name="text">
<string>新建项目</string>
</property>
</item>
<item>
<property name="text">
<string>新建项目</string>
</property>
</item>
<item>
<property name="text">
<string>新建项目</string>
</property>
</item>
</widget>
</widget>
</item>
<item>
<widget class="QStackedWidget" name="stackedWidget">
<property name="font">
<font>
<family>微软雅黑</family>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1280</width>
<height>23</height>
</rect>
</property>
<widget class="QMenu" name="menu_F">
<property name="title">
<string>文件(F)</string>
</property>
<addaction name="separator"/>
<addaction name="separator"/>
<addaction name="action_3"/>
<addaction name="action_4"/>
</widget>
<widget class="QMenu" name="menu_data">
<property name="font">
<font>
<family>微软雅黑</family>
</font>
</property>
<property name="title">
<string>数据</string>
</property>
<widget class="QMenu" name="menu_output">
<property name="title">
<string>导出聊天记录(全部)</string>
</property>
<addaction name="action_output_CSV"/>
</widget>
<resources/>
<connections/>
<addaction name="menu_output"/>
<addaction name="action_output_contacts"/>
</widget>
<widget class="QMenu" name="menu_2">
<property name="title">
<string>帮助</string>
</property>
<addaction name="action_help_decrypt"/>
<addaction name="action_help_chat"/>
<addaction name="action_help_contact"/>
</widget>
<widget class="QMenu" name="menu_about">
<property name="title">
<string>关于</string>
</property>
<addaction name="action_desc"/>
</widget>
<widget class="QMenu" name="menu_3">
<property name="title">
<string>不显示或者显示异常请重启应用、没反应那就多等一会儿</string>
</property>
</widget>
<addaction name="menu_F"/>
<addaction name="menu_data"/>
<addaction name="menu_2"/>
<addaction name="menu_about"/>
<addaction name="menu_3"/>
</widget>
<widget class="QStatusBar" name="statusbar"/>
<action name="action_3">
<property name="text">
<string>保存</string>
</property>
</action>
<action name="action_4">
<property name="text">
<string>退出</string>
</property>
</action>
<action name="action_help_decrypt">
<property name="text">
<string>解密教程</string>
</property>
<property name="font">
<font>
<family>Microsoft YaHei UI</family>
</font>
</property>
</action>
<action name="action_desc">
<property name="text">
<string>说明</string>
</property>
</action>
<action name="action_help_chat">
<property name="text">
<string>聊天相关</string>
</property>
</action>
<action name="action_help_contact">
<property name="text">
<string>好友相关</string>
</property>
</action>
<action name="action_output_CSV">
<property name="text">
<string>CSV</string>
</property>
</action>
<action name="action_output_contacts">
<property name="text">
<string>导出联系人</string>
</property>
</action>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -1,11 +1,8 @@
import json
import os
import sys
from flask import Flask, render_template, send_file
from pyecharts import options as opts
from pyecharts.charts import Bar
from pyecharts.globals import ThemeType
from app.DataBase import msg_db
from app.analysis import analysis
@ -19,25 +16,8 @@ contact: ContactPC = None
@app.route("/")
def index():
# 创建一个简单的柱状图
bar = (
Bar(init_opts=opts.InitOpts(theme=ThemeType.LIGHT))
.add_xaxis(["A", "B", "C", "D", "E"])
.add_yaxis("Series", [5, 20, 36, 10, 75])
.set_global_opts(title_opts=opts.TitleOpts(title="Flask and Pyecharts Interaction"))
)
# 将图表转换成 HTML
chart_html = bar.render_embed()
# 渲染模板,并传递图表的 HTML 到模板中
return render_template("index.html", chart_html=chart_html)
@app.route("/index")
def index0():
return render_template("index1.html")
return render_template("index.html")
@app.route('/home')
def home():