This commit is contained in:
27942
2026-01-20 15:24:08 +08:00
parent 2cac92f9c5
commit d1bebfed68
135 changed files with 646 additions and 276 deletions

View File

@@ -11,7 +11,7 @@ from PyQt5.QtWidgets import (
QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,
QPushButton, QLabel, QLineEdit, QTextEdit, QFileDialog,
QTableWidget, QTableWidgetItem, QMessageBox, QDateTimeEdit,
QGroupBox, QCheckBox, QProgressBar
QGroupBox, QCheckBox, QProgressBar, QGridLayout
)
from PyQt5.QtCore import Qt, QThread, pyqtSignal, QDateTime
from PyQt5.QtGui import QFont
@@ -456,11 +456,14 @@ class MainWindow(QMainWindow):
self.worker_thread = None
self.configs = [] # 存储从Excel导入的配置
self.prepared_files = None # 存储通过"更新数据"找到的文件列表
self.running_total = 0
self.running_done = 0
self.init_ui()
def init_ui(self):
self.setWindowTitle("拼多多自动化发布工具")
self.setGeometry(100, 100, 1000, 800)
self.apply_styles()
# 创建中央部件
central_widget = QWidget()
@@ -468,7 +471,37 @@ class MainWindow(QMainWindow):
# 主布局
main_layout = QVBoxLayout()
main_layout.setContentsMargins(20, 20, 20, 20)
main_layout.setSpacing(14)
central_widget.setLayout(main_layout)
# 顶部标题区
header_layout = QHBoxLayout()
title_box = QVBoxLayout()
title_label = QLabel("拼多多自动化发布工具")
title_label.setObjectName("titleLabel")
subtitle_label = QLabel("配置导入 • 文件查找 • 批量上传")
subtitle_label.setObjectName("subtitleLabel")
title_box.addWidget(title_label)
title_box.addWidget(subtitle_label)
header_layout.addLayout(title_box)
header_layout.addStretch()
main_layout.addLayout(header_layout)
# 状态卡片区
status_layout = QHBoxLayout()
self.status_update_value = QLabel("未更新")
self.status_pending_value = QLabel("0")
self.status_running_value = QLabel("0")
update_card = self._build_status_card("更新状态", self.status_update_value)
pending_card = self._build_status_card("待执行", self.status_pending_value)
running_card = self._build_status_card("执行中", self.status_running_value)
status_layout.addWidget(update_card)
status_layout.addWidget(pending_card)
status_layout.addWidget(running_card)
main_layout.addLayout(status_layout)
# Excel导入区域
import_group = QGroupBox("Excel配置导入可选")
@@ -492,98 +525,70 @@ class MainWindow(QMainWindow):
# 配置输入区域
config_group = QGroupBox("配置信息")
config_layout = QVBoxLayout()
# 多多ID
h2 = QHBoxLayout()
h2.addWidget(QLabel("多多ID:"))
grid = QGridLayout()
grid.setHorizontalSpacing(12)
grid.setVerticalSpacing(10)
self.user_id_input = QLineEdit()
h2.addWidget(self.user_id_input)
config_layout.addLayout(h2)
# 序号
h3 = QHBoxLayout()
h3.addWidget(QLabel("序号:"))
self.index_input = QLineEdit()
h3.addWidget(self.index_input)
config_layout.addLayout(h3)
# 话题
h4 = QHBoxLayout()
h4.addWidget(QLabel("话题:"))
self.topic_input = QLineEdit()
h4.addWidget(self.topic_input)
config_layout.addLayout(h4)
# 定时发布
h5 = QHBoxLayout()
h5.addWidget(QLabel("定时发布:"))
self.schedule_datetime = QDateTimeEdit()
self.schedule_datetime.setCalendarPopup(True)
self.schedule_datetime.setDateTime(QDateTime.currentDateTime())
h5.addWidget(self.schedule_datetime)
config_layout.addLayout(h5)
# 达人链接
h6 = QHBoxLayout()
h6.addWidget(QLabel("达人链接:"))
self.url_input = QLineEdit()
h6.addWidget(self.url_input)
config_layout.addLayout(h6)
# 执行人
h7 = QHBoxLayout()
h7.addWidget(QLabel("执行人:"))
self.executor_input = QLineEdit()
h7.addWidget(self.executor_input)
config_layout.addLayout(h7)
grid.addWidget(QLabel("多多ID:"), 0, 0)
grid.addWidget(self.user_id_input, 0, 1)
grid.addWidget(QLabel("序号:"), 0, 2)
grid.addWidget(self.index_input, 0, 3)
grid.addWidget(QLabel("话题:"), 1, 0)
grid.addWidget(self.topic_input, 1, 1)
grid.addWidget(QLabel("定时发布:"), 1, 2)
grid.addWidget(self.schedule_datetime, 1, 3)
grid.addWidget(QLabel("达人链接:"), 2, 0)
grid.addWidget(self.url_input, 2, 1)
grid.addWidget(QLabel("执行人:"), 2, 2)
grid.addWidget(self.executor_input, 2, 3)
# 文件夹路径(最外层文件夹)
h8 = QHBoxLayout()
h8.addWidget(QLabel("资料文件夹路径:"))
grid.addWidget(QLabel("资料文件夹路径:"), 3, 0)
self.folder_path_input = QLineEdit()
# 设置默认值为桌面的"多多自动化发文"
default_path = get_default_folder_path()
self.folder_path_input.setPlaceholderText(f"留空则使用默认路径: {default_path}")
h8.addWidget(self.folder_path_input)
grid.addWidget(self.folder_path_input, 3, 1, 1, 2)
self.folder_browse_btn = QPushButton("浏览")
self.folder_browse_btn.setProperty("variant", "secondary")
self.folder_browse_btn.clicked.connect(self.browse_folder)
h8.addWidget(self.folder_browse_btn)
config_layout.addLayout(h8)
# 添加提示标签
grid.addWidget(self.folder_browse_btn, 3, 3)
tip_label = QLabel("提示:只需填写最外层文件夹路径,程序会自动查找子文件夹中的文件")
tip_label.setStyleSheet("color: #666; font-size: 10px;")
config_layout.addWidget(tip_label)
# 文件路径字段(用于单个文件或文件列表)
h8_1 = QHBoxLayout()
h8_1.addWidget(QLabel("文件路径:"))
self.file_path_input = QLineEdit()
self.file_path_input.setPlaceholderText("可选:填写单个文件路径或留空使用文件夹路径查找")
h8_1.addWidget(self.file_path_input)
self.file_browse_btn = QPushButton("浏览文件")
self.file_browse_btn.clicked.connect(self.browse_file)
h8_1.addWidget(self.file_browse_btn)
config_layout.addLayout(h8_1)
grid.addWidget(tip_label, 4, 0, 1, 4)
# 更新数据按钮
h8_2 = QHBoxLayout()
update_row = QHBoxLayout()
self.update_data_btn = QPushButton("更新数据")
self.update_data_btn.setStyleSheet("background-color: #2196F3; color: white; font-size: 12px; padding: 8px;")
self.update_data_btn.setProperty("variant", "primary")
self.update_data_btn.clicked.connect(self.update_data)
h8_2.addWidget(self.update_data_btn)
update_row.addWidget(self.update_data_btn)
self.update_status_label = QLabel("未更新")
self.update_status_label.setStyleSheet("color: #666; font-size: 10px;")
h8_2.addWidget(self.update_status_label)
h8_2.addStretch()
config_layout.addLayout(h8_2)
update_row.addWidget(self.update_status_label)
update_row.addStretch()
update_row_widget = QWidget()
update_row_widget.setLayout(update_row)
grid.addWidget(update_row_widget, 6, 0, 1, 4)
# 批量上传勾选框
h9 = QHBoxLayout()
self.batch_upload_checkbox = QCheckBox("批量上传(如果文件夹中有多个视频,将使用批量上传模式)")
self.batch_upload_checkbox.setChecked(False)
h9.addWidget(self.batch_upload_checkbox)
config_layout.addLayout(h9)
grid.addWidget(self.batch_upload_checkbox, 7, 0, 1, 4)
config_layout.addLayout(grid)
config_group.setLayout(config_layout)
main_layout.addWidget(config_group)
@@ -592,9 +597,9 @@ class MainWindow(QMainWindow):
self.table_group = QGroupBox("配置列表从Excel导入后显示可直接在表格中编辑")
table_layout = QVBoxLayout()
self.config_table = QTableWidget()
self.config_table.setColumnCount(8)
self.config_table.setColumnCount(9)
self.config_table.setHorizontalHeaderLabels([
'多多ID', '序号', '话题', '定时发布', '间隔时间(秒)', '达人链接', '执行人', '情况'
'多多ID', '序号', '话题', '定时发布', '间隔时间(秒)', '达人链接', '执行人', '情况', '文件路径'
])
self.config_table.horizontalHeader().setStretchLastSection(True)
# 设置表格可编辑
@@ -606,7 +611,7 @@ class MainWindow(QMainWindow):
# 执行按钮
self.execute_btn = QPushButton("开始上传")
self.execute_btn.setStyleSheet("background-color: #4CAF50; color: white; font-size: 14px; padding: 10px;")
self.execute_btn.setProperty("variant", "accent")
self.execute_btn.clicked.connect(self.execute_task)
main_layout.addWidget(self.execute_btn)
@@ -615,7 +620,7 @@ class MainWindow(QMainWindow):
log_layout = QVBoxLayout()
self.log_text = QTextEdit()
self.log_text.setReadOnly(True)
self.log_text.setFont(QFont("Consolas", 9))
self.log_text.setFont(QFont("Consolas", 10))
log_layout.addWidget(self.log_text)
log_group.setLayout(log_layout)
main_layout.addWidget(log_group)
@@ -629,6 +634,150 @@ class MainWindow(QMainWindow):
logger.remove()
logger.add(lambda msg: None) # 禁用默认输出通过信号在GUI中显示
def _build_status_card(self, title, value_label):
"""创建状态卡片"""
card = QWidget()
card.setObjectName("statusCard")
layout = QVBoxLayout(card)
layout.setContentsMargins(12, 10, 12, 10)
title_label = QLabel(title)
title_label.setObjectName("statusTitle")
value_label.setObjectName("statusValue")
layout.addWidget(title_label)
layout.addWidget(value_label)
return card
def set_status_cards(self, update_text=None, pending=None, running=None):
"""更新状态卡片显示"""
if update_text is not None:
self.status_update_value.setText(update_text)
if pending is not None:
self.status_pending_value.setText(str(pending))
if running is not None:
self.status_running_value.setText(str(running))
def set_running_progress(self, done, total):
"""更新执行中统计"""
self.running_done = done
self.running_total = total
if total > 0:
self.set_status_cards(running=f"{done}/{total}")
else:
self.set_status_cards(running="0")
def apply_styles(self):
"""应用统一的界面样式"""
self.setStyleSheet("""
QWidget {
font-family: "Microsoft YaHei";
font-size: 12px;
color: #1f1f1f;
background-color: #f6f7fb;
}
QGroupBox {
background-color: #ffffff;
border: 1px solid #e5e7eb;
border-radius: 10px;
margin-top: 14px;
}
QGroupBox::title {
subcontrol-origin: margin;
left: 12px;
padding: 0 6px;
color: #4b5563;
font-weight: 600;
}
QLabel {
color: #374151;
}
QLabel#titleLabel {
font-size: 20px;
font-weight: 700;
color: #111827;
background: transparent;
}
QLabel#subtitleLabel {
font-size: 12px;
color: #6b7280;
background: transparent;
}
QWidget#statusCard {
background-color: #ffffff;
border: 1px solid #e5e7eb;
border-radius: 10px;
}
QLabel#statusTitle {
font-size: 11px;
color: #6b7280;
}
QLabel#statusValue {
font-size: 16px;
font-weight: 700;
color: #111827;
}
QLineEdit, QDateTimeEdit, QTextEdit {
background-color: #ffffff;
border: 1px solid #d1d5db;
border-radius: 6px;
padding: 6px 8px;
}
QLineEdit:focus, QDateTimeEdit:focus, QTextEdit:focus {
border: 1px solid #3b82f6;
}
QPushButton {
border-radius: 6px;
padding: 8px 12px;
background-color: #e5e7eb;
color: #111827;
}
QPushButton[variant="secondary"] {
background-color: #f3f4f6;
color: #111827;
}
QPushButton[variant="primary"] {
background-color: #3b82f6;
color: #ffffff;
}
QPushButton[variant="accent"] {
background-color: #10b981;
color: #ffffff;
font-size: 14px;
padding: 10px 14px;
}
QPushButton:hover {
background-color: #d1d5db;
}
QPushButton[variant="primary"]:hover {
background-color: #2563eb;
}
QPushButton[variant="accent"]:hover {
background-color: #059669;
}
QTableWidget {
background-color: #ffffff;
border: 1px solid #e5e7eb;
border-radius: 8px;
gridline-color: #eef2f7;
}
QHeaderView::section {
background-color: #f3f4f6;
padding: 6px;
border: none;
font-weight: 600;
color: #374151;
}
QProgressBar {
border: 1px solid #e5e7eb;
border-radius: 6px;
background-color: #ffffff;
text-align: center;
}
QProgressBar::chunk {
background-color: #3b82f6;
border-radius: 6px;
}
""")
def browse_excel(self):
"""浏览Excel文件"""
file_path, _ = QFileDialog.getOpenFileName(
@@ -643,14 +792,6 @@ class MainWindow(QMainWindow):
if folder_path:
self.folder_path_input.setText(folder_path)
def browse_file(self):
"""浏览文件"""
file_path, _ = QFileDialog.getOpenFileName(
self, "选择文件", "", "所有文件 (*.*)"
)
if file_path:
self.file_path_input.setText(file_path)
def import_excel(self):
"""导入Excel配置文件"""
excel_path = self.excel_path_input.text()
@@ -685,7 +826,8 @@ class MainWindow(QMainWindow):
'间隔时间': int(row.get('间隔时间', 0)) if pd.notna(row.get('间隔时间')) else 0,
'达人链接': str(row.get('达人链接', '')),
'执行人': str(row.get('执行人', '')),
'情况': str(row.get('情况', '待执行'))
'情况': str(row.get('情况', '待执行')),
'文件路径': '' # 文件路径字段初始为空,通过更新数据按钮填充
}
self.configs.append(config)
@@ -694,6 +836,7 @@ class MainWindow(QMainWindow):
# 显示表格
self.table_group.setVisible(True)
self.set_status_cards(update_text="未更新", pending=len(self.configs))
QMessageBox.information(self, "成功", f"成功导入 {len(self.configs)} 条配置")
@@ -714,8 +857,13 @@ class MainWindow(QMainWindow):
self.config_table.setItem(row_idx, 5, QTableWidgetItem(str(config.get('达人链接', ''))))
self.config_table.setItem(row_idx, 6, QTableWidgetItem(str(config.get('执行人', ''))))
self.config_table.setItem(row_idx, 7, QTableWidgetItem(str(config.get('情况', '待执行'))))
# 文件路径列第8列索引为8如果配置中没有则显示空
file_path = config.get('文件路径', '')
self.config_table.setItem(row_idx, 8, QTableWidgetItem(str(file_path)))
self.config_table.resizeColumnsToContents()
# 未更新前,用配置行数作为待执行提示
self.set_status_cards(pending=self.config_table.rowCount())
def get_config_from_table(self, row_index=0):
"""从表格中获取指定行的配置数据(使用表格中修改后的值)"""
@@ -745,7 +893,8 @@ class MainWindow(QMainWindow):
'间隔时间': get_cell_int(row_index, 4, 0),
'达人链接': get_cell_text(row_index, 5),
'执行人': get_cell_text(row_index, 6),
'情况': get_cell_text(row_index, 7) or '待执行'
'情况': get_cell_text(row_index, 7) or '待执行',
'文件路径': get_cell_text(row_index, 8) # 第8列是文件路径
}
return config
@@ -767,36 +916,84 @@ class MainWindow(QMainWindow):
'达人链接': self.url_input.text(),
'执行人': self.executor_input.text(),
'文件夹路径': folder_path,
'文件路径': self.file_path_input.text().strip(),
'情况': '待执行'
}
def update_data(self):
"""更新数据:找出文件并保存"""
"""更新数据:找出文件并保存到表格的文件路径列(更新所有行)"""
try:
# 优先使用Excel导入的配置(如果存在)
# 检查是否有Excel导入的配置表格
if self.configs and self.config_table.rowCount() > 0:
config = self.get_config_from_table(0)
if not config:
QMessageBox.warning(self, "警告", "无法获取配置数据")
return
# 添加文件夹路径
# 获取文件夹路径
folder_path = self.folder_path_input.text().strip()
if not folder_path:
folder_path = get_default_folder_path()
config['文件夹路径'] = folder_path
config['文件路径'] = self.file_path_input.text().strip()
if not os.path.exists(folder_path):
QMessageBox.warning(self, "警告", f"文件夹路径不存在: {folder_path}")
return
self.log_text.append("=" * 50)
self.log_text.append("开始批量更新所有行的文件路径...")
self.log_text.append(f"共有 {self.config_table.rowCount()} 行需要更新")
# 遍历所有行,更新每行的文件路径
total_found = 0
for row_idx in range(self.config_table.rowCount()):
config = self.get_config_from_table(row_idx)
if not config:
self.log_text.append(f"{row_idx + 1} 行:无法获取配置数据,跳过")
continue
# 验证必填字段
if not config.get('多多id') or not config.get('序号'):
self.log_text.append(f"{row_idx + 1}多多ID或序号为空跳过")
continue
self.log_text.append(f"正在更新第 {row_idx + 1} 行的文件路径...")
self.log_text.append(f" 多多ID: {config.get('多多id')}, 序号: {config.get('序号')}")
# 查找该行对应的文件
found_files = self._find_files_for_config(config, folder_path)
if found_files:
# 将找到的文件路径拼接成字符串(多个文件用分号分隔)
file_paths_str = "; ".join([str(f['path']) for f in found_files])
self.config_table.setItem(row_idx, 8, QTableWidgetItem(file_paths_str))
# 同时更新self.configs中对应的配置
if row_idx < len(self.configs):
self.configs[row_idx]['文件路径'] = file_paths_str
video_count = sum(1 for f in found_files if f['path'].is_file() and any(f['path'].suffix.lower() in ['.mp4', '.avi', '.mov', '.mkv', '.flv', '.wmv', '.webm'] for ext in ['.mp4', '.avi', '.mov', '.mkv', '.flv', '.wmv', '.webm']))
self.log_text.append(f" ✓ 找到 {len(found_files)} 个文件({video_count} 个视频)")
total_found += len(found_files)
else:
# 清空文件路径列
self.config_table.setItem(row_idx, 8, QTableWidgetItem(""))
if row_idx < len(self.configs):
self.configs[row_idx]['文件路径'] = ""
self.log_text.append(f" ✗ 未找到匹配的文件")
self.log_text.append("=" * 50)
self.log_text.append(f"批量更新完成!共更新 {self.config_table.rowCount()} 行,找到 {total_found} 个文件")
self.update_status_label.setText(f"已更新: {self.config_table.rowCount()}行,{total_found}个文件")
self.update_status_label.setStyleSheet("color: #4CAF50; font-size: 10px;")
self.set_status_cards(update_text=f"已更新: {self.config_table.rowCount()}", pending=total_found)
QMessageBox.information(self, "成功", f"已更新所有行的文件路径!\n{self.config_table.rowCount()} 行,找到 {total_found} 个文件")
return
else:
# 没有表格,使用原来的逻辑(单个配置)
config = self.get_config()
current_row = -1 # 表示没有表格使用prepared_files
# 验证必填字段
if not config.get('多多id') or not config.get('序号'):
QMessageBox.warning(self, "警告", "请先填写多多ID和序号")
return
# 获取文件夹路径或文件路径
# 获取文件夹路径
folder_path = config.get('文件夹路径', '')
file_path = config.get('文件路径', '').strip()
if not folder_path:
folder_path = get_default_folder_path()
@@ -808,60 +1005,58 @@ class MainWindow(QMainWindow):
self.log_text.append("=" * 50)
self.log_text.append("开始更新数据,查找文件...")
# 如果指定了文件路径,直接使用该文件
if file_path and os.path.exists(file_path):
self.log_text.append(f"使用指定的文件路径: {file_path}")
path_obj = Path(file_path)
if path_obj.is_file():
# 判断是否为视频文件
video_extensions = ['.mp4', '.avi', '.mov', '.mkv', '.flv', '.wmv', '.webm']
is_video = any(path_obj.suffix.lower() == ext for ext in video_extensions)
self.prepared_files = [{
"url": config.get('达人链接', ''),
"user_id": config.get('多多id', ''),
"time_start": config.get('定时发布', '') if config.get('定时发布') else None,
"ht": config.get('话题', ''),
"index": config.get('序号', ''),
"path": path_obj
}]
file_type = "视频" if is_video else "文件"
self.log_text.append(f"找到 1 个{file_type}文件: {path_obj.name}")
self.update_status_label.setText(f"已更新: 1个{file_type}文件")
self.update_status_label.setStyleSheet("color: #4CAF50; font-size: 10px;")
QMessageBox.information(self, "成功", f"已找到 1 个{file_type}文件")
return
else:
QMessageBox.warning(self, "警告", "指定的路径不是文件")
return
# 在文件夹中查找文件
found_files = self._find_files_for_config(config, folder_path)
# 否则在文件夹中查找文件
index = config.get('序号', '')
video_extensions = ['.mp4', '.avi', '.mov', '.mkv', '.flv', '.wmv', '.webm']
found_files = []
if found_files:
self.prepared_files = found_files
video_extensions = ['.mp4', '.avi', '.mov', '.mkv', '.flv', '.wmv', '.webm']
video_count = sum(1 for f in found_files if f['path'].is_file() and any(f['path'].suffix.lower() == ext for ext in video_extensions))
folder_count = len(found_files) - video_count
self.log_text.append(f"更新完成!找到 {len(found_files)} 个文件/文件夹({video_count} 个视频,{folder_count} 个文件夹)")
self.update_status_label.setText(f"已更新: {len(found_files)}个文件")
self.update_status_label.setStyleSheet("color: #4CAF50; font-size: 10px;")
self.set_status_cards(update_text=f"已更新: {len(found_files)}个文件", pending=len(found_files))
QMessageBox.information(self, "成功", f"已找到 {len(found_files)} 个文件/文件夹")
else:
self.prepared_files = None
self.log_text.append("未找到匹配的文件")
self.update_status_label.setText("未找到文件")
self.update_status_label.setStyleSheet("color: #f44336; font-size: 10px;")
self.set_status_cards(update_text="未找到文件", pending=0)
QMessageBox.warning(self, "警告", "未找到匹配的文件")
except Exception as e:
error_msg = f"更新数据失败: {str(e)}"
self.log_text.append(error_msg)
QMessageBox.critical(self, "错误", error_msg)
logger.error(f"更新数据失败: {e}")
import traceback
traceback.print_exc()
def _find_files_for_config(self, config, folder_path):
"""根据配置查找文件(辅助方法)"""
found_files = []
index = config.get('序号', '')
video_extensions = ['.mp4', '.avi', '.mov', '.mkv', '.flv', '.wmv', '.webm']
try:
# 遍历最外层文件夹下的所有子文件夹
subdirs = [f for f in os.listdir(folder_path) if os.path.isdir(os.path.join(folder_path, f))]
self.log_text.append(f"在最外层文件夹下找到 {len(subdirs)} 个子文件夹")
# 找到匹配当前多多ID的文件夹
target_subdir = None
for subdir_name in subdirs:
if subdir_name == str(config.get('多多id')):
target_subdir = os.path.join(folder_path, subdir_name)
self.log_text.append(f"找到匹配的多多ID文件夹: {subdir_name}")
break
if not target_subdir:
QMessageBox.warning(self, "警告", f"未找到多多ID为 {config.get('多多id')} 的文件夹")
self.log_text.append(f"未找到匹配的多多ID文件夹")
return
return found_files
# 扫描该文件夹下的文件
items = os.listdir(target_subdir)
self.log_text.append(f"扫描文件夹: {os.path.basename(target_subdir)},共 {len(items)} 个项目")
for item_name in items:
item_path = os.path.join(target_subdir, item_name)
@@ -882,7 +1077,6 @@ class MainWindow(QMainWindow):
"index": str(index),
"path": path_obj
})
self.log_text.append(f"找到视频文件: {item_name}")
else:
# 如果是文件夹,可能是图片文件夹
found_files.append({
@@ -893,30 +1087,10 @@ class MainWindow(QMainWindow):
"index": str(index),
"path": path_obj
})
self.log_text.append(f"找到文件夹: {item_name}")
if found_files:
self.prepared_files = found_files
video_count = sum(1 for f in found_files if f['path'].is_file() and any(f['path'].suffix.lower() == ext for ext in video_extensions))
folder_count = len(found_files) - video_count
self.log_text.append(f"更新完成!找到 {len(found_files)} 个文件/文件夹({video_count} 个视频,{folder_count} 个文件夹)")
self.update_status_label.setText(f"已更新: {len(found_files)}个文件")
self.update_status_label.setStyleSheet("color: #4CAF50; font-size: 10px;")
QMessageBox.information(self, "成功", f"已找到 {len(found_files)} 个文件/文件夹")
else:
self.prepared_files = None
self.log_text.append("未找到匹配的文件")
self.update_status_label.setText("未找到文件")
self.update_status_label.setStyleSheet("color: #f44336; font-size: 10px;")
QMessageBox.warning(self, "警告", "未找到匹配的文件")
except Exception as e:
error_msg = f"更新数据失败: {str(e)}"
self.log_text.append(error_msg)
QMessageBox.critical(self, "错误", error_msg)
logger.error(f"更新数据失败: {e}")
import traceback
traceback.print_exc()
logger.error(f"查找文件失败: {e}")
return found_files
def execute_task(self):
"""执行任务"""
@@ -967,10 +1141,13 @@ class MainWindow(QMainWindow):
# 创建工作线程,传递预查找的文件列表
self.worker_thread = WorkerThread(config, is_batch_mode, self.prepared_files, self)
# 连接finished信号用于单个任务完成后显示弹窗
self.worker_thread.finished.connect(self.on_task_finished)
self.worker_thread.log_message.connect(self.log_text.append)
self.worker_thread.progress.connect(self.progress_bar.setValue)
self.worker_thread.start()
self.set_status_cards(pending=1)
self.set_running_progress(0, 1)
self.log_text.append("=" * 50)
mode_text = "批量上传" if is_batch_mode else "逐个上传"
@@ -980,7 +1157,7 @@ class MainWindow(QMainWindow):
self.log_text.append(f"开始执行任务({mode_text}模式)...")
def execute_batch_from_excel(self):
"""从Excel配置批量执行使用表格中修改后的配置"""
"""从Excel配置批量执行自动判断相同多多ID的mp4文件批量上传"""
# 获取文件夹路径,如果为空则使用默认路径
folder_path = self.folder_path_input.text().strip()
if not folder_path:
@@ -990,54 +1167,209 @@ class MainWindow(QMainWindow):
QMessageBox.warning(self, "警告", f"文件夹路径不存在: {folder_path}")
return
is_batch_mode = self.batch_upload_checkbox.isChecked()
# 从表格中获取配置(使用用户修改后的值)
# 从表格中获取所有配置(使用用户修改后的值)
if self.config_table.rowCount() == 0:
QMessageBox.warning(self, "警告", "配置列表为空请先导入Excel配置")
return
# 获取第一行的配置从表格中读取而不是从self.configs
config = self.get_config_from_table(0)
if not config:
QMessageBox.warning(self, "警告", "无法获取配置数据")
self.log_text.append("=" * 50)
self.log_text.append("开始分析配置,准备批量上传...")
# 收集所有配置及其对应的文件
all_configs_with_files = []
video_extensions = ['.mp4', '.avi', '.mov', '.mkv', '.flv', '.wmv', '.webm']
for row_idx in range(self.config_table.rowCount()):
config = self.get_config_from_table(row_idx)
if not config:
continue
# 验证必填字段
if not config.get('多多id') or not config.get('序号'):
self.log_text.append(f"{row_idx + 1}多多ID或序号为空跳过")
continue
# 添加文件夹路径
config['文件夹路径'] = folder_path
# 从文件路径列读取文件路径
file_path_str = config.get('文件路径', '').strip()
if file_path_str:
# 文件路径可能用分号分隔(多个文件)
file_paths = [p.strip() for p in file_path_str.split(';') if p.strip()]
files = []
for fp in file_paths:
if os.path.exists(fp):
path_obj = Path(fp)
files.append({
"url": config.get('达人链接', ''),
"user_id": config.get('多多id', ''),
"time_start": config.get('定时发布', '') if config.get('定时发布') else None,
"ht": config.get('话题', ''),
"index": config.get('序号', ''),
"path": path_obj
})
if files:
all_configs_with_files.append({
'config': config,
'files': files,
'row_idx': row_idx
})
self.log_text.append(f"{row_idx + 1} 行:从文件路径列读取到 {len(files)} 个文件")
else:
# 如果文件路径列为空,尝试查找文件
self.log_text.append(f"{row_idx + 1} 行:文件路径列为空,尝试查找文件...")
found_files = self._find_files_for_config(config, folder_path)
if found_files:
all_configs_with_files.append({
'config': config,
'files': found_files,
'row_idx': row_idx
})
self.log_text.append(f"{row_idx + 1} 行:找到 {len(found_files)} 个文件")
if not all_configs_with_files:
QMessageBox.warning(self, "警告", "未找到任何文件,请先点击'更新数据'按钮")
return
total_tasks = sum(len(item['files']) for item in all_configs_with_files)
pending_tasks = total_tasks
self.set_status_cards(pending=pending_tasks)
self.set_running_progress(0, total_tasks)
# 添加文件夹路径
config['文件夹路径'] = folder_path
# 按多多ID分组
from collections import defaultdict
grouped_by_user_id = defaultdict(list)
for item in all_configs_with_files:
user_id = item['config'].get('多多id', '')
grouped_by_user_id[user_id].append(item)
# 检查是否勾选了批量上传
# 如果已经更新了数据,根据预查找的文件判断是否为批量上传
if self.prepared_files:
video_extensions = ['.mp4', '.avi', '.mov', '.mkv', '.flv', '.wmv', '.webm']
video_files = [f for f in self.prepared_files if f['path'].is_file() and any(f['path'].suffix.lower() == ext for ext in video_extensions)]
if is_batch_mode and len(video_files) > 1:
self.log_text.append(f"检测到 {len(video_files)} 个视频文件,使用批量上传模式...")
elif is_batch_mode and len(video_files) <= 1:
self.log_text.append(f"只找到 {len(video_files)} 个视频文件,将使用单个上传模式...")
is_batch_mode = False
elif not is_batch_mode:
self.log_text.append(f"使用单个上传模式...")
self.log_text.append("=" * 50)
self.log_text.append(f"按多多ID分组{len(grouped_by_user_id)} 个不同的多多ID")
# 禁用按钮
self.execute_btn.setEnabled(False)
self.progress_bar.setVisible(True)
self.progress_bar.setValue(0)
self.set_status_cards(running=1)
# 创建工作线程,传递预查找的文件列表
self.worker_thread = WorkerThread(config, is_batch_mode, self.prepared_files, self)
self.worker_thread.finished.connect(self.on_task_finished)
self.worker_thread.log_message.connect(self.log_text.append)
self.worker_thread.progress.connect(self.progress_bar.setValue)
self.worker_thread.start()
# 处理每个多多ID组
total_processed = 0
for user_id, items in grouped_by_user_id.items():
self.log_text.append(f"\n处理多多ID: {user_id},共 {len(items)} 个配置")
# 收集该多多ID下的所有文件
all_files = []
for item in items:
all_files.extend(item['files'])
# 分离视频文件和图片文件夹
video_files = [f for f in all_files if f['path'].is_file() and any(f['path'].suffix.lower() == ext for ext in video_extensions)]
image_folders = [f for f in all_files if f['path'].is_dir()]
self.log_text.append(f" 视频文件: {len(video_files)}")
self.log_text.append(f" 图片文件夹: {len(image_folders)}")
# 使用第一个配置创建Pdd实例因为同一个多多ID配置应该相同
first_config = items[0]['config']
pdd = Pdd(
url=first_config.get('达人链接', ''),
user_id=user_id,
time_start=first_config.get('定时发布', '') if first_config.get('定时发布') else None,
ht=first_config.get('话题', ''),
index=first_config.get('序号', ''),
title=first_config.get('标题', None)
)
# 第一步:如果有多个视频文件(>1批量上传所有视频
if len(video_files) > 1:
# 检查是否都是mp4文件
all_mp4 = all(f['path'].suffix.lower() == '.mp4' for f in video_files)
if all_mp4:
self.log_text.append(f" ✓ 检测到 {len(video_files)} 个mp4文件批量上传所有视频action1方法")
else:
self.log_text.append(f" ✓ 检测到 {len(video_files)} 个视频文件批量上传所有视频action1方法")
# 批量上传所有视频
self.worker_thread = WorkerThread(first_config, True, video_files, self)
# 不连接finished信号避免每个任务完成就弹窗
self.worker_thread.log_message.connect(self.log_text.append)
self.worker_thread.progress.connect(self.progress_bar.setValue)
self.worker_thread.start()
# 等待完成
self.worker_thread.wait()
total_processed += len(video_files)
pending_tasks = max(pending_tasks - len(video_files), 0)
self.set_status_cards(pending=pending_tasks)
self.set_running_progress(total_processed, total_tasks)
self.log_text.append(f" ✓ 批量上传 {len(video_files)} 个视频完成")
elif len(video_files) == 1:
# 只有1个视频单个上传
self.log_text.append(f" → 只有1个视频文件单个上传")
self.worker_thread = WorkerThread(first_config, False, video_files, self)
# 不连接finished信号避免每个任务完成就弹窗
self.worker_thread.log_message.connect(self.log_text.append)
self.worker_thread.progress.connect(self.progress_bar.setValue)
self.worker_thread.start()
self.worker_thread.wait()
total_processed += len(video_files)
pending_tasks = max(pending_tasks - len(video_files), 0)
self.set_status_cards(pending=pending_tasks)
self.set_running_progress(total_processed, total_tasks)
self.log_text.append(f" ✓ 单个视频上传完成")
# 第二步:如果有图片文件夹,逐个上传图片
if image_folders:
self.log_text.append(f" → 开始逐个上传 {len(image_folders)} 个图片文件夹")
for idx, img_folder in enumerate(image_folders, 1):
# 找到该图片文件夹对应的配置(通过序号匹配)
folder_index = img_folder.get('index', '')
matching_config = None
for item in items:
if item['config'].get('序号', '') == folder_index:
matching_config = item['config']
break
# 如果找不到匹配的配置,使用第一个配置
if not matching_config:
matching_config = first_config
self.log_text.append(f" 上传第 {idx}/{len(image_folders)} 个图片文件夹(序号: {folder_index}")
pdd_img = Pdd(
url=matching_config.get('达人链接', ''),
user_id=user_id,
time_start=matching_config.get('定时发布', '') if matching_config.get('定时发布') else None,
ht=matching_config.get('话题', ''),
index=folder_index,
title=matching_config.get('标题', None)
)
self.worker_thread = WorkerThread(matching_config, False, [img_folder], self)
# 不连接finished信号避免每个任务完成就弹窗
self.worker_thread.log_message.connect(self.log_text.append)
self.worker_thread.progress.connect(self.progress_bar.setValue)
self.worker_thread.start()
self.worker_thread.wait()
total_processed += 1
pending_tasks = max(pending_tasks - 1, 0)
self.set_status_cards(pending=pending_tasks)
self.set_running_progress(total_processed, total_tasks)
self.log_text.append(f" ✓ 图片文件夹 {idx} 上传完成")
self.log_text.append(f" ✓ 所有图片文件夹上传完成")
self.progress_bar.setValue(100)
self.log_text.append("=" * 50)
mode_text = "批量上传" if is_batch_mode else "逐个上传"
if self.prepared_files:
self.log_text.append(f"开始执行任务({mode_text}模式,使用预查找的文件列表)...")
else:
self.log_text.append(f"开始执行任务({mode_text}模式)...")
self.log_text.append(f"使用配置 - 多多ID: {config.get('多多id')}, 序号: {config.get('序号')}, 话题: {config.get('话题')}")
self.log_text.append(f"所有任务执行完成!共处理 {total_processed} 个文件/文件夹")
self.execute_btn.setEnabled(True)
self.set_running_progress(0, 0)
self.set_status_cards(pending=0)
# 所有任务完成后,显示完成弹窗
QMessageBox.information(self, "任务完成", f"所有任务执行完成!\n共处理 {total_processed} 个文件/文件夹")
def count_videos_in_folder(self, folder_path, index):
"""统计文件夹中匹配序号的视频文件数量与main.py逻辑一致"""
@@ -1076,6 +1408,8 @@ class MainWindow(QMainWindow):
def on_task_finished(self, success, message):
"""任务完成回调"""
self.progress_bar.setValue(100)
self.set_running_progress(0, 0)
self.set_status_cards(pending=0)
if success:
QMessageBox.information(self, "成功", message)
@@ -1115,3 +1449,4 @@ def main():
if __name__ == '__main__':
main()
# docker run honeygain/honeygain -tou-accept -email ddrwode1@gmail.com -pass 040828cjj -device DEVICE_NAME

