rambo 3 weeks ago
commit
641dd672fd

+ 9 - 0
.gitignore

@@ -0,0 +1,9 @@
+**__pycache__
+dist/*
+build/*
+key
+temp
+venv/
+.venv/
+.vscode/
+.idea/

+ 79 - 0
UI/login.py

@@ -0,0 +1,79 @@
+# -*- coding: utf-8 -*-
+
+################################################################################
+## Form generated from reading UI file 'login.ui'
+##
+## Created by: Qt User Interface Compiler version 6.7.2
+##
+## WARNING! All changes made in this file will be lost when recompiling UI file!
+################################################################################
+
+from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale,
+    QMetaObject, QObject, QPoint, QRect,
+    QSize, QTime, QUrl, Qt)
+from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor,
+    QFont, QFontDatabase, QGradient, QIcon,
+    QImage, QKeySequence, QLinearGradient, QPainter,
+    QPalette, QPixmap, QRadialGradient, QTransform)
+from PySide6.QtWidgets import (QApplication, QLabel, QLineEdit, QPushButton,
+    QRadioButton, QSizePolicy, QWidget)
+
+class Ui_Form(object):
+    def setupUi(self, Form):
+        if not Form.objectName():
+            Form.setObjectName(u"Form")
+        Form.resize(406, 287)
+        Form.setStyleSheet(u"background-color: rgb(255, 255, 255);")
+        self.pushButton = QPushButton(Form)
+        self.pushButton.setObjectName(u"pushButton")
+        self.pushButton.setGeometry(QRect(100, 180, 271, 41))
+        self.pushButton.setStyleSheet(u"background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 rgba(255, 137, 27, 255), stop:1 rgba(255, 93, 1, 255));\n"
+"color: rgb(255, 255, 255);\n"
+"border-radius: 5px;  border: 2px groove gray;\n"
+"border:0px;\n"
+"font: 75 14pt \"Adobe Arabic\";")
+        self.lineEdit = QLineEdit(Form)
+        self.lineEdit.setObjectName(u"lineEdit")
+        self.lineEdit.setGeometry(QRect(100, 50, 271, 41))
+        self.label_2 = QLabel(Form)
+        self.label_2.setObjectName(u"label_2")
+        self.label_2.setGeometry(QRect(20, 50, 71, 41))
+        self.label_3 = QLabel(Form)
+        self.label_3.setObjectName(u"label_3")
+        self.label_3.setGeometry(QRect(20, 110, 71, 41))
+        self.lineEdit_2 = QLineEdit(Form)
+        self.lineEdit_2.setObjectName(u"lineEdit_2")
+        self.lineEdit_2.setGeometry(QRect(100, 110, 161, 41))
+        self.lineEdit_2.setEchoMode(QLineEdit.Password)
+        self.label_4 = QLabel(Form)
+        self.label_4.setObjectName(u"label_4")
+        self.label_4.setGeometry(QRect(0, 250, 401, 31))
+        self.radioButton = QRadioButton(Form)
+        self.radioButton.setObjectName(u"radioButton")
+        self.radioButton.setGeometry(QRect(100, 10, 101, 41))
+        self.radioButton.setChecked(True)
+        self.radioButton_2 = QRadioButton(Form)
+        self.radioButton_2.setObjectName(u"radioButton_2")
+        self.radioButton_2.setGeometry(QRect(200, 10, 101, 41))
+        self.pushButton_2 = QPushButton(Form)
+        self.pushButton_2.setObjectName(u"pushButton_2")
+        self.pushButton_2.setGeometry(QRect(260, 120, 111, 21))
+        self.pushButton_2.setStyleSheet(u"border-radius: 5px;  border: 2px groove gray;\n"
+"border:0px;")
+
+        self.retranslateUi(Form)
+
+        QMetaObject.connectSlotsByName(Form)
+    # setupUi
+
+    def retranslateUi(self, Form):
+        Form.setWindowTitle(QCoreApplication.translate("Form", u"Form", None))
+        self.pushButton.setText(QCoreApplication.translate("Form", u"\u767b\u5f55", None))
+        self.label_2.setText(QCoreApplication.translate("Form", u"\u624b\u673a\u53f7\uff1a", None))
+        self.label_3.setText(QCoreApplication.translate("Form", u"\u5bc6\u7801\uff1a", None))
+        self.label_4.setText("")
+        self.radioButton.setText(QCoreApplication.translate("Form", u"\u77ed\u4fe1\u9a8c\u8bc1\u7801\u767b\u5f55", None))
+        self.radioButton_2.setText(QCoreApplication.translate("Form", u"\u8d26\u53f7\u5bc6\u7801\u767b\u5f55", None))
+        self.pushButton_2.setText(QCoreApplication.translate("Form", u"\u83b7\u53d6\u9a8c\u8bc1\u7801", None))
+    # retranslateUi
+

+ 150 - 0
UI/login.ui

@@ -0,0 +1,150 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Form</class>
+ <widget class="QWidget" name="Form">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>406</width>
+    <height>287</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Form</string>
+  </property>
+  <property name="styleSheet">
+   <string notr="true">background-color: rgb(255, 255, 255);</string>
+  </property>
+  <widget class="QPushButton" name="pushButton">
+   <property name="geometry">
+    <rect>
+     <x>100</x>
+     <y>180</y>
+     <width>271</width>
+     <height>41</height>
+    </rect>
+   </property>
+   <property name="styleSheet">
+    <string notr="true">background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 rgba(255, 137, 27, 255), stop:1 rgba(255, 93, 1, 255));
+color: rgb(255, 255, 255);
+border-radius: 5px;  border: 2px groove gray;
+border:0px;
+font: 75 14pt &quot;Adobe Arabic&quot;;</string>
+   </property>
+   <property name="text">
+    <string>登录</string>
+   </property>
+  </widget>
+  <widget class="QLineEdit" name="lineEdit">
+   <property name="geometry">
+    <rect>
+     <x>100</x>
+     <y>50</y>
+     <width>271</width>
+     <height>41</height>
+    </rect>
+   </property>
+  </widget>
+  <widget class="QLabel" name="label_2">
+   <property name="geometry">
+    <rect>
+     <x>20</x>
+     <y>50</y>
+     <width>71</width>
+     <height>41</height>
+    </rect>
+   </property>
+   <property name="text">
+    <string>手机号:</string>
+   </property>
+  </widget>
+  <widget class="QLabel" name="label_3">
+   <property name="geometry">
+    <rect>
+     <x>20</x>
+     <y>110</y>
+     <width>71</width>
+     <height>41</height>
+    </rect>
+   </property>
+   <property name="text">
+    <string>密码:</string>
+   </property>
+  </widget>
+  <widget class="QLineEdit" name="lineEdit_2">
+   <property name="geometry">
+    <rect>
+     <x>100</x>
+     <y>110</y>
+     <width>161</width>
+     <height>41</height>
+    </rect>
+   </property>
+   <property name="echoMode">
+    <enum>QLineEdit::Password</enum>
+   </property>
+  </widget>
+  <widget class="QLabel" name="label_4">
+   <property name="geometry">
+    <rect>
+     <x>0</x>
+     <y>250</y>
+     <width>401</width>
+     <height>31</height>
+    </rect>
+   </property>
+   <property name="text">
+    <string/>
+   </property>
+  </widget>
+  <widget class="QRadioButton" name="radioButton">
+   <property name="geometry">
+    <rect>
+     <x>100</x>
+     <y>10</y>
+     <width>101</width>
+     <height>41</height>
+    </rect>
+   </property>
+   <property name="text">
+    <string>短信验证码登录</string>
+   </property>
+   <property name="checked">
+    <bool>true</bool>
+   </property>
+  </widget>
+  <widget class="QRadioButton" name="radioButton_2">
+   <property name="geometry">
+    <rect>
+     <x>200</x>
+     <y>10</y>
+     <width>101</width>
+     <height>41</height>
+    </rect>
+   </property>
+   <property name="text">
+    <string>账号密码登录</string>
+   </property>
+  </widget>
+  <widget class="QPushButton" name="pushButton_2">
+   <property name="geometry">
+    <rect>
+     <x>260</x>
+     <y>120</y>
+     <width>111</width>
+     <height>21</height>
+    </rect>
+   </property>
+   <property name="styleSheet">
+    <string notr="true">border-radius: 5px;  border: 2px groove gray;
+border:0px;</string>
+   </property>
+   <property name="text">
+    <string>获取验证码</string>
+   </property>
+  </widget>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>

+ 268 - 0
UI/main_ui.py

@@ -0,0 +1,268 @@
+# -*- coding: utf-8 -*-
+
+################################################################################
+## Form generated from reading UI file 'main_ui.ui'
+##
+## Created by: Qt User Interface Compiler version 6.7.2
+##
+## WARNING! All changes made in this file will be lost when recompiling UI file!
+################################################################################
+
+from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale,
+    QMetaObject, QObject, QPoint, QRect,
+    QSize, QTime, QUrl, Qt)
+from PySide6.QtGui import (QAction, QBrush, QColor, QConicalGradient,
+    QCursor, QFont, QFontDatabase, QGradient,
+    QIcon, QImage, QKeySequence, QLinearGradient,
+    QPainter, QPalette, QPixmap, QRadialGradient,
+    QTransform)
+from PySide6.QtWidgets import (QApplication, QLabel, QMainWindow, QMenu,
+    QMenuBar, QProgressBar, QPushButton, QScrollArea,
+    QSizePolicy, QStatusBar, QWidget)
+
+class Ui_MainWindow(object):
+    def setupUi(self, MainWindow):
+        if not MainWindow.objectName():
+            MainWindow.setObjectName(u"MainWindow")
+        MainWindow.resize(571, 365)
+        MainWindow.setStyleSheet(u"background-color: #ebf1f7;")
+        self.action = QAction(MainWindow)
+        self.action.setObjectName(u"action")
+        self.action_2 = QAction(MainWindow)
+        self.action_2.setObjectName(u"action_2")
+        self.action_3 = QAction(MainWindow)
+        self.action_3.setObjectName(u"action_3")
+        self.action_4 = QAction(MainWindow)
+        self.action_4.setObjectName(u"action_4")
+        self.action_5 = QAction(MainWindow)
+        self.action_5.setObjectName(u"action_5")
+        self.action_6 = QAction(MainWindow)
+        self.action_6.setObjectName(u"action_6")
+        self.action_7 = QAction(MainWindow)
+        self.action_7.setObjectName(u"action_7")
+        self.action_8 = QAction(MainWindow)
+        self.action_8.setObjectName(u"action_8")
+        self.action_9 = QAction(MainWindow)
+        self.action_9.setObjectName(u"action_9")
+        self.action_10 = QAction(MainWindow)
+        self.action_10.setObjectName(u"action_10")
+        self.action_11 = QAction(MainWindow)
+        self.action_11.setObjectName(u"action_11")
+        self.centralwidget = QWidget(MainWindow)
+        self.centralwidget.setObjectName(u"centralwidget")
+        self.widget = QWidget(self.centralwidget)
+        self.widget.setObjectName(u"widget")
+        self.widget.setGeometry(QRect(10, 10, 391, 41))
+        self.widget.setStyleSheet(u"background-color: #f7fcfd;\n"
+"border-radius: 5px;\n"
+"border: 2px groove gray;\n"
+"border:0px;")
+        self.progressBar = QProgressBar(self.widget)
+        self.progressBar.setObjectName(u"progressBar")
+        self.progressBar.setGeometry(QRect(10, 20, 371, 16))
+        self.progressBar.setStyleSheet(u"QProgressBar {\n"
+"    border: 0px solid grey;\n"
+"    color:rgb(255,255,255);\n"
+"    border-radius: 10px;\n"
+"    text-align: center;\n"
+"	border: 2px groove gray;\n"
+"	border:0px;\n"
+"    background-color: #6272a4;\n"
+"            }\n"
+"QProgressBar::chunk {\n"
+"    border-radius: 10px;\n"
+"    background-color: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 0, stop: 0 #fa78c9, stop: 1 #b058fb);\n"
+"            }")
+        self.progressBar.setValue(24)
+        self.label = QLabel(self.widget)
+        self.label.setObjectName(u"label")
+        self.label.setGeometry(QRect(10, 0, 371, 16))
+        self.label.setStyleSheet(u"font: 10pt \"Adobe \u9ed1\u4f53 Std R\";")
+        self.label_2 = QLabel(self.centralwidget)
+        self.label_2.setObjectName(u"label_2")
+        self.label_2.setGeometry(QRect(420, 10, 91, 31))
+        self.label_2.setStyleSheet(u"background-color: #f7fcfd;\n"
+"border-radius: 5px;\n"
+"border: 2px groove gray;\n"
+"border:0px;")
+        self.label_2.setAlignment(Qt.AlignCenter)
+        self.label_3 = QLabel(self.centralwidget)
+        self.label_3.setObjectName(u"label_3")
+        self.label_3.setGeometry(QRect(520, 10, 31, 31))
+        self.label_3.setStyleSheet(u"background-color: #f7fcfd;\n"
+"border-radius: 5px;\n"
+"border: 2px groove gray;\n"
+"border:0px;")
+        self.label_3.setAlignment(Qt.AlignCenter)
+        self.pushButton_6 = QPushButton(self.centralwidget)
+        self.pushButton_6.setObjectName(u"pushButton_6")
+        self.pushButton_6.setGeometry(QRect(420, 270, 131, 31))
+        self.pushButton_6.setStyleSheet(u"background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 rgba(255, 137, 27, 255), stop:1 rgba(255, 93, 1, 255));\n"
+"color: rgb(255, 255, 255);\n"
+"border-radius: 5px;  border: 2px groove gray;\n"
+"border:0px;")
+        self.pushButton = QPushButton(self.centralwidget)
+        self.pushButton.setObjectName(u"pushButton")
+        self.pushButton.setGeometry(QRect(420, 250, 131, 31))
+        self.pushButton.setStyleSheet(u"background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 rgba(255, 137, 27, 255), stop:1 rgba(255, 93, 1, 255));\n"
+"color: rgb(255, 255, 255);\n"
+"border-radius: 5px;  border: 2px groove gray;\n"
+"border:0px;")
+        self.label_7 = QLabel(self.centralwidget)
+        self.label_7.setObjectName(u"label_7")
+        self.label_7.setGeometry(QRect(420, 45, 131, 21))
+        self.label_7.setStyleSheet(u"background-color: #f7fcfd;\n"
+"border-radius: 5px;\n"
+"border: 2px groove gray;\n"
+"border:0px;")
+        self.label_7.setAlignment(Qt.AlignCenter)
+        self.label_10 = QLabel(self.centralwidget)
+        self.label_10.setObjectName(u"label_10")
+        self.label_10.setGeometry(QRect(420, 70, 131, 71))
+        self.label_10.setStyleSheet(u"background-color: #f7fcfd;\n"
+"border-radius: 5px;\n"
+"border: 2px groove gray;\n"
+"border:0px;")
+        self.label_10.setAlignment(Qt.AlignCenter)
+        self.label_9 = QLabel(self.centralwidget)
+        self.label_9.setObjectName(u"label_9")
+        self.label_9.setGeometry(QRect(430, 80, 41, 16))
+        self.label_9.setStyleSheet(u"background-color: rgb(255, 255, 255,0);\n"
+"font: 7pt \"Adobe Arabic\";")
+        self.label_9.setAlignment(Qt.AlignCenter)
+        self.label_11 = QLabel(self.centralwidget)
+        self.label_11.setObjectName(u"label_11")
+        self.label_11.setGeometry(QRect(430, 100, 41, 20))
+        self.label_11.setStyleSheet(u"background-color: rgb(255, 255, 255,0);\n"
+"font: 15pt \"Adobe \u9ed1\u4f53 Std R\";")
+        self.label_11.setAlignment(Qt.AlignCenter)
+        self.label_12 = QLabel(self.centralwidget)
+        self.label_12.setObjectName(u"label_12")
+        self.label_12.setGeometry(QRect(500, 80, 41, 16))
+        self.label_12.setStyleSheet(u"background-color: rgb(255, 255, 255,0);\n"
+"font: 7pt \"Adobe Arabic\";")
+        self.label_12.setAlignment(Qt.AlignCenter)
+        self.label_13 = QLabel(self.centralwidget)
+        self.label_13.setObjectName(u"label_13")
+        self.label_13.setGeometry(QRect(500, 100, 41, 20))
+        self.label_13.setStyleSheet(u"background-color: rgb(255, 255, 255,0);\n"
+"font: 15pt \"Adobe \u9ed1\u4f53 Std R\";")
+        self.label_13.setAlignment(Qt.AlignCenter)
+        self.scrollArea = QScrollArea(self.centralwidget)
+        self.scrollArea.setObjectName(u"scrollArea")
+        self.scrollArea.setGeometry(QRect(10, 60, 391, 261))
+        self.scrollArea.setStyleSheet(u"background-color: #f7fcfd;\n"
+"border-radius: 5px;\n"
+"border: 2px groove gray;\n"
+"border:0px;")
+        self.scrollArea.setWidgetResizable(True)
+        self.scrollAreaWidgetContents = QWidget()
+        self.scrollAreaWidgetContents.setObjectName(u"scrollAreaWidgetContents")
+        self.scrollAreaWidgetContents.setGeometry(QRect(0, 0, 378, 8000))
+        self.scrollAreaWidgetContents.setMinimumSize(QSize(0, 8000))
+        self.widget_2 = QWidget(self.scrollAreaWidgetContents)
+        self.widget_2.setObjectName(u"widget_2")
+        self.widget_2.setGeometry(QRect(10, 10, 351, 200))
+        sizePolicy = QSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Preferred)
+        sizePolicy.setHorizontalStretch(0)
+        sizePolicy.setVerticalStretch(0)
+        sizePolicy.setHeightForWidth(self.widget_2.sizePolicy().hasHeightForWidth())
+        self.widget_2.setSizePolicy(sizePolicy)
+        self.label_5 = QLabel(self.widget_2)
+        self.label_5.setObjectName(u"label_5")
+        self.label_5.setGeometry(QRect(50, 90, 271, 21))
+        self.label_5.setStyleSheet(u"font: 10pt \"Adobe \u9ed1\u4f53 Std R\";")
+        self.label_5.setAlignment(Qt.AlignCenter)
+        self.scrollArea.setWidget(self.scrollAreaWidgetContents)
+        self.label_14 = QLabel(self.centralwidget)
+        self.label_14.setObjectName(u"label_14")
+        self.label_14.setGeometry(QRect(430, 120, 41, 16))
+        self.label_14.setStyleSheet(u"background-color: rgb(255, 255, 255,0);\n"
+"font: 7pt \"Adobe Arabic\";\n"
+"color: rgb(0, 85, 255);")
+        self.label_14.setAlignment(Qt.AlignCenter)
+        self.widget_3 = QWidget(self.centralwidget)
+        self.widget_3.setObjectName(u"widget_3")
+        self.widget_3.setGeometry(QRect(10, 330, 391, 41))
+        self.widget_3.setStyleSheet(u"background-color: #f7fcfd;\n"
+"border-radius: 5px;\n"
+"border: 2px groove gray;\n"
+"border:0px;")
+        self.label_4 = QLabel(self.widget_3)
+        self.label_4.setObjectName(u"label_4")
+        self.label_4.setGeometry(QRect(10, 10, 241, 21))
+        self.label_4.setStyleSheet(u"font: 10pt \"Adobe \u9ed1\u4f53 Std R\";")
+        self.label_8 = QLabel(self.widget_3)
+        self.label_8.setObjectName(u"label_8")
+        self.label_8.setGeometry(QRect(270, 10, 51, 21))
+        self.label_8.setStyleSheet(u"font: 10pt \"Adobe \u9ed1\u4f53 Std R\";")
+        self.label_15 = QLabel(self.widget_3)
+        self.label_15.setObjectName(u"label_15")
+        self.label_15.setGeometry(QRect(330, 10, 51, 21))
+        self.label_15.setStyleSheet(u"font: 10pt \"Adobe \u9ed1\u4f53 Std R\";")
+        MainWindow.setCentralWidget(self.centralwidget)
+        self.menubar = QMenuBar(MainWindow)
+        self.menubar.setObjectName(u"menubar")
+        self.menubar.setGeometry(QRect(0, 0, 571, 18))
+        self.menubar.setStyleSheet(u"background-color: #ebf1f7;\n"
+"color: rgb(102, 102, 102);\n"
+"border-radius: 0px;\n"
+"border: none;")
+        self.menu = QMenu(self.menubar)
+        self.menu.setObjectName(u"menu")
+        self.menu_2 = QMenu(self.menubar)
+        self.menu_2.setObjectName(u"menu_2")
+        self.menu_3 = QMenu(self.menubar)
+        self.menu_3.setObjectName(u"menu_3")
+        MainWindow.setMenuBar(self.menubar)
+        self.statusbar = QStatusBar(MainWindow)
+        self.statusbar.setObjectName(u"statusbar")
+        MainWindow.setStatusBar(self.statusbar)
+
+        self.menubar.addAction(self.menu.menuAction())
+        self.menubar.addAction(self.menu_2.menuAction())
+        self.menubar.addAction(self.menu_3.menuAction())
+        self.menu.addAction(self.action_2)
+        self.menu_2.addAction(self.action_5)
+        self.menu_3.addAction(self.action_10)
+        self.menu_3.addAction(self.action_11)
+
+        self.retranslateUi(MainWindow)
+
+        QMetaObject.connectSlotsByName(MainWindow)
+    # setupUi
+
+    def retranslateUi(self, MainWindow):
+        MainWindow.setWindowTitle(QCoreApplication.translate("MainWindow", u"MainWindow", None))
+        self.action.setText(QCoreApplication.translate("MainWindow", u"\u5408\u5e76\u8868\u683c", None))
+        self.action_2.setText(QCoreApplication.translate("MainWindow", u"\u56fe\u7247\u538b\u7f29", None))
+        self.action_3.setText(QCoreApplication.translate("MainWindow", u"\u4e0b\u8f7d\u8868\u683c\u56fe\u7247", None))
+        self.action_4.setText(QCoreApplication.translate("MainWindow", u"\u62cd\u7167\u547d\u540d", None))
+        self.action_5.setText(QCoreApplication.translate("MainWindow", u"\u56fe\u7247\u79fb\u52a8", None))
+        self.action_6.setText(QCoreApplication.translate("MainWindow", u"\u4e0b\u8f7d\u8d27\u53f7\u56fe\u5230\u6587\u4ef6\u5939", None))
+        self.action_7.setText(QCoreApplication.translate("MainWindow", u"\u8868\u683c\u56fe\u7247\u7f29\u653e\u8bbe\u7f6e", None))
+        self.action_8.setText(QCoreApplication.translate("MainWindow", u"\u8bbe\u7f6e", None))
+        self.action_9.setText(QCoreApplication.translate("MainWindow", u"\u8868\u683c\u83b7\u53d6\u5546\u54c1\u521b\u5efa\u4eba", None))
+        self.action_10.setText(QCoreApplication.translate("MainWindow", u"\u8bbe\u7f6e", None))
+        self.action_11.setText(QCoreApplication.translate("MainWindow", u"\u8054\u7cfb\u6211\u4eec", None))
+        self.label.setText(QCoreApplication.translate("MainWindow", u"\u603b\u6761\u6570\uff1a100   \u5904\u7406\u4e2d10\u6761   \u5df2\u5b8c\u621010\u6761  \u5931\u8d2510\u6761", None))
+        self.label_2.setText(QCoreApplication.translate("MainWindow", u"\u64cd\u4f5c\u4eba \u5f20\u4e09", None))
+        self.label_3.setText(QCoreApplication.translate("MainWindow", u"\u9000\u51fa", None))
+        self.pushButton_6.setText(QCoreApplication.translate("MainWindow", u"\u7ec8\u6b62\u7a0b\u5e8f", None))
+        self.pushButton.setText(QCoreApplication.translate("MainWindow", u"\u5f00\u59cb\u62a0\u56fe", None))
+        self.label_7.setText(QCoreApplication.translate("MainWindow", u"\u6d59\u6c5f\u7ea2\u873b\u8713\u80a1\u4efd\u6709\u9650\u516c\u53f8", None))
+        self.label_10.setText("")
+        self.label_9.setText(QCoreApplication.translate("MainWindow", u"\u5269\u4f59\u70b9\u6570", None))
+        self.label_11.setText(QCoreApplication.translate("MainWindow", u"80000", None))
+        self.label_12.setText(QCoreApplication.translate("MainWindow", u"\u672c\u6b21\u4f7f\u7528", None))
+        self.label_13.setText(QCoreApplication.translate("MainWindow", u"80000", None))
+        self.label_5.setText(QCoreApplication.translate("MainWindow", u"\u70b9\u51fb\u9009\u62e9\u6587\u4ef6\u5939/\u9009\u62e9\u56fe\u7247", None))
+        self.label_14.setText(QCoreApplication.translate("MainWindow", u"\u5237\u65b0", None))
+        self.label_4.setText(QCoreApplication.translate("MainWindow", u"\u5df2\u9009:", None))
+        self.label_8.setText(QCoreApplication.translate("MainWindow", u"\u91cd\u65b0\u9009\u62e9", None))
+        self.label_15.setText(QCoreApplication.translate("MainWindow", u"\u6253\u5f00\u6587\u4ef6\u5939", None))
+        self.menu.setTitle(QCoreApplication.translate("MainWindow", u"\u83dc\u5355", None))
+        self.menu_2.setTitle(QCoreApplication.translate("MainWindow", u"\u5176\u4ed6", None))
+        self.menu_3.setTitle(QCoreApplication.translate("MainWindow", u"\u8bbe\u7f6e", None))
+    # retranslateUi
+

+ 539 - 0
UI/main_ui.ui

@@ -0,0 +1,539 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MainWindow</class>
+ <widget class="QMainWindow" name="MainWindow">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>571</width>
+    <height>365</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>MainWindow</string>
+  </property>
+  <property name="styleSheet">
+   <string notr="true">background-color: #ebf1f7;</string>
+  </property>
+  <widget class="QWidget" name="centralwidget">
+   <widget class="QWidget" name="widget" native="true">
+    <property name="geometry">
+     <rect>
+      <x>10</x>
+      <y>10</y>
+      <width>391</width>
+      <height>41</height>
+     </rect>
+    </property>
+    <property name="styleSheet">
+     <string notr="true">background-color: #f7fcfd;
+border-radius: 5px;
+border: 2px groove gray;
+border:0px;</string>
+    </property>
+    <widget class="QProgressBar" name="progressBar">
+     <property name="geometry">
+      <rect>
+       <x>10</x>
+       <y>20</y>
+       <width>371</width>
+       <height>16</height>
+      </rect>
+     </property>
+     <property name="styleSheet">
+      <string notr="true">QProgressBar {
+    border: 0px solid grey;
+    color:rgb(255,255,255);
+    border-radius: 10px;
+    text-align: center;
+	border: 2px groove gray;
+	border:0px;
+    background-color: #6272a4;
+            }
+QProgressBar::chunk {
+    border-radius: 10px;
+    background-color: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 0, stop: 0 #fa78c9, stop: 1 #b058fb);
+            }</string>
+     </property>
+     <property name="value">
+      <number>24</number>
+     </property>
+    </widget>
+    <widget class="QLabel" name="label">
+     <property name="geometry">
+      <rect>
+       <x>10</x>
+       <y>0</y>
+       <width>371</width>
+       <height>16</height>
+      </rect>
+     </property>
+     <property name="styleSheet">
+      <string notr="true">font: 10pt &quot;Adobe 黑体 Std R&quot;;</string>
+     </property>
+     <property name="text">
+      <string>总条数:100   处理中10条   已完成10条  失败10条</string>
+     </property>
+    </widget>
+   </widget>
+   <widget class="QLabel" name="label_2">
+    <property name="geometry">
+     <rect>
+      <x>420</x>
+      <y>10</y>
+      <width>91</width>
+      <height>31</height>
+     </rect>
+    </property>
+    <property name="styleSheet">
+     <string notr="true">background-color: #f7fcfd;
+border-radius: 5px;
+border: 2px groove gray;
+border:0px;</string>
+    </property>
+    <property name="text">
+     <string>操作人 张三</string>
+    </property>
+    <property name="alignment">
+     <set>Qt::AlignCenter</set>
+    </property>
+   </widget>
+   <widget class="QLabel" name="label_3">
+    <property name="geometry">
+     <rect>
+      <x>520</x>
+      <y>10</y>
+      <width>31</width>
+      <height>31</height>
+     </rect>
+    </property>
+    <property name="styleSheet">
+     <string notr="true">background-color: #f7fcfd;
+border-radius: 5px;
+border: 2px groove gray;
+border:0px;</string>
+    </property>
+    <property name="text">
+     <string>退出</string>
+    </property>
+    <property name="alignment">
+     <set>Qt::AlignCenter</set>
+    </property>
+   </widget>
+   <widget class="QPushButton" name="pushButton_6">
+    <property name="geometry">
+     <rect>
+      <x>420</x>
+      <y>270</y>
+      <width>131</width>
+      <height>31</height>
+     </rect>
+    </property>
+    <property name="styleSheet">
+     <string notr="true">background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 rgba(255, 137, 27, 255), stop:1 rgba(255, 93, 1, 255));
+color: rgb(255, 255, 255);
+border-radius: 5px;  border: 2px groove gray;
+border:0px;</string>
+    </property>
+    <property name="text">
+     <string>终止程序</string>
+    </property>
+   </widget>
+   <widget class="QPushButton" name="pushButton">
+    <property name="geometry">
+     <rect>
+      <x>420</x>
+      <y>250</y>
+      <width>131</width>
+      <height>31</height>
+     </rect>
+    </property>
+    <property name="styleSheet">
+     <string notr="true">background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 rgba(255, 137, 27, 255), stop:1 rgba(255, 93, 1, 255));
+color: rgb(255, 255, 255);
+border-radius: 5px;  border: 2px groove gray;
+border:0px;</string>
+    </property>
+    <property name="text">
+     <string>开始抠图</string>
+    </property>
+   </widget>
+   <widget class="QLabel" name="label_7">
+    <property name="geometry">
+     <rect>
+      <x>420</x>
+      <y>45</y>
+      <width>131</width>
+      <height>21</height>
+     </rect>
+    </property>
+    <property name="styleSheet">
+     <string notr="true">background-color: #f7fcfd;
+border-radius: 5px;
+border: 2px groove gray;
+border:0px;</string>
+    </property>
+    <property name="text">
+     <string>浙江红蜻蜓股份有限公司</string>
+    </property>
+    <property name="alignment">
+     <set>Qt::AlignCenter</set>
+    </property>
+   </widget>
+   <widget class="QLabel" name="label_10">
+    <property name="geometry">
+     <rect>
+      <x>420</x>
+      <y>70</y>
+      <width>131</width>
+      <height>71</height>
+     </rect>
+    </property>
+    <property name="styleSheet">
+     <string notr="true">background-color: #f7fcfd;
+border-radius: 5px;
+border: 2px groove gray;
+border:0px;</string>
+    </property>
+    <property name="text">
+     <string/>
+    </property>
+    <property name="alignment">
+     <set>Qt::AlignCenter</set>
+    </property>
+   </widget>
+   <widget class="QLabel" name="label_9">
+    <property name="geometry">
+     <rect>
+      <x>430</x>
+      <y>80</y>
+      <width>41</width>
+      <height>16</height>
+     </rect>
+    </property>
+    <property name="styleSheet">
+     <string notr="true">background-color: rgb(255, 255, 255,0);
+font: 7pt &quot;Adobe Arabic&quot;;</string>
+    </property>
+    <property name="text">
+     <string>剩余点数</string>
+    </property>
+    <property name="alignment">
+     <set>Qt::AlignCenter</set>
+    </property>
+   </widget>
+   <widget class="QLabel" name="label_11">
+    <property name="geometry">
+     <rect>
+      <x>430</x>
+      <y>100</y>
+      <width>41</width>
+      <height>20</height>
+     </rect>
+    </property>
+    <property name="styleSheet">
+     <string notr="true">background-color: rgb(255, 255, 255,0);
+font: 15pt &quot;Adobe 黑体 Std R&quot;;</string>
+    </property>
+    <property name="text">
+     <string>80000</string>
+    </property>
+    <property name="alignment">
+     <set>Qt::AlignCenter</set>
+    </property>
+   </widget>
+   <widget class="QLabel" name="label_12">
+    <property name="geometry">
+     <rect>
+      <x>500</x>
+      <y>80</y>
+      <width>41</width>
+      <height>16</height>
+     </rect>
+    </property>
+    <property name="styleSheet">
+     <string notr="true">background-color: rgb(255, 255, 255,0);
+font: 7pt &quot;Adobe Arabic&quot;;</string>
+    </property>
+    <property name="text">
+     <string>本次使用</string>
+    </property>
+    <property name="alignment">
+     <set>Qt::AlignCenter</set>
+    </property>
+   </widget>
+   <widget class="QLabel" name="label_13">
+    <property name="geometry">
+     <rect>
+      <x>500</x>
+      <y>100</y>
+      <width>41</width>
+      <height>20</height>
+     </rect>
+    </property>
+    <property name="styleSheet">
+     <string notr="true">background-color: rgb(255, 255, 255,0);
+font: 15pt &quot;Adobe 黑体 Std R&quot;;</string>
+    </property>
+    <property name="text">
+     <string>80000</string>
+    </property>
+    <property name="alignment">
+     <set>Qt::AlignCenter</set>
+    </property>
+   </widget>
+   <widget class="QScrollArea" name="scrollArea">
+    <property name="geometry">
+     <rect>
+      <x>10</x>
+      <y>60</y>
+      <width>391</width>
+      <height>261</height>
+     </rect>
+    </property>
+    <property name="styleSheet">
+     <string notr="true">background-color: #f7fcfd;
+border-radius: 5px;
+border: 2px groove gray;
+border:0px;</string>
+    </property>
+    <property name="widgetResizable">
+     <bool>true</bool>
+    </property>
+    <widget class="QWidget" name="scrollAreaWidgetContents">
+     <property name="geometry">
+      <rect>
+       <x>0</x>
+       <y>0</y>
+       <width>378</width>
+       <height>8000</height>
+      </rect>
+     </property>
+     <property name="minimumSize">
+      <size>
+       <width>0</width>
+       <height>8000</height>
+      </size>
+     </property>
+     <widget class="QWidget" name="widget_2" native="true">
+      <property name="geometry">
+       <rect>
+        <x>10</x>
+        <y>10</y>
+        <width>351</width>
+        <height>200</height>
+       </rect>
+      </property>
+      <property name="sizePolicy">
+       <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
+        <horstretch>0</horstretch>
+        <verstretch>0</verstretch>
+       </sizepolicy>
+      </property>
+      <widget class="QLabel" name="label_5">
+       <property name="geometry">
+        <rect>
+         <x>50</x>
+         <y>90</y>
+         <width>271</width>
+         <height>21</height>
+        </rect>
+       </property>
+       <property name="styleSheet">
+        <string notr="true">font: 10pt &quot;Adobe 黑体 Std R&quot;;</string>
+       </property>
+       <property name="text">
+        <string>点击选择文件夹/选择图片</string>
+       </property>
+       <property name="alignment">
+        <set>Qt::AlignCenter</set>
+       </property>
+      </widget>
+     </widget>
+    </widget>
+   </widget>
+   <widget class="QLabel" name="label_14">
+    <property name="geometry">
+     <rect>
+      <x>430</x>
+      <y>120</y>
+      <width>41</width>
+      <height>16</height>
+     </rect>
+    </property>
+    <property name="styleSheet">
+     <string notr="true">background-color: rgb(255, 255, 255,0);
+font: 7pt &quot;Adobe Arabic&quot;;
+color: rgb(0, 85, 255);</string>
+    </property>
+    <property name="text">
+     <string>刷新</string>
+    </property>
+    <property name="alignment">
+     <set>Qt::AlignCenter</set>
+    </property>
+   </widget>
+   <widget class="QWidget" name="widget_3" native="true">
+    <property name="geometry">
+     <rect>
+      <x>10</x>
+      <y>330</y>
+      <width>391</width>
+      <height>41</height>
+     </rect>
+    </property>
+    <property name="styleSheet">
+     <string notr="true">background-color: #f7fcfd;
+border-radius: 5px;
+border: 2px groove gray;
+border:0px;</string>
+    </property>
+    <widget class="QLabel" name="label_4">
+     <property name="geometry">
+      <rect>
+       <x>10</x>
+       <y>10</y>
+       <width>241</width>
+       <height>21</height>
+      </rect>
+     </property>
+     <property name="styleSheet">
+      <string notr="true">font: 10pt &quot;Adobe 黑体 Std R&quot;;</string>
+     </property>
+     <property name="text">
+      <string>已选:</string>
+     </property>
+    </widget>
+    <widget class="QLabel" name="label_8">
+     <property name="geometry">
+      <rect>
+       <x>270</x>
+       <y>10</y>
+       <width>51</width>
+       <height>21</height>
+      </rect>
+     </property>
+     <property name="styleSheet">
+      <string notr="true">font: 10pt &quot;Adobe 黑体 Std R&quot;;</string>
+     </property>
+     <property name="text">
+      <string>重新选择</string>
+     </property>
+    </widget>
+    <widget class="QLabel" name="label_15">
+     <property name="geometry">
+      <rect>
+       <x>330</x>
+       <y>10</y>
+       <width>51</width>
+       <height>21</height>
+      </rect>
+     </property>
+     <property name="styleSheet">
+      <string notr="true">font: 10pt &quot;Adobe 黑体 Std R&quot;;</string>
+     </property>
+     <property name="text">
+      <string>打开文件夹</string>
+     </property>
+    </widget>
+   </widget>
+  </widget>
+  <widget class="QMenuBar" name="menubar">
+   <property name="geometry">
+    <rect>
+     <x>0</x>
+     <y>0</y>
+     <width>571</width>
+     <height>18</height>
+    </rect>
+   </property>
+   <property name="styleSheet">
+    <string notr="true">background-color: #ebf1f7;
+color: rgb(102, 102, 102);
+border-radius: 0px;
+border: none;</string>
+   </property>
+   <widget class="QMenu" name="menu">
+    <property name="title">
+     <string>菜单</string>
+    </property>
+    <addaction name="action_2"/>
+   </widget>
+   <widget class="QMenu" name="menu_2">
+    <property name="title">
+     <string>其他</string>
+    </property>
+    <addaction name="action_5"/>
+   </widget>
+   <widget class="QMenu" name="menu_3">
+    <property name="title">
+     <string>设置</string>
+    </property>
+    <addaction name="action_10"/>
+    <addaction name="action_11"/>
+   </widget>
+   <addaction name="menu"/>
+   <addaction name="menu_2"/>
+   <addaction name="menu_3"/>
+  </widget>
+  <widget class="QStatusBar" name="statusbar"/>
+  <action name="action">
+   <property name="text">
+    <string>合并表格</string>
+   </property>
+  </action>
+  <action name="action_2">
+   <property name="text">
+    <string>图片压缩</string>
+   </property>
+  </action>
+  <action name="action_3">
+   <property name="text">
+    <string>下载表格图片</string>
+   </property>
+  </action>
+  <action name="action_4">
+   <property name="text">
+    <string>拍照命名</string>
+   </property>
+  </action>
+  <action name="action_5">
+   <property name="text">
+    <string>图片移动</string>
+   </property>
+  </action>
+  <action name="action_6">
+   <property name="text">
+    <string>下载货号图到文件夹</string>
+   </property>
+  </action>
+  <action name="action_7">
+   <property name="text">
+    <string>表格图片缩放设置</string>
+   </property>
+  </action>
+  <action name="action_8">
+   <property name="text">
+    <string>设置</string>
+   </property>
+  </action>
+  <action name="action_9">
+   <property name="text">
+    <string>表格获取商品创建人</string>
+   </property>
+  </action>
+  <action name="action_10">
+   <property name="text">
+    <string>设置</string>
+   </property>
+  </action>
+  <action name="action_11">
+   <property name="text">
+    <string>联系我们</string>
+   </property>
+  </action>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>

+ 83 - 0
UI/move_files.py

@@ -0,0 +1,83 @@
+# -*- coding: utf-8 -*-
+
+################################################################################
+## Form generated from reading UI file 'move_files.ui'
+##
+## Created by: Qt User Interface Compiler version 6.2.4
+##
+## WARNING! All changes made in this file will be lost when recompiling UI file!
+################################################################################
+
+from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale,
+    QMetaObject, QObject, QPoint, QRect,
+    QSize, QTime, QUrl, Qt)
+from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor,
+    QFont, QFontDatabase, QGradient, QIcon,
+    QImage, QKeySequence, QLinearGradient, QPainter,
+    QPalette, QPixmap, QRadialGradient, QTransform)
+from PySide6.QtWidgets import (QApplication, QLabel, QPushButton, QSizePolicy,
+    QTextBrowser, QTextEdit, QWidget)
+
+class Ui_Form(object):
+    def setupUi(self, Form):
+        if not Form.objectName():
+            Form.setObjectName(u"Form")
+        Form.resize(409, 338)
+        Form.setStyleSheet(u"background-color: rgb(232, 232, 232);")
+        self.label_2 = QLabel(Form)
+        self.label_2.setObjectName(u"label_2")
+        self.label_2.setGeometry(QRect(10, 10, 81, 16))
+        self.label_3 = QLabel(Form)
+        self.label_3.setObjectName(u"label_3")
+        self.label_3.setGeometry(QRect(100, 10, 81, 16))
+        self.label_3.setStyleSheet(u"color: rgb(40, 12, 255);")
+        self.pushButton = QPushButton(Form)
+        self.pushButton.setObjectName(u"pushButton")
+        self.pushButton.setGeometry(QRect(90, 280, 161, 41))
+        self.pushButton.setStyleSheet(u"background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 rgba(255, 137, 27, 255), stop:1 rgba(255, 93, 1, 255));\n"
+"color: rgb(255, 255, 255);\n"
+"border-radius: 5px;  \n"
+"border: 2px groove gray;\n"
+"border:0px;")
+        self.textEdit = QTextEdit(Form)
+        self.textEdit.setObjectName(u"textEdit")
+        self.textEdit.setGeometry(QRect(10, 120, 121, 141))
+        self.textEdit.setStyleSheet(u"background-color: rgb(255, 255, 255);")
+        self.textEdit.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
+        self.textEdit.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
+        self.textBrowser = QTextBrowser(Form)
+        self.textBrowser.setObjectName(u"textBrowser")
+        self.textBrowser.setGeometry(QRect(10, 40, 381, 51))
+        self.textEdit_2 = QTextEdit(Form)
+        self.textEdit_2.setObjectName(u"textEdit_2")
+        self.textEdit_2.setGeometry(QRect(140, 120, 121, 141))
+        self.textEdit_2.setStyleSheet(u"background-color: rgb(255, 255, 255);")
+        self.textEdit_3 = QTextEdit(Form)
+        self.textEdit_3.setObjectName(u"textEdit_3")
+        self.textEdit_3.setGeometry(QRect(270, 120, 121, 141))
+        self.textEdit_3.setStyleSheet(u"background-color: rgb(255, 255, 255);")
+        self.label = QLabel(Form)
+        self.label.setObjectName(u"label")
+        self.label.setGeometry(QRect(10, 100, 121, 20))
+        self.label_4 = QLabel(Form)
+        self.label_4.setObjectName(u"label_4")
+        self.label_4.setGeometry(QRect(140, 100, 121, 20))
+        self.label_5 = QLabel(Form)
+        self.label_5.setObjectName(u"label_5")
+        self.label_5.setGeometry(QRect(270, 100, 121, 20))
+
+        self.retranslateUi(Form)
+
+        QMetaObject.connectSlotsByName(Form)
+    # setupUi
+
+    def retranslateUi(self, Form):
+        Form.setWindowTitle(QCoreApplication.translate("Form", u"\u56fe\u7247\u6279\u91cf\u79fb\u52a8\u5de5\u5177", None))
+        self.label_2.setText(QCoreApplication.translate("Form", u"\u9009\u62e9\u56fe\u7247\u6587\u4ef6\u5939", None))
+        self.label_3.setText(QCoreApplication.translate("Form", u"\u70b9\u51fb\u9009\u62e9\u6587\u4ef6\u5939", None))
+        self.pushButton.setText(QCoreApplication.translate("Form", u"\u6267\u884c", None))
+        self.label.setText(QCoreApplication.translate("Form", u"\u5f85\u8f6c\u79fb\u56fe\u7247\u540d\u79f0(\u4e0d\u9700\u8981\u540e\u7f00\uff09", None))
+        self.label_4.setText(QCoreApplication.translate("Form", u"\u5904\u7406\u6210\u529f\u56fe", None))
+        self.label_5.setText(QCoreApplication.translate("Form", u"\u65e0\u6cd5\u5bf9\u5e94\u56fe", None))
+    # retranslateUi
+

+ 165 - 0
UI/move_files.ui

@@ -0,0 +1,165 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Form</class>
+ <widget class="QWidget" name="Form">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>409</width>
+    <height>338</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>图片批量移动工具</string>
+  </property>
+  <property name="styleSheet">
+   <string notr="true">background-color: rgb(232, 232, 232);</string>
+  </property>
+  <widget class="QLabel" name="label_2">
+   <property name="geometry">
+    <rect>
+     <x>10</x>
+     <y>10</y>
+     <width>81</width>
+     <height>16</height>
+    </rect>
+   </property>
+   <property name="text">
+    <string>选择图片文件夹</string>
+   </property>
+  </widget>
+  <widget class="QLabel" name="label_3">
+   <property name="geometry">
+    <rect>
+     <x>100</x>
+     <y>10</y>
+     <width>81</width>
+     <height>16</height>
+    </rect>
+   </property>
+   <property name="styleSheet">
+    <string notr="true">color: rgb(40, 12, 255);</string>
+   </property>
+   <property name="text">
+    <string>点击选择文件夹</string>
+   </property>
+  </widget>
+  <widget class="QPushButton" name="pushButton">
+   <property name="geometry">
+    <rect>
+     <x>90</x>
+     <y>280</y>
+     <width>161</width>
+     <height>41</height>
+    </rect>
+   </property>
+   <property name="styleSheet">
+    <string notr="true">background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 rgba(255, 137, 27, 255), stop:1 rgba(255, 93, 1, 255));
+color: rgb(255, 255, 255);
+border-radius: 5px;  
+border: 2px groove gray;
+border:0px;</string>
+   </property>
+   <property name="text">
+    <string>执行</string>
+   </property>
+  </widget>
+  <widget class="QTextEdit" name="textEdit">
+   <property name="geometry">
+    <rect>
+     <x>10</x>
+     <y>120</y>
+     <width>121</width>
+     <height>141</height>
+    </rect>
+   </property>
+   <property name="styleSheet">
+    <string notr="true">background-color: rgb(255, 255, 255);</string>
+   </property>
+   <property name="verticalScrollBarPolicy">
+    <enum>Qt::ScrollBarAlwaysOff</enum>
+   </property>
+   <property name="horizontalScrollBarPolicy">
+    <enum>Qt::ScrollBarAlwaysOff</enum>
+   </property>
+  </widget>
+  <widget class="QTextBrowser" name="textBrowser">
+   <property name="geometry">
+    <rect>
+     <x>10</x>
+     <y>40</y>
+     <width>381</width>
+     <height>51</height>
+    </rect>
+   </property>
+  </widget>
+  <widget class="QTextEdit" name="textEdit_2">
+   <property name="geometry">
+    <rect>
+     <x>140</x>
+     <y>120</y>
+     <width>121</width>
+     <height>141</height>
+    </rect>
+   </property>
+   <property name="styleSheet">
+    <string notr="true">background-color: rgb(255, 255, 255);</string>
+   </property>
+  </widget>
+  <widget class="QTextEdit" name="textEdit_3">
+   <property name="geometry">
+    <rect>
+     <x>270</x>
+     <y>120</y>
+     <width>121</width>
+     <height>141</height>
+    </rect>
+   </property>
+   <property name="styleSheet">
+    <string notr="true">background-color: rgb(255, 255, 255);</string>
+   </property>
+  </widget>
+  <widget class="QLabel" name="label">
+   <property name="geometry">
+    <rect>
+     <x>10</x>
+     <y>100</y>
+     <width>121</width>
+     <height>20</height>
+    </rect>
+   </property>
+   <property name="text">
+    <string>待转移图片名称(不需要后缀)</string>
+   </property>
+  </widget>
+  <widget class="QLabel" name="label_4">
+   <property name="geometry">
+    <rect>
+     <x>140</x>
+     <y>100</y>
+     <width>121</width>
+     <height>20</height>
+    </rect>
+   </property>
+   <property name="text">
+    <string>处理成功图</string>
+   </property>
+  </widget>
+  <widget class="QLabel" name="label_5">
+   <property name="geometry">
+    <rect>
+     <x>270</x>
+     <y>100</y>
+     <width>121</width>
+     <height>20</height>
+    </rect>
+   </property>
+   <property name="text">
+    <string>无法对应图</string>
+   </property>
+  </widget>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>

+ 95 - 0
UI/rename_pic.py

@@ -0,0 +1,95 @@
+# -*- coding: utf-8 -*-
+
+################################################################################
+## Form generated from reading UI file 'rename_pic.ui'
+##
+## Created by: Qt User Interface Compiler version 6.2.4
+##
+## WARNING! All changes made in this file will be lost when recompiling UI file!
+################################################################################
+
+from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale,
+    QMetaObject, QObject, QPoint, QRect,
+    QSize, QTime, QUrl, Qt)
+from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor,
+    QFont, QFontDatabase, QGradient, QIcon,
+    QImage, QKeySequence, QLinearGradient, QPainter,
+    QPalette, QPixmap, QRadialGradient, QTransform)
+from PySide6.QtWidgets import (QApplication, QComboBox, QLabel, QProgressBar,
+    QPushButton, QSizePolicy, QTextBrowser, QWidget)
+
+class Ui_Form(object):
+    def setupUi(self, Form):
+        if not Form.objectName():
+            Form.setObjectName(u"Form")
+        Form.resize(416, 326)
+        Form.setStyleSheet(u"background-color: rgb(255, 255, 255);")
+        self.pushButton = QPushButton(Form)
+        self.pushButton.setObjectName(u"pushButton")
+        self.pushButton.setGeometry(QRect(120, 280, 161, 31))
+        self.pushButton.setStyleSheet(u"background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 rgba(255, 137, 27, 255), stop:1 rgba(255, 93, 1, 255));\n"
+"color: rgb(255, 255, 255);\n"
+"border-radius: 5px;  border: 2px groove gray;\n"
+"border:0px;")
+        self.textBrowser_2 = QTextBrowser(Form)
+        self.textBrowser_2.setObjectName(u"textBrowser_2")
+        self.textBrowser_2.setGeometry(QRect(10, 110, 391, 161))
+        self.textBrowser_2.setStyleSheet(u"background-color: rgb(242, 242, 242);\n"
+"border-radius: 5px;  border: 2px groove gray;\n"
+"border:0px;")
+        self.label_3 = QLabel(Form)
+        self.label_3.setObjectName(u"label_3")
+        self.label_3.setGeometry(QRect(90, 10, 101, 21))
+        self.label_3.setStyleSheet(u"color: rgb(0, 0, 255);")
+        self.label_4 = QLabel(Form)
+        self.label_4.setObjectName(u"label_4")
+        self.label_4.setGeometry(QRect(10, 40, 391, 31))
+        self.label_4.setStyleSheet(u"background-color: rgb(233, 231, 231);\n"
+"border-radius: 5px;  border: 2px groove gray;\n"
+"border:0px;\n"
+"")
+        self.label_4.setWordWrap(True)
+        self.label_2 = QLabel(Form)
+        self.label_2.setObjectName(u"label_2")
+        self.label_2.setGeometry(QRect(10, 10, 61, 21))
+        self.comboBox = QComboBox(Form)
+        self.comboBox.addItem("")
+        self.comboBox.addItem("")
+        self.comboBox.addItem("")
+        self.comboBox.setObjectName(u"comboBox")
+        self.comboBox.setGeometry(QRect(330, 10, 71, 22))
+        self.label_5 = QLabel(Form)
+        self.label_5.setObjectName(u"label_5")
+        self.label_5.setGeometry(QRect(200, 10, 121, 21))
+        self.progressBar = QProgressBar(Form)
+        self.progressBar.setObjectName(u"progressBar")
+        self.progressBar.setGeometry(QRect(10, 80, 391, 23))
+        self.progressBar.setValue(24)
+
+        self.retranslateUi(Form)
+
+        QMetaObject.connectSlotsByName(Form)
+    # setupUi
+
+    def retranslateUi(self, Form):
+        Form.setWindowTitle(QCoreApplication.translate("Form", u"\u57fa\u4e8e\u4e8c\u7ef4\u7801\u547d\u540d\u56fe\u7247", None))
+        self.pushButton.setText(QCoreApplication.translate("Form", u"\u6267\u884c\u5904\u7406", None))
+        self.textBrowser_2.setHtml(QCoreApplication.translate("Form", u"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
+"<html><head><meta name=\"qrichtext\" content=\"1\" /><meta charset=\"utf-8\" /><style type=\"text/css\">\n"
+"p, li { white-space: pre-wrap; }\n"
+"</style></head><body style=\" font-family:'Microsoft YaHei UI'; font-size:9pt; font-weight:400; font-style:normal;\">\n"
+"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">1\u3001\u62cd\u7167\u65f6\uff0c\u5148\u62cd\u4e8c\u7ef4\u7801\uff0c\u518d\u62cd\u978b\u5b50</p>\n"
+"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">2\u3001\u52a1\u5fc5\u786e\u4fdd\u5148\u62cd\u4e8c\u7ef4\u7801\uff0c\u518d\u62cd\u978b\u3002</p>\n"
+"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">3\u3001\u52a1\u5fc5\u786e\u4fdd\u6bcf\u4e2a\u8d27\u53f7\u4e24\u5f20\u56fe</p>\n"
+"<p style="
+                        "\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><br /></p></body></html>", None))
+        self.label_3.setText(QCoreApplication.translate("Form", u"\u70b9\u51fb\u9009\u62e9\u6587\u4ef6\u5939", None))
+        self.label_4.setText(QCoreApplication.translate("Form", u"\u6587\u4ef6\u5c55\u793a\u8def\u5f84", None))
+        self.label_2.setText(QCoreApplication.translate("Form", u"\u5f85\u5904\u7406\u6587\u4ef6\u5939", None))
+        self.comboBox.setItemText(0, QCoreApplication.translate("Form", u"\u8bf7\u9009\u62e9", None))
+        self.comboBox.setItemText(1, QCoreApplication.translate("Form", u"\u6dfb\u52a0", None))
+        self.comboBox.setItemText(2, QCoreApplication.translate("Form", u"\u4e0d\u6dfb\u52a0", None))
+
+        self.label_5.setText(QCoreApplication.translate("Form", u"\u8d27\u53f7\u662f\u5426\u6dfb\u52a0\u5230\u56fe\u7247\u4e2d\uff1a", None))
+    # retranslateUi
+

+ 168 - 0
UI/rename_pic.ui

@@ -0,0 +1,168 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Form</class>
+ <widget class="QWidget" name="Form">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>416</width>
+    <height>326</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>基于二维码命名图片</string>
+  </property>
+  <property name="styleSheet">
+   <string notr="true">background-color: rgb(255, 255, 255);</string>
+  </property>
+  <widget class="QPushButton" name="pushButton">
+   <property name="geometry">
+    <rect>
+     <x>120</x>
+     <y>280</y>
+     <width>161</width>
+     <height>31</height>
+    </rect>
+   </property>
+   <property name="styleSheet">
+    <string notr="true">background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 rgba(255, 137, 27, 255), stop:1 rgba(255, 93, 1, 255));
+color: rgb(255, 255, 255);
+border-radius: 5px;  border: 2px groove gray;
+border:0px;</string>
+   </property>
+   <property name="text">
+    <string>执行处理</string>
+   </property>
+  </widget>
+  <widget class="QTextBrowser" name="textBrowser_2">
+   <property name="geometry">
+    <rect>
+     <x>10</x>
+     <y>110</y>
+     <width>391</width>
+     <height>161</height>
+    </rect>
+   </property>
+   <property name="styleSheet">
+    <string notr="true">background-color: rgb(242, 242, 242);
+border-radius: 5px;  border: 2px groove gray;
+border:0px;</string>
+   </property>
+   <property name="html">
+    <string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
+&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;meta charset=&quot;utf-8&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
+p, li { white-space: pre-wrap; }
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Microsoft YaHei UI'; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;1、拍照时,先拍二维码,再拍鞋子&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;2、务必确保先拍二维码,再拍鞋。&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;3、务必确保每个货号两张图&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+   </property>
+  </widget>
+  <widget class="QLabel" name="label_3">
+   <property name="geometry">
+    <rect>
+     <x>90</x>
+     <y>10</y>
+     <width>101</width>
+     <height>21</height>
+    </rect>
+   </property>
+   <property name="styleSheet">
+    <string notr="true">color: rgb(0, 0, 255);</string>
+   </property>
+   <property name="text">
+    <string>点击选择文件夹</string>
+   </property>
+  </widget>
+  <widget class="QLabel" name="label_4">
+   <property name="geometry">
+    <rect>
+     <x>10</x>
+     <y>40</y>
+     <width>391</width>
+     <height>31</height>
+    </rect>
+   </property>
+   <property name="styleSheet">
+    <string notr="true">background-color: rgb(233, 231, 231);
+border-radius: 5px;  border: 2px groove gray;
+border:0px;
+</string>
+   </property>
+   <property name="text">
+    <string>文件展示路径</string>
+   </property>
+   <property name="wordWrap">
+    <bool>true</bool>
+   </property>
+  </widget>
+  <widget class="QLabel" name="label_2">
+   <property name="geometry">
+    <rect>
+     <x>10</x>
+     <y>10</y>
+     <width>61</width>
+     <height>21</height>
+    </rect>
+   </property>
+   <property name="text">
+    <string>待处理文件夹</string>
+   </property>
+  </widget>
+  <widget class="QComboBox" name="comboBox">
+   <property name="geometry">
+    <rect>
+     <x>330</x>
+     <y>10</y>
+     <width>71</width>
+     <height>22</height>
+    </rect>
+   </property>
+   <item>
+    <property name="text">
+     <string>请选择</string>
+    </property>
+   </item>
+   <item>
+    <property name="text">
+     <string>添加</string>
+    </property>
+   </item>
+   <item>
+    <property name="text">
+     <string>不添加</string>
+    </property>
+   </item>
+  </widget>
+  <widget class="QLabel" name="label_5">
+   <property name="geometry">
+    <rect>
+     <x>200</x>
+     <y>10</y>
+     <width>121</width>
+     <height>21</height>
+    </rect>
+   </property>
+   <property name="text">
+    <string>货号是否添加到图片中:</string>
+   </property>
+  </widget>
+  <widget class="QProgressBar" name="progressBar">
+   <property name="geometry">
+    <rect>
+     <x>10</x>
+     <y>80</y>
+     <width>391</width>
+     <height>23</height>
+    </rect>
+   </property>
+   <property name="value">
+    <number>24</number>
+   </property>
+  </widget>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>

+ 101 - 0
UI/resize_photos.py

@@ -0,0 +1,101 @@
+# -*- coding: utf-8 -*-
+
+################################################################################
+## Form generated from reading UI file 'resize_photos.ui'
+##
+## Created by: Qt User Interface Compiler version 6.2.4
+##
+## WARNING! All changes made in this file will be lost when recompiling UI file!
+################################################################################
+
+from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale,
+    QMetaObject, QObject, QPoint, QRect,
+    QSize, QTime, QUrl, Qt)
+from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor,
+    QFont, QFontDatabase, QGradient, QIcon,
+    QImage, QKeySequence, QLinearGradient, QPainter,
+    QPalette, QPixmap, QRadialGradient, QTransform)
+from PySide6.QtWidgets import (QApplication, QLabel, QLineEdit, QProgressBar,
+    QPushButton, QSizePolicy, QTextBrowser, QWidget)
+
+class Ui_Form(object):
+    def setupUi(self, Form):
+        if not Form.objectName():
+            Form.setObjectName(u"Form")
+        Form.resize(457, 418)
+        Form.setStyleSheet(u"background-color: rgb(232, 232, 232);")
+        self.label_2 = QLabel(Form)
+        self.label_2.setObjectName(u"label_2")
+        self.label_2.setGeometry(QRect(10, 70, 81, 16))
+        self.label_3 = QLabel(Form)
+        self.label_3.setObjectName(u"label_3")
+        self.label_3.setGeometry(QRect(100, 70, 81, 16))
+        self.label_3.setStyleSheet(u"color: rgb(40, 12, 255);")
+        self.label_4 = QLabel(Form)
+        self.label_4.setObjectName(u"label_4")
+        self.label_4.setGeometry(QRect(10, 90, 431, 31))
+        self.label_4.setWordWrap(True)
+        self.progressBar = QProgressBar(Form)
+        self.progressBar.setObjectName(u"progressBar")
+        self.progressBar.setGeometry(QRect(20, 190, 421, 31))
+        self.progressBar.setValue(24)
+        self.pushButton = QPushButton(Form)
+        self.pushButton.setObjectName(u"pushButton")
+        self.pushButton.setGeometry(QRect(150, 360, 161, 41))
+        self.pushButton.setStyleSheet(u"background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 rgba(255, 137, 27, 255), stop:1 rgba(255, 93, 1, 255));\n"
+"color: rgb(255, 255, 255);\n"
+"border-radius: 5px;  border: 2px groove gray;\n"
+"border:0px;")
+        self.textBrowser = QTextBrowser(Form)
+        self.textBrowser.setObjectName(u"textBrowser")
+        self.textBrowser.setGeometry(QRect(10, 10, 431, 51))
+        self.textBrowser_2 = QTextBrowser(Form)
+        self.textBrowser_2.setObjectName(u"textBrowser_2")
+        self.textBrowser_2.setGeometry(QRect(10, 230, 431, 111))
+        self.textBrowser_2.setStyleSheet(u"border-radius: 5px;  border: 2px groove gray;\\nborder:0px;")
+        self.label_5 = QLabel(Form)
+        self.label_5.setObjectName(u"label_5")
+        self.label_5.setGeometry(QRect(20, 170, 361, 20))
+        self.label_5.setAlignment(Qt.AlignCenter)
+        self.label_6 = QLabel(Form)
+        self.label_6.setObjectName(u"label_6")
+        self.label_6.setGeometry(QRect(10, 140, 71, 16))
+        self.lineEdit = QLineEdit(Form)
+        self.lineEdit.setObjectName(u"lineEdit")
+        self.lineEdit.setGeometry(QRect(100, 130, 113, 31))
+        self.lineEdit.setStyleSheet(u"background-color: rgb(255, 255, 255);")
+        self.label_7 = QLabel(Form)
+        self.label_7.setObjectName(u"label_7")
+        self.label_7.setGeometry(QRect(220, 140, 141, 16))
+        self.label_8 = QLabel(Form)
+        self.label_8.setObjectName(u"label_8")
+        self.label_8.setGeometry(QRect(350, 370, 81, 21))
+        self.label_8.setStyleSheet(u"color: rgb(40, 12, 255);")
+
+        self.retranslateUi(Form)
+
+        QMetaObject.connectSlotsByName(Form)
+    # setupUi
+
+    def retranslateUi(self, Form):
+        Form.setWindowTitle(QCoreApplication.translate("Form", u"\u56fe\u7247\u81ea\u52a8\u538b\u7f29", None))
+        self.label_2.setText(QCoreApplication.translate("Form", u"\u5f53\u524d\u56fe\u7247\u8def\u5f84", None))
+        self.label_3.setText(QCoreApplication.translate("Form", u"\u70b9\u51fb\u4fee\u6539\u8def\u5f84", None))
+        self.label_4.setText(QCoreApplication.translate("Form", u"\u6587\u4ef6\u5939\u8def\u5f84\u5c55\u793a", None))
+        self.pushButton.setText(QCoreApplication.translate("Form", u"\u6267\u884c\u538b\u7f29", None))
+        self.textBrowser.setHtml(QCoreApplication.translate("Form", u"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
+"<html><head><meta name=\"qrichtext\" content=\"1\" /><meta charset=\"utf-8\" /><style type=\"text/css\">\n"
+"p, li { white-space: pre-wrap; }\n"
+"</style></head><body style=\" font-family:'Microsoft YaHei UI'; font-size:9pt; font-weight:400; font-style:normal;\">\n"
+"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">\u6ce8\u610f\u5f53\u524d\u56fe\u7247\u81ea\u52a8\u6539\u5c3a\u5bf8\u529f\u80fd\uff0c\u4f1a\u904d\u5386\u60a8\u7684\u6240\u9009\u7684\u6587\u4ef6\u5939\uff0c\u4ee5\u53ca\u5b50\u6587\u4ef6\u5939\uff0c\u8bf7\u6ce8\u610f\u6587\u4ef6\u5939\u9009\u62e9\u662f\u5426\u6b63\u786e\uff0c\u6570\u636e\u81ea\u884c\u5907\u4efd\u3002\u6267\u884c\u540e\u65e0\u6cd5\u64a4\u56de\u3002</p></body></html>", None))
+        self.textBrowser_2.setHtml(QCoreApplication.translate("Form", u"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
+"<html><head><meta name=\"qrichtext\" content=\"1\" /><meta charset=\"utf-8\" /><style type=\"text/css\">\n"
+"p, li { white-space: pre-wrap; }\n"
+"</style></head><body style=\" font-family:'Microsoft YaHei UI'; font-size:9pt; font-weight:400; font-style:normal;\">\n"
+"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'SimSun';\"><br /></p></body></html>", None))
+        self.label_5.setText(QCoreApplication.translate("Form", u"\u56fe\u7247\u538b\u7f29\u8fdb\u5ea6", None))
+        self.label_6.setText(QCoreApplication.translate("Form", u"\u56fe\u7247\u50cf\u7d20\u5bbd\u5ea6", None))
+        self.label_7.setText(QCoreApplication.translate("Form", u"PX(\u5efa\u8bae\u586b\u5199800)", None))
+        self.label_8.setText(QCoreApplication.translate("Form", u"\u6253\u5f00\u6587\u4ef6\u5939", None))
+    # retranslateUi
+

+ 207 - 0
UI/resize_photos.ui

@@ -0,0 +1,207 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Form</class>
+ <widget class="QWidget" name="Form">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>457</width>
+    <height>418</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>图片自动压缩</string>
+  </property>
+  <property name="styleSheet">
+   <string notr="true">background-color: rgb(232, 232, 232);</string>
+  </property>
+  <widget class="QLabel" name="label_2">
+   <property name="geometry">
+    <rect>
+     <x>10</x>
+     <y>70</y>
+     <width>81</width>
+     <height>16</height>
+    </rect>
+   </property>
+   <property name="text">
+    <string>当前图片路径</string>
+   </property>
+  </widget>
+  <widget class="QLabel" name="label_3">
+   <property name="geometry">
+    <rect>
+     <x>100</x>
+     <y>70</y>
+     <width>81</width>
+     <height>16</height>
+    </rect>
+   </property>
+   <property name="styleSheet">
+    <string notr="true">color: rgb(40, 12, 255);</string>
+   </property>
+   <property name="text">
+    <string>点击修改路径</string>
+   </property>
+  </widget>
+  <widget class="QLabel" name="label_4">
+   <property name="geometry">
+    <rect>
+     <x>10</x>
+     <y>90</y>
+     <width>431</width>
+     <height>31</height>
+    </rect>
+   </property>
+   <property name="text">
+    <string>文件夹路径展示</string>
+   </property>
+   <property name="wordWrap">
+    <bool>true</bool>
+   </property>
+  </widget>
+  <widget class="QProgressBar" name="progressBar">
+   <property name="geometry">
+    <rect>
+     <x>20</x>
+     <y>190</y>
+     <width>421</width>
+     <height>31</height>
+    </rect>
+   </property>
+   <property name="value">
+    <number>24</number>
+   </property>
+  </widget>
+  <widget class="QPushButton" name="pushButton">
+   <property name="geometry">
+    <rect>
+     <x>150</x>
+     <y>360</y>
+     <width>161</width>
+     <height>41</height>
+    </rect>
+   </property>
+   <property name="styleSheet">
+    <string notr="true">background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 rgba(255, 137, 27, 255), stop:1 rgba(255, 93, 1, 255));
+color: rgb(255, 255, 255);
+border-radius: 5px;  border: 2px groove gray;
+border:0px;</string>
+   </property>
+   <property name="text">
+    <string>执行压缩</string>
+   </property>
+  </widget>
+  <widget class="QTextBrowser" name="textBrowser">
+   <property name="geometry">
+    <rect>
+     <x>10</x>
+     <y>10</y>
+     <width>431</width>
+     <height>51</height>
+    </rect>
+   </property>
+   <property name="html">
+    <string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
+&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;meta charset=&quot;utf-8&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
+p, li { white-space: pre-wrap; }
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Microsoft YaHei UI'; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;注意当前图片自动改尺寸功能,会遍历您的所选的文件夹,以及子文件夹,请注意文件夹选择是否正确,数据自行备份。执行后无法撤回。&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+   </property>
+  </widget>
+  <widget class="QTextBrowser" name="textBrowser_2">
+   <property name="geometry">
+    <rect>
+     <x>10</x>
+     <y>230</y>
+     <width>431</width>
+     <height>111</height>
+    </rect>
+   </property>
+   <property name="styleSheet">
+    <string notr="true">border-radius: 5px;  border: 2px groove gray;\nborder:0px;</string>
+   </property>
+   <property name="html">
+    <string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
+&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;meta charset=&quot;utf-8&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
+p, li { white-space: pre-wrap; }
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Microsoft YaHei UI'; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'SimSun';&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+   </property>
+  </widget>
+  <widget class="QLabel" name="label_5">
+   <property name="geometry">
+    <rect>
+     <x>20</x>
+     <y>170</y>
+     <width>361</width>
+     <height>20</height>
+    </rect>
+   </property>
+   <property name="text">
+    <string>图片压缩进度</string>
+   </property>
+   <property name="alignment">
+    <set>Qt::AlignCenter</set>
+   </property>
+  </widget>
+  <widget class="QLabel" name="label_6">
+   <property name="geometry">
+    <rect>
+     <x>10</x>
+     <y>140</y>
+     <width>71</width>
+     <height>16</height>
+    </rect>
+   </property>
+   <property name="text">
+    <string>图片像素宽度</string>
+   </property>
+  </widget>
+  <widget class="QLineEdit" name="lineEdit">
+   <property name="geometry">
+    <rect>
+     <x>100</x>
+     <y>130</y>
+     <width>113</width>
+     <height>31</height>
+    </rect>
+   </property>
+   <property name="styleSheet">
+    <string notr="true">background-color: rgb(255, 255, 255);</string>
+   </property>
+  </widget>
+  <widget class="QLabel" name="label_7">
+   <property name="geometry">
+    <rect>
+     <x>220</x>
+     <y>140</y>
+     <width>141</width>
+     <height>16</height>
+    </rect>
+   </property>
+   <property name="text">
+    <string>PX(建议填写800)</string>
+   </property>
+  </widget>
+  <widget class="QLabel" name="label_8">
+   <property name="geometry">
+    <rect>
+     <x>350</x>
+     <y>370</y>
+     <width>81</width>
+     <height>21</height>
+    </rect>
+   </property>
+   <property name="styleSheet">
+    <string notr="true">color: rgb(40, 12, 255);</string>
+   </property>
+   <property name="text">
+    <string>打开文件夹</string>
+   </property>
+  </widget>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>

+ 73 - 0
UI/set_image_mode.py

@@ -0,0 +1,73 @@
+# -*- coding: utf-8 -*-
+
+################################################################################
+## Form generated from reading UI file 'set_image_mode.ui'
+##
+## Created by: Qt User Interface Compiler version 6.7.2
+##
+## WARNING! All changes made in this file will be lost when recompiling UI file!
+################################################################################
+
+from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale,
+    QMetaObject, QObject, QPoint, QRect,
+    QSize, QTime, QUrl, Qt)
+from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor,
+    QFont, QFontDatabase, QGradient, QIcon,
+    QImage, QKeySequence, QLinearGradient, QPainter,
+    QPalette, QPixmap, QRadialGradient, QTransform)
+from PySide6.QtWidgets import (QApplication, QLabel, QLineEdit, QPushButton,
+    QSizePolicy, QWidget)
+
+class Ui_Form(object):
+    def setupUi(self, Form):
+        if not Form.objectName():
+            Form.setObjectName(u"Form")
+        Form.resize(410, 275)
+        sizePolicy = QSizePolicy(QSizePolicy.Policy.Preferred, QSizePolicy.Policy.Ignored)
+        sizePolicy.setHorizontalStretch(0)
+        sizePolicy.setVerticalStretch(0)
+        sizePolicy.setHeightForWidth(Form.sizePolicy().hasHeightForWidth())
+        Form.setSizePolicy(sizePolicy)
+        Form.setStyleSheet(u"background-color: rgb(255, 255, 255);")
+        self.pushButton = QPushButton(Form)
+        self.pushButton.setObjectName(u"pushButton")
+        self.pushButton.setGeometry(QRect(120, 200, 161, 31))
+        self.pushButton.setStyleSheet(u"background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 rgba(255, 137, 27, 255), stop:1 rgba(255, 93, 1, 255));\n"
+"color: rgb(255, 255, 255);\n"
+"border-radius: 5px;  border: 2px groove gray;\n"
+"border:0px;")
+        self.label_7 = QLabel(Form)
+        self.label_7.setObjectName(u"label_7")
+        self.label_7.setGeometry(QRect(10, 35, 91, 21))
+        self.lineEdit = QLineEdit(Form)
+        self.lineEdit.setObjectName(u"lineEdit")
+        self.lineEdit.setGeometry(QRect(100, 35, 271, 20))
+        self.label = QLabel(Form)
+        self.label.setObjectName(u"label")
+        self.label.setGeometry(QRect(90, 60, 281, 16))
+        self.label_2 = QLabel(Form)
+        self.label_2.setObjectName(u"label_2")
+        self.label_2.setGeometry(QRect(90, 125, 281, 16))
+        self.label_8 = QLabel(Form)
+        self.label_8.setObjectName(u"label_8")
+        self.label_8.setGeometry(QRect(10, 100, 91, 21))
+        self.lineEdit_2 = QLineEdit(Form)
+        self.lineEdit_2.setObjectName(u"lineEdit_2")
+        self.lineEdit_2.setGeometry(QRect(100, 100, 271, 20))
+
+        self.retranslateUi(Form)
+
+        QMetaObject.connectSlotsByName(Form)
+    # setupUi
+
+    def retranslateUi(self, Form):
+        Form.setWindowTitle(QCoreApplication.translate("Form", u"\u8bbe\u7f6e", None))
+        self.pushButton.setText(QCoreApplication.translate("Form", u"\u4fdd\u5b58", None))
+        self.label_7.setText(QCoreApplication.translate("Form", u"\u4e0d\u6263\u56fe\u7684\u6587\u4ef6\u5939", None))
+        self.lineEdit.setText(QCoreApplication.translate("Form", u"\u5df2\u6263\u56fe\uff0c", None))
+        self.label.setText(QCoreApplication.translate("Form", u"\u542b\u4ee5\u4e0a\u5173\u952e\u8bcd\u7684\u4e0d\u8fdb\u884c\u62a0\u56fe\uff0c\u591a\u4e2a\u6587\u4ef6\u5939\u4f7f\u7528\u9017\u53f7\u5206\u9694", None))
+        self.label_2.setText(QCoreApplication.translate("Form", u"\u542b\u4ee5\u4e0a\u5173\u952e\u8bcd\u7684\u4e0d\u8fdb\u884c\u62a0\u56fe\uff0c\u591a\u4e2a\u6587\u4ef6\u5939\u4f7f\u7528\u9017\u53f7\u5206\u9694", None))
+        self.label_8.setText(QCoreApplication.translate("Form", u"\u4e0d\u6263\u56fe\u7684\u6587\u4ef6", None))
+        self.lineEdit_2.setText(QCoreApplication.translate("Form", u"\u5df2\u6263\u56fe\uff0c", None))
+    # retranslateUi
+

+ 125 - 0
UI/set_image_mode.ui

@@ -0,0 +1,125 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Form</class>
+ <widget class="QWidget" name="Form">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>410</width>
+    <height>275</height>
+   </rect>
+  </property>
+  <property name="sizePolicy">
+   <sizepolicy hsizetype="Preferred" vsizetype="Ignored">
+    <horstretch>0</horstretch>
+    <verstretch>0</verstretch>
+   </sizepolicy>
+  </property>
+  <property name="windowTitle">
+   <string>设置</string>
+  </property>
+  <property name="styleSheet">
+   <string notr="true">background-color: rgb(255, 255, 255);</string>
+  </property>
+  <widget class="QPushButton" name="pushButton">
+   <property name="geometry">
+    <rect>
+     <x>120</x>
+     <y>200</y>
+     <width>161</width>
+     <height>31</height>
+    </rect>
+   </property>
+   <property name="styleSheet">
+    <string notr="true">background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 rgba(255, 137, 27, 255), stop:1 rgba(255, 93, 1, 255));
+color: rgb(255, 255, 255);
+border-radius: 5px;  border: 2px groove gray;
+border:0px;</string>
+   </property>
+   <property name="text">
+    <string>保存</string>
+   </property>
+  </widget>
+  <widget class="QLabel" name="label_7">
+   <property name="geometry">
+    <rect>
+     <x>10</x>
+     <y>35</y>
+     <width>91</width>
+     <height>21</height>
+    </rect>
+   </property>
+   <property name="text">
+    <string>不扣图的文件夹</string>
+   </property>
+  </widget>
+  <widget class="QLineEdit" name="lineEdit">
+   <property name="geometry">
+    <rect>
+     <x>100</x>
+     <y>35</y>
+     <width>271</width>
+     <height>20</height>
+    </rect>
+   </property>
+   <property name="text">
+    <string>已扣图,</string>
+   </property>
+  </widget>
+  <widget class="QLabel" name="label">
+   <property name="geometry">
+    <rect>
+     <x>90</x>
+     <y>60</y>
+     <width>281</width>
+     <height>16</height>
+    </rect>
+   </property>
+   <property name="text">
+    <string>含以上关键词的不进行抠图,多个文件夹使用逗号分隔</string>
+   </property>
+  </widget>
+  <widget class="QLabel" name="label_2">
+   <property name="geometry">
+    <rect>
+     <x>90</x>
+     <y>125</y>
+     <width>281</width>
+     <height>16</height>
+    </rect>
+   </property>
+   <property name="text">
+    <string>含以上关键词的不进行抠图,多个文件夹使用逗号分隔</string>
+   </property>
+  </widget>
+  <widget class="QLabel" name="label_8">
+   <property name="geometry">
+    <rect>
+     <x>10</x>
+     <y>100</y>
+     <width>91</width>
+     <height>21</height>
+    </rect>
+   </property>
+   <property name="text">
+    <string>不扣图的文件</string>
+   </property>
+  </widget>
+  <widget class="QLineEdit" name="lineEdit_2">
+   <property name="geometry">
+    <rect>
+     <x>100</x>
+     <y>100</y>
+     <width>271</width>
+     <height>20</height>
+    </rect>
+   </property>
+   <property name="text">
+    <string>已扣图,</string>
+   </property>
+  </widget>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>

+ 17 - 0
config.ini

@@ -0,0 +1,17 @@
+[basicSetup]
+name = ¿ÙͼÈí¼þ
+account = 15957854217
+version = 0.17
+env = dev
+last_select_path = C:/Users/gymmc/Desktop/¿Ùͼ²âÊÔ/1
+
+[domain_dev]
+domain = http://mybackend2.pubdata.cn
+host = mybackend2.pubdata.cn
+origin = http://my2.pubdata.cn
+
+[domain_prod]
+domain = https://dev2.valimart.net
+host = dev2.valimart.net
+origin = https://pc.valimart.net
+

+ 5 - 0
custom_config.ini

@@ -0,0 +1,5 @@
+[basicSetup]
+account = 15957854217
+is_fall_dir = żŰÍź,ŇŃżŰÍź
+is_fall_file = ΢ĐĹ
+

+ 0 - 0
log/logging_text.log


+ 1002 - 0
main.py

@@ -0,0 +1,1002 @@
+# -*- coding: utf-8 -*-
+# import time
+# import module.log as log
+import sys
+import os
+import time
+from module.other.log import MyLogger
+from UI.main_ui import Ui_MainWindow
+from PySide6.QtWidgets import *
+from PySide6.QtCore import *
+from PySide6.QtGui import *
+import settings
+
+from module.module_resize_pic import ResizePic
+from module.other.module_setting import ToSetting
+from module.other.module_online_data import GetOnlineData
+from module.module_login import LoginWindow
+from module.remove_bg_pixian import RemoveBgPiXian
+from module.deal_cutout import DealCutout
+
+import requests
+from module.module_move_files import MoveFiles
+import webbrowser
+import io
+from PIL import Image
+from qt_material import apply_stylesheet,list_themes
+
+"""
+抠图软件,使用pixian抠图
+"""
+
+
+class MainWindow(QMainWindow, Ui_MainWindow):
+    sign_self = Signal(dict)
+
+    def __init__(self):
+        super().__init__()
+        self.deal_data_info_1 = {"time": time.time(),
+                                 "num": 1}
+        self.to_end = False
+        self.setupUi(self)
+        self.login_show(flag="hide")
+        self.logger = MyLogger().logger
+        self.setWindowIcon(QIcon("resource\images\icon.png"))
+        self.setWindowTitle("惠利玛图片抠图工具V{}-{}".format(settings.Version, settings.env))
+        self.setFixedSize(self.width(), self.height())
+        # ------------------
+        self.file_path = ""
+        self.one_image_path = ""
+        # ------------------
+        self.mods_list = []
+        self.state = 0
+        self.remaining_times = 0  # 剩余总次数
+        # ---------------
+        self.total_num = 0  # 总条数
+        self.pending_processing = 0  # 待处理
+        self.processing_failed = 0  # 处理失败
+        self.processing_successfully = 0  # 处理成功
+        self.processing_error = 0  # 处理异常
+        # -------------------
+
+        self.state_change(self.state)
+        self.need_cutout_images = []
+        self.mods = False
+        self.r_pixian = RemoveBgPiXian()
+        self._app = None
+        self.get_online_data = GetOnlineData()
+        self.cumulative_frequency_times = 0  # 本次抠图次数
+        self.qss_style()
+        self.init()
+        self.state_change(to_state=0)
+        QTimer.singleShot(500, self.check_versions)  # 检查版本
+        QTimer.singleShot(1000, self.check_login)
+
+    def qss_style(self):
+        style_sheet = """
+                /* 滚动条的整体样式 */
+                QScrollBar {
+                    background-color: #F0F0F0;
+                    width: 5px;
+                    height: 15px;
+                    border: 1px;
+                    margin: 15px 0px 15px 0px;
+                }
+                
+                /* 滚动条的滑块 */
+                QScrollBar::handle {
+                    background-color: #e3e3e3;
+                    min-height: 20px;
+                    border-radius: 15px;
+                }
+
+                /* 滚动条滑块悬停时的样式 */
+                QScrollBar::handle:hover {
+                    background-color: #555555;
+                }
+
+                /* 滚动条滑块按下时的样式 */
+                QScrollBar::handle:pressed {
+                    background-color: #444444;
+                }
+
+                /* 滚动条的上下按钮 */
+                QScrollBar::add-line, QScrollBar::sub-line {
+                    border: none;
+                    background-color: #F0F0F0;
+                    height: 0px;
+                    width: 0px;
+                    subcontrol-position: both-ends;
+                    subcontrol-origin: margin;
+                }
+
+                /* 滚动条的上下按钮不可见 */
+                QScrollBar::add-page, QScrollBar::sub-page {
+                    background: none;
+                }
+
+                /* 滚动条的滑块到达顶部/底部时的样式 */
+                QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical {
+                    height: 0px;
+                }
+
+                /* 滚动条的滑块到达顶部/底部时的样式 */
+                QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical {
+                    background: none;
+                }
+            """
+        # 使用QSS设置圆角
+        self.setStyleSheet(style_sheet)
+
+    def login_info_is_false(self):
+        reply = QMessageBox.question(self, '确认', "登录信息已失效", QMessageBox.Yes)
+        QTimer.singleShot(500, self.to_logout)
+
+    def refresh_times(self, is_online=True, remaining_times=None):
+        # 刷新剩余次数
+        if remaining_times is not None:
+            self.remaining_times = remaining_times
+
+        if is_online:
+            _ = self.get_online_data.get_cutout_image_times()
+            if _ is False:
+                self.remaining_times = 0
+                self.login_info_is_false()
+            else:
+                if "balance" in _:
+                    self.remaining_times = _["balance"]
+        self.label_11.setText("{}".format(self.remaining_times))
+        self.label_13.setText("{}".format(self.cumulative_frequency_times))
+        self.label_10.show()
+
+        if self.remaining_times <= 0:
+            return False
+        return True
+
+    def check_path(self, _path):
+        if not os.path.exists(_path):
+            os.mkdir(_path)
+        return True
+
+    def show_resize_pic_ui(self, *args):
+        self.show_resize_pic = ResizePic()
+
+    def closeEvent(self, event):
+        print("to close")
+        reply = QMessageBox.question(self, '确认', "确定要关闭窗口吗?", QMessageBox.Yes | QMessageBox.No)
+        if reply == QMessageBox.Yes:
+            # 如果用户点击了"是"按钮,则正常关闭窗口
+            super().closeEvent(event)
+            os._exit(0)
+        else:
+            # 否则取消关闭操作
+            event.ignore()
+
+    def login_show(self, flag="show"):
+        if flag == "show":
+            self.label_2.show()
+            self.label_7.show()
+            self.label_10.show()
+            self.label_9.show()
+            self.label_11.show()
+            self.label_12.show()
+            self.label_13.show()
+            self.label_2.setText("--")
+            self.label_7.setText("--")
+            self.label_14.show()
+            self.label_11.setText("--")
+            self.label_13.setText("--")
+        else:
+            self.label_14.hide()
+            self.label_2.hide()
+            self.label_7.hide()
+            self.label_10.hide()
+            self.label_9.hide()
+            self.label_11.hide()
+            self.label_12.hide()
+            self.label_13.hide()
+
+    def label_refresh_times(self, *args):
+        self.label_11.setText("--")
+        self.label_11.show()
+        time.sleep(0.1)
+        self.refresh_times()
+        pass
+
+    def init(self):
+
+        self.label.setText("未避免重复抠图等软件只允许扣jpg格式图片")
+        self.label.show()
+        self.label_5.show()
+        self.label_5.move(40, 40)
+        self.label_14.hide()
+        self.label_14.mousePressEvent = self.label_refresh_times
+
+        self.deal_cutout_mode = DealCutout(windows=self)
+        self.deal_cutout_mode.signal_data.connect(self.deal_sign_data)
+        self.label_5.mousePressEvent = self.select_file_path
+        self.label_8.mousePressEvent = self.select_file_path
+
+        self.pushButton_6.clicked.connect(self.stop_func)  # 停止按钮
+
+        self.sign_self.connect(self.deal_sign_data)
+        self.pushButton.clicked.connect(lambda: self.deal_sign_data({"_type": "run_cutout"}))
+        self.pushButton_6.hide()
+
+        # 菜单
+        self.action_2.triggered.connect(self.show_resize_pic_ui)
+        self.action_5.triggered.connect(self.show_move_file_ui)
+        self.action_10.triggered.connect(self.show_to_setting)
+        self.action_11.triggered.connect(self.contact_us)
+
+    def contact_us(self, *args):
+        url = 'https://www.valimart.net/'
+        webbrowser.open(url)
+
+    def open_file_path(self, *args, **kwargs):
+        try:
+            if self.file_path:
+                os.startfile(self.file_path)
+        except:
+            pass
+
+    def deal_sign_data(self, data: dict):
+        # 进度处理
+        if data["_type"] == "schedule":
+            processing_failed, processing_successfully = data["data"]["processing_failed"], data["data"][
+                "processing_successfully"]
+            self.pending_processing -= 1
+            self.processing_successfully += processing_successfully
+
+            self.processing_failed += processing_failed
+
+            # if processing_successfully > 0:
+            #     # self.remaining_times -= 1
+            #     # self.cumulative_frequency_times += 1
+            #     self.label_13.setText("{}".format(self.cumulative_frequency_times))
+
+            self.send_processing()
+
+            if self.pending_processing <= 0:
+                t = time.time() - self.deal_data_info_1["time"]
+                n = self.deal_data_info_1["num"]
+                self.logger.info("本次图片张数:{},共计耗时:{}".format(n, t))
+
+                data = {"_type": "complete",
+                        "data": ""
+                        }
+                self.sign_self.emit(data)
+
+        if data["_type"] == "refresh_times":
+            self.cumulative_frequency_times += data["data"]["cumulative_frequency_times_change"]
+
+            if data["data"]["cumulative_frequency_times_change"] < 0:
+                self.remaining_times = self.remaining_times + 1
+            else:
+                self.remaining_times = self.remaining_times - 1
+
+            print("self.remaining_times:", self.remaining_times)
+            self.refresh_times(is_online=False, )
+
+        if data["_type"] == "run_cutout":
+            self.pushButton.setEnabled(False)
+            need_cutout_images = []
+            for image_item in self.widget_2.findChildren(MyImage):
+                need_cutout_images.append(image_item.image_data)
+
+            if not self.mods:
+                a = QMessageBox.question(self, '确认', '无抠图权限,请联系业务员'.format(),
+                                         QMessageBox.Yes)
+                if a == QMessageBox.Yes:
+                    pass
+                self.pushButton.setEnabled(True)
+                return
+
+            n = len([x for x in need_cutout_images if x["need_cutout"]])
+            if n == 0:
+                a = QMessageBox.question(self, '确认', '没有需要的处理的图片'.format(),
+                                         QMessageBox.Yes)
+                self.pushButton.setEnabled(True)
+
+            if n > 0:
+                # 检查余额是否正确
+                if self.remaining_times < n:
+                    a = QMessageBox.question(self, '确认', '待处理图:{}张,剩余点数:{},余额不足'.format(n, self.remaining_times),
+                                             QMessageBox.Yes)
+                    if a == QMessageBox.Yes:
+                        pass
+                    self.pushButton.setEnabled(True)
+                    return
+                else:
+                    a = QMessageBox.question(self, '确认', '图片总数:{},是否进行抠图处理?'.format(n),
+                                             QMessageBox.Yes | QMessageBox.No)
+                    if a == QMessageBox.Yes:
+                        self.deal_data_info_1 = {"time": time.time(),
+                                                 "num": n}
+                        self.label.setText("")
+                        self.state_change(to_state=2)
+                        self.total_num = len([x for x in need_cutout_images if x["need_cutout"]])  # 总条数
+                        self.pending_processing = int(self.total_num)  # 待处理
+                        self.processing_failed = 0  # 处理失败
+                        self.processing_successfully = 0  # 处理成功
+                        self.processing_error = 0  # 处理异常
+                        self.deal_cutout_mode.need_cutout_images = need_cutout_images
+                        self.deal_cutout_mode.start()
+
+        if data["_type"] == "clean_text":
+            print("clean_text=========================")
+            return
+
+        if data["_type"] == "info":
+            self.show_text_browser(data["data"])
+            return
+
+        if data["_type"] == "complete":
+            if self.state != 1:
+                self.state_change(to_state=1)
+                time.sleep(0.2)
+                self.refresh_times(is_online=True)
+            return
+
+        if data["_type"] == "progress_display":
+            self.label.setText(data["data"])
+            if data["show_p"]:
+                self.progressBar.show()
+                total_num = data["total_num"]
+                if total_num > 0:
+                    pending_processing = data["pending_processing"]
+                    # print("total_num:{},pending_processing:{}".format(total_num, pending_processing))
+                    v = int((total_num - pending_processing) / total_num * 100)
+                    # print("progressBar", v)
+                    self.progressBar.setValue(v)
+            else:
+                self.progressBar.hide()
+            return
+
+        if data["_type"] == "show_text_browser":
+            self.show_text_browser(data["data"])
+            return
+
+        if data["_type"] == "show_image_item_info":
+            if data["data"]["file_path"] in self.all_image_item:
+                image_item = self.all_image_item[data["data"]["file_path"]]
+                image_item.set_image_text(data["data"]["text"], data["data"]["info"])
+                pass
+
+    def send_processing(self, show_p=True):
+        data = {"_type": "progress_display",
+                "data": "总数:{total_num} 待处理{pending_processing}条 完成{processing_successfully}条  失败{processing_failed}条  系统异常{processing_error}条".format(
+                    total_num=self.total_num,
+                    pending_processing=self.pending_processing,
+                    processing_successfully=self.processing_successfully,
+                    processing_failed=self.processing_failed,
+                    processing_error=self.processing_error
+                ),
+                "total_num": self.total_num,
+                "pending_processing": self.pending_processing,
+                "show_p": show_p,
+                }
+        # print(data)
+        self.sign_self.emit(data)
+
+    def show_label_images(self,show_not_need_images=False):
+        # 清空元素
+        self.all_image_item = {}
+        self.widget_2.move(0, 0)
+        self.widget_2.width = self.scrollArea.width()
+        for image_item in self.widget_2.findChildren(MyImage):
+            image_item.deleteLater()
+
+        x, y = 20, 10
+        for image_data in self.need_cutout_images:
+            if not show_not_need_images:
+                if not image_data["need_cutout"]:
+                    continue
+            image_item = MyImage(parent=self.widget_2, image_data=image_data, windows=self)
+            self.all_image_item[image_data["file_path"]] = image_item
+            image_item.signal_data.connect(self.deal_sign_data)
+            image_item.move(x, y)
+            image_item.show()
+            x = x + image_item.width + 9
+            if x > 300:
+                x = 20
+                y = y + 10 + image_item.height
+
+        # self.widget_2.height = y + 500
+        print(self.scrollArea.width(), y + 80)
+        self.widget_2.resize(self.scrollArea.width(), y + 80)
+        # 滚动条进行置顶操作
+        self.scrollArea.verticalScrollBar().setValue(0)
+        self.scrollAreaWidgetContents.setMinimumSize(0, self.widget_2.height() + 20)
+
+    def show_to_setting(self):
+        self.t_setting = ToSetting(windows=self)
+
+    def show_move_file_ui(self, *args, **kwargs):
+        MoveFiles(windows=self)
+        pass
+
+    def check_versions(self):
+        def compare_versions(version1, version2):
+            v1 = list(map(int, version1.split(".")))
+            v2 = list(map(int, version2.split(".")))
+            print(v1, v2)
+            if v1 > v2:
+                return 1
+            elif v1 < v2:
+                return -1
+            else:
+                return 0
+        # todo 版本更新确认
+        url = "{domain}/api/openai/client_version".format(
+            domain=settings.DOMAIN,
+        )
+
+        s = requests.get(url=url, params={"type": "client_remove_bg"})
+        online_version = None
+        try:
+            r_data = s.json()
+            print(r_data["data"])
+            online_version = r_data["data"]["version"]
+        except:
+            # self.label_6.setText("获取抠图软件版本信息错误")
+            pass
+        print("online_version:", online_version)
+        if online_version:
+            if compare_versions(settings.Version, online_version) == -1:
+                a = QMessageBox.question(self, '确认', '当前不是最新版本,请下载最新版本',
+                                         QMessageBox.Yes)
+                if a == QMessageBox.Yes:
+                    print("close")
+                os._exit(0)
+                # self.close()
+                return
+
+    def check_login(self, *args, **kwargs):
+        # 验证用户身份有效性
+        if settings.Account and settings.Key:
+            self.login_complete()
+        else:
+            self.login_show(flag="hide")
+            self.label_3.setText("登录")
+            self.label_3.mousePressEvent = self.to_login
+
+    def show_text_browser(self, text):
+        # self.textBrowser.append(text)
+        pass
+
+    def unselect_file_path(self, *args):
+        if self.state == 1:
+            self.state_change(to_state=0)
+
+    def select_file_path(self, *args):
+
+        if not settings.IsLogin:
+            a = QMessageBox.question(self, '确认', '请先登录',
+                                     QMessageBox.Yes)
+            return
+
+        if not self.mods:
+            a = QMessageBox.question(self, '确认', '无抠图软件权限,请联系管理员',
+                                     QMessageBox.Yes)
+            return
+
+        messageBox = QMessageBox()
+        messageBox.setWindowTitle(' ')
+        messageBox.setText('如您选择文件夹,则软件会自动遍历您选择文件下的所有文件夹;为避免重复抠图等软件只允许扣jpg格式图片')
+        # style_sheet = """
+        #         QMessageBox {
+        #             background-color: #F5F5F5;
+        #             font-family: Arial, sans-serif;
+        #             font-size: 14px;
+        #             color: #333333;
+        #             border-radius: 10px;
+        #             padding: 10px;
+        #             outline: none;
+        #             icon: none;
+        #         }
+        #         QMessageBox QPushButton {
+        #             background-color: #007BFF;
+        #             color: #FFFFFF;
+        #             border: none;
+        #             border-radius: 5px;
+        #             padding: 8px 15px;
+        #             font-size: 16px;
+        #             font-weight: bold;
+        #             margin: 10px;
+        #         }
+        #         QMessageBox QPushButton:hover {
+        #             background-color: #0056b3;
+        #         }
+        #         QMessageBox QPushButton:pressed {
+        #             background-color: #004085;
+        #         }
+        #         QMessageBox QLabel {
+        #             padding: 10px;
+        #             font-size: 16px;
+        #             font-weight: bold;
+        #         }
+        #         QMessageBox QFrame {
+        #             border: 1px solid #DADADA;
+        #             border-radius: 10px;
+        #         }
+        #     """
+        # messageBox.setStyleSheet(style_sheet)
+        messageBox.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
+        # messageBox.setIcon(QMessageBox.NoIcon)  # 设置无图标
+        buttonY = messageBox.button(QMessageBox.Yes)
+        buttonY.setText('选择文件夹')
+        buttonN = messageBox.button(QMessageBox.No)
+        buttonN.setText('选择图片')
+        messageBox.exec()
+
+        if settings.LastSelectPath:
+            last_select_path = settings.LastSelectPath
+        else:
+            last_select_path = "./"
+
+        if messageBox.clickedButton() == buttonY:
+            file_path = QFileDialog.getExistingDirectory(self, "选取文件夹", last_select_path)
+            # 存储last_select_path
+            self.file_path = file_path
+            self.one_image_path = ""
+            if not file_path:
+                return
+            # 显示文件名称
+            text = "已选:" + file_path
+            if len(text) > 28:
+                text = text[:15] + "..." + text[-10:]
+            self.label_4.setText(text)
+
+            # 检查需要处理的文件数量
+            self.init_images(file_path=self.file_path)
+            if len([x for x in self.need_cutout_images if x["need_cutout"]]) == 0:
+                a = QMessageBox.question(self, '确认', '您所选文件夹下没有jpg图片,或对应图片已扣图',
+                                         QMessageBox.Yes)
+                if a == QMessageBox.Yes:
+                    pass
+
+            if len([x for x in self.need_cutout_images if x["need_cutout"]]) > 0:
+                self.state_change(to_state=1)
+        else:
+            # 选择图片
+            images_path_list = QFileDialog.getOpenFileNames(self, "选择图片", last_select_path,
+                                                            "*.jpg;;*.jpeg;;All Files(*)")
+
+            print("已选images_path_list:", images_path_list)
+
+            self.file_path = ""
+
+            self.one_image_path = []
+            _Type = ['.jpg', '.JPG', '.jpeg', '.JPEG', ]
+            for image_path in images_path_list[0]:
+                _file = os.path.split(image_path)[1]
+                _f_e = os.path.splitext(_file)[1]
+                if _f_e in _Type:
+                    self.one_image_path.append(image_path)
+
+            if not self.one_image_path:
+                return
+            file_path = os.path.split(self.one_image_path[0])[0]
+
+            # 显示文件名称
+            text = "已选:" + "{}个图片文件".format(len(self.one_image_path))
+            if len(text) > 28:
+                text = text[:15] + "..." + text[-10:]
+            self.label_4.setText(text)
+
+            # 检查需要处理的文件数量
+            self.init_images(image_list=self.one_image_path)
+            # state_change
+            if len(self.need_cutout_images) > 0:
+                self.state_change(to_state=1)
+
+        settings.LastSelectPath = file_path
+        self.file_path = file_path
+        settings.set_config(data_dict={"last_select_path": last_select_path}, section="basicSetup",
+                            _config_name="config")
+
+        self.label_15.mousePressEvent = self.open_file_path
+
+    def init_images(self, file_path=None, image_list=None):
+        self.need_cutout_images = []
+        self.pushButton.hide()
+        self.pushButton.setEnabled(False)
+        self._n = 0
+        self._n_c = 0
+        show_not_need_images = False
+        if file_path:
+            show_not_need_images = False
+            self.check_need_cutout_images(root_path=file_path)
+
+        if image_list:
+            show_not_need_images = True
+            for image_path in image_list:
+                root_path, file = os.path.split(image_path)
+                file_name, file_e = os.path.splitext(file)
+                self.need_cutout_images.append({"file_name": file_name,
+                                                "file_e": file_e,
+                                                "file_path": image_path,
+                                                "file": file,
+                                                "root_path": root_path,
+                                                "need_cutout": True,
+                                                })
+
+            for index,image_data in enumerate(self.need_cutout_images):
+                root_path = image_data["root_path"]
+                file_name = image_data["file_name"]
+                _path_1 = "{}/{}.png".format(root_path,file_name)
+                _path_2 = "{}/已扣图/{}.png".format(root_path,file_name)
+                if os.path.exists(_path_1):
+                    self.need_cutout_images[index]["need_cutout"] = False
+                    continue
+                if os.path.exists(_path_2):
+                    self.need_cutout_images[index]["need_cutout"] = False
+                    continue
+
+        # print("self.need_cutout_images",self.need_cutout_images)
+        # if file_path:
+        #     if len([x for x in self.need_cutout_images if x["need_cutout"]]) > 0:
+        #         self.sign_self.emit({"_type": "clean_text"})
+        #         self.pushButton.show()
+        #         self.pushButton.setEnabled(True)
+        # else:
+        #     if len(self.need_cutout_images) > 0:
+        #         self.sign_self.emit({"_type": "clean_text"})
+        #         self.pushButton.show()
+        #         self.pushButton.setEnabled(True)
+        self.show_label_images(show_not_need_images)
+
+    def check_need_cutout_images(self, root_path):
+        _Type = ['.jpg', '.JPG', '.jpeg', '.JPEG', ]
+        _is_cutout = []
+        for file in os.listdir(root_path):
+            self._n_c += 1
+            if self._n_c > 500:
+                self.need_cutout_images = []
+                data = {"_type": "show_text_browser",
+                        "data": "目录下文件过多,请检查目录是否正确"
+                        }
+                self.sign_self.emit(data)
+                return
+            file_path = "{}/{}".format(root_path, file)
+            if os.path.isdir(file_path):
+                print(file_path)
+                if file == "已扣图":
+                    # 哪些图片已经有抠图
+                    for x_file in os.listdir(file_path):
+                        x_file_name, x_file_e = os.path.splitext(x_file)
+                        if x_file_e == ".png":
+                            _is_cutout.append(x_file_name)
+
+        # ===============================================================
+        for file in os.listdir(root_path):
+            file_path = "{}/{}".format(root_path, file)
+            if os.path.isdir(file_path):
+                print(file_path)
+                # 不是已扣图文件夹,则进行遍历
+                f = True
+                for i in settings.is_fall_dir:
+                    if i in file:
+                        f = False
+                        break
+                if f:
+                    self.check_need_cutout_images(file_path)
+
+            file_name, file_e = os.path.splitext(file)
+            if file_e not in _Type:
+                continue
+
+            # 检查文件是否在禁止抠图里
+            f = True
+            for i in settings.is_fall_file:
+                if i in file:
+                    f = False
+                    break
+            if not f:
+                continue
+
+            need_cutout = False if file_name in _is_cutout else True
+            if os.path.exists("{}/{}.png".format(root_path, file_name)):
+                need_cutout = False
+
+            # 图片进行处理
+            self.need_cutout_images.append({"file_name": file_name,
+                                            "file_e": file_e,
+                                            "file_path": file_path,
+                                            "file": file,
+                                            "root_path": root_path,
+                                            "need_cutout": need_cutout,
+                                            })
+
+    def to_login(self, *args, **kwargs):
+        self.login = LoginWindow(windows=self, call_back=self.login_complete)
+
+    def login_complete(self, *args, **kwargs):
+        # settings.get_authorization()
+        print("登录验证~")
+        url = "{domain}/api/auth/user".format(
+            domain=settings.DOMAIN
+        )
+        s = requests.session()
+        _s = s.get(url=url, headers=settings.Headers)
+        # print(_s)
+        response_data = _s.json()
+        code = response_data["code"]
+        # print(response_data)
+        if code == 0:
+            settings.Headers = {
+                "Authorization": settings.Authorization,
+                "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36",
+                "Origin": settings.Origin,
+                "Host": settings.Host,
+                "Content-Type": "application/json;charset=UTF-8"
+            }
+            # print(settings.Headers)
+            self.login_show(flag="show")
+            self.label_2.setText(response_data["data"]["real_name"] + "\n" + response_data["data"]["phone"])
+            self.label_7.setText(response_data["data"]["brand_company_name"])
+            self.label_3.setText("退出")
+            self.label_3.mousePressEvent = self.to_logout
+            settings.IsLogin = True
+            menu_dict = GetOnlineData().get_current_menu()
+            # todo 处理操作权限等
+            self.mods_list = []
+            # menu_dict = {"HctGood":"111111"}
+            self.mods = False
+            if 'DataDashboard' in menu_dict:
+                if "批量抠图" in menu_dict["DataDashboard"]:
+                    self.mods = True
+
+                self.mods_list = menu_dict["DataDashboard"]
+                print("mods_list:", self.mods_list)
+                # if "add" in menu_dict["HctGood"]:
+                self.get_online_data.refresh_headers()
+                self.refresh_times()
+            else:
+                pass
+                # self.pushButton_5.setText("无抠图权限")
+                # self.pushButton_5.setEnabled(False)
+                # self.pushButton_7.hide()
+                self.mods = False
+
+            self.state_change(self.state)
+            # 存储登录用户手机号
+            settings.Account = str(response_data["data"]["phone"])
+            settings.set_config(data_dict={"Account": settings.Account, }, _config_name="config")
+            return True
+
+        else:
+            self.label_14.hide()
+            self.login_show(flag="hide")
+            self.label_3.setText("登录")
+            self.label_3.mousePressEvent = self.to_login
+            settings.IsLogin = False
+            self.mods = False
+            return False
+
+    def to_logout(self, *args, **kwargs):
+        # http://pcback.cnhqt.com/api/auth/logout
+        url = "{domain}/api/auth/logout".format(
+            domain=settings.DOMAIN
+        )
+        s = requests.session()
+        _s = s.post(url=url, headers=settings.Headers)
+        # response_data = _s.json()
+        data_dict = {
+            "account": "",
+        }
+        settings.Authorization = ""
+        settings.set_config(data_dict)
+        settings.set_key("")  # 清空密码
+
+        # 初始化
+        self.login_show(flag="hide")
+        self.label_3.setText("登录")
+        self.label_3.mousePressEvent = self.to_login
+        settings.IsLogin = False
+        self.mods = False
+        self.state_change(to_state=0)
+
+    def state_change(self, to_state: int):
+        self.state = to_state
+
+        # 初始化
+        if self.state == 0:
+            for image_item in self.widget_2.findChildren(MyImage):
+                image_item.deleteLater()
+
+            self.label_5.show()
+            self.widget_3.move(10, 10)
+            self.widget_3.hide()
+            self.widget.move(10, 10)
+            self.widget.hide()
+            self.scrollArea.resize(391, 311)
+            self.scrollArea.move(10, 10)
+            self.scrollAreaWidgetContents.setMinimumSize(0, 200)
+            self.progressBar.hide()
+            self.pushButton_6.hide()
+            self.file_path = ""
+            # self.label.setText("")
+            # self.label.hide()
+            self.excel_file_dict = {}
+            self.label_4.setText("")
+            # self.label_5.hide()
+            self.pushButton.hide()
+
+        # 已选择文件未开始
+        if self.state == 1:
+            self.label_5.hide()
+            self.label_8.show()
+            self.scrollArea.move(10, 60)
+            self.scrollArea.resize(391, 261)
+            self.widget_3.show()
+            self.widget.hide()
+            self.progressBar.hide()
+            self.label.show()
+            self.pushButton.setEnabled(True)
+            self.pushButton_6.hide()
+            self.pushButton.show()
+            self.label_14.show()
+
+        # 进行中处理
+        if self.state == 2:
+            self.label_5.hide()
+            self.label_8.hide()
+            self.pushButton.setEnabled(False)
+            self.scrollArea.move(10, 60)
+            self.scrollArea.resize(391, 261)
+            self.widget_3.hide()
+            self.widget.show()
+            self.progressBar.setValue(0)
+            self.progressBar.show()
+            # self.label_5.hide()
+            # self.label.setText("")
+            self.label_14.hide()
+            self.pushButton_6.show()
+            self.pushButton.hide()
+
+        # 隐藏无权限按钮
+        # if "add" not in self.mods_list:
+        #     self.pushButton.hide()
+        # if "export" not in self.mods_list:
+        #     self.action_6.setEnabled(False)
+        # else:
+        #     self.action_6.setEnabled(True)
+
+    def stop_func(self):
+        a = QMessageBox.question(self, '确认', '是否终止当前正在运行?',
+                                 QMessageBox.Yes | QMessageBox.No)
+        if a == QMessageBox.Yes:
+            self.deal_cutout_mode.state = 2
+            self.state_change(to_state=1)
+
+class MyImage(QLabel):
+    signal_data = Signal(dict)
+
+    def __init__(self, parent, image_data, windows):
+        super().__init__(parent)
+        self.windows = windows
+        self.image_data = image_data
+        self.image_path = image_data["file_path"]
+        self.image_file = os.path.split(image_data["file_path"])[1]
+
+        self.resize(61, 81)
+        self.width = 61
+        self.height = 81
+        self.setStyleSheet(
+            "background-color: rgb(255, 255, 255);border-radius: 5px;  border: 2px groove gray;border:0px;")
+        self.label_2 = QLabel(self)
+        self.label_2.move(0, 0)
+        self.label_2.resize(61, 61)
+
+        self.label = QLabel(self)
+        self.label.move(0, 61)
+        self.label.resize(61, 20)
+        self.set_label_image()
+        self.label.setAlignment(Qt.AlignCenter)
+        self.label.show()
+        self.label_2.show()
+
+    def crop_to_square(self,img):
+        # 打开图片
+        width, height = img.size  # 获取原始图片的宽度和高度
+        if width == height:
+            return img
+        if width > height:
+            _x = int((width-height)/2)
+            img = img.crop((_x, 0, width-_x, height))
+        else:
+            _y = int((height-width) / 2)
+            img = img.crop((0, _y, width, height-_y))
+        return img
+
+    def set_label_image(self):
+        try:
+            bytes_io = io.BytesIO()
+            w, h = self.label_2.width(), self.label_2.height()
+
+            _img_raw = Image.open(self.image_path)
+            _img_raw.thumbnail((w*2, h*2))
+            _img_raw = self.get_image_orientation(_img_raw)
+            img_raw = self.crop_to_square(_img_raw)
+            img_raw = img_raw.resize(size=(w, h))
+            img_raw.save(bytes_io, "JPEG")
+            icon = QPixmap()
+            # icon.loadFromData(img)
+            icon.loadFromData(bytes_io.getvalue())
+            # icon = icon.scaled(self.size(), Qt.KeepAspectRatio, Qt.SmoothTransformation)
+            self.label_2.setPixmap(icon)
+            # self.mousePressEvent = lambda x: self.show_one_data(row)
+
+            if self.image_data["need_cutout"] is False:
+                self.set_image_text("有抠图过")
+            else:
+                self.set_image_text("未开始")
+        except:
+            self.image_data["need_cutout"] = False
+            self.set_image_text("图异常", info="{} 图片异常无法进行抠图".format(self.image_file))
+            self.label_2.setStyleSheet("""background-color: rgb(228, 228, 255);color: rgb(0, 0, 0);""")
+
+    def get_image_orientation(self,img):
+        # 获取EXIF数据
+        exif = img._getexif()
+        if exif is not None:
+            # EXIF标签274对应的是Orientation
+            orientation = exif.get(0x0112)
+            if orientation == 2:
+                # 水平翻转
+                img = img.transpose(Image.FLIP_LEFT_RIGHT)
+            elif orientation == 3:
+                # 旋转180度
+                img = img.rotate(180, expand=True)
+            elif orientation == 4:
+                # 垂直翻转
+                img = img.transpose(Image.FLIP_TOP_BOTTOM)
+            elif orientation == 5:
+                # 水平翻转后顺时针旋转90度
+                img = img.transpose(Image.FLIP_LEFT_RIGHT).transpose(Image.ROTATE_270)
+            elif orientation == 6:
+                # 顺时针旋转90度
+                img = img.transpose(Image.ROTATE_270)
+            elif orientation == 7:
+                # 水平翻转后逆时针旋转90度
+                img = img.transpose(Image.FLIP_LEFT_RIGHT).transpose(Image.ROTATE_90)
+            elif orientation == 8:
+                # 逆时针旋转90度
+                img = img.transpose(Image.ROTATE_90)
+            else:
+                pass
+
+        return img
+
+    def set_image_text(self, text, info=""):
+        s = {
+            "未开始": """background-color: rgb(255, 255, 255);color: rgb(0, 0, 0);""",
+            "进行中": """background-color: rgb(255, 255, 255);color: rgb(255, 220, 91);""",
+            "已完成": """background-color: rgb(255, 255, 255);color: rgb(89, 168, 105);""",
+            "出错/超时": """background-color: rgb(255, 255, 255);color: rgb(219, 88, 96);""",
+            "已取消": """background-color: rgb(255, 255, 255);color: rgb(219, 88, 96);""",
+            "图异常": """background-color: rgb(255, 255, 255);color: rgb(219, 88, 96);""",
+            "有抠图过": """background-color: rgb(255, 255, 255);color: rgb(53, 36, 137);""",
+        }
+        if text in ["已完成", "图异常"]:
+            self.image_data["need_cutout"] = False
+
+        if text in s:
+            self.label.setStyleSheet(s[text])
+
+        self.label.setText(text)
+        if info:
+            self.label.setToolTip(info)
+
+
+if __name__ == '__main__':
+    QApplication.setAttribute(Qt.AA_EnableHighDpiScaling)
+    app = QApplication(sys.argv)
+    print(list_themes())
+
+    apply_stylesheet(app, theme='light_blue.xml',invert_secondary=True)
+    main_window = MainWindow()
+    main_window.show()
+    sys.exit(app.exec())

