262 lines
9.2 KiB
Python
262 lines
9.2 KiB
Python
![]() |
from PyQt5.QtWidgets import (QDialog, QVBoxLayout, QHBoxLayout, QLabel,
|
|||
|
QComboBox, QPushButton, QTextEdit, QFrame,
|
|||
|
QScrollArea, QWidget)
|
|||
|
from PyQt5.QtCore import Qt
|
|||
|
from PyQt5.QtGui import QColor, QTextCharFormat, QTextCursor
|
|||
|
import difflib
|
|||
|
|
|||
|
class VersionCompareDialog(QDialog):
|
|||
|
"""版本比较对话框"""
|
|||
|
|
|||
|
def __init__(self, versions, parent=None):
|
|||
|
super().__init__(parent)
|
|||
|
# 按联系人分组版本
|
|||
|
self.contact_versions = self.group_versions_by_contact(versions)
|
|||
|
self.init_ui()
|
|||
|
self.apply_style()
|
|||
|
|
|||
|
def group_versions_by_contact(self, versions):
|
|||
|
"""将版本按联系人分组
|
|||
|
Returns:
|
|||
|
Dict[str, List[Dict]]: 以联系人wxid为键,版本列表为值的字典
|
|||
|
"""
|
|||
|
grouped = {}
|
|||
|
for version in versions:
|
|||
|
contact = version['contact']
|
|||
|
wxid = contact['wxid']
|
|||
|
if wxid not in grouped:
|
|||
|
grouped[wxid] = []
|
|||
|
grouped[wxid].append(version)
|
|||
|
return grouped
|
|||
|
|
|||
|
def init_ui(self):
|
|||
|
"""初始化UI"""
|
|||
|
self.setWindowTitle("版本比较")
|
|||
|
self.setMinimumSize(800, 600)
|
|||
|
|
|||
|
layout = QVBoxLayout(self)
|
|||
|
|
|||
|
# 联系人选择
|
|||
|
contact_layout = QHBoxLayout()
|
|||
|
contact_layout.addWidget(QLabel("选择联系人:"))
|
|||
|
self.contact_combo = QComboBox()
|
|||
|
self.contact_combo.currentIndexChanged.connect(self.on_contact_changed)
|
|||
|
contact_layout.addWidget(self.contact_combo)
|
|||
|
layout.addLayout(contact_layout)
|
|||
|
|
|||
|
# 版本选择区域
|
|||
|
select_layout = QHBoxLayout()
|
|||
|
|
|||
|
# 版本A选择
|
|||
|
version_a_layout = QVBoxLayout()
|
|||
|
version_a_layout.addWidget(QLabel("版本A:"))
|
|||
|
self.version_a_combo = QComboBox()
|
|||
|
self.version_a_combo.currentIndexChanged.connect(self.compare_versions)
|
|||
|
version_a_layout.addWidget(self.version_a_combo)
|
|||
|
select_layout.addLayout(version_a_layout)
|
|||
|
|
|||
|
# 版本B选择
|
|||
|
version_b_layout = QVBoxLayout()
|
|||
|
version_b_layout.addWidget(QLabel("版本B:"))
|
|||
|
self.version_b_combo = QComboBox()
|
|||
|
self.version_b_combo.currentIndexChanged.connect(self.compare_versions)
|
|||
|
version_b_layout.addWidget(self.version_b_combo)
|
|||
|
select_layout.addLayout(version_b_layout)
|
|||
|
|
|||
|
layout.addLayout(select_layout)
|
|||
|
|
|||
|
# 比较结果区域
|
|||
|
scroll = QScrollArea()
|
|||
|
scroll.setWidgetResizable(True)
|
|||
|
scroll.setObjectName("compare-scroll")
|
|||
|
|
|||
|
content_widget = QWidget()
|
|||
|
self.content_layout = QVBoxLayout(content_widget)
|
|||
|
|
|||
|
# 各部分内容比较
|
|||
|
self.add_compare_section("新年祝福语", "greeting")
|
|||
|
self.add_compare_section("美好祝愿", "wishes")
|
|||
|
self.add_compare_section("祝福成语", "idioms")
|
|||
|
self.add_compare_section("新年图片提示词", "image_prompt")
|
|||
|
|
|||
|
scroll.setWidget(content_widget)
|
|||
|
layout.addWidget(scroll)
|
|||
|
|
|||
|
# 底部按钮
|
|||
|
button_layout = QHBoxLayout()
|
|||
|
close_btn = QPushButton("关闭")
|
|||
|
close_btn.setObjectName("close-btn")
|
|||
|
close_btn.clicked.connect(self.accept)
|
|||
|
button_layout.addStretch()
|
|||
|
button_layout.addWidget(close_btn)
|
|||
|
layout.addLayout(button_layout)
|
|||
|
|
|||
|
# 初始化联系人列表
|
|||
|
self.init_contacts()
|
|||
|
|
|||
|
def init_contacts(self):
|
|||
|
"""初始化联系人列表"""
|
|||
|
self.contact_combo.clear()
|
|||
|
for wxid, versions in self.contact_versions.items():
|
|||
|
if versions: # 确保有版本数据
|
|||
|
contact_name = versions[0]['contact']['name'] # 使用第一个版本中的联系人名称
|
|||
|
self.contact_combo.addItem(contact_name, wxid) # 使用wxid作为用户数据
|
|||
|
|
|||
|
def on_contact_changed(self, index):
|
|||
|
"""联系人选择改变时的处理"""
|
|||
|
if index < 0:
|
|||
|
return
|
|||
|
|
|||
|
# 获取选中联系人的wxid
|
|||
|
wxid = self.contact_combo.currentData()
|
|||
|
versions = self.contact_versions.get(wxid, [])
|
|||
|
|
|||
|
# 更新版本选择框
|
|||
|
self.version_a_combo.clear()
|
|||
|
self.version_b_combo.clear()
|
|||
|
|
|||
|
contact_name = versions[0]['contact']['name']
|
|||
|
for version in versions:
|
|||
|
version_text = f"{contact_name} - 版本{version['version_number']} ({version['create_time']})"
|
|||
|
self.version_a_combo.addItem(version_text, version)
|
|||
|
self.version_b_combo.addItem(version_text, version)
|
|||
|
|
|||
|
# 默认选择最新的两个版本
|
|||
|
if len(versions) >= 2:
|
|||
|
self.version_a_combo.setCurrentIndex(len(versions) - 2)
|
|||
|
self.version_b_combo.setCurrentIndex(len(versions) - 1)
|
|||
|
|
|||
|
def add_compare_section(self, title, content_key):
|
|||
|
"""添加比较部分"""
|
|||
|
section = QWidget()
|
|||
|
layout = QVBoxLayout(section)
|
|||
|
|
|||
|
# 标题
|
|||
|
title_label = QLabel(title)
|
|||
|
title_label.setObjectName("title")
|
|||
|
layout.addWidget(title_label)
|
|||
|
|
|||
|
# 内容比较区域
|
|||
|
content_layout = QHBoxLayout()
|
|||
|
|
|||
|
# 版本A内容
|
|||
|
text_a = QTextEdit()
|
|||
|
text_a.setReadOnly(True)
|
|||
|
setattr(self, f"{content_key}_a", text_a)
|
|||
|
content_layout.addWidget(text_a)
|
|||
|
|
|||
|
# 版本B内容
|
|||
|
text_b = QTextEdit()
|
|||
|
text_b.setReadOnly(True)
|
|||
|
setattr(self, f"{content_key}_b", text_b)
|
|||
|
content_layout.addWidget(text_b)
|
|||
|
|
|||
|
layout.addLayout(content_layout)
|
|||
|
self.content_layout.addWidget(section)
|
|||
|
|
|||
|
def compare_versions(self):
|
|||
|
"""比较选中的两个版本"""
|
|||
|
if self.version_a_combo.currentIndex() < 0 or self.version_b_combo.currentIndex() < 0:
|
|||
|
return
|
|||
|
|
|||
|
version_a = self.version_a_combo.currentData()
|
|||
|
version_b = self.version_b_combo.currentData()
|
|||
|
|
|||
|
if version_a and version_b:
|
|||
|
self.compare_content("greeting", version_a, version_b)
|
|||
|
self.compare_content("wishes", version_a, version_b)
|
|||
|
self.compare_content("idioms", version_a, version_b)
|
|||
|
self.compare_content("image_prompt", version_a, version_b)
|
|||
|
|
|||
|
def compare_content(self, content_key, version_a, version_b):
|
|||
|
"""比较特定内容"""
|
|||
|
text_a = version_a.get(content_key, '')
|
|||
|
text_b = version_b.get(content_key, '')
|
|||
|
|
|||
|
# 获取文本框引用
|
|||
|
text_edit_a = getattr(self, f"{content_key}_a")
|
|||
|
text_edit_b = getattr(self, f"{content_key}_b")
|
|||
|
|
|||
|
# 清空文本框
|
|||
|
text_edit_a.clear()
|
|||
|
text_edit_b.clear()
|
|||
|
|
|||
|
# 计算差异
|
|||
|
differ = difflib.Differ()
|
|||
|
diff = list(differ.compare(text_a.splitlines(), text_b.splitlines()))
|
|||
|
|
|||
|
# 设置差异高亮格式
|
|||
|
add_format = QTextCharFormat()
|
|||
|
add_format.setBackground(QColor(200, 255, 200)) # 浅绿色背景
|
|||
|
|
|||
|
del_format = QTextCharFormat()
|
|||
|
del_format.setBackground(QColor(255, 200, 200)) # 浅红色背景
|
|||
|
|
|||
|
# 显示差异
|
|||
|
cursor_a = text_edit_a.textCursor()
|
|||
|
cursor_b = text_edit_b.textCursor()
|
|||
|
|
|||
|
for line in diff:
|
|||
|
if line.startswith('- '):
|
|||
|
cursor_a.insertText(line[2:] + '\n', del_format)
|
|||
|
cursor_b.insertText('\n')
|
|||
|
elif line.startswith('+ '):
|
|||
|
cursor_a.insertText('\n')
|
|||
|
cursor_b.insertText(line[2:] + '\n', add_format)
|
|||
|
else:
|
|||
|
cursor_a.insertText(line[2:] + '\n')
|
|||
|
cursor_b.insertText(line[2:] + '\n')
|
|||
|
|
|||
|
# 滚动到顶部
|
|||
|
text_edit_a.verticalScrollBar().setValue(0)
|
|||
|
text_edit_b.verticalScrollBar().setValue(0)
|
|||
|
|
|||
|
def apply_style(self):
|
|||
|
"""应用样式"""
|
|||
|
self.setStyleSheet("""
|
|||
|
QDialog {
|
|||
|
background-color: #F9F4E6;
|
|||
|
min-width: 800px;
|
|||
|
min-height: 600px;
|
|||
|
}
|
|||
|
QLabel {
|
|||
|
color: #333333;
|
|||
|
}
|
|||
|
QLabel#title {
|
|||
|
font-size: 18px;
|
|||
|
font-weight: bold;
|
|||
|
color: #D4341F;
|
|||
|
padding: 10px;
|
|||
|
}
|
|||
|
QLabel#version-label {
|
|||
|
font-size: 16px;
|
|||
|
font-weight: bold;
|
|||
|
color: #D4341F;
|
|||
|
padding: 5px;
|
|||
|
}
|
|||
|
QTextEdit {
|
|||
|
background-color: white;
|
|||
|
border: 1px solid #E8C06F;
|
|||
|
border-radius: 4px;
|
|||
|
padding: 8px;
|
|||
|
font-size: 14px;
|
|||
|
}
|
|||
|
QPushButton {
|
|||
|
background-color: #E8C06F;
|
|||
|
color: #333333;
|
|||
|
border: none;
|
|||
|
padding: 8px 16px;
|
|||
|
border-radius: 4px;
|
|||
|
min-width: 80px;
|
|||
|
}
|
|||
|
QPushButton:hover {
|
|||
|
background-color: #D4B05F;
|
|||
|
}
|
|||
|
QPushButton#close-btn {
|
|||
|
background-color: #D4341F;
|
|||
|
color: white;
|
|||
|
}
|
|||
|
QPushButton#close-btn:hover {
|
|||
|
background-color: #A61F14;
|
|||
|
}
|
|||
|
""")
|