上传文件至 /
This commit is contained in:
parent
90bd27d95d
commit
f73123ad4e
|
@ -0,0 +1,294 @@
|
|||
import sys
|
||||
import requests
|
||||
import json
|
||||
from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,
|
||||
QLabel, QLineEdit, QPushButton, QTextEdit, QMessageBox,
|
||||
QFileDialog, QComboBox, QFormLayout, QGroupBox)
|
||||
from PyQt5.QtCore import Qt
|
||||
from PyQt5.QtGui import QFont
|
||||
|
||||
|
||||
class TurbineAddWindow(QMainWindow):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.setWindowTitle("新增机组")
|
||||
self.setGeometry(100, 100, 600, 600)
|
||||
self.setStyleSheet("""
|
||||
QMainWindow {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
QGroupBox {
|
||||
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-weight: bold;
|
||||
min-width: 80px;
|
||||
}
|
||||
QPushButton {
|
||||
background-color: #4CAF50;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 5px 10px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
QPushButton:hover {
|
||||
background-color: #45a049;
|
||||
}
|
||||
QComboBox, QLineEdit, QTextEdit {
|
||||
padding: 5px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 3px;
|
||||
}
|
||||
""")
|
||||
|
||||
# 存储项目数据的字典 {项目显示名称: 项目ID}
|
||||
self.project_data = {}
|
||||
|
||||
self.init_ui()
|
||||
self.load_project_list()
|
||||
|
||||
def init_ui(self):
|
||||
# 主窗口部件
|
||||
central_widget = QWidget()
|
||||
self.setCentralWidget(central_widget)
|
||||
main_layout = QVBoxLayout()
|
||||
|
||||
# 项目查询组
|
||||
project_group = QGroupBox("项目信息")
|
||||
project_layout = QFormLayout()
|
||||
|
||||
# 项目选择下拉框
|
||||
self.project_combo = QComboBox()
|
||||
project_layout.addRow(QLabel("项目名称*:"), self.project_combo)
|
||||
|
||||
# 刷新项目列表按钮
|
||||
self.refresh_btn = QPushButton("刷新项目列表")
|
||||
self.refresh_btn.clicked.connect(self.load_project_list)
|
||||
project_layout.addRow(self.refresh_btn)
|
||||
|
||||
project_group.setLayout(project_layout)
|
||||
main_layout.addWidget(project_group)
|
||||
|
||||
# 机组信息组
|
||||
turbine_group = QGroupBox("机组信息")
|
||||
turbine_layout = QFormLayout()
|
||||
|
||||
# 机组名称
|
||||
self.turbine_name_input = QLineEdit()
|
||||
turbine_layout.addRow(QLabel("机组名称:"), self.turbine_name_input)
|
||||
|
||||
# 机组编码
|
||||
self.turbine_code_input = QLineEdit()
|
||||
turbine_layout.addRow(QLabel("机组编码:"), self.turbine_code_input)
|
||||
|
||||
# 机组描述
|
||||
self.turbine_desc_input = QTextEdit()
|
||||
self.turbine_desc_input.setMaximumHeight(80)
|
||||
turbine_layout.addRow(QLabel("机组描述:"), self.turbine_desc_input)
|
||||
|
||||
# 机组厂商
|
||||
self.turbine_manufacturer_input = QLineEdit()
|
||||
turbine_layout.addRow(QLabel("机组厂商:"), self.turbine_manufacturer_input)
|
||||
|
||||
# 机组型号
|
||||
self.turbine_model_input = QLineEdit()
|
||||
turbine_layout.addRow(QLabel("机组型号:"), self.turbine_model_input)
|
||||
|
||||
# 机组封面图
|
||||
self.cover_image_path = ""
|
||||
self.cover_image_label = QLabel("未选择图片")
|
||||
self.cover_image_label.setStyleSheet("color: #666; font-style: italic;")
|
||||
self.select_image_btn = QPushButton("选择图片")
|
||||
self.select_image_btn.clicked.connect(self.select_image)
|
||||
|
||||
image_layout = QHBoxLayout()
|
||||
image_layout.addWidget(self.cover_image_label)
|
||||
image_layout.addWidget(self.select_image_btn)
|
||||
turbine_layout.addRow(QLabel("机组封面图:"), image_layout)
|
||||
|
||||
turbine_group.setLayout(turbine_layout)
|
||||
main_layout.addWidget(turbine_group)
|
||||
|
||||
# 按钮区域
|
||||
button_layout = QHBoxLayout()
|
||||
button_layout.addStretch()
|
||||
|
||||
# 清空按钮
|
||||
self.clear_btn = QPushButton("清空表单")
|
||||
self.clear_btn.setFixedWidth(100)
|
||||
self.clear_btn.clicked.connect(self.clear_form)
|
||||
button_layout.addWidget(self.clear_btn)
|
||||
|
||||
# 提交按钮
|
||||
self.submit_btn = QPushButton("提交")
|
||||
self.submit_btn.setFixedWidth(100)
|
||||
self.submit_btn.clicked.connect(self.submit_data)
|
||||
button_layout.addWidget(self.submit_btn)
|
||||
|
||||
main_layout.addLayout(button_layout)
|
||||
central_widget.setLayout(main_layout)
|
||||
|
||||
def load_project_list(self):
|
||||
"""加载项目列表"""
|
||||
url = "http://pms.dtyx.net:9158/project/list"
|
||||
headers = {
|
||||
"Authorization": "null",
|
||||
"Content-Type": "application/x-www-form-urlencoded"
|
||||
}
|
||||
|
||||
try:
|
||||
response = requests.get(url, headers=headers)
|
||||
response.raise_for_status()
|
||||
|
||||
result = response.json()
|
||||
if result.get("success") and "data" in result:
|
||||
self.project_data = {}
|
||||
self.project_combo.clear()
|
||||
|
||||
# 获取并排序项目数据
|
||||
projects = result["data"]
|
||||
sorted_projects = sorted(projects, key=lambda x: x.get("projectName", ""))
|
||||
|
||||
# 填充项目数据
|
||||
for project in sorted_projects:
|
||||
display_name = f"{project.get('projectName', '')} (ID: {project.get('projectId', '')})"
|
||||
self.project_data[display_name] = project.get("projectId", "")
|
||||
self.project_combo.addItem(display_name)
|
||||
|
||||
if self.project_data:
|
||||
QMessageBox.information(self, "成功", f"成功加载{len(self.project_data)}个项目")
|
||||
else:
|
||||
QMessageBox.warning(self, "警告", "没有找到项目数据")
|
||||
else:
|
||||
QMessageBox.warning(self, "警告", f"获取项目列表失败: {result.get('msg', '未知错误')}")
|
||||
|
||||
except Exception as e:
|
||||
QMessageBox.critical(self, "错误", f"获取项目列表时出错:\n{str(e)}")
|
||||
|
||||
def select_image(self):
|
||||
options = QFileDialog.Options()
|
||||
file_path, _ = QFileDialog.getOpenFileName(
|
||||
self, "选择机组封面图", "",
|
||||
"图片文件 (*.jpg *.jpeg *.png *.gif);;所有文件 (*.*)",
|
||||
options=options
|
||||
)
|
||||
|
||||
if file_path:
|
||||
self.cover_image_path = file_path
|
||||
self.cover_image_label.setText(file_path.split('/')[-1])
|
||||
self.cover_image_label.setStyleSheet("color: #333; font-style: normal;")
|
||||
|
||||
def validate_inputs(self):
|
||||
if not self.project_combo.currentText():
|
||||
QMessageBox.warning(self, "输入错误", "请选择项目!")
|
||||
return False
|
||||
return True
|
||||
|
||||
def submit_data(self):
|
||||
if not self.validate_inputs():
|
||||
return
|
||||
|
||||
# 获取选择的项目ID
|
||||
selected_project = self.project_combo.currentText()
|
||||
project_id = self.project_data.get(selected_project, "")
|
||||
|
||||
# 构造请求数据
|
||||
turbine_data = {
|
||||
"projectId": project_id,
|
||||
"turbineName": self.turbine_name_input.text().strip(),
|
||||
"turbineCode": self.turbine_code_input.text().strip(),
|
||||
"turbineDesc": self.turbine_desc_input.toPlainText().strip(),
|
||||
"turbineManufacturer": self.turbine_manufacturer_input.text().strip(),
|
||||
"turbineModel": self.turbine_model_input.text().strip(),
|
||||
"turbineCoverUrl": self.cover_image_path if self.cover_image_path else ""
|
||||
}
|
||||
|
||||
# 确认对话框
|
||||
reply = QMessageBox.question(
|
||||
self, '确认提交',
|
||||
'确定要提交这些信息吗?',
|
||||
QMessageBox.Yes | QMessageBox.No, QMessageBox.No
|
||||
)
|
||||
|
||||
if reply == QMessageBox.No:
|
||||
return
|
||||
|
||||
# 提交数据
|
||||
url = "http://pms.dtyx.net:9158/turbine"
|
||||
headers = {
|
||||
"Authorization": "null",
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
|
||||
try:
|
||||
response = requests.post(url, headers=headers, data=json.dumps(turbine_data))
|
||||
response.raise_for_status()
|
||||
|
||||
result = response.json()
|
||||
|
||||
# 创建自定义消息框显示大尺寸结果
|
||||
msg_box = QMessageBox(self)
|
||||
msg_box.setWindowTitle("提交成功")
|
||||
msg_box.setIcon(QMessageBox.Information)
|
||||
msg_box.setText("机组信息提交成功!")
|
||||
|
||||
text_edit = QTextEdit()
|
||||
text_edit.setReadOnly(True)
|
||||
text_edit.setPlainText(json.dumps(result, indent=2))
|
||||
text_edit.setMinimumSize(500, 300)
|
||||
text_edit.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
|
||||
|
||||
msg_box.layout().addWidget(text_edit, 1, 0, 1, msg_box.layout().columnCount())
|
||||
msg_box.setStyleSheet("QLabel{min-width: 400px;}")
|
||||
msg_box.exec_()
|
||||
|
||||
except Exception as e:
|
||||
error_box = QMessageBox(self)
|
||||
error_box.setWindowTitle("提交失败")
|
||||
error_box.setIcon(QMessageBox.Critical)
|
||||
error_box.setText("机组信息提交失败!")
|
||||
|
||||
error_text = QTextEdit()
|
||||
error_text.setReadOnly(True)
|
||||
error_text.setPlainText(str(e))
|
||||
error_text.setMinimumSize(500, 150)
|
||||
error_text.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
|
||||
|
||||
error_box.layout().addWidget(error_text, 1, 0, 1, error_box.layout().columnCount())
|
||||
error_box.exec_()
|
||||
|
||||
def clear_form(self):
|
||||
"""手动清空表单的方法"""
|
||||
reply = QMessageBox.question(
|
||||
self, '确认清空',
|
||||
'确定要清空所有已填写的信息吗?',
|
||||
QMessageBox.Yes | QMessageBox.No, QMessageBox.No
|
||||
)
|
||||
|
||||
if reply == QMessageBox.Yes:
|
||||
self.turbine_name_input.clear()
|
||||
self.turbine_code_input.clear()
|
||||
self.turbine_desc_input.clear()
|
||||
self.turbine_manufacturer_input.clear()
|
||||
self.turbine_model_input.clear()
|
||||
self.cover_image_path = ""
|
||||
self.cover_image_label.setText("未选择图片")
|
||||
self.cover_image_label.setStyleSheet("color: #666; font-style: italic;")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
app = QApplication(sys.argv)
|
||||
font = QFont("Microsoft YaHei", 10)
|
||||
app.setFont(font)
|
||||
|
||||
window = TurbineAddWindow()
|
||||
window.show()
|
||||
sys.exit(app.exec_())
|
|
@ -0,0 +1,247 @@
|
|||
import sys
|
||||
import requests
|
||||
import json
|
||||
from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,
|
||||
QLabel, QLineEdit, QPushButton, QTextEdit, QMessageBox,
|
||||
QComboBox, QFormLayout, QGroupBox, QSizePolicy)
|
||||
from PyQt5.QtCore import Qt
|
||||
from PyQt5.QtGui import QFont
|
||||
|
||||
|
||||
class PartAddWindow(QMainWindow):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.setWindowTitle("新增部件")
|
||||
self.setGeometry(100, 100, 600, 600)
|
||||
self.setStyleSheet("""
|
||||
QMainWindow {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
QGroupBox {
|
||||
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-weight: bold;
|
||||
min-width: 80px;
|
||||
}
|
||||
QPushButton {
|
||||
background-color: #4CAF50;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 5px 10px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
QPushButton:hover {
|
||||
background-color: #45a049;
|
||||
}
|
||||
QComboBox, QLineEdit, QTextEdit {
|
||||
padding: 5px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 3px;
|
||||
}
|
||||
""")
|
||||
|
||||
self.turbine_data = {}
|
||||
self.init_ui()
|
||||
|
||||
def init_ui(self):
|
||||
central_widget = QWidget()
|
||||
self.setCentralWidget(central_widget)
|
||||
main_layout = QVBoxLayout()
|
||||
|
||||
# 项目查询组
|
||||
project_group = QGroupBox("项目查询")
|
||||
project_layout = QFormLayout()
|
||||
|
||||
self.project_id_input = QLineEdit()
|
||||
self.project_id_input.setPlaceholderText("请输入项目ID")
|
||||
project_layout.addRow(QLabel("项目ID*:"), self.project_id_input)
|
||||
|
||||
self.query_btn = QPushButton("查询机组列表")
|
||||
self.query_btn.clicked.connect(self.load_turbine_list)
|
||||
project_layout.addRow(self.query_btn)
|
||||
|
||||
project_group.setLayout(project_layout)
|
||||
main_layout.addWidget(project_group)
|
||||
|
||||
# 部件信息组
|
||||
part_group = QGroupBox("部件信息")
|
||||
part_layout = QFormLayout()
|
||||
|
||||
self.turbine_combo = QComboBox()
|
||||
part_layout.addRow(QLabel("机组名称*:"), self.turbine_combo)
|
||||
|
||||
self.part_name_combo = QComboBox()
|
||||
self.part_name_combo.addItems(["", "叶片1", "叶片2", "叶片3"])
|
||||
part_layout.addRow(QLabel("部件名称*:"), self.part_name_combo)
|
||||
|
||||
self.part_code_input = QLineEdit()
|
||||
part_layout.addRow(QLabel("部件编号:"), self.part_code_input)
|
||||
|
||||
self.part_type_combo = QComboBox()
|
||||
self.part_type_combo.addItems(["", "VANE-1", "VANE-2", "VANE-3"])
|
||||
part_layout.addRow(QLabel("部件类型:"), self.part_type_combo)
|
||||
|
||||
self.part_desc_input = QTextEdit()
|
||||
self.part_desc_input.setMaximumHeight(80)
|
||||
part_layout.addRow(QLabel("部件描述:"), self.part_desc_input)
|
||||
|
||||
self.part_manufacturer_input = QLineEdit()
|
||||
part_layout.addRow(QLabel("部件厂商:"), self.part_manufacturer_input)
|
||||
|
||||
self.part_model_input = QLineEdit()
|
||||
part_layout.addRow(QLabel("部件型号:"), self.part_model_input)
|
||||
|
||||
part_group.setLayout(part_layout)
|
||||
main_layout.addWidget(part_group)
|
||||
|
||||
# 按钮区域
|
||||
button_layout = QHBoxLayout()
|
||||
button_layout.addStretch()
|
||||
|
||||
self.submit_btn = QPushButton("提交")
|
||||
self.submit_btn.setFixedWidth(100)
|
||||
self.submit_btn.clicked.connect(self.submit_data)
|
||||
button_layout.addWidget(self.submit_btn)
|
||||
|
||||
main_layout.addLayout(button_layout)
|
||||
central_widget.setLayout(main_layout)
|
||||
|
||||
def load_turbine_list(self):
|
||||
project_id = self.project_id_input.text().strip()
|
||||
if not project_id:
|
||||
QMessageBox.warning(self, "输入错误", "请输入项目ID!")
|
||||
return
|
||||
|
||||
url = "http://pms.dtyx.net:9158/turbine/list"
|
||||
headers = {
|
||||
"Authorization": "null",
|
||||
"Content-Type": "application/x-www-form-urlencoded"
|
||||
}
|
||||
|
||||
try:
|
||||
params = {"projectId": project_id}
|
||||
response = requests.get(url, headers=headers, params=params)
|
||||
response.raise_for_status()
|
||||
|
||||
result = response.json()
|
||||
if result.get("success") and "data" in result:
|
||||
self.turbine_data = {}
|
||||
self.turbine_combo.clear()
|
||||
|
||||
turbines = result["data"]
|
||||
sorted_turbines = sorted(turbines, key=lambda x: x.get("turbineName", ""))
|
||||
|
||||
for turbine in sorted_turbines:
|
||||
display_name = f"{turbine.get('turbineName', '')} (ID: {turbine.get('turbineId', '')})"
|
||||
self.turbine_data[display_name] = turbine.get("turbineId", "")
|
||||
self.turbine_combo.addItem(display_name)
|
||||
|
||||
if self.turbine_data:
|
||||
QMessageBox.information(self, "成功", f"成功加载{len(self.turbine_data)}个机组")
|
||||
else:
|
||||
QMessageBox.warning(self, "警告", "没有找到机组数据")
|
||||
else:
|
||||
QMessageBox.warning(self, "警告", f"获取机组列表失败: {result.get('msg', '未知错误')}")
|
||||
|
||||
except Exception as e:
|
||||
QMessageBox.critical(self, "错误", f"获取机组列表时出错:\n{str(e)}")
|
||||
|
||||
def validate_inputs(self):
|
||||
if not self.project_id_input.text().strip():
|
||||
QMessageBox.warning(self, "输入错误", "请输入项目ID!")
|
||||
return False
|
||||
if not self.turbine_combo.currentText():
|
||||
QMessageBox.warning(self, "输入错误", "请选择机组!")
|
||||
return False
|
||||
if not self.part_name_combo.currentText():
|
||||
QMessageBox.warning(self, "输入错误", "请选择部件名称!")
|
||||
return False
|
||||
return True
|
||||
|
||||
def submit_data(self):
|
||||
if not self.validate_inputs():
|
||||
return
|
||||
|
||||
selected_turbine = self.turbine_combo.currentText()
|
||||
turbine_id = self.turbine_data.get(selected_turbine, "")
|
||||
|
||||
part_data = {
|
||||
"turbineId": turbine_id,
|
||||
"partName": self.part_name_combo.currentText(),
|
||||
"partCode": self.part_code_input.text().strip(),
|
||||
"partType": self.part_type_combo.currentText(),
|
||||
"partDesc": self.part_desc_input.toPlainText().strip(),
|
||||
"partManufacturer": self.part_manufacturer_input.text().strip(),
|
||||
"partModel": self.part_model_input.text().strip()
|
||||
}
|
||||
|
||||
reply = QMessageBox.question(
|
||||
self, '确认提交',
|
||||
'确定要提交这些部件信息吗?',
|
||||
QMessageBox.Yes | QMessageBox.No, QMessageBox.No
|
||||
)
|
||||
|
||||
if reply == QMessageBox.No:
|
||||
return
|
||||
|
||||
url = "http://pms.dtyx.net:9158/part"
|
||||
headers = {
|
||||
"Authorization": "null",
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
|
||||
try:
|
||||
response = requests.post(url, headers=headers, data=json.dumps(part_data))
|
||||
response.raise_for_status()
|
||||
|
||||
result = response.json()
|
||||
|
||||
# 创建自定义消息框显示大尺寸结果
|
||||
msg_box = QMessageBox(self)
|
||||
msg_box.setWindowTitle("提交成功")
|
||||
msg_box.setIcon(QMessageBox.Information)
|
||||
msg_box.setText("部件信息提交成功!")
|
||||
|
||||
text_edit = QTextEdit()
|
||||
text_edit.setReadOnly(True)
|
||||
text_edit.setPlainText(json.dumps(result, indent=2))
|
||||
text_edit.setMinimumSize(500, 300)
|
||||
text_edit.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
|
||||
|
||||
msg_box.layout().addWidget(text_edit, 1, 0, 1, msg_box.layout().columnCount())
|
||||
msg_box.setStyleSheet("QLabel{min-width: 400px;}")
|
||||
msg_box.exec_()
|
||||
|
||||
except Exception as e:
|
||||
error_box = QMessageBox(self)
|
||||
error_box.setWindowTitle("提交失败")
|
||||
error_box.setIcon(QMessageBox.Critical)
|
||||
error_box.setText("部件信息提交失败!")
|
||||
|
||||
error_text = QTextEdit()
|
||||
error_text.setReadOnly(True)
|
||||
error_text.setPlainText(str(e))
|
||||
error_text.setMinimumSize(500, 150)
|
||||
error_text.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
|
||||
|
||||
error_box.layout().addWidget(error_text, 1, 0, 1, error_box.layout().columnCount())
|
||||
error_box.exec_()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
app = QApplication(sys.argv)
|
||||
font = QFont("Microsoft YaHei", 10)
|
||||
app.setFont(font)
|
||||
|
||||
window = PartAddWindow()
|
||||
window.show()
|
||||
sys.exit(app.exec_())
|
|
@ -0,0 +1,791 @@
|
|||
import os
|
||||
import sys
|
||||
import requests
|
||||
import json
|
||||
from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,
|
||||
QLabel, QLineEdit, QComboBox, QPushButton, QFileDialog,
|
||||
QGroupBox, QDateTimeEdit, QDoubleSpinBox, QSpinBox, QTextEdit,
|
||||
QTabWidget, QScrollArea, QMessageBox, QCalendarWidget, QGridLayout,QFormLayout)
|
||||
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, 900, 700)
|
||||
|
||||
# 初始化参数
|
||||
self.base_url = "http://pms.dtyx.net:9158/image"
|
||||
self.file_paths = []
|
||||
self.upload_in_progress = False
|
||||
self.cancel_requested = False
|
||||
self.batch_size = 20 # 每批次上传的图片数量
|
||||
|
||||
# 存储项目、机组、部件数据
|
||||
self.project_data = {} # {项目显示名称: 项目ID}
|
||||
self.turbine_data = {} # {机组显示名称: 机组ID}
|
||||
self.part_data = {} # {部件显示名称: 部件ID}
|
||||
|
||||
# 当前选择的项目ID和机组ID
|
||||
self.current_project_id = ""
|
||||
self.current_turbine_id = ""
|
||||
|
||||
# 初始化UI
|
||||
self.init_ui()
|
||||
self.load_project_list()
|
||||
|
||||
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)
|
||||
|
||||
# 项目选择标签页
|
||||
project_tab = QWidget()
|
||||
tab_widget.addTab(project_tab, "项目选择")
|
||||
self.setup_project_tab(project_tab)
|
||||
|
||||
# 图片参数标签页
|
||||
param_tab = QWidget()
|
||||
tab_widget.addTab(param_tab, "图片参数")
|
||||
self.setup_param_tab(param_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_project_tab(self, tab):
|
||||
layout = QVBoxLayout()
|
||||
tab.setLayout(layout)
|
||||
|
||||
# 项目选择
|
||||
project_group = QGroupBox("项目选择")
|
||||
project_layout = QFormLayout()
|
||||
|
||||
self.project_combo = NoWheelComboBox()
|
||||
self.project_combo.currentIndexChanged.connect(self.on_project_selected)
|
||||
project_layout.addRow(QLabel("项目名称*:"), self.project_combo)
|
||||
|
||||
# 刷新项目按钮
|
||||
self.refresh_project_btn = QPushButton("刷新项目列表")
|
||||
self.refresh_project_btn.clicked.connect(self.load_project_list)
|
||||
project_layout.addRow(self.refresh_project_btn)
|
||||
|
||||
project_group.setLayout(project_layout)
|
||||
layout.addWidget(project_group)
|
||||
|
||||
# 机组选择
|
||||
turbine_group = QGroupBox("机组选择")
|
||||
turbine_layout = QFormLayout()
|
||||
|
||||
self.turbine_combo = NoWheelComboBox()
|
||||
self.turbine_combo.currentIndexChanged.connect(self.on_turbine_selected)
|
||||
turbine_layout.addRow(QLabel("机组名称*:"), self.turbine_combo)
|
||||
|
||||
# 刷新机组按钮
|
||||
self.refresh_turbine_btn = QPushButton("刷新机组列表")
|
||||
self.refresh_turbine_btn.clicked.connect(lambda: self.load_turbine_list(self.current_project_id))
|
||||
turbine_layout.addRow(self.refresh_turbine_btn)
|
||||
|
||||
turbine_group.setLayout(turbine_layout)
|
||||
layout.addWidget(turbine_group)
|
||||
|
||||
# 部件选择
|
||||
part_group = QGroupBox("部件选择")
|
||||
part_layout = QFormLayout()
|
||||
|
||||
self.part_combo = NoWheelComboBox()
|
||||
part_layout.addRow(QLabel("部件名称*:"), self.part_combo)
|
||||
|
||||
# 刷新部件按钮
|
||||
self.refresh_part_btn = QPushButton("刷新部件列表")
|
||||
self.refresh_part_btn.clicked.connect(
|
||||
lambda: self.load_part_list(self.current_project_id, self.current_turbine_id))
|
||||
part_layout.addRow(self.refresh_part_btn)
|
||||
|
||||
part_group.setLayout(part_layout)
|
||||
layout.addWidget(part_group)
|
||||
|
||||
# 文件选择区域
|
||||
file_group = QGroupBox("图片选择")
|
||||
file_layout = QVBoxLayout()
|
||||
|
||||
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)
|
||||
file_layout.addWidget(self.select_files_btn)
|
||||
|
||||
self.file_list_label = QLabel("已选择 0 个文件")
|
||||
self.file_list_label.setFont(QFont("Arial", 10))
|
||||
file_layout.addWidget(self.file_list_label)
|
||||
|
||||
file_group.setLayout(file_layout)
|
||||
layout.addWidget(file_group)
|
||||
|
||||
# 添加弹性空间
|
||||
layout.addStretch()
|
||||
|
||||
def setup_param_tab(self, tab):
|
||||
layout = QVBoxLayout()
|
||||
tab.setLayout(layout)
|
||||
|
||||
# 图片源选择
|
||||
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)
|
||||
|
||||
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 load_project_list(self):
|
||||
"""加载项目列表"""
|
||||
url = "http://pms.dtyx.net:9158/project/list"
|
||||
headers = {
|
||||
"Authorization": "null",
|
||||
"Content-Type": "application/x-www-form-urlencoded"
|
||||
}
|
||||
|
||||
try:
|
||||
response = requests.get(url, headers=headers)
|
||||
response.raise_for_status()
|
||||
|
||||
result = response.json()
|
||||
if result.get("success") and "data" in result:
|
||||
self.project_data = {}
|
||||
self.project_combo.clear()
|
||||
|
||||
# 获取并排序项目数据
|
||||
projects = result["data"]
|
||||
sorted_projects = sorted(projects, key=lambda x: x.get("projectName", ""))
|
||||
|
||||
# 填充项目数据
|
||||
for project in sorted_projects:
|
||||
display_name = f"{project.get('projectName', '')} (ID: {project.get('projectId', '')})"
|
||||
self.project_data[display_name] = project.get("projectId", "")
|
||||
self.project_combo.addItem(display_name)
|
||||
|
||||
if self.project_data:
|
||||
self.log_message(f"成功加载{len(self.project_data)}个项目")
|
||||
else:
|
||||
self.log_message("没有找到项目数据")
|
||||
QMessageBox.warning(self, "警告", "没有找到项目数据")
|
||||
else:
|
||||
self.log_message(f"获取项目列表失败: {result.get('msg', '未知错误')}")
|
||||
QMessageBox.warning(self, "警告", f"获取项目列表失败: {result.get('msg', '未知错误')}")
|
||||
|
||||
except Exception as e:
|
||||
self.log_message(f"获取项目列表时出错:\n{str(e)}")
|
||||
QMessageBox.critical(self, "错误", f"获取项目列表时出错:\n{str(e)}")
|
||||
|
||||
def load_turbine_list(self, project_id):
|
||||
"""加载机组列表"""
|
||||
if not project_id:
|
||||
QMessageBox.warning(self, "警告", "请先选择项目!")
|
||||
return
|
||||
|
||||
url = "http://pms.dtyx.net:9158/turbine/list"
|
||||
headers = {
|
||||
"Authorization": "null",
|
||||
"Content-Type": "application/x-www-form-urlencoded"
|
||||
}
|
||||
|
||||
try:
|
||||
params = {"projectId": project_id}
|
||||
response = requests.get(url, headers=headers, params=params)
|
||||
response.raise_for_status()
|
||||
|
||||
result = response.json()
|
||||
if result.get("success") and "data" in result:
|
||||
self.turbine_data = {}
|
||||
self.turbine_combo.clear()
|
||||
|
||||
# 获取并排序机组数据
|
||||
turbines = result["data"]
|
||||
sorted_turbines = sorted(turbines, key=lambda x: x.get("turbineName", ""))
|
||||
|
||||
# 填充机组数据
|
||||
for turbine in sorted_turbines:
|
||||
display_name = f"{turbine.get('turbineName', '')} (ID: {turbine.get('turbineId', '')})"
|
||||
self.turbine_data[display_name] = turbine.get("turbineId", "")
|
||||
self.turbine_combo.addItem(display_name)
|
||||
|
||||
if self.turbine_data:
|
||||
self.log_message(f"成功加载{len(self.turbine_data)}个机组")
|
||||
else:
|
||||
self.log_message("没有找到机组数据")
|
||||
QMessageBox.warning(self, "警告", "没有找到机组数据")
|
||||
else:
|
||||
self.log_message(f"获取机组列表失败: {result.get('msg', '未知错误')}")
|
||||
QMessageBox.warning(self, "警告", f"获取机组列表失败: {result.get('msg', '未知错误')}")
|
||||
|
||||
except Exception as e:
|
||||
self.log_message(f"获取机组列表时出错:\n{str(e)}")
|
||||
QMessageBox.critical(self, "错误", f"获取机组列表时出错:\n{str(e)}")
|
||||
|
||||
def load_part_list(self, project_id, turbine_id):
|
||||
"""加载部件列表"""
|
||||
if not project_id or not turbine_id:
|
||||
QMessageBox.warning(self, "警告", "请先选择项目和机组!")
|
||||
return
|
||||
|
||||
url = "http://pms.dtyx.net:9158/part/list"
|
||||
headers = {
|
||||
"Authorization": "null",
|
||||
"Content-Type": "application/x-www-form-urlencoded"
|
||||
}
|
||||
|
||||
try:
|
||||
params = {
|
||||
"projectId": project_id,
|
||||
"turbineId": turbine_id
|
||||
}
|
||||
response = requests.get(url, headers=headers, params=params)
|
||||
response.raise_for_status()
|
||||
|
||||
result = response.json()
|
||||
if result.get("success") and "data" in result:
|
||||
self.part_data = {}
|
||||
self.part_combo.clear()
|
||||
|
||||
# 获取并排序部件数据
|
||||
parts = result["data"]
|
||||
sorted_parts = sorted(parts, key=lambda x: x.get("partName", ""))
|
||||
|
||||
# 填充部件数据
|
||||
for part in sorted_parts:
|
||||
display_name = f"{part.get('partName', '')} (ID: {part.get('partId', '')})"
|
||||
self.part_data[display_name] = part.get("partId", "")
|
||||
self.part_combo.addItem(display_name)
|
||||
|
||||
if self.part_data:
|
||||
self.log_message(f"成功加载{len(self.part_data)}个部件")
|
||||
else:
|
||||
self.log_message("没有找到部件数据")
|
||||
QMessageBox.warning(self, "警告", "没有找到部件数据")
|
||||
else:
|
||||
self.log_message(f"获取部件列表失败: {result.get('msg', '未知错误')}")
|
||||
QMessageBox.warning(self, "警告", f"获取部件列表失败: {result.get('msg', '未知错误')}")
|
||||
|
||||
except Exception as e:
|
||||
self.log_message(f"获取部件列表时出错:\n{str(e)}")
|
||||
QMessageBox.critical(self, "错误", f"获取部件列表时出错:\n{str(e)}")
|
||||
|
||||
def on_project_selected(self, index):
|
||||
"""项目选择变化事件"""
|
||||
if index >= 0:
|
||||
selected_project = self.project_combo.currentText()
|
||||
self.current_project_id = self.project_data.get(selected_project, "")
|
||||
self.log_message(f"已选择项目: {selected_project}")
|
||||
self.load_turbine_list(self.current_project_id)
|
||||
else:
|
||||
self.current_project_id = ""
|
||||
self.turbine_combo.clear()
|
||||
self.part_combo.clear()
|
||||
|
||||
def on_turbine_selected(self, index):
|
||||
"""机组选择变化事件"""
|
||||
if index >= 0:
|
||||
selected_turbine = self.turbine_combo.currentText()
|
||||
self.current_turbine_id = self.turbine_data.get(selected_turbine, "")
|
||||
self.log_message(f"已选择机组: {selected_turbine}")
|
||||
self.load_part_list(self.current_project_id, self.current_turbine_id)
|
||||
else:
|
||||
self.current_turbine_id = ""
|
||||
self.part_combo.clear()
|
||||
|
||||
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.update_file_count()
|
||||
self.log_message(f"已选择 {len(files)} 个图片文件")
|
||||
|
||||
def clear_selection(self):
|
||||
self.file_paths = []
|
||||
self.update_file_count()
|
||||
self.log_message("已清空文件选择")
|
||||
|
||||
def update_file_count(self):
|
||||
"""更新文件计数显示"""
|
||||
self.file_list_label.setText(f"已选择 {len(self.file_paths)} 个文件")
|
||||
|
||||
def log_message(self, message):
|
||||
"""记录日志信息"""
|
||||
self.log_text.append(f"[{QDateTime.currentDateTime().toString('yyyy-MM-dd hh:mm:ss')}] {message}")
|
||||
|
||||
def validate_inputs(self):
|
||||
"""验证输入是否完整"""
|
||||
if not self.current_project_id:
|
||||
QMessageBox.warning(self, "警告", "请选择项目!")
|
||||
return False
|
||||
if not self.current_turbine_id:
|
||||
QMessageBox.warning(self, "警告", "请选择机组!")
|
||||
return False
|
||||
if not self.part_combo.currentText():
|
||||
QMessageBox.warning(self, "警告", "请选择部件!")
|
||||
return False
|
||||
if not self.file_paths:
|
||||
QMessageBox.warning(self, "警告", "请选择要上传的图片文件!")
|
||||
return False
|
||||
return True
|
||||
|
||||
def start_upload(self):
|
||||
if self.upload_in_progress:
|
||||
QMessageBox.warning(self, "警告", "已有上传任务在进行中!")
|
||||
return
|
||||
|
||||
if not self.validate_inputs():
|
||||
return
|
||||
|
||||
self.upload_in_progress = True
|
||||
self.cancel_requested = False
|
||||
self.upload_btn.setEnabled(False)
|
||||
self.clear_btn.setEnabled(False)
|
||||
|
||||
# 使用QTimer在事件循环中启动上传,避免界面卡住
|
||||
QTimer.singleShot(100, self.upload_images)
|
||||
|
||||
def upload_images(self):
|
||||
try:
|
||||
# 获取选择的部件ID
|
||||
selected_part = self.part_combo.currentText()
|
||||
part_id = self.part_data.get(selected_part, "")
|
||||
if not part_id:
|
||||
raise ValueError("无法获取部件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}"
|
||||
|
||||
# 计算总批次数
|
||||
total_files = len(self.file_paths)
|
||||
total_batches = (total_files + self.batch_size - 1) // self.batch_size
|
||||
|
||||
self.log_message(f"开始上传 {total_files} 张图片,分为 {total_batches} 批,每批 {self.batch_size} 张...")
|
||||
self.log_message(f"请求URL: {url}")
|
||||
self.log_message(f"请求参数: {params}")
|
||||
|
||||
# 显示上传进度对话框
|
||||
self.progress = QMessageBox(self)
|
||||
self.progress.setWindowTitle("上传中")
|
||||
self.progress.setText(f"正在上传 {total_files} 张图片 (0/{total_batches} 批),请稍候...")
|
||||
self.progress.setStandardButtons(QMessageBox.Cancel)
|
||||
self.progress.buttonClicked.connect(self.cancel_upload)
|
||||
self.progress.show()
|
||||
|
||||
# 确保UI更新
|
||||
QApplication.processEvents()
|
||||
|
||||
# 分批上传
|
||||
success_count = 0
|
||||
fail_count = 0
|
||||
|
||||
for batch_num in range(total_batches):
|
||||
if self.cancel_requested:
|
||||
self.log_message("用户取消了上传操作")
|
||||
break
|
||||
|
||||
# 获取当前批次的文件
|
||||
start_idx = batch_num * self.batch_size
|
||||
end_idx = min((batch_num + 1) * self.batch_size, total_files)
|
||||
batch_files = self.file_paths[start_idx:end_idx]
|
||||
|
||||
# 准备图片列表参数
|
||||
batch_params = params.copy()
|
||||
for i, file_path in enumerate(batch_files):
|
||||
file_name = os.path.basename(file_path)
|
||||
batch_params[f"imageList[{i}].imageName"] = file_name
|
||||
batch_params[f"imageList[{i}].imagePath"] = file_path
|
||||
|
||||
if "imageType" in batch_params:
|
||||
batch_params[f"imageList[{i}].imageType"] = batch_params["imageType"]
|
||||
if "shootingMethod" in batch_params:
|
||||
batch_params[f"imageList[{i}].shootingMethod"] = batch_params["shootingMethod"]
|
||||
if "weather" in batch_params:
|
||||
batch_params[f"imageList[{i}].weather"] = batch_params["weather"]
|
||||
|
||||
# 准备文件数据
|
||||
files = []
|
||||
for file_path in batch_files:
|
||||
file_name = os.path.basename(file_path)
|
||||
files.append(('files', (file_name, open(file_path, 'rb'), 'image/jpeg')))
|
||||
|
||||
self.log_message(f"正在上传第 {batch_num + 1}/{total_batches} 批 ({len(batch_files)} 张图片)...")
|
||||
|
||||
# 更新进度对话框
|
||||
self.progress.setText(f"正在上传 {total_files} 张图片 ({batch_num + 1}/{total_batches} 批),请稍候...")
|
||||
QApplication.processEvents()
|
||||
|
||||
try:
|
||||
response = requests.post(
|
||||
url,
|
||||
headers={"Authorization": "null"},
|
||||
params=batch_params,
|
||||
files=files,
|
||||
timeout=30 # 设置超时时间为30秒
|
||||
)
|
||||
|
||||
if response.status_code == 200:
|
||||
self.log_message(f"第 {batch_num + 1} 批上传成功!")
|
||||
success_count += len(batch_files)
|
||||
else:
|
||||
self.log_message(f"第 {batch_num + 1} 批上传失败,状态码: {response.status_code}")
|
||||
self.log_message(f"响应内容: {response.text}")
|
||||
fail_count += len(batch_files)
|
||||
|
||||
except Exception as e:
|
||||
self.log_message(f"第 {batch_num + 1} 批上传过程中发生错误: {str(e)}")
|
||||
fail_count += len(batch_files)
|
||||
|
||||
finally:
|
||||
# 确保所有文件都被关闭
|
||||
for file in files:
|
||||
file[1][1].close()
|
||||
|
||||
self.progress.close()
|
||||
|
||||
# 上传结果统计
|
||||
if self.cancel_requested:
|
||||
self.log_message(f"上传已取消,已上传 {success_count} 张,失败 {fail_count} 张")
|
||||
QMessageBox.information(self, "上传取消", f"上传已取消,已上传 {success_count} 张,失败 {fail_count} 张")
|
||||
else:
|
||||
self.log_message(f"上传完成! 成功 {success_count} 张,失败 {fail_count} 张")
|
||||
if fail_count == 0:
|
||||
QMessageBox.information(self, "成功", f"所有图片上传成功! 共 {success_count} 张")
|
||||
else:
|
||||
QMessageBox.warning(self, "完成", f"上传完成! 成功 {success_count} 张,失败 {fail_count} 张")
|
||||
|
||||
# 上传完成后自动清空已选文件
|
||||
if not self.cancel_requested and success_count > 0:
|
||||
self.clear_selection()
|
||||
|
||||
except Exception as e:
|
||||
self.log_message(f"上传过程中发生错误: {str(e)}")
|
||||
QMessageBox.critical(self, "错误", f"上传过程中发生错误: {str(e)}")
|
||||
|
||||
finally:
|
||||
self.reset_upload_state()
|
||||
|
||||
def reset_upload_state(self):
|
||||
"""重置上传状态"""
|
||||
self.upload_in_progress = False
|
||||
self.cancel_requested = False
|
||||
self.upload_btn.setEnabled(True)
|
||||
self.clear_btn.setEnabled(True)
|
||||
|
||||
def cancel_upload(self):
|
||||
"""取消上传操作"""
|
||||
self.cancel_requested = True
|
||||
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_())
|
Loading…
Reference in New Issue