+ 673 - 0
module/deal_cutout - 副本.py

@@ -0,0 +1,673 @@
+import copy
+import random
+import time
+from concurrent.futures import as_completed, ThreadPoolExecutor
+import threading
+import os
+from module.remove_bg_pixian import RemoveBgPiXian
+from PySide6.QtWidgets import *
+from PySide6.QtCore import *
+from module.other.module_online_data import GetOnlineData
+import hashlib
+from PIL import Image
+from module.other.remove_bg_ali import RemoveBgALi
+from module.other.pic import Picture
+import io
+from module.other.log import logger
+from module.deal_one_image import DealOneImage
+
+
+class DealCutout(QThread):
+    signal_data = Signal(dict)
+
+    def __init__(self, windows):
+        super().__init__()
+        self.windows = windows
+        self.lock = threading.Lock()
+        self.r_ali = RemoveBgALi()
+        self.r_pixian = RemoveBgPiXian()
+        self.need_cutout_images = {}
+        self.state = 2  # 1进行中 2停止
+        self.get_online_data = GetOnlineData()
+        self.is_upload_pic_num = 0
+        self.is_deal_num = 0
+        # 图片列表
+        self.upload_pic_dict = {}
+
+    def run(self):
+        # self.total_num = len([x for x in self.need_cutout_images if x["need_cutout"]])  # 总条数
+        # self.pending_processing = int(self.total_num)  # 待处理
+        # self.processing_failed = 0  # 处理失败
+        # self.processing_successfully = 0  # 处理成功
+        # self.processing_error = 0  # 处理异常
+        self.get_online_data.refresh_headers()
+
+        executor = ThreadPoolExecutor(max_workers=4)
+        executor_pic_upload = ThreadPoolExecutor(max_workers=2)
+
+        tasks = []
+        tasks_2 = []
+        self.state = 1
+        self.is_upload_pic_num = 0
+        self.is_deal_num = 0
+        num = 0
+        for image_data in self.need_cutout_images:
+            if not image_data["need_cutout"]:
+                continue
+            num += 1
+            task = executor.submit(DealOneImage(image_data=image_data, lock=self.lock, windows=self, num=num).run)
+            tasks.append(task)
+
+            task_2 = executor_pic_upload.submit(self.upload_pics, image_data=image_data)
+            tasks_2.append(task_2)
+
+    def send_info(self, text="", is_success=None, _type="show_text_browser"):
+        with self.lock:
+            if is_success is not None:
+                if is_success:
+                    processing_failed = 0
+                    processing_successfully = 1
+                else:
+                    processing_failed = 1
+                    processing_successfully = 0
+
+                self.signal_data.emit({"_type": "schedule",
+                                       "data": {"processing_failed": processing_failed,
+                                                "processing_successfully": processing_successfully,
+                                                }})
+
+            if text:
+                data = {"_type": "show_text_browser",
+                        "data": text,
+                        }
+                self.signal_data.emit(data)
+
+    def show_image_info(self, data):
+        with self.lock:
+            data = {"_type": "show_image_item_info",
+                    "data": data,
+                    }
+            self.signal_data.emit(data)
+
+    def add_log(self, text, _type="info"):
+        with self.lock:
+            logger.info(text)
+
+    def run_with_thread222(self, image_data):
+        with self.lock:
+            self.is_deal_num += 1
+        file_path = image_data["file_path"]
+
+        self.add_log("开始处理第{}个,图片地址:{}".format(self.is_deal_num, file_path))
+
+        self.send_info("\n开始处理:{}".format(file_path[-20:] if len(file_path) > 20 else file_path))
+        _data = {"text": "处理中",
+                 "info": "",
+                 "file_path": file_path
+                 }
+        self.show_image_info(_data)
+
+        if self.windows.remaining_times <= 0:
+            self.send_info(text="次数不足,处理失败", is_success=False)
+            return
+        # 检查图片上传是否有结束
+        n = 90
+        while 1:
+            if self.state != 1:
+                self.send_info(text="{} 用户主动终止".format(image_data["file_name"]), is_success=False)
+                return
+            time.sleep(1)
+            n -= 1
+            # print(n)
+            if file_path in self.upload_pic_dict:
+                break
+            else:
+                if n <= 0:
+                    text = "{} 图片上传处理超时".format(image_data["file_name"])
+                    self.send_info(text=text, is_success=False)
+                    logger.warning(text)
+                    _data = {"text": "出错/超时",
+                             "info": "处理超时",
+                             "file_path": file_path
+                             }
+                    self.show_image_info(_data)
+                    return
+                continue
+
+        s = time.time()
+        # print(self.upload_pic_dict[file_path])
+        _flag = self.upload_pic_dict[file_path]["flag"]
+
+        if not _flag:
+            self.add_log("第{}个 未查到上传的图片地址".format(self.is_deal_num))
+
+            _data = {"text": "出错/超时",
+                     "info": "上传错误",
+                     "file_path": file_path
+                     }
+            self.show_image_info(_data)
+            text = "{} 上传错误".format(image_data["file_name"])
+            self.send_info(text=text, is_success=False)
+            return
+
+        image_url = self.upload_pic_dict[file_path]["url"]
+        image_deal_info = self.upload_pic_dict[file_path]["image_deal_info"]
+
+        _data = {"text": "开始抠图",
+                 "info": "",
+                 "file_path": file_path
+                 }
+        self.show_image_info(_data)
+
+        self.add_log("第{}个 开始抠图".format(self.is_deal_num))
+
+        with self.lock:
+            self.is_upload_pic_num -= 1
+
+        # todo 抠图
+        out_root_path = "{}/已扣图".format(image_data["root_path"])
+        self.check_path(out_root_path)
+        print(image_url)
+        try:
+            generate_ids, remaining_times = self.get_online_data.remove_background(images_url=[image_url])
+            self.add_log("第{}个 上报抠图任务成功,任务id:{}".format(self.is_deal_num, generate_ids))
+        except BaseException as e:
+            print(e)
+            text = "{} 提交抠图请求错误".format(image_data["file_name"])
+            print(text)
+
+            self.add_log("第{}个 提交抠图请求错误".format(self.is_deal_num))
+            self.send_info(text=text, is_success=False)
+
+            _data = {"text": "出错/超时",
+                     "info": text,
+                     "file_path": file_path
+                     }
+            self.show_image_info(_data)
+            return
+
+        with self.lock:
+            self.signal_data.emit({"_type": "refresh_times",
+                                   "data": {"remaining_times": remaining_times,
+                                            "is_online": False
+                                            }})
+
+        # 查询抠图进度
+        time.sleep(2)
+        generate_ids = [str(x) for x in generate_ids]
+
+        n = 60 * 5
+        with self.lock:
+            print(generate_ids)
+            print(file_path, "查询抠图进度")
+
+        self.add_log("第{}个 查询抠图进度,id:{}".format(self.is_deal_num, generate_ids))
+        while 1:
+            try:
+                data = self.get_online_data.search_progress(generate_ids=generate_ids)
+                pixian_status = data[0]["status"]
+
+            except BaseException as e:
+                print(e)
+                text = "{} 查询抠图进度错误".format(image_data["file_name"])
+                self.add_log("第{}个 查询抠图进度错误,id:{}".format(self.is_deal_num, generate_ids))
+                print(text)
+                logger.error("{};{}".format(text, e))
+                self.send_info(text=text, is_success=False)
+
+                _data = {"text": "出错/超时",
+                         "info": text,
+                         "file_path": file_path
+                         }
+                self.show_image_info(_data)
+                return
+
+            # print(data)
+
+            time.sleep(1)
+            n -= 1
+            if self.state != 1:
+                self.send_info(text="{} 用户主动终止".format(image_data["file_name"]), is_success=False)
+                return
+
+            if n <= 0:
+                result = False
+                text = "{} 抠图300秒超时".format(image_data["file_name"])
+                _data = {"text": "已完成",
+                         "info": text,
+                         "file_path": file_path
+                         }
+                self.show_image_info(_data)
+                self.send_info(text=text, is_success=False)
+                _data = {"text": "出错/超时",
+                         "info": text,
+                         "file_path": file_path
+                         }
+                self.show_image_info(_data)
+
+                return
+
+            if pixian_status == -1:
+                text = "服务端抠图出错"
+                self.send_info(text=text, is_success=False)
+                _data = {"text": "出错/超时",
+                         "info": text,
+                         "file_path": file_path
+                         }
+                self.show_image_info(_data)
+                return
+
+            if pixian_status == 2:
+                result_image_url = data[0]["result_image_urls"][0]
+                result = True
+                # print(result_image_url)
+                try:
+                    second_cut_image = self.get_online_data.download_picture(url=result_image_url, out_path=None)
+                except BaseException as e:
+                    print(e)
+                    text = "{} 图片数据流获取错误".format(image_data["file_name"])
+                    print(text)
+                    logger.error("{};{}".format(text, e))
+                    self.send_info(text=text, is_success=False)
+
+                    _data = {"text": "出错/超时",
+                             "info": text,
+                             "file_path": file_path
+                             }
+                    self.show_image_info(_data)
+
+                    return
+                break
+
+        if result:
+            # 拼接处理
+            # print("耗时1:", time.time() - s)
+            try:
+                out_path = "{}/{}.png".format(out_root_path, image_data["file_name"])
+                if image_deal_info["二次抠图是否缩放"]:
+                    print("图片尺寸还原")
+                    second_cut_image = second_cut_image.resize(image_deal_info["抠图扩边后图片大小"])
+                # 创建空白图片并粘贴回去
+                _img_im = Image.new(mode="RGBA", size=image_deal_info["原始图片大小"], color=(0, 0, 0, 0))
+                _img_im.paste(second_cut_image, box=(image_deal_info["抠图扩边后位置"][0], image_deal_info["抠图扩边后位置"][1]))
+                _img_im.save(out_path)
+            except BaseException as e:
+                print(e)
+                text = "{} 图片处理错误,代码44".format(image_data["file_name"])
+                print(text)
+                logger.error("{};{}".format(text, e))
+                self.send_info(text=text, is_success=False)
+
+                _data = {"text": "出错/超时",
+                         "info": text,
+                         "file_path": file_path
+                         }
+                self.show_image_info(_data)
+                return
+
+            with self.lock:
+                print("耗时2:", time.time() - s)
+
+            self.add_log("第{}个 抠图已完成,id:{},耗时:{}".format(self.is_deal_num, generate_ids, time.time() - s))
+            self.send_info(text="{} 抠图已完成".format(image_data["file_name"]), is_success=True)
+
+            _data = {"text": "已完成",
+                     "info": "",
+                     "file_path": file_path
+                     }
+            self.show_image_info(_data)
+        else:
+            self.send_info(text="{} 处理失败,请联系管理员".format(image_data["file_name"]), is_success=False)
+            _data = {"text": "出错/超时",
+                     "info": "处理失败,请联系管理员",
+                     "file_path": file_path
+                     }
+            self.show_image_info(_data)
+
+    def get_keys(self):
+        # 执行顺序
+        # 获取key、获取im对象、调用抠图、返回抠图结果
+        n = 3
+        while 1:
+            if self.state != 1:
+                return None
+            key = self.get_online_data.get_keys()
+            n -= 1
+            if n <= 0:
+                return None
+            if not key:
+                time.sleep(10)
+                continue
+            else:
+                return key
+
+    def run_with_thread(self, image_data):
+        # 直接调用抠图
+        # todo 1、增加获取key,2、key需要加密、3、429报错 重试再来拿一个KEY
+
+        with self.lock:
+            self.is_deal_num += 1
+            is_deal_num = copy.copy(self.is_deal_num)
+
+        file_path = image_data["file_path"]
+        self.add_log("开始处理第{}个,图片地址:{}".format(is_deal_num, file_path))
+
+        _data = {"text": "处理中",
+                 "info": "",
+                 "file_path": file_path
+                 }
+        self.show_image_info(_data)
+
+        if self.windows.remaining_times <= 0:
+            self.send_info(text="次数不足,处理失败", is_success=False)
+            return
+
+        # 检查图片上传是否有结束
+        n = 60
+        while 1:
+            if self.state != 1:
+                self.send_info(text="{} 用户主动终止".format(image_data["file_name"]), is_success=False)
+                return
+            n -= 1
+            # print(n)
+            if file_path in self.upload_pic_dict:
+                break
+
+            else:
+                time.sleep(1)
+                if n <= 0:
+                    text = "{} 处理超时".format(image_data["file_name"])
+                    self.send_info(text=text, is_success=False)
+                    logger.warning(text)
+                    _data = {"text": "出错/超时",
+                             "info": "处理超时",
+                             "file_path": file_path
+                             }
+                    self.show_image_info(_data)
+                    return
+                continue
+
+        s = time.time()
+        # print(self.upload_pic_dict[file_path])
+        _flag = self.upload_pic_dict[file_path]["flag"]
+
+        if not _flag:
+            self.add_log("第{}个 未查到上传的图片地址".format(self.is_deal_num))
+            _data = {"text": "出错/超时",
+                     "info": "上传错误",
+                     "file_path": file_path
+                     }
+            self.show_image_info(_data)
+            text = "{} 上传错误".format(image_data["file_name"])
+            self.send_info(text=text, is_success=False)
+            return
+
+        # image_url = self.upload_pic_dict[file_path]["url"]
+        image_deal_info = self.upload_pic_dict[file_path]["image_deal_info"]
+        _im = self.upload_pic_dict[file_path]["_im"]
+
+        _data = {"text": "开始抠图",
+                 "info": "",
+                 "file_path": file_path
+                 }
+        self.show_image_info(_data)
+
+        self.add_log("第{}个 开始抠图".format(self.is_deal_num))
+
+        with self.lock:
+            self.is_upload_pic_num -= 1
+
+        # todo 抠图
+        out_root_path = "{}/已扣图".format(image_data["root_path"])
+        self.check_path(out_root_path)
+
+        # 直接调用pixian
+        # second_cut_image,_ = self.r_pixian.run_by_image_url(image_url)
+        # todo 获取key
+        n = 2
+        while 1:
+            key = self.get_keys()
+            if not key:
+                _data = {"text": "出错/超时",
+                         "info": "多次获取key失败",
+                         "file_path": file_path
+                         }
+                self.show_image_info(_data)
+                self.send_info(text="{} 处理失败,请联系管理员".format(image_data["file_name"]), is_success=False)
+                return
+            n -= 1
+            second_cut_image, _ = self.r_pixian.run_by_image_im(_im, key)
+            if second_cut_image is None:
+                # todo 判断code
+                if n <= 0:
+                    _data = {"text": "出错/超时",
+                             "info": "多次抠图失败:{}".format(_),
+                             "file_path": file_path
+                             }
+                    self.show_image_info(_data)
+                    self.send_info(text="{} 处理失败,请联系管理员".format(image_data["file_name"]), is_success=False)
+                    return
+                time.sleep(6)
+                continue
+            else:
+                break
+
+        # 拼接处理
+        # print("耗时1:", time.time() - s)
+        try:
+            out_path = "{}/{}.png".format(out_root_path, image_data["file_name"])
+            if image_deal_info["二次抠图是否缩放"]:
+                print("图片尺寸还原")
+                second_cut_image = second_cut_image.resize(image_deal_info["抠图扩边后图片大小"])
+            # 创建空白图片并粘贴回去
+            _img_im = Image.new(mode="RGBA", size=image_deal_info["原始图片大小"], color=(0, 0, 0, 0))
+            _img_im.paste(second_cut_image, box=(image_deal_info["抠图扩边后位置"][0], image_deal_info["抠图扩边后位置"][1]))
+            _img_im.save(out_path)
+        except BaseException as e:
+            print(e)
+            text = "{} 图片处理错误,代码44".format(image_data["file_name"])
+            print(text)
+            logger.error("{};{}".format(text, e))
+            self.send_info(text=text, is_success=False)
+
+            _data = {"text": "出错/超时",
+                     "info": text,
+                     "file_path": file_path
+                     }
+            self.show_image_info(_data)
+            return
+
+        with self.lock:
+            print("耗时2:", time.time() - s)
+
+        self.send_info(text="{} 抠图已完成".format(image_data["file_name"]), is_success=True)
+        _data = {"text": "已完成",
+                 "info": "",
+                 "file_path": file_path
+                 }
+        self.show_image_info(_data)
+
+    def upload_pics(self, image_data):
+        # todo 1、增加阿里调用报错的重试机制
+
+        while 1:
+            if self.state != 1:
+                return
+            # print("self.is_upload_pic_num:", self.is_upload_pic_num)
+            with self.lock:
+                if self.is_upload_pic_num >= 4:
+                    f = False
+                else:
+                    self.is_upload_pic_num += 1
+                    f = True
+            if f:
+                break
+            else:
+                time.sleep(1)
+                continue
+
+        file_path = image_data["file_path"]
+        image_deal_info = {}
+        try:
+            _data = {"text": "开始上传",
+                     "info": "",
+                     "file_path": file_path
+                     }
+            self.show_image_info(_data)
+            cut_image, image_deal_info = self.get_image_cut(file_path)
+            # buffer = io.BytesIO()
+            # cut_image.save(buffer, format='JPEG')
+            # buffer.seek(0)
+            # url = self.get_online_data.upload_pic(file_path=None, buffer=buffer)
+            f = True
+            url = ""
+            _data = {"text": "上传成功",
+                     "info": "",
+                     "file_path": file_path
+                     }
+            self.show_image_info(_data)
+
+        except BaseException as e:
+            print(e)
+            _data = {"text": "上传出错",
+                     "info": "{}".format(e),
+                     "file_path": file_path
+                     }
+
+            self.show_image_info(_data)
+            text = "{} 图片上传".format(image_data["file_name"])
+            logger.error("{};{}".format(text, e))
+            self.send_info(text=text, is_success=None)
+            f = False
+            url = ""
+            cut_image = ""
+
+        with self.lock:
+            # print(file_path, "图片已上传")
+            self.upload_pic_dict[file_path] = {"url": url,
+                                               "image_deal_info": image_deal_info,
+                                               "flag": f,
+                                               "_im": cut_image, }
+
+    def upload_pics2222(self, image_data):
+        while 1:
+            if self.state != 1:
+                return
+            # print("self.is_upload_pic_num:", self.is_upload_pic_num)
+            with self.lock:
+                if self.is_upload_pic_num >= 4:
+                    f = False
+                else:
+                    self.is_upload_pic_num += 1
+                    f = True
+            if f:
+                break
+            else:
+                time.sleep(1)
+                continue
+
+        file_path = image_data["file_path"]
+        image_deal_info = {}
+        try:
+            _data = {"text": "开始上传",
+                     "info": "",
+                     "file_path": file_path
+                     }
+            self.show_image_info(_data)
+            cut_image, image_deal_info = self.get_image_cut(file_path)
+            buffer = io.BytesIO()
+            cut_image.save(buffer, format='JPEG')
+            buffer.seek(0)
+            url = self.get_online_data.upload_pic(file_path=None, buffer=buffer)
+            f = True
+            # url = ""
+            _data = {"text": "上传成功",
+                     "info": "",
+                     "file_path": file_path
+                     }
+            self.show_image_info(_data)
+
+        except BaseException as e:
+            print(e)
+            _data = {"text": "上传出错",
+                     "info": "{}".format(e),
+                     "file_path": file_path
+                     }
+
+            self.show_image_info(_data)
+            text = "{} 图片上传".format(image_data["file_name"])
+            logger.error("{};{}".format(text, e))
+            self.send_info(text=text, is_success=None)
+            f = False
+            url = ""
+            cut_image = ""
+
+        with self.lock:
+            # print(file_path, "图片已上传")
+            self.upload_pic_dict[file_path] = {"url": url,
+                                               "image_deal_info": image_deal_info,
+                                               "flag": f,
+                                               "_im": cut_image, }
+
+    def get_image_cut(self, file_path):
+        original_pic = Picture(file_path)
+        original_pic.im = original_pic.im.convert("RGB")
+        image_deal_info = {}
+        image_deal_info["原始图片大小"] = (original_pic.x, original_pic.y)
+        if original_pic.x * original_pic.y < 1000000:
+            cut_image = original_pic.im
+            image_deal_info["抠图扩边后图片大小"] = cut_image.size
+            image_deal_info["二次抠图是否缩放"] = False
+            image_deal_info["抠图扩边后位置"] = (0, 0, original_pic.x, original_pic.y)
+        else:
+            # print("alilkoutu1")
+            cut_image = self.r_ali.get_image_cut(file_path=None, out_file_path=None, original_im=original_pic.im)
+            # print("alilkoutu2")
+            x1, y1, x2, y2 = cut_image.getbbox()
+            image_deal_info["鞋子原始位置"] = (x1, y1, x2, y2)
+            o_w, o_h = cut_image.size
+            image_deal_info["鞋子原始抠图后大小"] = (o_w, o_h)
+            # 扩边处理
+            _w, _h = x2 - x1, y2 - y1
+            out_px = 0.06
+            _w, _h = int(out_px * _w), int(out_px * _h)
+            n_x1, n_y1, n_x2, n_y2 = x1 - _w, y1 - _h, x2 + _w, y2 + _h
+            if n_x1 < 0:
+                n_x1 = 0
+            if n_y1 < 0:
+                n_y1 = 0
+            if n_x2 > o_w:
+                n_x2 = o_w
+            if n_y2 > o_h:
+                n_y2 = o_h
+
+            image_deal_info["抠图扩边后位置"] = (n_x1, n_y1, n_x2, n_y2)
+            cut_image = original_pic.im.crop(image_deal_info["抠图扩边后位置"])
+            image_deal_info["抠图扩边后图片大小"] = cut_image.size
+            x, y = image_deal_info["抠图扩边后图片大小"]
+            max_size = 32000000
+            # max_size = 1000000
+            if x * y > max_size:
+                r = max_size / (x * y)
+                size = (int(x * r), int(y * r))
+                print(size)
+                cut_image = cut_image.resize(size=size)
+                image_deal_info["二次抠图是否缩放"] = True
+            else:
+                image_deal_info["二次抠图是否缩放"] = False
+
+        return cut_image, image_deal_info
+
+    def check_path(self, _path):
+        if not os.path.exists(_path):
+            os.mkdir(_path)
+        return True
+
+    def md5_of_image(self, image_path):
+        # 打开图片文件
+        with open(image_path, 'rb') as f:
+            # 读取文件内容
+            data = f.read()
+            # 计算MD5值
+            md5 = hashlib.md5(data).hexdigest()
+            return md5

