pingtai_test/picture_upload.py

498 lines
18 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import os
import sys
import requests
from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,
QLabel, QLineEdit, QComboBox, QPushButton, QFileDialog,
QGroupBox, QDateTimeEdit, QDoubleSpinBox, QSpinBox, QTextEdit,
QTabWidget, QScrollArea, QMessageBox, QCalendarWidget,QGridLayout)
from PyQt5.QtCore import Qt, QDateTime, QTimer
from PyQt5.QtGui import QFont, QIcon
class NoWheelComboBox(QComboBox):
def wheelEvent(self, event):
event.ignore()
class NoWheelSpinBox(QSpinBox):
def wheelEvent(self, event):
event.ignore()
class NoWheelDoubleSpinBox(QDoubleSpinBox):
def wheelEvent(self, event):
event.ignore()
class ImageUploaderApp(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("图片批量上传工具")
self.setWindowIcon(QIcon("upload_icon.png")) # 替换为您自己的图标或删除此行
self.setGeometry(100, 100, 850, 650)
# 初始化参数
self.base_url = "http://pms.dtyx.net:9158/image"
self.default_part_id = "a3b4b81c5973a1895a4d95d50dd8351c"
self.file_paths = []
self.upload_in_progress = False
# 初始化UI
self.init_ui()
def init_ui(self):
# 创建主窗口部件
main_widget = QWidget()
self.setCentralWidget(main_widget)
# 主布局
main_layout = QVBoxLayout()
main_widget.setLayout(main_layout)
# 创建标签页
tab_widget = QTabWidget()
main_layout.addWidget(tab_widget)
# 基本参数标签页
basic_tab = QWidget()
tab_widget.addTab(basic_tab, "基本参数")
self.setup_basic_tab(basic_tab)
# 高级参数标签页
advanced_tab = QWidget()
tab_widget.addTab(advanced_tab, "高级参数")
self.setup_advanced_tab(advanced_tab)
# 底部按钮区域
button_layout = QHBoxLayout()
self.upload_btn = QPushButton("开始上传")
self.upload_btn.setFont(QFont("Arial", 12, QFont.Bold))
self.upload_btn.setStyleSheet("background-color: #4CAF50; color: white; padding: 10px;")
self.upload_btn.clicked.connect(self.start_upload)
self.clear_btn = QPushButton("清空选择")
self.clear_btn.setFont(QFont("Arial", 12))
self.clear_btn.setStyleSheet("background-color: #f44336; color: white; padding: 10px;")
self.clear_btn.clicked.connect(self.clear_selection)
button_layout.addWidget(self.upload_btn)
button_layout.addWidget(self.clear_btn)
main_layout.addLayout(button_layout)
# 日志输出
self.log_text = QTextEdit()
self.log_text.setReadOnly(True)
self.log_text.setFont(QFont("Consolas", 10))
self.log_text.setStyleSheet("background-color: #f5f5f5;")
main_layout.addWidget(self.log_text)
def setup_basic_tab(self, tab):
layout = QVBoxLayout()
tab.setLayout(layout)
# Part ID设置
part_id_group = QGroupBox("部件ID设置")
part_id_layout = QVBoxLayout()
self.part_id_input = QLineEdit(self.default_part_id)
part_id_layout.addWidget(QLabel("部件ID:"))
part_id_layout.addWidget(self.part_id_input)
part_id_group.setLayout(part_id_layout)
layout.addWidget(part_id_group)
# 图片源选择
source_group = QGroupBox("图片源设置")
source_layout = QVBoxLayout()
self.source_combo = NoWheelComboBox()
self.source_combo.addItems(["图像采集", "外部工作", "内部工作", "防雷工作"])
self.source_combo.setCurrentText("内部工作")
source_layout.addWidget(QLabel("图片源类型:"))
source_layout.addWidget(self.source_combo)
source_group.setLayout(source_layout)
layout.addWidget(source_group)
# 图片类型选择
type_group = QGroupBox("图片类型设置")
type_layout = QVBoxLayout()
self.type_combo = NoWheelComboBox()
self.type_combo.addItems(["", "缺陷影像", "典型影像", "其他影像"])
type_layout.addWidget(QLabel("图片类型:"))
type_layout.addWidget(self.type_combo)
type_group.setLayout(type_layout)
layout.addWidget(type_group)
# 拍摄方式选择
method_group = QGroupBox("拍摄方式设置")
method_layout = QVBoxLayout()
self.method_combo = NoWheelComboBox()
self.method_combo.addItems(["", "无人机航拍", "手持相机拍摄"])
method_layout.addWidget(QLabel("拍摄方式:"))
method_layout.addWidget(self.method_combo)
method_group.setLayout(method_layout)
layout.addWidget(method_group)
# 天气选择
weather_group = QGroupBox("天气设置")
weather_layout = QVBoxLayout()
self.weather_combo = NoWheelComboBox()
weather_options = [
"", "晴天", "多云", "阴天", "小雨", "中雨", "大雨", "暴雨",
"阵雨", "雷阵雨", "雷电", "冰雹", "轻雾", "", "浓雾",
"", "雨夹雪", "小雪", "中雪", "大雪", "暴雪", "冻雨"
]
self.weather_combo.addItems(weather_options)
weather_layout.addWidget(QLabel("天气情况:"))
weather_layout.addWidget(self.weather_combo)
weather_group.setLayout(weather_layout)
layout.addWidget(weather_group)
# 文件选择按钮
self.select_files_btn = QPushButton("选择图片文件")
self.select_files_btn.setFont(QFont("Arial", 12))
self.select_files_btn.setStyleSheet("background-color: #2196F3; color: white; padding: 8px;")
self.select_files_btn.clicked.connect(self.select_files)
layout.addWidget(self.select_files_btn)
# 选中的文件列表
self.file_list_label = QLabel("已选择 0 个文件")
self.file_list_label.setFont(QFont("Arial", 10))
layout.addWidget(self.file_list_label)
# 添加弹性空间
layout.addStretch()
def setup_advanced_tab(self, tab):
scroll = QScrollArea()
scroll.setWidgetResizable(True)
tab.layout = QVBoxLayout(tab)
tab.layout.addWidget(scroll)
container = QWidget()
scroll.setWidget(container)
layout = QVBoxLayout()
container.setLayout(layout)
# 采集员信息
collector_group = QGroupBox("采集员信息")
collector_layout = QVBoxLayout()
self.collector_id_input = QLineEdit()
self.collector_name_input = QLineEdit()
collector_layout.addWidget(QLabel("采集员ID:"))
collector_layout.addWidget(self.collector_id_input)
collector_layout.addWidget(QLabel("采集员姓名:"))
collector_layout.addWidget(self.collector_name_input)
collector_group.setLayout(collector_layout)
layout.addWidget(collector_group)
# 拍摄时间
time_group = QGroupBox("拍摄时间")
time_layout = QVBoxLayout()
# 开始时间
start_time_group = QGroupBox("开始时间")
start_time_layout = QVBoxLayout()
self.start_calendar = QCalendarWidget()
self.start_time_edit = QDateTimeEdit()
self.start_time_edit.setDisplayFormat("HH:mm:ss")
self.start_time_edit.setTime(QDateTime.currentDateTime().time())
start_time_layout.addWidget(self.start_calendar)
start_time_layout.addWidget(self.start_time_edit)
start_time_group.setLayout(start_time_layout)
# 结束时间
end_time_group = QGroupBox("结束时间")
end_time_layout = QVBoxLayout()
self.end_calendar = QCalendarWidget()
self.end_time_edit = QDateTimeEdit()
self.end_time_edit.setDisplayFormat("HH:mm:ss")
self.end_time_edit.setTime(QDateTime.currentDateTime().time())
end_time_layout.addWidget(self.end_calendar)
end_time_layout.addWidget(self.end_time_edit)
end_time_group.setLayout(end_time_layout)
time_layout.addWidget(start_time_group)
time_layout.addWidget(end_time_group)
time_group.setLayout(time_layout)
layout.addWidget(time_group)
# 环境参数
env_group = QGroupBox("环境参数")
env_layout = QGridLayout()
self.humidity_spin = NoWheelSpinBox()
self.humidity_spin.setRange(0, 100)
self.humidity_spin.setSpecialValueText("未设置")
self.humidity_spin.setValue(0)
self.temp_min_spin = NoWheelDoubleSpinBox()
self.temp_min_spin.setRange(-50, 50)
self.temp_min_spin.setSpecialValueText("未设置")
self.temp_min_spin.setValue(-50)
self.temp_max_spin = NoWheelDoubleSpinBox()
self.temp_max_spin.setRange(-50, 50)
self.temp_max_spin.setSpecialValueText("未设置")
self.temp_max_spin.setValue(-50)
self.wind_level_spin = NoWheelSpinBox()
self.wind_level_spin.setRange(0, 12)
self.wind_level_spin.setSpecialValueText("未设置")
self.wind_level_spin.setValue(0)
self.distance_spin = NoWheelSpinBox()
self.distance_spin.setRange(0, 1000)
self.distance_spin.setSpecialValueText("未设置")
self.distance_spin.setValue(0)
env_layout.addWidget(QLabel("湿度(%):"), 0, 0)
env_layout.addWidget(self.humidity_spin, 0, 1)
env_layout.addWidget(QLabel("最低温度(℃):"), 1, 0)
env_layout.addWidget(self.temp_min_spin, 1, 1)
env_layout.addWidget(QLabel("最高温度(℃):"), 2, 0)
env_layout.addWidget(self.temp_max_spin, 2, 1)
env_layout.addWidget(QLabel("风力等级:"), 3, 0)
env_layout.addWidget(self.wind_level_spin, 3, 1)
env_layout.addWidget(QLabel("拍摄距离(m):"), 4, 0)
env_layout.addWidget(self.distance_spin, 4, 1)
env_group.setLayout(env_layout)
layout.addWidget(env_group)
# 添加弹性空间
layout.addStretch()
def select_files(self):
options = QFileDialog.Options()
files, _ = QFileDialog.getOpenFileNames(
self, "选择图片文件", "",
"图片文件 (*.jpg *.jpeg *.png *.bmp *.gif)",
options=options
)
if files:
self.file_paths = files
self.file_list_label.setText(f"已选择 {len(files)} 个文件")
self.log_message(f"已选择 {len(files)} 个图片文件")
def clear_selection(self):
self.file_paths = []
self.file_list_label.setText("已选择 0 个文件")
self.log_message("已清空文件选择")
def log_message(self, message):
self.log_text.append(f"[{QDateTime.currentDateTime().toString('yyyy-MM-dd hh:mm:ss')}] {message}")
def start_upload(self):
if self.upload_in_progress:
QMessageBox.warning(self, "警告", "已有上传任务在进行中!")
return
if not self.file_paths:
QMessageBox.warning(self, "警告", "请先选择要上传的图片文件!")
return
self.upload_in_progress = True
self.upload_btn.setEnabled(False)
self.clear_btn.setEnabled(False)
# 使用QTimer在事件循环中启动上传避免界面卡住
QTimer.singleShot(100, self.upload_images)
def upload_images(self):
try:
# 准备参数
part_id = self.part_id_input.text().strip() or self.default_part_id
# 从日历和时间控件获取时间
start_date = self.start_calendar.selectedDate()
start_time = self.start_time_edit.time()
start_datetime = QDateTime(start_date, start_time)
end_date = self.end_calendar.selectedDate()
end_time = self.end_time_edit.time()
end_datetime = QDateTime(end_date, end_time)
# 构建参数字典,只包含有值的参数
params = {
"imageSource": ["collect", "out-work", "in-work", "lightning-protection-work"][
self.source_combo.currentIndex()],
}
# 添加可选参数
if self.type_combo.currentIndex() > 0:
params["imageType"] = ["", "DEFECT", "TYPICAL", "OTHER"][self.type_combo.currentIndex()]
if self.method_combo.currentIndex() > 0:
params["shootingMethod"] = ["", "UAV", "HANDHELD_CAMERA"][self.method_combo.currentIndex()]
if self.weather_combo.currentIndex() > 0:
weather_options = [
"", "SUNNY", "CLOUDY", "OVERCAST", "LIGHT_RAIN", "MODERATE_RAIN", "HEAVY_RAIN",
"CLOUDBURST", "SHOWER", "THUNDERSHOWER", "THUNDER", "HAIL", "LIGHT_FOG",
"FOG", "THICK_FOG", "HAZE", "SLEET", "LIGHT_SNOW", "MODERATE_SNOW",
"HEAVY_SNOW", "BLIZZARD", "FREEZING_RAIN"
]
params["weather"] = weather_options[self.weather_combo.currentIndex()]
collector_id = self.collector_id_input.text().strip()
if collector_id:
params["collectorId"] = collector_id
collector_name = self.collector_name_input.text().strip()
if collector_name:
params["collectorName"] = collector_name
params["shootingTimeBegin"] = start_datetime.toString("yyyy-MM-dd hh:mm:ss")
params["shootingTimeEnd"] = end_datetime.toString("yyyy-MM-dd hh:mm:ss")
# 环境参数
if self.humidity_spin.value() > 0:
params["humidness"] = self.humidity_spin.value()
if self.temp_min_spin.value() > -50:
params["temperatureMin"] = self.temp_min_spin.value()
if self.temp_max_spin.value() > -50:
params["temperatureMax"] = self.temp_max_spin.value()
if self.wind_level_spin.value() > 0:
params["windLevel"] = self.wind_level_spin.value()
if self.distance_spin.value() > 0:
params["shootingDistance"] = self.distance_spin.value()
# 构建URL
url = f"{self.base_url}/{params['imageSource']}/upload-batch/{part_id}"
# 准备图片列表参数
for i, file_path in enumerate(self.file_paths):
file_name = os.path.basename(file_path)
params[f"imageList[{i}].imageName"] = file_name
params[f"imageList[{i}].imagePath"] = file_path
if "imageType" in params:
params[f"imageList[{i}].imageType"] = params["imageType"]
if "shootingMethod" in params:
params[f"imageList[{i}].shootingMethod"] = params["shootingMethod"]
if "weather" in params:
params[f"imageList[{i}].weather"] = params["weather"]
# 准备文件数据
files = []
for file_path in self.file_paths:
file_name = os.path.basename(file_path)
files.append(('files', (file_name, open(file_path, 'rb'), 'image/jpeg')))
self.log_message(f"开始上传 {len(self.file_paths)} 张图片...")
self.log_message(f"请求URL: {url}")
self.log_message(f"请求参数: {params}")
# 显示上传进度对话框
self.progress = QMessageBox(self)
self.progress.setWindowTitle("上传中")
self.progress.setText(f"正在上传 {len(self.file_paths)} 张图片,请稍候...")
self.progress.setStandardButtons(QMessageBox.Cancel)
self.progress.buttonClicked.connect(self.cancel_upload)
self.progress.show()
# 确保UI更新
QApplication.processEvents()
response = requests.post(
url,
headers={"Authorization": "null"},
params=params,
files=files
)
self.progress.close()
if response.status_code == 200:
self.log_message("上传成功!")
self.log_message(f"响应数据: {response.text}")
QMessageBox.information(self, "成功", "图片上传成功!")
else:
self.log_message(f"上传失败,状态码: {response.status_code}")
self.log_message(f"响应内容: {response.text}")
QMessageBox.critical(self, "错误", f"上传失败: {response.text}")
except Exception as e:
self.log_message(f"上传过程中发生错误: {str(e)}")
QMessageBox.critical(self, "错误", f"上传过程中发生错误: {str(e)}")
finally:
# 确保所有文件都被关闭
if 'files' in locals():
for file in files:
file[1][1].close()
self.upload_in_progress = False
self.upload_btn.setEnabled(True)
self.clear_btn.setEnabled(True)
def cancel_upload(self):
self.upload_in_progress = False
self.log_message("用户取消了上传操作")
self.progress.close()
if __name__ == "__main__":
app = QApplication(sys.argv)
# 设置全局样式
app.setStyle("Fusion")
app.setStyleSheet("""
QMainWindow {
background-color: #f5f5f5;
}
QGroupBox {
font-weight: bold;
border: 1px solid #ccc;
border-radius: 5px;
margin-top: 10px;
padding-top: 15px;
}
QGroupBox::title {
subcontrol-origin: margin;
left: 10px;
padding: 0 3px;
}
QLabel {
font-size: 12px;
}
QComboBox, QLineEdit, QDateTimeEdit, QSpinBox, QDoubleSpinBox {
padding: 5px;
border: 1px solid #ccc;
border-radius: 3px;
min-width: 200px;
}
QTextEdit {
border: 1px solid #ccc;
border-radius: 3px;
}
QCalendarWidget {
border: 1px solid #ccc;
border-radius: 3px;
}
""")
window = ImageUploaderApp()
window.show()
sys.exit(app.exec_())