全面删除对模拟器数据库的支持

This commit is contained in:
shuaikangzhou 2023-12-13 21:35:13 +08:00
parent 858fc306b4
commit 4c6ec0ed3b
82 changed files with 38 additions and 6639 deletions

View File

@ -1,7 +0,0 @@
PRAGMA key = '10f35f1';
PRAGMA cipher_migrate;
ATTACH DATABASE './app/DataBase/Msg.db' AS Msg KEY '';
SELECT sqlcipher_export('Msg');
DETACH DATABASE Msg;

View File

@ -1,584 +0,0 @@
# -*- coding: utf-8 -*-
"""
@File : data.py
@Author : Shuaikang Zhou
@Time : 2023/1/5 0:11
@IDE : Pycharm
@Version : Python3.10
@comment : ···
"""
import hashlib
import os
import sqlite3
import threading
import time
import requests
DB = None
cursor = None
lock = threading.Lock()
Type = {
1: '文本内容',
2: '位置信息',
3: '图片及视频',
34: '语音消息',
42: '名片(公众号名片)',
43: '图片及视频',
47: '表情包',
48: '定位信息',
49: '小程序链接',
10000: '撤回消息提醒',
1048625: '照片',
16777265: '链接',
285212721: '文件',
419430449: '微信转账',
436207665: '微信红包',
469762097: '微信红包',
11879048186: '位置共享',
}
Type0 = {
'1': '文字',
'3': '图片',
'43': '视频',
'-1879048185': '微信运动排行榜',
'5': '',
'47': '表情包',
'268445456': '撤回的消息',
'34': '语音',
'419430449': '转账',
'50': '语音电话',
'100001': '领取红包',
'10000': '消息已发出,但被对方拒收了。',
'822083633': '回复消息',
'922746929': '拍一拍',
'1090519089': '发送文件',
'318767153': '付款成功',
'436207665': '发红包',
}
def mkdir(path):
path = path.strip()
path = path.rstrip("\\")
if os.path.exists(path):
return False
os.makedirs(path)
return True
root_path = os.path.abspath('.')
mkdir(os.path.abspath('.') + '/app/DataBase')
mkdir(os.path.abspath('.') + '/app/data/emoji')
if os.path.exists('./app/DataBase/Msg.db'):
DB = sqlite3.connect("./app/DataBase/Msg.db", check_same_thread=False)
# '''创建游标'''
cursor = DB.cursor()
if os.path.exists('./Msg.db'):
DB = sqlite3.connect("./Msg.db", check_same_thread=False)
# '''创建游标'''
cursor = DB.cursor()
def is_db_exist() -> bool:
"""
判断数据库是否正常使用
"""
global DB
global cursor
if DB and cursor:
try:
sql = 'select * from userinfo where id=2'
cursor.execute(sql)
result = cursor.fetchone()
if result[2]:
return True
else:
return False
except Exception as e:
return False
return False
def init_database():
global DB
global cursor
if os.path.exists('./app/DataBase/Msg.db'):
DB = sqlite3.connect("./app/DataBase/Msg.db", check_same_thread=False)
# '''创建游标'''
cursor = DB.cursor()
if os.path.exists('./Msg.db'):
DB = sqlite3.connect("./Msg.db", check_same_thread=False)
# '''创建游标'''
cursor = DB.cursor()
def decrypt(db, key):
if not key:
print('缺少数据库密钥')
return False
if not db:
print('没有数据库文件')
return False
if is_db_exist():
print('/app/DataBase/Msg.db 已经存在')
return True
cmd = './sqlcipher-3.0.1/bin/sqlcipher-shell32.exe'
param = f"""
PRAGMA key = '{key}';
PRAGMA cipher_migrate;
ATTACH DATABASE './app/DataBase/Msg.db' AS Msg KEY '';
SELECT sqlcipher_export('Msg');
DETACH DATABASE Msg;
"""
with open('./app/data/config.txt', 'w') as f:
f.write(param)
p = os.system(f"{os.path.abspath('.')}{cmd} {db} < ./app/data/config.txt")
global DB
global cursor
DB = sqlite3.connect("./app/DataBase/Msg.db", check_same_thread=False)
# '''创建游标'''
cursor = DB.cursor()
def get_myinfo():
sql = 'select * from userinfo where id=2'
cursor.execute(sql)
result = cursor.fetchone()
return result[2]
def get_contacts():
sql = 'select * from rcontact'
cursor.execute(sql)
result = cursor.fetchall()
return result
def get_rconversation():
sql = '''
select msgCount,username,unReadCount,chatmode,status,isSend,conversationTime,msgType,digest,digestUser,hasTrunc,attrflag
from rconversation
where chatmode=1 or chatmode=0 and (msgType='1' or msgType='3' or msgType='47')
order by msgCount desc
'''
'''order by conversationTime desc'''
cursor.execute(sql)
result = cursor.fetchall()
return result
def timestamp2str(timestamp):
# t2 = 1586102400
s_l = time.localtime(timestamp / 1000)
ts = time.strftime("%Y/%m/%d", s_l)
# print(ts)
return ts
def get_conRemark(username):
try:
lock.acquire(True)
sql = 'select conRemark,nickname from rcontact where username=?'
cursor.execute(sql, [username])
result = cursor.fetchone()
if result:
if result[0]:
return result[0]
else:
return result[1]
except:
time.sleep(0.1)
sql = 'select conRemark,nickname from rcontact where username=?'
cursor.execute(sql, [username])
result = cursor.fetchone()
if result:
if result[0]:
return result[0]
else:
return result[1]
finally:
lock.release()
return False
def get_nickname(username):
sql = 'select nickname,alias from rcontact where username=?'
cursor.execute(sql, [username])
result = cursor.fetchone()
return result
def avatar_md5(wxid):
m = hashlib.md5()
# 参数必须是byte类型否则报Unicode-objects must be encoded before hashing错误
m.update(bytes(wxid.encode('utf-8')))
return m.hexdigest()
def get_avator(wxid):
if wxid == None:
return os.path.join(root_path, '/app/data/icons/default_avatar.svg')
wxid = str(wxid)
avatar = avatar_md5(wxid)
path = os.path.join(root_path, 'app', 'data', 'avatar', avatar[:2], avatar[2:4])
# avatar_path + avatar[:2] + '/' + avatar[2:4]
for root, dirs, files in os.walk(path):
for file in files:
if avatar in file:
avatar = file
break
return os.path.join(path, avatar)
# return f'''{path}/{avatar}'''
# return f'''{path}/user_{avatar}.png'''
def get_message(wxid, num):
sql = '''
select * from message
where talker = ?
order by createTime desc
limit ?,100
'''
cursor.execute(sql, [wxid, num * 100])
return cursor.fetchall()
def get_text_by_num(wxid, num):
sql = '''
SELECT content,strftime('%Y-%m-%d',createTime/1000,'unixepoch','localtime') as days
from message
where talker = ? and type=1
order by days
'''
'''group by days'''
cursor.execute(sql, [wxid])
return cursor.fetchall()
def search_send_message(start_time, end_time):
start_time = '2022-1-1 00:00:00'
end_time = '2023-1-1 00:00:00'
start = time.mktime(time.strptime(start_time, '%Y-%m-%d %H:%M:%S'))
end = time.mktime(time.strptime(end_time, '%Y-%m-%d %H:%M:%S'))
sql = '''
select count(*) from message
where createTime >? and createTime < ? and isSend=0 and talker like '%wxid%';
'''
cursor.execute(sql, [start * 1000, end * 1000])
return cursor.fetchone()
def clearImagePath(imgpath):
path = imgpath.split('/')
newPath = '/'.join(path[:-1]) + '/' + path[-1][3:] + '.jpg'
if os.path.exists(newPath):
return newPath
newPath = '/'.join(path[:-1]) + '/' + path[-1][3:] + '.png'
if os.path.exists(newPath):
return newPath
newPath = '/'.join(path[:-1]) + '/' + path[-1] + 'hd'
if os.path.exists(newPath):
return newPath
return imgpath
def get_all_message(wxid):
sql = '''
select * from message
where talker = ?
order by createTime
'''
cursor.execute(sql, [wxid])
return cursor.fetchall()
def get_emoji(imgPath):
newPath = f"{os.path.abspath('.')}/app/data/emoji/{imgPath}"
if os.path.exists(newPath):
return newPath
else:
sql = '''
select cdnUrl
from EmojiInfo
where md5=?
'''
try:
cursor.execute(sql, [imgPath])
result = cursor.fetchone()
download_emoji(newPath, result[0])
except sqlite3.ProgrammingError as e:
print(e, imgPath)
return False
return False
def download_emoji(imgPath, url):
if not url:
return False
try:
resp = requests.get(url)
with open(imgPath, 'wb') as f:
f.write(resp.content)
except:
return False
return imgPath
def get_chatroom_displayname(chatroom, username):
sql = 'select memberlist,displayname from chatroom where chatroomname =?'
cursor.execute(sql, [chatroom])
result = cursor.fetchone()
wxids = result[0].split(';')
names = result[1].split('')
id = wxids.index(username)
print(result[0])
print(wxids)
for i in wxids:
print(get_conRemark(i))
return names[id]
def get_contacts():
sql = '''
select * from rcontact
where type=3 or type = 333
'''
cursor.execute(sql)
result = cursor.fetchall()
return result
def send_nums(username):
sql = '''
select count(*) from message
where talker = ? and isSend=1
'''
cursor.execute(sql, [username])
return cursor.fetchone()[0]
def recv_nums(username):
sql = '''
select count(*) from message
where talker = ? and isSend=0
'''
cursor.execute(sql, [username])
return cursor.fetchone()[0]
def get_imgPath(imgPath):
sql = '''
select bigImgPath from ImgInfo2
where thumbImgPath = ?;
'''
cursor.execute(sql, [imgPath])
return cursor.fetchone()[0]
def get_text(username):
sql = '''
select content from message
where talker=? and type=1
'''
cursor.execute(sql, [username])
result = cursor.fetchall()
return ''.join(map(lambda x: x[0], result))
def msg_type_num(username):
sql = '''
select type,count(*) from message
where talker = ?
group by type
'''
cursor.execute(sql, [username])
return cursor.fetchall()
def get_msg_start_time(username):
sql = '''
select strftime('%Y-%m-%d %H:%M:%S',createTime/1000,'unixepoch','localtime') from message
where talker = ?
order by msgId
limit 1
'''
cursor.execute(sql, [username])
return cursor.fetchone()[0]
def get_msg_end_time(username):
sql = '''
select strftime('%Y-%m-%d %H:%M:%S',createTime/1000,'unixepoch','localtime') from message
where talker = ?
order by msgId desc
limit 1
'''
cursor.execute(sql, [username])
try:
return cursor.fetchone()[0]
except:
return None
def get_msg_by_days(username, year='2022'):
sql = '''
SELECT strftime('%Y-%m-%d',createTime/1000,'unixepoch','localtime') as days,count(msgId)
from message
where talker = ? and strftime('%Y',createTime/1000,'unixepoch','localtime') = ?
group by days
'''
cursor.execute(sql, [username, year])
result = cursor.fetchall()
return result
def get_msg_by_day(username):
sql = '''
SELECT strftime('%Y-%m-%d',createTime/1000,'unixepoch','localtime') as days,count(msgId)
from message
where talker = ?
group by days
'''
cursor.execute(sql, [username])
result = cursor.fetchall()
return result
def get_msg_by_month(username, year='2022'):
sql = '''
SELECT strftime('%Y-%m',createTime/1000,'unixepoch','localtime') as days,count(msgId)
from message
where talker = ? and strftime('%Y',createTime/1000,'unixepoch','localtime') = ?
group by days
'''
cursor.execute(sql, [username, year])
result = cursor.fetchall()
return result
def get_msg_by_hour(username):
sql = '''
SELECT strftime('%H:00',createTime/1000,'unixepoch','localtime') as days,count(msgId)
from message
where talker = ?
group by days
'''
cursor.execute(sql, [username])
result = cursor.fetchall()
return result
def get_sport():
sql = '''
SELECT createTime,content,strftime('%Y-%m-%d',createTime/1000,'unixepoch','localtime') as months
from message
where talker = 'gh_43f2581f6fd6'
'''
cursor.execute(sql)
result = cursor.fetchall()
return result
def get_myInfo():
sql = '''
select value from userinfo
where id = 4
'''
cursor.execute(sql)
name = cursor.fetchone()[0]
sql = '''
select value from userinfo
where id = 5
'''
cursor.execute(sql)
email = cursor.fetchone()[0]
sql = '''
select value from userinfo
where id = 6
'''
cursor.execute(sql)
tel = cursor.fetchone()[0]
sql = '''
select value from userinfo
where id = 9
'''
cursor.execute(sql)
QQ = cursor.fetchone()[0]
sql = '''
select value from userinfo
where id = 42
'''
cursor.execute(sql)
wxid = cursor.fetchone()[0]
sql = '''
select value from userinfo
where id = 12291
'''
cursor.execute(sql)
signature = cursor.fetchone()[0]
sql = '''
select value from userinfo
where id = 12292
'''
cursor.execute(sql)
city = cursor.fetchone()[0]
sql = '''
select value from userinfo
where id = 12293
'''
cursor.execute(sql)
province = cursor.fetchone()[0]
return {
'name': name,
'username': wxid,
'city': city,
'province': province,
'email': email,
'QQ': QQ,
'signature': signature,
'tel': tel,
}
def search_Latest_chat_time(wxid):
# 查找聊天最晚的消息
sql = '''
SELECT strftime('%H:%M:%S',createTime/1000,'unixepoch','localtime') as t,content,strftime('%Y-%m-%d %H:%M:%S',createTime/1000,'unixepoch','localtime')
from message
where talker = ? and t>'00:00:00' and t<'05:00:00' and type=1
order by t desc
'''
cursor.execute(sql, [wxid])
result = cursor.fetchall()
return result
def search_emoji(wxid):
# 查找聊天最晚的消息
sql = '''
SELECT imgPath,strftime('%Y-%m-%d %H:%M:%S',createTime/1000,'unixepoch','localtime') as t,count(imgPath)
from message
where talker = ? and t>'2022-01-01 00:00:00' and t<'2022-12-31 00::00:00' and type=47 and isSend=0
group by content
order by count(imgPath) desc
'''
cursor.execute(sql, [wxid])
result = cursor.fetchall()
return result
if __name__ == '__main__':
wxid = 'wxid_8piw6sb4hvfm22'
# wxid = 'wxid_wt2vsktnu4z022'
# emotion_analysis(wxid)
t = search_Latest_chat_time(wxid)
print(t[0])
d = get_msg_by_days(wxid)
print(len(d))
e = search_emoji(wxid)
print(e)
p = get_emoji(e[1][0])
print(p)

View File

@ -1,6 +0,0 @@
import sys
from PyQt5.QtWidgets import QWidget, QApplication, QVBoxLayout, QHBoxLayout, QPushButton, QLabel, QFileDialog
from PyQt5.Qt import QPixmap, QPoint, Qt, QPainter, QIcon
from PyQt5.QtCore import QSize
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtGui import QImageReader

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 543 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 678 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 405 KiB

View File

@ -1,9 +0,0 @@
from ui import MainDemo
from config import *
if __name__ == '__main__':
app = QApplication(sys.argv)
box = MainDemo()
box.show()
app.exec_()

View File