38
main.py
View File

@@ -24,8 +24,36 @@ class Pdd:
self.user_profile_url_template = None # 用户信息URL模板
self.title = title
self.ht = ht
self.ht = self._format_topic(ht) # 格式化话题
self.index = index
def _format_topic(self, topic_str):
"""
格式化话题:将"拍出氛围感-好看照片分享"转换为"#拍出氛围感 #好看照片分享"
Args:
topic_str: 原始话题字符串,可能包含"-"分隔符
Returns:
格式化后的话题字符串,每个部分前加"#"
"""
if not topic_str:
return ""
# 按"-"分割话题
parts = [part.strip() for part in topic_str.split("-") if part.strip()]
# 为每个部分添加"#"
formatted_parts = []
for part in parts:
# 如果部分已经以"#"开头,不再添加
if part.startswith("#"):
formatted_parts.append(part)
else:
formatted_parts.append(f"#{part}")
# 用空格连接
return " ".join(formatted_parts)
def create_page(self):
co = ChromiumOptions()
@@ -835,7 +863,9 @@ class Pdd:
try:
video_path = video_info["path"]
video_name = video_path.name
video_ht = video_info.get("ht", self.ht)
# 格式化话题(如果还没有格式化)
raw_ht = video_info.get("ht", self.ht)
video_ht = self._format_topic(raw_ht) if raw_ht else self.ht
video_time_start = video_info.get("time_start", self.time_start)
video_url = video_info.get("url", self.url)
@@ -924,7 +954,9 @@ class Pdd:
# 1. 输入视频描述
logger.info(f" 步骤1: 输入视频描述...")
try:
desc_text = video_name.split(".")[0].split("-")[-1] + video_ht
# 格式化话题(如果还没有格式化)
formatted_ht = self._format_topic(video_ht) if video_ht else ""
desc_text = video_name.split(".")[0].split("-")[-1] + formatted_ht
logger.info(f" 描述文本: {desc_text[:50]}...")
desc_inputs = video_container.eles('x://*[starts-with(@id, "magicdomid")]')
if desc_inputs:

View File

@@ -8,5 +8,5 @@
"top_topics_and_observing_domains": [ ]
} ],
"hex_encoded_hmac_key": "434BF7DBD7DA573B45E0A11AD9045A61B6221D14AE2F9A341E2FEF659AF071F6",
"next_scheduled_calculation_time": "13413450070590344"
"next_scheduled_calculation_time": "13413450070590402"
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 109 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 98 KiB

Binary file not shown.

Binary file not shown.

View File

@@ -1,3 +1,3 @@
2026/01/20-11:44:57.801 9844 Reusing MANIFEST C:\Users\27942\Desktop\codesk\haha\user\user_data\Default\Extension State/MANIFEST-000001
2026/01/20-11:44:57.803 9844 Recovering log #3
2026/01/20-11:44:57.803 9844 Reusing old log C:\Users\27942\Desktop\codesk\haha\user\user_data\Default\Extension State/000003.log
2026/01/20-15:00:02.034 2974 Reusing MANIFEST C:\Users\27942\Desktop\codesk\haha\user\user_data\Default\Extension State/MANIFEST-000001
2026/01/20-15:00:02.035 2974 Recovering log #3
2026/01/20-15:00:02.035 2974 Reusing old log C:\Users\27942\Desktop\codesk\haha\user\user_data\Default\Extension State/000003.log

