From 4bf1729d208cfd421de75732e497f6599e9abfcb Mon Sep 17 00:00:00 2001 From: shuaikangzhou <863909694@qq.com> Date: Sun, 10 Dec 2023 18:55:17 +0800 Subject: [PATCH] =?UTF-8?q?=E7=94=A8=E6=88=B7=E5=8F=AF=E8=87=AA=E5=AE=9A?= =?UTF-8?q?=E4=B9=89=E9=80=89=E6=8B=A9=E5=AF=BC=E5=87=BAHTML=E7=9A=84?= =?UTF-8?q?=E6=B6=88=E6=81=AF=E7=B1=BB=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/DataBase/output_pc.py | 505 +++++++++++++++-------------- app/main/__init__.py | 9 - app/ui_pc/contact/contactInfo.py | 25 +- app/ui_pc/contact/export_dialog.py | 92 ++++++ readme.md | 4 +- 5 files changed, 377 insertions(+), 258 deletions(-) delete mode 100644 app/main/__init__.py create mode 100644 app/ui_pc/contact/export_dialog.py diff --git a/app/DataBase/output_pc.py b/app/DataBase/output_pc.py index 1ca25f4..20a6370 100644 --- a/app/DataBase/output_pc.py +++ b/app/DataBase/output_pc.py @@ -1,7 +1,7 @@ import csv import html import os - +from re import findall from PyQt5.QtCore import pyqtSignal, QThread from PyQt5.QtWidgets import QFileDialog @@ -58,10 +58,11 @@ class Output(QThread): CSV_ALL = 3 CONTACT_CSV = 4 - def __init__(self, contact, parent=None, type_=DOCX): + def __init__(self, contact, type_=DOCX, message_types={}, parent=None): super().__init__(parent) self.Child0 = None self.last_timestamp = 0 + self.message_types = message_types self.sec = 2 # 默认1000秒 self.contact = contact self.ta_username = contact.wxid if contact else '' @@ -122,7 +123,7 @@ class Output(QThread): elif self.output_type == self.CONTACT_CSV: self.contact_to_csv() else: - self.Child = ChildThread(self.contact, type_=self.output_type) + self.Child = ChildThread(self.contact, type_=self.output_type,message_types=self.message_types) self.Child.progressSignal.connect(self.progress) self.Child.rangeSignal.connect(self.rangeSignal) self.Child.okSignal.connect(self.okSignal) @@ -144,27 +145,85 @@ class ChildThread(QThread): DOCX = 1 HTML = 2 - def __init__(self, contact, parent=None, type_=DOCX): + def __init__(self, contact, type_=DOCX, message_types={}, parent=None): super().__init__(parent) self.contact = contact + self.message_types = message_types self.last_timestamp = 0 self.sec = 2 # 默认1000秒 self.msg_id = 0 self.output_type = type_ + def is_5_min(self, timestamp): if abs(timestamp - self.last_timestamp) > 300: self.last_timestamp = timestamp return True return False - def text(self, doc, isSend, message, status): + def text(self, doc, message): + type_ = message[2] + str_content = message[7] + str_time = message[8] + is_send = message[4] + avatar = 'myhead.png' if is_send else 'tahead.png' + timestamp = message[5] + str_content = escape_js_and_html(str_content) + if self.is_5_min(timestamp): + doc.write( + f'''{{ type:0, text: '{str_time}',is_send:0,avatar_path:''}},''' + ) + emojiText = findall(r"(\[.+?\])", str_content) + for emoji_text in emojiText: + if emoji_text in emoji: + str_content = str_content.replace(emoji_text, emoji[emoji_text]) + doc.write( + f'''{{ type:{type_}, text: '{str_content}',is_send:{is_send},avatar_path:'{avatar}'}},''' + ) + + def image(self, doc, message): + type_ = message[2] + str_content = message[7] + str_time = message[8] + is_send = message[4] + avatar = 'myhead.png' if is_send else 'tahead.png' + timestamp = message[5] + BytesExtra = message[10] + str_content = escape_js_and_html(str_content) + image_path = hard_link_db.get_image(str_content, BytesExtra, thumb=False) + image_thumb_path = hard_link_db.get_image(str_content, BytesExtra, thumb=True) + if image_path is None and image_thumb_path is not None: + image_path = image_thumb_path + if image_path is None and image_thumb_path is None: + return + image_path = path.get_relative_path(image_path, base_path=f'/data/聊天记录/{self.contact.remark}/image') + image_path = image_path.replace('\\', '/') + # print(f"tohtml:---{image_path}") + if self.is_5_min(timestamp): + doc.write( + f'''{{ type:0, text: '{str_time}',is_send:0,avatar_path:''}},''' + ) + doc.write( + f'''{{ type:{type_}, text: '{image_path}',is_send:{is_send},avatar_path:'{avatar}'}},''' + ) return - def image(self, doc, isSend, Type, content, imgPath): - return - - def emoji(self, doc, isSend, content, imgPath): + def emoji(self, doc, message): + origin_docx_path = f"{os.path.abspath('.')}/data/聊天记录/{self.contact.remark}" + str_content = message[7] + str_time = message[8] + is_send = message[4] + avatar = 'myhead.png' if is_send else 'tahead.png' + timestamp = message[5] + emoji_path = get_emoji(str_content, thumb=True, output_path=origin_docx_path + '/emoji') + emoji_path = './emoji/' + os.path.basename(emoji_path) + if self.is_5_min(timestamp): + doc.write( + f'''{{ type:0, text: '{str_time}',is_send:0,avatar_path:''}},''' + ) + doc.write( + f'''{{ type:{3}, text: '{emoji_path}',is_send:{is_send},avatar_path:'{avatar}'}},''' + ) return def wx_file(self, doc, isSend, content, status): @@ -176,11 +235,55 @@ class ChildThread(QThread): def reply(self, doc, isSend, content, status): return - def pat_a_pat(self, doc, isSend, content, status): - return + def system_msg(self, doc, message): + str_content = message[7] + is_send = message[4] + str_content = escape_js_and_html(str_content.lstrip('').rstrip('')) + doc.write( + f'''{{ type:0, text: '{str_content}',is_send:{is_send},avatar_path:''}},''' + ) - def video(self, doc, isSend, content, status, img_path): - return + def video(self, doc, message): + origin_docx_path = f"{os.path.abspath('.')}/data/聊天记录/{self.contact.remark}" + type_ = message[2] + str_content = message[7] + str_time = message[8] + is_send = message[4] + BytesExtra = message[10] + avatar = 'myhead.png' if is_send else 'tahead.png' + timestamp = message[5] + video_path = hard_link_db.get_video(str_content, BytesExtra, thumb=False) + image_path = hard_link_db.get_video(str_content, BytesExtra, thumb=True) + if video_path is None and image_path is not None: + print(video_path, image_path) + image_path = path.get_relative_path(image_path, base_path=f'/data/聊天记录/{self.contact.remark}/image') + print(image_path) + image_path = image_path.replace('\\', '/') + # print(f"tohtml:---{image_path}") + if self.is_5_min(timestamp): + doc.write( + f'''{{ type:0, text: '{str_time}',is_send:0,avatar_path:''}},''' + ) + doc.write( + f'''{{ type:3, text: '{image_path}',is_send:{is_send},avatar_path:'{avatar}'}},''' + ) + return + if video_path is None and image_path is None: + return + video_path = f'{MePC().wx_dir}/{video_path}' + if os.path.exists(video_path): + new_path = origin_docx_path + '/video/' + os.path.basename(video_path) + if not os.path.exists(new_path): + shutil.copy(video_path, os.path.join(origin_docx_path, 'video')) + video_path = f'./video/{os.path.basename(video_path)}' + video_path = video_path.replace('\\', '/') + if self.is_5_min(timestamp): + doc.write( + f'''{{ type:0, text: '{str_time}',is_send:0,avatar_path:''}},''' + ) + doc.write( + f'''{{ type:{type_}, text: '{video_path}',is_send:{is_send},avatar_path:'{avatar}'}},''' + ) def to_csv(self): origin_docx_path = f"{os.path.abspath('.')}/data/聊天记录/{self.contact.remark}" @@ -224,7 +327,152 @@ class ChildThread(QThread): messages = msg_db.get_messages(self.contact.wxid) filename = f"{os.path.abspath('.')}/data/聊天记录/{self.contact.remark}/{self.contact.remark}.html" f = open(filename, 'w', encoding='utf-8') - html_head = ''' + f.write(html_head) + MePC().avatar.save(os.path.join(origin_docx_path, 'myhead.png')) + self.contact.avatar.save(os.path.join(origin_docx_path, 'tahead.png')) + self.rangeSignal.emit(len(messages)) + total_steps = len(messages) + for index, message in enumerate(messages): + type_ = message[2] + self.progressSignal.emit(int((index+1) / total_steps * 100)) + if type_ == 1 and self.message_types.get(type_): + self.text(f, message) + elif type_ == 3 and self.message_types.get(type_): + self.image(f, message) + elif type_ == 43 and self.message_types.get(type_): + self.video(f, message) + elif type_ == 47 and self.message_types.get(type_): + self.emoji(f, message) + elif type_ == 10000 and self.message_types.get(type_): + self.system_msg(f, message) + f.write(html_end) + f.close() + self.okSignal.emit(1) + + def run(self): + if self.output_type == Output.DOCX: + return + elif self.output_type == Output.CSV: + self.to_csv() + elif self.output_type == Output.HTML: + self.to_html_() + elif self.output_type == Output.CSV_ALL: + self.to_csv_all() + + def cancel(self): + self.requestInterruption() + + +emoji = { + '[微笑]': '', + '[撇嘴]': '', + '[色]': '', + '[发呆]': '', + '[得意]': '', + '[流泪]': '', + '[害羞]': '', + '[闭嘴]': '', + '[睡]': '', + '[大哭]': '', + '[尴尬]': '', + '[发怒]': '', + '[调皮]': '', + '[呲牙]': '', + '[惊讶]': '', + '[难过]': '', + '[抓狂]': '', + '[吐]': '', + '[偷笑]': '', + '[愉快]': '', + '[白眼]': '', + '[傲慢]': '', + '[困]': '', + '[惊恐]': '', + '[憨笑]': '', + '[悠闲]': '', + '[咒骂]': '', + '[疑问]': '', + '[嘘]': '', + '[晕]': '', + '[衰]': '', + '[骷髅]': '', + '[敲打]': '', + '[再见]': '', + '[擦汗]': '', + '[抠鼻]': '', + '[鼓掌]': '', + '[坏笑]': '', + '[右哼哼]': '', + '[鄙视]': '', + '[委屈]': '', + '[快哭了]': '', + '[阴险]': '', + '[亲亲]': '', + '[可怜]': '', + '[笑脸]': '', + '[生病]': '', + '[脸红]': '', + '[破涕为笑]': '', + '[恐惧]': '', + '[失望]': '', + '[无语]': '', + '[嘿哈]': '', + '[捂脸]': '', + '[奸笑]': '', + '[机智]': '', + '[皱眉]': '', + '[耶]': '', + '[吃瓜]': '', + '[加油]': '', + '[汗]': '', + '[天啊]': '', + '[Emm]': '', + '[社会社会]': '', + '[旺柴]': '', + '[好的]': '', + '[打脸]': '', + '[哇]': '', + '[翻白眼]': '', + '[666]': '', + '[让我看看]': '', + '[叹气]': '', + '[苦涩]': '', + '[裂开]': '', + '[嘴唇]': '', + '[爱心]': '', + '[心碎]': '', + '[拥抱]': '', + '[强]': '', + '[弱]': '', + '[握手]': '', + '[胜利]': '', + '[抱拳]': '', + '[勾引]': '', + '[拳头]': '', + '[OK]': '', + '[合十]': '', + '[啤酒]': '', + '[咖啡]': '', + '[蛋糕]': '', + '[玫瑰]': '', + '[凋谢]': '', + '[菜刀]': '', + '[炸弹]': '', + '[便便]': '', + '[月亮]': '', + '[太阳]': '', + '[庆 祝]': '', + '[礼物]': '', + '[红包]': '', + '[發]': '', + '[福]': '', + '[烟花]': '', + '[爆竹]': '', + '[猪头]': '', + '[跳跳]': '', + '[发抖]': '', + '[转圈]': ''} +html_head = ''' @@ -244,7 +492,7 @@ class ChildThread(QThread): align-items: center; justify-content: center; } - + .modal { display: none; position: fixed; @@ -255,7 +503,7 @@ class ChildThread(QThread): height: 100%; background-color: rgba(0, 0, 0, 0.8); } - + .modal-image { display: block; max-width: 90%; @@ -517,212 +765,7 @@ const chatContainer = document.getElementById('chat-container'); // Sample chat messages (replace this with your actual data) const chatMessages = [ ''' - f.write(html_head) - MePC().avatar.save(os.path.join(origin_docx_path, 'myhead.png')) - self.contact.avatar.save(os.path.join(origin_docx_path, 'tahead.png')) - self.rangeSignal.emit(len(messages)) - emoji = { - '[微笑]': '', - '[撇嘴]': '', - '[色]': '', - '[发呆]': '', - '[得意]': '', - '[流泪]': '', - '[害羞]': '', - '[闭嘴]': '', - '[睡]': '', - '[大哭]': '', - '[尴尬]': '', - '[发怒]': '', - '[调皮]': '', - '[呲牙]': '', - '[惊讶]': '', - '[难过]': '', - '[抓狂]': '', - '[吐]': '', - '[偷笑]': '', - '[愉快]': '', - '[白眼]': '', - '[傲慢]': '', - '[困]': '', - '[惊恐]': '', - '[憨笑]': '', - '[悠闲]': '', - '[咒骂]': '', - '[疑问]': '', - '[嘘]': '', - '[晕]': '', - '[衰]': '', - '[骷髅]': '', - '[敲打]': '', - '[再见]': '', - '[擦汗]': '', - '[抠鼻]': '', - '[鼓掌]': '', - '[坏笑]': '', - '[右哼哼]': '', - '[鄙视]': '', - '[委屈]': '', - '[快哭了]': '', - '[阴险]': '', - '[亲亲]': '', - '[可怜]': '', - '[笑脸]': '', - '[生病]': '', - '[脸红]': '', - '[破涕为笑]': '', - '[恐惧]': '', - '[失望]': '', - '[无语]': '', - '[嘿哈]': '', - '[捂脸]': '', - '[奸笑]': '', - '[机智]': '', - '[皱眉]': '', - '[耶]': '', - '[吃瓜]': '', - '[加油]': '', - '[汗]': '', - '[天啊]': '', - '[Emm]': '', - '[社会社会]': '', - '[旺柴]': '', - '[好的]': '', - '[打脸]': '', - '[哇]': '', - '[翻白眼]': '', - '[666]': '', - '[让我看看]': '', - '[叹气]': '', - '[苦涩]': '', - '[裂开]': '', - '[嘴唇]': '', - '[爱心]': '', - '[心碎]': '', - '[拥抱]': '', - '[强]': '', - '[弱]': '', - '[握手]': '', - '[胜利]': '', - '[抱拳]': '', - '[勾引]': '', - '[拳头]': '', - '[OK]': '', - '[合十]': '', - '[啤酒]': '', - '[咖啡]': '', - '[蛋糕]': '', - '[玫瑰]': '', - '[凋谢]': '', - '[菜刀]': '', - '[炸弹]': '', - '[便便]': '', - '[月亮]': '', - '[太阳]': '', - '[庆 祝]': '', - '[礼物]': '', - '[红包]': '', - '[發]': '', - '[福]': '', - '[烟花]': '', - '[爆竹]': '', - '[猪头]': '', - '[跳跳]': '', - '[发抖]': '', - '[转圈]': ''} - from re import findall - for index, message in enumerate(messages): - type_ = message[2] - str_content = message[7] - str_time = message[8] - # print(type_, type(type_)) - is_send = message[4] - BytesExtra = message[10] - # avatar = MePC().avatar_path if is_send else self.contact.avatar_path - # avatar = avatar.replace('\\', '\\\\') - avatar = 'myhead.png' if is_send else 'tahead.png' - timestamp = message[5] - self.progressSignal.emit(index) - if type_ == 1: - str_content = escape_js_and_html(str_content) - if self.is_5_min(timestamp): - f.write( - f'''{{ type:0, text: '{str_time}',is_send:0,avatar_path:''}},''' - ) - - emojiText = findall(r"(\[.+?\])", str_content) - for emoji_text in emojiText: - if emoji_text in emoji: - str_content = str_content.replace(emoji_text, emoji[emoji_text]) - f.write( - f'''{{ type:{type_}, text: '{str_content}',is_send:{is_send},avatar_path:'{avatar}'}},''' - ) - elif type_ == 3: - image_path = hard_link_db.get_image(str_content, BytesExtra, thumb=False) - image_thumb_path = hard_link_db.get_image(str_content, BytesExtra, thumb=True) - if image_path is None and image_thumb_path is not None: - image_path = image_thumb_path - if image_path is None and image_thumb_path is None: - continue - image_path = path.get_relative_path(image_path, base_path=f'/data/聊天记录/{self.contact.remark}/image') - image_path = image_path.replace('\\', '/') - # print(f"tohtml:---{image_path}") - if self.is_5_min(timestamp): - f.write( - f'''{{ type:0, text: '{str_time}',is_send:0,avatar_path:''}},''' - ) - f.write( - f'''{{ type:{type_}, text: '{image_path}',is_send:{is_send},avatar_path:'{avatar}'}},''' - ) - elif type_ == 43: - video_path = hard_link_db.get_video(str_content, BytesExtra, thumb=False) - image_path = hard_link_db.get_video(str_content, BytesExtra, thumb=True) - if video_path is None and image_path is not None: - print(video_path, image_path) - image_path = path.get_relative_path(image_path, base_path=f'/data/聊天记录/{self.contact.remark}/image') - print(image_path) - image_path = image_path.replace('\\', '/') - # print(f"tohtml:---{image_path}") - if self.is_5_min(timestamp): - f.write( - f'''{{ type:0, text: '{str_time}',is_send:0,avatar_path:''}},''' - ) - f.write( - f'''{{ type:3, text: '{image_path}',is_send:{is_send},avatar_path:'{avatar}'}},''' - ) - continue - if video_path is None and image_path is None: - continue - video_path = f'{MePC().wx_dir}/{video_path}' - if os.path.exists(video_path): - new_path = origin_docx_path + '/video/' + os.path.basename(video_path) - if not os.path.exists(new_path): - shutil.copy(video_path, os.path.join(origin_docx_path, 'video')) - video_path = f'./video/{os.path.basename(video_path)}' - video_path = video_path.replace('\\', '/') - if self.is_5_min(timestamp): - f.write( - f'''{{ type:0, text: '{str_time}',is_send:0,avatar_path:''}},''' - ) - f.write( - f'''{{ type:{type_}, text: '{video_path}',is_send:{is_send},avatar_path:'{avatar}'}},''' - ) - elif type_ == 47: - emoji_path = get_emoji(str_content, thumb=True, output_path=origin_docx_path + '/emoji') - emoji_path = './emoji/'+os.path.basename(emoji_path) - if self.is_5_min(timestamp): - f.write( - f'''{{ type:0, text: '{str_time}',is_send:0,avatar_path:''}},''' - ) - f.write( - f'''{{ type:{3}, text: '{emoji_path}',is_send:{is_send},avatar_path:'{avatar}'}},''' - ) - elif type_ == 10000: - str_content = escape_js_and_html(str_content.lstrip('').rstrip('')) - f.write( - f'''{{ type:0, text: '{str_content}',is_send:{is_send},avatar_path:''}},''' - ) - html_end = ''' +html_end = ''' ]; function renderMessages(messages) { for (const message of messages) { @@ -864,7 +907,7 @@ const chatMessages = [ modalImage.src = image.src; console.log(image.src); } - + function hideModal() { var modal = document.getElementById("modal"); modal.style.display = "none"; @@ -873,19 +916,3 @@ const chatMessages = [ ''' - f.write(html_end) - f.close() - self.okSignal.emit(1) - - def run(self): - if self.output_type == Output.DOCX: - return - elif self.output_type == Output.CSV: - self.to_csv() - elif self.output_type == Output.HTML: - self.to_html_() - elif self.output_type == Output.CSV_ALL: - self.to_csv_all() - - def cancel(self): - self.requestInterruption() diff --git a/app/main/__init__.py b/app/main/__init__.py deleted file mode 100644 index d4d7b49..0000000 --- a/app/main/__init__.py +++ /dev/null @@ -1,9 +0,0 @@ -# -*- coding: utf-8 -*- -""" -@File : __init__.py.py -@Author : Shuaikang Zhou -@Time : 2023/1/5 18:11 -@IDE : Pycharm -@Version : Python3.10 -@comment : ··· -""" diff --git a/app/ui_pc/contact/contactInfo.py b/app/ui_pc/contact/contactInfo.py index 1d1b40b..2fe26b4 100644 --- a/app/ui_pc/contact/contactInfo.py +++ b/app/ui_pc/contact/contactInfo.py @@ -1,12 +1,13 @@ from PyQt5.QtCore import pyqtSignal, QUrl, QThread from PyQt5.QtGui import QDesktopServices -from PyQt5.QtWidgets import QWidget, QMenu, QAction, QToolButton, QMessageBox +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): @@ -17,7 +18,7 @@ class ContactInfo(QWidget, Ui_Form): def __init__(self, contact, parent=None): super(ContactInfo, self).__init__(parent) self.setupUi(self) - self.contact:ContactPC = contact + self.contact: ContactPC = contact self.view_userinfo = userinfo.UserinfoController(self.contact) self.btn_back.clicked.connect(self.back) self.init_ui() @@ -116,14 +117,22 @@ class ContactInfo(QWidget, Ui_Form): return self.outputThread = Output(self.Me, self.contact.wxid) elif self.sender() == self.toCSVAct: - self.outputThread = Output(self.contact, type_=Output.CSV) + # 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: - self.outputThread = Output(self.contact, type_=Output.HTML) + dialog = ExportDialog(self.contact,title='选择导出的消息类型', file_type='html', parent=self) + result = dialog.exec_() # 使用exec_()获取用户的操作结果 + # if result == QDialog.Accepted: + # self.result_label.setText("用户点击了导出按钮") + # else: + # self.result_label.setText("用户点击了取消按钮") + # self.outputThread = Output(self.contact, type_=Output.HTML) - 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() + # 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) diff --git a/app/ui_pc/contact/export_dialog.py b/app/ui_pc/contact/export_dialog.py new file mode 100644 index 0000000..5365b36 --- /dev/null +++ b/app/ui_pc/contact/export_dialog.py @@ -0,0 +1,92 @@ +from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QDialog, QVBoxLayout, QCheckBox, QHBoxLayout, \ + QProgressBar, QLabel, QMessageBox + +from app.DataBase.output_pc import Output + +types = { + '文本': 1, + '图片': 3, + '视频': 43, + '表情包': 47, + '拍一拍等系统消息': 10000 +} + + +class ExportDialog(QDialog): + def __init__(self, contact=None, title="选择导出的类型", file_type="csv", parent=None): + super(ExportDialog, self).__init__(parent) + + self.contact = contact + if file_type == 'html': + self.export_type = Output.HTML + self.export_choices = {"文本": True, "图片": True, "视频": True, "表情包": True, + '拍一拍等系统消息': True} # 定义导出的数据类型,默认全部选择 + elif file_type == 'csv': + self.export_type = Output.CSV + self.export_choices = {"文本": 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_()) diff --git a/readme.md b/readme.md index 5380288..d911f1b 100644 --- a/readme.md +++ b/readme.md @@ -35,8 +35,8 @@ ## 🍉功能 -- 🔒️🔑🔓️手机本地微信数据库🐶 -- 🔒️🔑🔓️PC端本地微信数据库🐶 +- 🔒️🔑🔓️手机本地微信数据库 +- 🔒️🔑🔓️PC端本地微信数据库 - 还原微信聊天界面 - 🗨文本✅ - 🏝图片✅