@ -1,157 +0,0 @@
# -*- coding: utf-8 -*-
from .config import *
class ImageBox(QWidget):
def __init__(self):
super(ImageBox, self).__init__()
self.img = None
self.scaled_img = None
self.point = QPoint(100, 100)
self.start_pos = None
self.end_pos = None
self.left_click = False
self.scale = 1
def init_ui(self):
self.setWindowTitle("ImageBox")
def set_image(self, img_path):
"""
open image file
:param img_path: image file path
:return:
"""
# img = QImageReader(img_path)
# img.setScaledSize(QSize(self.size().width(), self.size().height()))
# img = img.read()
self.img = QPixmap(img_path)
# print(self.img.size(),self.img.size().width(),self.img.size().height())
self.scaled_img = self.img
# print(img_size)
img_size = self.scaled_img.size()
x = min(500, max((1000 - img_size.width()) // 2, 0))
y = min(300, max((600 - img_size.height()) // 2 - 60, 0))
# print(x,y)
self.point = QPoint(x, y)
def paintEvent(self, e):
"""
receive paint events
:param e: QPaintEvent
:return:
"""
if self.scaled_img:
painter = QPainter()
painter.begin(self)
painter.scale(self.scale, self.scale)
painter.drawPixmap(self.point, self.scaled_img)
painter.end()
def wheelEvent(self, event):
angle = event.angleDelta() / 8 # 返回QPoint对象为滚轮转过的数值单位为1/8度
angleY = angle.y()
# 获取当前鼠标相对于view的位置
if angleY > 0:
self.scale *= 1.1
else: # 滚轮下滚
self.scale *= 0.9
self.adjustSize()
self.update()
def mouseMoveEvent(self, e):
"""
mouse move events for the widget
:param e: QMouseEvent
:return:
"""
if self.left_click:
self.end_pos = e.pos() - self.start_pos
self.point = self.point + self.end_pos
self.start_pos = e.pos()
self.repaint()
def mousePressEvent(self, e):
"""
mouse press events for the widget
:param e: QMouseEvent
:return:
"""
if e.button() == Qt.LeftButton:
self.left_click = True
self.start_pos = e.pos()
def mouseReleaseEvent(self, e):
"""
mouse release events for the widget
:param e: QMouseEvent
:return:
"""
if e.button() == Qt.LeftButton:
self.left_click = False
class MainDemo(QWidget):
def __init__(self):
super(MainDemo, self).__init__()
self.setWindowTitle("Image Viewer")
self.setFixedSize(1000, 600)
self.setWindowIcon(QIcon('./app/data/icons/logo.svg'))
self.zoom_in = QPushButton("")
self.zoom_in.clicked.connect(self.large_click)
self.zoom_in.setFixedSize(30, 30)
in_icon = QIcon("./app/ImageBox/icons/zoom_in.jpg")
self.zoom_in.setIcon(in_icon)
self.zoom_in.setIconSize(QSize(30, 30))
self.zoom_out = QPushButton("")
self.zoom_out.clicked.connect(self.small_click)
self.zoom_out.setFixedSize(30, 30)
out_icon = QIcon("./app/ImageBox/icons/zoom_out.jpg")
self.zoom_out.setIcon(out_icon)
self.zoom_out.setIconSize(QSize(30, 30))
w = QWidget(self)
layout = QHBoxLayout()
layout.addWidget(self.zoom_in)
layout.addWidget(self.zoom_out)
layout.setAlignment(Qt.AlignLeft)
w.setLayout(layout)
w.setFixedSize(550, 50)
self.box = ImageBox()
self.box.resize(500, 300)
layout = QVBoxLayout()
layout.addWidget(w)
layout.addWidget(self.box)
self.setLayout(layout)
def open_image(self):
"""
select image file and open it
:return:
"""
img_name, _ = QFileDialog.getOpenFileName(self, "Open Image File", "*.jpg;;*.png;;*.jpeg")
self.box.set_image(img_name)
def large_click(self):
"""
used to enlarge image
:return:
"""
if self.box.scale < 2:
self.box.scale += 0.1
self.box.adjustSize()
self.update()
def small_click(self):
"""
used to reduce image
:return:
"""
if self.box.scale > 0.1:
self.box.scale -= 0.2
self.box.adjustSize()
self.update()

View File

@ -1,18 +0,0 @@
from PyQt5.QtGui import QIcon
class Icon:
Default_avatar_path = './app/data/icons/default_avatar.svg'
MainWindow_Icon = QIcon('./app/data/icons/logo.svg')
Default_avatar = QIcon(Default_avatar_path)
Output = QIcon('./app/data/icons/output.svg')
Back = QIcon('./app/data/icons/back.svg')
ToDocx = QIcon('app/data/icons/word.svg')
ToCSV = QIcon('app/data/icons/csv.svg')
ToHTML = QIcon('app/data/icons/html.svg')
Chat_Icon = QIcon('./app/data/icons/chat.svg')
Contact_Icon = QIcon('./app/data/icons/contact.svg')
MyInfo_Icon = QIcon('./app/data/icons/myinfo.svg')
Annual_Report_Icon = QIcon('./app/data/icons/annual_report.svg')
Analysis_Icon = QIcon('./app/data/icons/analysis.svg')
Emotion_Icon = QIcon('./app/data/icons/emotion.svg')

View File

@ -1,17 +0,0 @@
# -*- coding: utf-8 -*-
"""
@File : __init__.py.py
@Author : Shuaikang Zhou
@Time : 2022/12/13 14:19
@IDE : Pycharm
@Version : Python3.10
@comment : ···
"""
# from .ICON import Icon
# from .chat import chat
from app.Ui import mainview
# 文件__init__.py
# from login import login
from app.Ui.decrypt import decrypt
__all__ = ["decrypt", 'mainview', 'chat']

View File

@ -1,9 +0,0 @@
# -*- coding: utf-8 -*-
"""
@File : __init__.py.py
@Author : Shuaikang Zhou
@Time : 2022/12/13 20:33
@IDE : Pycharm
@Version : Python3.10
@comment : ···
"""

View File

@ -1,499 +0,0 @@
# -*- coding: utf-8 -*-
"""
@File : chat.py
@Author : Shuaikang Zhou
@Time : 2022/12/13 17:07
@IDE : Pycharm
@Version : Python3.10
@comment : 聊天窗口
"""
import time
import traceback
from typing import Dict
import xmltodict
from PIL import Image
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from app.components.Button_Contact import ContactUi
from app.log import logger, log
from .chatUi import *
from ...DataBase import data
from ...ImageBox.ui import MainDemo
class ChatController(QWidget, Ui_Form):
exitSignal = pyqtSignal()
urlSignal = pyqtSignal(QUrl)
# username = ''
def __init__(self, me, parent=None):
super(ChatController, self).__init__(parent)
self.chatroomFlag = None
self.ta_avatar = None
self.setupUi(self)
self.message = self.message_2
self.frame = self.frame_2
self.scrollAreaWidgetContents = self.scrollAreaWidgetContents_2
self.label_remark = self.label_remark_2
self.textEdit = self.textEdit_2
self.setWindowTitle('WeChat')
self.setWindowIcon(QIcon('./app/data/icon.png'))
self.initui()
self.Me = me
self.Thread = ChatMsg(self.Me.wxid, None)
self.Thread.isSend_signal.connect(self.showMsg)
self.Thread.okSignal.connect(self.setScrollBarPos)
self.contacts: Dict[str, ContactUi] = {}
self.last_btn = None
self.chat_flag = True
# self.showChat()
self.message.verticalScrollBar().valueChanged.connect(self.textbrower_verticalScrollBar)
self.show_flag = False
self.ta_username = None
self.last_pos = 0
self.last_msg_time = 0 # 上次信息的时间
self.last_talkerId = None
self.now_talkerId = None
self.showChat()
def initui(self):
self.qurl = QUrl('baidu.com')
# self.urlSignal.connect(self.hyperlink)
self.message.setOpenLinks(False)
self.message.setOpenExternalLinks(False)
# self.message.anchorClicked(self.hyperlink())
self.message.anchorClicked.connect(self.hyperlink)
self.btn_sendMsg_2.setToolTip('按Enter键发送按Ctrl+Enter键换行')
def showChat(self):
"""
显示联系人界面
:return:
"""
if self.show_flag:
return
self.show_flag = True
rconversations = data.get_rconversation()
# max_hight = max(len(rconversations) * 80, 680)
max_hight = max(len(rconversations) * 80, self.size().height())
self.scrollAreaWidgetContents.setGeometry(
QtCore.QRect(0, 0, 300, max_hight))
for i in range(len(rconversations)):
rconversation = rconversations[i]
username = rconversation[1]
# print('联系人:', i, rconversation)
pushButton_2 = ContactUi(self.scrollAreaWidgetContents, i, rconversation)
pushButton_2.setGeometry(QtCore.QRect(0, 80 * i, 300, 80))
pushButton_2.setLayoutDirection(QtCore.Qt.LeftToRight)
pushButton_2.clicked.connect(pushButton_2.show_msg)
pushButton_2.usernameSingal.connect(self.Chat)
self.contacts[username] = pushButton_2
def Chat(self, talkerId):
"""
聊天界面 点击联系人头像时候显示聊天数据
:param talkerId:
:return:
"""
self.now_talkerId = talkerId
# 把当前按钮设置为灰色
if self.last_talkerId and self.last_talkerId != talkerId:
print('对方账号:', self.last_talkerId)
self.contacts[self.last_talkerId].setStyleSheet(
"QPushButton {background-color: rgb(220,220,220);}"
"QPushButton:hover{background-color: rgb(208,208,208);}\n"
)
self.last_talkerId = talkerId
self.contacts[talkerId].setStyleSheet(
"QPushButton {background-color: rgb(198,198,198);}"
"QPushButton:hover{background-color: rgb(209,209,209);}\n"
)
conRemark = self.contacts[talkerId].contact.conRemark
self.label_remark.setText(conRemark)
self.message.clear()
self.message.append(talkerId)
self.ta_username = talkerId
if '@chatroom' in talkerId:
self.chatroomFlag = True
else:
self.chatroomFlag = False
self.ta_avatar = self.contacts[talkerId].contact.avatar_path
self.textEdit.setFocus()
self.Thread.ta_u = talkerId
self.Thread.msg_id = 0
self.Thread.start()
# 创建新的线程用于显示聊天记录
def closeEvent(self, a0: QtGui.QCloseEvent) -> None:
print("closed")
self.exitSignal.emit()
self.close()
def textbrower_verticalScrollBar(self, pos):
"""
滚动条到0之后自动更新聊天记录
:param pos:
:return:
"""
# print(pos)
if pos > 0:
return
self.last_pos = self.message.verticalScrollBar().maximum()
self.Thread.start()
def setScrollBarPos(self, pos):
"""
将滚动条位置设置为上次看到的地方
:param pos:
:return:
"""
pos = self.message.verticalScrollBar().maximum() - self.last_pos
print(pos)
self.message.verticalScrollBar().setValue(pos)
def check_time(self, msg_time):
"""
判断两次聊天时间是否大于五分钟
超过五分钟就显示时间
:param msg_time:
:return:
"""
dt = msg_time - self.last_msg_time
# print(msg_time)
if abs(dt // 1000) >= 300:
s_l = time.localtime(msg_time / 1000)
ts = time.strftime("%Y-%m-%d %H:%M", s_l)
html = '''
<table align="center" style="vertical-align: middle;">
<tbody>
<tr>
<td>%s</td>
</tr>
</tbody>
</table>''' % (ts)
# print(html)
self.last_msg_time = msg_time
self.message.insertHtml(html)
@log
def showMsg(self, message):
"""
显示聊天消息
:param message:
:return:
"""
msgId = message[0]
# print(msgId, type(msgId))
self.message.moveCursor(self.message.textCursor().Start)
ta_username = message[7]
msgType = str(message[2])
isSend = message[4]
content = message[8]
imgPath = message[9]
msg_time = message[6]
self.check_time(msg_time)
if msgType == '1':
# return
self.show_text(isSend, content)
elif msgType == '3':
# return
self.show_img(isSend, imgPath, content)
elif msgType == '47':
# return
self.show_emoji(isSend, imgPath, content)
elif msgType == '268445456':
self.show_recall_information(content)
elif msgType == '922746929':
self.pat_a_pat(content)
# self.message.moveCursor(self.message.textCursor().End)
@log
def pat_a_pat(self, content):
try:
pat_data = xmltodict.parse(content)
pat_data = pat_data['msg']['appmsg']['patMsg']['records']['record']
fromUser = pat_data['fromUser']
pattedUser = pat_data['pattedUser']
template = pat_data['template']
template = ''.join(template.split('${pattedusername@textstatusicon}'))
template = ''.join(template.split('${fromusername@textstatusicon}'))
template = template.replace(f'${{{fromUser}}}', data.get_conRemark(fromUser))
template = template.replace(f'${{{pattedUser}}}', data.get_conRemark(pattedUser))
print(template)
except Exception as e:
print(e)
template = '糟糕!出错了。'
html = '''
<table align="center" style="vertical-align: middle;">
<tbody>
<tr>
<td>%s</td>
</tr>
</tbody>
</table>''' % template
self.message.insertHtml(html)
@log
def show_recall_information(self, content):
html = '''
<table align="center" style="vertical-align: middle;">
<tbody>
<tr>
<td>%s</td>
</tr>
</tbody>
</table>''' % content
self.message.insertHtml(html)
@log
def show_emoji(self, isSend, imagePath, content):
imgPath = data.get_emoji(imagePath)
if not imgPath:
return False
try:
image = Image.open(imgPath)
except Exception as e:
logger.error(f"\nshow_emoji is error,here are details:\n{traceback.format_exc()}")
print(e)
return
imagePixmap = image.size # 宽高像素
# 设置最大宽度
if imagePixmap[0] < 150:
size = ""
else:
size = '''height="150" width="150"'''
html = '''
<td style="border: 1px #000000 solid;" height="150">
<img src="{0}" {1} >
</td>
'''.format(imgPath, size)
style = 'vertical-align: top'
if isSend:
self.right(html, style=style)
else:
if self.chatroomFlag:
username = content.split(':')[0]
self.chatroom_left(html, username=username, style=style)
self.left(html, style=style)
@log
def show_img(self, isSend, imgPath, content):
'THUMBNAIL_DIRPATH://th_29cd0f0ca87652943be9ede365aabeaa'
# imgPath = imgPath.split('th_')[1]
imgPath = data.get_imgPath(imgPath)
imgPath = f'./app/data/image2/{imgPath[0:2]}/{imgPath[2:4]}/{imgPath}'
html = '''
<td style="border: 1px #000000 solid;" height="150">
<a href="%s" target="_blank" height="150">
<img herf= "baidu.com" align="right" src="%s" style="max-height:100%%" height="200">
</a>
</td>
''' % (imgPath, imgPath)
style = 'vertical-align: top'
if isSend:
self.right(html, style=style)
else:
if self.chatroomFlag:
username = content.split(':')[0]
self.chatroom_left(html, username=username, style=style)
else:
self.left(html, style=style)
@log
def show_text(self, isSend, content):
if isSend:
html = '''
<td style="background-color: #9EEA6A;border-radius: 40px;">&nbsp;%s&nbsp;</td>
''' % content
self.right(html)
else:
if self.chatroomFlag:
# print(content)
'wxid_mv4jjhc0w0w521:'
username = content.split(':')[0]
msg = ''.join(content.split(':')[1:])
# avatar = data.get_avator(username)
html = '''
<td max-width = 300 style="background-color: #fff;border-radius: 4px;">
%s
</td>
''' % (msg)
# self.left(html, avatar=avatar)
self.chatroom_left(html, username=username)
else:
html = '''
<td max-width = 300 style="background-color: #fff;border-radius: 4px;">&nbsp;%s&nbsp;</td>
''' % (content)
self.left(html)
def hyperlink(self, url: QUrl):
"""
超链接点击之后放大显示图片
:param url:
:return:
"""
path = data.clearImagePath(url.path())
print(url.path(), path)
self.imagebox = MainDemo()
self.imagebox.show()
self.imagebox.box.set_image(path)
def right(self, content, style='vertical-align: middle'):
html = '''
<div>
<table align="right" style="%s;">
<tbody>
<tr>
%s
<td></td>
<td style="border: 1px #000000 solid"><img align="right" src="%s" width="45" height="45"/></td>
<td width="15"></td>
</tr>
</tbody>
</table>
</div>
''' % (style, content, self.Me.avatar_path)
# print('总的HTML')
# print(html)
self.message.insertHtml(html)
def left(self, content, avatar=None, style='vertical-align: middle'):
if not avatar:
avatar = self.ta_avatar
if self.chatroomFlag == 5:
try:
username, msg = content.split('\n')
avatar = data.get_avator(username)
html = '''
<div>
<table align="left" style="%s;">
<tbody>
<tr>
<td width="15"></td>
<td rowspan="2" style="border: 1px #000000 solid"><img align="right" src="%s" width="45" height="45"/></td>
<td></td>
<td></td>
</tr>
<tr>
<td width="15"></td>
<td></td>
%s
</tr>
</tbody>
</table>
</div>
''' % (style, avatar, msg)
except:
return
else:
html = '''
<div>
<table align="left" style="%s;">
<tbody>
<tr>
<td width="15"></td>
<td style="border: 1px #000000 solid"><img align="right" src="%s" width="45" height="45"/></td>
<td></td>
%s
</tr>
</tbody>
</table>
</div>
''' % (style, avatar, content)
self.message.insertHtml(html)
def chatroom_left(self, content, username, style='vertical-align: middle'):
# if username:
avatar = data.get_avator(username)
# conRemark = data.get_conRemark(username)
conRemark = data.get_conRemark(username)
html = '''
<div>
<table align="left" style="%s;">
<tbody>
<tr>
<td width="15"></td>
<td rowspan="2" style="border: 1px #000000 solid"><img align="right" src="%s" width="45" height="45"/></td>
<td></td>
<td>%s</td>
</tr>
<tr>
<td width="15"></td>
<td></td>
%s
</tr>
</tbody>
</table>
</div>
''' % (style, avatar, conRemark, content)
self.message.insertHtml(html)
def destroy_me(self):
"""注销账户"""
pass
class ChatMsg(QThread):
"""
多线程显示信息
"""
isSend_signal = pyqtSignal(tuple)
okSignal = pyqtSignal(int)
def __init__(self, my_u, ta_u, parent=None):
super().__init__(parent)
self.sec = 2 # 默认1000秒
self.my_u = my_u
self.ta_u = ta_u
self.my_avatar = data.get_avator(my_u)
self.msg_id = 0
def run(self):
self.ta_avatar = data.get_avator(self.ta_u)
messages = data.get_message(self.ta_u, self.msg_id)
# messages.reverse()
for message in messages:
self.isSend_signal.emit(message)
self.msg_id += 1
self.okSignal.emit(1)
class myTextEdit(QtWidgets.QTextEdit): # 继承 原本组件
sendSignal = pyqtSignal(str)
def __init__(self, parent):
QtWidgets.QTextEdit.__init__(self, parent)
self.parent = parent
_translate = QtCore.QCoreApplication.translate
self.setHtml(_translate("Dialog",
"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" "
"\"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
"<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
"p, li { white-space: pre-wrap; }\n"
"</style></head><body style=\" font-family:\'SimSun\'; font-size:15pt; "
"font-weight:400; font-style:normal;\">\n"
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; "
"margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><br "
"/></p></body></html>"))
def keyPressEvent(self, event):
QtWidgets.QTextEdit.keyPressEvent(self, event)
if event.key() == Qt.Key_Return: # 如果是Enter 按钮
modifiers = event.modifiers()
if modifiers == Qt.ControlModifier:
print('success press ctrl+enter key', self.toPlainText())
self.append('\0')
return
self.sendSignal.emit(self.toPlainText())
print('success press enter key', self.toPlainText())

View File

@ -1,157 +0,0 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'chatUi.ui'
#
# Created by: PyQt5 UI code generator 5.15.7
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName("Form")
Form.resize(878, 720)
self.horizontalLayout = QtWidgets.QHBoxLayout(Form)
self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout.setSpacing(0)
self.horizontalLayout.setObjectName("horizontalLayout")
self.scrollArea_2 = QtWidgets.QScrollArea(Form)
self.scrollArea_2.setEnabled(True)
self.scrollArea_2.setMaximumSize(QtCore.QSize(325, 150000))
self.scrollArea_2.setAutoFillBackground(False)
self.scrollArea_2.setFrameShape(QtWidgets.QFrame.NoFrame)
self.scrollArea_2.setFrameShadow(QtWidgets.QFrame.Raised)
self.scrollArea_2.setMidLineWidth(0)
self.scrollArea_2.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
self.scrollArea_2.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.scrollArea_2.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.AdjustToContentsOnFirstShow)
self.scrollArea_2.setWidgetResizable(False)
self.scrollArea_2.setObjectName("scrollArea_2")
self.scrollAreaWidgetContents_2 = QtWidgets.QWidget()
self.scrollAreaWidgetContents_2.setGeometry(QtCore.QRect(0, 0, 300, 12000))
self.scrollAreaWidgetContents_2.setObjectName("scrollAreaWidgetContents_2")
self.pushButton_3 = QtWidgets.QPushButton(self.scrollAreaWidgetContents_2)
self.pushButton_3.setGeometry(QtCore.QRect(0, 0, 300, 80))
self.pushButton_3.setLayoutDirection(QtCore.Qt.LeftToRight)
self.pushButton_3.setAutoFillBackground(False)
self.pushButton_3.setText("")
self.pushButton_3.setIconSize(QtCore.QSize(80, 80))
self.pushButton_3.setObjectName("pushButton_3")
self.label_2 = QtWidgets.QLabel(self.scrollAreaWidgetContents_2)
self.label_2.setGeometry(QtCore.QRect(220, 10, 72, 15))
self.label_2.setObjectName("label_2")
self.scrollArea_2.setWidget(self.scrollAreaWidgetContents_2)
self.horizontalLayout.addWidget(self.scrollArea_2)
self.frame_2 = QtWidgets.QFrame(Form)
self.frame_2.setMinimumSize(QtCore.QSize(500, 500))
self.frame_2.setStyleSheet("background-color: #F5F5F5;")
self.frame_2.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame_2.setFrameShadow(QtWidgets.QFrame.Raised)
self.frame_2.setObjectName("frame_2")
self.verticalLayout = QtWidgets.QVBoxLayout(self.frame_2)
self.verticalLayout.setContentsMargins(0, 0, 0, 0)
self.verticalLayout.setSpacing(0)
self.verticalLayout.setObjectName("verticalLayout")
self.horizontalLayout_3 = QtWidgets.QHBoxLayout()
self.horizontalLayout_3.setObjectName("horizontalLayout_3")
self.label_remark_2 = QtWidgets.QLabel(self.frame_2)
font = QtGui.QFont()
font.setPointSize(12)
self.label_remark_2.setFont(font)
self.label_remark_2.setText("")
self.label_remark_2.setObjectName("label_remark_2")
self.horizontalLayout_3.addWidget(self.label_remark_2)
spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.horizontalLayout_3.addItem(spacerItem)
self.toolButton_2 = QtWidgets.QToolButton(self.frame_2)
self.toolButton_2.setObjectName("toolButton_2")
self.horizontalLayout_3.addWidget(self.toolButton_2)
self.verticalLayout.addLayout(self.horizontalLayout_3)
self.line_5 = QtWidgets.QFrame(self.frame_2)
self.line_5.setFrameShape(QtWidgets.QFrame.HLine)
self.line_5.setFrameShadow(QtWidgets.QFrame.Sunken)
self.line_5.setObjectName("line_5")
self.verticalLayout.addWidget(self.line_5)
self.message_2 = QtWidgets.QTextBrowser(self.frame_2)
self.message_2.setContextMenuPolicy(QtCore.Qt.ActionsContextMenu)
self.message_2.setStyleSheet("background-color: #F5F5F5;")
self.message_2.setObjectName("message_2")
self.verticalLayout.addWidget(self.message_2)
self.line_6 = QtWidgets.QFrame(self.frame_2)
self.line_6.setFrameShape(QtWidgets.QFrame.HLine)
self.line_6.setFrameShadow(QtWidgets.QFrame.Sunken)
self.line_6.setObjectName("line_6")
self.verticalLayout.addWidget(self.line_6)
self.textEdit_2 = QtWidgets.QTextEdit(self.frame_2)
font = QtGui.QFont()
font.setPointSize(15)
self.textEdit_2.setFont(font)
self.textEdit_2.setAutoFillBackground(False)
self.textEdit_2.setStyleSheet("background-color: #F5F5F5;")
self.textEdit_2.setFrameShape(QtWidgets.QFrame.NoFrame)
self.textEdit_2.setOverwriteMode(False)
self.textEdit_2.setTabStopWidth(80)
self.textEdit_2.setAcceptRichText(True)
self.textEdit_2.setCursorWidth(1)
self.textEdit_2.setTextInteractionFlags(QtCore.Qt.TextEditorInteraction)
self.textEdit_2.setObjectName("textEdit_2")
self.verticalLayout.addWidget(self.textEdit_2)
self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.horizontalLayout_2.addItem(spacerItem1)
self.btn_sendMsg_2 = QtWidgets.QPushButton(self.frame_2)
font = QtGui.QFont()
font.setFamily("黑体")
font.setPointSize(15)
font.setBold(False)
font.setWeight(50)
self.btn_sendMsg_2.setFont(font)
self.btn_sendMsg_2.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor))
self.btn_sendMsg_2.setMouseTracking(False)
self.btn_sendMsg_2.setAutoFillBackground(False)
self.btn_sendMsg_2.setStyleSheet("QPushButton {\n"
" background-color:rgb(233,233,233);\n"
" padding: 10px;\n"
" color:rgb(5,180,104);}\n"
" QPushButton:hover{\n"
" background-color:rgb(198,198,198)}\n"
" ")
self.btn_sendMsg_2.setIconSize(QtCore.QSize(40, 40))
self.btn_sendMsg_2.setCheckable(False)
self.btn_sendMsg_2.setAutoDefault(True)
self.btn_sendMsg_2.setObjectName("btn_sendMsg_2")
self.horizontalLayout_2.addWidget(self.btn_sendMsg_2)
self.horizontalLayout_2.setStretch(0, 7)
self.horizontalLayout_2.setStretch(1, 2)
self.verticalLayout.addLayout(self.horizontalLayout_2)
self.verticalLayout.setStretch(0, 2)
self.verticalLayout.setStretch(1, 2)
self.verticalLayout.setStretch(2, 60)
self.verticalLayout.setStretch(3, 2)
self.verticalLayout.setStretch(4, 2)
self.verticalLayout.setStretch(5, 1)
self.horizontalLayout.addWidget(self.frame_2)
self.retranslateUi(Form)
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
_translate = QtCore.QCoreApplication.translate
Form.setWindowTitle(_translate("Form", "Form"))
self.label_2.setText(_translate("Form", "TextLabel"))
self.toolButton_2.setText(_translate("Form", "..."))
self.textEdit_2.setHtml(_translate("Form",
"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
"<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
"p, li { white-space: pre-wrap; }\n"
"</style></head><body style=\" font-family:\'SimSun\'; font-size:15pt; font-weight:400; font-style:normal;\">\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> </p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> </p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> </p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> </p></body></html>"))
self.btn_sendMsg_2.setText(_translate("Form", "发送"))

View File

@ -1,140 +0,0 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'form.ui'
#
# Created by: PyQt5 UI code generator 5.15.7
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName("Form")
Form.resize(878, 720)
self.horizontalLayout = QtWidgets.QHBoxLayout(Form)
self.horizontalLayout.setObjectName("horizontalLayout")
self.scrollArea_2 = QtWidgets.QScrollArea(Form)
self.scrollArea_2.setEnabled(True)
self.scrollArea_2.setMaximumSize(QtCore.QSize(325, 150000))
self.scrollArea_2.setAutoFillBackground(False)
self.scrollArea_2.setFrameShape(QtWidgets.QFrame.WinPanel)
self.scrollArea_2.setFrameShadow(QtWidgets.QFrame.Raised)
self.scrollArea_2.setMidLineWidth(0)
self.scrollArea_2.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
self.scrollArea_2.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.scrollArea_2.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.AdjustToContentsOnFirstShow)
self.scrollArea_2.setWidgetResizable(False)
self.scrollArea_2.setObjectName("scrollArea_2")
self.scrollAreaWidgetContents_2 = QtWidgets.QWidget()
self.scrollAreaWidgetContents_2.setGeometry(QtCore.QRect(0, 0, 300, 12000))
self.scrollAreaWidgetContents_2.setObjectName("scrollAreaWidgetContents_2")
self.pushButton_3 = QtWidgets.QPushButton(self.scrollAreaWidgetContents_2)
self.pushButton_3.setGeometry(QtCore.QRect(0, 0, 300, 80))
self.pushButton_3.setLayoutDirection(QtCore.Qt.LeftToRight)
self.pushButton_3.setAutoFillBackground(False)
self.pushButton_3.setText("")
self.pushButton_3.setIconSize(QtCore.QSize(80, 80))
self.pushButton_3.setObjectName("pushButton_3")
self.label_2 = QtWidgets.QLabel(self.scrollAreaWidgetContents_2)
self.label_2.setGeometry(QtCore.QRect(220, 10, 72, 15))
self.label_2.setObjectName("label_2")
self.scrollArea_2.setWidget(self.scrollAreaWidgetContents_2)
self.horizontalLayout.addWidget(self.scrollArea_2)
self.frame_2 = QtWidgets.QFrame(Form)
self.frame_2.setMinimumSize(QtCore.QSize(500, 500))
self.frame_2.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame_2.setFrameShadow(QtWidgets.QFrame.Raised)
self.frame_2.setObjectName("frame_2")
self.verticalLayout = QtWidgets.QVBoxLayout(self.frame_2)
self.verticalLayout.setObjectName("verticalLayout")
self.horizontalLayout_3 = QtWidgets.QHBoxLayout()
self.horizontalLayout_3.setObjectName("horizontalLayout_3")
self.label_remark_2 = QtWidgets.QLabel(self.frame_2)
font = QtGui.QFont()
font.setPointSize(12)
self.label_remark_2.setFont(font)
self.label_remark_2.setText("")
self.label_remark_2.setObjectName("label_remark_2")
self.horizontalLayout_3.addWidget(self.label_remark_2)
spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.horizontalLayout_3.addItem(spacerItem)
self.toolButton_2 = QtWidgets.QToolButton(self.frame_2)
self.toolButton_2.setObjectName("toolButton_2")
self.horizontalLayout_3.addWidget(self.toolButton_2)
self.verticalLayout.addLayout(self.horizontalLayout_3)
self.line_4 = QtWidgets.QFrame(self.frame_2)
self.line_4.setLineWidth(6)
self.line_4.setFrameShape(QtWidgets.QFrame.VLine)
self.line_4.setFrameShadow(QtWidgets.QFrame.Sunken)
self.line_4.setObjectName("line_4")
self.verticalLayout.addWidget(self.line_4)
self.line_5 = QtWidgets.QFrame(self.frame_2)
self.line_5.setFrameShape(QtWidgets.QFrame.HLine)
self.line_5.setFrameShadow(QtWidgets.QFrame.Sunken)
self.line_5.setObjectName("line_5")
self.verticalLayout.addWidget(self.line_5)
self.message_2 = QtWidgets.QTextBrowser(self.frame_2)
self.message_2.setContextMenuPolicy(QtCore.Qt.ActionsContextMenu)
self.message_2.setStyleSheet("background-color: #F5F5F5;")
self.message_2.setObjectName("message_2")
self.verticalLayout.addWidget(self.message_2)
self.textEdit_2 = QtWidgets.QTextEdit(self.frame_2)
font = QtGui.QFont()
font.setPointSize(15)
self.textEdit_2.setFont(font)
self.textEdit_2.setTabStopWidth(80)
self.textEdit_2.setCursorWidth(1)
self.textEdit_2.setObjectName("textEdit_2")
self.verticalLayout.addWidget(self.textEdit_2)
self.line_6 = QtWidgets.QFrame(self.frame_2)
self.line_6.setFrameShape(QtWidgets.QFrame.HLine)
self.line_6.setFrameShadow(QtWidgets.QFrame.Sunken)
self.line_6.setObjectName("line_6")
self.verticalLayout.addWidget(self.line_6)
self.btn_sendMsg_2 = QtWidgets.QPushButton(self.frame_2)
font = QtGui.QFont()
font.setFamily("黑体")
font.setPointSize(15)
font.setBold(False)
font.setWeight(50)
self.btn_sendMsg_2.setFont(font)
self.btn_sendMsg_2.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor))
self.btn_sendMsg_2.setMouseTracking(False)
self.btn_sendMsg_2.setAutoFillBackground(False)
self.btn_sendMsg_2.setStyleSheet("QPushButton {\n"
" background-color: #f0f0f0;\n"
" \n"
" padding: 10px;\n"
" color:rgb(5,180,104);\n"
"}")
self.btn_sendMsg_2.setIconSize(QtCore.QSize(40, 40))
self.btn_sendMsg_2.setCheckable(False)
self.btn_sendMsg_2.setAutoDefault(True)
self.btn_sendMsg_2.setObjectName("btn_sendMsg_2")
self.verticalLayout.addWidget(self.btn_sendMsg_2)
self.verticalLayout.setStretch(0, 1)
self.verticalLayout.setStretch(2, 3)
self.verticalLayout.setStretch(3, 20)
self.verticalLayout.setStretch(4, 1)
self.verticalLayout.setStretch(6, 1)
self.horizontalLayout.addWidget(self.frame_2)
self.retranslateUi(Form)
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
_translate = QtCore.QCoreApplication.translate
Form.setWindowTitle(_translate("Form", "Form"))
self.label_2.setText(_translate("Form", "TextLabel"))
self.toolButton_2.setText(_translate("Form", "..."))
self.textEdit_2.setHtml(_translate("Form",
"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
"<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
"p, li { white-space: pre-wrap; }\n"
"</style></head><body style=\" font-family:\'SimSun\'; font-size:15pt; font-weight:400; font-style:normal;\">\n"
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><br /></p></body></html>"))
self.btn_sendMsg_2.setText(_translate("Form", "发送"))

Binary file not shown.

View File

@ -1,9 +0,0 @@
# -*- coding: utf-8 -*-
"""
@File : __init__.py.py
@Author : Shuaikang Zhou
@Time : 2022/12/13 20:33
@IDE : Pycharm
@Version : Python3.10
@comment : ···
"""

View File

@ -1,153 +0,0 @@
import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWebEngineWidgets import QWebEngineView
from PyQt5.QtWidgets import *
QCoreApplication.setAttribute(Qt.AA_UseSoftwareOpenGL)
from . import charts
class AnalysisController(QWidget):
def __init__(self, username, parent=None):
super().__init__(parent)
self.ta_username = username
# self.setWindowTitle('数据分析')
# self.setWindowIcon(QIcon('./app/data/icon.png'))
# self.setWindowFlag(Qt.FramelessWindowHint)
self.setStyleSheet('''QWidget{background-color:rgb(255, 255, 255);}''')
self.center()
self.setAttribute(Qt.WA_AttributeCount)
self.label_01()
self.isStart = False
def center(self): # 定义一个函数使得窗口居中显示
# 获取屏幕坐标系
screen = QDesktopWidget().screenGeometry()
# 获取窗口坐标系
size = self.geometry()
newLeft = (screen.width() - size.width()) / 2
newTop = (screen.height() - size.height()) / 2
self.move(int(newLeft), int(newTop))
def label_01(self):
self.label = QLabel(self)
size = self.geometry()
self.label.setGeometry(size.width() // 2, self.height() // 2, 100, 100)
self.label.setToolTip("这是一个标签")
self.m_movie()
def m_movie(self):
movie = QMovie("./app/data/bg.gif")
self.label.setMovie(movie)
movie.start()
def initUI(self):
self.label.setVisible(False)
# self.setStyleSheet('''QWidget{background-color:rgb(240, 240, 240);}''')
main_box = QVBoxLayout(self)
main_box.setContentsMargins(0, 0, 0, 0)
main_box.setSpacing(0)
self.browser1 = QWebEngineView()
self.browser1.load(QUrl('file:///data/聊天统计/title.html'))
self.browser1.setMinimumSize(810, 60)
self.browser1.setStyleSheet('''QWidget{background-color:rgb(240, 240, 240);}''')
self.browser2 = QWebEngineView()
self.browser2.load(QUrl('file:///data/聊天统计/wordcloud.html'))
self.browser2.setStyleSheet('''QWidget{background-color:rgb(240, 240, 240);}''')
# self.browser2.setMinimumWidth(810)
self.browser2.setMinimumSize(810, 810)
self.browser3 = QWebEngineView()
self.browser3.load(QUrl('file:///data/聊天统计/time.html'))
self.browser3.setMaximumSize(810, 100)
self.browser3.adjustSize()
self.browser4 = QWebEngineView()
self.browser4.load(QUrl('http://www.baidu.com'))
self.browser4.resize(800, 600)
self.browser5 = QWebEngineView()
self.browser5.load(QUrl('file:///data/聊天统计/chat_session.html'))
self.browser6 = QWebEngineView()
self.browser6.load(QUrl('file:///data/聊天统计/sports.html'))
self.browser7 = QWebEngineView()
self.browser7.load(QUrl('file:///data/聊天统计/month_num.html'))
self.browser8 = QWebEngineView()
self.browser8.load(QUrl('file:///data/聊天统计/calendar.html'))
self.browser9 = QWebEngineView()
self.browser9.load(QUrl('file:///data/聊天统计/msg_type_rate.html'))
self.browser10 = QWebEngineView()
self.browser10.load(QUrl('file:///data/聊天统计/send_recv_rate.html'))
self.browser10.adjustSize()
# self.browser10.
main_box.addWidget(self.browser1)
self.scrollArea = QScrollArea()
self.scrollArea.setEnabled(True)
self.scrollArea.adjustSize()
scrollAreaContent = QWidget(self.scrollArea)
scrollAreaContent.setStyleSheet('''QWidget{background-color:rgb(240, 240, 240);}''')
Vlayout2 = QVBoxLayout()
Vlayout2.setContentsMargins(0, 0, 0, 0)
Vlayout2.setSpacing(0)
Vlayout2.addWidget(self.browser3)
Vlayout2.addWidget(self.browser2)
Vlayout2.addWidget(self.browser8)
Vlayout2.addWidget(self.browser6)
Vlayout2.addWidget(self.browser5)
Vlayout2.addWidget(self.browser7)
Vlayout2.addWidget(self.browser9)
Vlayout2.addWidget(self.browser10)
scrollAreaContent.setLayout(Vlayout2)
self.scrollArea.setWidget(scrollAreaContent)
main_box.addWidget(self.scrollArea)
main_box.setStretch(0, 1)
main_box.setStretch(1, 10)
self.setLayout(main_box)
def setBackground(self):
palette = QPalette()
pix = QPixmap("./app/data/bg.png")
pix = pix.scaled(self.width(), self.height(), Qt.IgnoreAspectRatio, Qt.SmoothTransformation) # 自适应图片大小
palette.setBrush(self.backgroundRole(), QBrush(pix)) # 设置背景图片
# palette.setColor(self.backgroundRole(), QColor(192, 253, 123)) # 设置背景颜色
self.setPalette(palette)
def start(self):
if not self.isStart:
self.Thread = LoadData(self.ta_username)
self.Thread.okSignal.connect(self.initUI)
self.Thread.start()
self.isStart = True
class LoadData(QThread):
"""
发送信息线程
"""
okSignal = pyqtSignal(int)
def __init__(self, ta_u, parent=None):
super().__init__(parent)
self.ta_username = ta_u
def run(self):
charts.chat_start_endTime(self.ta_username)
charts.title(self.ta_username)
charts.send_recv_rate(self.ta_username)
charts.message_word_cloud(self.ta_username)
charts.msg_type_rate(self.ta_username)
charts.calendar_chart(self.ta_username)
charts.month_num(self.ta_username)
charts.sport(self.ta_username)
charts.chat_session(self.ta_username)
self.okSignal.emit(10)
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = MainWindow()
sys.exit(app.exec_())

View File

@ -1,539 +0,0 @@
import os
import traceback
import jieba
import pandas as pd
import xmltodict
from pyecharts import options as opts
from pyecharts.charts import Pie, WordCloud, Calendar, Bar, Line, Timeline, Grid
from app.log import logger, log
from ....DataBase import data
# from app.DataBase import data
data.mkdir(os.path.abspath('.') + '/data/聊天统计')
Type = {
'1': '文字',
'3': '图片',
'43': '视频',
'-1879048185': '微信运动排行榜',
'5': '',
'47': '表情包',
'268445456': '撤回消息',
'34': '语音',
'419430449': '转账',
'50': '语音电话',
'100001': '领取红包',
'10000': '消息已发出,但被对方拒收了。',
'822083633': '回复消息',
'922746929': '拍一拍',
'1090519089': '文件',
'318767153': '付款成功',
'436207665': '发红包',
'49': '分享链接'
}
charts_width = 800
charts_height = 450
wordcloud_width = 780
wordcloud_height = 720
@log
def send_recv_rate(username):
send_num = data.send_nums(username)
recv_num = data.recv_nums(username)
total_num = send_num + recv_num
print(send_num, recv_num)
c = (
Pie(init_opts=opts.InitOpts(
# bg_color='rgb(240,240,240)',
width=f"{charts_width}px",
height=f"{charts_height}px")
)
.add(
"",
[
('发送', send_num), ('接收', recv_num)
],
center=["40%", "50%"],
)
.set_global_opts(
title_opts=opts.TitleOpts(title=f"信息发送接收", subtitle=f"总计:{total_num}条消息", pos_bottom="0%"),
legend_opts=opts.LegendOpts(type_="scroll", pos_left="80%", orient="vertical"),
)
.set_series_opts(
label_opts=opts.LabelOpts(formatter="{b}:{d}%"),
)
.render("./data/聊天统计/send_recv_rate.html")
)
@log
def msg_type_rate(username):
type_data = data.msg_type_num(username)
type_data = sorted(type_data, key=lambda x: x[1], reverse=True)
data1 = type_data[:4]
data2 = sum(map(lambda x: x[1], type_data[4:]))
print(type_data)
new_data = []
for t in data1:
try:
new_data.append((Type[str(t[0])], t[1]))
except:
new_data.append(('未知类型', t[1]))
new_data.append(('其他', data2))
c = (
Pie(init_opts=opts.InitOpts(width=f"{charts_width}px", height=f"{charts_height}px"))
.add(
"",
new_data
,
center=["40%", "50%"],
)
.set_global_opts(
title_opts=opts.TitleOpts(title=f"消息类型占比", pos_bottom="0%"),
legend_opts=opts.LegendOpts(type_="scroll", pos_left="80%", orient="vertical"),
)
.set_series_opts(
label_opts=opts.LabelOpts(formatter="{b}:{d}%"),
)
.render("./data/聊天统计/msg_type_rate.html")
)
@log
def message_word_cloud(username):
text = data.get_text(username)
total_msg_len = len(text)
word_list = jieba.cut(text)
# word = " ".join(word_list)
# print(word)
stopwords = set()
content = [line.strip() for line in open('./app/data/stopwords.txt', 'r', encoding='utf-8').readlines()]
stopwords.update(content)
wordcount = {}
for word in jieba.cut(text):
if len(word) > 1 and word not in stopwords:
wordcount[word] = wordcount.get(word, 0) + 1
text_data = sorted(wordcount.items(), key=lambda x: x[1], reverse=True)
if len(text_data) > 100:
text_data = text_data[:100]
# print(text_data)
(
WordCloud(init_opts=opts.InitOpts(width=f"{wordcloud_width}px", height=f"{wordcloud_height}px"))
.add(series_name="聊天文字", data_pair=text_data, word_size_range=[20, 100])
.set_global_opts(
title_opts=opts.TitleOpts(
title=f"词云图", subtitle=f"总计{total_msg_len}",
title_textstyle_opts=opts.TextStyleOpts(font_size=23)
),
tooltip_opts=opts.TooltipOpts(is_show=True),
legend_opts=opts.LegendOpts(is_show=False)
)
.render("./data/聊天统计/wordcloud.html")
)
@log
def calendar_chart(username):
msg_data = data.get_msg_by_days(username, year='2022')
if not msg_data:
return False
min_ = min(map(lambda x: x[1], msg_data))
max_ = max(map(lambda x: x[1], msg_data))
c = (
Calendar(init_opts=opts.InitOpts(width=f"{charts_width}px", height=f"{charts_height}px"))
.add(
"",
msg_data,
calendar_opts=opts.CalendarOpts(range_="2022")
)
.set_global_opts(
title_opts=opts.TitleOpts(title="2022年聊天情况"),
visualmap_opts=opts.VisualMapOpts(
max_=max_,
min_=min_,
orient="horizontal",
# is_piecewise=True,
# pos_top="200px",
pos_bottom="0px",
pos_left="0px",
),
legend_opts=opts.LegendOpts(is_show=False)
)
.render("./data/聊天统计/calendar.html")
)
@log
def month_num(username):
"""
每月聊天条数
"""
msg_data = data.get_msg_by_month(username, year='2022')
y_data = list(map(lambda x: x[1], msg_data))
x_axis = list(map(lambda x: x[0], msg_data))
c = (
Bar(init_opts=opts.InitOpts(width=f"{charts_width}px", height=f"{charts_height}px"))
.add_xaxis(x_axis)
.add_yaxis("消息数量", y_data)
.set_global_opts(
title_opts=opts.TitleOpts(title="逐月统计", subtitle=None),
datazoom_opts=opts.DataZoomOpts(),
toolbox_opts=opts.ToolboxOpts(),
)
.render("./data/聊天统计/month_num.html")
)
@log
def chat_session(username):
msg_data = data.get_msg_by_hour(username)
x_axis = list(map(lambda x: x[0], msg_data))
y_data = list(map(lambda x: x[1], msg_data))
# print(x_axis)
# print(y_data)
# max_ = max(y_data)
c = (
Line(init_opts=opts.InitOpts(width=f"{charts_width}px", height=f"{charts_height}px"))
.add_xaxis(xaxis_data=x_axis)
.add_yaxis(
series_name="聊天频率",
y_axis=y_data,
markpoint_opts=opts.MarkPointOpts(
data=[
opts.MarkPointItem(type_="max", name="最大值"),
opts.MarkPointItem(type_="min", name="最小值", value=int(10)),
]
),
markline_opts=opts.MarkLineOpts(
data=[opts.MarkLineItem(type_="average", name="平均值")]
),
)
.set_global_opts(
title_opts=opts.TitleOpts(title="聊天时段", subtitle=None),
# datazoom_opts=opts.DataZoomOpts(),
# toolbox_opts=opts.ToolboxOpts(),
)
.set_series_opts(
label_opts=opts.LabelOpts(
is_show=False
)
)
.render("./data/聊天统计/chat_session.html")
)
@log
def sport(username):
sports = data.get_sport()
ranks = []
steps = []
date = []
for sport in sports:
try:
timestamp, content, t = sport
rank_data = xmltodict.parse(content)
sub_data = rank_data['msg']['appmsg']['hardwareinfo']['messagenodeinfo']
# print(sub_data)
# my_rank = sub_data['rankinfo']['rank']['rankdisplay']
# my_steps = int(sub_data['rankinfo']['score']['scoredisplay'])
# print(f'rank: {my_rank},steps: {my_steps}')
rank_view = rank_data['msg']['appmsg']['hardwareinfo']['rankview']['rankinfolist']['rankinfo']
for userinfo in rank_view:
username0 = userinfo['username']
if username0 == username:
rank_ta = int(userinfo['rank']['rankdisplay'])
steps_ta = int(userinfo['score']['scoredisplay'])
ranks.append(rank_ta)
steps.append(steps_ta)
date.append(t)
except:
logger.error(f"\nsport is error,here are details:\n{traceback.format_exc()}\n")
continue
try:
# todo 可能没有运动信息
df = pd.DataFrame({'ranks': ranks, 'score': steps, 'date': date}, index=date)
months = pd.date_range(date[0], date[-1], freq='M')
except:
months = []
tl = Timeline(init_opts=opts.InitOpts(width=f"{charts_width}px", height=f"{charts_height}px"))
tl.add_schema(is_auto_play=True)
for i in range(len(months) - 1):
da = df[(months[i + 1].strftime("%Y-%m-%d") >= df['date']) & (df['date'] > months[i].strftime("%Y-%m-%d"))]
bar = (
Bar(init_opts=opts.InitOpts(width=f"{charts_width}px", height=f"{charts_height}px"))
.add_xaxis(list(da['date']))
.add_yaxis(
"步数",
list(da['score']),
yaxis_index=1,
color="#d14a61",
)
.extend_axis(
yaxis=opts.AxisOpts(
name="步数",
type_="value",
# grid_index=0,
# min_=0,
# max_=250,
position="right",
axisline_opts=opts.AxisLineOpts(
linestyle_opts=opts.LineStyleOpts(color="#d14a61")
),
# axislabel_opts=opts.LabelOpts(formatter="{value} ml"),
)
)
.extend_axis(
yaxis=opts.AxisOpts(
type_="value",
name="排名",
# min_=0,
# max_=25,
position="left",
is_inverse=True,
is_show=False,
# interval=True,
# grid_index=1,
axisline_opts=opts.AxisLineOpts(
linestyle_opts=opts.LineStyleOpts(color="#675bba")
),
# axislabel_opts=opts.LabelOpts(formatter="{value} °C"),
splitline_opts=opts.SplitLineOpts(
is_show=True, linestyle_opts=opts.LineStyleOpts(opacity=1)
),
)
)
.set_global_opts(
title_opts=opts.TitleOpts(
title="{}".format(months[i + 1].strftime("%Y-%m")),
),
# legend_opts=opts.LegendOpts(is_show=False),
yaxis_opts=opts.AxisOpts(is_inverse=True),
# xaxis_opts=opts.AxisOpts(type_='time')
)
.set_series_opts(
label_opts=opts.LabelOpts(
is_show=False
)
)
)
# init_opts = opts.InitOpts(width="400px", height="235px")
line = (
Line(init_opts=opts.InitOpts(width=f"{charts_width}px", height=f"{charts_height}px"))
.add_xaxis(list(da['date']))
.add_yaxis(
"排名",
list(da['ranks']),
yaxis_index=0,
color="#675bba",
# label_opts=opts.LabelOpts(is_show=False),
)
.set_global_opts(
yaxis_opts=opts.AxisOpts(is_inverse=True),
# xaxis_opts=opts.AxisOpts(type_='time')
)
.set_series_opts(
label_opts=opts.LabelOpts(
is_show=False
)
)
)
bar.overlap(line)
grid = Grid()
grid.add(bar, opts.GridOpts(pos_left="5%", pos_right="11%"), is_control_axis_index=True)
# grid.render("grid_multi_yaxis.html")
tl.add(grid, "{}".format(months[i].strftime("%Y-%m")))
tl.render("./data/聊天统计/sports.html")
return {
username: {
'ranks': ranks,
'score': steps,
'date': date,
}
}
@log
def chat_start_endTime(username):
start_time = data.get_msg_start_time(username)
end_time = data.get_msg_end_time(username)
year = start_time[:4]
month = start_time[5:7]
day = start_time[8:10]
hour = start_time[11:13]
minute = start_time[14:16]
second = start_time[17:]
html = '''
<html>
<head>
<meta charset="UTF-8">
<title>聊天时间</title>
<style>
/* 倒计时开始 */
.gn_box {
padding: 0px 0px;
margin-bottom:0px;
text-align: center;
background-color: #fff;
}
#t_d{
color: #982585;
font-size: 18px;
}
#t_h{
color: #8f79c1;
font-size: 18px;
}
#t_m{
color: #65b4b5;
font-size: 18px;
}
#t_s{
color: #83caa3;
font-size: 18px;
}
#text{
color: #E80017;
font-size: 18px;
}
</style>
<!--倒计时开始-->
</head>
<body>
<div class="gn_box">
<h1>
<font color="#E80017"></font><font color="#D1002E">一次</font><font color="#BA0045">聊天</font><font
color="#A3005C">发生</font><font color="#8C0073"></font>
<font color="#75008A">%s</font><font color="#5E00A1">-</font><font color="#4700B8">%s</font><font
color="#3000CF"> %s</font><font color="#1900E6">:%s</font><font color="#0200FD">:%s</font>
</h1>
<center>
<div id="CountMsg" class="HotDate">
<span id="text">距今已有</span>
<span id="t_d">626 </span>
<span id="t_h">6 </span>
<span id="t_m">26 </span>
<span id="t_s">26 </span>
</div>
</center>
</div>
<!--倒计时结束-->
<script type="text/javascript"> function getRTime() {
var EndTime = new Date('%s');
var NowTime = new Date();
var t = NowTime.getTime()-EndTime.getTime();
var d = Math.floor(t / 1000 / 60 / 60 / 24);
var h = Math.floor(t / 1000 / 60 / 60 %% 24);
var m = Math.floor(t / 1000 / 60 %% 60);
var s = Math.floor(t / 1000 %% 60);
document.getElementById("t_d").innerHTML = d + "";
document.getElementById("t_h").innerHTML = h + "";
document.getElementById("t_m").innerHTML = m + "";
document.getElementById("t_s").innerHTML = s + "";
}
setInterval(getRTime, 1000);
</script>
</body>
</html>
''' % (year, month + '-' + day, hour, minute, second, start_time)
with open('./data/聊天统计/time.html', 'w', encoding='utf-8') as f:
f.write(html)
@log
def title(username):
conRemark = data.get_conRemark(username)
avatar = data.get_avator(username)
html = '''
<html>
<head>
<meta charset="UTF-8">
<title>聊天时间</title>
<style>
/* 倒计时开始 */
.gn_box {
padding: 0px 0px;
margin-bottom: 0px;
text-align: center;
background-color: #fff;
}
#t_d{
color: #982585;
font-size: 18px;
}
#t_h{
color: #8f79c1;
font-size: 18px;
}
#t_m{
color: #65b4b5;
font-size: 18px;
}
#t_s{
color: #83caa3;
font-size: 18px;
}
#text{
color: #E80017;
font-size: 18px;
}
#conRemark{
color: #A3005C;
font-size: 28px;
}
#table {
width: 600px; height: 100px;//可随意
position: absolute; left: 0; top: 0; right: 0; bottom: 0;
margin: auto; /* 有了这个就自动居中了 */
}
</style>
<!--倒计时开始-->
</head>
<body>
<div class="gn_box">
<table align="center" style="margin:0px auto;">
<tr valign="middle">
<td valign="middle">
<table>
<tr>
<td>
<img src="../../../%s" height="40" width="40"
alt="Avatar"/>
</td>
</tr>
</table>
</td>
<td align="center" valign="middle">
<table>
<tr>
<td>
<font id="conRemark">%s</font>
</td>
</tr>
</table>
</td>
</tr>
</table>
<div>
<span>
</span>
<span></span>
</div>
</div>
</body>
</html>
''' % (avatar, conRemark)
with open('./data/聊天统计/title.html', 'w', encoding='utf-8') as f:
f.write(html)
if __name__ == '__main__':
# send_recv_rate('wxid_wt2vsktnu4z022')
sport('wxid_wt2vsktnu4z022')

View File

@ -1,174 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Awesome-pyecharts</title>
<script type="text/javascript" src="https://assets.pyecharts.org/assets/v5/echarts.min.js"></script>
</head>
<body >
<div id="ec5cb8f7096941f5ba51d65454d9c631" class="chart-container" style="width:470px; height:270px; "></div>
<script>
var chart_ec5cb8f7096941f5ba51d65454d9c631 = echarts.init(
document.getElementById('ec5cb8f7096941f5ba51d65454d9c631'), 'white', {renderer: 'canvas'});
var option_ec5cb8f7096941f5ba51d65454d9c631 = {
"animation": true,
"animationThreshold": 2000,
"animationDuration": 1000,
"animationEasing": "cubicOut",
"animationDelay": 0,
"animationDurationUpdate": 300,
"animationEasingUpdate": "cubicOut",
"animationDelayUpdate": 0,
"aria": {
"enabled": false
},
"color": [
"#5470c6",
"#91cc75",
"#fac858",
"#ee6666",
"#73c0de",
"#3ba272",
"#fc8452",
"#9a60b4",
"#ea7ccc"
],
"series": [
{
"type": "pie",
"colorBy": "data",
"legendHoverLink": true,
"selectedMode": false,
"selectedOffset": 10,
"clockwise": true,
"startAngle": 90,
"minAngle": 0,
"minShowLabelAngle": 0,
"avoidLabelOverlap": true,
"stillShowZeroSum": true,
"percentPrecision": 2,
"showEmptyCircle": true,
"emptyCircleStyle": {
"color": "lightgray",
"borderColor": "#000",
"borderWidth": 0,
"borderType": "solid",
"borderDashOffset": 0,
"borderCap": "butt",
"borderJoin": "bevel",
"borderMiterLimit": 10,
"opacity": 1
},
"data": [
{
"name": "\u53d1\u9001",
"value": 0.6
},
{
"name": "\u63a5\u6536",
"value": 0.4
}
],
"radius": [
"0%",
"75%"
],
"center": [
"40%",
"50%"
],
"label": {
"show": true,
"margin": 8,
"formatter": "{b}: {c}"
},
"labelLine": {
"show": true,
"showAbove": false,
"length": 15,
"length2": 15,
"smooth": false,
"minTurnAngle": 90,
"maxSurfaceAngle": 90
},
"rippleEffect": {
"show": true,
"brushType": "stroke",
"scale": 2.5,
"period": 4
}
}
],
"legend": [
{
"data": [
"\u53d1\u9001",
"\u63a5\u6536"
],
"selected": {},
"type": "scroll",
"show": true,
"left": "60%",
"orient": "vertical",
"padding": 5,
"itemGap": 10,
"itemWidth": 25,
"itemHeight": 14,
"backgroundColor": "transparent",
"borderColor": "#ccc",
"borderWidth": 1,
"borderRadius": 0,
"pageButtonItemGap": 5,
"pageButtonPosition": "end",
"pageFormatter": "{current}/{total}",
"pageIconColor": "#2f4554",
"pageIconInactiveColor": "#aaa",
"pageIconSize": 15,
"animationDurationUpdate": 800,
"selector": false,
"selectorPosition": "auto",
"selectorItemGap": 7,
"selectorButtonGap": 10
}
],
"tooltip": {
"show": true,
"trigger": "item",
"triggerOn": "mousemove|click",
"axisPointer": {
"type": "line"
},
"showContent": true,
"alwaysShowContent": false,
"showDelay": 0,
"hideDelay": 100,
"enterable": false,
"confine": false,
"appendToBody": false,
"transitionDuration": 0.4,
"textStyle": {
"fontSize": 14
},
"borderWidth": 0,
"padding": 5,
"order": "seriesAsc"
},
"title": [
{
"show": true,
"text": "\u53d1\u9001\u63a5\u6536\u5360\u6bd4",
"target": "blank",
"subtarget": "blank",
"padding": 5,
"itemGap": 10,
"textAlign": "auto",
"textVerticalAlign": "auto",
"triggerEvent": false
}
]
};
chart_ec5cb8f7096941f5ba51d65454d9c631.setOption(option_ec5cb8f7096941f5ba51d65454d9c631);
</script>
</body>
</html>

View File

@ -1,116 +0,0 @@
# -*- coding: utf-8 -*-
"""
@File : contact.py
@Author : Shuaikang Zhou
@Time : 2022/12/13 15:07
@IDE : Pycharm
@Version : Python3.10
@comment : ···
"""
from typing import Dict
from PyQt5 import QtCore
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
import app.components.Button_Contact as MyLabel
from app import person
from app.DataBase import data
from app.Ui.contact.contactInfo import ContactInfo
from app.Ui.contact.contactUi import Ui_Dialog
EMOTION = 1
ANALYSIS = 2
class StackedWidget():
def __init__(self):
pass
class ContactController(QWidget, Ui_Dialog):
exitSignal = pyqtSignal()
urlSignal = pyqtSignal(QUrl)
# username = ''
def __init__(self, Me: person.Me, parent=None):
super(ContactController, self).__init__(parent)
self.chatroomFlag = None
self.ta_avatar = None
self.setupUi(self)
self.Me = Me
self.contacts: Dict[str, MyLabel.ContactUi] = {}
self.contactInfo: Dict[str, ContactInfo] = {}
self.show_flag = False
self.last_talkerId = None
self.now_talkerId = None
# self.showContact()
self.show_thread = ShowContactThread()
self.show_thread.showSingal.connect(self.showContact)
self.show_thread.heightSingal.connect(self.setScreenAreaHeight)
self.show_thread.start()
def showContact(self, data_):
"""
data:Tuple[rconversation,index:int]
显示联系人
:return:
"""
rconversation, i = data_
username = rconversation[1]
# print(username)
pushButton_2 = MyLabel.ContactUi(self.scrollAreaWidgetContents, i, rconversation)
pushButton_2.setGeometry(QtCore.QRect(0, 80 * i, 300, 80))
pushButton_2.setLayoutDirection(QtCore.Qt.LeftToRight)
pushButton_2.clicked.connect(pushButton_2.show_msg)
pushButton_2.usernameSingal.connect(self.Contact)
self.contacts[username] = pushButton_2
self.contactInfo[username] = ContactInfo(username, self.Me)
self.stackedWidget.addWidget(self.contactInfo[username])
def setScreenAreaHeight(self, height: int):
self.scrollAreaWidgetContents.setGeometry(
QtCore.QRect(0, 0, 300, height))
def Contact(self, talkerId):
"""
聊天界面 点击联系人头像时候显示聊天数据
:param talkerId:
:return:
"""
self.now_talkerId = talkerId
# 把当前按钮设置为灰色
if self.last_talkerId and self.last_talkerId != talkerId:
print('对方账号:', self.last_talkerId)
self.contacts[self.last_talkerId].setStyleSheet(
"QPushButton {background-color: rgb(220,220,220);}"
"QPushButton:hover{background-color: rgb(208,208,208);}\n"
)
self.last_talkerId = talkerId
self.contacts[talkerId].setStyleSheet(
"QPushButton {background-color: rgb(198,198,198);}"
"QPushButton:hover{background-color: rgb(209,209,209);}\n"
)
self.stackedWidget.setCurrentWidget(self.contactInfo[talkerId])
if '@chatroom' in talkerId:
self.chatroomFlag = True
else:
self.chatroomFlag = False
class ShowContactThread(QThread):
showSingal = pyqtSignal(tuple)
heightSingal = pyqtSignal(int)
def __init__(self):
super().__init__()
def run(self) -> None:
rconversations = data.get_rconversation()
max_height = max(len(rconversations) * 80, 680)
# 设置滚动区域的高度
self.heightSingal.emit(max_height)
for i in range(len(rconversations)):
self.showSingal.emit((rconversations[i], i))

View File

@ -1,137 +0,0 @@
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from app import person
from app.DataBase import output
from app.Ui.Icon import Icon
from .analysis import analysis
from .contactInfoUi import Ui_Form
from .emotion import emotion
from .userinfo import userinfo
class ContactInfo(QWidget, Ui_Form):
exitSignal = pyqtSignal()
urlSignal = pyqtSignal(QUrl)
# username = ''
def __init__(self, wxid, me: person.Me, parent=None):
super(ContactInfo, self).__init__(parent)
self.setupUi(self)
self.contact = person.Contact(wxid)
self.view_userinfo = userinfo.UserinfoController(self.contact)
self.view_analysis = analysis.AnalysisController(wxid)
self.view_emotion = emotion.EmotionController(wxid)
self.btn_analysis.clicked.connect(self.analysis)
self.btn_emotion.clicked.connect(self.emotionale_Analysis)
self.btn_report.clicked.connect(self.annual_report)
self.btn_back.clicked.connect(self.back)
self.Me = me
# self.
self.init_ui()
def init_ui(self):
self.btn_back.setIcon(Icon.Back)
self.btn_report.setIcon(Icon.Annual_Report_Icon)
self.btn_analysis.setIcon(Icon.Analysis_Icon)
self.btn_emotion.setIcon(Icon.Emotion_Icon)
self.label_remark.setText(self.contact.conRemark)
self.stackedWidget.addWidget(self.view_userinfo)
self.stackedWidget.addWidget(self.view_analysis)
self.stackedWidget.addWidget(self.view_emotion)
self.stackedWidget.setCurrentWidget(self.view_userinfo)
menu = QMenu(self)
self.toDocxAct = QAction(Icon.ToDocx, '导出Docx', self)
self.toCSVAct = QAction(Icon.ToCSV, '导出CSV', self)
self.toHtmlAct = QAction(Icon.ToHTML, '导出HTML', self)
self.toolButton_output.setPopupMode(QToolButton.MenuButtonPopup)
self.toolButton_output.clicked.connect(self.toolButton_show)
menu.addAction(self.toDocxAct)
menu.addAction(self.toCSVAct)
menu.addAction(self.toHtmlAct)
self.toolButton_output.setMenu(menu)
self.toolButton_output.setIcon(Icon.Output)
# self.toolButton_output.addSeparator()
self.toHtmlAct.triggered.connect(self.output)
self.toDocxAct.triggered.connect(self.output)
self.toCSVAct.triggered.connect(self.output)
def toolButton_show(self):
self.toolButton_output.showMenu()
def analysis(self):
self.stackedWidget.setCurrentWidget(self.view_analysis)
if 'room' in self.contact.wxid:
QMessageBox.warning(
self, '警告',
'暂不支持群组'
)
return
self.view_analysis.start()
def annual_report(self):
QMessageBox.warning(
self,
"提示",
"敬请期待"
)
return
# self.report = report.ReportController(self.contact)
# self.report.show()
def emotionale_Analysis(self):
self.stackedWidget.setCurrentWidget(self.view_emotion)
if 'room' in self.contact.wxid:
QMessageBox.warning(
self, '警告',
'暂不支持群组'
)
return
self.view_emotion.start()
def back(self):
"""
将userinfo界面设置为可见其他界面设置为不可见
"""
self.stackedWidget.setCurrentWidget(self.view_userinfo)
def output(self):
"""
导出聊天记录
:return:
"""
self.stackedWidget.setCurrentWidget(self.view_userinfo)
if self.sender() == self.toDocxAct:
self.outputThread = output.Output(self.Me, self.contact.wxid)
elif self.sender() == self.toCSVAct:
print('开始导出csv')
self.outputThread = output.Output(self.Me, self.contact.wxid, type_=output.Output.CSV)
print('导出csv')
elif self.sender() == self.toHtmlAct:
print('功能暂未实现')
QMessageBox.warning(self,
"别急别急",
"马上就实现该功能"
)
return
self.outputThread.progressSignal.connect(self.output_progress)
self.outputThread.rangeSignal.connect(self.set_progressBar_range)
self.outputThread.okSignal.connect(self.hide_progress_bar)
self.outputThread.start()
def hide_progress_bar(self, int):
reply = QMessageBox(self)
reply.setIcon(QMessageBox.Information)
reply.setWindowTitle('OK')
reply.setText(f"导出聊天记录成功\n在.\\data\\目录下")
reply.addButton("确认", QMessageBox.AcceptRole)
reply.addButton("取消", QMessageBox.RejectRole)
api = reply.exec_()
self.view_userinfo.progressBar.setVisible(False)
def output_progress(self, value):
self.view_userinfo.progressBar.setProperty('value', value)
def set_progressBar_range(self, value):
self.view_userinfo.progressBar.setVisible(True)
self.view_userinfo.progressBar.setRange(0, value)

View File

@ -1,92 +0,0 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'contactInfoUi.ui'
#
# Created by: PyQt5 UI code generator 5.15.7
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName("Form")
Form.resize(817, 748)
self.horizontalLayout = QtWidgets.QHBoxLayout(Form)
self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout.setSpacing(0)
self.horizontalLayout.setObjectName("horizontalLayout")
self.frame = QtWidgets.QFrame(Form)
self.frame.setFrameShape(QtWidgets.QFrame.NoFrame)
self.frame.setFrameShadow(QtWidgets.QFrame.Raised)
self.frame.setObjectName("frame")
self.verticalLayout = QtWidgets.QVBoxLayout(self.frame)
self.verticalLayout.setContentsMargins(0, 0, 0, 0)
self.verticalLayout.setSpacing(0)
self.verticalLayout.setObjectName("verticalLayout")
self.horizontalLayout_3 = QtWidgets.QHBoxLayout()
self.horizontalLayout_3.setSpacing(0)
self.horizontalLayout_3.setObjectName("horizontalLayout_3")
self.label_remark = QtWidgets.QLabel(self.frame)
self.label_remark.setMaximumSize(QtCore.QSize(16777215, 100))
font = QtGui.QFont()
font.setPointSize(12)
self.label_remark.setFont(font)
self.label_remark.setText("")
self.label_remark.setObjectName("label_remark")
self.horizontalLayout_3.addWidget(self.label_remark)
self.btn_analysis = QtWidgets.QPushButton(self.frame)
self.btn_analysis.setStyleSheet("")
self.btn_analysis.setFlat(True)
self.btn_analysis.setObjectName("btn_analysis")
self.horizontalLayout_3.addWidget(self.btn_analysis)
self.btn_emotion = QtWidgets.QPushButton(self.frame)
self.btn_emotion.setFlat(True)
self.btn_emotion.setObjectName("btn_emotion")
self.horizontalLayout_3.addWidget(self.btn_emotion)
self.btn_report = QtWidgets.QPushButton(self.frame)
self.btn_report.setFlat(True)
self.btn_report.setObjectName("btn_report")
self.horizontalLayout_3.addWidget(self.btn_report)
self.btn_back = QtWidgets.QPushButton(self.frame)
self.btn_back.setFlat(True)
self.btn_back.setObjectName("btn_back")
self.horizontalLayout_3.addWidget(self.btn_back)
self.toolButton_output = QtWidgets.QToolButton(self.frame)
icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap("../../data/icons/output.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.toolButton_output.setIcon(icon)
self.toolButton_output.setCheckable(False)
self.toolButton_output.setPopupMode(QtWidgets.QToolButton.MenuButtonPopup)
self.toolButton_output.setToolButtonStyle(QtCore.Qt.ToolButtonTextBesideIcon)
self.toolButton_output.setAutoRaise(True)
self.toolButton_output.setArrowType(QtCore.Qt.NoArrow)
self.toolButton_output.setObjectName("toolButton_output")
self.horizontalLayout_3.addWidget(self.toolButton_output)
self.verticalLayout.addLayout(self.horizontalLayout_3)
self.stackedWidget = QtWidgets.QStackedWidget(self.frame)
self.stackedWidget.setObjectName("stackedWidget")
self.page_3 = QtWidgets.QWidget()
self.page_3.setObjectName("page_3")
self.stackedWidget.addWidget(self.page_3)
self.page_4 = QtWidgets.QWidget()
self.page_4.setObjectName("page_4")
self.stackedWidget.addWidget(self.page_4)
self.verticalLayout.addWidget(self.stackedWidget)
self.horizontalLayout.addWidget(self.frame)
self.retranslateUi(Form)
self.stackedWidget.setCurrentIndex(1)
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
_translate = QtCore.QCoreApplication.translate
Form.setWindowTitle(_translate("Form", "Form"))
self.btn_analysis.setText(_translate("Form", "统计信息"))
self.btn_emotion.setText(_translate("Form", "情感分析"))
self.btn_report.setText(_translate("Form", "年度报告"))
self.btn_back.setText(_translate("Form", "退出"))
self.toolButton_output.setText(_translate("Form", "导出聊天记录"))

View File

@ -1,77 +0,0 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'contactUi.ui'
#
# Created by: PyQt5 UI code generator 5.15.7
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_Dialog(object):
def setupUi(self, Dialog):
Dialog.setObjectName("Dialog")
Dialog.resize(1141, 740)
Dialog.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor))
Dialog.setAutoFillBackground(False)
self.horizontalLayout = QtWidgets.QHBoxLayout(Dialog)
self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout.setSpacing(0)
self.horizontalLayout.setObjectName("horizontalLayout")
self.frame_2 = QtWidgets.QFrame(Dialog)
self.frame_2.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame_2.setFrameShadow(QtWidgets.QFrame.Raised)
self.frame_2.setObjectName("frame_2")
self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.frame_2)
self.horizontalLayout_2.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout_2.setSpacing(0)
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
self.scrollArea = QtWidgets.QScrollArea(self.frame_2)
self.scrollArea.setEnabled(True)
self.scrollArea.setMinimumSize(QtCore.QSize(325, 0))
self.scrollArea.setMaximumSize(QtCore.QSize(325, 150000))
self.scrollArea.setAutoFillBackground(False)
self.scrollArea.setFrameShape(QtWidgets.QFrame.NoFrame)
self.scrollArea.setFrameShadow(QtWidgets.QFrame.Raised)
self.scrollArea.setMidLineWidth(0)
self.scrollArea.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
self.scrollArea.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.scrollArea.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.AdjustToContentsOnFirstShow)
self.scrollArea.setWidgetResizable(False)
self.scrollArea.setObjectName("scrollArea")
self.scrollAreaWidgetContents = QtWidgets.QWidget()
self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 300, 12000))
self.scrollAreaWidgetContents.setObjectName("scrollAreaWidgetContents")
self.pushButton_2 = QtWidgets.QPushButton(self.scrollAreaWidgetContents)
self.pushButton_2.setGeometry(QtCore.QRect(0, 0, 300, 80))
self.pushButton_2.setLayoutDirection(QtCore.Qt.LeftToRight)
self.pushButton_2.setAutoFillBackground(False)
self.pushButton_2.setText("")
self.pushButton_2.setIconSize(QtCore.QSize(80, 80))
self.pushButton_2.setObjectName("pushButton_2")
self.label = QtWidgets.QLabel(self.scrollAreaWidgetContents)
self.label.setGeometry(QtCore.QRect(220, 10, 72, 15))
self.label.setObjectName("label")
self.scrollArea.setWidget(self.scrollAreaWidgetContents)
self.horizontalLayout_2.addWidget(self.scrollArea)
self.stackedWidget = QtWidgets.QStackedWidget(self.frame_2)
self.stackedWidget.setObjectName("stackedWidget")
self.page = QtWidgets.QWidget()
self.page.setObjectName("page")
self.stackedWidget.addWidget(self.page)
self.page_2 = QtWidgets.QWidget()
self.page_2.setObjectName("page_2")
self.stackedWidget.addWidget(self.page_2)
self.horizontalLayout_2.addWidget(self.stackedWidget)
self.horizontalLayout.addWidget(self.frame_2)
self.retranslateUi(Dialog)
QtCore.QMetaObject.connectSlotsByName(Dialog)
def retranslateUi(self, Dialog):
_translate = QtCore.QCoreApplication.translate
Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
self.label.setText(_translate("Dialog", "TextLabel"))