View File

@@ -1,3 +1,3 @@
2026/01/20-11:38:03.001 1990 Reusing MANIFEST C:\Users\27942\Desktop\codesk\haha\user\user_data\Default\Extension State/MANIFEST-000001
2026/01/20-11:38:03.002 1990 Recovering log #3
2026/01/20-11:38:03.004 1990 Reusing old log C:\Users\27942\Desktop\codesk\haha\user\user_data\Default\Extension State/000003.log
2026/01/20-13:46:23.475 4ac8 Reusing MANIFEST C:\Users\27942\Desktop\codesk\haha\user\user_data\Default\Extension State/MANIFEST-000001
2026/01/20-13:46:23.476 4ac8 Recovering log #3
2026/01/20-13:46:23.477 4ac8 Reusing old log C:\Users\27942\Desktop\codesk\haha\user\user_data\Default\Extension State/000003.log

Binary file not shown.

View File

@@ -1,3 +1,3 @@
2026/01/20-11:44:58.548 9a04 Reusing MANIFEST C:\Users\27942\Desktop\codesk\haha\user\user_data\Default\File System\Origins/MANIFEST-000001
2026/01/20-11:44:58.549 9a04 Recovering log #6
2026/01/20-11:44:58.549 9a04 Reusing old log C:\Users\27942\Desktop\codesk\haha\user\user_data\Default\File System\Origins/000006.log
2026/01/20-15:00:02.654 d04 Reusing MANIFEST C:\Users\27942\Desktop\codesk\haha\user\user_data\Default\File System\Origins/MANIFEST-000001
2026/01/20-15:00:02.654 d04 Recovering log #6
2026/01/20-15:00:02.655 d04 Reusing old log C:\Users\27942\Desktop\codesk\haha\user\user_data\Default\File System\Origins/000006.log