+ 79 - 0
module/deal_cutout.py

@@ -0,0 +1,79 @@
+import time
+from concurrent.futures import as_completed, ThreadPoolExecutor, wait
+import threading
+from module.remove_bg_pixian import RemoveBgPiXian
+from PySide6.QtWidgets import *
+from PySide6.QtCore import *
+from module.other.module_online_data import GetOnlineData
+from module.deal_one_image import DealOneImage, DealOneImageBeforehand
+from module.other.log import MyLogger
+
+
+class DealCutout(QThread):
+    signal_data = Signal(dict)
+
+    def __init__(self, windows):
+        super().__init__()
+        self.windows = windows
+        self.lock = threading.Lock()
+        self.need_cutout_images = {}
+        self.state = 2  # 1进行中 2停止
+        self.get_online_data = GetOnlineData()
+        self.is_upload_pic_num = 0
+        self.is_deal_num = 0
+        # 图片列表
+        self.upload_pic_dict = {}
+        self.logger = MyLogger().logger
+
+    def run(self):
+        # self.total_num = len([x for x in self.need_cutout_images if x["need_cutout"]])  # 总条数
+        # self.pending_processing = int(self.total_num)  # 待处理
+        # self.processing_failed = 0  # 处理失败
+        # self.processing_successfully = 0  # 处理成功
+        # self.processing_error = 0  # 处理异常
+        self.get_online_data.refresh_headers()
+
+        executor = ThreadPoolExecutor(max_workers=4)
+        executor_pic_upload = ThreadPoolExecutor(max_workers=2)
+
+        tasks_1 = []
+        tasks_2 = []
+        self.state = 1
+        self.is_upload_pic_num = 0
+        self.is_deal_num = 0
+        num = 0
+        for image_data in self.need_cutout_images:
+            if not image_data["need_cutout"]:
+                continue
+            num += 1
+            task_1 = executor.submit(DealOneImage(image_data=image_data, lock=self.lock, windows=self, num=num).run)
+            tasks_1.append(task_1)
+
+            task_2 = executor_pic_upload.submit(
+                DealOneImageBeforehand(image_data=image_data, lock=self.lock, windows=self, num=num).run)
+            tasks_2.append(task_2)
+        self.check_thread(tasks_1, tasks_2)
+
+    def check_thread(self, *tasks_list):
+        time.sleep(2)
+        while 1:
+            f = True
+            for tasks in tasks_list:
+                done, not_done = wait(tasks)
+                if not_done:
+                    time.sleep(2)
+                    f = False
+                    continue
+
+                for task in done:
+                    try:
+                        result = task.result()
+                        # print(result)
+                    except BaseException as e:
+                        self.logger.info("有线程出错:{}".format(e))
+
+            if f:
+                break
+
+        self.signal_data.emit({"_type": "complete",
+                               "data": ""})