View File

@ -1,170 +0,0 @@
import numpy as np
import pandas as pd
from pyecharts import options as opts
from pyecharts.charts import Line
from app.log import log
from ....DataBase import data
def load_data(wxid):
message_data = data.get_text_by_num(wxid, 1)
df = pd.DataFrame(message_data, columns=['message', 'date'])
# print(df)
d = df.groupby('date')
for key, value in d:
yield key, value['message'].values
import snownlp
@log
def emotion_analysis(wxid):
dates = []
emotions = []
for date, messages in load_data(wxid):
dates.append(date)
s = 0
for msg in messages:
val = snownlp.SnowNLP(msg).sentiments
s += val
emotions.append(s / len(messages))
emotions = np.array(emotions)
emotions = np.around(emotions, 3) * 100
emotions = np.around(emotions, 1)
return dates, emotions
@log
def plot_emotion(wxid):
"""
画图
"""
datas, emotions = emotion_analysis(wxid) # 获取数据
max_ = max(emotions)
min_ = min(emotions)
c = (
Line()
.add_xaxis(
xaxis_data=datas,
)
.add_yaxis(
series_name="情感趋势",
is_smooth=True,
y_axis=emotions,
markpoint_opts=opts.MarkPointOpts(
data=[
opts.MarkPointItem(type_="max", name="最大值", value=int(max_ * 100) / 100),
opts.MarkPointItem(type_="min", name="最小值", value=int(min_ * 100) / 100),
]
),
markline_opts=opts.MarkLineOpts(
data=[opts.MarkLineItem(type_="average", name="平均值")]
),
)
.set_global_opts(
yaxis_opts=opts.AxisOpts(
max_=max_,
min_=min_,
),
xaxis_opts=opts.AxisOpts(
type_='time'
),
axispointer_opts=opts.AxisPointerOpts(
is_show=True, link=[{"xAxisIndex": "all"}]
),
)
.set_series_opts(label_opts=opts.LabelOpts(is_show=False))
.render("./data/聊天统计/emotion_chart.html")
)
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWebEngineWidgets import QWebEngineView
from PyQt5.QtWidgets import *
from . import emotionUi
class EmotionController(QWidget, emotionUi.Ui_Dialog):
def __init__(self, username, parent=None):
super().__init__(parent)
self.ta_username = username
# self.setStyleSheet('''QWidget{background-color:rgb(240, 240, 240);}''')
# 加载动画
self.center()
self.label_01()
def center(self): # 定义一个函数使得窗口居中显示
# 获取屏幕坐标系
screen = QDesktopWidget().screenGeometry()
# 获取窗口坐标系
size = self.geometry()
newLeft = (screen.width() - size.width()) / 2
newTop = (screen.height() - size.height()) / 2
self.move(int(newLeft), int(newTop))
def label_01(self):
w = self.size().width()
h = self.size().height()
self.label = QLabel(self)
self.label.setGeometry(w // 2, h // 2, 100, 100)
self.label.setToolTip("这是一个标签")
self.m_movie()
def m_movie(self):
movie = QMovie("./app/data/bg.gif")
self.label.setMovie(movie)
movie.start()
def initUI(self):
self.label.setVisible(False)
# self.setStyleSheet('''QWidget{background-color:rgb(244, 244, 244);}''')
main_box = QHBoxLayout(self)
self.browser1 = QWebEngineView()
self.browser1.load(QUrl('file:///data/聊天统计/emotion_chart.html'))
# self.browser1.setStyleSheet('''QWidget{background-color:rgb(240, 240, 240);}''')
splitter1 = QSplitter(Qt.Vertical)
splitter1.addWidget(self.browser1)
main_box.addWidget(splitter1)
self.setLayout(main_box)
def setBackground(self):
palette = QPalette()
pix = QPixmap("./app/data/bg.png")
pix = pix.scaled(self.width(), self.height(), Qt.IgnoreAspectRatio, Qt.SmoothTransformation) # 自适应图片大小
palette.setBrush(self.backgroundRole(), QBrush(pix)) # 设置背景图片
# palette.setColor(self.backgroundRole(), QColor(192, 253, 123)) # 设置背景颜色
self.setPalette(palette)
def start(self):
# 防止卡死,新建线程处理数据
self.Thread = LoadData(self.ta_username)
self.Thread.okSignal.connect(self.initUI)
self.Thread.start()
class LoadData(QThread):
"""
发送信息线程
"""
okSignal = pyqtSignal(int)
def __init__(self, ta_u, parent=None):
super().__init__(parent)
self.ta_username = ta_u
def run(self):
plot_emotion(self.ta_username)
self.okSignal.emit(10)
if __name__ == '__main__':
# wxid = 'wxid_8piw6sb4hvfm22'
wxid = 'wxid_wt2vsktnu4z022'
load_data(wxid)

View File

@ -1,24 +0,0 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'emotionUi.ui'
#
# Created by: PyQt5 UI code generator 5.15.7
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore
class Ui_Dialog(object):
def setupUi(self, Dialog):
Dialog.setObjectName("Dialog")
Dialog.resize(400, 300)
self.retranslateUi(Dialog)
QtCore.QMetaObject.connectSlotsByName(Dialog)
def retranslateUi(self, Dialog):
_translate = QtCore.QCoreApplication.translate
Dialog.setWindowTitle(_translate("Dialog", "Dialog"))

View File

@ -1,28 +0,0 @@
from bs4 import BeautifulSoup
def create_title_page(nickname, time, avatar_path):
with open('D:\\Project\\Python\\WeChatMsg\\app\\data\\html\\0.html', 'r+', encoding='utf-8') as f:
html_document = f.read()
# 创建Beautiful Soup对象
soup = BeautifulSoup(html_document, 'html.parser')
# 找到需要替换的图片元素
target_image = soup.find(id='avatar')
# 替换图片元素的src属性
if target_image:
target_image['src'] = avatar_path
# 找到需要替换的元素
target_element = soup.find(id='nickname')
# 替换元素的文本内容
if target_element:
target_element.string = nickname
target_element = soup.find(id='first_time')
# 替换元素的文本内容
if target_element:
target_element.string = time
with open('./data/AnnualReport/0.html', 'w', encoding='utf-8') as f1:
f1.write(soup.prettify())
if __name__ == '__main__':
create_title_page('小学生', '2023-09-18 20:39:08', 'D:\Project\Python\WeChatMsg\\app\data\icons\default_avatar.svg')

View File

@ -1,74 +0,0 @@
import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWebEngineWidgets import QWebEngineView
from PyQt5.QtWidgets import *
from app import person
from app.DataBase import data
from . import annual_report
class ReportController(QWidget):
def __init__(self, contact: person.Contact, me: person.Me = None, parent=None):
super().__init__(parent)
self.ta_username = contact.wxid
self.contact = contact
self.Me = me
# self.setStyleSheet('''QWidget{background-color:rgb(240, 240, 240);}''')
# 加载动画
self.center()
self.label_01()
def center(self): # 定义一个函数使得窗口居中显示
# 获取屏幕坐标系
screen = QDesktopWidget().screenGeometry()
# 获取窗口坐标系
size = self.geometry()
newLeft = (screen.width() - size.width()) / 2
newTop = (screen.height() - size.height()) / 2
self.move(int(newLeft), int(newTop))
def label_01(self):
w = self.size().width()
h = self.size().height()
self.label = QLabel(self)
self.label.setGeometry(w // 2, h // 2, 100, 100)
self.label.setToolTip("这是一个标签")
# self.m_movie()
self.initUI()
def m_movie(self):
movie = QMovie("./app/data/bg.gif")
self.label.setMovie(movie)
movie.start()
def initUI(self):
start_time = data.get_msg_start_time(self.contact.wxid)
annual_report.create_title_page(self.contact.nickname, start_time, self.contact.avatar_path)
self.label.setVisible(False)
# self.setStyleSheet('''QWidget{background-color:rgb(244, 244, 244);}''')
main_box = QHBoxLayout(self)
self.browser1 = QWebEngineView()
self.browser1.load(QUrl('file:///data/AnnualReport/index.html'))
splitter1 = QSplitter(Qt.Vertical)
splitter1.addWidget(self.browser1)
main_box.addWidget(splitter1)
self.setLayout(main_box)
def setBackground(self):
palette = QPalette()
pix = QPixmap("./app/data/bg.png")
pix = pix.scaled(self.width(), self.height(), Qt.IgnoreAspectRatio, Qt.SmoothTransformation) # 自适应图片大小
palette.setBrush(self.backgroundRole(), QBrush(pix)) # 设置背景图片
# palette.setColor(self.backgroundRole(), QColor(192, 253, 123)) # 设置背景颜色
self.setPalette(palette)
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = ReportController(1)
ex.show()
sys.exit(app.exec_())

View File

@ -1,9 +0,0 @@
# -*- coding: utf-8 -*-
"""
@File : __init__.py.py
@Author : Shuaikang Zhou
@Time : 2022/12/24 10:34
@IDE : Pycharm
@Version : Python3.10
@comment : ···
"""

View File

@ -1,15 +0,0 @@
from PyQt5.QtWidgets import *
from .userinfoUi import Ui_Frame
class UserinfoController(QWidget, Ui_Frame):
def __init__(self, contact, parent=None):
super().__init__(parent)
self.setupUi(self)
self.l_remark.setText(contact.conRemark)
self.l_avatar.setPixmap(contact.avatar)
self.l_nickname.setText(f'昵称:{contact.nickname}')
self.l_username.setText(f'微信号:{contact.alias}')
self.lineEdit.setText(contact.conRemark)
self.progressBar.setVisible(False)

View File

@ -1,121 +0,0 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'userinfoUi.ui'
#
# Created by: PyQt5 UI code generator 5.15.7
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_Frame(object):
def setupUi(self, Frame):
Frame.setObjectName("Frame")
Frame.resize(800, 720)
Frame.setCursor(QtGui.QCursor(QtCore.Qt.IBeamCursor))
Frame.setMouseTracking(True)
Frame.setTabletTracking(True)
self.horizontalLayout_3 = QtWidgets.QHBoxLayout(Frame)
self.horizontalLayout_3.setObjectName("horizontalLayout_3")
self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.horizontalLayout_2.addItem(spacerItem)
self.verticalLayout = QtWidgets.QVBoxLayout()
self.verticalLayout.setObjectName("verticalLayout")
spacerItem1 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
self.verticalLayout.addItem(spacerItem1)
self.gridLayout = QtWidgets.QGridLayout()
self.gridLayout.setHorizontalSpacing(6)
self.gridLayout.setObjectName("gridLayout")
self.l_avatar = QtWidgets.QLabel(Frame)
self.l_avatar.setMinimumSize(QtCore.QSize(80, 80))
self.l_avatar.setMaximumSize(QtCore.QSize(80, 80))
self.l_avatar.setText("")
self.l_avatar.setPixmap(QtGui.QPixmap("../../../a_img/be0fa6c0c4707fb5f7b37b660de826d3.jpg"))
self.l_avatar.setScaledContents(True)
self.l_avatar.setObjectName("l_avatar")
self.gridLayout.addWidget(self.l_avatar, 0, 0, 3, 1)
self.l_remark = QtWidgets.QLabel(Frame)
self.l_remark.setMinimumSize(QtCore.QSize(0, 30))
self.l_remark.setMaximumSize(QtCore.QSize(16777215, 30))
font = QtGui.QFont()
font.setPointSize(15)
self.l_remark.setFont(font)
self.l_remark.setObjectName("l_remark")
self.gridLayout.addWidget(self.l_remark, 0, 1, 1, 1)
self.l_nickname = QtWidgets.QLabel(Frame)
self.l_nickname.setMinimumSize(QtCore.QSize(0, 30))
self.l_nickname.setMaximumSize(QtCore.QSize(16777215, 30))
self.l_nickname.setObjectName("l_nickname")
self.gridLayout.addWidget(self.l_nickname, 1, 1, 1, 1)
self.l_username = QtWidgets.QLabel(Frame)
self.l_username.setMinimumSize(QtCore.QSize(0, 20))
self.l_username.setMaximumSize(QtCore.QSize(16777215, 20))
self.l_username.setObjectName("l_username")
self.gridLayout.addWidget(self.l_username, 2, 1, 1, 1)
self.gridLayout.setRowStretch(0, 1)
self.gridLayout.setRowStretch(1, 1)
self.gridLayout.setRowStretch(2, 1)
self.verticalLayout.addLayout(self.gridLayout)
spacerItem2 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
self.verticalLayout.addItem(spacerItem2)
self.horizontalLayout = QtWidgets.QHBoxLayout()
self.horizontalLayout.setObjectName("horizontalLayout")
self.label = QtWidgets.QLabel(Frame)
self.label.setMinimumSize(QtCore.QSize(80, 0))
self.label.setMaximumSize(QtCore.QSize(80, 16777215))
font = QtGui.QFont()
font.setPointSize(15)
self.label.setFont(font)
self.label.setObjectName("label")
self.horizontalLayout.addWidget(self.label)
self.lineEdit = QtWidgets.QLineEdit(Frame)
self.lineEdit.setMinimumSize(QtCore.QSize(0, 25))
self.lineEdit.setMaximumSize(QtCore.QSize(16777215, 25))
font = QtGui.QFont()
font.setPointSize(15)
self.lineEdit.setFont(font)
self.lineEdit.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor))
self.lineEdit.setAutoFillBackground(False)
self.lineEdit.setStyleSheet("background:transparent;border-width:0;border-style:outset")
self.lineEdit.setObjectName("lineEdit")
self.horizontalLayout.addWidget(self.lineEdit)
self.verticalLayout.addLayout(self.horizontalLayout)
spacerItem3 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
self.verticalLayout.addItem(spacerItem3)
self.progressBar = QtWidgets.QProgressBar(Frame)
self.progressBar.setProperty("value", 24)
self.progressBar.setObjectName("progressBar")
self.verticalLayout.addWidget(self.progressBar)
spacerItem4 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
self.verticalLayout.addItem(spacerItem4)
self.verticalLayout.setStretch(0, 2)
self.verticalLayout.setStretch(1, 3)
self.verticalLayout.setStretch(2, 4)
self.verticalLayout.setStretch(3, 1)
self.verticalLayout.setStretch(4, 4)
self.verticalLayout.setStretch(5, 1)
self.verticalLayout.setStretch(6, 2)
self.horizontalLayout_2.addLayout(self.verticalLayout)
spacerItem5 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.horizontalLayout_2.addItem(spacerItem5)
self.horizontalLayout_2.setStretch(0, 1)
self.horizontalLayout_2.setStretch(1, 2)
self.horizontalLayout_2.setStretch(2, 1)
self.horizontalLayout_3.addLayout(self.horizontalLayout_2)
self.retranslateUi(Frame)
QtCore.QMetaObject.connectSlotsByName(Frame)
def retranslateUi(self, Frame):
_translate = QtCore.QCoreApplication.translate
Frame.setWindowTitle(_translate("Frame", "Frame"))
self.l_remark.setText(_translate("Frame", "曹雨萱"))
self.l_nickname.setText(_translate("Frame", "昵称997"))
self.l_username.setText(_translate("Frame", "账号TextLabel"))
self.label.setText(_translate("Frame", "备注名"))
self.lineEdit.setText(_translate("Frame", "曹雨萱"))