View File

@@ -1,3 +1,3 @@
2026/01/20-11:38:03.788 3e60 Reusing MANIFEST C:\Users\27942\Desktop\codesk\haha\user\user_data\Default\File System\Origins/MANIFEST-000001
2026/01/20-11:38:03.789 3e60 Recovering log #6
2026/01/20-11:38:03.790 3e60 Reusing old log C:\Users\27942\Desktop\codesk\haha\user\user_data\Default\File System\Origins/000006.log
2026/01/20-13:46:24.016 4ac8 Reusing MANIFEST C:\Users\27942\Desktop\codesk\haha\user\user_data\Default\File System\Origins/MANIFEST-000001
2026/01/20-13:46:24.016 4ac8 Recovering log #6
2026/01/20-13:46:24.017 4ac8 Reusing old log C:\Users\27942\Desktop\codesk\haha\user\user_data\Default\File System\Origins/000006.log

View File

@@ -1,3 +1,3 @@
2026/01/20-11:45:04.150 5350 Reusing MANIFEST C:\Users\27942\Desktop\codesk\haha\user\user_data\Default\GCM Store\Encryption/MANIFEST-000001
2026/01/20-11:45:04.150 5350 Recovering log #3
2026/01/20-11:45:04.151 5350 Reusing old log C:\Users\27942\Desktop\codesk\haha\user\user_data\Default\GCM Store\Encryption/000003.log
2026/01/20-15:00:08.336 880c Reusing MANIFEST C:\Users\27942\Desktop\codesk\haha\user\user_data\Default\GCM Store\Encryption/MANIFEST-000001
2026/01/20-15:00:08.337 880c Recovering log #3
2026/01/20-15:00:08.337 880c Reusing old log C:\Users\27942\Desktop\codesk\haha\user\user_data\Default\GCM Store\Encryption/000003.log

