出入库记录上线
This commit is contained in:
		
							
								
								
									
										120
									
								
								main.py
									
									
									
									
									
								
							
							
						
						
									
										120
									
								
								main.py
									
									
									
									
									
								
							@@ -588,6 +588,9 @@ class MainWindow(QMainWindow):
 | 
				
			|||||||
        # 白名单存储
 | 
					        # 白名单存储
 | 
				
			||||||
        self.whitelist = set()  # 存储白名单车牌号
 | 
					        self.whitelist = set()  # 存储白名单车牌号
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
 | 
					        # 出入库记录存储
 | 
				
			||||||
 | 
					        self.parking_records = []  # 存储所有出入库记录
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
        # 帧率检测相关
 | 
					        # 帧率检测相关
 | 
				
			||||||
        self.frame_times = deque(maxlen=30)  # 存储最近30帧的时间戳
 | 
					        self.frame_times = deque(maxlen=30)  # 存储最近30帧的时间戳
 | 
				
			||||||
        self.current_fps = 30.0  # 默认帧率
 | 
					        self.current_fps = 30.0  # 默认帧率
 | 
				
			||||||
@@ -918,11 +921,53 @@ class MainWindow(QMainWindow):
 | 
				
			|||||||
        control_layout.addWidget(whitelist_group)
 | 
					        control_layout.addWidget(whitelist_group)
 | 
				
			||||||
        control_layout.addWidget(manual_group)
 | 
					        control_layout.addWidget(manual_group)
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
 | 
					        # 出入库记录显示区域
 | 
				
			||||||
 | 
					        records_frame = QFrame()
 | 
				
			||||||
 | 
					        records_frame.setFrameStyle(QFrame.StyledPanel)
 | 
				
			||||||
 | 
					        records_frame.setStyleSheet("""
 | 
				
			||||||
 | 
					            QFrame {
 | 
				
			||||||
 | 
					                background-color: #f8f9fa;
 | 
				
			||||||
 | 
					                border: 1px solid #dee2e6;
 | 
				
			||||||
 | 
					                border-radius: 8px;
 | 
				
			||||||
 | 
					                padding: 10px;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        """)
 | 
				
			||||||
 | 
					        records_layout = QVBoxLayout(records_frame)
 | 
				
			||||||
 | 
					        records_layout.setSpacing(8)
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        # 记录标题
 | 
				
			||||||
 | 
					        records_title = QLabel("出入库记录")
 | 
				
			||||||
 | 
					        records_title.setFont(QFont("Microsoft YaHei", 11, QFont.Bold))
 | 
				
			||||||
 | 
					        records_title.setStyleSheet("QLabel { color: #495057; margin-bottom: 5px; }")
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        # 记录滚动区域
 | 
				
			||||||
 | 
					        records_scroll = QScrollArea()
 | 
				
			||||||
 | 
					        records_scroll.setWidgetResizable(True)
 | 
				
			||||||
 | 
					        records_scroll.setMaximumHeight(200)
 | 
				
			||||||
 | 
					        records_scroll.setStyleSheet("""
 | 
				
			||||||
 | 
					            QScrollArea { 
 | 
				
			||||||
 | 
					                border: 1px solid #e9ecef; 
 | 
				
			||||||
 | 
					                background-color: white; 
 | 
				
			||||||
 | 
					                border-radius: 4px;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        """)
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        self.records_widget = QWidget()
 | 
				
			||||||
 | 
					        self.records_layout = QVBoxLayout(self.records_widget)
 | 
				
			||||||
 | 
					        self.records_layout.setAlignment(Qt.AlignTop)
 | 
				
			||||||
 | 
					        self.records_layout.setSpacing(2)
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        records_scroll.setWidget(self.records_widget)
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        records_layout.addWidget(records_title)
 | 
				
			||||||
 | 
					        records_layout.addWidget(records_scroll)
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
        right_layout.addWidget(title_label)
 | 
					        right_layout.addWidget(title_label)
 | 
				
			||||||
        right_layout.addLayout(method_layout)
 | 
					        right_layout.addLayout(method_layout)
 | 
				
			||||||
        right_layout.addWidget(self.count_label)
 | 
					        right_layout.addWidget(self.count_label)
 | 
				
			||||||
        right_layout.addWidget(scroll_area)
 | 
					        right_layout.addWidget(scroll_area)
 | 
				
			||||||
        right_layout.addWidget(control_frame)
 | 
					        right_layout.addWidget(control_frame)
 | 
				
			||||||
 | 
					        right_layout.addWidget(records_frame)
 | 
				
			||||||
        right_layout.addWidget(self.current_method_label)
 | 
					        right_layout.addWidget(self.current_method_label)
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        # 添加到主布局
 | 
					        # 添加到主布局
 | 
				
			||||||