View File

@ -1,161 +0,0 @@
# -*- coding: utf-8 -*-
"""
@File : decrypt.py
@Author : Shuaikang Zhou
@Time : 2023/1/5 18:13
@IDE : Pycharm
@Version : Python3.10
@comment : ··· 解密数据库导出原始数据库文件
"""
import hashlib
import time
import xml.etree.ElementTree as ET
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from . import decryptUi
from ...DataBase import data
class DecryptControl(QWidget, decryptUi.Ui_Dialog):
DecryptSignal = pyqtSignal(str)
registerSignal = pyqtSignal(str)
def __init__(self, parent=None):
super(DecryptControl, self).__init__(parent)
self.setupUi(self)
self.setWindowTitle('解密')
self.setWindowIcon(QIcon('./app/data/icons/logo.svg'))
self.btn_db.clicked.connect(self.get_db)
self.btn_xml.clicked.connect(self.get_xml)
self.pushButton_3.clicked.connect(self.decrypt)
self.xml_path: str = None
self.db_path: str = None
def db_exist(self):
if data.is_db_exist():
self.btnEnterClicked()
self.close()
def get_xml(self):
self.xml_path, _ = QFileDialog.getOpenFileName(self, 'Open file', r'..', "Xml files (*.xml)")
if self.xml_path:
self.label_xml.setText('xml已就绪')
key = self.parser_xml()
self.label_key.setText(f'数据库密钥:{key}')
return self.xml_path
return False
def get_db(self):
self.db_path, _ = QFileDialog.getOpenFileName(self, 'Open file', r'..', "Database files (*.db)")
if self.db_path:
if ' ' in self.db_path:
self.label_db.setText('数据库未就绪')
QMessageBox.critical(self, "错误", "db文件路径请不要带有空格\n可以放在D:\\\\data 目录下")
self.db_path = ''
elif self.db_path.isascii():
self.label_db.setText('数据库已就绪')
return self.db_path
else:
self.label_db.setText('数据库未就绪')
QMessageBox.critical(self, "错误", "db文件请不要带有中文路径\n可以放在D:\\\\data 目录下")
self.db_path = ''
return False
def decrypt(self):
if not (self.xml_path and self.db_path):
QMessageBox.critical(self, "错误", "请把两个文件加载进来")
return
key = self.parser_xml()
self.label_key.setText(f'数据库密钥:{key}')
self.thread1 = MyThread()
self.thread1.signal.connect(self.progressBar_view)
self.thread1.start()
self.thread2 = DecryptThread(self.db_path, key)
self.thread2.signal.connect(self.progressBar_view)
self.thread2.start()
def parser_xml(self):
if not self.xml_path:
return False
pid = self.pid(self.xml_path)
if not pid:
return False
key = self.key(pid)
return key
def pid(self, xml_path):
tree = ET.parse(xml_path)
# 根节点
root = tree.getroot()
# 标签名
for stu in root:
if stu.attrib["name"] == '_auth_uin':
return stu.attrib['value']
return False
def key(self, uin, IMEI='1234567890ABCDEF'):
m = hashlib.md5()
m.update(bytes((IMEI + uin).encode('utf-8')))
psw = m.hexdigest()
return psw[:7]
def btnEnterClicked(self):
# print("enter clicked")
# 中间可以添加处理逻辑
self.DecryptSignal.emit('ok')
self.close()
def progressBar_view(self, value):
"""
进度条显示
:param value: 进度0-100
:return: None
"""
self.progressBar.setProperty('value', value)
if value == '99':
QMessageBox.information(self, "温馨提示", "我知道你很急\n但你先别急")
if value == '100':
QMessageBox.information(self, "解密成功", "请退出该界面",
QMessageBox.Yes)
self.btnExitClicked()
data.init_database()
def btnExitClicked(self):
# print("Exit clicked")
self.DecryptSignal.emit('ok')
self.close()
class DecryptThread(QThread):
signal = pyqtSignal(str)
def __init__(self, db_path, key):
super(DecryptThread, self).__init__()
self.db_path = db_path
self.key = key
self.textBrowser = None
def __del__(self):
pass
def run(self):
data.decrypt(self.db_path, self.key)
self.signal.emit('100')
class MyThread(QThread):
signal = pyqtSignal(str)
def __init__(self):
super(MyThread, self).__init__()
def __del__(self):
pass
def run(self):
for i in range(100):
self.signal.emit(str(i))
time.sleep(0.1)

View File

@ -1,72 +0,0 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'decryptUi.ui'
#
# Created by: PyQt5 UI code generator 5.15.7
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_Dialog(object):
def setupUi(self, Dialog):
Dialog.setObjectName("Dialog")
Dialog.resize(400, 300)
self.label_3 = QtWidgets.QLabel(Dialog)
self.label_3.setGeometry(QtCore.QRect(110, 20, 221, 51))
font = QtGui.QFont()
font.setFamily("一纸情书")
font.setPointSize(20)
self.label_3.setFont(font)
self.label_3.setObjectName("label_3")
self.progressBar = QtWidgets.QProgressBar(Dialog)
self.progressBar.setGeometry(QtCore.QRect(90, 260, 271, 23))
self.progressBar.setProperty("value", 50)
self.progressBar.setObjectName("progressBar")
self.label_key = QtWidgets.QLabel(Dialog)
self.label_key.setGeometry(QtCore.QRect(80, 230, 241, 20))
self.label_key.setText("")
self.label_key.setObjectName("label_key")
self.widget = QtWidgets.QWidget(Dialog)
self.widget.setGeometry(QtCore.QRect(80, 80, 245, 134))
self.widget.setObjectName("widget")
self.verticalLayout = QtWidgets.QVBoxLayout(self.widget)
self.verticalLayout.setContentsMargins(0, 0, 0, 0)
self.verticalLayout.setObjectName("verticalLayout")
self.horizontalLayout = QtWidgets.QHBoxLayout()
self.horizontalLayout.setObjectName("horizontalLayout")
self.btn_xml = QtWidgets.QPushButton(self.widget)
self.btn_xml.setObjectName("btn_xml")
self.horizontalLayout.addWidget(self.btn_xml)
self.label_xml = QtWidgets.QLabel(self.widget)
self.label_xml.setObjectName("label_xml")
self.horizontalLayout.addWidget(self.label_xml)
self.verticalLayout.addLayout(self.horizontalLayout)
self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
self.btn_db = QtWidgets.QPushButton(self.widget)
self.btn_db.setObjectName("btn_db")
self.horizontalLayout_2.addWidget(self.btn_db)
self.label_db = QtWidgets.QLabel(self.widget)
self.label_db.setObjectName("label_db")
self.horizontalLayout_2.addWidget(self.label_db)
self.verticalLayout.addLayout(self.horizontalLayout_2)
self.pushButton_3 = QtWidgets.QPushButton(self.widget)
self.pushButton_3.setObjectName("pushButton_3")
self.verticalLayout.addWidget(self.pushButton_3)
self.retranslateUi(Dialog)
QtCore.QMetaObject.connectSlotsByName(Dialog)
def retranslateUi(self, Dialog):
_translate = QtCore.QCoreApplication.translate
Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
self.label_3.setText(_translate("Dialog", "解密数据库"))
self.btn_xml.setText(_translate("Dialog", "点击加载xml文件"))
self.label_xml.setText(_translate("Dialog", "xml未就绪"))
self.btn_db.setText(_translate("Dialog", "点击加载数据库文件"))
self.label_db.setText(_translate("Dialog", "数据库未就绪"))
self.pushButton_3.setText(_translate("Dialog", "开始解密数据库"))