View File

@@ -1,3 +1,3 @@
2026/01/20-11:38:09.362 349c Reusing MANIFEST C:\Users\27942\Desktop\codesk\haha\user\user_data\Default\GCM Store\Encryption/MANIFEST-000001
2026/01/20-11:38:09.364 349c Recovering log #3
2026/01/20-11:38:09.365 349c Reusing old log C:\Users\27942\Desktop\codesk\haha\user\user_data\Default\GCM Store\Encryption/000003.log
2026/01/20-13:46:29.475 2adc Reusing MANIFEST C:\Users\27942\Desktop\codesk\haha\user\user_data\Default\GCM Store\Encryption/MANIFEST-000001
2026/01/20-13:46:29.476 2adc Recovering log #3
2026/01/20-13:46:29.476 2adc Reusing old log C:\Users\27942\Desktop\codesk\haha\user\user_data\Default\GCM Store\Encryption/000003.log

View File

@@ -1,3 +1,3 @@
2026/01/20-11:45:04.066 5350 Reusing MANIFEST C:\Users\27942\Desktop\codesk\haha\user\user_data\Default\GCM Store/MANIFEST-000001
2026/01/20-11:45:04.066 5350 Recovering log #3
2026/01/20-11:45:04.067 5350 Reusing old log C:\Users\27942\Desktop\codesk\haha\user\user_data\Default\GCM Store/000003.log
2026/01/20-15:00:08.249 880c Reusing MANIFEST C:\Users\27942\Desktop\codesk\haha\user\user_data\Default\GCM Store/MANIFEST-000001
2026/01/20-15:00:08.250 880c Recovering log #3
2026/01/20-15:00:08.250 880c Reusing old log C:\Users\27942\Desktop\codesk\haha\user\user_data\Default\GCM Store/000003.log

