mirror of
https://github.com/LC044/WeChatMsg
synced 2024-11-14 05:21:41 +08:00
支持自定义选择导出聊天记录的日期
This commit is contained in:
parent
63a03858d2
commit
fe4e719012
1
.github/ISSUE_TEMPLATE/2_feature_request.yml
vendored
1
.github/ISSUE_TEMPLATE/2_feature_request.yml
vendored
@ -7,6 +7,7 @@ body:
|
|||||||
attributes:
|
attributes:
|
||||||
label: '👌 是否检查过没有类似issue'
|
label: '👌 是否检查过没有类似issue'
|
||||||
options:
|
options:
|
||||||
|
- 就不检查
|
||||||
- 否
|
- 否
|
||||||
- 是
|
- 是
|
||||||
validations:
|
validations:
|
||||||
|
@ -13,7 +13,7 @@ class CSVExporter(ExporterBase):
|
|||||||
columns = ['localId', 'TalkerId', 'Type', 'SubType',
|
columns = ['localId', 'TalkerId', 'Type', 'SubType',
|
||||||
'IsSender', 'CreateTime', 'Status', 'StrContent',
|
'IsSender', 'CreateTime', 'Status', 'StrContent',
|
||||||
'StrTime', 'Remark', 'NickName', 'Sender']
|
'StrTime', 'Remark', 'NickName', 'Sender']
|
||||||
messages = msg_db.get_messages(self.contact.wxid)
|
messages = msg_db.get_messages(self.contact.wxid, time_range=self.time_range)
|
||||||
# 写入CSV文件
|
# 写入CSV文件
|
||||||
with open(filename, mode='w', newline='', encoding='utf-8-sig') as file:
|
with open(filename, mode='w', newline='', encoding='utf-8-sig') as file:
|
||||||
writer = csv.writer(file)
|
writer = csv.writer(file)
|
||||||
|
@ -288,7 +288,7 @@ class DocxExporter(ExporterBase):
|
|||||||
doc = docx.Document()
|
doc = docx.Document()
|
||||||
doc.styles['Normal'].font.name = u'Cambria'
|
doc.styles['Normal'].font.name = u'Cambria'
|
||||||
doc.styles['Normal']._element.rPr.rFonts.set(qn('w:eastAsia'), u'宋体')
|
doc.styles['Normal']._element.rPr.rFonts.set(qn('w:eastAsia'), u'宋体')
|
||||||
messages = msg_db.get_messages(self.contact.wxid)
|
messages = msg_db.get_messages(self.contact.wxid, time_range=self.time_range)
|
||||||
Me().save_avatar(os.path.join(f"{origin_docx_path}/avatar/{Me().wxid}.png"))
|
Me().save_avatar(os.path.join(f"{origin_docx_path}/avatar/{Me().wxid}.png"))
|
||||||
if self.contact.is_chatroom:
|
if self.contact.is_chatroom:
|
||||||
for message in messages:
|
for message in messages:
|
||||||
|
@ -275,7 +275,7 @@ class HtmlExporter(ExporterBase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def export(self):
|
def export(self):
|
||||||
messages = msg_db.get_messages(self.contact.wxid)
|
messages = msg_db.get_messages(self.contact.wxid, time_range=self.time_range)
|
||||||
filename = f"{os.path.abspath('.')}/data/聊天记录/{self.contact.remark}/{self.contact.remark}.html"
|
filename = f"{os.path.abspath('.')}/data/聊天记录/{self.contact.remark}/{self.contact.remark}.html"
|
||||||
file_path = './app/resources/data/template.html'
|
file_path = './app/resources/data/template.html'
|
||||||
if not os.path.exists(file_path):
|
if not os.path.exists(file_path):
|
||||||
|
@ -113,7 +113,7 @@ class TxtExporter(ExporterBase):
|
|||||||
origin_docx_path = f"{os.path.abspath('.')}/data/聊天记录/{self.contact.remark}"
|
origin_docx_path = f"{os.path.abspath('.')}/data/聊天记录/{self.contact.remark}"
|
||||||
os.makedirs(origin_docx_path, exist_ok=True)
|
os.makedirs(origin_docx_path, exist_ok=True)
|
||||||
filename = f"{os.path.abspath('.')}/data/聊天记录/{self.contact.remark}/{self.contact.remark}.txt"
|
filename = f"{os.path.abspath('.')}/data/聊天记录/{self.contact.remark}/{self.contact.remark}.txt"
|
||||||
messages = msg_db.get_messages(self.contact.wxid)
|
messages = msg_db.get_messages(self.contact.wxid, time_range=self.time_range)
|
||||||
total_steps = len(messages)
|
total_steps = len(messages)
|
||||||
with open(filename, mode='w', newline='', encoding='utf-8') as f:
|
with open(filename, mode='w', newline='', encoding='utf-8') as f:
|
||||||
for index, message in enumerate(messages):
|
for index, message in enumerate(messages):
|
||||||
|
@ -139,7 +139,7 @@ class Msg:
|
|||||||
new_messages.append(new_message)
|
new_messages.append(new_message)
|
||||||
return new_messages
|
return new_messages
|
||||||
|
|
||||||
def get_messages(self, username_):
|
def get_messages(self, username_, time_range=None):
|
||||||
"""
|
"""
|
||||||
return list
|
return list
|
||||||
a[0]: localId,
|
a[0]: localId,
|
||||||
@ -157,10 +157,13 @@ class Msg:
|
|||||||
"""
|
"""
|
||||||
if not self.open_flag:
|
if not self.open_flag:
|
||||||
return None
|
return None
|
||||||
sql = '''
|
if time_range:
|
||||||
|
start_time, end_time = time_range
|
||||||
|
sql = f'''
|
||||||
select localId,TalkerId,Type,SubType,IsSender,CreateTime,Status,StrContent,strftime('%Y-%m-%d %H:%M:%S',CreateTime,'unixepoch','localtime') as StrTime,MsgSvrID,BytesExtra,CompressContent
|
select localId,TalkerId,Type,SubType,IsSender,CreateTime,Status,StrContent,strftime('%Y-%m-%d %H:%M:%S',CreateTime,'unixepoch','localtime') as StrTime,MsgSvrID,BytesExtra,CompressContent
|
||||||
from MSG
|
from MSG
|
||||||
where StrTalker=?
|
where StrTalker=?
|
||||||
|
{'AND CreateTime>' + str(start_time) + ' AND CreateTime<' + str(end_time) if time_range else ''}
|
||||||
order by CreateTime
|
order by CreateTime
|
||||||
'''
|
'''
|
||||||
try:
|
try:
|
||||||
@ -230,14 +233,17 @@ class Msg:
|
|||||||
# result.sort(key=lambda x: x[5])
|
# result.sort(key=lambda x: x[5])
|
||||||
return parser_chatroom_message(result) if username_.__contains__('@chatroom') else result
|
return parser_chatroom_message(result) if username_.__contains__('@chatroom') else result
|
||||||
|
|
||||||
def get_messages_by_type(self, username_, type_, year_='all'):
|
def get_messages_by_type(self, username_, type_, year_='all',time_range=None):
|
||||||
if not self.open_flag:
|
if not self.open_flag:
|
||||||
return None
|
return None
|
||||||
|
if time_range:
|
||||||
|
start_time, end_time = time_range
|
||||||
if year_ == 'all':
|
if year_ == 'all':
|
||||||
sql = '''
|
sql = f'''
|
||||||
select localId,TalkerId,Type,SubType,IsSender,CreateTime,Status,StrContent,strftime('%Y-%m-%d %H:%M:%S',CreateTime,'unixepoch','localtime') as StrTime,MsgSvrID,BytesExtra,CompressContent
|
select localId,TalkerId,Type,SubType,IsSender,CreateTime,Status,StrContent,strftime('%Y-%m-%d %H:%M:%S',CreateTime,'unixepoch','localtime') as StrTime,MsgSvrID,BytesExtra,CompressContent
|
||||||
from MSG
|
from MSG
|
||||||
where StrTalker=? and Type=?
|
where StrTalker=? and Type=?
|
||||||
|
{'AND CreateTime>' + str(start_time) + ' AND CreateTime<' + str(end_time) if time_range else ''}
|
||||||
order by CreateTime
|
order by CreateTime
|
||||||
'''
|
'''
|
||||||
try:
|
try:
|
||||||
|
@ -3,29 +3,12 @@ import html
|
|||||||
import os
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
import sys
|
import sys
|
||||||
import time
|
|
||||||
import traceback
|
|
||||||
import filecmp
|
import filecmp
|
||||||
from re import findall
|
|
||||||
|
|
||||||
import docx
|
|
||||||
from PyQt5.QtCore import pyqtSignal, QThread
|
from PyQt5.QtCore import pyqtSignal, QThread
|
||||||
from PyQt5.QtWidgets import QFileDialog
|
|
||||||
from docx import shared
|
|
||||||
from docx.enum.table import WD_ALIGN_VERTICAL
|
|
||||||
from docx.enum.text import WD_COLOR_INDEX, WD_PARAGRAPH_ALIGNMENT
|
|
||||||
from docx.oxml.ns import qn
|
|
||||||
|
|
||||||
from .package_msg import PackageMsg
|
|
||||||
from ..DataBase import media_msg_db, hard_link_db, micro_msg_db, msg_db
|
|
||||||
from ..log import logger
|
|
||||||
from ..person import Me, Contact
|
from ..person import Me, Contact
|
||||||
from ..util import path
|
|
||||||
from ..util.compress_content import parser_reply, music_share, share_card
|
|
||||||
from ..util.emoji import get_emoji_url
|
|
||||||
from ..util.file import get_file
|
|
||||||
from ..util.music import get_music_path
|
|
||||||
from ..util.image import get_image_path, get_image, get_image_abs_path
|
|
||||||
|
|
||||||
os.makedirs('./data/聊天记录', exist_ok=True)
|
os.makedirs('./data/聊天记录', exist_ok=True)
|
||||||
|
|
||||||
@ -107,7 +90,7 @@ class ExporterBase(QThread):
|
|||||||
CONTACT_CSV = 4
|
CONTACT_CSV = 4
|
||||||
TXT = 5
|
TXT = 5
|
||||||
|
|
||||||
def __init__(self, contact, type_=DOCX, message_types={}, parent=None):
|
def __init__(self, contact, type_=DOCX, message_types={},time_range=None, parent=None):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
self.message_types = message_types # 导出的消息类型
|
self.message_types = message_types # 导出的消息类型
|
||||||
self.contact: Contact = contact # 联系人
|
self.contact: Contact = contact # 联系人
|
||||||
@ -115,6 +98,7 @@ class ExporterBase(QThread):
|
|||||||
self.total_num = 1 # 总的消息数量
|
self.total_num = 1 # 总的消息数量
|
||||||
self.num = 0 # 当前处理的消息数量
|
self.num = 0 # 当前处理的消息数量
|
||||||
self.last_timestamp = 0
|
self.last_timestamp = 0
|
||||||
|
self.time_range = time_range
|
||||||
origin_docx_path = f"{os.path.abspath('.')}/data/聊天记录/{self.contact.remark}"
|
origin_docx_path = f"{os.path.abspath('.')}/data/聊天记录/{self.contact.remark}"
|
||||||
makedirs(origin_docx_path)
|
makedirs(origin_docx_path)
|
||||||
def run(self):
|
def run(self):
|
||||||
|
@ -39,11 +39,12 @@ class Output(QThread):
|
|||||||
TXT = 5
|
TXT = 5
|
||||||
Batch = 10086
|
Batch = 10086
|
||||||
|
|
||||||
def __init__(self, contact, type_=DOCX, message_types={}, sub_type=[], parent=None):
|
def __init__(self, contact, type_=DOCX, message_types={}, sub_type=[], time_range=None,parent=None):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
self.children = []
|
self.children = []
|
||||||
self.last_timestamp = 0
|
self.last_timestamp = 0
|
||||||
self.sub_type = sub_type
|
self.sub_type = sub_type
|
||||||
|
self.time_range = time_range
|
||||||
self.message_types = message_types
|
self.message_types = message_types
|
||||||
self.sec = 2 # 默认1000秒
|
self.sec = 2 # 默认1000秒
|
||||||
self.contact = contact
|
self.contact = contact
|
||||||
@ -161,7 +162,7 @@ class Output(QThread):
|
|||||||
self.okSignal.emit(1)
|
self.okSignal.emit(1)
|
||||||
|
|
||||||
def to_docx(self, contact, message_types, is_batch=False):
|
def to_docx(self, contact, message_types, is_batch=False):
|
||||||
Child = DocxExporter(contact, type_=self.DOCX, message_types=message_types)
|
Child = DocxExporter(contact, type_=self.DOCX, message_types=message_types,time_range=self.time_range)
|
||||||
self.children.append(Child)
|
self.children.append(Child)
|
||||||
Child.progressSignal.connect(self.progress)
|
Child.progressSignal.connect(self.progress)
|
||||||
if not is_batch:
|
if not is_batch:
|
||||||
@ -170,7 +171,7 @@ class Output(QThread):
|
|||||||
Child.start()
|
Child.start()
|
||||||
|
|
||||||
def to_txt(self, contact, message_types, is_batch=False):
|
def to_txt(self, contact, message_types, is_batch=False):
|
||||||
Child = TxtExporter(contact, type_=self.TXT, message_types=message_types)
|
Child = TxtExporter(contact, type_=self.TXT, message_types=message_types,time_range=self.time_range)
|
||||||
self.children.append(Child)
|
self.children.append(Child)
|
||||||
Child.progressSignal.connect(self.progress)
|
Child.progressSignal.connect(self.progress)
|
||||||
if not is_batch:
|
if not is_batch:
|
||||||
@ -179,7 +180,7 @@ class Output(QThread):
|
|||||||
Child.start()
|
Child.start()
|
||||||
|
|
||||||
def to_html(self, contact, message_types, is_batch=False):
|
def to_html(self, contact, message_types, is_batch=False):
|
||||||
Child = HtmlExporter(contact, type_=self.output_type, message_types=message_types)
|
Child = HtmlExporter(contact, type_=self.output_type, message_types=message_types,time_range=self.time_range)
|
||||||
self.children.append(Child)
|
self.children.append(Child)
|
||||||
Child.progressSignal.connect(self.progress)
|
Child.progressSignal.connect(self.progress)
|
||||||
if not is_batch:
|
if not is_batch:
|
||||||
@ -190,7 +191,7 @@ class Output(QThread):
|
|||||||
if message_types.get(34):
|
if message_types.get(34):
|
||||||
# 语音消息单独的线程
|
# 语音消息单独的线程
|
||||||
self.total_num += 1
|
self.total_num += 1
|
||||||
output_media = OutputMedia(contact)
|
output_media = OutputMedia(contact,time_range=self.time_range)
|
||||||
self.children.append(output_media)
|
self.children.append(output_media)
|
||||||
output_media.okSingal.connect(self.count_finish_num)
|
output_media.okSingal.connect(self.count_finish_num)
|
||||||
output_media.progressSignal.connect(self.progressSignal)
|
output_media.progressSignal.connect(self.progressSignal)
|
||||||
@ -198,7 +199,7 @@ class Output(QThread):
|
|||||||
if message_types.get(47):
|
if message_types.get(47):
|
||||||
# emoji消息单独的线程
|
# emoji消息单独的线程
|
||||||
self.total_num += 1
|
self.total_num += 1
|
||||||
output_emoji = OutputEmoji(contact)
|
output_emoji = OutputEmoji(contact,time_range=self.time_range)
|
||||||
self.children.append(output_emoji)
|
self.children.append(output_emoji)
|
||||||
output_emoji.okSingal.connect(self.count_finish_num)
|
output_emoji.okSingal.connect(self.count_finish_num)
|
||||||
output_emoji.progressSignal.connect(self.progressSignal)
|
output_emoji.progressSignal.connect(self.progressSignal)
|
||||||
@ -206,14 +207,14 @@ class Output(QThread):
|
|||||||
if message_types.get(3):
|
if message_types.get(3):
|
||||||
# 图片消息单独的线程
|
# 图片消息单独的线程
|
||||||
self.total_num += 1
|
self.total_num += 1
|
||||||
output_image = OutputImage(contact)
|
output_image = OutputImage(contact,time_range=self.time_range)
|
||||||
self.children.append(output_image)
|
self.children.append(output_image)
|
||||||
output_image.okSingal.connect(self.count_finish_num)
|
output_image.okSingal.connect(self.count_finish_num)
|
||||||
output_image.progressSignal.connect(self.progressSignal)
|
output_image.progressSignal.connect(self.progressSignal)
|
||||||
output_image.start()
|
output_image.start()
|
||||||
|
|
||||||
def to_csv(self, contact, message_types, is_batch=False):
|
def to_csv(self, contact, message_types, is_batch=False):
|
||||||
Child = CSVExporter(contact, type_=self.CSV, message_types=message_types)
|
Child = CSVExporter(contact, type_=self.CSV, message_types=message_types,time_range=self.time_range)
|
||||||
self.children.append(Child)
|
self.children.append(Child)
|
||||||
Child.progressSignal.connect(self.progress)
|
Child.progressSignal.connect(self.progress)
|
||||||
if not is_batch:
|
if not is_batch:
|
||||||
@ -263,13 +264,14 @@ class OutputMedia(QThread):
|
|||||||
okSingal = pyqtSignal(int)
|
okSingal = pyqtSignal(int)
|
||||||
progressSignal = pyqtSignal(int)
|
progressSignal = pyqtSignal(int)
|
||||||
|
|
||||||
def __init__(self, contact):
|
def __init__(self, contact,time_range=None):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.contact = contact
|
self.contact = contact
|
||||||
|
self.time_range = time_range
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
origin_docx_path = f"{os.path.abspath('.')}/data/聊天记录/{self.contact.remark}"
|
origin_docx_path = f"{os.path.abspath('.')}/data/聊天记录/{self.contact.remark}"
|
||||||
messages = msg_db.get_messages_by_type(self.contact.wxid, 34)
|
messages = msg_db.get_messages_by_type(self.contact.wxid, 34,time_range=self.time_range)
|
||||||
for message in messages:
|
for message in messages:
|
||||||
is_send = message[4]
|
is_send = message[4]
|
||||||
msgSvrId = message[9]
|
msgSvrId = message[9]
|
||||||
@ -289,13 +291,14 @@ class OutputEmoji(QThread):
|
|||||||
okSingal = pyqtSignal(int)
|
okSingal = pyqtSignal(int)
|
||||||
progressSignal = pyqtSignal(int)
|
progressSignal = pyqtSignal(int)
|
||||||
|
|
||||||
def __init__(self, contact):
|
def __init__(self, contact,time_range=None):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.contact = contact
|
self.contact = contact
|
||||||
|
self.time_range = time_range
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
origin_docx_path = f"{os.path.abspath('.')}/data/聊天记录/{self.contact.remark}"
|
origin_docx_path = f"{os.path.abspath('.')}/data/聊天记录/{self.contact.remark}"
|
||||||
messages = msg_db.get_messages_by_type(self.contact.wxid, 47)
|
messages = msg_db.get_messages_by_type(self.contact.wxid, 47,time_range=self.time_range)
|
||||||
for message in messages:
|
for message in messages:
|
||||||
str_content = message[7]
|
str_content = message[7]
|
||||||
try:
|
try:
|
||||||
@ -315,10 +318,11 @@ class OutputImage(QThread):
|
|||||||
okSingal = pyqtSignal(int)
|
okSingal = pyqtSignal(int)
|
||||||
progressSignal = pyqtSignal(int)
|
progressSignal = pyqtSignal(int)
|
||||||
|
|
||||||
def __init__(self, contact):
|
def __init__(self, contact,time_range):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.contact = contact
|
self.contact = contact
|
||||||
self.child_thread_num = 2
|
self.child_thread_num = 2
|
||||||
|
self.time_range =time_range
|
||||||
self.child_threads = [0] * (self.child_thread_num + 1)
|
self.child_threads = [0] * (self.child_thread_num + 1)
|
||||||
self.num = 0
|
self.num = 0
|
||||||
|
|
||||||
@ -331,7 +335,7 @@ class OutputImage(QThread):
|
|||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
origin_docx_path = f"{os.path.abspath('.')}/data/聊天记录/{self.contact.remark}"
|
origin_docx_path = f"{os.path.abspath('.')}/data/聊天记录/{self.contact.remark}"
|
||||||
messages = msg_db.get_messages_by_type(self.contact.wxid, 3)
|
messages = msg_db.get_messages_by_type(self.contact.wxid, 3,time_range=self.time_range)
|
||||||
for message in messages:
|
for message in messages:
|
||||||
str_content = message[7]
|
str_content = message[7]
|
||||||
BytesExtra = message[10]
|
BytesExtra = message[10]
|
||||||
@ -359,10 +363,11 @@ class OutputImageChild(QThread):
|
|||||||
okSingal = pyqtSignal(int)
|
okSingal = pyqtSignal(int)
|
||||||
progressSignal = pyqtSignal(int)
|
progressSignal = pyqtSignal(int)
|
||||||
|
|
||||||
def __init__(self, contact, messages):
|
def __init__(self, contact, messages,time_range):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.contact = contact
|
self.contact = contact
|
||||||
self.messages = messages
|
self.messages = messages
|
||||||
|
self.time_range = time_range
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
origin_docx_path = f"{os.path.abspath('.')}/data/聊天记录/{self.contact.remark}"
|
origin_docx_path = f"{os.path.abspath('.')}/data/聊天记录/{self.contact.remark}"
|
||||||
|
46
app/components/calendar_dialog.py
Normal file
46
app/components/calendar_dialog.py
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
import time
|
||||||
|
|
||||||
|
from PyQt5 import QtWidgets
|
||||||
|
from PyQt5.QtCore import QTimer, QThread, pyqtSignal
|
||||||
|
from PyQt5.QtWidgets import QApplication, QDialog, QCheckBox, QMessageBox, QCalendarWidget, QWidget, QVBoxLayout
|
||||||
|
|
||||||
|
|
||||||
|
class CalendarDialog(QDialog):
|
||||||
|
selected_date_signal = pyqtSignal(int)
|
||||||
|
def __init__(self, date_range=None, parent=None):
|
||||||
|
"""
|
||||||
|
|
||||||
|
@param date_range: tuple[Union[QDate, datetime.date],Union[QDate, datetime.date]]
|
||||||
|
@param parent:
|
||||||
|
"""
|
||||||
|
super().__init__(parent)
|
||||||
|
self.calendar = QCalendarWidget(self)
|
||||||
|
self.calendar.clicked.connect(self.onDateChanged)
|
||||||
|
if date_range:
|
||||||
|
self.calendar.setDateRange(*date_range)
|
||||||
|
layout = QVBoxLayout(self)
|
||||||
|
layout.addWidget(self.calendar)
|
||||||
|
self.setLayout(layout)
|
||||||
|
|
||||||
|
def onDateChanged(self):
|
||||||
|
# 获取选择的日期
|
||||||
|
selected_date = self.calendar.selectedDate()
|
||||||
|
s_t = time.strptime(selected_date.toString("yyyy-MM-dd"), "%Y-%m-%d") # 返回元祖
|
||||||
|
mkt = int(time.mktime(s_t))
|
||||||
|
timestamp = mkt
|
||||||
|
self.selected_date_signal.emit(timestamp)
|
||||||
|
print("Selected Date:", selected_date.toString("yyyy-MM-dd"),timestamp)
|
||||||
|
self.close()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
import sys
|
||||||
|
from datetime import datetime
|
||||||
|
app = QApplication(sys.argv)
|
||||||
|
# 设置日期范围
|
||||||
|
start_date = datetime(2023, 12, 11)
|
||||||
|
end_date = datetime(2024, 1, 9)
|
||||||
|
date_range = (start_date.date(),end_date.date())
|
||||||
|
ex = CalendarDialog(date_range=date_range)
|
||||||
|
ex.show()
|
||||||
|
sys.exit(app.exec_())
|
@ -3,14 +3,16 @@ from typing import List
|
|||||||
|
|
||||||
from PyQt5 import QtWidgets
|
from PyQt5 import QtWidgets
|
||||||
from PyQt5.QtCore import QTimer, QThread, pyqtSignal
|
from PyQt5.QtCore import QTimer, QThread, pyqtSignal
|
||||||
from PyQt5.QtWidgets import QApplication, QDialog, QCheckBox, QMessageBox
|
from PyQt5.QtWidgets import QApplication, QDialog, QCheckBox, QMessageBox, QCalendarWidget
|
||||||
|
|
||||||
from app.DataBase import micro_msg_db, misc_db
|
from app.DataBase import micro_msg_db, misc_db
|
||||||
from app.DataBase.output_pc import Output
|
from app.DataBase.output_pc import Output
|
||||||
from app.components import ScrollBar
|
from app.components import ScrollBar
|
||||||
|
from app.components.calendar_dialog import CalendarDialog
|
||||||
from app.components.export_contact_item import ContactQListWidgetItem
|
from app.components.export_contact_item import ContactQListWidgetItem
|
||||||
from app.person import Contact
|
from app.person import Contact
|
||||||
from app.ui.menu.exportUi import Ui_Dialog
|
from app.ui.menu.exportUi import Ui_Dialog
|
||||||
|
from app.ui.menu.export_time_range import TimeRangeDialog
|
||||||
|
|
||||||
types = {
|
types = {
|
||||||
'文本': 1,
|
'文本': 1,
|
||||||
@ -77,22 +79,46 @@ class ExportDialog(QDialog, Ui_Dialog):
|
|||||||
self.listWidget.itemClicked.connect(self.setCurrentIndex)
|
self.listWidget.itemClicked.connect(self.setCurrentIndex)
|
||||||
self.visited = set()
|
self.visited = set()
|
||||||
self.now_index = 0
|
self.now_index = 0
|
||||||
|
self.time_range = None
|
||||||
|
|
||||||
def set_export_date(self):
|
def set_export_date(self):
|
||||||
date_range = self.comboBox_time.currentText()
|
date_range = self.comboBox_time.currentText()
|
||||||
if date_range == '全部时间':
|
if date_range == '全部时间':
|
||||||
pass
|
pass
|
||||||
elif date_range == '最近三个月':
|
elif date_range == '最近三个月':
|
||||||
QMessageBox.warning(self,
|
from datetime import datetime, timedelta
|
||||||
"别急别急",
|
|
||||||
"马上就实现该功能"
|
|
||||||
)
|
|
||||||
elif date_range == '自定义时间':
|
|
||||||
QMessageBox.warning(self,
|
|
||||||
"别急别急",
|
|
||||||
"马上就实现该功能"
|
|
||||||
)
|
|
||||||
|
|
||||||
|
# 获取今天的日期和时间
|
||||||
|
today = datetime.now()
|
||||||
|
|
||||||
|
# 获取今天的日期
|
||||||
|
today_date = today.date()
|
||||||
|
|
||||||
|
# 获取今天的24:00:00的时间戳
|
||||||
|
today_midnight = datetime.combine(today_date, datetime.min.time()) + timedelta(days=1)
|
||||||
|
today_midnight_timestamp = int(today_midnight.timestamp())
|
||||||
|
|
||||||
|
# 获取三个月前的日期
|
||||||
|
three_months_ago = today - timedelta(days=90)
|
||||||
|
|
||||||
|
# 获取三个月前的00:00:00的时间戳
|
||||||
|
three_months_ago_date = three_months_ago.date()
|
||||||
|
three_months_ago_midnight = datetime.combine(three_months_ago_date, datetime.min.time())
|
||||||
|
three_months_ago_midnight_timestamp = int(three_months_ago_midnight.timestamp())
|
||||||
|
self.time_range = (three_months_ago_midnight_timestamp,today_midnight_timestamp)
|
||||||
|
|
||||||
|
elif date_range == '自定义时间':
|
||||||
|
self.time_range_view = TimeRangeDialog(parent=self)
|
||||||
|
self.time_range_view.date_range_signal.connect(self.set_time_range)
|
||||||
|
self.time_range_view.show()
|
||||||
|
self.comboBox_time.setCurrentIndex(0)
|
||||||
|
# QMessageBox.warning(self,
|
||||||
|
# "别急别急",
|
||||||
|
# "马上就实现该功能"
|
||||||
|
# )
|
||||||
|
def set_time_range(self,time_range):
|
||||||
|
self.time_range = time_range
|
||||||
|
self.comboBox_time.setCurrentIndex(2)
|
||||||
def export_data(self):
|
def export_data(self):
|
||||||
self.btn_start.setEnabled(False)
|
self.btn_start.setEnabled(False)
|
||||||
# 在这里获取用户选择的导出数据类型
|
# 在这里获取用户选择的导出数据类型
|
||||||
@ -115,7 +141,7 @@ class ExportDialog(QDialog, Ui_Dialog):
|
|||||||
select_contacts.append(self.contacts[i])
|
select_contacts.append(self.contacts[i])
|
||||||
# 在这里根据用户选择的数据类型执行导出操作
|
# 在这里根据用户选择的数据类型执行导出操作
|
||||||
print("选择的文件格式:", file_types)
|
print("选择的文件格式:", file_types)
|
||||||
self.worker = Output(select_contacts, type_=Output.Batch, message_types=selected_types, sub_type=file_types)
|
self.worker = Output(select_contacts, type_=Output.Batch, message_types=selected_types, sub_type=file_types,time_range=self.time_range)
|
||||||
# self.worker.progressSignal.connect(self.update_progress)
|
# self.worker.progressSignal.connect(self.update_progress)
|
||||||
self.worker.okSignal.connect(self.export_finished)
|
self.worker.okSignal.connect(self.export_finished)
|
||||||
self.worker.rangeSignal.connect(self.set_total_msg_num)
|
self.worker.rangeSignal.connect(self.set_total_msg_num)
|
||||||
|
72
app/ui/menu/export_time_range.py
Normal file
72
app/ui/menu/export_time_range.py
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
from datetime import datetime
|
||||||
|
from PyQt5 import QtWidgets
|
||||||
|
from PyQt5.QtCore import QTimer, QThread, pyqtSignal
|
||||||
|
from PyQt5.QtWidgets import QApplication, QDialog, QCheckBox, QMessageBox, QCalendarWidget, QWidget, QVBoxLayout, QLabel
|
||||||
|
|
||||||
|
from app.components.calendar_dialog import CalendarDialog
|
||||||
|
from .time_range import Ui_Dialog
|
||||||
|
|
||||||
|
Stylesheet = '''
|
||||||
|
QToolButton{
|
||||||
|
color:#000000;
|
||||||
|
}
|
||||||
|
'''
|
||||||
|
class TimeRangeDialog(QDialog, Ui_Dialog):
|
||||||
|
date_range_signal = pyqtSignal(tuple)
|
||||||
|
|
||||||
|
def __init__(self, date_range=None, parent=None):
|
||||||
|
"""
|
||||||
|
|
||||||
|
@param date_range: tuple[Union[QDate, datetime.date],Union[QDate, datetime.date]]
|
||||||
|
@param parent:
|
||||||
|
"""
|
||||||
|
super().__init__(parent)
|
||||||
|
self.calendar = None
|
||||||
|
self.setupUi(self)
|
||||||
|
self.setStyleSheet(Stylesheet)
|
||||||
|
self.toolButton_start_time.clicked.connect(self.select_date_start)
|
||||||
|
self.toolButton_end_time.clicked.connect(self.select_date_end)
|
||||||
|
self.calendar = CalendarDialog(date_range=date_range, parent=self)
|
||||||
|
self.calendar.selected_date_signal.connect(self.set_date)
|
||||||
|
self.btn_ok.clicked.connect(self.ok)
|
||||||
|
self.btn_cancel.clicked.connect(lambda x:self.close())
|
||||||
|
self.start_time_flag = True
|
||||||
|
self.start_timestamp = 0
|
||||||
|
self.end_timestamp = 0
|
||||||
|
|
||||||
|
def set_date(self, timestamp):
|
||||||
|
if self.start_time_flag:
|
||||||
|
self.start_timestamp = timestamp
|
||||||
|
date_object = datetime.fromtimestamp(timestamp)
|
||||||
|
str_start =date_object.strftime("%Y-%m-%d")
|
||||||
|
self.toolButton_start_time.setText(str_start)
|
||||||
|
else:
|
||||||
|
date_object = datetime.fromtimestamp(timestamp)
|
||||||
|
str_start = date_object.strftime("%Y-%m-%d")
|
||||||
|
self.end_timestamp = timestamp + 86399
|
||||||
|
self.toolButton_end_time.setText(str_start)
|
||||||
|
def ok(self):
|
||||||
|
date_range = (self.start_timestamp,self.end_timestamp)
|
||||||
|
self.date_range_signal.emit(date_range)
|
||||||
|
self.close()
|
||||||
|
def select_date_start(self):
|
||||||
|
self.start_time_flag = True
|
||||||
|
self.calendar.show()
|
||||||
|
|
||||||
|
def select_date_end(self):
|
||||||
|
self.start_time_flag = False
|
||||||
|
self.calendar.show()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
import sys
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
app = QApplication(sys.argv)
|
||||||
|
# 设置日期范围
|
||||||
|
start_date = datetime(2023, 12, 11)
|
||||||
|
end_date = datetime(2024, 1, 9)
|
||||||
|
date_range = (start_date.date(), end_date.date())
|
||||||
|
ex = CalendarDialog(date_range=date_range)
|
||||||
|
ex.show()
|
||||||
|
sys.exit(app.exec_())
|
71
app/ui/menu/time_range.py
Normal file
71
app/ui/menu/time_range.py
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# Form implementation generated from reading ui file 'time_range.ui'
|
||||||
|
#
|
||||||
|
# Created by: PyQt5 UI code generator 5.15.10
|
||||||
|
#
|
||||||
|
# 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(280, 200)
|
||||||
|
Dialog.setMinimumSize(QtCore.QSize(280, 200))
|
||||||
|
Dialog.setMaximumSize(QtCore.QSize(280, 200))
|
||||||
|
self.verticalLayout = QtWidgets.QVBoxLayout(Dialog)
|
||||||
|
self.verticalLayout.setObjectName("verticalLayout")
|
||||||
|
self.label = QtWidgets.QLabel(Dialog)
|
||||||
|
self.label.setLayoutDirection(QtCore.Qt.LeftToRight)
|
||||||
|
self.label.setAlignment(QtCore.Qt.AlignCenter)
|
||||||
|
self.label.setObjectName("label")
|
||||||
|
self.verticalLayout.addWidget(self.label)
|
||||||
|
self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
|
||||||
|
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
|
||||||
|
self.label_2 = QtWidgets.QLabel(Dialog)
|
||||||
|
self.label_2.setObjectName("label_2")
|
||||||
|
self.horizontalLayout_2.addWidget(self.label_2)
|
||||||
|
self.toolButton_start_time = QtWidgets.QToolButton(Dialog)
|
||||||
|
self.toolButton_start_time.setToolButtonStyle(QtCore.Qt.ToolButtonTextBesideIcon)
|
||||||
|
self.toolButton_start_time.setArrowType(QtCore.Qt.DownArrow)
|
||||||
|
self.toolButton_start_time.setObjectName("toolButton_start_time")
|
||||||
|
self.horizontalLayout_2.addWidget(self.toolButton_start_time)
|
||||||
|
self.verticalLayout.addLayout(self.horizontalLayout_2)
|
||||||
|
self.horizontalLayout = QtWidgets.QHBoxLayout()
|
||||||
|
self.horizontalLayout.setObjectName("horizontalLayout")
|
||||||
|
self.label_3 = QtWidgets.QLabel(Dialog)
|
||||||
|
self.label_3.setObjectName("label_3")
|
||||||
|
self.horizontalLayout.addWidget(self.label_3)
|
||||||
|
self.toolButton_end_time = QtWidgets.QToolButton(Dialog)
|
||||||
|
self.toolButton_end_time.setToolButtonStyle(QtCore.Qt.ToolButtonTextBesideIcon)
|
||||||
|
self.toolButton_end_time.setArrowType(QtCore.Qt.DownArrow)
|
||||||
|
self.toolButton_end_time.setObjectName("toolButton_end_time")
|
||||||
|
self.horizontalLayout.addWidget(self.toolButton_end_time)
|
||||||
|
self.verticalLayout.addLayout(self.horizontalLayout)
|
||||||
|
self.horizontalLayout_3 = QtWidgets.QHBoxLayout()
|
||||||
|
self.horizontalLayout_3.setObjectName("horizontalLayout_3")
|
||||||
|
self.btn_ok = QtWidgets.QPushButton(Dialog)
|
||||||
|
self.btn_ok.setObjectName("btn_ok")
|
||||||
|
self.horizontalLayout_3.addWidget(self.btn_ok)
|
||||||
|
self.btn_cancel = QtWidgets.QPushButton(Dialog)
|
||||||
|
self.btn_cancel.setObjectName("btn_cancel")
|
||||||
|
self.horizontalLayout_3.addWidget(self.btn_cancel)
|
||||||
|
self.verticalLayout.addLayout(self.horizontalLayout_3)
|
||||||
|
|
||||||
|
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", "自定义时间"))
|
||||||
|
self.label_2.setText(_translate("Dialog", "开始日期"))
|
||||||
|
self.toolButton_start_time.setText(_translate("Dialog", "请选择时间"))
|
||||||
|
self.label_3.setText(_translate("Dialog", "结束日期"))
|
||||||
|
self.toolButton_end_time.setText(_translate("Dialog", "请选择时间"))
|
||||||
|
self.btn_ok.setText(_translate("Dialog", "确定"))
|
||||||
|
self.btn_cancel.setText(_translate("Dialog", "取消"))
|
Loading…
Reference in New Issue
Block a user