View File

@ -1,146 +0,0 @@
# -*- coding: utf-8 -*-
"""
@File : mainview.py
@Author : Shuaikang Zhou
@Time : 2022/12/13 15:07
@IDE : Pycharm
@Version : Python3.10
@comment : 主窗口
"""
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from app import config
from app.DataBase import data
from app.Ui import mainwindow
from app.Ui.Icon import Icon
from app.Ui.chat import chat
from app.Ui.contact import contact
from app.components.prompt_bar import PromptBar
from app.person import Me
class MainWinController(QMainWindow, mainwindow.Ui_MainWindow):
exitSignal = pyqtSignal()
# username = ''
def __init__(self, username, parent=None):
super(MainWinController, self).__init__(parent)
self.setupUi(self)
self.setWindowIcon(Icon.MainWindow_Icon)
self.setAttribute(Qt.WA_AttributeCount)
self.Me = Me(data.get_myinfo())
self.chatView = chat.ChatController(self.Me, parent=None)
self.lay = QHBoxLayout()
self.page_chat.setLayout(self.lay)
self.lay.addWidget(self.chatView)
self.contactView = contact.ContactController(self.Me, parent=None)
self.lay0 = QHBoxLayout()
self.page_contact.setLayout(self.lay0)
self.lay0.addWidget(self.contactView)
self.btn_chat.clicked.connect(self.chat_view) # 聊天按钮
self.btn_contact.clicked.connect(self.contact_view)
# self.btn_myinfo.clicked.connect(self.myInfo)
self.btn_about.clicked.connect(self.about)
self.now_btn = self.btn_chat
self.btn_chat.setIcon(Icon.Chat_Icon)
self.btn_contact.setIcon(Icon.Contact_Icon)
self.btn_myinfo.setIcon(Icon.MyInfo_Icon)
self.btn_about.setIcon(Icon.MainWindow_Icon)
self.btn_about.setContextMenuPolicy(Qt.CustomContextMenu)
self.btn_about.customContextMenuRequested.connect(self.create_rightmenu) # 连接到菜单显示函数
self.last_btn = None
self.lastView = None
self.show_avatar()
self.init_ui()
self.menubar.setVisible(False)
self.statusbar.setVisible(False)
self.prompt_bar = PromptBar(self)
self.chat_view()
def init_ui(self):
# self.setWindowFlags(QtCore.Qt.FramelessWindowHint)
self.menubar.setStyleSheet("background-color: rgb(240, 240, 240);")
def create_rightmenu(self):
# 菜单对象
self.groupBox_menu = QMenu(self)
self.actionA = QAction(QIcon('image/保存.png'), u'保存数据',
self) # self.actionA = self.contextMenu.addAction(QIcon("images/0.png"),u'| 动作A')
self.actionA.setShortcut('Ctrl+S') # 设置快捷键
self.groupBox_menu.addAction(self.actionA) # 把动作A选项添加到菜单
self.actionB = QAction(QIcon('image/删除.png'), u'删除数据', self)
self.groupBox_menu.addAction(self.actionB)
# self.actionA.triggered.connect(self.button) # 将动作A触发时连接到槽函数 button
# self.actionB.triggered.connect(self.button_2)
self.groupBox_menu.popup(QCursor.pos()) # 声明当鼠标在groupBox控件上右击时在鼠标位置显示右键菜单 ,exec_,popup两个都可以
def show_avatar(self):
avatar = self.Me.avatar
pixmap = QPixmap(avatar).scaled(60, 60) # 按指定路径找到图片
self.myavatar.setPixmap(pixmap) # 在label上显示图片
def chat_view(self):
"""
聊天窗口
"""
self.now_btn = self.btn_chat
self.now_btn.setStyleSheet(
"QPushButton {background-color: rgb(198,198,198);border:none;}")
if self.last_btn and self.last_btn != self.now_btn:
self.last_btn.setStyleSheet(
"QPushButton {"
"background-color: rgb(240,240,240);"
"border:none;"
"}"
"QPushButton:hover{background-color: rgb(209,209,209);}\n"
)
self.last_btn = self.btn_chat
# self.state_lable.setGeometry(20, 300, 32, 32)
self.stackedWidget.setCurrentIndex(0)
self.chatView.showChat()
def contact_view(self):
"""
联系人窗口
"""
self.now_btn = self.btn_contact
self.now_btn.setStyleSheet(
"QPushButton {background-color: rgb(198,198,198);border:none;}")
if self.last_btn and self.last_btn != self.now_btn:
self.last_btn.setStyleSheet("QPushButton {background-color: rgb(240,240,240);border:none;}"
"QPushButton:hover{background-color: rgb(209,209,209);}\n")
self.last_btn = self.btn_contact
# geometry = self.btn_chat.geometry()
# self.state_lable.setGeometry(geometry)
self.stackedWidget.setCurrentIndex(1)
def myInfo(self):
"""
显示我的个人信息
"""
self.now_btn = self.btn_myinfo
self.now_btn.setStyleSheet(
"QPushButton {background-color: rgb(198,198,198);}")
if self.last_btn and self.last_btn != self.now_btn:
self.last_btn.setStyleSheet("QPushButton {background-color: rgb(240,240,240);}"
"QPushButton:hover{background-color: rgb(209,209,209);}\n")
self.last_btn = self.now_btn
def about(self):
"""
关于
"""
QMessageBox.about(self, "关于",
f"版本:{config.version}\n"
f"QQ交流群:{config.contact}\n"
"地址https://github.com/LC044/WeChatMsg"
)

View File

@ -1,177 +0,0 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'mainwindow.ui'
#
# Created by: PyQt5 UI code generator 5.15.7
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(1280, 779)
MainWindow.setStyleSheet("QPushButton {\n"
"background-color: rgb(240,240,240);\n"
"border:none;\n"
"}\n"
"QPushButton:hover{\n"
"background-color: rgb(209,209,209);\n"
"}\n"
" ")
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.horizontalLayout = QtWidgets.QHBoxLayout(self.centralwidget)
self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout.setSpacing(0)
self.horizontalLayout.setObjectName("horizontalLayout")
self.frame_info = QtWidgets.QFrame(self.centralwidget)
self.frame_info.setMinimumSize(QtCore.QSize(80, 500))
self.frame_info.setMaximumSize(QtCore.QSize(80, 16777215))
self.frame_info.setStyleSheet("background-color:rgb(240,240,240)")
self.frame_info.setFrameShape(QtWidgets.QFrame.NoFrame)
self.frame_info.setFrameShadow(QtWidgets.QFrame.Plain)
self.frame_info.setObjectName("frame_info")
self.verticalLayoutWidget = QtWidgets.QWidget(self.frame_info)
self.verticalLayoutWidget.setGeometry(QtCore.QRect(0, 190, 77, 271))
self.verticalLayoutWidget.setObjectName("verticalLayoutWidget")
self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.verticalLayoutWidget)
self.verticalLayout_2.setContentsMargins(0, 0, 0, 0)
self.verticalLayout_2.setSpacing(0)
self.verticalLayout_2.setObjectName("verticalLayout_2")
self.btn_chat = QtWidgets.QPushButton(self.verticalLayoutWidget)
self.btn_chat.setMinimumSize(QtCore.QSize(0, 60))
font = QtGui.QFont()
font.setFamily("微软雅黑")
self.btn_chat.setFont(font)
self.btn_chat.setStyleSheet("QPushButton {\n"
"background-color: rgb(240,240,240);\n"
"border:none;\n"
"}\n"
"QPushButton:hover{background-color: rgb(209,209,209);}\n"
" ")
self.btn_chat.setAutoDefault(True)
self.btn_chat.setDefault(False)
self.btn_chat.setFlat(False)
self.btn_chat.setObjectName("btn_chat")
self.verticalLayout_2.addWidget(self.btn_chat)
self.btn_contact = QtWidgets.QPushButton(self.verticalLayoutWidget)
self.btn_contact.setMinimumSize(QtCore.QSize(0, 60))
font = QtGui.QFont()
font.setFamily("微软雅黑")
self.btn_contact.setFont(font)
self.btn_contact.setStyleSheet("QPushButton {\n"
"background-color: rgb(240,240,240);\n"
"border:none;\n"
"}\n"
"QPushButton:hover{\n"
"background-color: rgb(209,209,209);\n"
"}\n"
" ")
self.btn_contact.setDefault(True)
self.btn_contact.setFlat(False)
self.btn_contact.setObjectName("btn_contact")
self.verticalLayout_2.addWidget(self.btn_contact)
self.btn_myinfo = QtWidgets.QPushButton(self.verticalLayoutWidget)
self.btn_myinfo.setMinimumSize(QtCore.QSize(60, 60))
font = QtGui.QFont()
font.setFamily("微软雅黑")
self.btn_myinfo.setFont(font)
self.btn_myinfo.setFlat(False)
self.btn_myinfo.setObjectName("btn_myinfo")
self.verticalLayout_2.addWidget(self.btn_myinfo)
self.btn_about = QtWidgets.QPushButton(self.verticalLayoutWidget)
self.btn_about.setMinimumSize(QtCore.QSize(60, 60))
font = QtGui.QFont()
font.setFamily("微软雅黑")
self.btn_about.setFont(font)
self.btn_about.setStyleSheet("QPushButton {background-color: rgb(240,240,240);}\n"
" QPushButton:hover{background-color: rgb(209,209,209);}\n"
" ")
self.btn_about.setFlat(False)
self.btn_about.setObjectName("btn_about")
self.verticalLayout_2.addWidget(self.btn_about)
self.verticalLayout_2.setStretch(0, 1)
self.verticalLayout_2.setStretch(1, 1)
self.verticalLayout_2.setStretch(2, 1)
self.verticalLayout_2.setStretch(3, 1)
self.myavatar = QtWidgets.QLabel(self.frame_info)
self.myavatar.setGeometry(QtCore.QRect(10, 40, 60, 60))
self.myavatar.setObjectName("myavatar")
self.horizontalLayout.addWidget(self.frame_info)
self.stackedWidget = QtWidgets.QStackedWidget(self.centralwidget)
font = QtGui.QFont()
font.setFamily("微软雅黑")
font.setBold(False)
font.setWeight(50)
self.stackedWidget.setFont(font)
self.stackedWidget.setObjectName("stackedWidget")
self.page_chat = QtWidgets.QWidget()
self.page_chat.setObjectName("page_chat")
self.stackedWidget.addWidget(self.page_chat)
self.page_contact = QtWidgets.QWidget()
self.page_contact.setObjectName("page_contact")
self.stackedWidget.addWidget(self.page_contact)
self.page_myinfo = QtWidgets.QWidget()
self.page_myinfo.setObjectName("page_myinfo")
self.stackedWidget.addWidget(self.page_myinfo)
self.page_2 = QtWidgets.QWidget()
self.page_2.setObjectName("page_2")
self.stackedWidget.addWidget(self.page_2)
self.horizontalLayout.addWidget(self.stackedWidget)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 1280, 23))
self.menubar.setObjectName("menubar")
self.menu_F = QtWidgets.QMenu(self.menubar)
self.menu_F.setObjectName("menu_F")
self.menu = QtWidgets.QMenu(self.menubar)
font = QtGui.QFont()
font.setFamily("微软雅黑")
self.menu.setFont(font)
self.menu.setObjectName("menu")
self.menu_2 = QtWidgets.QMenu(self.menubar)
self.menu_2.setObjectName("menu_2")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.action_3 = QtWidgets.QAction(MainWindow)
self.action_3.setObjectName("action_3")
self.action_4 = QtWidgets.QAction(MainWindow)
self.action_4.setObjectName("action_4")
self.action = QtWidgets.QAction(MainWindow)
font = QtGui.QFont()
font.setFamily("Microsoft YaHei UI")
self.action.setFont(font)
self.action.setObjectName("action")
self.menu_F.addSeparator()
self.menu_F.addSeparator()
self.menu_F.addAction(self.action_3)
self.menu_F.addAction(self.action_4)
self.menu_2.addAction(self.action)
self.menubar.addAction(self.menu_F.menuAction())
self.menubar.addAction(self.menu.menuAction())
self.menubar.addAction(self.menu_2.menuAction())
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.btn_chat.setText(_translate("MainWindow", "聊天"))
self.btn_contact.setText(_translate("MainWindow", "好友"))
self.btn_myinfo.setText(_translate("MainWindow", "我的"))
self.btn_about.setText(_translate("MainWindow", "关于"))
self.myavatar.setText(_translate("MainWindow", "avatar"))
self.menu_F.setTitle(_translate("MainWindow", "文件(F)"))
self.menu.setTitle(_translate("MainWindow", "编辑"))
self.menu_2.setTitle(_translate("MainWindow", "帮助"))
self.action_3.setText(_translate("MainWindow", "保存"))
self.action_4.setText(_translate("MainWindow", "退出"))
self.action.setText(_translate("MainWindow", "关于"))

View File

@ -1,40 +0,0 @@
# -*- coding: utf-8 -*-
"""
@File : contact.py
@Author : Shuaikang Zhou
@Time : 2022/12/13 15:07
@IDE : Pycharm
@Version : Python3.10
@comment : ···
"""
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from .userinfoUi import *
from ...DataBase import data
class MyinfoController(QWidget, Ui_Dialog):
exitSignal = pyqtSignal()
urlSignal = pyqtSignal(QUrl)
# username = ''
def __init__(self, Me, parent=None):
super(MyinfoController, self).__init__(parent)
self.setupUi(self)
self.setWindowTitle('WeChat')
self.setWindowIcon(QIcon('./app/data/icon.png'))
self.Me = Me
self.initui()
def initui(self):
self.myinfo = data.get_myInfo()
avatar = self.Me.my_avatar
pixmap = QPixmap(avatar).scaled(80, 80) # 按指定路径找到图片
self.label_avatar.setPixmap(pixmap) # 在label上显示图片
self.label_name.setText(self.myinfo['name'])
self.label_wxid.setText('微信号:' + self.myinfo['username'])
city = f"地区:{self.myinfo['province']}{self.myinfo['city']}"
self.label_city.setText(city)

View File

@ -1,59 +0,0 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'userinfoUi.ui'
#
# Created by: PyQt5 UI code generator 5.15.7
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_Dialog(object):
def setupUi(self, Dialog):
Dialog.setObjectName("Dialog")
Dialog.resize(1120, 720)
Dialog.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor))
Dialog.setAutoFillBackground(False)
self.frame_2 = QtWidgets.QFrame(Dialog)
self.frame_2.setGeometry(QtCore.QRect(0, 0, 1120, 720))
self.frame_2.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame_2.setFrameShadow(QtWidgets.QFrame.Raised)
self.frame_2.setObjectName("frame_2")
self.horizontalLayoutWidget = QtWidgets.QWidget(self.frame_2)
self.horizontalLayoutWidget.setGeometry(QtCore.QRect(340, 60, 291, 82))
self.horizontalLayoutWidget.setObjectName("horizontalLayoutWidget")
self.horizontalLayout = QtWidgets.QHBoxLayout(self.horizontalLayoutWidget)
self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout.setObjectName("horizontalLayout")
self.label_avatar = QtWidgets.QLabel(self.horizontalLayoutWidget)
self.label_avatar.setMinimumSize(QtCore.QSize(80, 80))
self.label_avatar.setObjectName("label_avatar")
self.horizontalLayout.addWidget(self.label_avatar)
self.verticalLayout = QtWidgets.QVBoxLayout()
self.verticalLayout.setObjectName("verticalLayout")
self.label_name = QtWidgets.QLabel(self.horizontalLayoutWidget)
self.label_name.setObjectName("label_name")
self.verticalLayout.addWidget(self.label_name)
self.label_wxid = QtWidgets.QLabel(self.horizontalLayoutWidget)
self.label_wxid.setObjectName("label_wxid")
self.verticalLayout.addWidget(self.label_wxid)
self.label_city = QtWidgets.QLabel(self.horizontalLayoutWidget)
self.label_city.setObjectName("label_city")
self.verticalLayout.addWidget(self.label_city)
self.horizontalLayout.addLayout(self.verticalLayout)
self.horizontalLayout.setStretch(0, 1)
self.horizontalLayout.setStretch(1, 3)
self.retranslateUi(Dialog)
QtCore.QMetaObject.connectSlotsByName(Dialog)
def retranslateUi(self, Dialog):
_translate = QtCore.QCoreApplication.translate
Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
self.label_avatar.setText(_translate("Dialog", "TextLabel"))
self.label_name.setText(_translate("Dialog", "TextLabel"))
self.label_wxid.setText(_translate("Dialog", "TextLabel"))
self.label_city.setText(_translate("Dialog", "TextLabel"))

View File

@ -1,108 +0,0 @@
import os.path
from typing import Dict
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QPixmap
from app.DataBase import data
from app.ui_pc.Icon import Icon
# from app.Ui.Icon import Icon
class Person:
def __init__(self, wxid: str):
self.wxid = wxid
self.conRemark = data.get_conRemark(wxid)
self.nickname, self.alias = data.get_nickname(wxid)
self.avatar_path = data.get_avator(wxid)
if os.path.exists(self.avatar_path):
self.avatar = QPixmap(self.avatar_path).scaled(60, 60)
else:
self.avatar_path = './app/data/icons/default_avatar.svg'
# self.avatar_path = Icon.Default_avatar_path
self.avatar = QPixmap(self.avatar_path).scaled(60, 60)
class Me(Person):
def __init__(self, wxid: str):
super(Me, self).__init__(wxid)
self.city = None
self.province = None
class Contact(Person):
def __init__(self, wxid: str):
super(Contact, self).__init__(wxid)
self.smallHeadImgUrl = ''
self.bigHeadImgUrl = ''
def singleton(cls):
_instance = {}
def inner():
if cls not in _instance:
_instance[cls] = cls()
return _instance[cls]
return inner
@singleton
class MePC:
def __init__(self):
self.avatar = QPixmap(Icon.Default_avatar_path)
self.avatar_path = 'D:\Project\Python\WeChatMsg\\app\data\icons\default_avatar.svg'
self.wxid = ''
self.wx_dir = ''
self.name = ''
self.mobile = ''
def set_avatar(self, img_bytes):
if not img_bytes:
self.avatar.load(Icon.Default_avatar_path)
return
if img_bytes[:4] == b'\x89PNG':
self.avatar.loadFromData(img_bytes, format='PNG')
else:
self.avatar.loadFromData(img_bytes, format='jfif')
class ContactPC:
def __init__(self, contact_info: Dict):
self.wxid = contact_info.get('UserName')
self.remark = contact_info.get('Remark')
# Alias,Type,Remark,NickName,PYInitial,RemarkPYInitial,ContactHeadImgUrl.smallHeadImgUrl,ContactHeadImgUrl,bigHeadImgUrl
self.alias = contact_info.get('Alias')
self.nickName = contact_info.get('NickName')
if not self.remark:
self.remark = self.nickName
self.smallHeadImgUrl = contact_info.get('smallHeadImgUrl')
self.smallHeadImgBLOG = b''
self.avatar = QPixmap()
self.avatar_path = 'D:\Project\Python\WeChatMsg\\app\data\icons\default_avatar.svg'
def set_avatar(self, img_bytes):
if not img_bytes:
self.avatar.load(Icon.Default_avatar_path)
return
if img_bytes[:4] == b'\x89PNG':
self.avatar.loadFromData(img_bytes, format='PNG')
else:
self.avatar.loadFromData(img_bytes, format='jfif')
self.avatar.scaled(60, 60, Qt.IgnoreAspectRatio, Qt.SmoothTransformation)
class Group(Person):
def __init__(self, wxid: str):
super(Group, self).__init__(wxid)
if __name__ == '__main__':
p1 = MePC()
p2 = MePC()
print(p1 == p2)

View File

@ -5,7 +5,7 @@ from typing import Dict
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QPixmap
from app.ui_pc.Icon import Icon
from app.ui.Icon import Icon
def singleton(cls):

View File

@ -1,28 +0,0 @@
from PyQt5.QtGui import QIcon
from app.resources import resource_rc
var = resource_rc.qt_resource_name
class Icon:
Default_avatar_path = ':/icons/icons/default_avatar.svg'
Default_image_path = ':/icons/icons/404.png'
MainWindow_Icon = QIcon(':/icons/icons/logo.svg')
Default_avatar = QIcon(Default_avatar_path)
Output = QIcon(':/icons/icons/output.svg')
Back = QIcon(':/icons/icons/back.svg')
ToDocx = QIcon(':/icons/icons/word.svg')
ToCSV = QIcon(':/icons/icons/csv.svg')
ToHTML = QIcon(':/icons/icons/html.svg')
ToTXT = QIcon(':/icons/icons/txt.svg')
Chat_Icon = QIcon(':/icons/icons/chat.svg')
Contact_Icon = QIcon(':/icons/icons/contact.svg')
MyInfo_Icon = QIcon(':/icons/icons/myinfo.svg')
Annual_Report_Icon = QIcon(':/icons/icons/annual_report.svg')
Analysis_Icon = QIcon(':/icons/icons/analysis.svg')
Emotion_Icon = QIcon(':/icons/icons/emotion.svg')
Search_Icon = QIcon(':/icons/icons/search.svg')
Tool_Icon = QIcon(':/icons/icons/tool.svg')
Home_Icon = QIcon(':/icons/icons/home.svg')
Help_Icon = QIcon(':/icons/icons/help.svg')

View File

View File

@ -1 +0,0 @@
from .chat_window import ChatWindow

View File

@ -1,48 +0,0 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'chatInfoUi.ui'
#
# Created by: PyQt5 UI code generator 5.15.7
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore, QtWidgets
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName("Form")
self.verticalLayout = QtWidgets.QVBoxLayout(Form)
self.verticalLayout.setContentsMargins(0, 0, 0, 0)
self.verticalLayout.setSpacing(0)
self.verticalLayout.setObjectName("verticalLayout")
self.frame = QtWidgets.QFrame(Form)
self.frame.setFrameShape(QtWidgets.QFrame.NoFrame)
self.frame.setFrameShadow(QtWidgets.QFrame.Raised)
self.frame.setObjectName("frame")
self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.frame)
self.verticalLayout_2.setObjectName("verticalLayout_2")
self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
self.label_reamrk = QtWidgets.QLabel(self.frame)
self.label_reamrk.setObjectName("label_reamrk")
self.horizontalLayout_2.addWidget(self.label_reamrk)
spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.horizontalLayout_2.addItem(spacerItem)
self.toolButton = QtWidgets.QToolButton(self.frame)
self.toolButton.setObjectName("toolButton")
self.horizontalLayout_2.addWidget(self.toolButton)
self.verticalLayout_2.addLayout(self.horizontalLayout_2)
self.verticalLayout.addWidget(self.frame)
self.retranslateUi(Form)
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
_translate = QtCore.QCoreApplication.translate
Form.setWindowTitle(_translate("Form", "Form"))
self.label_reamrk.setText(_translate("Form", "TextLabel"))
self.toolButton.setText(_translate("Form", "..."))

View File

@ -1,74 +0,0 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'chatUi.ui'
#
# Created by: PyQt5 UI code generator 5.15.7
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore, QtWidgets
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName("Form")
Form.resize(840, 752)
Form.setStyleSheet("background: rgb(240, 240, 240);")
self.horizontalLayout_2 = QtWidgets.QHBoxLayout(Form)
self.horizontalLayout_2.setSpacing(6)
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
self.verticalLayout_2 = QtWidgets.QVBoxLayout()
self.verticalLayout_2.setSpacing(6)
self.verticalLayout_2.setObjectName("verticalLayout_2")
self.verticalLayout = QtWidgets.QVBoxLayout()
self.verticalLayout.setObjectName("verticalLayout")
self.horizontalLayout = QtWidgets.QHBoxLayout()
self.horizontalLayout.setObjectName("horizontalLayout")
self.label = QtWidgets.QLabel(Form)
self.label.setText("")
self.label.setObjectName("label")
self.horizontalLayout.addWidget(self.label)
self.lineEdit = QtWidgets.QLineEdit(Form)
self.lineEdit.setMinimumSize(QtCore.QSize(200, 30))
self.lineEdit.setMaximumSize(QtCore.QSize(200, 16777215))
self.lineEdit.setStyleSheet("background:transparent;\n"
"border-radius:5px;\n"
"border-top: 0px solid #b2e281;\n"
"border-bottom: 0px solid #b2e281;\n"
"border-right: 0px solid #b2e281;\n"
"border-left: 0px solid #b2e281;\n"
"border-style:outset;\n"
"background-color:rgb(226,226,226);\n"
" ")
self.lineEdit.setCursorMoveStyle(QtCore.Qt.VisualMoveStyle)
self.lineEdit.setObjectName("lineEdit")
self.horizontalLayout.addWidget(self.lineEdit)
self.label_2 = QtWidgets.QLabel(Form)
self.label_2.setMinimumSize(QtCore.QSize(30, 0))
self.label_2.setText("")
self.label_2.setObjectName("label_2")
self.horizontalLayout.addWidget(self.label_2)
self.verticalLayout.addLayout(self.horizontalLayout)
self.verticalLayout_2.addLayout(self.verticalLayout)
self.listWidget = QtWidgets.QListWidget(Form)
self.listWidget.setMinimumSize(QtCore.QSize(250, 0))
self.listWidget.setMaximumSize(QtCore.QSize(250, 16777215))
self.listWidget.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.listWidget.setObjectName("listWidget")
self.verticalLayout_2.addWidget(self.listWidget)
self.verticalLayout_2.setStretch(1, 1)
self.horizontalLayout_2.addLayout(self.verticalLayout_2)
self.stackedWidget = QtWidgets.QStackedWidget(Form)
self.stackedWidget.setObjectName("stackedWidget")
self.horizontalLayout_2.addWidget(self.stackedWidget)
self.horizontalLayout_2.setStretch(1, 1)
self.retranslateUi(Form)
self.stackedWidget.setCurrentIndex(-1)
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
_translate = QtCore.QCoreApplication.translate
Form.setWindowTitle(_translate("Form", "Form"))

View File