View File

@@ -1,3 +1,3 @@
2026/01/20-11:38:09.287 349c Reusing MANIFEST C:\Users\27942\Desktop\codesk\haha\user\user_data\Default\GCM Store/MANIFEST-000001
2026/01/20-11:38:09.287 349c Recovering log #3
2026/01/20-11:38:09.288 349c Reusing old log C:\Users\27942\Desktop\codesk\haha\user\user_data\Default\GCM Store/000003.log
2026/01/20-13:46:29.403 2adc Reusing MANIFEST C:\Users\27942\Desktop\codesk\haha\user\user_data\Default\GCM Store/MANIFEST-000001
2026/01/20-13:46:29.404 2adc Recovering log #3
2026/01/20-13:46:29.404 2adc Reusing old log C:\Users\27942\Desktop\codesk\haha\user\user_data\Default\GCM Store/000003.log

Binary file not shown.

View File

@@ -1,3 +1,3 @@
2026/01/20-11:45:10.721 9a04 Reusing MANIFEST C:\Users\27942\Desktop\codesk\haha\user\user_data\Default\IndexedDB\https_mcn.pinduoduo.com_0.indexeddb.leveldb/MANIFEST-000001
2026/01/20-11:45:10.722 9a04 Recovering log #11
2026/01/20-11:45:10.734 9a04 Reusing old log C:\Users\27942\Desktop\codesk\haha\user\user_data\Default\IndexedDB\https_mcn.pinduoduo.com_0.indexeddb.leveldb/000011.log
2026/01/20-15:00:14.224 1b20 Reusing MANIFEST C:\Users\27942\Desktop\codesk\haha\user\user_data\Default\IndexedDB\https_mcn.pinduoduo.com_0.indexeddb.leveldb/MANIFEST-000001
2026/01/20-15:00:14.225 1b20 Recovering log #15
2026/01/20-15:00:14.228 1b20 Reusing old log C:\Users\27942\Desktop\codesk\haha\user\user_data\Default\IndexedDB\https_mcn.pinduoduo.com_0.indexeddb.leveldb/000015.log