+ 497 - 0
module/deal_one_image.py

@@ -0,0 +1,497 @@
+import copy
+import os.path
+from module.other.module_online_data import GetOnlineData
+import time
+from module.other.log import MyLogger
+import os
+from module.remove_bg_pixian import RemoveBgPiXian
+from PIL import Image
+from module.other.pic import Picture
+from module.other.remove_bg_ali import RemoveBgALi
+import cv2
+import numpy as np
+
+
+class Base(object):
+    def __init__(self, image_data, lock, windows, num):
+        self.lock = lock
+        self.windows = windows
+        self.image_data = image_data
+        self.num = num
+        self.get_online_data = GetOnlineData()
+        self.file_path = image_data["file_path"]
+        self.file_name = image_data["file_name"]
+        self.file = os.path.split(self.file_path)[1]
+        self.is_once_data = {}
+        self.logger = MyLogger().logger
+
+    def add_log(self, text, _type="info"):
+        self.logger.info("第{}个,图片名称:{},内容:{}".format(self.num, self.file, text))
+
+    def show_image_info(self, data):
+        data["file_path"] = self.file_path
+        with self.lock:
+            data = {"_type": "show_image_item_info",
+                    "data": data,
+                    }
+            self.windows.signal_data.emit(data)
+
+    def send_info(self, text="", is_success=None, _type="show_text_browser", need_point_return=False):
+        with self.lock:
+            if is_success is not None:
+                if is_success:
+                    processing_failed = 0
+                    processing_successfully = 1
+                else:
+                    processing_failed = 1
+                    processing_successfully = 0
+                    # 分数返回
+                    if need_point_return:
+                        # 分数返回
+                        if self.is_once("add_point"):
+                            print("第{}个,图片名称:{},内容:{}".format(self.num, self.file, "扣分返回"))
+                            self.dispose_point(_type="add")
+                            self.refresh_times(cumulative_frequency_times_change=-1)
+                        pass
+
+                self.windows.signal_data.emit({"_type": "schedule",
+                                               "data": {"processing_failed": processing_failed,
+                                                        "processing_successfully": processing_successfully,
+                                                        }})
+
+            if text:
+                data = {"_type": "show_text_browser",
+                        "data": text,
+                        }
+                self.windows.signal_data.emit(data)
+
+    def check_path(self, _path):
+        if not os.path.exists(_path):
+            os.mkdir(_path)
+        return True
+
+    def is_once(self, key):
+        if key not in self.is_once_data:
+            self.is_once_data[key] = 0
+            return True
+        return False
+
+    def refresh_times(self, cumulative_frequency_times_change=0):
+        data = {"_type": "refresh_times",
+                "data": {"cumulative_frequency_times_change": cumulative_frequency_times_change
+                         },
+                }
+        self.windows.signal_data.emit(data)
+        pass
+
+    def dispose_point(self, _type):
+        n = 3
+        while n:
+            n -= 1
+            try:
+                _r = self.get_online_data.dispose_point(_type)
+                balance = _r["data"]["balance"]
+                return True
+            except:
+                time.sleep(0.5)
+                continue
+
+        return False
+
+
+class DealOneImage(Base):
+    def __init__(self, image_data, lock, windows, num):
+        super().__init__(image_data, lock, windows, num)
+        self.image_data = image_data
+        self.lock = lock
+        self.windows = windows
+        self.num = num
+        self.file_path = image_data["file_path"]
+        self.file = os.path.split(self.file_path)[1]
+        self.root_path = image_data["root_path"]
+        self.r_pixian = RemoveBgPiXian()
+        self.file_name = image_data["file_name"]
+
+    def run(self):
+        # 直接调用抠图
+        # 1、增加获取key,2、key需要加密、3、429报错 重试再来拿一个KEY
+        self.add_log("开始处理")
+        self.show_image_info({"text": "处理中", "info": "", })
+
+        if self.windows.windows.remaining_times <= 0:
+            self.send_info(text="次数不足,处理失败", is_success=False)
+            return
+
+        # 检查图片上传是否有结束
+        n = 60
+        while 1:
+            if self.windows.state != 1:
+                self.show_image_info({"text": "已取消", "info": "", })
+                self.send_info(text="用户主动终止", is_success=False)
+                return
+            n -= 1
+            # print(n)
+            if self.file_path in self.windows.upload_pic_dict:
+                break
+
+            else:
+                time.sleep(1)
+                if n <= 0:
+                    text = "处理超时"
+                    self.send_info(text=text, is_success=False)
+
+                    _data = {"text": "出错/超时",
+                             "info": "处理超时",
+                             }
+                    self.show_image_info(_data)
+                    return
+                continue
+
+        s = time.time()
+        # print(self.upload_pic_dict[file_path])
+        _flag = self.windows.upload_pic_dict[self.file_path]["flag"]
+        if not _flag:
+            self.add_log("未查到上传的图片地址")
+            _data = {"text": "出错/超时",
+                     "info": "上传错误",
+                     }
+            self.show_image_info(_data)
+            self.send_info(text="上传错误", is_success=False)
+            return
+
+        image_deal_info = self.windows.upload_pic_dict[self.file_path]["image_deal_info"]
+        original_im = self.windows.upload_pic_dict[self.file_path]["_im"]
+
+        self.show_image_info({"text": "开始抠图", "info": "", })
+        self.add_log("抠图中")
+
+        with self.lock:
+            self.windows.is_upload_pic_num -= 1
+
+        # 抠图
+        out_root_path = "{}/已扣图".format(self.root_path)
+        self.check_path(out_root_path)
+
+        # 直接调用pixian
+        # second_cut_image,_ = self.r_pixian.run_by_image_url(image_url)
+
+        try:
+            balance = self.get_online_data.get_cutout_image_times()["balance"]
+            self.add_log("查询balance:{}成功".format(balance))
+            if balance <= 0:
+                self.add_log("次数不足,处理失败")
+                self.send_info(text="次数不足,处理失败", is_success=False)
+                return
+        except:
+            self.add_log("查询balance失败")
+            self.send_info(text="查询balance失败", is_success=False)
+            return
+
+        n = 0
+        while 1:
+            # 获取key
+            if self.windows.state != 1:
+                self.show_image_info({"text": "已取消", "info": "", })
+                self.send_info(text="用户主动终止", is_success=False)
+                return
+            n += 1
+            data = self.get_online_data.get_key_secret()
+            key = (data["api_info"]["api_key"], data["api_info"]["api_serect"])
+            self.add_log("查询key成功")
+
+            if not key:
+                _data = {"text": "出错/超时",
+                         "info": "多次获取key失败",
+                         }
+                self.add_log(text="多次获取key失败")
+                self.show_image_info(_data)
+                self.send_info(text="处理失败,请联系管理员", is_success=False)
+                return
+
+            if self.is_once("sub_point"):
+                # 调用扣分
+                with self.lock:
+                    self.refresh_times(cumulative_frequency_times_change=1)
+                    f = self.dispose_point(_type="sub")
+                if not f:
+                    self.add_log(text="多次获取调用余额扣减失败")
+                    self.send_info(text="多次获取调用余额扣减失败", is_success=False)
+                    _data = {"text": "出错/超时",
+                             "info": "多次获取调用余额扣减失败",
+                             }
+                    self.show_image_info(_data)
+                    return
+
+            pixian_cutout_data = self.r_pixian.run_by_image_im(original_im, key)
+            # pixian_cutout_data = {"status_code":200}
+
+            if pixian_cutout_data["status_code"] == 200:
+                second_cut_image = pixian_cutout_data["im"]
+                # second_cut_image.save("xx.png")
+                # second_cut_image = Image.open("xx.png")
+                self.add_log(text="调用抠图完成")
+                break
+
+            elif pixian_cutout_data["status_code"] == 402:
+                if n >= 2:
+                    _data = {"text": "出错/超时",
+                             "info": "多次抠图失败:{}".format(pixian_cutout_data["status_code"]),
+                             }
+                    self.add_log(text="多次抠图失败:{}".format(pixian_cutout_data["status_code"]))
+                    self.show_image_info(_data)
+                    self.send_info(text="处理失败,请联系管理员", is_success=False, need_point_return=True)
+                    if self.is_once("余额不足报错"):
+                        # todo 余额不足报错,钉钉消息通知
+                        self.get_online_data.send_message("Pixian:{} 余额不足".format(key))
+                        pass
+                    return
+                self.add_log(text="抠图失败:{},延迟6秒".format(pixian_cutout_data["status_code"]))
+                time.sleep(6)
+                continue
+
+            elif pixian_cutout_data["status_code"] == 429:
+                if n >= 2:
+                    _data = {"text": "出错/超时",
+                             "info": "多次抠图失败:{}".format(pixian_cutout_data["status_code"]),
+                             }
+
+                    self.show_image_info(_data)
+                    self.add_log(text="多次抠图失败:{}".format(pixian_cutout_data["status_code"]))
+                    self.send_info(text="处理失败,请联系管理员", is_success=False, need_point_return=True)
+                    return
+
+                self.add_log(text="抠图失败:{},延迟10秒".format(pixian_cutout_data["status_code"]))
+                time.sleep(10)
+                continue
+            else:
+                _data = {"text": "出错/超时", "info": "抠图异常", }
+                self.show_image_info(_data)
+                self.send_info(text="处理失败,请联系管理员", is_success=False, need_point_return=True)
+                if "message" in pixian_cutout_data:
+                    text = "抠图异常,code:{},message:{}".format(pixian_cutout_data["status_code"],
+                                                            pixian_cutout_data["message"])
+                else:
+                    text = "抠图异常,code:{}".format(pixian_cutout_data["status_code"])
+                self.add_log(text)
+                return
+
+        # 拼接处理
+        # print("耗时1:", time.time() - s)
+
+        try:
+            out_path = "{}/{}.png".format(out_root_path, self.file_name)
+            if image_deal_info["二次抠图是否缩放"]:
+                # print("图片尺寸还原")
+                self.add_log(text="图片尺寸进行还原")
+                original_im = image_deal_info["抠图扩边后PIL对象"]
+                second_cut_image = self.picture_resize_to_original(second_cut_image, original_im)
+                # second_cut_image = second_cut_image.resize(image_deal_info["抠图扩边后图片大小"])
+            # 创建空白图片并粘贴回去
+            _img_im = Image.new(mode="RGBA", size=image_deal_info["原始图片大小"], color=(0, 0, 0, 0))
+            _img_im.paste(second_cut_image, box=(image_deal_info["抠图扩边后位置"][0], image_deal_info["抠图扩边后位置"][1]))
+            _img_im.save(out_path)
+
+        except BaseException as e:
+            # print(e)
+            text = "{} 图片处理错误,代码44".format(e)
+            self.add_log(text)
+            self.send_info(text=text, is_success=False, need_point_return=True)
+            _data = {"text": "出错/超时",
+                     "info": text,
+                     }
+            self.show_image_info(_data)
+            return
+
+        self.add_log(text="本张耗时:{}".format(time.time() - s))
+        self.send_info(text="抠图已完成", is_success=True)
+        self.show_image_info({"text": "已完成", "info": "", })
+
+    def picture_resize_to_original(self, _img, original_im):
+        """
+
+        Parameters
+        ----------
+        _img 需要还原的PIL对象
+        original_im 原图对象
+
+        Returns
+        -------
+
+        """
+
+        # 将抠图结果转成mask
+        # 将抠图结果放大到原始图大小
+        _img = _img.resize(original_im.size)
+        new_big_mask = Image.new('RGB', _img.size, (0, 0, 0))
+        white = Image.new('RGB', _img.size, (255, 255, 255))
+        new_big_mask.paste(white, mask=_img.split()[3])
+
+        # ---------制作选区缩小的mask
+        mask = cv2.cvtColor(np.asarray(new_big_mask), cv2.COLOR_BGR2GRAY)  # 将PIL 格式转换为 CV对象
+        mask[mask != 255] = 0
+        # 黑白反转
+        # mask = 255 - mask
+        # 选区缩小10
+        kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (10, 10))
+        erode_im = cv2.morphologyEx(mask, cv2.MORPH_ERODE, kernel)
+
+        # -------再进行抠图处理
+        mask = Image.fromarray(cv2.cvtColor(erode_im, cv2.COLOR_GRAY2RGBA))  # CV 对象转 PIL
+        transparent_im = Image.new('RGBA', original_im.size, (0, 0, 0, 0))
+        transparent_im.paste(original_im, (0, 0), mask.convert('L'))
+        # 上述抠图结果进行拼接
+        _img.paste(transparent_im, (0, 0), transparent_im)
+
+        return _img
+
+
+class DealOneImageBeforehand(Base):
+    def __init__(self, image_data, lock, windows, num):
+        super().__init__(image_data, lock, windows, num)
+        self.image_data = image_data
+        self.lock = lock
+        self.windows = windows
+        self.get_online_data = GetOnlineData()
+        self.num = num
+        self.file_path = image_data["file_path"]
+        self.file = os.path.split(self.file_path)[1]
+        self.root_path = image_data["root_path"]
+        self.r_ali = RemoveBgALi()
+        self.file_name = image_data["file_name"]
+
+    def run(self):
+        # 增加阿里调用报错的重试机制
+        # a = 1/0
+        # raise "11111111111111111"
+        while 1:
+            if self.windows.state != 1:
+                self.show_image_info({"text": "已取消", "info": "", })
+                return
+            with self.lock:
+                if self.windows.is_upload_pic_num >= 4:
+                    f = False
+                else:
+                    self.windows.is_upload_pic_num += 1
+                    f = True
+            if f:
+                break
+            else:
+                time.sleep(1)
+                continue
+        image_deal_info = {}
+        try:
+            _data = {"text": "开始上传",
+                     "info": "",
+                     }
+            self.show_image_info(_data)
+            cut_image, image_deal_info = self.get_image_cut()
+
+
+            f = True
+            url = ""
+            self.show_image_info({"text": "上传成功", "info": "", })
+        except BaseException as e:
+            # print(e)
+            self.show_image_info({"text": "上传出错", "info": "{}".format(e), })
+            f = False
+            url = ""
+            cut_image = ""
+
+        # cut_image.save("1.jpg",format="JPEG")
+        # raise 1
+
+        with self.lock:
+            self.windows.upload_pic_dict[self.file_path] = {"url": url,
+                                                            "image_deal_info": image_deal_info,
+                                                            "flag": f,
+                                                            "_im": cut_image, }
+
+    def get_image_cut(self):
+        original_pic = Picture(self.file_path)
+        original_pic.im = self.get_image_orientation(original_pic.im)
+        original_pic.x, original_pic.y = original_pic.im.size
+
+        original_pic.im = original_pic.im.convert("RGB")
+        image_deal_info = {}
+        image_deal_info["原始图片大小"] = (original_pic.x, original_pic.y)
+        if original_pic.x * original_pic.y < 1000000:
+            cut_image = original_pic.im
+            image_deal_info["抠图扩边后图片大小"] = cut_image.size
+            image_deal_info["二次抠图是否缩放"] = False
+            image_deal_info["抠图扩边后位置"] = (0, 0, original_pic.x, original_pic.y)
+        else:
+            self.add_log("开始预抠图处理")
+            cut_image = self.r_ali.get_image_cut(file_path=None, out_file_path=None, original_im=original_pic.im)
+            # cut_image.save("XX1.png")
+
+            self.add_log("预抠图处理结束")
+
+            x1, y1, x2, y2 = cut_image.getbbox()
+            image_deal_info["鞋子原始位置"] = (x1, y1, x2, y2)
+            o_w, o_h = cut_image.size
+            image_deal_info["鞋子原始抠图后大小"] = (o_w, o_h)
+            # 扩边处理
+            _w, _h = x2 - x1, y2 - y1
+            out_px = 0.025
+            _w, _h = int(out_px * _w), int(out_px * _h)
+            n_x1, n_y1, n_x2, n_y2 = x1 - _w, y1 - _h, x2 + _w, y2 + _h
+            if n_x1 < 0:
+                n_x1 = 0
+            if n_y1 < 0:
+                n_y1 = 0
+            if n_x2 > o_w:
+                n_x2 = o_w
+            if n_y2 > o_h:
+                n_y2 = o_h
+            image_deal_info["抠图扩边后位置"] = (n_x1, n_y1, n_x2, n_y2)
+            cut_image = original_pic.im.crop(image_deal_info["抠图扩边后位置"])
+
+            image_deal_info["抠图扩边后图片大小"] = cut_image.size
+            x, y = image_deal_info["抠图扩边后图片大小"]
+            # max_size = 32000000
+            max_size = 12000000
+            if x * y > max_size:
+                r = max_size / (x * y)
+                size = (int(x * r), int(y * r))
+                self.add_log(text="图片进行压缩,压缩前:{},压缩后:{}".format(image_deal_info["抠图扩边后图片大小"], size))
+                image_deal_info["抠图扩边后PIL对象"] = copy.deepcopy(cut_image)
+                cut_image = cut_image.resize(size=size)
+                # print(cut_image.size)
+                # print(image_deal_info["抠图扩边后PIL对象"].size)
+                image_deal_info["二次抠图是否缩放"] = True
+            else:
+                image_deal_info["二次抠图是否缩放"] = False
+        return cut_image, image_deal_info
+
+    def get_image_orientation(self, img):
+        # 获取EXIF数据
+        exif = img._getexif()
+        if exif is not None:
+            # EXIF标签274对应的是Orientation
+            orientation = exif.get(0x0112)
+            if orientation == 2:
+                # 水平翻转
+                img = img.transpose(Image.FLIP_LEFT_RIGHT)
+            elif orientation == 3:
+                # 旋转180度
+                img = img.rotate(180, expand=True)
+            elif orientation == 4:
+                # 垂直翻转
+                img = img.transpose(Image.FLIP_TOP_BOTTOM)
+            elif orientation == 5:
+                # 水平翻转后顺时针旋转90度
+                img = img.transpose(Image.FLIP_LEFT_RIGHT).transpose(Image.ROTATE_270)
+            elif orientation == 6:
+                # 顺时针旋转90度
+                img = img.transpose(Image.ROTATE_270)
+            elif orientation == 7:
+                # 水平翻转后逆时针旋转90度
+                img = img.transpose(Image.FLIP_LEFT_RIGHT).transpose(Image.ROTATE_90)
+            elif orientation == 8:
+                # 逆时针旋转90度
+                img = img.transpose(Image.ROTATE_90)
+        else:
+            print("没有EXIF数据或没有方向信息")
+            orientation = 1
+
+        return img