@ -1,160 +0,0 @@
import traceback
from PyQt5.QtCore import QThread, pyqtSignal
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QLabel, QHBoxLayout
from app.DataBase import msg_db, hard_link_db
from app.components.bubble_message import BubbleMessage, ChatWidget, Notice
from app.person_pc import MePC
from app.util import get_abs_path
from app.util.emoji import get_emoji
class ChatInfo(QWidget):
def __init__(self, contact, parent=None):
super().__init__(parent)
self.last_timestamp = 0
self.last_str_time = ''
self.last_pos = 0
self.contact = contact
self.init_ui()
self.show_chats()
def init_ui(self):
self.label_reamrk = QLabel(self.contact.remark)
self.hBoxLayout = QHBoxLayout()
self.hBoxLayout.addWidget(self.label_reamrk)
self.vBoxLayout = QVBoxLayout()
self.vBoxLayout.setSpacing(0)
self.vBoxLayout.addLayout(self.hBoxLayout)
self.chat_window = ChatWidget()
self.chat_window.scrollArea.verticalScrollBar().valueChanged.connect(self.verticalScrollBar)
self.vBoxLayout.addWidget(self.chat_window)
self.setLayout(self.vBoxLayout)
def show_chats(self):
self.show_chat_thread = ShowChatThread(self.contact)
self.show_chat_thread.showSingal.connect(self.add_message)
self.show_chat_thread.finishSingal.connect(self.show_finish)
# self.show_chat_thread.start()
def show_finish(self, ok):
self.setScrollBarPos()
self.show_chat_thread.quit()
def verticalScrollBar(self, pos):
"""
滚动条到0之后自动更新聊天记录
:param pos:
:return:
"""
# print(pos)
if pos > 0:
return
# 记录当前滚动条最大值
self.last_pos = self.chat_window.verticalScrollBar().maximum()
self.update_history_messages()
def update_history_messages(self):
self.show_chat_thread.start()
def setScrollBarPos(self):
"""
将滚动条位置设置为上次看到的地方
:param pos:
:return:
"""
self.chat_window.update()
self.chat_window.show()
pos = self.chat_window.verticalScrollBar().maximum() - self.last_pos
self.chat_window.set_scroll_bar_value(pos)
def is_5_min(self, timestamp):
if abs(timestamp - self.last_timestamp) > 300:
self.last_timestamp = timestamp
return True
return False
def add_message(self, message):
try:
type_ = message[2]
str_content = message[7]
str_time = message[8]
# print(type_, type(type_))
is_send = message[4]
avatar = MePC().avatar if is_send else self.contact.avatar
timestamp = message[5]
BytesExtra = message[10]
if type_ == 1:
if self.is_5_min(timestamp):
time_message = Notice(self.last_str_time)
self.last_str_time = str_time
self.chat_window.add_message_item(time_message, 0)
bubble_message = BubbleMessage(
str_content,
avatar,
type_,
is_send
)
self.chat_window.add_message_item(bubble_message, 0)
elif type_ == 3:
# return
if self.is_5_min(timestamp):
time_message = Notice(self.last_str_time)
self.last_str_time = str_time
self.chat_window.add_message_item(time_message, 0)
image_path = hard_link_db.get_image(content=str_content,bytesExtra=BytesExtra, thumb=False)
image_path = get_abs_path(image_path)
bubble_message = BubbleMessage(
image_path,
avatar,
type_,
is_send
)
self.chat_window.add_message_item(bubble_message, 0)
elif type_ == 47:
return
if self.is_5_min(timestamp):
time_message = Notice(self.last_str_time)
self.last_str_time = str_time
self.chat_window.add_message_item(time_message, 0)
image_path = get_emoji(str_content, thumb=True)
bubble_message = BubbleMessage(
image_path,
avatar,
3,
is_send
)
self.chat_window.add_message_item(bubble_message, 0)
elif type_ == 10000:
str_content = str_content.lstrip('<revokemsg>').rstrip('</revokemsg>')
message = Notice(str_content )
self.chat_window.add_message_item(message, 0)
except:
print(message)
traceback.print_exc()
class ShowChatThread(QThread):
showSingal = pyqtSignal(tuple)
finishSingal = pyqtSignal(int)
msg_id = 0
# heightSingal = pyqtSignal(int)
def __init__(self, contact):
super().__init__()
self.last_message_id = 9999999999
self.wxid = contact.wxid
def run(self) -> None:
messages = msg_db.get_message_by_num(self.wxid, self.last_message_id)
if messages:
self.last_message_id = messages[-1][0]
for message in messages:
self.showSingal.emit(message)
self.msg_id += 1
self.finishSingal.emit(1)

View File

@ -1,165 +0,0 @@
from PyQt5.QtCore import QThread, pyqtSignal
from PyQt5.QtWidgets import QWidget, QMessageBox, QAction, QLineEdit
from app.DataBase import micro_msg_db, misc_db, msg_db
from app.components import ContactQListWidgetItem
from app.person_pc import ContactPC
from app.ui_pc.Icon import Icon
from app.util import search
from .chatUi import Ui_Form
from .chat_info import ChatInfo
# 美化样式表
Stylesheet = """
/*去掉item虚线边框*/
QListWidget, QListView, QTreeWidget, QTreeView {
outline: 0px;
border:none;
background-color:rgb(240,240,240)
}
/*设置左侧选项的最小最大宽度,文字颜色和背景颜色*/
QListWidget {
min-width: 250px;
max-width: 250px;
min-height: 80px;
max-height: 1200px;
color: black;
border:none;
}
QListWidget::item{
height:60px;
width:250px;
}
/*被选中时的背景颜色和左边框颜色*/
QListWidget::item:selected {
background: rgb(204, 204, 204);
border-bottom: 2px solid rgb(9, 187, 7);
border-left:none;
color: black;
font-weight: bold;
}
/*鼠标悬停颜色*/
HistoryPanel::item:hover {
background: rgb(52, 52, 52);
}
"""
class ChatWindow(QWidget, Ui_Form):
load_finish_signal = pyqtSignal(bool)
def __init__(self, parent=None):
super().__init__(parent)
self.show_thread = None
self.setupUi(self)
self.ok_flag = False
self.setStyleSheet(Stylesheet)
self.contacts = [[], []]
self.init_ui()
self.show_chats()
self.visited = set()
def init_ui(self):
search_action = QAction(self.lineEdit)
search_action.setIcon(Icon.Search_Icon)
self.lineEdit.addAction(search_action, QLineEdit.LeadingPosition)
self.lineEdit.returnPressed.connect(self.search_contact)
self.listWidget.clear()
self.listWidget.currentRowChanged.connect(self.setCurrentIndex)
self.listWidget.setCurrentRow(0)
self.stackedWidget.setCurrentIndex(0)
def show_chats(self):
# return
if self.ok_flag:
return
msg_db.init_database()
micro_msg_db.init_database()
if not msg_db.open_flag:
QMessageBox.critical(self, "错误", "数据库不存在\n请先解密数据库")
self.show_thread = ShowThread()
self.show_thread.load_finish_signal.connect(self.load_finish_signal)
self.show_thread.start()
return
self.show_thread = ShowContactThread()
self.show_thread.showSingal.connect(self.show_chat)
self.show_thread.load_finish_signal.connect(self.stop_loading)
self.show_thread.start()
self.ok_flag = True
def search_contact(self):
content = self.lineEdit.text()
if not content:
return
index = self.search_contact_index(content)
self.select_contact_by_index(index)
def search_contact_index(self, content: str) -> int:
return search.search_by_content(content, self.contacts)
def select_contact_by_index(self, index):
self.stackedWidget.setCurrentIndex(index)
self.listWidget.setCurrentRow(index)
def show_chat(self, contact):
self.contacts[0].append(contact.remark)
self.contacts[1].append(contact.nickName)
contact_item = ContactQListWidgetItem(contact.remark, contact.smallHeadImgUrl, contact.smallHeadImgBLOG)
self.listWidget.addItem(contact_item)
self.listWidget.setItemWidget(contact_item, contact_item.widget)
chat_info_window = ChatInfo(contact)
self.stackedWidget.addWidget(chat_info_window)
def setCurrentIndex(self, row):
# print(row)
self.stackedWidget.setCurrentIndex(row)
if row not in self.visited:
chat_info_window = self.stackedWidget.currentWidget()
chat_info_window.update_history_messages()
self.visited.add(row)
def stop_loading(self, a0):
# self.label.setVisible(False)
self.load_finish_signal.emit(True)
class ShowContactThread(QThread):
showSingal = pyqtSignal(ContactPC)
load_finish_signal = pyqtSignal(bool)
# heightSingal = pyqtSignal(int)
def __init__(self):
super().__init__()
def run(self) -> None:
contact_info_lists = micro_msg_db.get_contact()
for contact_info_list in contact_info_lists:
# UserName, Alias,Type,Remark,NickName,PYInitial,RemarkPYInitial,ContactHeadImgUrl.smallHeadImgUrl,ContactHeadImgUrl,bigHeadImgUrl
contact_info = {
'UserName': contact_info_list[0],
'Alias': contact_info_list[1],
'Type': contact_info_list[2],
'Remark': contact_info_list[3],
'NickName': contact_info_list[4],
'smallHeadImgUrl': contact_info_list[7]
}
contact = ContactPC(contact_info)
contact.smallHeadImgBLOG = misc_db.get_avatar_buffer(contact.wxid)
contact.set_avatar(contact.smallHeadImgBLOG)
self.showSingal.emit(contact)
# pprint(contact.__dict__)
self.load_finish_signal.emit(True)
class ShowThread(QThread):
showSingal = pyqtSignal(ContactPC)
load_finish_signal = pyqtSignal(bool)
# heightSingal = pyqtSignal(int)
def __init__(self):
super().__init__()
def run(self) -> None:
QThread.sleep(1)
self.load_finish_signal.emit(True)

View File

@ -1 +0,0 @@
from .contact_window import ContactWindow

View File

@ -1,162 +0,0 @@
from PyQt5.QtCore import pyqtSignal, QUrl, QThread
from PyQt5.QtGui import QDesktopServices
from PyQt5.QtWidgets import QWidget, QMenu, QAction, QToolButton, QMessageBox, QDialog
from app.DataBase.output_pc import Output
from app.ui_pc.Icon import Icon
from .contactInfoUi import Ui_Form
from .userinfo import userinfo
from ...person_pc import ContactPC
from .export_dialog import ExportDialog
class ContactInfo(QWidget, Ui_Form):
exitSignal = pyqtSignal()
urlSignal = pyqtSignal(QUrl)
# username = ''
def __init__(self, contact, parent=None):
super(ContactInfo, self).__init__(parent)
self.setupUi(self)
self.contact: ContactPC = contact
self.view_userinfo = userinfo.UserinfoController(self.contact)
self.btn_back.clicked.connect(self.back)
self.init_ui()
def init_ui(self):
self.btn_back.setIcon(Icon.Back)
self.btn_report.setIcon(Icon.Annual_Report_Icon)
self.btn_analysis.setIcon(Icon.Analysis_Icon)
self.btn_emotion.setIcon(Icon.Emotion_Icon)
self.btn_report.clicked.connect(self.annual_report)
self.btn_analysis.clicked.connect(self.analysis)
self.btn_emotion.clicked.connect(self.emotionale_Analysis)
self.label_remark.setText(self.contact.remark)
self.stackedWidget.addWidget(self.view_userinfo)
self.stackedWidget.setCurrentWidget(self.view_userinfo)
menu = QMenu(self)
self.toDocxAct = QAction(Icon.ToDocx, '导出Docx', self)
self.toCSVAct = QAction(Icon.ToCSV, '导出CSV', self)
self.toHtmlAct = QAction(Icon.ToHTML, '导出HTML', self)
self.toTxtAct = QAction(Icon.ToTXT, '导出TXT', self)
self.toolButton_output.setPopupMode(QToolButton.MenuButtonPopup)
self.toolButton_output.clicked.connect(self.toolButton_show)
menu.addAction(self.toDocxAct)
menu.addAction(self.toCSVAct)
menu.addAction(self.toHtmlAct)
menu.addAction(self.toTxtAct)
self.toolButton_output.setMenu(menu)
self.toolButton_output.setIcon(Icon.Output)
# self.toolButton_output.addSeparator()
self.toHtmlAct.triggered.connect(self.output)
self.toDocxAct.triggered.connect(self.output)
self.toCSVAct.triggered.connect(self.output)
self.toTxtAct.triggered.connect(self.output)
def toolButton_show(self):
self.toolButton_output.showMenu()
def analysis(self):
QMessageBox.warning(self,
"别急别急",
"马上就实现该功能"
)
return
self.stackedWidget.setCurrentWidget(self.view_analysis)
if 'room' in self.contact.wxid:
QMessageBox.warning(
self, '警告',
'暂不支持群组'
)
return
self.view_analysis.start()
def annual_report(self):
# QMessageBox.warning(
# self,
# "提示",
# "敬请期待"
# )
# return
self.contact.save_avatar()
self.report_thread = ReportThread(self.contact)
self.report_thread.okSignal.connect(lambda x: QDesktopServices.openUrl(QUrl("http://127.0.0.1:21314")))
self.report_thread.start()
QDesktopServices.openUrl(QUrl("http://127.0.0.1:21314"))
def emotionale_Analysis(self):
QMessageBox.warning(self,
"别急别急",
"马上就实现该功能"
)
return
self.stackedWidget.setCurrentWidget(self.view_emotion)
if 'room' in self.contact.wxid:
QMessageBox.warning(
self, '警告',
'暂不支持群组'
)
return
self.view_emotion.start()
def back(self):
"""
将userinfo界面设置为可见其他界面设置为不可见
"""
self.stackedWidget.setCurrentWidget(self.view_userinfo)
def output(self):
"""
导出聊天记录
:return:
"""
self.stackedWidget.setCurrentWidget(self.view_userinfo)
if self.sender() == self.toDocxAct:
print('功能暂未实现')
QMessageBox.warning(self,
"别急别急",
"马上就实现该功能"
)
return
self.outputThread = Output(self.Me, self.contact.wxid)
elif self.sender() == self.toCSVAct:
# self.outputThread = Output(self.contact, type_=Output.CSV)
dialog = ExportDialog(self.contact,title='选择导出的消息类型', file_type='csv', parent=self)
result = dialog.exec_() # 使用exec_()获取用户的操作结果
elif self.sender() == self.toHtmlAct:
dialog = ExportDialog(self.contact,title='选择导出的消息类型', file_type='html', parent=self)
result = dialog.exec_() # 使用exec_()获取用户的操作结果
elif self.sender() == self.toTxtAct:
dialog = ExportDialog(self.contact, title='选择导出的消息类型', file_type='txt', parent=self)
result = dialog.exec_() # 使用exec_()获取用户的操作结果
def hide_progress_bar(self, int):
reply = QMessageBox(self)
reply.setIcon(QMessageBox.Information)
reply.setWindowTitle('OK')
reply.setText(f"导出聊天记录成功\n在./data/目录下(跟exe文件在一起)")
reply.addButton("确认", QMessageBox.AcceptRole)
reply.addButton("取消", QMessageBox.RejectRole)
api = reply.exec_()
self.view_userinfo.progressBar.setVisible(False)
def output_progress(self, value):
self.view_userinfo.progressBar.setProperty('value', value)
def set_progressBar_range(self, value):
self.view_userinfo.progressBar.setVisible(True)
self.view_userinfo.progressBar.setRange(0, value)
class ReportThread(QThread):
okSignal = pyqtSignal(bool)
def __init__(self, contact):
super().__init__()
self.contact = contact
def run(self):
from app.web_ui import web
web.contact = self.contact
web.run(port='21314')
self.okSignal.emit(True)

View File

@ -1,107 +0,0 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'contactInfoUi.ui'
#
# Created by: PyQt5 UI code generator 5.15.7
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName("Form")
Form.resize(494, 748)
self.verticalLayout = QtWidgets.QVBoxLayout(Form)
self.verticalLayout.setObjectName("verticalLayout")
self.horizontalLayout_3 = QtWidgets.QHBoxLayout()
self.horizontalLayout_3.setSpacing(0)
self.horizontalLayout_3.setObjectName("horizontalLayout_3")
self.label_remark = QtWidgets.QLabel(Form)
self.label_remark.setMaximumSize(QtCore.QSize(120, 100))
font = QtGui.QFont()
font.setPointSize(12)
self.label_remark.setFont(font)
self.label_remark.setText("")
self.label_remark.setObjectName("label_remark")
self.horizontalLayout_3.addWidget(self.label_remark)
self.btn_analysis = QtWidgets.QPushButton(Form)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.btn_analysis.sizePolicy().hasHeightForWidth())
self.btn_analysis.setSizePolicy(sizePolicy)
self.btn_analysis.setStyleSheet("")
self.btn_analysis.setFlat(False)
self.btn_analysis.setObjectName("btn_analysis")
self.horizontalLayout_3.addWidget(self.btn_analysis)
self.btn_emotion = QtWidgets.QPushButton(Form)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.btn_emotion.sizePolicy().hasHeightForWidth())
self.btn_emotion.setSizePolicy(sizePolicy)
self.btn_emotion.setFlat(False)
self.btn_emotion.setObjectName("btn_emotion")
self.horizontalLayout_3.addWidget(self.btn_emotion)
self.btn_report = QtWidgets.QPushButton(Form)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.btn_report.sizePolicy().hasHeightForWidth())
self.btn_report.setSizePolicy(sizePolicy)
self.btn_report.setFlat(False)
self.btn_report.setObjectName("btn_report")
self.horizontalLayout_3.addWidget(self.btn_report)
self.btn_back = QtWidgets.QPushButton(Form)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.btn_back.sizePolicy().hasHeightForWidth())
self.btn_back.setSizePolicy(sizePolicy)
self.btn_back.setFlat(False)
self.btn_back.setObjectName("btn_back")
self.horizontalLayout_3.addWidget(self.btn_back)
self.toolButton_output = QtWidgets.QToolButton(Form)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.toolButton_output.sizePolicy().hasHeightForWidth())
self.toolButton_output.setSizePolicy(sizePolicy)
icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap("../../data/icons/output.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.toolButton_output.setIcon(icon)
self.toolButton_output.setCheckable(False)
self.toolButton_output.setPopupMode(QtWidgets.QToolButton.MenuButtonPopup)
self.toolButton_output.setToolButtonStyle(QtCore.Qt.ToolButtonTextBesideIcon)
self.toolButton_output.setAutoRaise(True)
self.toolButton_output.setArrowType(QtCore.Qt.NoArrow)
self.toolButton_output.setObjectName("toolButton_output")
self.horizontalLayout_3.addWidget(self.toolButton_output)
self.horizontalLayout_3.setStretch(0, 1)
self.verticalLayout.addLayout(self.horizontalLayout_3)
self.stackedWidget = QtWidgets.QStackedWidget(Form)
self.stackedWidget.setObjectName("stackedWidget")
self.page_3 = QtWidgets.QWidget()
self.page_3.setObjectName("page_3")
self.stackedWidget.addWidget(self.page_3)
self.page_4 = QtWidgets.QWidget()
self.page_4.setObjectName("page_4")
self.stackedWidget.addWidget(self.page_4)
self.verticalLayout.addWidget(self.stackedWidget)
self.retranslateUi(Form)
self.stackedWidget.setCurrentIndex(1)
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
_translate = QtCore.QCoreApplication.translate
Form.setWindowTitle(_translate("Form", "Form"))
self.btn_analysis.setText(_translate("Form", "统计信息"))
self.btn_emotion.setText(_translate("Form", "情感分析"))
self.btn_report.setText(_translate("Form", "年度报告"))
self.btn_back.setText(_translate("Form", "退出"))
self.toolButton_output.setText(_translate("Form", "导出聊天记录"))

View File

@ -1,74 +0,0 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'contactUi.ui'
#
# Created by: PyQt5 UI code generator 5.15.7
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore, QtWidgets
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName("Form")
Form.resize(840, 752)
Form.setStyleSheet("background: rgb(240, 240, 240);")
self.horizontalLayout_2 = QtWidgets.QHBoxLayout(Form)
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
self.verticalLayout_2 = QtWidgets.QVBoxLayout()
self.verticalLayout_2.setSpacing(6)
self.verticalLayout_2.setObjectName("verticalLayout_2")
self.verticalLayout = QtWidgets.QVBoxLayout()
self.verticalLayout.setObjectName("verticalLayout")
self.horizontalLayout = QtWidgets.QHBoxLayout()
self.horizontalLayout.setObjectName("horizontalLayout")
self.label = QtWidgets.QLabel(Form)
self.label.setText("")
self.label.setObjectName("label")
self.horizontalLayout.addWidget(self.label)
self.lineEdit = QtWidgets.QLineEdit(Form)
self.lineEdit.setMinimumSize(QtCore.QSize(200, 30))
self.lineEdit.setMaximumSize(QtCore.QSize(200, 16777215))
self.lineEdit.setStyleSheet("background:transparent;\n"
"border-radius:5px;\n"
"border-top: 0px solid #b2e281;\n"
"border-bottom: 0px solid #b2e281;\n"
"border-right: 0px solid #b2e281;\n"
"border-left: 0px solid #b2e281;\n"
"border-style:outset;\n"
"background-color:rgb(226,226,226);\n"
" ")
self.lineEdit.setCursorMoveStyle(QtCore.Qt.VisualMoveStyle)
self.lineEdit.setObjectName("lineEdit")
self.horizontalLayout.addWidget(self.lineEdit)
self.label_2 = QtWidgets.QLabel(Form)
self.label_2.setMinimumSize(QtCore.QSize(30, 0))
self.label_2.setMaximumSize(QtCore.QSize(30, 16777215))
self.label_2.setText("")
self.label_2.setObjectName("label_2")
self.horizontalLayout.addWidget(self.label_2)
self.verticalLayout.addLayout(self.horizontalLayout)
self.verticalLayout_2.addLayout(self.verticalLayout)
self.listWidget = QtWidgets.QListWidget(Form)
self.listWidget.setMinimumSize(QtCore.QSize(250, 0))
self.listWidget.setMaximumSize(QtCore.QSize(250, 16777215))
self.listWidget.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.listWidget.setObjectName("listWidget")
self.verticalLayout_2.addWidget(self.listWidget)
self.verticalLayout_2.setStretch(1, 1)
self.horizontalLayout_2.addLayout(self.verticalLayout_2)
self.stackedWidget = QtWidgets.QStackedWidget(Form)
self.stackedWidget.setObjectName("stackedWidget")
self.horizontalLayout_2.addWidget(self.stackedWidget)
self.horizontalLayout_2.setStretch(1, 1)
self.retranslateUi(Form)
self.stackedWidget.setCurrentIndex(-1)
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
_translate = QtCore.QCoreApplication.translate
Form.setWindowTitle(_translate("Form", "Form"))

View File

@ -1,155 +0,0 @@
from PyQt5.QtCore import QThread, pyqtSignal
from PyQt5.QtWidgets import QWidget, QMessageBox, QAction, QLineEdit
from app.DataBase import micro_msg_db, misc_db
from app.components import ContactQListWidgetItem
from app.person_pc import ContactPC
from app.ui_pc.Icon import Icon
from .contactInfo import ContactInfo
from .contactUi import Ui_Form
from ...util import search
# 美化样式表
Stylesheet = """
QPushButton{
background-color: transparent;
}
QPushButton:hover {
background-color: lightgray;
}
/*去掉item虚线边框*/
QListWidget, QListView, QTreeWidget, QTreeView {
outline: 0px;
border:none;
background-color:rgb(240,240,240)
}
/*设置左侧选项的最小最大宽度,文字颜色和背景颜色*/
QListWidget {
min-width: 250px;
max-width: 250px;
min-height: 80px;
max-height: 1200px;
color: black;
border:none;
}
QListWidget::item{
height:60px;
width:250px;
}
/*被选中时的背景颜色和左边框颜色*/
QListWidget::item:selected {
background: rgb(204, 204, 204);
border-bottom: 2px solid rgb(9, 187, 7);
border-left:none;
color: black;
font-weight: bold;
}
/*鼠标悬停颜色*/
HistoryPanel::item:hover {
background: rgb(52, 52, 52);
}
"""
class ContactWindow(QWidget, Ui_Form):
load_finish_signal = pyqtSignal(bool)
def __init__(self, parent=None):
super().__init__(parent)
self.show_thread = None
self.setupUi(self)
self.ok_flag = False
self.setStyleSheet(Stylesheet)
self.init_ui()
self.contacts = [[], []]
self.show_contacts()
def init_ui(self):
search_action = QAction(self.lineEdit)
search_action.setIcon(Icon.Search_Icon)
self.lineEdit.addAction(search_action, QLineEdit.LeadingPosition)
self.lineEdit.returnPressed.connect(self.search_contact)
self.listWidget.clear()
self.listWidget.currentRowChanged.connect(self.setCurrentIndex)
self.listWidget.setCurrentRow(0)
self.stackedWidget.setCurrentIndex(0)
def show_contacts(self):
# return
if self.ok_flag:
return
micro_msg_db.init_database()
if not micro_msg_db.open_flag:
QMessageBox.critical(self, "错误", "数据库不存在\n请先解密数据库")
self.show_thread = ShowThread()
self.show_thread.showSingal.connect(self.show_contact)
self.show_thread.load_finish_signal.connect(self.load_finish_signal)
self.show_thread.start()
return
self.show_thread = ShowContactThread()
self.show_thread.showSingal.connect(self.show_contact)
self.show_thread.load_finish_signal.connect(self.load_finish_signal)
self.show_thread.start()
self.ok_flag = True
def search_contact(self):
keyword = self.lineEdit.text()
if keyword:
index = search.search_by_content(keyword, self.contacts)
self.listWidget.setCurrentRow(index)
self.stackedWidget.setCurrentIndex(index)
def show_contact(self, contact: ContactPC):
self.contacts[0].append(contact.remark)
self.contacts[1].append(contact.nickName)
contact_item = ContactQListWidgetItem(contact.remark, contact.smallHeadImgUrl, contact.smallHeadImgBLOG)
self.listWidget.addItem(contact_item)
self.listWidget.setItemWidget(contact_item, contact_item.widget)
contact_info_window = ContactInfo(contact)
self.stackedWidget.addWidget(contact_info_window)
def setCurrentIndex(self, row):
# print(row)
self.stackedWidget.setCurrentIndex(row)
class ShowContactThread(QThread):
showSingal = pyqtSignal(ContactPC)
load_finish_signal = pyqtSignal(bool)
# heightSingal = pyqtSignal(int)
def __init__(self):
super().__init__()
def run(self) -> None:
contact_info_lists = micro_msg_db.get_contact()
for contact_info_list in contact_info_lists:
# UserName, Alias,Type,Remark,NickName,PYInitial,RemarkPYInitial,ContactHeadImgUrl.smallHeadImgUrl,ContactHeadImgUrl,bigHeadImgUrl
contact_info = {
'UserName': contact_info_list[0],
'Alias': contact_info_list[1],
'Type': contact_info_list[2],
'Remark': contact_info_list[3],
'NickName': contact_info_list[4],
'smallHeadImgUrl': contact_info_list[7]
}
contact = ContactPC(contact_info)
contact.smallHeadImgBLOG = misc_db.get_avatar_buffer(contact.wxid)
contact.set_avatar(contact.smallHeadImgBLOG)
self.showSingal.emit(contact)
# pprint(contact.__dict__)
self.load_finish_signal.emit(True)
class ShowThread(QThread):
showSingal = pyqtSignal(ContactPC)
load_finish_signal = pyqtSignal(bool)
# heightSingal = pyqtSignal(int)
def __init__(self):
super().__init__()
def run(self) -> None:
QThread.sleep(1)
self.load_finish_signal.emit(True)

View File

@ -1,105 +0,0 @@
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QDialog, QVBoxLayout, QCheckBox, QHBoxLayout, \
QProgressBar, QLabel, QMessageBox
from app.DataBase.output_pc import Output
types = {
'文本': 1,
'图片': 3,
'语音': 34,
'视频': 43,
'表情包': 47,
'拍一拍等系统消息': 10000
}
Stylesheet = """
QPushButton{
background-color: #ffffff;
}
QPushButton:hover {
background-color: lightgray;
}
"""
class ExportDialog(QDialog):
def __init__(self, contact=None, title="选择导出的类型", file_type="csv", parent=None):
super(ExportDialog, self).__init__(parent)
self.setStyleSheet(Stylesheet)
self.contact = contact
if file_type == 'html':
self.export_type = Output.HTML
self.export_choices = {"文本": True, "图片": True, "语音": True, "视频": True, "表情包": True,
'拍一拍等系统消息': True} # 定义导出的数据类型,默认全部选择
elif file_type == 'csv':
self.export_type = Output.CSV
self.export_choices = {"文本": True, "图片": True, "视频": True, "表情包": True} # 定义导出的数据类型,默认全部选择
elif file_type == 'txt':
self.export_type = Output.TXT
self.export_choices = {"文本": True, "图片": True, "语音": True, "视频": True, "表情包": True} # 定义导出的数据类型,默认全部选择
else:
self.export_choices = {"文本": True, "图片": True, "视频": True, "表情包": True} # 定义导出的数据类型,默认全部选择
self.setWindowTitle(title)
layout = QVBoxLayout(self)
self.resize(400, 300)
self.worker = None # 导出线程
self.progress_bar = QProgressBar(self)
self.progress_label = QLabel(self)
for export_type, default_state in self.export_choices.items():
checkbox = QCheckBox(export_type)
checkbox.setChecked(default_state)
layout.addWidget(checkbox)
layout.addWidget(self.progress_bar)
layout.addWidget(self.progress_label)
hlayout = QHBoxLayout(self)
self.export_button = QPushButton("导出")
self.export_button.clicked.connect(self.export_data)
hlayout.addWidget(self.export_button)
self.cancel_button = QPushButton("取消")
self.cancel_button.clicked.connect(self.reject) # 使用reject关闭对话框
hlayout.addWidget(self.cancel_button)
layout.addLayout(hlayout)
self.setLayout(layout)
def export_data(self):
self.export_button.setEnabled(False)
self.cancel_button.setEnabled(False)
# 在这里获取用户选择的导出数据类型
selected_types = {types[export_type]: checkbox.isChecked() for export_type, checkbox in
zip(self.export_choices.keys(), self.findChildren(QCheckBox))}
# 在这里根据用户选择的数据类型执行导出操作
print("选择的数据类型:", selected_types)
self.worker = Output(self.contact, type_=self.export_type, message_types=selected_types)
self.worker.progressSignal.connect(self.update_progress)
self.worker.okSignal.connect(self.export_finished)
self.worker.start()
# self.accept() # 使用accept关闭对话框
def export_finished(self):
self.export_button.setEnabled(True)
self.cancel_button.setEnabled(True)
reply = QMessageBox(self)
reply.setIcon(QMessageBox.Information)
reply.setWindowTitle('OK')
reply.setText(f"导出聊天记录成功\n在./data/目录下(跟exe文件在一起)")
reply.addButton("确认", QMessageBox.AcceptRole)
reply.addButton("取消", QMessageBox.RejectRole)
api = reply.exec_()
self.accept()
def update_progress(self, progress_percentage):
self.progress_bar.setValue(progress_percentage)
self.progress_label.setText(f"导出进度: {progress_percentage}%")
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
dialog = ExportDialog()
result = dialog.exec_() # 使用exec_()获取用户的操作结果
if result == QDialog.Accepted:
print("用户点击了导出按钮")
else:
print("用户点击了取消按钮")
sys.exit(app.exec_())

View File

@ -1,9 +0,0 @@
# -*- coding: utf-8 -*-
"""
@File : __init__.py.py
@Author : Shuaikang Zhou
@Time : 2022/12/24 10:34
@IDE : Pycharm
@Version : Python3.10
@comment : ···
"""

View File

@ -1,15 +0,0 @@
from PyQt5.QtWidgets import *
from .userinfoUi import Ui_Frame
class UserinfoController(QWidget, Ui_Frame):
def __init__(self, contact, parent=None):
super().__init__(parent)
self.setupUi(self)
self.l_remark.setText(contact.remark)
self.l_avatar.setPixmap(contact.avatar)
self.l_nickname.setText(f'昵称:{contact.nickName}')
self.l_username.setText(f'微信号:{contact.alias}')
self.lineEdit.setText(contact.remark)
self.progressBar.setVisible(False)

View File

@ -1,123 +0,0 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'userinfoUi.ui'
#
# Created by: PyQt5 UI code generator 5.15.7
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_Frame(object):
def setupUi(self, Frame):
Frame.setObjectName("Frame")
Frame.resize(624, 720)
Frame.setCursor(QtGui.QCursor(QtCore.Qt.IBeamCursor))
Frame.setMouseTracking(True)
Frame.setTabletTracking(True)
self.horizontalLayout_3 = QtWidgets.QHBoxLayout(Frame)
self.horizontalLayout_3.setObjectName("horizontalLayout_3")
self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.horizontalLayout_2.addItem(spacerItem)
self.verticalLayout = QtWidgets.QVBoxLayout()
self.verticalLayout.setObjectName("verticalLayout")
spacerItem1 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
self.verticalLayout.addItem(spacerItem1)
self.gridLayout = QtWidgets.QGridLayout()
self.gridLayout.setHorizontalSpacing(6)
self.gridLayout.setObjectName("gridLayout")
self.l_avatar = QtWidgets.QLabel(Frame)
self.l_avatar.setMinimumSize(QtCore.QSize(80, 80))
self.l_avatar.setMaximumSize(QtCore.QSize(80, 80))
self.l_avatar.setText("")
self.l_avatar.setPixmap(QtGui.QPixmap("../../../a_img/be0fa6c0c4707fb5f7b37b660de826d3.jpg"))
self.l_avatar.setScaledContents(True)
self.l_avatar.setObjectName("l_avatar")
self.gridLayout.addWidget(self.l_avatar, 0, 0, 3, 1)
self.l_remark = QtWidgets.QLabel(Frame)
self.l_remark.setMinimumSize(QtCore.QSize(0, 30))
self.l_remark.setMaximumSize(QtCore.QSize(16777215, 30))
font = QtGui.QFont()
font.setPointSize(15)
self.l_remark.setFont(font)
self.l_remark.setObjectName("l_remark")
self.gridLayout.addWidget(self.l_remark, 0, 1, 1, 1)
self.l_nickname = QtWidgets.QLabel(Frame)
self.l_nickname.setMinimumSize(QtCore.QSize(0, 30))
self.l_nickname.setMaximumSize(QtCore.QSize(16777215, 30))
self.l_nickname.setObjectName("l_nickname")
self.gridLayout.addWidget(self.l_nickname, 1, 1, 1, 1)
self.l_username = QtWidgets.QLabel(Frame)
self.l_username.setMinimumSize(QtCore.QSize(0, 20))
self.l_username.setMaximumSize(QtCore.QSize(16777215, 20))
self.l_username.setObjectName("l_username")
self.gridLayout.addWidget(self.l_username, 2, 1, 1, 1)
self.gridLayout.setRowStretch(0, 1)
self.gridLayout.setRowStretch(1, 1)
self.gridLayout.setRowStretch(2, 1)
self.verticalLayout.addLayout(self.gridLayout)
spacerItem2 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
self.verticalLayout.addItem(spacerItem2)
self.horizontalLayout = QtWidgets.QHBoxLayout()
self.horizontalLayout.setObjectName("horizontalLayout")
self.label = QtWidgets.QLabel(Frame)
self.label.setMinimumSize(QtCore.QSize(80, 0))
self.label.setMaximumSize(QtCore.QSize(80, 16777215))
font = QtGui.QFont()
font.setPointSize(15)
self.label.setFont(font)
self.label.setObjectName("label")
self.horizontalLayout.addWidget(self.label)
self.lineEdit = QtWidgets.QLineEdit(Frame)
self.lineEdit.setMinimumSize(QtCore.QSize(0, 25))
self.lineEdit.setMaximumSize(QtCore.QSize(16777215, 25))
font = QtGui.QFont()
font.setPointSize(15)
self.lineEdit.setFont(font)
self.lineEdit.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor))
self.lineEdit.setAutoFillBackground(False)
self.lineEdit.setStyleSheet("\n"
" background:transparent;border-width:0;border-style:outset\n"
" ")
self.lineEdit.setObjectName("lineEdit")
self.horizontalLayout.addWidget(self.lineEdit)
self.verticalLayout.addLayout(self.horizontalLayout)
spacerItem3 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
self.verticalLayout.addItem(spacerItem3)
self.progressBar = QtWidgets.QProgressBar(Frame)
self.progressBar.setProperty("value", 24)
self.progressBar.setObjectName("progressBar")
self.verticalLayout.addWidget(self.progressBar)
spacerItem4 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
self.verticalLayout.addItem(spacerItem4)
self.verticalLayout.setStretch(0, 2)
self.verticalLayout.setStretch(1, 3)
self.verticalLayout.setStretch(2, 4)
self.verticalLayout.setStretch(3, 1)
self.verticalLayout.setStretch(4, 4)
self.verticalLayout.setStretch(5, 1)
self.verticalLayout.setStretch(6, 2)
self.horizontalLayout_2.addLayout(self.verticalLayout)
spacerItem5 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.horizontalLayout_2.addItem(spacerItem5)
self.horizontalLayout_2.setStretch(0, 1)
self.horizontalLayout_2.setStretch(1, 2)
self.horizontalLayout_2.setStretch(2, 1)
self.horizontalLayout_3.addLayout(self.horizontalLayout_2)
self.retranslateUi(Frame)
QtCore.QMetaObject.connectSlotsByName(Frame)
def retranslateUi(self, Frame):
_translate = QtCore.QCoreApplication.translate
Frame.setWindowTitle(_translate("Frame", "Frame"))
self.l_remark.setText(_translate("Frame", "曹雨萱"))
self.l_nickname.setText(_translate("Frame", "昵称997"))
self.l_username.setText(_translate("Frame", "账号TextLabel"))
self.label.setText(_translate("Frame", "备注名"))
self.lineEdit.setText(_translate("Frame", "曹雨萱"))