View File

@@ -1,3 +1,3 @@
2026/01/20-11:45:07.804 9a04 Reusing MANIFEST C:\Users\27942\Desktop\codesk\haha\user\user_data\Default\IndexedDB\https_mcn.pinduoduo.com_0.indexeddb.leveldb/MANIFEST-000001
2026/01/20-11:45:07.804 9a04 Recovering log #11
2026/01/20-11:45:07.818 9a04 Reusing old log C:\Users\27942\Desktop\codesk\haha\user\user_data\Default\IndexedDB\https_mcn.pinduoduo.com_0.indexeddb.leveldb/000011.log
2026/01/20-15:00:11.696 2974 Reusing MANIFEST C:\Users\27942\Desktop\codesk\haha\user\user_data\Default\IndexedDB\https_mcn.pinduoduo.com_0.indexeddb.leveldb/MANIFEST-000001
2026/01/20-15:00:11.697 2974 Recovering log #15
2026/01/20-15:00:11.698 2974 Reusing old log C:\Users\27942\Desktop\codesk\haha\user\user_data\Default\IndexedDB\https_mcn.pinduoduo.com_0.indexeddb.leveldb/000015.log

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

View File

@@ -1,3 +1,3 @@
2026/01/20-11:44:57.684 99c8 Reusing MANIFEST C:\Users\27942\Desktop\codesk\haha\user\user_data\Default\Local Storage\leveldb/MANIFEST-000001
2026/01/20-11:44:57.688 99c8 Recovering log #7
2026/01/20-11:44:57.697 99c8 Reusing old log C:\Users\27942\Desktop\codesk\haha\user\user_data\Default\Local Storage\leveldb/000007.log
2026/01/20-15:00:01.875 288c Reusing MANIFEST C:\Users\27942\Desktop\codesk\haha\user\user_data\Default\Local Storage\leveldb/MANIFEST-000001
2026/01/20-15:00:01.879 288c Recovering log #7
2026/01/20-15:00:01.884 288c Reusing old log C:\Users\27942\Desktop\codesk\haha\user\user_data\Default\Local Storage\leveldb/000007.log

View File

@@ -1,3 +1,3 @@
2026/01/20-11:38:02.888 8da8 Reusing MANIFEST C:\Users\27942\Desktop\codesk\haha\user\user_data\Default\Local Storage\leveldb/MANIFEST-000001
2026/01/20-11:38:02.894 8da8 Recovering log #7
2026/01/20-11:38:02.901 8da8 Reusing old log C:\Users\27942\Desktop\codesk\haha\user\user_data\Default\Local Storage\leveldb/000007.log
2026/01/20-13:46:23.318 674 Reusing MANIFEST C:\Users\27942\Desktop\codesk\haha\user\user_data\Default\Local Storage\leveldb/MANIFEST-000001
2026/01/20-13:46:23.322 674 Recovering log #7
2026/01/20-13:46:23.330 674 Reusing old log C:\Users\27942\Desktop\codesk\haha\user\user_data\Default\Local Storage\leveldb/000007.log

File diff suppressed because one or more lines are too long

View File

@@ -1 +1 @@
{"sts":[{"expiry":1779765891.342828,"host":"dERK8Ko+SPll3fI4ktOXyGETlPtRvoHIttvQhh3OR68=","mode":"force-https","sts_include_subdomains":true,"sts_observed":1768879491.342831},{"expiry":1779259199.044976,"host":"myxca24Fg7L/IgePD/QeLaUxbyYNmJdOyLPYvlVtjPE=","mode":"force-https","sts_include_subdomains":true,"sts_observed":1768372799.044977},{"expiry":1800416698.125972,"host":"5EdUoB7YUY9zZV+2DkgVXgho8WUvp+D+6KpeUOhNQIM=","mode":"force-https","sts_include_subdomains":false,"sts_observed":1768880698.125974},{"expiry":1800416698.182832,"host":"8/RrMmQlCD2Gsp14wUCE1P8r7B2C5+yE0+g79IPyRsc=","mode":"force-https","sts_include_subdomains":true,"sts_observed":1768880698.182834}],"version":2}
{"sts":[{"expiry":1779774321.330876,"host":"dERK8Ko+SPll3fI4ktOXyGETlPtRvoHIttvQhh3OR68=","mode":"force-https","sts_include_subdomains":true,"sts_observed":1768887921.33088},{"expiry":1779259199.044976,"host":"myxca24Fg7L/IgePD/QeLaUxbyYNmJdOyLPYvlVtjPE=","mode":"force-https","sts_include_subdomains":true,"sts_observed":1768372799.044977},{"expiry":1800428402.512637,"host":"5EdUoB7YUY9zZV+2DkgVXgho8WUvp+D+6KpeUOhNQIM=","mode":"force-https","sts_include_subdomains":false,"sts_observed":1768892402.512638},{"expiry":1800428402.39833,"host":"8/RrMmQlCD2Gsp14wUCE1P8r7B2C5+yE0+g79IPyRsc=","mode":"force-https","sts_include_subdomains":true,"sts_observed":1768892402.398333}],"version":2}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,3 +1,3 @@
2026/01/20-11:44:57.531 301c Reusing MANIFEST C:\Users\27942\Desktop\codesk\haha\user\user_data\Default\Service Worker\Database/MANIFEST-000001
2026/01/20-11:44:57.532 301c Recovering log #3
2026/01/20-11:44:57.533 301c Reusing old log C:\Users\27942\Desktop\codesk\haha\user\user_data\Default\Service Worker\Database/000003.log
2026/01/20-15:00:01.795 6014 Reusing MANIFEST C:\Users\27942\Desktop\codesk\haha\user\user_data\Default\Service Worker\Database/MANIFEST-000001
2026/01/20-15:00:01.796 6014 Recovering log #3
2026/01/20-15:00:01.797 6014 Reusing old log C:\Users\27942\Desktop\codesk\haha\user\user_data\Default\Service Worker\Database/000003.log

View File

@@ -1,3 +1,3 @@
2026/01/20-11:38:02.715 2428 Reusing MANIFEST C:\Users\27942\Desktop\codesk\haha\user\user_data\Default\Service Worker\Database/MANIFEST-000001
2026/01/20-11:38:02.717 2428 Recovering log #3
2026/01/20-11:38:02.719 2428 Reusing old log C:\Users\27942\Desktop\codesk\haha\user\user_data\Default\Service Worker\Database/000003.log
2026/01/20-13:46:47.829 8278 Reusing MANIFEST C:\Users\27942\Desktop\codesk\haha\user\user_data\Default\Service Worker\Database/MANIFEST-000001
2026/01/20-13:46:47.837 8278 Recovering log #3
2026/01/20-13:46:47.839 8278 Reusing old log C:\Users\27942\Desktop\codesk\haha\user\user_data\Default\Service Worker\Database/000003.log

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More