+ 256 - 0
module/module_login.py

@@ -0,0 +1,256 @@
+import time
+from UI.login import Ui_Form
+from PySide6.QtWidgets import *
+import json
+import requests
+import settings
+from PySide6.QtCore import *
+import threading
+from module.other.rsa import RSAService
+
+
+class LoginWindow(QWidget, Ui_Form):
+    get_verification_code_last_time = 0
+
+    def __init__(self, windows=None, call_back=None, par=None):
+        super().__init__()
+        self.windows = windows
+        self.call_back = call_back
+        self.par = par
+        self.setupUi(self)
+        self.setFixedSize(self.width(), self.height())
+        self.setWindowTitle("惠利玛系统登录")
+        self.init()
+        self.setWindowModality(Qt.ApplicationModal)
+        self.show()
+
+    def init(self):
+        self.scrollArea = None
+        self.group = QButtonGroup(self)
+        self.group.setObjectName("radioButtonGroup")
+
+        self.group.addButton(self.radioButton)
+        self.group.addButton(self.radioButton_2)
+        # 设置为单选
+        self.group.setExclusive(True)
+
+        self.radioButton.toggled.connect(self.radioButton_clicked)
+        self.radioButton_2.toggled.connect(self.radioButton_clicked)
+        self.lineEdit.setText(settings.Account)
+        self.pushButton.clicked.connect(self.login)
+        self.pushButton_2.clicked.connect(self.get_verification_code)
+        self.change_mode("短信验证码登录")
+
+    def radioButton_clicked(self, *args):
+        if self.radioButton.isChecked():
+            self.change_mode("短信验证码登录")
+        else:
+            self.change_mode("账号密码登录")
+
+    def change_mode(self, mode_name):
+        self.radioButton.setChecked(False)
+        self.radioButton_2.setChecked(False)
+        self.pushButton_2.hide()
+        self.lineEdit_2.setText("")
+
+        if mode_name == "短信验证码登录":
+            self.pushButton_2.setText("获取验证码")
+            self.radioButton.setChecked(True)
+            self.pushButton_2.show()
+            self.label_3.setText("验证码:")
+            self.lineEdit_2.setEchoMode(QLineEdit.Normal)
+            self.lineEdit_2.resize(161, 41)
+
+        if mode_name == "账号密码登录":
+            self.lineEdit_2.resize(271, 41)
+            self.radioButton_2.setChecked(True)
+            self.label_3.setText("密码:")
+            self.lineEdit_2.setEchoMode(QLineEdit.Password)
+
+    def show_companies(self, company_list):
+        self.scrollArea = QScrollArea(parent=self)
+        self.scrollArea.resize(self.size())
+        self.widget_2 = QWidget()
+        self.widget_2.setStyleSheet("background-color: rgb(245, 245, 245)")
+        self.widget_2.setMinimumSize(self.width(), self.height() * 3)
+        self.scrollArea.setWidget(self.widget_2)
+        self.setWindowModality(Qt.ApplicationModal)
+        self.scrollArea.show()
+
+        x, y = 0, 10
+        for company in company_list:
+            company_widget = SelectCompany(self.widget_2, data=company)
+            company_widget.signal_data.connect(self.select_company)
+            company_widget.move(int((self.width() - company_widget.width()) / 2), y)
+            y += 45
+
+    def get_verification_code(self):
+        self.pushButton_2.setEnabled(False)
+        if time.time() - LoginWindow.get_verification_code_last_time < 60:
+            self.pushButton_2.setEnabled(True)
+            return False, "60秒内只允许发送一次"
+        phone = self.lineEdit.text()
+        print("phone", phone)
+
+        if phone == "":
+            reply = QMessageBox.question(self, '确认', "请输入手机号", QMessageBox.Yes)
+            self.pushButton_2.setEnabled(True)
+            return False, "请输入手机号"
+
+        try:
+            phone = int(phone)
+            if len(str(phone)) != 11:
+                reply = QMessageBox.question(self, '确认', "手机号码长度错误", QMessageBox.Yes)
+                self.pushButton_2.setEnabled(True)
+                return False
+        except:
+            reply = QMessageBox.question(self, '确认', "手机号码格式错误", QMessageBox.Yes)
+            self.pushButton_2.setEnabled(True)
+            return False, "手机号码格式错误"
+        url = "{domain}/api/auth/send_code".format(
+            domain=settings.DOMAIN
+        )
+        post_data = {"phone": str(phone),
+                     "_params_": RSAService().encrypt_public(phone=str(phone)),
+                     }
+        _s = requests.post(url=url, headers=settings.Headers, data=json.dumps(post_data))
+        threading.Thread(target=self.show_countdown, args=()).start()
+        return True, "成功"
+
+    def show_countdown(self, *args):
+        n = 60
+        self.pushButton_2.setEnabled(False)
+        while n:
+            n -= 1
+            self.pushButton_2.setText("{}秒后重试".format(n))
+            time.sleep(1)
+
+        self.pushButton_2.setEnabled(True)
+        self.pushButton_2.setText("获取验证码")
+        pass
+
+    def select_company(self, data):
+        if self.scrollArea is not None:
+            self.scrollArea.hide()
+        company_id = data["id"]
+        url = "{domain}/api/backend/account/select_company".format(
+            domain=settings.DOMAIN
+        )
+        post_data = {
+            "id": company_id
+        }
+
+        _s = self.s.post(url=url, headers=settings.Headers, data=json.dumps(post_data))
+        response_data = _s.json()
+        print(response_data["message"])
+        self.label_4.setText(response_data["message"])
+        if response_data["code"] == 0:
+            authorization = "Bearer {}".format(self.token)
+            settings.Headers["Authorization"] = authorization
+            data_dict = {"account": self.lineEdit.text(), }
+            settings.set_config(data_dict)
+            settings.set_key(authorization)
+
+            self.close()
+            if self.call_back:
+                self.call_back()
+        else:
+            self.label_4.setText(response_data["message"])
+            return
+
+    def login(self):
+        login_mode = "短信验证码登录" if self.radioButton.isChecked() else "账号密码登录"
+
+        self.label_4.setText("")
+        if login_mode == "账号密码登录":
+            login_type = 0
+        else:
+            login_type = 1
+
+        url = "{domain}/api/auth/login".format(
+            domain=settings.DOMAIN
+        )
+        post_data = {
+            "device": "backend",
+            "platform": "image_cutout",
+            "password": self.lineEdit_2.text(),
+            "type": login_type,
+            "username": self.lineEdit.text(),
+        }
+        self.s = requests.session()
+        _s = self.s.post(url=url, headers=settings.Headers, data=json.dumps(post_data))
+        print(_s)
+        response_data = _s.json()
+        code = response_data["code"]
+        print(response_data)
+        self.label_4.setText(response_data["message"])
+        if code != 0:
+            return
+
+        self.token = response_data["data"]["token"]
+        authorization = "Bearer {}".format(self.token)
+        settings.Headers["Authorization"] = authorization
+
+        is_need_select_company = response_data["data"]["is_need_select_company"]
+        if is_need_select_company == 0:
+
+            data_dict = {"account": self.lineEdit.text(), }
+            settings.set_config(data_dict)
+            settings.set_key(authorization)
+
+            self.close()
+            if self.call_back:
+                self.call_back()
+            return
+
+        url = "{domain}/api/backend/account/get_account_company".format(
+            domain=settings.DOMAIN
+        )
+        _s = self.s.get(url=url, headers=settings.Headers)
+        response_data = _s.json()
+
+        print(response_data)
+        company_list = []
+
+        if len(response_data["data"]) == 1:
+            company_id = response_data["data"]["id"]
+            self.select_company({"id": company_id})
+        else:
+            for i in response_data["data"]:
+                company_list.append(i)
+
+            self.show_companies(company_list=company_list)
+
+
+class SelectCompany(QLabel):
+    signal_data = Signal(dict)
+    is_clicked = Signal()
+
+    def __init__(self, parent, data):
+        super().__init__(parent=parent)
+        self.parent = parent
+        self.data = data
+        self.resize(270, 40)
+        self.setStyleSheet("""
+        background-color: rgb(235, 241, 247));
+        color: #666666;
+        border-radius: 5px;
+        border: 0px groove gray;
+        """)
+        self.init()
+        self.show()
+
+    def init(self):
+        self.setText(self.data["name"])
+
+    def mousePressEvent(self, ev):
+        self.is_clicked.emit()
+        a = QMessageBox.question(self, '确认', '是否选择该企业身份登录?',
+                                 QMessageBox.Yes | QMessageBox.No)
+        if a == QMessageBox.No:
+            return
+        # self.setStyleSheet("""
+        # background-color: rgb(60, 63, 65);
+        # """)
+        self.setEnabled(False)
+        self.signal_data.emit({"id": self.data["id"]})