View File

@ -1,250 +0,0 @@
# -*- coding: utf-8 -*-
"""
@File : mainview.py
@Author : Shuaikang Zhou
@Time : 2022/12/13 15:07
@IDE : Pycharm
@Version : Python3.10
@comment : 主窗口
"""
import json
import os.path
from PyQt5.QtCore import pyqtSignal, QUrl, Qt, QThread, QSize
from PyQt5.QtGui import QPixmap, QFont, QDesktopServices
from PyQt5.QtWidgets import QMainWindow, QLabel, QListWidgetItem, QMessageBox
from app import config
from app.DataBase import msg_db, misc_db, micro_msg_db, hard_link_db
from app.ui_pc.Icon import Icon
from . import mainwindow
from .chat import ChatWindow
from .contact import ContactWindow
from .tool.tool_window import ToolWindow
from ..DataBase.output_pc import Output
from ..person_pc import MePC
# 美化样式表
Stylesheet = """
/*去掉item虚线边框*/
QListWidget, QListView, QTreeWidget, QTreeView {
outline: 0px;
}
/*设置左侧选项的最小最大宽度,文字颜色和背景颜色*/
QListWidget {
min-width: 120px;
max-width: 120px;
color: black;
background: white;
border:none;
}
QListWidget::item{
height:60;
}
/*被选中时的背景颜色和左边框颜色*/
QListWidget::item:selected {
background: rgb(204, 204, 204);
border-left: 4px solid rgb(9, 187, 7);
color: black;
font-weight: bold;
}
/*鼠标悬停颜色*/
HistoryPanel::item:hover {
background: rgb(52, 52, 52);
}
"""
class MainWinController(QMainWindow, mainwindow.Ui_MainWindow):
exitSignal = pyqtSignal(bool)
okSignal = pyqtSignal(bool)
# username = ''
def __init__(self, username, parent=None):
super(MainWinController, self).__init__(parent)
self.outputThread0 = None
self.outputThread = None
self.setupUi(self)
self.setWindowIcon(Icon.MainWindow_Icon)
self.setStyleSheet(Stylesheet)
self.listWidget.clear()
self.resize(QSize(800, 600))
self.action_desc.triggered.connect(self.about)
self.load_flag = False
self.load_data()
self.load_num = 0
self.label = QLabel(self)
self.label.setGeometry((self.width() - 300) // 2, (self.height() - 100) // 2, 300, 100)
self.label.setPixmap(QPixmap(':/icons/icons/loading.svg'))
def load_data(self, flag=True):
if os.path.exists('./app/data/info.json'):
with open('./app/data/info.json', 'r', encoding='utf-8') as f:
dic = json.loads(f.read())
wxid = dic.get('wxid')
if wxid:
me = MePC()
me.wxid = dic.get('wxid')
me.name = dic.get('name')
me.mobile = dic.get('mobile')
me.wx_dir = dic.get('wx_dir')
self.set_my_info(wxid)
self.load_flag = True
else:
QMessageBox.information(
self,
'温馨提示',
'点击 工具->获取信息 重启后可以显示本人头像哦'
)
def init_ui(self):
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")))
self.action_help_chat.triggered.connect(
lambda: QDesktopServices.openUrl(QUrl("https://blog.lc044.love/post/5")))
self.action_help_decrypt.triggered.connect(
lambda: QDesktopServices.openUrl(QUrl("https://blog.lc044.love/post/4")))
self.listWidget.setVisible(False)
self.stackedWidget.setVisible(False)
self.listWidget.currentRowChanged.connect(self.setCurrentIndex)
tool_item = QListWidgetItem(Icon.Tool_Icon, '工具', self.listWidget)
chat_item = QListWidgetItem(Icon.Chat_Icon, '聊天', self.listWidget)
contact_item = QListWidgetItem(Icon.Contact_Icon, '好友', self.listWidget)
myinfo_item = QListWidgetItem(Icon.Home_Icon, '我的', self.listWidget)
tool_window = ToolWindow()
tool_window.get_info_signal.connect(self.set_my_info)
tool_window.decrypt_success_signal.connect(self.decrypt_success)
tool_window.load_finish_signal.connect(self.loading)
self.stackedWidget.addWidget(tool_window)
self.chat_window = ChatWindow()
# chat_window = QWidget()
self.stackedWidget.addWidget(self.chat_window)
self.contact_window = ContactWindow()
self.stackedWidget.addWidget(self.contact_window)
label = QLabel('该功能暂不支持哦')
label.setFont(QFont("微软雅黑", 50))
label.setAlignment(Qt.AlignCenter)
self.stackedWidget.addWidget(label)
tool_window.load_finish_signal.connect(self.loading)
self.statusbar.showMessage('聊天窗口上划到顶部会加载新的聊天记录\n一次不行那就多来几次')
self.contact_window.load_finish_signal.connect(self.loading)
self.chat_window.load_finish_signal.connect(self.loading)
def setCurrentIndex(self, row):
self.stackedWidget.setCurrentIndex(row)
if row == 2:
self.stackedWidget.currentWidget().show_contacts()
if row == 1:
self.stackedWidget.currentWidget().show_chats()
def setWindow(self, window):
try:
window.load_finish_signal.connect(self.loading)
except:
pass
self.stackedWidget.addWidget(window)
def set_my_info(self, wxid):
self.avatar = QPixmap()
try:
img_bytes = misc_db.get_avatar_buffer(wxid)
except AttributeError:
return
if not img_bytes:
return
if img_bytes[:4] == b'\x89PNG':
self.avatar.loadFromData(img_bytes, format='PNG')
else:
self.avatar.loadFromData(img_bytes, format='jfif')
self.avatar.scaled(60, 60)
me = MePC()
me.set_avatar(img_bytes)
self.myavatar.setScaledContents(True)
self.myavatar.setPixmap(self.avatar)
def stop_loading(self, a0):
self.label.setVisible(False)
def loading(self, a0):
self.load_num += 1
# self.label.setVisible(False)
print('加载一个了')
if self.load_num == 1:
print('ok了')
self.label.clear()
self.label.hide()
self.okSignal.emit(True)
self.listWidget.setVisible(True)
self.stackedWidget.setVisible(True)
if self.load_flag:
self.listWidget.setCurrentRow(1)
self.stackedWidget.setCurrentIndex(1)
else:
self.listWidget.setCurrentRow(0)
self.stackedWidget.setCurrentIndex(0)
def output(self):
if self.sender() == self.action_output_CSV:
self.outputThread = Output(None, type_=Output.CSV_ALL)
self.outputThread.okSignal.connect(
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):
QMessageBox.about(self, "提醒", msg)
def about(self):
"""
关于
"""
QMessageBox.about(self, "关于",
f'''版本:{config.version}<br>QQ交流群:{config.contact}<br>地址:<a href='https://github.com/LC044/WeChatMsg'>https://github.com/LC044/WeChatMsg</a><br>新特性:<br>{''.join(['' + i for i in config.description])}
'''
)
def decrypt_success(self):
QMessageBox.about(self, "解密成功", "请重新启动")
self.close()
def close(self) -> bool:
super().close()
misc_db.close()
msg_db.close()
micro_msg_db.close()
hard_link_db.close()
self.contact_window.close()
self.exitSignal.emit(True)
class LoadWindowThread(QThread):
okSignal = pyqtSignal(bool)
def __init__(self):
super().__init__()
self.num = 0
def loading(self):
self.num += 1
print('加载一个了')
if self.num == 2:
self.okSignal.emit(True)
def run(self):
self.chat_window = ChatWindow()
self.contact_window = ContactWindow()
self.contact_window.load_finish_signal.connect(self.loading)
self.chat_window.load_finish_signal.connect(self.loading)
print('加载完成')
self.okSignal.emit(True)

View File

@ -1,179 +0,0 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'mainwindow.ui'
#
# Created by: PyQt5 UI code generator 5.15.7
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
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"
" ")
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.horizontalLayout = QtWidgets.QHBoxLayout(self.centralwidget)
self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout.setSpacing(0)
self.horizontalLayout.setObjectName("horizontalLayout")
self.frame_info = QtWidgets.QFrame(self.centralwidget)
self.frame_info.setMinimumSize(QtCore.QSize(80, 500))
self.frame_info.setMaximumSize(QtCore.QSize(80, 16777215))
self.frame_info.setStyleSheet("background-color:rgb(240,240,240)")
self.frame_info.setFrameShape(QtWidgets.QFrame.NoFrame)
self.frame_info.setFrameShadow(QtWidgets.QFrame.Plain)
self.frame_info.setObjectName("frame_info")
self.myavatar = QtWidgets.QLabel(self.frame_info)
self.myavatar.setGeometry(QtCore.QRect(10, 40, 60, 60))
self.myavatar.setObjectName("myavatar")
self.listWidget = QtWidgets.QListWidget(self.frame_info)
self.listWidget.setGeometry(QtCore.QRect(0, 230, 120, 331))
self.listWidget.setMinimumSize(QtCore.QSize(120, 0))
self.listWidget.setMaximumSize(QtCore.QSize(120, 16777215))
self.listWidget.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.listWidget.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.listWidget.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.AdjustIgnored)
self.listWidget.setObjectName("listWidget")
item = QtWidgets.QListWidgetItem()
self.listWidget.addItem(item)
item = QtWidgets.QListWidgetItem()
self.listWidget.addItem(item)
item = QtWidgets.QListWidgetItem()
self.listWidget.addItem(item)
item = QtWidgets.QListWidgetItem()
self.listWidget.addItem(item)
item = QtWidgets.QListWidgetItem()
self.listWidget.addItem(item)
self.horizontalLayout.addWidget(self.frame_info)
self.stackedWidget = QtWidgets.QStackedWidget(self.centralwidget)
font = QtGui.QFont()
font.setFamily("微软雅黑")
font.setBold(False)
font.setWeight(50)
self.stackedWidget.setFont(font)
self.stackedWidget.setObjectName("stackedWidget")
self.horizontalLayout.addWidget(self.stackedWidget)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 1280, 23))
self.menubar.setObjectName("menubar")
self.menu_F = QtWidgets.QMenu(self.menubar)
self.menu_F.setObjectName("menu_F")
self.menu_data = QtWidgets.QMenu(self.menubar)
font = QtGui.QFont()
font.setFamily("微软雅黑")
self.menu_data.setFont(font)
self.menu_data.setObjectName("menu_data")
self.menu_output = QtWidgets.QMenu(self.menu_data)
self.menu_output.setObjectName("menu_output")
self.menu_2 = QtWidgets.QMenu(self.menubar)
self.menu_2.setObjectName("menu_2")
self.menu_about = QtWidgets.QMenu(self.menubar)
self.menu_about.setObjectName("menu_about")
self.menu_3 = QtWidgets.QMenu(self.menubar)
self.menu_3.setObjectName("menu_3")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.action_3 = QtWidgets.QAction(MainWindow)
self.action_3.setObjectName("action_3")
self.action_4 = QtWidgets.QAction(MainWindow)
self.action_4.setObjectName("action_4")
self.action_help_decrypt = QtWidgets.QAction(MainWindow)
font = QtGui.QFont()
font.setFamily("Microsoft YaHei UI")
self.action_help_decrypt.setFont(font)
self.action_help_decrypt.setObjectName("action_help_decrypt")
self.action_desc = QtWidgets.QAction(MainWindow)
self.action_desc.setObjectName("action_desc")
self.action_help_chat = QtWidgets.QAction(MainWindow)
self.action_help_chat.setObjectName("action_help_chat")
self.action_help_contact = QtWidgets.QAction(MainWindow)
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)
self.menu_about.addAction(self.action_desc)
self.menubar.addAction(self.menu_F.menuAction())
self.menubar.addAction(self.menu_data.menuAction())
self.menubar.addAction(self.menu_2.menuAction())
self.menubar.addAction(self.menu_about.menuAction())
self.menubar.addAction(self.menu_3.menuAction())
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.myavatar.setText(_translate("MainWindow", "avatar"))
__sortingEnabled = self.listWidget.isSortingEnabled()
self.listWidget.setSortingEnabled(False)
item = self.listWidget.item(0)
item.setText(_translate("MainWindow", "新建项目"))
item = self.listWidget.item(1)
item.setText(_translate("MainWindow", "新建项目"))
item = self.listWidget.item(2)
item.setText(_translate("MainWindow", "新建项目"))
item = self.listWidget.item(3)
item.setText(_translate("MainWindow", "新建项目"))
item = self.listWidget.item(4)
item.setText(_translate("MainWindow", "新建项目"))
self.listWidget.setSortingEnabled(__sortingEnabled)
self.menu_F.setTitle(_translate("MainWindow", "文件(F)"))
self.menu_data.setTitle(_translate("MainWindow", "数据"))
self.menu_output.setTitle(_translate("MainWindow", "导出聊天记录(全部)"))
self.menu_2.setTitle(_translate("MainWindow", "帮助"))
self.menu_about.setTitle(_translate("MainWindow", "关于"))
self.menu_3.setTitle(_translate("MainWindow", "不显示或者显示异常请重启应用、没反应那就多等一会儿"))
self.action_3.setText(_translate("MainWindow", "保存"))
self.action_4.setText(_translate("MainWindow", "退出"))
self.action_help_decrypt.setText(_translate("MainWindow", "解密教程"))
self.action_desc.setText(_translate("MainWindow", "说明"))
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 +0,0 @@

View File

@ -1,3 +0,0 @@
from .pc_decrypt import DecryptControl
__all__ = ['DecryptControl']

View File

@ -1,197 +0,0 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'decryptUi.ui'
#
# Created by: PyQt5 UI code generator 5.15.7
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_Dialog(object):
def setupUi(self, Dialog):
Dialog.setObjectName("Dialog")
Dialog.resize(611, 519)
font = QtGui.QFont()
font.setFamily("微软雅黑")
Dialog.setFont(font)
Dialog.setLayoutDirection(QtCore.Qt.LeftToRight)
self.verticalLayout_3 = QtWidgets.QVBoxLayout(Dialog)
self.verticalLayout_3.setObjectName("verticalLayout_3")
self.verticalLayout_2 = QtWidgets.QVBoxLayout()
self.verticalLayout_2.setObjectName("verticalLayout_2")
self.horizontalLayout_4 = QtWidgets.QHBoxLayout()
self.horizontalLayout_4.setObjectName("horizontalLayout_4")
spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.horizontalLayout_4.addItem(spacerItem)
self.btn_help = QtWidgets.QPushButton(Dialog)
self.btn_help.setMaximumSize(QtCore.QSize(200, 16777215))
self.btn_help.setObjectName("btn_help")
self.horizontalLayout_4.addWidget(self.btn_help)
spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.horizontalLayout_4.addItem(spacerItem1)
self.verticalLayout_2.addLayout(self.horizontalLayout_4)
spacerItem2 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
self.verticalLayout_2.addItem(spacerItem2)
self.horizontalLayout_3 = QtWidgets.QHBoxLayout()
self.horizontalLayout_3.setObjectName("horizontalLayout_3")
spacerItem3 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.horizontalLayout_3.addItem(spacerItem3)
self.verticalLayout = QtWidgets.QVBoxLayout()
self.verticalLayout.setObjectName("verticalLayout")
self.label_3 = QtWidgets.QLabel(Dialog)
font = QtGui.QFont()
font.setFamily("一纸情书")
font.setPointSize(20)
self.label_3.setFont(font)
self.label_3.setAlignment(QtCore.Qt.AlignCenter)
self.label_3.setObjectName("label_3")
self.verticalLayout.addWidget(self.label_3)
self.label_9 = QtWidgets.QLabel(Dialog)
self.label_9.setAlignment(QtCore.Qt.AlignCenter)
self.label_9.setObjectName("label_9")
self.verticalLayout.addWidget(self.label_9)
self.gridLayout_2 = QtWidgets.QGridLayout()
self.gridLayout_2.setObjectName("gridLayout_2")
self.gridLayout = QtWidgets.QGridLayout()
self.gridLayout.setObjectName("gridLayout")
self.label_phone = QtWidgets.QLabel(Dialog)
self.label_phone.setText("")
self.label_phone.setObjectName("label_phone")
self.gridLayout.addWidget(self.label_phone, 2, 1, 1, 1)
self.label_7 = QtWidgets.QLabel(Dialog)
self.label_7.setObjectName("label_7")
self.gridLayout.addWidget(self.label_7, 1, 0, 1, 1)
self.lineEdit = QtWidgets.QLineEdit(Dialog)
self.lineEdit.setStyleSheet("background:transparent;\n"
"\n"
" border-radius:5px;\n"
" border-top: 0px solid #b2e281;\n"
" border-bottom: 2px solid black;\n"
" border-right: 0px solid #b2e281;\n"
" border-left: 0px solid #b2e281;\n"
"\n"
"\n"
" border-style:outset\n"
" ")
self.lineEdit.setFrame(False)
self.lineEdit.setObjectName("lineEdit")
self.gridLayout.addWidget(self.lineEdit, 4, 1, 1, 1)
self.label_5 = QtWidgets.QLabel(Dialog)
self.label_5.setObjectName("label_5")
self.gridLayout.addWidget(self.label_5, 3, 0, 1, 1)
self.label_6 = QtWidgets.QLabel(Dialog)
self.label_6.setObjectName("label_6")
self.gridLayout.addWidget(self.label_6, 5, 0, 1, 1)
self.label_key = QtWidgets.QLabel(Dialog)
self.label_key.setMaximumSize(QtCore.QSize(400, 16777215))
self.label_key.setText("")
self.label_key.setObjectName("label_key")
self.gridLayout.addWidget(self.label_key, 5, 1, 1, 1)
self.label = QtWidgets.QLabel(Dialog)
self.label.setObjectName("label")
self.gridLayout.addWidget(self.label, 0, 0, 1, 1)
self.label_2 = QtWidgets.QLabel(Dialog)
self.label_2.setObjectName("label_2")
self.gridLayout.addWidget(self.label_2, 2, 0, 1, 1)
self.label_pid = QtWidgets.QLabel(Dialog)
self.label_pid.setText("")
self.label_pid.setObjectName("label_pid")
self.gridLayout.addWidget(self.label_pid, 0, 1, 1, 1)
self.label_name = QtWidgets.QLabel(Dialog)
self.label_name.setText("")
self.label_name.setObjectName("label_name")
self.gridLayout.addWidget(self.label_name, 3, 1, 1, 1)
self.label_4 = QtWidgets.QLabel(Dialog)
self.label_4.setObjectName("label_4")
self.gridLayout.addWidget(self.label_4, 4, 0, 1, 1)
self.label_version = QtWidgets.QLabel(Dialog)
self.label_version.setText("")
self.label_version.setObjectName("label_version")
self.gridLayout.addWidget(self.label_version, 1, 1, 1, 1)
self.label_8 = QtWidgets.QLabel(Dialog)
self.label_8.setObjectName("label_8")
self.gridLayout.addWidget(self.label_8, 6, 0, 1, 1)
self.label_db_dir = QtWidgets.QLabel(Dialog)
self.label_db_dir.setMaximumSize(QtCore.QSize(400, 300))
self.label_db_dir.setText("")
self.label_db_dir.setObjectName("label_db_dir")
self.gridLayout.addWidget(self.label_db_dir, 6, 1, 1, 1)
self.gridLayout.setColumnMinimumWidth(0, 1)
self.gridLayout.setColumnStretch(0, 1)
self.gridLayout.setColumnStretch(1, 10)
self.gridLayout_2.addLayout(self.gridLayout, 0, 0, 2, 1)
self.btn_getinfo = QtWidgets.QPushButton(Dialog)
self.btn_getinfo.setMinimumSize(QtCore.QSize(0, 60))
self.btn_getinfo.setObjectName("btn_getinfo")
self.gridLayout_2.addWidget(self.btn_getinfo, 0, 1, 1, 1)
self.checkBox = QtWidgets.QCheckBox(Dialog)
self.checkBox.setText("")
self.checkBox.setObjectName("checkBox")
self.gridLayout_2.addWidget(self.checkBox, 0, 2, 1, 1)
self.btn_db_dir = QtWidgets.QPushButton(Dialog)
self.btn_db_dir.setMinimumSize(QtCore.QSize(0, 60))
self.btn_db_dir.setObjectName("btn_db_dir")
self.gridLayout_2.addWidget(self.btn_db_dir, 1, 1, 1, 1)
self.checkBox_2 = QtWidgets.QCheckBox(Dialog)
self.checkBox_2.setText("")
self.checkBox_2.setObjectName("checkBox_2")
self.gridLayout_2.addWidget(self.checkBox_2, 1, 2, 1, 1)
self.verticalLayout.addLayout(self.gridLayout_2)
self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
spacerItem4 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.horizontalLayout_2.addItem(spacerItem4)
self.pushButton_3 = QtWidgets.QPushButton(Dialog)
self.pushButton_3.setMinimumSize(QtCore.QSize(0, 60))
self.pushButton_3.setMaximumSize(QtCore.QSize(100, 16777215))
self.pushButton_3.setObjectName("pushButton_3")
self.horizontalLayout_2.addWidget(self.pushButton_3)
self.label_tip = QtWidgets.QLabel(Dialog)
self.label_tip.setObjectName("label_tip")
self.horizontalLayout_2.addWidget(self.label_tip)
spacerItem5 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.horizontalLayout_2.addItem(spacerItem5)
self.verticalLayout.addLayout(self.horizontalLayout_2)
self.horizontalLayout = QtWidgets.QHBoxLayout()
self.horizontalLayout.setObjectName("horizontalLayout")
self.label_ready = QtWidgets.QLabel(Dialog)
self.label_ready.setObjectName("label_ready")
self.horizontalLayout.addWidget(self.label_ready)
self.progressBar = QtWidgets.QProgressBar(Dialog)
self.progressBar.setProperty("value", 50)
self.progressBar.setObjectName("progressBar")
self.horizontalLayout.addWidget(self.progressBar)
self.verticalLayout.addLayout(self.horizontalLayout)
self.horizontalLayout_3.addLayout(self.verticalLayout)
spacerItem6 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.horizontalLayout_3.addItem(spacerItem6)
self.verticalLayout_2.addLayout(self.horizontalLayout_3)
spacerItem7 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
self.verticalLayout_2.addItem(spacerItem7)
self.verticalLayout_3.addLayout(self.verticalLayout_2)
self.retranslateUi(Dialog)
QtCore.QMetaObject.connectSlotsByName(Dialog)
def retranslateUi(self, Dialog):
_translate = QtCore.QCoreApplication.translate
Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
self.btn_help.setText(_translate("Dialog", "使用说明"))
self.label_3.setText(_translate("Dialog", "解密数据库"))
self.label_9.setText(_translate("Dialog", "以下内容为自动获取,如获取失败请手动填写"))
self.label_7.setText(_translate("Dialog", "版本"))
self.label_5.setText(_translate("Dialog", "微信昵称"))
self.label_6.setText(_translate("Dialog", "密钥"))
self.label.setText(_translate("Dialog", "PID"))
self.label_2.setText(_translate("Dialog", "手机号"))
self.label_4.setText(_translate("Dialog", "wxid"))
self.label_8.setText(_translate("Dialog", "微信路径"))
self.btn_getinfo.setText(_translate("Dialog", "获取信息"))
self.btn_db_dir.setText(_translate("Dialog", "设置微信路径"))
self.pushButton_3.setText(_translate("Dialog", "开始启动"))
self.label_tip.setText(_translate("Dialog", "TextLabel"))
self.label_ready.setText(_translate("Dialog", "未就绪"))