@@ -1528,7 +1573,7 @@ class MainWindow(QMainWindow):
 | 
				
			|||||||
                # 显示费用确认对话框
 | 
					                # 显示费用确认对话框
 | 
				
			||||||
                if self.show_parking_fee_dialog(plate_number, time_diff):
 | 
					                if self.show_parking_fee_dialog(plate_number, time_diff):
 | 
				
			||||||
                    # 用户确认缴费,发送时间间隔命令
 | 
					                    # 用户确认缴费,发送时间间隔命令
 | 
				
			||||||
                    message = f"{plate_number} {int(time_diff)}sec"
 | 
					                    message = f"{plate_number} {int(time_diff)}seconds"
 | 
				
			||||||
                    try:
 | 
					                    try:
 | 
				
			||||||
                        send_command(1, message)
 | 
					                        send_command(1, message)
 | 
				
			||||||
                        print(f"发送道闸命令: {message}")
 | 
					                        print(f"发送道闸命令: {message}")
 | 
				
			||||||
@@ -1539,6 +1584,10 @@ class MainWindow(QMainWindow):
 | 
				
			|||||||
                            'command_sent': True
 | 
					                            'command_sent': True
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                        
 | 
					                        
 | 
				
			||||||
 | 
					                        # 计算并记录出库信息(包含缴费金额)
 | 
				
			||||||
 | 
					                        fee_amount = self.calculate_parking_fee(time_diff)
 | 
				
			||||||
 | 
					                        self.add_parking_record(plate_number, 'exit', fee_amount)
 | 
				
			||||||
 | 
					                        
 | 
				
			||||||
                        # 清除记录,使第三次识别时重新按首次处理
 | 
					                        # 清除记录,使第三次识别时重新按首次处理
 | 
				
			||||||
                        del self.plate_records[plate_number]
 | 
					                        del self.plate_records[plate_number]
 | 
				
			||||||
                        
 | 
					                        
 | 
				
			||||||