+ 171 - 0
module/module_move_files.py

@@ -0,0 +1,171 @@
+from UI.move_files import Ui_Form as move_files_Ui_Form
+from PySide6.QtWidgets import *
+from PySide6.QtCore import *
+import settings
+import os
+import threading
+import shutil
+import time
+
+"""
+图片移动
+"""
+
+
+class MoveFiles(QWidget, move_files_Ui_Form):
+    progress_sign = Signal(dict)
+    info_sign = Signal(str)
+    text_show = Signal(str)
+
+    def __init__(self, windows):
+        super().__init__()
+        self.windows = windows
+
+        # 加载默认配置
+        self.to_deal_image_dir = ""
+        self.setupUi(self)
+        # 0禁用  1进行中  2已结束
+        self.state = 2
+        self.init()
+        self.setFixedSize(self.width(), self.height())
+        self.setWindowModality(Qt.ApplicationModal)
+        self.show()
+
+    def init(self):
+        self.label_3.mousePressEvent = self.change_image_dir
+        self.textBrowser.setText(self.get_len_text(self.to_deal_image_dir, 50))
+
+        self.pushButton.clicked.connect(self.run)
+        # self.pushButton_2.clicked.connect(lambda: os.startfile(os.getcwd() + "/" + "out_put"))
+
+    def get_len_text(self, text, max_len: int):
+        if len(text) > max_len:
+            text = text[:int(max_len / 4)] + "..." + text[-1 * int(max_len * 3 / 4):]
+        return text
+
+    def change_image_dir(self, *args):
+        pic_dir = QFileDialog.getExistingDirectory(None, "选取图片文件夹", "")
+        if not pic_dir:
+            self.textBrowser.setText("")
+            self.to_deal_image_dir = ""
+            return
+        self.to_deal_image_dir = pic_dir
+        self.textBrowser.setText(pic_dir)
+
+    def check_path(self, _path):
+        if not os.path.exists(_path):
+            os.mkdir(_path)
+        return True
+
+    def set_state(self, state_value: int):
+        # 0禁用  1进行中  2已结束
+        if state_value not in [0, 1, 2]:
+            return
+        self.state = state_value
+        if self.state == 0:
+            self.pushButton.setEnabled(False)
+        if self.state == 1:
+            self.pushButton.setEnabled(False)
+        if self.state == 2:
+            self.pushButton.setEnabled(True)
+
+    def check_file_is_closed(self, file_path):
+        try:
+            s = int(time.time())
+            _name, extension = os.path.splitext(file_path)
+            _temp_file_name = "{_name}_{_time}{extension}".format(_name=_name,
+                                                                  _time=s,
+                                                                  extension=extension)
+            os.rename(file_path, _temp_file_name)
+            os.rename(_temp_file_name, file_path)
+            return True
+
+        except:
+
+            return False
+
+    def run(self):
+        self.total_num = 0
+        if not self.to_deal_image_dir:
+            QMessageBox.question(self, '确认', '请选择待处理图片文件夹', QMessageBox.Yes)
+            return
+        self.textEdit_2.setText("")
+        self.textEdit_3.setText("")
+        text = self.textEdit.toPlainText()
+        goods_art_list = []
+        for i in text.split("\n"):
+            i = i.replace(" ", "")
+            if i:
+                goods_art_list.append(i.upper())
+        if not goods_art_list:
+            QMessageBox.question(self, '确认', '请填写待转移图片', QMessageBox.Yes)
+            return
+
+        to_deal_pic = []
+        _Type = ['.png', '.PNG', '.jpg', '.JPG', '.jpge', '.JPGE', '.gif', '.GIF']
+        for pic in os.listdir(self.to_deal_image_dir):
+            pic_path = "{}/{}".format(self.to_deal_image_dir, pic)
+            if os.path.isfile(pic_path):
+                if os.path.splitext(pic)[1] in _Type:
+                    to_deal_pic.append(pic)
+
+        if not to_deal_pic:
+            QMessageBox.question(self, '确认', '该文件夹下没有任何图片', QMessageBox.Yes)
+            return
+
+        # 开始执行拼接处理
+        # self.r = RunExcel(self)
+        # self.r.start()
+        self.set_state(state_value=1)
+        self.t = threading.Thread(target=self.run_by_thread, args=())
+        self.t.start()
+
+    def run_by_thread(self):
+        out_path = "{}/已匹配".format(self.to_deal_image_dir)
+        self.check_path(out_path)
+        # 待处理图片
+        to_deal_pic = {}
+        _Type = ['.png', '.PNG', '.jpg', '.JPG', '.jpge', '.JPGE', '.gif', '.GIF']
+        for pic in os.listdir(self.to_deal_image_dir):
+            pic_path = "{}/{}".format(self.to_deal_image_dir, pic)
+            if os.path.isfile(pic_path):
+                if os.path.splitext(pic)[1] in _Type:
+                    to_deal_pic[os.path.splitext(pic)[0].upper()] = pic_path
+
+        text = self.textEdit.toPlainText()
+        goods_art_list = []
+        for i in text.split("\n"):
+            i = i.replace(" ", "")
+            if i:
+                goods_art_list.append(i.upper())
+
+        for goods_art_no in goods_art_list:
+            print("开始处理:{}".format(goods_art_no))
+            if goods_art_no in to_deal_pic:
+                print("开始移动:{}".format(to_deal_pic[goods_art_no]))
+                shutil.move(to_deal_pic[goods_art_no], out_path)
+                self.textEdit_2.append(goods_art_no)
+            else:
+                self.textEdit_3.append(goods_art_no)
+
+        self.set_state(state_value=2)
+        print("----------已完成----------")
+
+    def column_to_letter(self, column_index):
+        """
+        将列位置转换为对应的字母
+        """
+        letter = ''
+        while column_index > 0:
+            column_index -= 1
+            letter = chr(column_index % 26 + 65) + letter
+            column_index //= 26
+        return letter
+
+    def append_text_to_browser(self, text):
+        self.textBrowser_2.append(text)
+
+    def create_folder(self, path):
+        if not os.path.exists(path):
+            os.makedirs(path)
+            return False

+ 7 - 0
module/module_print.py

@@ -0,0 +1,7 @@
+import inspect
+
+
+def to_print(*args):
+    frame = inspect.currentframe()
+    func_name = frame.f_back.f_code.co_name
+    print("func:{}".format(func_name), args)

+ 278 - 0
module/module_rename_pic.py