View File

@ -1,259 +0,0 @@
import json
import os.path
import time
import traceback
from PyQt5.QtCore import pyqtSignal, QThread, QUrl, QFile, QIODevice, QTextStream
from PyQt5.QtGui import QDesktopServices
from PyQt5.QtWidgets import QWidget, QMessageBox, QFileDialog
from app.DataBase import msg_db, misc_db
from app.DataBase.merge import merge_databases, merge_MediaMSG_databases
from app.decrypt import get_wx_info, decrypt
from app.log import logger
from app.util import path
from . import decryptUi
class DecryptControl(QWidget, decryptUi.Ui_Dialog):
DecryptSignal = pyqtSignal(bool)
get_wxidSignal = pyqtSignal(str)
def __init__(self, parent=None):
super(DecryptControl, self).__init__(parent)
self.setupUi(self)
self.pushButton_3.clicked.connect(self.decrypt)
self.btn_getinfo.clicked.connect(self.get_info)
self.btn_db_dir.clicked.connect(self.select_db_dir)
self.lineEdit.returnPressed.connect(self.set_wxid)
self.lineEdit.textChanged.connect(self.set_wxid_)
self.btn_help.clicked.connect(self.show_help)
self.label_tip.setVisible(False)
self.info = {}
self.lineEdit.setFocus()
self.ready = False
self.wx_dir = None
def show_help(self):
# 定义网页链接
url = QUrl("https://blog.lc044.love/post/4")
# 使用QDesktopServices打开网页
QDesktopServices.openUrl(url)
# @log
def get_info(self):
try:
file = QFile(':/data/version_list.json')
if file.open(QIODevice.ReadOnly | QIODevice.Text):
stream = QTextStream(file)
content = stream.readAll()
file.close()
VERSION_LIST = json.loads(content)
else:
return
result = get_wx_info.get_info(VERSION_LIST)
print(result)
if result == -1:
QMessageBox.critical(self, "错误", "请登录微信")
elif result == -2:
QMessageBox.critical(self, "错误", "微信版本不匹配\n请更新微信版本为:3.9.8.15")
elif result == -3:
QMessageBox.critical(self, "错误", "WeChat WeChatWin.dll Not Found")
else:
self.ready = True
self.info = result[0]
self.label_key.setText(self.info['key'])
self.lineEdit.setText(self.info['wxid'])
self.label_name.setText(self.info['name'])
self.label_phone.setText(self.info['mobile'])
self.label_pid.setText(str(self.info['pid']))
self.label_version.setText(self.info['version'])
self.lineEdit.setFocus()
self.checkBox.setChecked(True)
self.get_wxidSignal.emit(self.info['wxid'])
directory = os.path.join(path.wx_path(), self.info['wxid'])
if os.path.exists(directory):
self.label_db_dir.setText(directory)
self.wx_dir = directory
self.checkBox_2.setChecked(True)
self.ready = True
if self.ready:
self.label_ready.setText('已就绪')
if self.wx_dir and os.path.exists(os.path.join(self.wx_dir)):
self.label_ready.setText('已就绪')
except Exception as e:
QMessageBox.critical(self, "未知错误", "请收集报错信息发起issue解决问题")
logger.error(traceback.format_exc())
def set_wxid_(self):
self.info['wxid'] = self.lineEdit.text()
def set_wxid(self):
self.info['wxid'] = self.lineEdit.text()
QMessageBox.information(self, "ok", f"wxid修改成功{self.info['wxid']}")
def select_db_dir(self):
directory = QFileDialog.getExistingDirectory(
self, "选取微信文件保存目录——能看到Msg文件夹",
path.wx_path()
) # 起始路径
db_dir = os.path.join(directory, 'Msg')
if not os.path.exists(db_dir):
QMessageBox.critical(self, "错误", "文件夹选择错误\n一般以wxid_xxx结尾")
return
self.label_db_dir.setText(directory)
self.wx_dir = directory
self.checkBox_2.setChecked(True)
if self.ready:
self.label_ready.setText('已就绪')
def decrypt(self):
if not self.ready:
QMessageBox.critical(self, "错误", "请先获取密钥")
return
if not self.wx_dir:
QMessageBox.critical(self, "错误", "请先选择微信安装路径")
return
if self.lineEdit.text() == 'None':
QMessageBox.critical(self, "错误", "请填入wxid")
return
db_dir = os.path.join(self.wx_dir, 'Msg')
if self.ready:
if not os.path.exists(db_dir):
QMessageBox.critical(self, "错误", "文件夹选择错误\n一般以wxid_xxx结尾")
return
if self.info.get('key') == 'none':
QMessageBox.critical(self, "错误", "密钥错误\n请检查微信版本是否为最新和微信路径是否正确")
self.label_tip.setVisible(True)
self.label_tip.setText('点我之后没有反应那就多等儿吧,不要再点了')
self.thread2 = DecryptThread(db_dir, self.info['key'])
self.thread2.maxNumSignal.connect(self.setProgressBarMaxNum)
self.thread2.signal.connect(self.progressBar_view)
self.thread2.okSignal.connect(self.btnExitClicked)
self.thread2.errorSignal.connect(
lambda x: QMessageBox.critical(self, "错误", "密钥错误\n请检查微信版本是否为最新和微信路径是否正确")
)
self.thread2.start()
def btnEnterClicked(self):
# print("enter clicked")
# 中间可以添加处理逻辑
# QMessageBox.about(self, "解密成功", "数据库文件存储在app/DataBase/Msg文件夹下")
self.DecryptSignal.emit(True)
# self.close()
def setProgressBarMaxNum(self, max_val):
self.progressBar.setRange(0, max_val)
def progressBar_view(self, value):
"""
进度条显示
:param value: 进度0-100
:return: None
"""
self.progressBar.setProperty('value', value)
# self.btnExitClicked()
# data.init_database()
def btnExitClicked(self):
# print("Exit clicked")
dic = {
'wxid': self.info['wxid'],
'wx_dir': self.wx_dir,
'name': self.info['name'],
'mobile': self.info['mobile']
}
try:
os.makedirs('./app/data', exist_ok=True)
with open('./app/data/info.json', 'w', encoding='utf-8') as f:
f.write(json.dumps(dic))
except:
with open('./info.json', 'w', encoding='utf-8') as f:
f.write(json.dumps(dic))
# 目标数据库文件
target_database = "app/DataBase/Msg/MSG.db"
# 源数据库文件列表
source_databases = [f"app/DataBase/Msg/MSG{i}.db" for i in range(1, 20)]
import shutil
shutil.copy("app/DataBase/Msg/MSG0.db", target_database) # 使用一个数据库文件作为模板
# 合并数据库
try:
merge_databases(source_databases, target_database)
except FileNotFoundError:
QMessageBox.critical(self, "错误", "数据库不存在\n请检查微信版本是否为最新")
# 音频数据库文件
target_database = "app/DataBase/Msg/MediaMSG.db"
# 源数据库文件列表
source_databases = [f"app/DataBase/Msg/MediaMSG{i}.db" for i in range(1, 20)]
import shutil
shutil.copy("app/DataBase/Msg/MediaMSG0.db", target_database) # 使用一个数据库文件作为模板
# 合并数据库
try:
merge_MediaMSG_databases(source_databases, target_database)
except FileNotFoundError:
QMessageBox.critical(self, "错误", "数据库不存在\n请检查微信版本是否为最新")
self.DecryptSignal.emit(True)
self.close()
class DecryptThread(QThread):
signal = pyqtSignal(str)
maxNumSignal = pyqtSignal(int)
okSignal = pyqtSignal(str)
errorSignal = pyqtSignal(bool)
def __init__(self, db_path, key):
super(DecryptThread, self).__init__()
self.db_path = db_path
self.key = key
self.textBrowser = None
def __del__(self):
pass
def run(self):
misc_db.close()
msg_db.close()
# micro_msg_db.close()
# hard_link_db.close()
output_dir = 'app/DataBase/Msg'
os.makedirs(output_dir, exist_ok=True)
tasks = []
if os.path.exists(self.db_path):
for root, dirs, files in os.walk(self.db_path):
for file in files:
if '.db' == file[-3:]:
if 'xInfo.db' == file:
continue
inpath = os.path.join(root, file)
# print(inpath)
output_path = os.path.join(output_dir, file)
tasks.append([self.key, inpath, output_path])
self.maxNumSignal.emit(len(tasks))
for i, task in enumerate(tasks):
if decrypt.decrypt(*task) == -1:
self.errorSignal.emit(True)
self.signal.emit(str(i))
# print(self.db_path)
self.okSignal.emit('ok')
# self.signal.emit('100')
class MyThread(QThread):
signal = pyqtSignal(str)
def __init__(self):
super(MyThread, self).__init__()
def __del__(self):
pass
def run(self):
for i in range(100):
self.signal.emit(str(i))
time.sleep(0.1)

View File

@ -1,83 +0,0 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'toolUI.ui'
#
# Created by: PyQt5 UI code generator 5.15.7
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_Dialog(object):
def setupUi(self, Dialog):
Dialog.setObjectName("Dialog")
Dialog.resize(590, 547)
font = QtGui.QFont()
font.setFamily("微软雅黑")
Dialog.setFont(font)
self.verticalLayout = QtWidgets.QVBoxLayout(Dialog)
self.verticalLayout.setObjectName("verticalLayout")
self.horizontalLayout = QtWidgets.QHBoxLayout()
self.horizontalLayout.setSizeConstraint(QtWidgets.QLayout.SetDefaultConstraint)
self.horizontalLayout.setSpacing(0)
self.horizontalLayout.setObjectName("horizontalLayout")
self.label = QtWidgets.QLabel(Dialog)
self.label.setMaximumSize(QtCore.QSize(80, 80))
self.label.setText("")
self.label.setObjectName("label")
self.horizontalLayout.addWidget(self.label)
self.listWidget = QtWidgets.QListWidget(Dialog)
self.listWidget.setMinimumSize(QtCore.QSize(100, 80))
self.listWidget.setMaximumSize(QtCore.QSize(500, 80))
self.listWidget.setFrameShape(QtWidgets.QFrame.NoFrame)
self.listWidget.setFrameShadow(QtWidgets.QFrame.Plain)
self.listWidget.setLineWidth(0)
self.listWidget.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.listWidget.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.listWidget.setFlow(QtWidgets.QListView.LeftToRight)
self.listWidget.setObjectName("listWidget")
item = QtWidgets.QListWidgetItem()
self.listWidget.addItem(item)
item = QtWidgets.QListWidgetItem()
self.listWidget.addItem(item)
item = QtWidgets.QListWidgetItem()
self.listWidget.addItem(item)
item = QtWidgets.QListWidgetItem()
self.listWidget.addItem(item)
item = QtWidgets.QListWidgetItem()
self.listWidget.addItem(item)
self.horizontalLayout.addWidget(self.listWidget)
self.label_2 = QtWidgets.QLabel(Dialog)
self.label_2.setMaximumSize(QtCore.QSize(80, 80))
self.label_2.setText("")
self.label_2.setObjectName("label_2")
self.horizontalLayout.addWidget(self.label_2)
self.verticalLayout.addLayout(self.horizontalLayout)
self.stackedWidget = QtWidgets.QStackedWidget(Dialog)
self.stackedWidget.setObjectName("stackedWidget")
self.verticalLayout.addWidget(self.stackedWidget)
self.verticalLayout.setStretch(1, 1)
self.retranslateUi(Dialog)
self.stackedWidget.setCurrentIndex(-1)
QtCore.QMetaObject.connectSlotsByName(Dialog)
def retranslateUi(self, Dialog):
_translate = QtCore.QCoreApplication.translate
Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
__sortingEnabled = self.listWidget.isSortingEnabled()
self.listWidget.setSortingEnabled(False)
item = self.listWidget.item(0)
item.setText(_translate("Dialog", "新建项目"))
item = self.listWidget.item(1)
item.setText(_translate("Dialog", "新建项目"))
item = self.listWidget.item(2)
item.setText(_translate("Dialog", "新建项目"))
item = self.listWidget.item(3)
item.setText(_translate("Dialog", "新建项目"))
item = self.listWidget.item(4)
item.setText(_translate("Dialog", "新建项目"))
self.listWidget.setSortingEnabled(__sortingEnabled)

View File

@ -1,89 +0,0 @@
from PyQt5.QtCore import Qt, pyqtSignal
from PyQt5.QtGui import QFont
from PyQt5.QtWidgets import QWidget, QListWidgetItem, QLabel
from app.ui_pc.Icon import Icon
from .pc_decrypt import DecryptControl
from .toolUI import Ui_Dialog
# 美化样式表
Stylesheet = """
QPushButton{
background-color: #ffffff;
}
QPushButton:hover {
background-color: lightgray;
}
/*去掉item虚线边框*/
QListWidget, QListView, QTreeWidget, QTreeView {
outline: 0px;
border:none;
background-color:rgb(240,240,240)
}
/*设置左侧选项的最小最大宽度,文字颜色和背景颜色*/
QListWidget {
min-width: 400px;
max-width: 400px;
min-height: 80px;
max-height: 80px;
color: black;
border:none;
}
QListWidget::item{
height:80px;
width:80px;
}
/*被选中时的背景颜色和左边框颜色*/
QListWidget::item:selected {
background: rgb(204, 204, 204);
border-bottom: 4px solid rgb(9, 187, 7);
border-left:none;
color: black;
font-weight: bold;
}
/*鼠标悬停颜色*/
HistoryPanel::item:hover {
background: rgb(52, 52, 52);
}
"""
class ToolWindow(QWidget, Ui_Dialog):
get_info_signal = pyqtSignal(str)
decrypt_success_signal = pyqtSignal(bool)
load_finish_signal = pyqtSignal(bool)
def __init__(self, parent=None):
super().__init__(parent)
self.setupUi(self)
self.setStyleSheet(Stylesheet)
self.init_ui()
self.load_finish_signal.emit(True)
def init_ui(self):
self.listWidget.clear()
self.listWidget.currentRowChanged.connect(self.setCurrentIndex)
chat_item = QListWidgetItem(Icon.Chat_Icon, '解密', self.listWidget)
contact_item = QListWidgetItem(Icon.Contact_Icon, '别点', self.listWidget)
myinfo_item = QListWidgetItem(Icon.MyInfo_Icon, '别点', self.listWidget)
tool_item = QListWidgetItem(Icon.MyInfo_Icon, '别点', self.listWidget)
decrypt_window = DecryptControl()
decrypt_window.get_wxidSignal.connect(self.get_info_signal)
decrypt_window.DecryptSignal.connect(self.decrypt_success_signal)
self.stackedWidget.addWidget(decrypt_window)
label = QLabel('都说了不让你点', self)
label.setFont(QFont("微软雅黑", 50))
label.setAlignment(Qt.AlignCenter)
# 设置label的背景颜色(这里随机)
# 这里加了一个margin边距(方便区分QStackedWidget和QLabel的颜色)
# label.setStyleSheet('background: rgb(%d, %d, %d);margin: 50px;' % (
# randint(0, 255), randint(0, 255), randint(0, 255)))
self.stackedWidget.addWidget(label)
self.stackedWidget.addWidget(label)
self.stackedWidget.addWidget(label)
self.listWidget.setCurrentRow(0)
self.stackedWidget.setCurrentIndex(0)
def setCurrentIndex(self, row):
print(row)
self.stackedWidget.setCurrentIndex(row)

View File

@ -1,41 +0,0 @@
import ctypes
import sys
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import QApplication, QMessageBox, QWidget
from app.resources import resource_rc
from app.ui_pc.tool.pc_decrypt import pc_decrypt
var = resource_rc.qt_resource_name
ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID("WeChatReport")
class ViewController(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle('解密')
self.setWindowIcon(QIcon(':/icons/icons/logo.svg'))
self.viewMainWIn = None
self.viewDecrypt = None
def loadPCDecryptView(self):
"""
登录界面
:return:
"""
self.viewDecrypt = pc_decrypt.DecryptControl(self)
self.viewDecrypt.DecryptSignal.connect(self.show_success)
# self.viewDecrypt.show()
def show_success(self):
QMessageBox.about(self, "解密成功", "数据库文件存储在\napp/DataBase/Msg\n文件夹下")
self.close()
if __name__ == '__main__':
app = QApplication(sys.argv)
view = ViewController()
view.loadPCDecryptView()
view.show()
sys.exit(app.exec_())

View File

@ -56,7 +56,7 @@ pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
1. 运行程序
```shell
python main_pc.py
python main.py
```
2. 选择联系人

65
main.py
View File

@ -1,40 +1,31 @@
import ctypes
import sys
import time
import traceback
from PyQt5.QtGui import QFont
from PyQt5.QtWidgets import *
import app.DataBase.data as DB
from app.Ui import decrypt, mainview
from app.log import logger
from app.ui import mainview
from app.ui.tool.pc_decrypt import pc_decrypt
from app.config import version
ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID("WeChatReport")
class ViewController:
class ViewController(QWidget):
def __init__(self):
self.viewMainWIn = None
super().__init__()
self.viewMainWindow = None
self.viewDecrypt = None
def loadDecryptView(self):
"""
登录界面
:return:
"""
if DB.is_db_exist():
self.loadMainWinView()
else:
self.viewDecrypt = decrypt.DecryptControl() # 需要将view login设为成员变量
self.viewDecrypt.DecryptSignal.connect(self.loadMainWinView)
self.viewDecrypt.show()
self.viewDecrypt.db_exist()
def loadPCDecryptView(self):
"""
登录界面
:return:
"""
self.viewDecrypt = pc_decrypt.DecryptControl()
self.viewDecrypt.DecryptSignal.connect(self.loadMainWinView)
self.viewDecrypt.DecryptSignal.connect(self.show_success)
self.viewDecrypt.show()
def loadMainWinView(self, username=None):
@ -45,21 +36,31 @@ class ViewController:
"""
username = ''
start = time.time()
self.viewMainWIn = mainview.MainWinController(username=username)
self.viewMainWIn.setWindowTitle("Chat")
# print(username)
self.viewMainWIn.username = username
# self.viewMainWIn.exitSignal.connect(self.loadDecryptView) # 不需要回到登录界面可以省略
self.viewMainWIn.show()
end = time.time()
print('ok', end - start)
# self.viewMainWIn.signUp()
self.viewMainWindow = mainview.MainWinController(username=username)
self.viewMainWindow.exitSignal.connect(self.close)
try:
self.viewMainWindow.setWindowTitle(f"留痕-{version}")
self.viewMainWindow.show()
end = time.time()
print('ok', '本次加载用了', end - start, 's')
self.viewMainWindow.init_ui()
except Exception as e:
print(f"Exception: {e}")
logger.error(traceback.print_exc())
def show_success(self):
QMessageBox.about(self, "解密成功", "数据库文件存储在\napp/DataBase/Msg\n文件夹下")
if __name__ == '__main__':
app = QApplication(sys.argv)
view = ViewController()
# view.loadPCDecryptView()
view.loadDecryptView() # 进入登录界面如果view login不是成员变量则离开作用域后失效。
# view.loadMainWinView('102')
sys.exit(app.exec_())
try:
# view.loadPCDecryptView()
view.loadMainWinView()
# view.show()
# view.show_success()
sys.exit(app.exec_())
except Exception as e:
print(f"Exception: {e}")
logger.error(traceback.print_exc())

View File

@ -1,66 +0,0 @@
import ctypes
import sys
import time
import traceback
from PyQt5.QtGui import QFont
from PyQt5.QtWidgets import *
from app.log import logger
from app.ui_pc import mainview
from app.ui_pc.tool.pc_decrypt import pc_decrypt
from app.config import version
ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID("WeChatReport")
class ViewController(QWidget):
def __init__(self):
super().__init__()
self.viewMainWindow = None
self.viewDecrypt = None
def loadPCDecryptView(self):
"""
登录界面
:return:
"""
self.viewDecrypt = pc_decrypt.DecryptControl()
self.viewDecrypt.DecryptSignal.connect(self.show_success)
self.viewDecrypt.show()
def loadMainWinView(self, username=None):
"""
聊天界面
:param username: 账号
:return:
"""
username = ''
start = time.time()
self.viewMainWindow = mainview.MainWinController(username=username)
self.viewMainWindow.exitSignal.connect(self.close)
try:
self.viewMainWindow.setWindowTitle(f"留痕-{version}")
self.viewMainWindow.show()
end = time.time()
print('ok', '本次加载用了', end - start, 's')
self.viewMainWindow.init_ui()
except Exception as e:
print(f"Exception: {e}")
logger.error(traceback.print_exc())
def show_success(self):
QMessageBox.about(self, "解密成功", "数据库文件存储在\napp/DataBase/Msg\n文件夹下")
if __name__ == '__main__':
app = QApplication(sys.argv)
view = ViewController()
try:
# view.loadPCDecryptView()
view.loadMainWinView()
# view.show()
# view.show_success()
sys.exit(app.exec_())
except Exception as e:
print(f"Exception: {e}")
logger.error(traceback.print_exc())

View File

@ -97,7 +97,7 @@
# Python>=3.10
git clone https://github.com/LC044/WeChatMsg
cd WeChatMsg
pip install -r requirements_pc.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
```
### 2. 使用
@ -113,7 +113,7 @@ pip install -r requirements_pc.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
2. 运行程序
```shell
python main_pc.py
python main.py
```
3. 点击获取信息
@ -188,13 +188,6 @@ python main_pc.py
![](./doc/images/login_wx.png)
如果您遇到下图所示的问题,需要先运行`decrypt_window`的可执行文件或者源代码文件
```
python decrypt_window.py
```
![](./doc/images/decrypt_wx.png)
如果您在运行可执行程序的时候出现闪退的现象,请右击软件使用管理员权限运行。
@ -205,7 +198,7 @@ python decrypt_window.py
![](./doc/images/with_wxid_name.png)
如果出现如图所示的报错信息,将`app/database/msg`文件夹删除,重新运行`main_pc.py`。
如果出现如图所示的报错信息,将`app/database/msg`文件夹删除,重新运行`main.py`。
![](./doc/images/err_log.png)
@ -221,59 +214,6 @@ python decrypt_window.py
</details>
## 使用模拟器(支持可视化分析)
<details>
**不推荐使用PC端微信可视化功能马上实现**
1. 根据[教程](https://blog.csdn.net/m0_59452630/article/details/124222235?spm=1001.2014.3001.5501)获得两个文件
- auth_info_key_prefs.xml——解析数据库密码
- EnMicroMsg.db——聊天数据库
- **上面这两个文件就可以**
2. 安装依赖库
python版本>=3.10
**说明:用到了python3.10的match语法不方便更换python版本的小伙伴可以把match(运行报错的地方)更改为if else**
命令行运行以下代码(**建议使用Pycharm打开项目Pycharm会自动配置好所有东西直接运行main.py即可**
```bash
pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
```
运行main.py
```bash
python main.py
```
3. 出现解密界面
![image-20230521001305274](doc/images/image-20230521001305274.png)
按照提示选择上面获得的两个文件,等待解密完成,重新运行程序
4. 进入主界面
这时候不显示头像,因为头像文件没有导入进来
![image-20230521001547481](doc/images/image-20230521001547481.png)
根据[教程](https://blog.csdn.net/m0_59452630/article/details/124222235?spm=1001.2014.3001.5501)
将头像文件夹avatar复制到工程目录./app/data/目录下
![image-20230521001726799](doc/images/image-20230521001726799.png)
如果想要显示聊天图像就把[教程](https://blog.csdn.net/m0_59452630/article/details/124222235?spm=1001.2014.3001.5501)
里的image2文件夹复制到./app/data文件夹里效果跟上图一样
复制进来之后再运行程序就有图像了
![image-20230520235113261](doc/images/image-20230520235113261.png)
</details>
# 🏆致谢

Binary file not shown.

View File

@ -1,10 +0,0 @@
PyQt5
psutil
pycryptodomex
pywin32
pymem
silk-python
pyaudio
fuzzywuzzy
python-Levenshtein
lz4

View File

@ -1,19 +0,0 @@
PyQt5
psutil
pycryptodomex
pywin32
pymem
silk-python
pyaudio
fuzzywuzzy
python-Levenshtein
Pillow==10.1.0
requests
flask==3.0.0
pyecharts==2.0.1
jieba==0.42.1
google==3.0.0
protobuf==4.25.1
soupsieve==2.5
lz4==4.3.2
pilk==0.2.4

View File

@ -1,5 +0,0 @@
PRAGMA key = '10f35f1';
PRAGMA cipher_migrate;
ATTACH DATABASE 'plaintext.db' AS plaintext KEY '';
SELECT sqlcipher_export('plaintext');
DETACH DATABASE plaintext;

View File

@ -1,3 +0,0 @@
1.将要加密的数据名称改为encrypt.db并放到当前bin目录下
2.编辑adb.txt 文件 PRAGMA key = 'password';这里的password是加密数据的密码
3.修改保存完双击sqlcipher.bat文件

View File

@ -1,3 +0,0 @@
sqlcipher-shell32.exe encrypt.db < adb.txt
echo 解密完成
pause

View File

@ -1,3 +0,0 @@
sqlcipher-shell32.exe encrypt.db < adb.txt
echo 解密完成
pause