123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521 |
- from UI.workloadinfos import Ui_workloadinfos
- from .LogerinTxt import app_logger
- from PyQt6.QtCore import Qt,QTimer
- from PyQt6.QtWidgets import QWidget,QMessageBox,QTableWidgetItem,QFileDialog,QStyledItemDelegate,QStyle,QMenu
- from PyQt6 import QtCore
- from PyQt6.QtGui import QTextDocument, QTextCursor, QTextCharFormat, QColor, QTextOption, QPalette
- import requests
- import os
- import json
- import openpyxl
- import datetime
- import time
- filename = "D:\\flightinfo\\logs\\peoples.json"
- class Workloadinfos(Ui_workloadinfos, QWidget):
- def __init__(self, parent=None):
- super().__init__(parent)
- self.setupUi(self)
- self.ipinfo = None
- self.user = None
- self.selectedbc=None
- self.selectedtime=None
- self.doubleclickLock = 0
- self.headerLabel = ["序号", "交", "姓名", "备", "角色", "备", "授权", "备", "工作量", "备", "当前工作量", "备", "总工作量", "备",
- "总工时", "备", "当前工作", "备", "修正工时", "备", "修正详情", "备注信息", "备", "备", "备", "备", "备", "备",
- "1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19","20"]
- self.tableWidgetWorkload.setSortingEnabled(True)
- self.tableWidgetWorkload.setColumnCount(len(self.headerLabel))
- self.tableWidgetWorkload.verticalHeader().setVisible(False)
- self.tableWidgetWorkload.setHorizontalHeaderLabels(self.headerLabel)
- self.refresh.clicked.connect(self.refreshnow)
- self.changeupdate.clicked.connect(self.update)
- self.clear.clicked.connect(self.clearselect)
- self.autoupdateMode=False
- self.autoupdate_check.stateChanged.connect(self.on_checkbox_changed)
- # 保存当前排序状态
- self.current_sort_column = -1
- self.current_sort_order = Qt.SortOrder.AscendingOrder
- self.searchinfo.returnPressed.connect(self.search_table)
- self.searchinfo.textChanged.connect(self.search_table_empty)
- self.selectall.clicked.connect(self.selectall_funciton)
- self.load_pushbutton.clicked.connect(self.get_load)
- self.tableWidgetWorkload.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu)
- self.tableWidgetWorkload.customContextMenuRequested.connect(self.generateMenu)
- self.tableWidgetWorkload.horizontalHeader().sortIndicatorChanged.connect(self.on_sort_changed)
- self.changeupdate.clicked.connect(self.changeupdate_Function)
- self.tableWidgetWorkload.cellDoubleClicked.connect(self.itemclick2)
- def start(self):
- self.show()
- self.peopleresold = self.read_json_to_list()
- try:
- ip = "http://" + str(self.ipinfo) + "/static/getPglistInDatabase"
- self.peopleres = requests.get(url=ip, timeout=30).json()['返回值']
- #print(self.peopleres)
- except Exception as e:
- QMessageBox.warning(self, "提示", "服务器连接超时,请联系管理员检查服务器!")
- app_logger.log_error(e)
- self.peopleres = []
- self.peopleselect=self.peopleresold if self.peopleresold else self.peopleres
- self.comboBox_peoplelist.addItems(self.peopleres)
- self.set_initial_selection()
- self.refreshnow()
- self.serchTimer = QTimer()
- self.serchTimer.start(120 * 1000)
- self.serchTimer.timeout.connect(self.autoupdate)
- def itemclick2(self, row, column):
- try:
- # print(self.doubleclickLock)
- if column == 21 and self.doubleclickLock == 0:
- self.doubleclickLockUpdate=1
- self.clickrow = row
- self.clickcolumn = column
- self.olditem = self.tableWidgetWorkload.item(row, column).text()
- item = self.tableWidgetWorkload.item(row, column)
- # 如果单元格对象不存在,则返回默认的背景色
- if not item:
- self.color=self.tableWidgetWorkload.palette().color(QPalette.Base)
- else:
- # 获取并返回单元格的背景色
- self.color = item.background()
- self.tableWidgetWorkload.cellChanged.connect(self.cellchanged)
- else:
- self.doubleclickLockUpdate = 0
- except Exception as e:
- app_logger.log_error(e)
- def cellchanged(self, row, column):
- if self.clickrow == row and self.clickcolumn == column :
- self.clickrow = None
- self.clickcolumn = None
- try:
- self.doubleclickLock = 1
- self.newitem = self.tableWidgetWorkload.item(row, column).text().replace("\"","*").replace("\\",";").replace("\'","*").replace("/","、").replace("#","*")
- name = self.tableWidgetWorkload.item(row, 2).text()
- if column == 21 and self.olditem != self.newitem:
- item = self.tableWidgetWorkload.item(row, column)
- if item.text() != "":
- text = item.text().replace("\"", "*").replace("\\", ";").replace("\'", "*").replace("/", "、").replace("#", "*")
- else:
- text = "清空项目12345678987654321"
- ip = "http://" + str(self.ipinfo) + "/static/updateNoteItem/" + "%s/" % str(text) + "%s" % str(name)
- # print(ip)
- ip2 = "http://" + str(self.ipinfo) + "/static/insertLogs2/" + "排班辅助%s的备注模块:由%s变更为%s/" % (name,self.olditem, self.newitem) + "%s/" % str(self.user) + "%s" % str(datetime.datetime.now())
- try:
- requests.get(url=ip, timeout=30).json()
- requests.get(url=ip2, timeout=30).json()
- self.tableWidgetWorkload.setItem(int(row), column, QTableWidgetItem(str(self.newitem)))
- self.tableWidgetWorkload.item(int(row), column).setBackground(QColor("yellow"))
- self.tableWidgetWorkload.item(int(row), column).setTextAlignment(Qt.AlignmentFlag.AlignCenter)
- except Exception as e:
- app_logger.log_error(e)
- QMessageBox.warning(self, "提示", "服务器连接超时,请联系管理员检查服务器!")
- self.doubleclickLockUpdate = 0
- self.doubleclickLock = 0
- self.tableWidgetWorkload.cellChanged.disconnect(self.cellchanged)
- except Exception as e:
- self.doubleclickLockUpdate = 0
- self.clickrow = None
- self.clickcolumn = None
- app_logger.log_error(e)
- try:
- self.tableWidgetWorkload.cellChanged.disconnect(self.cellchanged)
- except:
- pass
- self.tableWidgetWorkload.setItem(int(row), column, QTableWidgetItem(str(self.olditem)))
- self.tableWidgetWorkload.item(int(row), column).setBackground(QColor(self.color))
- self.tableWidgetWorkload.item(int(row), column).setTextAlignment(Qt.AlignmentFlag.AlignCenter)
- app_logger.log_error(e)
- self.doubleclickLock = 0
- def changeupdate_Function(self):
- day=datetime.datetime.now().strftime("%Y%m%d")
- info = self.changeinfo.text().strip().lower()
- people = self.changepeople.text().strip()
- costtime = self.changevalue.text().strip().lower()
- try:
- costtime = float(costtime)
- if info and people and costtime:
- timestr=str(int(time.time()*1000))
- id= f"人工修正-{info}-{timestr}-{people}"
- data0={
- "id": id,
- 'people':people,
- 'costtime':costtime,
- 'info':info,
- 'day':day
- }
- try:
- ip = "http://" + str(self.ipinfo) + "/static/manchangecosttime"
- data = json.dumps(data0)
- res = requests.post(url=ip, data=data, timeout=30).json()
- if res["返回值"] == "ok":
- QMessageBox.information(self, "提示", "操作成功!")
- self.refreshnow()
- else:
- QMessageBox.warning(self, "提示", "操作失败!")
- except Exception as e:
- QMessageBox.warning(self, "提示", "服务器连接超时,请联系管理员检查服务器!")
- app_logger.log_error(e)
- else:
- QMessageBox.warning(self,"警告", "请填写完整信息!!!")
- except ValueError:
- QMessageBox.warning(self,"警告", "工时内请填写数字!!!")
- def generateMenu(self, pos):
- try:
- nowDay = datetime.date.today().strftime("%Y%m%d")
- a_str = nowDay + " 09:00:00"
- b_str = nowDay + " 20:30:00"
- a = datetime.datetime.strptime(a_str, "%Y%m%d %H:%M:%S")
- b = datetime.datetime.strptime(b_str, "%Y%m%d %H:%M:%S")
- nowtime = datetime.datetime.now()
- passday = (nowtime - datetime.timedelta(days=4)).strftime("%Y%m%d")
- if a < nowtime < b:
- for i in self.tableWidgetWorkload.selectionModel().selection().indexes():
- menu = QMenu()
- item = menu.addAction('上个班未交班')
- item2 = menu.addAction('上个班交班')
- screenPos = self.tableWidgetWorkload.mapToGlobal(pos)
- action = menu.exec(screenPos)
- rowIndex = i.row()
- taskids = self.tableWidgetWorkload.item(rowIndex, 3).text()
- handstsNow=self.tableWidgetWorkload.item(rowIndex, 1).text()
- name=self.tableWidgetWorkload.item(rowIndex, 2).text()
- data={
- "ids":taskids,
- "type":handstsNow,
- "name":name,
- "date":passday,
- }
- if action == item:
- if handstsNow == "Y":
- self.handoverflight(data)
- self.refreshnow()
- else:
- QMessageBox.warning(self, "警告", f"未查询到{name}交班记录,无需取消交班")
- return
- elif action == item2:
- if handstsNow != "Y":
- self.handoverflight(data)
- self.refreshnow()
- else:
- QMessageBox.warning(self, "警告", f"经查询{name}已被记录交班,不用重复记录")
- return
- else:
- return
- except Exception as e:
- app_logger.log_error(e)
- def get_load(self):
- try:
- peoples = []
- fileName, _ = QFileDialog.getOpenFileName(self, '打开文件', '/')
- ext = os.path.splitext(fileName)[1].lower()
- if ext == ".xlsx":
- workbook = openpyxl.load_workbook(filename=fileName)
- mysheet = workbook.active
- myrows = list(mysheet.values)
- if myrows[0][0] != ""and myrows[0][0] != None:
- for i in myrows:
- if i[0] != ""and i[0] != None:
- peoples.append(i[0])
- if peoples:
- self.peopleselect=peoples
- self.write_list_to_json(peoples)
- self.set_initial_selection()
- self.refreshnow()
- else:
- QMessageBox.information(self, "提示", "人员名单导入为空,请重新录入")
- else:
- QMessageBox.warning(self, "警告", "请使用xlsx文件,在第一列输入人名再导入,人名需要带字母")
- return
- except Exception as e:
- app_logger.log_error(e)
- def selectall_funciton(self):
- self.peopleselect=self.peopleres
- self.write_list_to_json(self.peopleselect)
- self.set_initial_selection()
- def search_table_empty(self):
- """根据搜索框内容过滤表格数据"""
- search_text = self.searchinfo.text().strip().lower()
- if not search_text:
- # 如果搜索框为空,显示所有行
- for row in range(self.tableWidgetWorkload.rowCount()):
- self.tableWidgetWorkload.setRowHidden(row, False)
- return
- def search_table(self):
- """根据搜索框内容过滤表格数据"""
- search_text = self.searchinfo.text().strip().lower()
- if not search_text:
- # 如果搜索框为空,显示所有行
- for row in range(self.tableWidgetWorkload.rowCount()):
- self.tableWidgetWorkload.setRowHidden(row, False)
- return
- # 遍历表格所有单元格进行搜索
- for row in range(self.tableWidgetWorkload.rowCount()):
- row_hidden = True
- for col in range(self.tableWidgetWorkload.columnCount()):
- item = self.tableWidgetWorkload.item(row, col)
- if item and search_text in item.text().lower():
- row_hidden = False
- break
- self.tableWidgetWorkload.setRowHidden(row, row_hidden)
- def on_sort_changed(self, logicalIndex, order):
- """记录当前的排序状态"""
- self.current_sort_column = logicalIndex
- self.current_sort_order = order
- def on_checkbox_changed(self, state):
- if state != 0:
- self.autoupdateMode = True
- else:
- self.autoupdateMode = False
- def ensure_file_exists(self):
- """确保文件存在,不存在则创建空文件"""
- directory = os.path.dirname(filename)
- # 如果目录不存在,则创建目录
- if directory and not os.path.exists(directory):
- os.makedirs(directory)
- # 如果文件不存在,则创建空文件
- if not os.path.exists(filename):
- with open(filename, 'w', encoding='utf-8') as f:
- f.write("[]") #
- def write_list_to_json(self,data_list):
- """将 Python 列表写入 JSON 文件"""
- try:
- self.ensure_file_exists() # 确保文件存在
- with open(filename, 'w', encoding='utf-8') as f:
- json.dump(data_list, f, ensure_ascii=False)
- #print(f"数据已成功写入 {filename}")
- except Exception as e:
- app_logger.log_error(e)
- #print(f"写入文件时出错: {e}")
- def read_json_to_list(self):
- """从 JSON 文件读取数据并转换为 Python 列表"""
- try:
- self.ensure_file_exists() # 确保文件存在
- with open(filename, 'r', encoding='utf-8') as f:
- data = json.load(f)
- return data
- except json.JSONDecodeError:
- #print(f"文件 {filename} 格式不是有效的 JSON,将重置为空列表")
- # 重置文件为空白列表
- self.write_list_to_json([])
- return None
- except Exception as e:
- return None
- def set_initial_selection(self):
- """设置多选ComboBox的初始选中值"""
- for i in range(self.comboBox_peoplelist.model().rowCount()):
- item = self.comboBox_peoplelist.model().item(i)
- if item.text() in self.peopleselect:
- item.setCheckState(QtCore.Qt.CheckState.Checked)
- else:
- item.setCheckState(QtCore.Qt.CheckState.Unchecked)
- self.comboBox_peoplelist.update_text()
- def getdatas(self):
- try:
- ip = "http://" + str(self.ipinfo) + "/static/getworkload"
- data = json.dumps(self.peopleselect)
- res = requests.post(url=ip, data=data, timeout=30).json()
- return res
- except Exception as e:
- QMessageBox.warning(self, "提示", "服务器连接超时,请联系管理员检查服务器!")
- app_logger.log_error(e)
- def handoverflight(self,data0):
- try:
- ip = "http://" + str(self.ipinfo) + "/static/handoverflight"
- data = json.dumps(data0)
- res = requests.post(url=ip, data=data, timeout=30).json()
- if res["返回值"] == "ok":
- QMessageBox.information(self, "提示", "操作成功!")
- else:
- QMessageBox.warning(self, "提示", "操作失败!")
- except Exception as e:
- QMessageBox.warning(self, "提示", "服务器连接超时,请联系管理员检查服务器!")
- app_logger.log_error(e)
- def autoupdate(self):
- if self.autoupdateMode:
- res = self.getdatas()
- self.tableDisplay(res)
- if self.searchinfo.text():
- self.search_table()
- def tableDisplay(self,displaydata):
- try:
- if displaydata:
- self.tableWidgetWorkload.setSortingEnabled(False)
- # 清除原有数据
- self.tableWidgetWorkload.setRowCount(0)
- # 设置列数(假设数据是二维列表,第一行为表头)
- self.tableWidgetWorkload.setRowCount(len(displaydata))
- for row in range(len(displaydata)):
- for col in range(len(self.headerLabel)):
- item = QTableWidgetItem(str(displaydata[str(row)][str(col)]))
- self.tableWidgetWorkload.setItem(row, col, item)
- if col == 16 and "无" not in str(displaydata[str(row)][str(col)]):
- item.setForeground(QColor("red"))
- font = item.font()
- item.setFont(font)
- elif col == 8 :
- item.setForeground(QColor("green"))
- font = item.font()
- font.setBold(True)
- item.setFont(font)
- elif col == 21 and str(displaydata[str(row)][str(col)]) != "" :
- item.setBackground(QColor("yellow"))
- elif col == 1 and str(displaydata[str(row)][str(col)]) == "Y":
- item.setBackground(QColor("yellow"))
- if col not in [5]:
- self.tableWidgetWorkload.item(int(row), col).setTextAlignment(Qt.AlignmentFlag.AlignCenter)
- else:
- self.tableWidgetWorkload.item(int(row), col).setTextAlignment(Qt.AlignmentFlag.AlignTop | Qt.AlignmentFlag.AlignCenter)
- self.tableWidgetWorkload.setRowHeight(int(row), 35)
- settips = {1: "3", 14: "20"}
- for key, value in settips.items():
- if self.tableWidgetWorkload.item(int(row), key):
- self.tableWidgetWorkload.item(int(row), key).setToolTip("%s" % (str(displaydata[str(row)][str(value)])))
- self.tableWidgetWorkload.setItemDelegate(ColoredTextDelegate())
- self.tableWidgetWorkload.resizeColumnsToContents()
- self.tableWidgetWorkload.setWordWrap(True)
- self.tableWidgetWorkload.setColumnWidth(6, 100)
- for i in range(len(self.headerLabel)):
- if i in [3,5,7,9,11,13,15,17,19,22,23,24,25,26,27,10,12,18,20]:
- self.tableWidgetWorkload.setColumnHidden(i, True)
- else:
- self.tableWidgetWorkload.setColumnHidden(i, False)
- self.tableWidgetWorkload.setSortingEnabled(True)
- except Exception as e:
- app_logger.log_error(e)
- self.tableWidgetWorkload.setSortingEnabled(True)
- def refreshnow(self):
- self.peopleselect = self.comboBox_peoplelist.get_selected_items()
- self.write_list_to_json(self.peopleselect)
- res=self.getdatas()
- self.tableDisplay(res)
- if self.searchinfo.text():
- self.search_table()
- def clearselect(self):
- self.peopleselect=[]
- self.write_list_to_json(self.peopleselect)
- self.set_initial_selection()
- class ColoredTextDelegate(QStyledItemDelegate):
- def paint(self, painter, option, index):# 保存painter状态
- painter.save()
- # 设置交替行颜色
- palette = option.palette
- if index.row() % 2 == 1:
- bg_color = palette.color(QPalette.ColorRole.AlternateBase)
- else:
- bg_color = palette.color(QPalette.ColorRole.Base)
- # 绘制背景(考虑选中状态)
- if option.state & QStyle.StateFlag.State_Selected:
- painter.fillRect(option.rect, palette.highlight())
- else:
- painter.fillRect(option.rect, bg_color)
- if index.column() in [28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47]:
- # 获取单元格文本
- text = index.data(Qt.ItemDataRole.DisplayRole) or ""
- if "预排" in text:
- painter.fillRect(option.rect, QColor("yellow"))
- # 设置文本绘制选项
- painter.save()
- text_option = QTextOption()
- text_option.setAlignment(Qt.AlignmentFlag.AlignCenter)
- doc = QTextDocument()
- doc.setDefaultTextOption(text_option)
- doc.setTextWidth(option.rect.width())
- default_format = QTextCharFormat()
- default_format.setForeground(QColor("gray"))
- font = default_format.font()
- font.setPointSize(8)
- default_format.setFont(font)
- balck_format = QTextCharFormat()
- balck_format.setForeground(QColor("balck"))
- font = balck_format.font()
- font.setPointSize(10)
- balck_format.setFont(font)
- # 插入带格式文本
- cursor = QTextCursor(doc)
- cursor.insertText(text[:5], balck_format)
- cursor.insertText(text[5:], default_format)
- # 绘制文档
- painter.save()
- painter.translate(option.rect.topLeft())
- doc.drawContents(painter)
- painter.restore()
- elif index.column() == 8:
- text = index.data(Qt.ItemDataRole.DisplayRole) or ""
- start = text.find("(")
- end = text.find(")")
- # 设置文本绘制选项
- painter.save()
- text_option = QTextOption()
- text_option.setAlignment(Qt.AlignmentFlag.AlignCenter)
- doc = QTextDocument()
- doc.setDefaultTextOption(text_option)
- doc.setTextWidth(option.rect.width())
- default_format = QTextCharFormat()
- default_format.setForeground(QColor("red"))
- font = default_format.font()
- font.setBold(True)
- default_format.setFont(font)
- balck_format = QTextCharFormat()
- balck_format.setForeground(QColor("balck"))
- # 插入带格式文本
- cursor = QTextCursor(doc)
- cursor.insertText(text[:start+1], balck_format)
- cursor.insertText(text[start+1:end], default_format)
- cursor.insertText(text[end:], balck_format)
- # 计算垂直居中位置
- text_height = doc.size().height()
- y_offset = (option.rect.height() - text_height) / 2
- # 绘制文本
- painter.translate(option.rect.x(), option.rect.y() + y_offset)
- doc.drawContents(painter)
- painter.restore()
- else:
- # 其他单元格使用默认绘制
- super().paint(painter, option, index)
- def sizeHint(self, option, index):
- # 确保单元格有合适的大小
- if index.column() == 8:
- text = index.data(Qt.ItemDataRole.DisplayRole) or ""
- doc = QTextDocument()
- doc.setPlainText(text)
- doc.setTextWidth(option.rect.width())
- return doc.size().toSize()
- return super().sizeHint(option, index)
|