@@ -0,0 +1,278 @@
+from UI.rename_pic import Ui_Form as rename_pic_Ui_Form
+from PySide6.QtWidgets import *
+from PySide6.QtCore import *
+# from collections import defaultdict
+import os
+import log
+from PIL import Image, ImageDraw, ImageFont
+import time
+import settings
+# from pyzbar.pyzbar import decode
+import shutil
+from cv2 import cvtColor, COLOR_RGB2BGR
+# cv2.cvtColor(np.asarray(im), cv2.COLOR_RGB2BGR)
+import numpy as np
+from cv2.wechat_qrcode import WeChatQRCode
+from module.module_online_data import GetOnlineData
+
+
+# pip install opencv-python -i https://pypi.douban.com/simple
+# pip install opencv-contrib-python -i https://pypi.douban.com/simple
+
+class Picture:
+    def __init__(self, in_path):
+        self.im = Image.open(in_path)
+        self.x, self.y = self.im.size
+        # print(self.x, self.y)
+
+    def save_img(self, outpath, quality=90):
+        # self.im = self.im.convert("RGB")
+        self.im.save(outpath, quality=quality)
+
+    def resize(self, width):
+        re_x = int(width)
+        re_y = int(self.y * re_x / self.x)
+        self.im = self.im.resize((re_x, re_y), Image.Resampling.LANCZOS)
+        self.x, self.y = self.im.size
+
+    def resize_regular(self, width, high):
+        self.im = self.im.resize((width, high), Image.Resampling.LANCZOS)
+
+    def corp_square(self):
+        if self.y < self.x:
+            return
+        self.im = self.im.crop((0, int((self.y - self.x) / 2), self.x, self.y - int((self.y - self.x) / 2)))
+
+
+class RenamePic(QWidget, rename_pic_Ui_Form):
+    progress_sign = Signal(dict)
+    info_sign = Signal(str)
+    text_show = Signal(str)
+
+    def __init__(self, windows=None):
+        super().__init__()
+        # 加载默认配置
+        self.setupUi(self)
+        # 0禁用  1进行中  2已结束
+        self.state = 2
+        self.init()
+        self.pic_dir = ""
+        self.setFixedSize(self.width(), self.height())
+        self.set_state(2)
+        self.show()
+        QTimer.singleShot(500, self.check_login)
+
+    def check_login(self, *args):
+        if not settings.IsLogin:
+            a = QMessageBox.question(self, '确认', '请先登录',
+                                     QMessageBox.Yes)
+            self.close()
+
+    def init(self):
+        self.text_show.connect(self.append_text_to_browser)
+        self.label_3.mousePressEvent = self.select_pic_dir
+        self.label_4.setText("")
+        # self.label_6.setText(self.get_len_text(self.to_deal_excel_dir, 50))
+        self.pushButton.clicked.connect(self.run)
+
+    def create_folder(self, path):
+        if not os.path.exists(path):
+            os.makedirs(path)
+
+    def get_len_text(self, text, max_len: int):
+        if len(text) > max_len:
+            text = text[:int(max_len / 4)] + "..." + text[-1 * int(max_len * 3 / 4):]
+        return text
+
+    def select_pic_dir(self, *args):
+        pic_dir = QFileDialog.getExistingDirectory(None, "选取文件夹", "")
+
+        if not pic_dir:
+            self.label_4.setText("")
+            return
+        self.pic_dir = pic_dir
+        self.label_4.setText(pic_dir)
+
+    def check_path(self, _path):
+        if not os.path.exists(_path):
+            os.mkdir(_path)
+        return True
+
+    def set_state(self, state_value: int):
+        # 0禁用  1进行中  2已结束
+        if state_value not in [0, 1, 2]:
+            return
+        self.state = state_value
+        if self.state == 0:
+            self.progressBar.hide()
+            self.pushButton.setEnabled(False)
+        if self.state == 1:
+            self.progressBar.show()
+            self.progressBar.setValue(0)
+            self.textBrowser_2.show()
+            self.pushButton.setEnabled(False)
+            self.textBrowser_2.clear()
+        if self.state == 2:
+            self.progressBar.hide()
+            self.pushButton.setEnabled(True)
+
+    def run(self):
+        # 基础检查
+        if not settings.IsLogin:
+            a = QMessageBox.question(self, '确认', '请先登录',
+                                     QMessageBox.Yes)
+            return
+
+        self.set_state(1)
+        if not self.pic_dir:
+            self.text_show.emit("请选择图片文件夹")
+            self.set_state(2)
+            return
+        if self.comboBox.currentText() == "请选择":
+            self.text_show.emit("请选择是否将货号添加到图片中")
+            self.set_state(2)
+            return
+        total = 0
+        _Type = ['.png', '.PNG', '.jpg', '.JPG', '.gif', '.GIF', '.jpeg', '.JPEG']
+        for image_file in os.listdir(self.pic_dir):
+            path = "{}\{}".format(self.pic_dir, image_file)
+            if os.path.isfile(path):
+                if os.path.splitext(image_file)[1] in _Type:
+                    total += 1
+        if total == 0:
+            self.text_show.emit("当前文件夹下没有图片")
+            self.set_state(2)
+            return
+        is_add_text = False
+        if self.comboBox.currentText() == "添加":
+            is_add_text = True
+        self.run_deal(total=total, is_add_text=is_add_text)
+
+        self.set_state(2)
+
+    def send_info(self, data):
+        if data["_type"] == "show_p":
+            self.progressBar.setValue(data["data"])
+        if data["_type"] == "text":
+            self.textBrowser_2.append(data["data"])
+
+    def run_deal(self, total, is_add_text=False):
+        # 输出目录
+        out_put_path = "{}\out_put_{}".format(os.path.split(self.pic_dir)[0], int(time.time()))
+        # 无法识别的目录
+        error_path = "{}\识别失败".format(out_put_path)
+        # 识别成功的目录
+        success_path = "{}\识别成功".format(out_put_path)
+
+        self.check_path(out_put_path)
+        self.check_path(error_path)
+        self.check_path(success_path)
+
+        error_list = []
+        _Type = ['.png', '.PNG', '.jpg', '.JPG', '.gif', '.GIF', '.jpeg', '.JPEG']
+        last_code = None
+        do_n = 0
+        for image_file in os.listdir(self.pic_dir):
+            if os.path.splitext(image_file)[1] in _Type:
+                # 获取当前路径的文件夹名称
+                file_path = "{}/{}".format(self.pic_dir, image_file)
+                self.send_info({"_type": "text",
+                                "data": "{}图片解析".format(image_file)})
+                code = self.get_code(file_path)
+
+                if code:
+                    if "_" in code:
+                        goods_number = code.split("_")[0]
+                        numbers_list = [goods_number]
+                        r_data = GetOnlineData().get_goods_art_no_info(numbers_list=numbers_list)
+                        if goods_number in r_data:
+                            code = r_data[goods_number]["商品货号"]
+                        else:
+                            code = None
+                            self.send_info({"_type": "text",
+                                            "data": "{}查询不到商品".format(goods_number)})
+
+                if code:
+                    # 获取到二维码内容,说明是二维码图片,则不做处理
+                    last_code = code
+                    continue
+                else:
+                    # 上个二维码没有解析成功
+                    if not last_code:
+                        error_list.append(image_file)
+                        self.send_info({"_type": "text",
+                                        "data": "{}无法识别".format(image_file)})
+                        shutil.copyfile(file_path, "{}\{}".format(error_path, image_file))
+                    #
+                    if last_code:
+                        print("{}--------".format(last_code))
+                        # 目标文件路径
+                        _file_name = "{}{}".format(last_code, os.path.splitext(image_file)[1])
+                        dst_file = "{}/{}".format(success_path, _file_name)
+                        if os.path.exists(dst_file):
+                            self.send_info({"_type": "text",
+                                            "data": "{}图片已存在".format(image_file)})
+                            last_code = None
+                            continue
+                        shutil.copy(file_path, dst_file)  # 复制文件
+                        pic = Picture(dst_file)
+                        pic.resize(width=800)
+                        pic.corp_square()  # 居中剪裁
+                        if is_add_text:
+                            draw = ImageDraw.Draw(pic.im)
+                            font_style_1 = ImageFont.truetype(r"ttf\simfang.ttf", 40, encoding="utf-8")
+                            draw.text((0, 0), last_code, 0, font=font_style_1)
+                        pic.save_img(dst_file)
+                        # 处理成功了,清空上个记录
+                        last_code = None
+
+            do_n += 1
+            self.send_info({"_type": "show_p",
+                            "data": int(do_n / total * 100)})
+        if error_list:
+            self.send_info({"_type": "text",
+                            "data": "以下图片无法解析,请自行处理"})
+        self.send_info({"_type": "text",
+                        "data": "{}".format(error_list)})
+
+        os.startfile(out_put_path)
+
+    def append_text_to_browser(self, text):
+        self.textBrowser_2.append(text)
+
+    def create_folder(self, path):
+        if not os.path.exists(path):
+            os.makedirs(path)
+            return False
+
+    def get_code(self, file_path):
+        pic = Picture(file_path)
+        pic.resize(width=1000)
+        im = pic.im
+        img = cvtColor(np.asarray(im), COLOR_RGB2BGR)
+        # path = r"D:\MyDocuments\PythonCode\MyPython\red_dragonfly\deal_pics\rename_by_qrcode\opencv_3rdparty-wechat_qrcode"
+        detector = WeChatQRCode(detector_prototxt_path="qr_mode/detect.prototxt",
+                                detector_caffe_model_path="qr_mode/detect.caffemodel",
+                                super_resolution_prototxt_path="qr_mode/sr.prototxt",
+                                super_resolution_caffe_model_path="qr_mode/sr.caffemodel")
+
+        res, points = detector.detectAndDecode(img)
+        if res:
+            return res[0]
+        return None
+
+    def deal_pic_resize(self, file_path, target_size, times=0, ):
+        file_size = int(os.path.getsize(file_path) / 1024)
+        if file_size < target_size:
+            return
+        times += 1
+        if times > 2:
+            print(file_path, "压缩次数", times)
+        k = 0.9
+        # if file_size > target_size * 5:
+        #     k = 0.7
+        pic = Picture(file_path)
+        w = int(pic.x * k)
+        pic.resize(w)
+        pic.save_img(file_path)
+        return self.deal_pic_resize(file_path, target_size, times)

+ 181 - 0
module/module_resize_pic.py

@@ -0,0 +1,181 @@
+# -*- coding: utf-8 -*-
+import time
+import sys
+import os
+from UI.resize_photos import Ui_Form as ResizePicUI
+from PySide6.QtWidgets import *
+from PySide6.QtCore import *
+from PIL import Image
+
+
+class ResizePic(QWidget, ResizePicUI):
+    signal_data = Signal(dict)
+
+    def __init__(self, windows=None):
+        super().__init__()
+        self.windows = windows
+        self.setupUi(self)
+        self.setFixedSize(self.width(), self.height())
+        self.allow_modified = True
+        self.pic_width_target = 10000
+        self.state = 0
+        self.show_img_dir = ""
+        self.change_state(self.state)
+        self.init()
+        self.setWindowModality(Qt.ApplicationModal)
+        self.show()
+
+    def change_state(self, index=0):
+        if index == 0:
+            self.progressBar.hide()
+            self.label_5.hide()
+            self.pushButton.setText("执行压缩")
+            self.pushButton.setEnabled(True)
+        if index == 1:
+            self.progressBar.show()
+            self.progressBar.setValue(0)
+            self.textBrowser_2.setText("")
+            self.label_5.show()
+            self.pushButton.setText("进行中")
+            self.pushButton.setEnabled(False)
+
+    def init(self):
+        self.label_4.setText("")
+        self.label_8.hide()
+        self.label_3.mousePressEvent = self.change_img_dir
+        self.label_8.mousePressEvent = self.open_dir
+        self.signal_data.connect(self.show_info)
+        self.pushButton.clicked.connect(self.run)
+
+    def open_dir(self, *args, **kwargs):
+        if self.show_img_dir:
+            os.startfile(self.show_img_dir)
+
+    def run(self, is_sure=False):
+        if not self.lineEdit.text():
+            QMessageBox.question(self, '确认', '请输入目标像素', QMessageBox.Yes)
+            return
+        else:
+            try:
+                self.pic_width_target = int(self.lineEdit.text())
+                if self.pic_width_target < 200 or self.pic_width_target > 2000:
+                    QMessageBox.question(self, '确认', '建议像素在800px左右', QMessageBox.Yes)
+                    return
+            except:
+                QMessageBox.question(self, '确认', '像素必须是整数', QMessageBox.Yes)
+                return
+
+        if not is_sure:
+            if not self.show_img_dir:
+                QMessageBox.question(self, '确认', '请选择图片文件夹', QMessageBox.Yes)
+                return
+
+            a = QMessageBox.question(self, '确认', '是否确认继续执行,软件会自动处理所有子文件夹,请自行备份数据,执行后无法恢复',
+                                     QMessageBox.Yes | QMessageBox.No)
+            if a != QMessageBox.Yes:
+                return
+
+            # 计算待处理图片数量
+            total_pic = 0
+            _Type = ['.png', '.PNG', '.jpg', '.JPG', '.gif', '.GIF', '.jpeg', '.JPEG']
+            for dirpath, dirnames, filenames in os.walk(self.show_img_dir):
+                for file in filenames:
+                    if os.path.splitext(file)[1] in _Type:
+                        total_pic += 1
+
+            if not total_pic:
+                QMessageBox.question(self, '确认', '没有任何图片', QMessageBox.Yes)
+                return
+
+            a = QMessageBox.question(self, '确认', '待处理图片数:{},是否继续'.format(total_pic),
+                                     QMessageBox.Yes | QMessageBox.No)
+            if a == QMessageBox.Yes:
+                self.run(is_sure=True)
+        else:
+            self.deal_pic()
+
+    def show_info(self, data):
+        if data["_type"] == "show_schedule":
+            self.progressBar.setValue(data["data"])
+
+        if data["_type"] == "show_text":
+            self.textBrowser_2.append(data["data"])
+
+        if data["_type"] == "change_state":
+            self.change_state(data["data"])
+
+    def deal_pic(self):
+        total_pic = 0
+        _Type = ['.png', '.PNG', '.jpg', '.JPG', '.gif', '.GIF', '.jpeg', '.JPEG']
+        for dirpath, dirnames, filenames in os.walk(self.show_img_dir):
+            for file in filenames:
+                if os.path.splitext(file)[1] in _Type:
+                    total_pic += 1
+
+        self.signal_data.emit({"_type": "change_state",
+                               "data": 1})
+
+        self.signal_data.emit({"_type": "show_schedule",
+                               "data": 0})
+
+        n = 0
+        _Type = ['.png', '.PNG', '.jpg', '.JPG', '.gif', '.GIF', '.jpeg', '.JPEG']
+        for dirpath, dirnames, filenames in os.walk(self.show_img_dir):
+            for file in filenames:
+                if os.path.splitext(file)[1] in _Type:
+                    n += 1
+                    file_path = dirpath + "/" + file
+                    self.signal_data.emit({"_type": "show_schedule",
+                                           "data": (n / total_pic * 100)})
+                    self.signal_data.emit({"_type": "show_text",
+                                           "data": "正在处理:{}".format(file)})
+                    print(file_path)
+                    pic = Picture(file_path)
+                    if pic.x > self.pic_width_target:
+                        pic.resize(self.pic_width_target)
+                        pic.save_img(file_path)
+        self.signal_data.emit({"_type": "show_text",
+                               "data": "已完成"})
+        self.signal_data.emit({"_type": "change_state",
+                               "data": 0})
+
+    def change_img_dir(self, *args):
+        folder = QFileDialog.getExistingDirectory(self, "选取文件夹", "./")
+        print(folder)
+        self.show_img_dir = folder
+        self.label_4.setText(self.show_img_dir)
+        if self.show_img_dir:
+            self.label_8.show()
+        else:
+            self.label_8.hide()
+
+
+class Picture:
+
+    def __init__(self, in_path):
+        self.im = Image.open(in_path)
+        self.x, self.y = self.im.size
+        # print(self.x, self.y)
+
+    def save_img(self, outpath, quality=90):
+        if outpath.endswith("jpg"):
+            if self.im.mode != 'RGB':
+                self.im = self.im.convert("RGB")
+                self.im.save(outpath,format="JPEG")
+                return
+
+        if outpath.endswith("png"):
+            if self.im.mode != 'RGBA':
+                self.im = self.im.convert("RGBA")
+            self.im.save(outpath)
+            return
+        self.im.save(outpath)
+
+    def resize(self, width):
+        re_x = int(width)
+        re_y = int(self.y * re_x / self.x)
+        self.im = self.im.resize((re_x, re_y), Image.Resampling.LANCZOS)
+        self.x, self.y = self.im.size
+
+    def resize_regular(self, width, high):
+        self.im = self.im.resize((width, high), Image.Resampling.LANCZOS)

+ 15 - 0
module/other/command_func.py

@@ -0,0 +1,15 @@
+import hashlib
+
+
+def get_file_md5(file_path):
+    # 打开文件并读取其中的数据
+    with open(file_path, 'rb') as f:
+        data = f.read()
+    # 计算MD5值并输出结果
+    md5_value = hashlib.md5(data).hexdigest()
+    return md5_value
+
+
+if __name__ == '__main__':
+    print(get_file_md5(
+        r"D:\MyDocuments\PythonCode\MyPython\red_dragonfly\deal_excel\haocaitong_data_completion\2024年春夏季线下商品资料表初步模版11.2.xlsx"))

+ 0 - 0
module/other/custom_config.ini


+ 71 - 0
module/other/log.py

@@ -0,0 +1,71 @@
+import logging
+import sys
+import os
+from logging.handlers import RotatingFileHandler
+import threading
+
+
+class MyLogger(object):
+    instance = None
+    init_flag = None
+
+    def __init__(self, name=""):
+        """此处设计为,如果已经存在实例时,不再执行初始化"""
+        if self.init_flag:
+            return
+        else:
+            self.init_flag = True
+
+        self.logger_lock = threading.Lock()
+        self.name = name
+        self.init()
+
+    def init(self):
+        # 创建日志器
+        self.logger = logging.getLogger("图片抠图工具")
+        self.logger.setLevel("DEBUG")
+
+        if not os.path.exists("{}\log".format(os.getcwd())):
+            os.mkdir("{}\log".format(os.getcwd()))
+
+        # 定义日志处理器
+        cl = logging.StreamHandler()  # 将日志输出到终端
+        fl = RotatingFileHandler("log\logging_text.log", mode="a", encoding="utf-8", maxBytes=10 * 1024 * 1024,
+                                 backupCount=5)  # 输出日志到文本
+
+        # 定义初始化格式 # 定义两个日志布局
+        fmt1 = ("%(asctime)s---%(name)s---%(message)s")
+        fmt2 = ("%(asctime)s---%(lineno)d---%(name)s---%(message)s")
+
+        # 创建初始化器
+        a = logging.Formatter(fmt=fmt1)
+        b = logging.Formatter(fmt=fmt2)
+
+        # 添加处理器格式 将上面创建的初始化器添加
+        cl.setFormatter(a)
+        fl.setFormatter(b)
+
+        # 将处理器添加到日志器
+        self.logger.addHandler(cl)
+        self.logger.addHandler(fl)
+
+        sys.excepthook = self.handle_exception
+
+    # 函数,用来记录系统报错
+    def handle_exception(self, exc_type, exc_value, exc_traceback):
+        if issubclass(exc_type, KeyboardInterrupt):
+            sys.__excepthook__(exc_type, exc_value, exc_traceback)
+            return
+        self.logger.error("Uncaught exception", exc_info=(exc_type, exc_value, exc_traceback))
+
+    def __new__(cls, *args, **kwargs):
+        """如果当前没有实例时,调用父类__new__方法,生成示例,有则返回保存的内存地址。"""
+        if not cls.instance:
+            cls.instance = super().__new__(cls)
+        return cls.instance
+
+# logger.debug("debug message")
+# logger.info("debug message")
+# logger.warning("warning message")
+# logger.error("error message")
+# logger.critical("critical message")

+ 74 - 0
module/other/module_aes.py

@@ -0,0 +1,74 @@
+from Crypto.Cipher import AES
+from binascii import b2a_hex, a2b_hex
+import wmi
+
+
+# pip install pycryptodome
+# pip install wmi
+
+class Aes(object):
+    # 如果text不足16位的倍数就用空格补足为16位
+    def add_to_16(self, text):
+        if len(text.encode('utf-8')) % 16:
+            add = 16 - (len(text.encode('utf-8')) % 16)
+        else:
+            add = 0
+        text = text + ('\0' * add)
+        return text.encode('utf-8')
+
+    # 加密函数
+    def encrypt(self, text, key, iv):
+        mode = AES.MODE_CBC
+        text = self.add_to_16(text)
+        cryptos = AES.new(key=key.encode('utf-8'), mode=mode, iv=iv.encode('utf-8'))
+        cipher_text = cryptos.encrypt(text)
+        # 因为AES加密后的字符串不一定是ascii字符集的,输出保存可能存在问题,所以这里转为16进制字符串
+        return b2a_hex(cipher_text)
+
+    # 解密后,去掉补足的空格用strip() 去掉
+    def decrypt(self, text, key, iv):
+        mode = AES.MODE_CBC
+        cryptos = AES.new(key=key.encode('utf-8'), mode=mode, iv=iv.encode('utf-8'))
+        plain_text = cryptos.decrypt(a2b_hex(text))
+        return bytes.decode(plain_text).rstrip('\0')
+
+    def get_computer_key(self):
+        c = wmi.WMI()
+        system_info = c.Win32_ComputerSystem()[0]
+        mac_address = c.Win32_NetworkAdapterConfiguration(IPEnabled=True)[0].MACAddress
+        cpu_id = c.Win32_Processor()[0].ProcessorId
+        machine_code = system_info.Manufacturer + '' + system_info.Model + '' + mac_address + '' + cpu_id
+        machine_code = machine_code.replace(" ", "").replace(":", "")
+        return machine_code
+
+    def get_authorization(self, key_text, key, iv):
+        machine_code = self.get_computer_key()
+        try:
+            text = self.decrypt(key_text, key, iv)  # 解密
+        except:
+            return "false"
+        try:
+            _machine_code, authorization = text.split("_")
+            if _machine_code != machine_code:
+                return "false"
+        except:
+            return "false"
+        return authorization
+
+    def get_key(self, authorization, key, iv):
+        machine_code = self.get_computer_key()
+        key = self.encrypt("{}_{}".format(machine_code, authorization), key, iv)  # 加密
+
+        return key.decode()
+
+
+if __name__ == '__main__':
+    print(Aes().get_computer_key())
+    # e = Aes().encrypt("hellosadsasdasdas1111+ world", "8E5EC2AC2191167DF9B753BA93A1E7B1", "0112030405060701")  # 加密
+    # d = Aes().decrypt(e, "8E5EC2AC2191167DF9B753BA93A1E7B1", "0112030405060701")  # 解密
+    c = Aes().get_key("heldasdasdsdsadsadsadsadsadsadsdsadsadasdasds", "8E5EC2AC2191167DF9B753BA93A1E7B1", "0112030405060701")
+    print(c)
+    print(
+        Aes().get_authorization(c, "8E5EC2AC2191167DF9B753BA93A1E7B1", "0112030405060701"))
+    # print("加密:", e)
+    # print("解密:", d)

+ 188 - 0
module/other/module_online_data.py

@@ -0,0 +1,188 @@
+# import json
+# import time
+import copy
+import random
+import time
+import requests
+import settings
+import json
+import numpy as np
+import os, io
+from PIL import Image
+from io import BytesIO
+
+
+class JsonEncoder(json.JSONEncoder):
+    """Convert numpy classes to JSON serializable objects."""
+
+    def default(self, obj):
+        if isinstance(obj, (np.integer, np.floating, np.bool_)):
+            return obj.item()
+        elif isinstance(obj, np.ndarray):
+            return obj.tolist()
+        else:
+            return super(JsonEncoder, self).default(obj)
+
+
+class GetOnlineData(object):
+    def __init__(self):
+        self.s = requests.session()
+        self.post_headers = {"Authorization": settings.Headers["Authorization"],
+                             "Origin": settings.Headers["Origin"],
+                             "Host": settings.Headers["Host"],
+                             "Content-Length": "0",
+                             "Content-Type": "application/json",
+                             "Accept": "application/json"}
+
+    def refresh_headers(self):
+        self.post_headers = {"Authorization": settings.Headers["Authorization"],
+                             "Origin": settings.Headers["Origin"],
+                             "Host": settings.Headers["Host"],
+                             "Content-Length": "0",
+                             "Content-Type": "application/json",
+                             "Accept": "application/json"}
+
+    def get_key_secret(self):
+        # 获取抠图剩余次数
+        url = "{domain}/api/ai_image/client/get_key_serect".format(
+            domain=settings.DOMAIN)
+        _s = self.s.post(url=url, headers=self.post_headers, timeout=10)
+        response_data = _s.json()
+        return response_data["data"]
+
+    def get_cutout_image_times(self):
+        # 获取抠图剩余次数
+        url = "{domain}/api/ai_image/client/search_company_balance".format(
+            domain=settings.DOMAIN)
+        _s = self.s.post(url=url, headers=self.post_headers, timeout=10)
+        response_data = _s.json()
+        if "data" not in response_data:
+            return False
+        else:
+            return response_data["data"]
+
+    def search_progress(self, generate_ids):
+        # 查进度
+        url = "{domain}/api/ai_image/client/search_progress".format(
+            domain=settings.DOMAIN
+        )
+        data = {"generate_ids": generate_ids}
+        _s = self.s.post(url=url, headers=self.post_headers, data=json.dumps(data), timeout=60)
+        response_data = _s.json()
+        return response_data["data"]
+
+    def download_picture(self, url, out_path):
+        response = requests.get(url, timeout=30)
+        pic = response.content
+        if out_path:
+            with open(out_path, 'wb') as f:
+                f.write(pic)
+        else:
+            return Image.open(BytesIO(pic))
+
+    def remove_background(self, images_url):
+        url = "{domain}/api/ai_image/client/remove_background".format(
+            domain=settings.DOMAIN
+        )
+        data = {"images": images_url}
+        _s = self.s.post(url=url, headers=self.post_headers, data=json.dumps(data), timeout=30)
+        response_data = _s.json()
+        return response_data["data"]["generate_ids"], int(response_data["data"]["balance"])
+
+    def get_current_menu(self):
+        def get_menu(_menu_dict, _data):
+            for menu in _data:
+                _menu_dict[menu["key"]] = {}
+                for mods in menu["mods_arr"]:
+                    _menu_dict[menu["key"]][mods["key"]] = mods["name"]
+                if "_child" in menu:
+                    get_menu(_menu_dict, menu["_child"])
+            return _menu_dict
+
+        url = "{domain}/api/backend/basic/get_current_menu".format(
+            domain=settings.DOMAIN,
+        )
+        _s = self.s.get(url=url, headers=settings.Headers)
+        response_data = _s.json()
+        try:
+            menu_data = response_data["data"]["pc_menu"]
+            menu_dict = {}
+            menu_dict = get_menu(menu_dict, menu_data)
+        except:
+            menu_dict = {}
+        # print(json.dumps(menu_dict,ensure_ascii=False))
+        # raise 1
+        return menu_dict
+
+    def upload_pic(self, file_path, buffer=None):
+        if buffer is None:
+            root_path, file_name = os.path.split(file_path)
+            e = os.path.splitext(file_name)[1]
+
+            __format = {"jpg": "JPEG",
+                        "JPG": "JPEG",
+                        "JPEG": "JPEG",
+                        "jpeg": "JPEG",
+                        "png": "PNG",
+                        "PNG": "PNG", }
+
+            _format = __format[e[1:]]
+            if _format == "JPEG":
+                buffer = io.BytesIO()
+                im = Image.open(file_path)
+                im.save(buffer, format='JPEG')
+                buffer.seek(0)
+            else:
+                with open(file_path, 'rb') as file:
+                    buffer = io.BytesIO(file.read())
+
+            files = [
+                ('file',
+                 (file_path,
+                  buffer,
+                  'image/{}'.format(_format)))
+            ]
+        else:
+            files = [
+                ('file',
+                 ("1.jpg",
+                  buffer,
+                  'image/{}'.format("JPEG")))
+            ]
+
+        url = "{domain}/api/backend/upload".format(
+            domain=settings.DOMAIN
+        )
+
+        headers = {"Authorization": settings.Headers["Authorization"],
+                   "Origin": settings.Headers["Origin"],
+                   "Host": settings.Headers["Host"],
+                   }
+
+        _s = requests.post(url=url, headers=headers, files=files, timeout=60)
+        # print(_s.text)
+        response_data = _s.json()
+        return response_data["data"]["url"]
+
+    def get_keys(self):
+        k = "pxnib99dbchtmdm"
+        s = "ub9uj5678gs4m2bnrass1t3tn6ughlk065ianosk06akagolcr2u"
+        return (k,s)
+
+    def dispose_point(self,_type):
+        # 扣分 sub;add为增加分数,每次操作一分
+        url = "{domain}/api/ai_image/client/dispose_point".format(
+            domain=settings.DOMAIN)
+        data = {"type": _type}
+        _s = self.s.post(url=url, headers=self.post_headers,data=json.dumps(data), timeout=10)
+        response_data = _s.json()
+        return response_data
+
+    def send_message(self,text):
+        # 发送钉钉消息
+        url = "{domain}/api/ai_image/client/send_message".format(
+            domain=settings.DOMAIN)
+        data = {"message": text}
+        _s = self.s.post(url=url, headers=self.post_headers,data=json.dumps(data), timeout=10)
+        response_data = _s.json()
+        return response_data

+ 62 - 0
module/other/module_setting.py

@@ -0,0 +1,62 @@
+# -*- coding: utf-8 -*-
+import time
+import sys
+import os
+
+import settings
+from UI.set_image_mode import Ui_Form
+from PySide6.QtWidgets import *
+from PySide6.QtCore import *
+
+
+class ToSetting(QWidget, Ui_Form):
+    signal_data = Signal(dict)
+
+    def __init__(self, windows):
+        super().__init__()
+        self.windows = windows
+        self.setupUi(self)
+        self.setFixedSize(self.width(), self.height())
+        self.init()
+        self.setWindowModality(Qt.ApplicationModal)
+        self.show()
+
+    def init(self):
+        self.pushButton.clicked.connect(self.run)
+        # 回填数据
+
+        self.lineEdit.setText(",".join(settings.is_fall_dir))
+
+        self.lineEdit_2.setText(",".join(settings.is_fall_file))
+
+    def run(self):
+        is_fall_dir = self.lineEdit.text()
+        if not is_fall_dir:
+            is_fall_dir = "已扣图"
+        else:
+            if "已扣图" not in is_fall_dir:
+                is_fall_dir += ",已扣图"
+
+        is_fall_dir = is_fall_dir.replace(",", ",")
+        is_fall_dir = is_fall_dir.replace(",,", ",")
+
+        settings.set_config(data_dict={"is_fall_dir": is_fall_dir}, section="basicSetup")
+
+        if is_fall_dir:
+            is_fall_dir = is_fall_dir.split(",")
+            settings.is_fall_dir = [x for x in is_fall_dir if x]
+        else:
+            settings.is_fall_dir = []
+
+
+        is_fall_file = self.lineEdit_2.text()
+        is_fall_file = is_fall_file.replace(",", ",")
+        settings.set_config(data_dict={"is_fall_file": is_fall_file}, section="basicSetup")
+
+        if is_fall_file:
+            is_fall_file = is_fall_file.split(",")
+            settings.is_fall_file = [x for x in is_fall_file if x]
+        else:
+            settings.is_fall_file = []
+
+        self.close()

