diff --git a/main.py b/main.py new file mode 100644 index 0000000..ac924ac --- /dev/null +++ b/main.py @@ -0,0 +1,624 @@ +from PyQt5.QtGui import QStandardItem, QStandardItemModel, QPixmap +from PyQt5.QtSql import QSqlTableModel, QSqlDatabase +from LoginUi import * +from InterfaceUi import * +from PyQt5.QtWidgets import QApplication, QMainWindow, QTableWidgetItem, QTableView, QWidget, QVBoxLayout, QComboBox, \ + QButtonGroup, QMessageBox, QRadioButton +from PyQt5.QtCore import Qt, QTimer, QTime, QDateTime +import sys +import pymysql +import random +from datetime import datetime + +user_now="" + +class LoginWindow(QMainWindow): + def __init__(self): + super().__init__() + self.ui=Ui_LoginWindow() + self.ui.setupUi(self) + #去除边框 + self.setWindowFlag(QtCore.Qt.FramelessWindowHint) + self.setAttribute(QtCore.Qt.WA_TranslucentBackground) + #阴影 + self.shadow = QtWidgets.QGraphicsDropShadowEffect(self) + self.shadow.setOffset(0,0) + self.shadow.setBlurRadius(10) + self.shadow.setColor(QtCore.Qt.black) + self.ui.frame.setGraphicsEffect(self.shadow) + #按钮切换登录和注册、以及按登录键实现页面跳转 + self.ui.login_button.clicked.connect(lambda: self.ui.stackedWidget_2.setCurrentIndex(0)) + self.ui.register_button.clicked.connect(lambda: self.ui.stackedWidget_2.setCurrentIndex(1)) + self.ui.login_sure.clicked.connect(self.login_in) + self.ui.register_sure.clicked.connect(self.register_in) + self.show() + + def mousePressEvent(self, event): + if event.button() == Qt.LeftButton: + self.drag_position = event.globalPos() - self.frameGeometry().topLeft() + event.accept() + + def mouseMoveEvent(self, event): + if event.buttons() == Qt.LeftButton: + self.move(event.globalPos() - self.drag_position) + event.accept() + + def mouseReleaseEvent(self, event): + self.drag_position = None + + #注册账号 + def register_in(self): + account = self.ui.register_account.text() + password_1 = self.ui.register_psw.text() + password_2 = self.ui.register_psw2.text() + # 判断是否输入为空 + if not account or not password_1 or not password_2: + self.ui.stackedWidget.setCurrentIndex(2) # 设置当前页面索引为空输入错误页面 + return + # 判断账号是否已存在 + try: + db = pymysql.connect(host='127.0.0.1', user='root', password='20021220', database='pybank') + cur = db.cursor() + cur.execute('select cid from customer') + rows = cur.fetchall() + db.close() + except Exception as e: + print(f"Database error: {e}") + self.ui.stackedWidget.setCurrentIndex(2) # 设置为数据库错误页面(可以调整索引) + return + # 提取所有现有账号 + existing_accounts = [row[0] for row in rows] + if account in existing_accounts: + self.ui.stackedWidget.setCurrentIndex(3) # 设置当前页面索引为账号已存在错误页面 + return + # 判断两次输入密码是否正确 + if password_1 == password_2: + try: + db = pymysql.connect(host='127.0.0.1', user='root', password='20021220', database='pybank') + cur = db.cursor() + cur.execute(f"insert into customer(cid, cpsw) values('{account}', '{password_2}')") + db.commit() # 提交事务 + db.close() + self.ui.stackedWidget.setCurrentIndex(4) # 设置当前页面索引为注册成功页面 + except Exception as e: + print(f"Database error: {e}") + self.ui.stackedWidget.setCurrentIndex(2) # 设置为数据库错误页面 + return + else: + self.ui.stackedWidget.setCurrentIndex(1) # 设置当前页面索引为密码不匹配错误页面 + return + + + #登录验证 + def login_in(self): + account = self.ui.login_account.text() + password = self.ui.login_psw.text() + # 检查输入框是否为空 + if not account or not password: + self.ui.stackedWidget.setCurrentIndex(2) # 设置当前页面索引为空输入错误页面 + return + account_list = [] + password_list = [] + try: + db = pymysql.connect(host='127.0.0.1', user='root', password='20021220', database='pybank') + cur = db.cursor() + cur.execute('select cid, cpsw from customer') + rows = cur.fetchall() + db.close() + except Exception as e: + print(f"Database error: {e}") + self.ui.stackedWidget.setCurrentIndex(2) # 设置为数据库错误页面(可以调整索引) + return + for row in rows: + account_list.append(row[0]) + password_list.append(row[1]) + # 验证账号和密码 + for i in range(len(account_list)): + if account == account_list[i] and password == password_list[i]: # 假设密码是字符串 + global user_now + user_now = account + self.win = MainWindow() + self.win.show() + self.close() + return + # 如果没有匹配成功 + self.ui.stackedWidget.setCurrentIndex(5) # 设置当前页面索引为账号或密码错误页面 + + +class MainWindow(QMainWindow): + def __init__(self): + super().__init__() + self.model = None + self.ui=Ui_MainWindow() + self.ui.setupUi(self) + self.initialize_image() #初始化图片 + try: + # 设置定时器 + self.timer = QTimer(self) + self.timer.timeout.connect(self.update_time) + self.timer.start(1000) # 每秒更新一次 + self.update_time() # 初始化时间显示 + except Exception as e: + print(e) + #去除边框 + self.setWindowFlag(QtCore.Qt.FramelessWindowHint) + self.setAttribute(QtCore.Qt.WA_TranslucentBackground) + #阴影 + self.shadow = QtWidgets.QGraphicsDropShadowEffect(self) + self.shadow.setOffset(0,0) + self.shadow.setBlurRadius(10) + self.shadow.setColor(QtCore.Qt.black) + self.ui.frame_6.setGraphicsEffect(self.shadow) + #按钮切换到各个操作面 + self.ui.logout_button.clicked.connect(self.log_out) + self.ui.pushButton_home.clicked.connect(self.home_in) + self.ui.pushButton_add.clicked.connect(self.add_in) + self.ui.pushButton_get.clicked.connect(self.get_out) + self.ui.pushButton_transfer.clicked.connect(self.transfer_in) + self.ui.pushButton_look.clicked.connect(self.look_in) + self.ui.pushButton_irt.clicked.connect(self.irt_in) + self.ui.pushButton_info.clicked.connect(self.info_in) + self.ui.pushButton_6.clicked.connect(lambda :self.ui.stackedWidget.setCurrentIndex(6)) + # 创建 tableView 属性,并将其设置为 UI 文件中的 tableView 对象 + self.tableView = self.ui.tableView # 这里的 self.ui.tableView 是 UI 文件中 tableView 对象的引用 + self.show() + + def mousePressEvent(self, event): + if event.button() == Qt.LeftButton: + self.drag_position = event.globalPos() - self.frameGeometry().topLeft() + event.accept() + + def mouseMoveEvent(self, event): + if event.buttons() == Qt.LeftButton: + self.move(event.globalPos() - self.drag_position) + event.accept() + + def mouseReleaseEvent(self, event): + self.drag_position = None + + def update_time(self): + current_time = QTime.currentTime() + self.ui.label_17.setText(current_time.toString('hh:mm:ss')) + + def update_time(self): + current_date_time = QDateTime.currentDateTime() + formatted_time = current_date_time.toString('yyyy-MM-dd hh:mm:ss dddd') + self.ui.label_17.setText(formatted_time) + + #初始化图片,应用在info中 + def initialize_image(self): + try: + pixmap = QPixmap(":/images/images/123.jpg") + self.ui.label_16.setScaledContents(True) # 让图片填充满 QLabel + self.ui.label_16.setPixmap(pixmap) + #self.ui.label_16.setPixmap(pixmap.scaled(self.ui.label_16.size(), Qt.KeepAspectRatio)) + except Exception as e: + print(f"Error loading image: {e}") + + #将account表中数据导出到home界面,使用的是tableWidget + def home_in(self): + global user_now + self.ui.stackedWidget.setCurrentIndex(0) + try: + # 连接数据库 + db = pymysql.connect(host='127.0.0.1', user='root', password='20021220', database='pybank') + cur = db.cursor() + cur.execute(f"SELECT * FROM account WHERE cid = '{user_now}'") + rows = cur.fetchall() + db.commit() + db.close() + # 填充表格数据 + for row_index, row_data in enumerate(rows): + for col_index, data in enumerate(row_data): + item = QTableWidgetItem(str(data)) + item.setFlags(item.flags() & ~Qt.ItemIsEditable) # 禁止编辑 + item.setTextAlignment(Qt.AlignCenter) #居中 + self.ui.tableWidget.setItem(row_index, col_index, item) + except Exception as e: + print(f"Database error: {e}") + # 连接数据库或执行查询时出错,可以在界面上显示相应的错误提示 + + def add_in(self): + self.ui.stackedWidget.setCurrentIndex(1) + self.ui.submit_button.clicked.connect(self.add_acc) + + def add_acc(self): + global user_now + try: + accid = self.generator_accid() + accbalance = self.ui.get_savings.text() + current_date = datetime.now().date() + acc_start = current_date.strftime('%Y-%m-%d') + cid = user_now + acctime = self.ui.deposit_time.currentText() + + # 获取 QGroupBox 中选中的 QRadioButton + typebox = self.ui.type_box + acctype = None + for button in typebox.findChildren(QRadioButton): + if button.isChecked(): + acctype = button + break + if acctype is None: + raise ValueError("未选择账户类型") + + acc_type = acctype.text() + + # 确认选择活期类型时长只能选择不定期 + if acc_type == "活期" and acctime != "不定期": + raise ValueError("活期账户的时长只能选择不定期") + + # 验证输入是否为空 + if not accbalance or not acc_type or not acctime: + raise ValueError("所有输入字段必须填写") + + accbalance_old=accbalance + accbalance=int(accbalance) + if acc_type=="定期": + if acctime=='1年': + accbalance=accbalance*(1+0.017) + elif acctime=='2年': + accbalance=accbalance*(1+0.019)**2 + elif acctime=='3年': + accbalance=accbalance*(1+0.022)**3 + else: + accbalance=accbalance*(1+0.024)**5 + # 输出到控制台 + print(accid, accbalance, acc_start, acctime, cid, acc_type) + + + # 将新账户信息插入数据库 + try: + db = pymysql.connect(host='127.0.0.1', user='root', password='20021220', database='pybank') + cur = db.cursor() + query = "INSERT INTO account (accid, accbalance, acctime_start, accdur_time, cid, acc_type) VALUES (%s, %s, %s, %s, %s, %s)" + cur.execute(query, (accid, accbalance, acc_start, acctime, cid, acc_type)) + db.commit() + db.close() + QMessageBox.information(self, "成功", "账户添加成功") + except Exception as db_error: + print(f"数据库错误: {db_error}") + QMessageBox.critical(self, "错误", "添加账户到数据库失败") + return + + # 将信息写入文件 + try: + filename = f"{user_now}.txt" + if acc_type=="定期": + s = f"用户于{acc_start},开通账号:{accid},存取金额为{accbalance_old},期限为{acctime},到期后待取金额为{accbalance:.3f}\n" + else: + s = f"用户于{acc_start},开通账号:{accid},存取金额为{accbalance_old},期限为{acctime}\n" + with open(filename, "a", encoding='UTF-8') as file: + file.write(s) + file.write("-" * 76 + "\n") + print(f"信息已写入文件: {filename}") + except Exception as file_error: + print(f"文件写入错误: {file_error}") + + # 清空输入框 + self.ui.get_savings.clear() + self.ui.deposit_time.setCurrentIndex(0) + for button in typebox.findChildren(QRadioButton): + button.setAutoExclusive(False) + button.setChecked(False) + button.setAutoExclusive(True) + + except ValueError as ve: + QMessageBox.critical(self, "错误", str(ve)) + except Exception as e: + print(e) + QMessageBox.critical(self, "错误", f"发生错误: {e}") + + def generator_accid(self): + while True: + accid = random.randint(10000, 99999) + try: + db = pymysql.connect(host='127.0.0.1', user='root', password='20021220', database='pybank') + cur = db.cursor() + cur.execute('SELECT * FROM account WHERE accid = %s', (accid,)) + rows = cur.fetchone() + if not rows: + db.close() + return accid + else: + print("Accid already exists. Generating a new one.") + db.close() + except Exception as e: + print(f"Database error: {e}") + return accid + + def get_out(self): + self.ui.stackedWidget.setCurrentIndex(2) + self.ui.sure_button1.clicked.connect(self.get_money) + + def get_money(self): + global user_now + accid=self.ui.accid_1.text() + savings=self.ui.money_1.text() + psw=self.ui.psw_sure1.text() + + self.ui.accid_1.clear() + self.ui.money_1.clear() + self.ui.psw_sure1.clear() + # 检查取款金额是否为空 + if not savings: + QMessageBox.critical(self, "错误", "请输入取款金额") + return + try: + db = pymysql.connect(host='127.0.0.1', user='root', password='20021220', database='pybank') + cur = db.cursor() + # 查询密码是否匹配 + cur.execute(f"SELECT cpsw FROM customer WHERE cid='{user_now}'") + rows = cur.fetchone() + if not rows or rows[0] != psw: + QMessageBox.critical(self, "错误", "密码错误") + db.close() + return + # 查询账户余额 + cur.execute(f"SELECT accbalance, acc_type FROM account WHERE accid='{accid}' AND cid='{user_now}'") + rows = cur.fetchone() + if not rows: + QMessageBox.critical(self, "错误", "账户不存在或不属于当前用户") + db.close() + return + accbalance, acc_type = rows + + # 检查账户类型是否是活期 + if acc_type != "活期": + QMessageBox.critical(self, "错误", "账户类型不是活期,无法取款") + db.close() + return + + # 检查余额是否足够 + if float(accbalance) < float(savings): + QMessageBox.critical(self, "错误", "账户余额不足") + db.close() + return + + # 更新账户余额 + new_balance = float(accbalance) - float(savings) + cur.execute(f"UPDATE account SET accbalance={new_balance} WHERE accid='{accid}' AND cid='{user_now}'") + db.commit() + QMessageBox.information(self, "成功", f"成功取款 {savings} 元,当前余额为 {new_balance} 元") + db.close() + + current_date = datetime.now().date() + acctime= current_date.strftime('%Y-%m-%d') + # 将信息写入文件 + try: + filename = f"{user_now}.txt" + s = f"用户于{acctime},在账户{accid},取款{savings}元,当前余额为{new_balance}元\n" + with open(filename, "a", encoding='UTF-8') as file: + file.write(s) + file.write("-" * 76 + "\n") + print(f"信息已写入文件: {filename}") + except Exception as file_error: + print(f"文件写入错误: {file_error}") + + except Exception as e: + print(f"数据库错误: {e}") + QMessageBox.critical(self, "错误", "数据库错误") + + + def transfer_in(self): + self.ui.stackedWidget.setCurrentIndex(3) + self.ui.sure_button2.clicked.connect(self.transfer) + + def transfer(self): + out_account = self.ui.out_accid.text() + in_account = self.ui.in_accid.text() + out_saving = self.ui.out_money.text() + psw = self.ui.sure_psw2.text() + + self.ui.out_accid.clear() + self.ui.in_accid.clear() + self.ui.out_money.clear() + self.ui.sure_psw2.clear() + + # 检查输入是否为空 + if not out_account or not in_account or not out_saving or not psw: + QMessageBox.critical(self, "错误", "请输入完整信息") + return + + try: + db = pymysql.connect(host='127.0.0.1', user='root', password='20021220', database='pybank') + cur = db.cursor() + + # 查询密码是否匹配 + cur.execute(f"SELECT cpsw FROM customer WHERE cid='{user_now}'") + rows = cur.fetchone() + if not rows or rows[0] != psw: + QMessageBox.critical(self, "错误", "密码错误") + db.close() + return + + # 查询转出账号是否存在并且是活期类型 + cur.execute( + f"SELECT accbalance FROM account WHERE accid='{out_account}' AND cid='{user_now}' AND acc_type='活期'") + rows = cur.fetchone() + if not rows: + QMessageBox.critical(self, "错误", "转出账号不存在或不是活期类型") + db.close() + return + out_balance = float(rows[0]) + + # 检查转出金额是否大于转出账号余额 + if float(out_saving) > out_balance: + QMessageBox.critical(self, "错误", "转出账号余额不足") + db.close() + return + + # 查询收款账号是否存在并且是活期类型 + cur.execute(f"SELECT acc_type FROM account WHERE accid='{in_account}' AND acc_type='活期'") + rows = cur.fetchone() + if not rows: + QMessageBox.critical(self, "错误", "收款账号不存在或不是活期类型") + db.close() + return + + # 更新转出账号余额和收款账号余额 + new_out_balance = out_balance - float(out_saving) + cur.execute( + f"UPDATE account SET accbalance={new_out_balance} WHERE accid='{out_account}' AND cid='{user_now}'") + cur.execute(f"UPDATE account SET accbalance=accbalance+{out_saving} WHERE accid='{in_account}'") + + # 获取收款账号所属用户的cid和新余额 + cur.execute(f"SELECT cid FROM account WHERE accid='{in_account}'") + row = cur.fetchone() + if not row: + QMessageBox.critical(self, "错误", "获取收款账号信息失败") + db.close() + return + recipient_cid = row[0] + + cur.execute(f"SELECT accbalance FROM account WHERE accid='{in_account}'") + row = cur.fetchone() + if not row: + QMessageBox.critical(self, "错误", "获取收款账号余额失败") + db.close() + return + new_in_balance = float(row[0]) + + db.commit() + QMessageBox.information(self, "成功", f"成功转账 {out_saving} 元到账户 {in_account}") + db.close() + + # 写入转账信息到文件 + try: + current_date = datetime.now().date() + acctime = current_date.strftime('%Y-%m-%d') + filename1 = f"{user_now}.txt" + filename2 = f"{recipient_cid}.txt" + out_info = f"用户于{acctime},账号:{out_account}转给{in_account}, {out_saving}元,当前余额为{new_out_balance}元\n" + in_info = f"用户于{acctime},账号:{in_account} 收到{out_saving}元,当前余额为{new_in_balance}元\n" + + with open(filename1, "a", encoding='UTF-8') as file1: + file1.write(out_info) + file1.write("-" * 76 + "\n") + with open(filename2, "a", encoding='UTF-8') as file2: + file2.write(in_info) + file2.write("-" * 76 + "\n") + print(f"信息已写入文件: {filename1} 和 {filename2}") + except Exception as file_error: + print(f"文件写入错误: {file_error}") + + except Exception as e: + print(f"数据库错误: {e}") + QMessageBox.critical(self, "错误", "数据库错误") + + def look_in(self): + try: + global user_now + self.ui.stackedWidget.setCurrentIndex(4) + textname=f"{user_now}.txt" + with open(textname,'r',encoding='utf-8') as f: + f.seek(0) + str=f.read() + self.ui.textEdit.setPlainText(str) + except Exception as e: + print(e) + + def irt_in(self): + self.ui.stackedWidget.setCurrentIndex(5) + try: + # 连接数据库 + db = pymysql.connect(host='127.0.0.1', user='root', password='20021220', database='pybank') + cur = db.cursor() + cur.execute("SELECT * FROM irt") + rows = cur.fetchall() + db.commit() + db.close() + # 设置表格行数 + self.ui.tableWidget_2.setRowCount(len(rows)) + # 填充表格数据 + for row_index, row_data in enumerate(rows): + for col_index, data in enumerate(row_data): + item = QTableWidgetItem(str(data)) + item.setFlags(item.flags() & ~Qt.ItemIsEditable) # 禁止编辑 + item.setTextAlignment(Qt.AlignCenter) # 居中 + self.ui.tableWidget_2.setItem(row_index, col_index, item) + except Exception as e: + print(f"Database error: {e}") + # 连接数据库或执行查询时出错,可以在界面上显示相应的错误提示 + + def info_in(self): + try: + # 切换到包含 QTableView 的页面 + self.ui.stackedWidget.setCurrentIndex(7) + # 设置模型 + self.model = QStandardItemModel(0, 7) + self.model.setHorizontalHeaderLabels(['身份证号', '姓名', '性别', '年龄', '电话号码', '户籍', '密码']) + self.tableView.setModel(self.model) + # 加载数据 + self.load_data() + # 使表格可编辑 + self.tableView.setEditTriggers(QTableView.AllEditTriggers) + # 捕捉模型数据改变信号 + self.model.itemChanged.connect(self.update_database) + except Exception as e: + print(f"Error in info_in: {e}") + + # 连接 MySQL 并获取数据 + def load_data(self): + global user_now + try: + connection = pymysql.connect( + host='127.0.0.1', + user='root', + password='20021220', + database='pybank' + ) + cursor = connection.cursor() + cursor.execute(f"SELECT * FROM customer where cid='{user_now}'") + data = cursor.fetchall() + cursor.close() + connection.close() + for row in data: + items = [QStandardItem(str(field)) for field in row] + for item in items: + item.setTextAlignment(Qt.AlignCenter) + self.model.appendRow(items) + except Exception as e: + print(f"Error loading data: {e}") + def update_database(self, item): + row = item.row() + col = item.column() + new_value = item.text() + print(row, col, new_value) + try: + # 获取主键(第一列是主键) + primary_key = self.model.item(row, 0).text() + # 映射列名 + columns = ['cid', 'cname', 'csex', 'cage', 'cnumber', 'caddress', 'cpsw'] + column_name = columns[col] + # 更新数据库 + connection = pymysql.connect( + host='127.0.0.1', + user='root', + password='20021220', + database='pybank' + ) + cursor = connection.cursor() + query = f"UPDATE customer SET {column_name} = %s WHERE cid = %s" + cursor.execute(query, (new_value, primary_key)) + connection.commit() + cursor.close() + connection.close() + print(f"Updated row {row}, column {col} with new value {new_value}") + except Exception as e: + print(f"Error updating database: {e}") + + + #退出当前账号回到登录界面 + def log_out(self): + global user_now + self.close() + self.login = LoginWindow() + user_now = "" + + + +if __name__ == '__main__': + app = QApplication(sys.argv) + win = LoginWindow() + sys.exit(app.exec_())