@@ -1566,6 +1615,9 @@ class MainWindow(QMainWindow):
 | 
				
			|||||||
                        'command_sent': True
 | 
					                        'command_sent': True
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    
 | 
					                    
 | 
				
			||||||
 | 
					                    # 记录入库信息
 | 
				
			||||||
 | 
					                    self.add_parking_record(plate_number, 'entry')
 | 
				
			||||||
 | 
					                    
 | 
				
			||||||
                    # 记录车牌信息,等待二次识别
 | 
					                    # 记录车牌信息,等待二次识别
 | 
				
			||||||
                    self.plate_records[plate_number] = {
 | 
					                    self.plate_records[plate_number] = {
 | 
				
			||||||
                        'first_time': current_time,
 | 
					                        'first_time': current_time,
 | 
				
			||||||
@@ -1665,6 +1717,72 @@ class MainWindow(QMainWindow):
 | 
				
			|||||||
        else:
 | 
					        else:
 | 
				
			||||||
            return False  # 未缴费或取消,拒绝开闸
 | 
					            return False  # 未缴费或取消,拒绝开闸
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					    def add_parking_record(self, plate_number, record_type, fee_amount=0):
 | 
				
			||||||
 | 
					        """添加出入库记录"""
 | 
				
			||||||
 | 
					        record = {
 | 
				
			||||||
 | 
					            'plate_number': plate_number,
 | 
				
			||||||
 | 
					            'type': record_type,  # 'entry' 或 'exit'
 | 
				
			||||||
 | 
					            'timestamp': datetime.now(),
 | 
				
			||||||
 | 
					            'fee_amount': fee_amount
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        self.parking_records.append(record)
 | 
				
			||||||
 | 
					        self.update_parking_records_display()
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    def update_parking_records_display(self):
 | 
				
			||||||
 | 
					        """更新出入库记录显示"""
 | 
				
			||||||
 | 
					        # 清空现有记录显示
 | 
				
			||||||
 | 
					        for i in reversed(range(self.records_layout.count())):
 | 
				
			||||||
 | 
					            child = self.records_layout.itemAt(i).widget()
 | 
				
			||||||
 | 
					            if child:
 | 
				
			||||||
 | 
					                child.setParent(None)
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        # 显示最近的20条记录
 | 
				
			||||||
 | 
					        recent_records = self.parking_records[-20:] if len(self.parking_records) > 20 else self.parking_records
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        for record in reversed(recent_records):  # 最新记录在上方
 | 
				
			||||||
 | 
					            record_widget = self.create_record_widget(record)
 | 
				
			||||||
 | 
					            self.records_layout.addWidget(record_widget)
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    def create_record_widget(self, record):
 | 
				
			||||||
 | 
					        """创建单条记录的显示widget"""
 | 
				
			||||||
 | 
					        widget = QFrame()
 | 
				
			||||||
 | 
					        widget.setFrameStyle(QFrame.Box)
 | 
				
			||||||
 | 
					        widget.setStyleSheet("""
 | 
				
			||||||
 | 
					            QFrame {
 | 
				
			||||||
 | 
					                background-color: #f8f9fa;
 | 
				
			||||||
 | 
					                border: 1px solid #dee2e6;
 | 
				
			||||||
 | 
					                border-radius: 5px;
 | 
				
			||||||
 | 
					                margin: 2px;
 | 
				
			||||||
 | 
					                padding: 5px;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        """)
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        layout = QVBoxLayout(widget)
 | 
				
			||||||
 | 
					        layout.setContentsMargins(8, 5, 8, 5)
 | 
				
			||||||
 | 
					        layout.setSpacing(3)
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        # 车牌号和类型
 | 
				
			||||||
 | 
					        type_text = "入库" if record['type'] == 'entry' else "出库"
 | 
				
			||||||
 | 
					        type_color = "#28a745" if record['type'] == 'entry' else "#dc3545"
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        header_label = QLabel(f"<b style='color: {type_color}'>{type_text}</b> - {record['plate_number']}")
 | 
				
			||||||
 | 
					        header_label.setStyleSheet("font-size: 12px; font-weight: bold;")
 | 
				
			||||||
 | 
					        layout.addWidget(header_label)
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        # 时间
 | 
				
			||||||
 | 
					        time_str = record['timestamp'].strftime("%Y-%m-%d %H:%M:%S")
 | 
				
			||||||
 | 
					        time_label = QLabel(f"时间: {time_str}")
 | 
				
			||||||
 | 
					        time_label.setStyleSheet("font-size: 10px; color: #6c757d;")
 | 
				
			||||||
 | 
					        layout.addWidget(time_label)
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        # 费用(仅出库记录显示)
 | 
				
			||||||
 | 
					        if record['type'] == 'exit' and record['fee_amount'] > 0:
 | 
				
			||||||
 | 
					            fee_label = QLabel(f"缴费金额: ¥{record['fee_amount']:.2f}")
 | 
				
			||||||
 | 
					            fee_label.setStyleSheet("font-size: 10px; color: #fd7e14; font-weight: bold;")
 | 
				
			||||||
 | 
					            layout.addWidget(fee_label)
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        return widget
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
    def closeEvent(self, event):
 | 
					    def closeEvent(self, event):
 | 
				
			||||||
        """窗口关闭事件"""
 | 
					        """窗口关闭事件"""
 | 
				
			||||||
        if self.camera_thread and self.camera_thread.running:
 | 
					        if self.camera_thread and self.camera_thread.running:
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										5
									
								
								parking_config.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								parking_config.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					    "free_parking_duration": 5,
 | 
				
			||||||
 | 
					    "billing_cycle": 3,
 | 
				
			||||||
 | 
					    "price_per_cycle": 5.0
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user