+ 26 - 0
module/other/pic.py

@@ -0,0 +1,26 @@
+from PIL import Image
+
+
+class Picture:
+    def __init__(self, in_path, im=None):
+        if im:
+            self.im = im
+        else:
+            self.im = Image.open(in_path)
+        self.x, self.y = self.im.size
+
+    def save_img(self, outpath, quality=90):
+        # self.im = self.im.convert("RGB")
+        self.im.save(outpath, quality=quality)
+
+    def resize(self, width):
+        re_x = int(width)
+        re_y = int(self.y * re_x / self.x)
+        self.im = self.im.resize((re_x, re_y), Image.BICUBIC)
+        self.x, self.y = self.im.size
+
+    def resize_by_heigh(self, heigh):
+        re_y = int(heigh)
+        re_x = int(self.x * re_y / self.y)
+        self.im = self.im.resize((re_x, re_y), Image.BICUBIC)
+        self.x, self.y = self.im.size

+ 267 - 0
module/other/remove_bg_ali.py

@@ -0,0 +1,267 @@
+import copy
+import json
+import os
+from PIL import Image
+from alibabacloud_imageseg20191230.client import Client as imageseg20191230Client
+from alibabacloud_imageseg20191230.models import SegmentCommodityAdvanceRequest
+from alibabacloud_imageseg20191230 import models as imageseg_20191230_models
+from alibabacloud_tea_util.models import RuntimeOptions
+from alibabacloud_tea_openapi import models as open_api_models
+from alibabacloud_tea_openapi.models import Config
+from alibabacloud_tea_util import models as util_models
+import requests
+from io import BytesIO
+import cv2
+import numpy as np
+from module.other.module_online_data import GetOnlineData
+
+
+
+# todo 获取密钥
+# key_id,key_secret = GetOnlineData().get_cutout_image_config()
+# 惠利玛的key
+AccessKeyId = 'LTAI5tBdDVT9Wc5idJXdGHjw'
+AccessKeySecret = 'bCSotQ7eAztOxx6AqHwJJPsb0hkECe'
+
+
+
+# https://help.aliyun.com/zh/viapi/developer-reference/python?spm=a2c4g.11186623.0.i0#task-2252575
+# pip install alibabacloud_goodstech20191230
+# pip install alibabacloud_tea_openapi
+# pip install alibabacloud_tea_util
+
+class Segment(object):
+    def __init__(self):
+        self.client = self.create_client()
+
+    def get_no_bg_common(self, file_path):
+        # 初始化RuntimeObject
+        runtime_option = RuntimeOptions()
+        try:
+            # 场景一:文件在本地
+            img = open(file_path, 'rb')
+            # 使用完成之后记得调用img.close()关闭流
+            # 场景二,使用任意可访问的url
+            # url = 'https://viapi-test-bj.oss-cn-beijing.aliyuncs.com/viapi-3.0domepic/ocr/RecognizeBankCard/yhk1.jpg'
+            # img = io.BytesIO(urlopen(url).read())
+            # 4、初始化Request,这里只是以RecognizeBankCard为例,其他能力请使用相应能力对应的类
+            request = SegmentCommodityAdvanceRequest()
+            request.image_urlobject = img
+
+            # 5、调用api,注意,recognize_bank_card_advance需要更换为相应能力对应的方法名。方法名是根据能力名称按照一定规范形成的,如能力名称为SegmentCommonImage,对应方法名应该为segment_common_image_advance。
+            response = self.client.segment_common_image_advance(request, runtime_option)
+            # 获取整体结果
+            # print(response.body)
+            img.close()
+            return response.body
+            # 获取单个字段,这里只是一个例子,具体能力下的字段需要看具体能力的文档
+            # print(response.body.data.card_number)
+            # tips: 可通过response.body.__dict__查看属性名称
+        except Exception as error:
+            # 获取整体报错信息
+            print("error", error)
+            return None
+            # 获取单个字段
+            # print(error.code)
+            # tips: 可通过error.__dict__查看属性名称
+
+    def get_no_bg_goods(self, file_path=None, _im=None):
+        # file_path = r"D:\MyDocuments\PythonCode\MyPython\red_dragonfly\deal_pics\change_color_2\test\_MG_9061.jpg"
+        # file_path_1 = r"D:\MyDocuments\PythonCode\MyPython\red_dragonfly\deal_pics\change_color_2\test\_MG_9061_resize.png"
+        # if file_path:
+        #     img = open(file_path, 'rb')
+        # if _im:
+        # https://blog.csdn.net/weixin_43411585/article/details/107780941
+        im = _im
+        # im.save(file_path)
+        img = BytesIO()
+        im.save(img, format='JPEG')  # format: PNG or JPEG
+        img.seek(0)  # rewind to the start
+
+        # img = img_byte.getvalue()  # im对象转为二进制流
+        # with open(file_path, "wb") as binary_file:
+        #     binary_file.write(im.tobytes())
+
+        # file_path = r"D:\MyDocuments\PythonCode\MyPython\red_dragonfly\deal_pics\change_color_2\test\1.png"
+        # img = open(file_path, 'rb')
+
+        request = imageseg_20191230_models.SegmentCommodityAdvanceRequest()
+        request.image_urlobject = img
+        client = self.create_client()
+        # 5、调用api,注意,recognize_bank_card_advance需要更换为相应能力对应的方法名。方法名是根据能力名称按照一定规范形成的,如能力名称为SegmentCommonImage,对应方法名应该为segment_common_image_advance。
+        runtime = util_models.RuntimeOptions()
+        response = client.segment_commodity_advance(request, runtime)
+        # img.close()
+        # print("1111111111111", response.body)
+        return response.body
+
+    def create_client(self):
+        """
+        使用AK&SK初始化账号Client
+        @param access_key_id:
+        @param access_key_secret:
+        @return: Client
+        @throws Exception
+        """
+        config = open_api_models.Config(
+            # 必填,您的 AccessKey ID,
+            access_key_id=AccessKeyId,
+            # 必填,您的 AccessKey Secret,
+            access_key_secret=AccessKeySecret
+        )
+        # 访问的域名
+        config.endpoint = f'imageseg.cn-shanghai.aliyuncs.com'
+        return imageseg20191230Client(config)
+
+
+class Picture:
+    def __init__(self, in_path, im=None):
+        if im:
+            self.im = im
+        else:
+            self.im = Image.open(in_path)
+        self.x, self.y = self.im.size
+        # print(self.x, self.y)
+
+    def save_img(self, outpath, quality=90):
+        # self.im = self.im.convert("RGB")
+        self.im.save(outpath, quality=quality)
+
+    def resize(self, width):
+        re_x = int(width)
+        re_y = int(self.y * re_x / self.x)
+        self.im = self.im.resize((re_x, re_y), Image.BICUBIC)
+        self.x, self.y = self.im.size
+
+    def resize_by_heigh(self, heigh):
+        re_y = int(heigh)
+        re_x = int(self.x * re_y / self.y)
+        self.im = self.im.resize((re_x, re_y), Image.BICUBIC)
+        self.x, self.y = self.im.size
+
+
+class RemoveBgALi(object):
+    def __init__(self):
+        self.segment = Segment()
+
+    def get_image_cut(self, file_path, out_file_path=None, original_im=None):
+        if original_im:
+            original_pic = Picture(in_path=None, im=original_im)
+        else:
+            original_pic = Picture(file_path)
+
+        if original_pic.im.mode != "RGB":
+            print("抠图图片不能是PNG")
+            return None
+
+        new_pic = copy.copy(original_pic)
+        after_need_resize = False
+        if new_pic.x > new_pic.y:
+            if new_pic.x > 2000:
+                after_need_resize = True
+                new_pic.resize(2000)
+        else:
+            if new_pic.y > 2000:
+                after_need_resize = True
+                new_pic.resize_by_heigh(heigh=2000)
+
+        # new_pic.im.show()
+        body = self.segment.get_no_bg_goods(file_path=None, _im=new_pic.im)
+        body = eval(str(body))
+        try:
+            image_url = body["Data"]["ImageURL"]
+        except BaseException as e:
+            print("阿里抠图错误:", e)
+            # todo 处理失败,需要删除过程图片
+            return None
+        # 字节流转PIL对象
+        response = requests.get(image_url)
+        pic = response.content
+        _img_im = Image.open(BytesIO(pic))  # 阿里返回的抠图结果 已转PIL对象
+        # 原图更大,则需要执行CV处理
+        if after_need_resize:
+            # 将抠图结果转成mask
+            # _img_im = Image.open(_path)
+            # 将抠图结果放大到原始图大小
+            _img_im = _img_im.resize(original_pic.im.size)
+            new_big_mask = Image.new('RGB', _img_im.size, (0, 0, 0))
+            white = Image.new('RGB', _img_im.size, (255, 255, 255))
+            new_big_mask.paste(white, mask=_img_im.split()[3])
+
+            # ---------制作选区缩小的mask
+            # mask = cv2.imread(mask_path)
+            # mask = cv2.cvtColor(mask, cv2.COLOR_BGR2GRAY)
+            mask = cv2.cvtColor(np.asarray(new_big_mask), cv2.COLOR_BGR2GRAY)  # 将PIL 格式转换为 CV对象
+            mask[mask != 255] = 0
+            # 黑白反转
+            # mask = 255 - mask
+            # 选区缩小10
+            kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (10, 10))
+            erode_im = cv2.morphologyEx(mask, cv2.MORPH_ERODE, kernel)
+
+            # -------再进行抠图处理
+            mask = Image.fromarray(cv2.cvtColor(erode_im, cv2.COLOR_GRAY2RGBA))  # CV 对象转 PIL
+            transparent_im = Image.new('RGBA', original_pic.im.size, (0, 0, 0, 0))
+            # original_pic.im.show()
+            # mask.show()
+            transparent_im.paste(original_pic.im, (0, 0), mask.convert('L'))
+            # transparent_im.show()
+            # 上述抠图结果进行拼接
+            _img_im.paste(transparent_im, (0, 0), transparent_im)
+            # _img_im.show("11111111111111111111111")
+        if out_file_path:
+            _img_im.save(out_file_path)
+        return _img_im
+
+    def get_image_cut1(self, file_path, out_file_path=None):
+        original_pic = Picture(file_path)
+        new_pic = copy.copy(original_pic)
+        if new_pic.x > 2000:
+            new_pic.resize(2000)
+        # new_pic.im.show()
+        body = self.segment.get_no_bg_goods(file_path=out_file_path, _im=new_pic.im)
+        body = eval(str(body))
+        try:
+            image_url = body["Data"]["ImageURL"]
+        except BaseException as e:
+            print("阿里抠图错误:", e)
+            # todo 处理失败,需要删除过程图片
+            return None
+        # 字节流转PIL对象
+        response = requests.get(image_url)
+        pic = response.content
+        _img_im = Image.open(BytesIO(pic))  # 阿里返回的抠图结果 已转PIL对象
+
+        if original_pic.x > 2000:
+            # 原图更大,则需要执行CV处理
+            # _img_im.show()
+            # 对mask进行放大,然后进行抠图处理
+            print("对mask进行放大,然后进行抠图处理")
+            transparent_im = Image.new('RGBA', original_pic.im.size, (0, 0, 0, 0))
+            # original_pic.im.show()
+            # mask.show()
+            _img_im = _img_im.resize((original_pic.x, original_pic.y))
+            # _img_im.show()
+            transparent_im.paste(original_pic.im, (0, 0), mask=_img_im)
+            # transparent_im.show()
+            # transparent_im.show()
+            _img_im = transparent_im
+            # 上述抠图结果进行拼接
+            # _img_im.paste(transparent_im, (0, 0), transparent_im)
+            pass
+
+        _img_im.save(out_file_path)
+        return _img_im
+
+    def download_picture(self, url, out_path):
+        response = requests.get(url)
+        pic = response.content
+        with open(out_path, 'wb') as f:
+            f.write(pic)
+
+
+if __name__ == '__main__':
+    r = RemoveBgALi()
+    path = r"D:\MyDocuments\PythonCode\MyPython\red_dragonfly\deal_pics\auto_capture_V2\IPC\test\171112057820408.png"
+    out_path = "{}._no_bg-out.png".format(path)
+    r.get_image_cut(path, out_file_path=out_path)

+ 50 - 0
module/other/rsa.py

@@ -0,0 +1,50 @@
+import base64
+import time
+import json
+
+from Crypto.Cipher import PKCS1_v1_5 as PKCS1_cipher
+from Crypto.PublicKey import RSA
+
+PUBLIC_KEY = '-----BEGIN PUBLIC KEY-----\n\
+MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDElMhAUOwyo78M97jDGlYvl1FZ\n\
+JZV+/EKZ3G7VDO1T5uUNnXWqgxSSwobbd384/npxvfFznoeJ+PaM/fXFNeOGKL9N\n\
+GrswS/jTmSdIUdoMQVbGuzrGUK1liK+L9VGxxCmbvJ1f+6iiOHUwZAx6AXA2Mk2s\n\
+8LVtXFCoM5cZWG4GiQIDAQAB\n\
+-----END PUBLIC KEY-----'
+
+
+class RSAService:
+    def __int__(self):
+        pass
+
+    def encrypt_public(self, phone) -> str:
+        """
+        使用公钥加密电话号码。
+
+        该方法首先构建一个包含电话号码、时间戳和设备信息的数据字典,
+        然后将该字典转换为JSON字符串,并将其编码为UTF-8字节流。
+        接着,使用RSA公钥对这些数据进行加密,并将加密后的数据使用Base64进行编码,
+        最后返回加密后的字符串。
+
+        参数:
+        phone -- 需要加密的电话号码。
+
+        返回:
+        加密后的电话号码字符串。
+        """
+        # 构建数据字典,包含电话号码、当前时间和设备信息
+        data = {"phone": phone, "time": int(time.time() * 1000), "device": "python"}
+        # 将数据字典转换为JSON字符串,并编码为UTF-8字节流
+        msg = json.dumps(data).encode("utf8")
+        # 使用RSA公钥创建加密器
+        cipher = PKCS1_cipher.new(RSA.importKey(PUBLIC_KEY))
+        # 使用RSA公钥加密数据,并使用Base64编码加密后的数据
+        encrypt_text = base64.b64encode(cipher.encrypt(bytes(msg)))
+        # 返回加密后的数据字符串
+        return encrypt_text.decode('utf-8')
+
+
+if __name__ == '__main__':
+    rsaService = RSAService()
+    msg = rsaService.encrypt_public(phone='13323232323')
+    print(msg)

+ 230 - 0
module/remove_bg_pixian.py

@@ -0,0 +1,230 @@
+import copy
+import os
+from PIL import Image
+from module.other.remove_bg_ali import RemoveBgALi
+import requests
+from io import BytesIO
+
+
+class Segment(object):
+    def __init__(self):
+        self.k = "pxnib99dbchtmdm"
+        self.s = "ub9uj5678gs4m2bnrass1t3tn6ughlk065ianosk06akagolcr2u"
+
+    def get_no_bg_goods2(self, file_path=None, _im=None):
+        im = _im
+        img = BytesIO()
+        try:
+            im.save(img, format='JPEG')  # format: PNG or JPEG
+        except:
+            im.save(img, format='PNG')  # format: PNG or JPEG
+        img.seek(0)  # rewind to the start
+
+        # img = "https://ossimg.valimart.net/uploads/vali_ai/20241011/172864207036098.png"
+
+        response = requests.post(
+            'http://47.76.110.118:27777/api/v2/remove-background',
+            files={'image.url': img},
+            data={
+                # TODO: Add more upload options here
+            },
+            auth=(self.k, self.s)
+        )
+        # print(response.content)
+        if response.status_code == requests.codes.ok:
+            return response.content, ""
+        else:
+            return None, response.content
+
+    def get_no_bg_goods_by_url(self, url):
+        response = requests.post(
+            'https://api.pixian.ai/api/v2/remove-background',
+            data={
+                'image.url': url
+            },
+            auth=(self.k, self.s)
+        )
+
+        if response.status_code == requests.codes.ok:
+            return response.content, ""
+        else:
+            print("response.status_code:", response.status_code)
+            return None, response.content
+
+    def get_no_bg_goods(self, file_path=None, _im=None, key=None):
+        im = _im
+        img = BytesIO()
+        try:
+            im.save(img, format='JPEG')  # format: PNG or JPEG
+        except:
+            im.save(img, format='PNG')  # format: PNG or JPEG
+        img.seek(0)  # rewind to the start
+
+        if key:
+            # todo 切换key
+            auth = key
+            # auth = (self.k, self.s)
+        else:
+            auth = (self.k, self.s)
+
+
+        try:
+            response = requests.post(
+                'https://api.pixian.ai/api/v2/remove-background',
+                files={'image': img},
+                data={
+                    # TODO: Add more upload options here
+                },
+                auth=auth,
+                timeout=40
+            )
+        except BaseException as e:
+            data = {"im": None,
+                    "status_code": "time_out",
+                    "message":"{}".format(e)
+                    }
+            return data
+
+        # print(response.content)
+
+        data = {"im": None,
+                "status_code": response.status_code, }
+
+        if response.status_code == requests.codes.ok:
+            data["im"] = Image.open(BytesIO(response.content))
+
+        return data
+
+
+class Picture:
+    def __init__(self, in_path, im=None):
+        if im:
+            self.im = im
+        else:
+            self.im = Image.open(in_path)
+        self.x, self.y = self.im.size
+        # print(self.x, self.y)
+
+    def save_img(self, outpath, quality=90):
+        # self.im = self.im.convert("RGB")
+        self.im.save(outpath, quality=quality)
+
+    def resize(self, width):
+        re_x = int(width)
+        re_y = int(self.y * re_x / self.x)
+        self.im = self.im.resize((re_x, re_y), Image.BICUBIC)
+        self.x, self.y = self.im.size
+
+    def resize_by_heigh(self, heigh):
+        re_y = int(heigh)
+        re_x = int(self.x * re_y / self.y)
+        self.im = self.im.resize((re_x, re_y), Image.BICUBIC)
+        self.x, self.y = self.im.size
+
+
+class RemoveBgPiXian(object):
+    def __init__(self):
+        self.segment = Segment()
+        self.r = RemoveBgALi()
+
+    def direct_matting_image(self, image):
+        # todo 不能超过32,000,000尺寸的数据
+        x, y = image.size
+        f = False
+        if x * y > 32000000:
+            r = 32000000 / x * y
+            image = image.resize(size=(int(x * r), int(y * r)))
+            f = True
+        pic, _ = self.segment.get_no_bg_goods(file_path=None, _im=image)
+        if not pic:
+            return None, _
+        _img_im = Image.open(BytesIO(pic))  # 阿里返回的抠图结果 已转PIL对象
+        if f:
+            _img_im = _img_im.resize(size=(x, y))
+        return _img_im, ""
+
+    def run_by_image_url(self, url):
+        pic, _ = self.segment.get_no_bg_goods_by_url(url)
+        if pic is not None:
+            _img_im = Image.open(BytesIO(pic))
+            return _img_im, None
+        else:
+            return None, _
+
+    def run_by_image_im(self, im, key):
+        return self.segment.get_no_bg_goods(_im=im, key=key)
+
+    def get_image_cut(self, file_path, out_file_path=None, original_im=None, image_preprocessing=False, is_test=False):
+        if original_im:
+            original_pic = Picture(in_path=None, im=original_im)
+        else:
+            original_pic = Picture(file_path)
+
+        if original_pic.im.mode != "RGB":
+            print("抠图图片不能是PNG")
+            return False, {"data": "抠图图片不能是PNG"}
+
+        if is_test:
+            cut_image = self.r.get_image_cut(file_path=None, out_file_path=None, original_im=original_pic.im)
+            if out_file_path:
+                cut_image.save(out_file_path)
+            return True, {}
+
+        if image_preprocessing:
+            cut_image = self.r.get_image_cut(file_path=None, out_file_path=None, original_im=original_pic.im)
+            image_deal_info = {}
+            x1, y1, x2, y2 = cut_image.getbbox()
+            image_deal_info["鞋子原始位置"] = (x1, y1, x2, y2)
+            o_w, o_h = cut_image.size
+            image_deal_info["鞋子原始抠图后大小"] = (o_w, o_h)
+            # 扩边处理
+            _w, _h = x2 - x1, y2 - y1
+            out_px = 0.06
+            _w, _h = int(out_px * _w), int(out_px * _h)
+            n_x1, n_y1, n_x2, n_y2 = x1 - _w, y1 - _h, x2 + _w, y2 + _h
+            if n_x1 < 0:
+                n_x1 = 0
+            if n_y1 < 0:
+                n_y1 = 0
+            if n_x2 > o_w:
+                n_x2 = o_w
+            if n_y2 > o_h:
+                n_y2 = o_h
+
+            image_deal_info["抠图扩边后位置"] = (n_x1, n_y1, n_x2, n_y2)
+            cut_image = original_pic.im.crop(image_deal_info["抠图扩边后位置"])
+            image_deal_info["抠图扩边后图片大小"] = cut_image.size
+            image_deal_info["原始图片大小"] = (original_pic.x, original_pic.y)
+
+            # 使用pixian进行抠图
+            second_cut_image, _ = self.direct_matting_image(image=cut_image)
+            if not second_cut_image:
+                return False, {"data": _}
+
+            if second_cut_image.size != image_deal_info["抠图扩边后图片大小"]:
+                print("图片尺寸还原")
+                second_cut_image = second_cut_image.resize(image_deal_info["抠图扩边后图片大小"])
+
+            # 创建空白图片并粘贴回去
+            _img_im = Image.new(mode="RGBA", size=image_deal_info["原始图片大小"], color=(0, 0, 0, 0))
+            _img_im.paste(second_cut_image, box=(image_deal_info["抠图扩边后位置"][0], image_deal_info["抠图扩边后位置"][1]))
+        else:
+            _img_im = self.direct_matting_image(image=original_pic.im)
+            pass
+
+        if out_file_path:
+            _img_im.save(out_file_path)
+        return True, {}
+
+    def download_picture(self, url, out_path):
+        response = requests.get(url)
+        pic = response.content
+        with open(out_path, 'wb') as f:
+            f.write(pic)
+
+
+if __name__ == '__main__':
+    r = RemoveBgPiXian()
+    path = r"C:\Users\gymmc\Desktop\白底部分品类45度\测试\eva_keai_1.png"
+    out_path = "{}._no_bg-out.png".format(path)
+    r.get_image_cut(path, out_file_path=out_path)

+ 18 - 0
pip.txt

@@ -0,0 +1,18 @@
+pip install PyQt5 -i https://pypi.douban.com/simple
+pip install pywin32==228 -i https://pypi.douban.com/simple
+pip install requests -i https://pypi.douban.com/simple
+pip install pyinstaller -i https://pypi.douban.com/simple
+pip install pyinstaller -i https://pypi.douban.com/simple
+pip install pyinstaller -i https://pypi.douban.com/simple
+pip install pyinstaller -i https://pypi.douban.com/simple
+
+
+
+
+
+
+
+
+
+pip install opencv-python -i https://pypi.douban.com/simple
+pip install opencv-contrib-python -i https://pypi.douban.com/simple

+ 6 - 0
requestments.txt

@@ -0,0 +1,6 @@
+PyQt5
+pywin32
+requests
+pyinstaller
+opencv-python
+opencv-contrib-python

BIN
resource/images/icon.png


+ 140 - 0
settings.py

@@ -0,0 +1,140 @@
+import logging
+import sys
+import configparser
+import os
+from module.other.module_aes import Aes
+
+
+# ===============默认数据配置=====================
+
+config_name = "config.ini"
+if os.path.exists(config_name):
+    with open(config_name) as f:
+        pass
+config = configparser.ConfigParser()
+try:
+    config.read(config_name, encoding="utf-8")
+except:
+    config.read(config_name)
+
+
+# ===========用户自定义配置=======================
+
+custom_config_name = "custom_config.ini"
+if not os.path.exists(custom_config_name):
+    with open(custom_config_name, 'w') as file:
+        pass
+
+custom_config = configparser.ConfigParser()
+try:
+    custom_config.read(custom_config_name, encoding="utf-8")
+except:
+    custom_config.read(custom_config_name)
+
+
+def set_config(data_dict, section="basicSetup", _config_name="custom_config"):
+    if _config_name == "config":
+        for i, v in data_dict.items():
+            config.set(section=section, option=i, value=v)
+        try:
+            config.write(open(config_name, 'w', encoding="ut-8"))
+        except:
+            config.write(open(config_name, 'w'))
+
+    else:
+        for i, v in data_dict.items():
+            custom_config.set(section=section, option=i, value=v)
+        try:
+            custom_config.write(open(custom_config_name, 'w', encoding="ut-8"))
+        except:
+            custom_config.write(open(custom_config_name, 'w'))
+
+
+def get_config(section_items):
+    __config_dict = {}
+    try:
+        for i, k in section_items:
+            __config_dict[i] = k
+    except:
+        pass
+    return __config_dict
+
+
+with open("key", "r") as f:
+    Key = f.read()
+
+
+def set_key(authorization):
+    global Authorization
+    Authorization = authorization
+    if authorization:
+        authorization = Aes().get_key(authorization, SecretKey, SecretIv)
+    with open("key", "w") as f:
+        f.write(authorization)
+
+
+config_dict = get_config(config.items('basicSetup'))
+config_domain_dev_dict = get_config(config.items('domain_dev'))
+config_domain_prod_dict = get_config(config.items('domain_prod'))
+
+env = config_dict["env"]
+Version = config_dict["version"]
+Account = config_dict["account"]
+LastSelectPath = config_dict["last_select_path"]
+
+
+# ============用户自定义信息获取=============
+def get_custom_config(p_value, key, _custom_config_dict):
+    if key in _custom_config_dict:
+        if _custom_config_dict[key]:
+            return _custom_config_dict[key]
+    return p_value
+
+
+try:
+    custom_config.add_section("basicSetup")
+except:
+    pass
+custom_config_dict = get_config(custom_config.items('basicSetup'))
+
+is_test = "否"
+is_test = get_custom_config(is_test, "is_test", custom_config_dict)
+is_fall_dir = ""
+is_fall_dir = get_custom_config(is_fall_dir, "is_fall_dir", custom_config_dict)
+is_fall_dir = is_fall_dir.replace(",","")
+is_fall_dir = is_fall_dir.split(",")
+is_fall_dir = [x for x in is_fall_dir if x]
+
+if "已抠图" not in is_fall_dir:
+    is_fall_dir.append("已抠图")
+
+is_fall_file = ""
+is_fall_file = get_custom_config(is_fall_file, "is_fall_file", custom_config_dict)
+is_fall_file = is_fall_file.replace(",","")
+is_fall_file = is_fall_file.split(",")
+is_fall_file = [x for x in is_fall_file if x]
+
+print("Version:",Version)
+
+if env == "dev":
+    DOMAIN = config_domain_dev_dict["domain"]
+    Host = config_domain_dev_dict["host"]
+    Origin = config_domain_dev_dict["origin"]
+else:
+    DOMAIN = config_domain_prod_dict["domain"]
+    Host = config_domain_prod_dict["host"]
+    Origin = config_domain_prod_dict["origin"]
+
+IsLogin = False
+SecretKey = "8E5EC2AC2191167DF9B753BA93A1E7B1"
+SecretIv = "0112030405060701"
+Authorization = Aes().get_authorization(Key, SecretKey, SecretIv)
+
+Headers = {
+    "Authorization": Authorization,
+    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36",
+    "Origin": Origin,
+    "Host": Host,
+    "Content-Type": "application/json;charset=UTF-8"
+}
+

+ 1 - 0
打包EXE - py39 - run1.txt

@@ -0,0 +1 @@
+pyinstaller.exe -F -w D:\MyDocuments\PythonCode\MyPython\red_dragonfly\deal_pics\image_cutout\main.py

+ 10 - 0
查询次数.txt

@@ -0,0 +1,10 @@
+SELECT
+	DATE_FORMAT(created_at,"%Y-%m-%d") as "使用日期",
+	COUNT(1) as "使用次数"
+FROM
+	`aigc_userpoints_logs` 
+WHERE
+	action_name = "客户端抠图" 
+	AND partner_company_id = 35662
+	GROUP BY DATE_FORMAT(created_at,"%Y-%m-%d")
+	ORDER BY DATE_FORMAT(created_at,"%Y-%m-%d") DESC