给姐姐家店写的一个,功能比较简单,结合gpt
功能包含:次卡和充值卡,可以查剩余次数、以及查找消费记录
···后期会把sqlite3转到mysql,换成springboot的一个项目
1.使用技术:
Python、sqlite3、PyQt5
2.页面
3.sqlite3
一共三张数据表:
- user_card : 次卡数据
- user_store : 储蓄卡
- consumption: 消费记录表
消费记录为了省事,包含了所有的记录,
4.代码(主要部分)
python
import re
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QLineEdit, QPushButton, QVBoxLayout, QHBoxLayout, \
QTableWidget, QTableWidgetItem, QHeaderView, QMessageBox, QDialog, QFormLayout, QInputDialog, QMainWindow
from PyQt5.QtGui import QColor, QPalette, QImage, QPixmap, QBrush, QPainter
from PyQt5.QtCore import Qt, QDate, QDateTime
import sqlite3
class BackgroundWidget(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
# self.image_path = "image/background.png"
self.image_path = "image/panda.png"
def paintEvent(self, event):
painter = QPainter(self)
painter.setRenderHint(QPainter.Antialiasing)
# 绘制背景图片
background_image = QImage(self.image_path)
background_image = background_image.scaled(self.size(), Qt.IgnoreAspectRatio, Qt.SmoothTransformation)
painter.drawImage(0, 0, background_image)
# 绘制半透明遮罩层
opacity = 0.6
overlay_color = QColor(0, 0, 0, int(255 * opacity))
painter.setCompositionMode(QPainter.CompositionMode_DestinationOver)
painter.fillRect(self.rect(), overlay_color)
super().paintEvent(event)
class ConsumeCard(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("理发店收银系统")
self.resize(1200, 800)
# 创建数据库连接
self.connection = sqlite3.connect("db/barbershop.db")
self.cursor = self.connection.cursor()
# 创建界面控件
self.id_label = QLabel("ID:")
self.id_input = QLineEdit()
self.name_label = QLabel("姓名:")
self.name_input = QLineEdit()
self.tel_label = QLabel("电话:")
self.tel_input = QLineEdit()
self.remain_label = QLabel("次数:")
self.remain_input = QLineEdit()
self.remark_label = QLabel("备注:")
self.remark_input = QLineEdit()
# self.discount_label = QLabel("折扣:")
# self.discount_input = QLineEdit()
self.create_user_button = QPushButton("新建用户")
self.search_label = QLabel("查询(ID或电话):")
self.search_input = QLineEdit()
self.search_button = QPushButton("查询")
self.clear_button = QPushButton("清除")
self.recharge_button = QPushButton("充值")
self.consume_button = QPushButton("消费")
# self.record_button = QPushButton("消费记录")
self.consumption_record_button = QPushButton("消费记录")
self.user_table = QTableWidget()
# 设置布局
form_layout = QFormLayout()
# form_layout.addRow(self.id_label, self.id_input)
form_layout.addRow(self.name_label, self.name_input)
form_layout.addRow(self.tel_label, self.tel_input)
form_layout.addRow(self.remain_label, self.remain_input)
form_layout.addRow(self.remark_label, self.remark_input)
# form_layout.addRow(self.discount_label, self.discount_input)
button_layout = QHBoxLayout()
button_layout.addWidget(self.create_user_button)
button_layout.addWidget(self.search_label)
button_layout.addWidget(self.search_input)
button_layout.addWidget(self.search_button)
button_layout.addWidget(self.clear_button)
button_layout.addWidget(self.recharge_button)
button_layout.addWidget(self.consume_button)
button_layout.addWidget(self.consumption_record_button)
main_layout = QVBoxLayout()
main_layout.addLayout(form_layout)
main_layout.addLayout(button_layout)
main_layout.addWidget(self.user_table)
self.setLayout(main_layout)
# 绑定信号与槽函数
self.create_user_button.clicked.connect(self.create_user)
self.search_button.clicked.connect(self.search_user)
self.clear_button.clicked.connect(self.clear)
self.recharge_button.clicked.connect(self.recharge)
self.consume_button.clicked.connect(self.consume)
# self.record_button.clicked.connect(self.show_consumption_records)
self.consumption_record_button.clicked.connect(self.show_consumption_record)
# 初始化用户表格
self.init_user_table()
# 当前选中的用户信息
self.current_user = None
background_widget = BackgroundWidget()
background_widget.setLayout(main_layout)
self.setCentralWidget(background_widget)
self.setAttribute(Qt.WA_TranslucentBackground) # 设置窗口背景透明
# 设置样式
self.setStyleSheet(
)
def set_background_image(self, image_path):
background_image = QImage(image_path)
background_image = background_image.scaled(self.size(), Qt.IgnoreAspectRatio, Qt.SmoothTransformation)
palette = QPalette()
palette.setBrush(QPalette.Background, QBrush(background_image))
self.setPalette(palette)
def init_user_table(self):
self.user_table.setColumnCount(5)
self.user_table.setHorizontalHeaderLabels(["ID", "姓名", "电话", "剩余次数", "备注"])
self.user_table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
self.user_table.setSelectionBehavior(QTableWidget.SelectRows)
self.user_table.setEditTriggers(QTableWidget.NoEditTriggers)
self.user_table.cellClicked.connect(self.show_user_info)
self.update_user_table()
def update_user_table(self):
self.user_table.clearContents()
self.cursor.execute("SELECT id, name, tel, remain, remark FROM user_card")
users = self.cursor.fetchall()
self.user_table.setRowCount(len(users))
for i, user in enumerate(users):
for j in range(len(user)):
item = QTableWidgetItem(str(user[j]))
item.setTextAlignment(Qt.AlignCenter)
self.user_table.setItem(i, j, item)
def show_user_info(self, row):
self.id_input.setText(self.user_table.item(row, 0).text())
self.name_input.setText(self.user_table.item(row, 1).text())
self.tel_input.setText(self.user_table.item(row, 2).text())
self.remain_input.setText(self.user_table.item(row, 3).text())
self.remark_input.setText(self.user_table.item(row, 4).text())
# self.discount_input.setText(self.user_table.item(row, 5).text())
# 存储选中的用户信息
self.current_user = {
'id': self.user_table.item(row, 0).text(),
'name': self.user_table.item(row, 1).text(),
'tel': self.user_table.item(row, 2).text(),
'remain': self.user_table.item(row, 3).text(),
'remark': self.user_table.item(row, 4).text(),
# 'discount': self.user_table.item(row, 5).text()
}
def create_user(self):
name = self.name_input.text()
tel = self.tel_input.text()
remain = self.remain_input.text()
remark = self.remark_input.text()
# discount = self.discount_input.text()
if not name or not tel or not remain:
QMessageBox.warning(self, "错误", "请填写完整用户信息")
return
try:
remain = int(remain)
# discount = float(discount)
except ValueError:
QMessageBox.warning(self, "错误", "次数必须是数字")
return
# 验证手机号格式
if not self.validate_phone_number(tel):
QMessageBox.warning(self, "错误", "手机号格式错误")
return
# 检查是否已经存在该手机号的用户
self.cursor.execute("SELECT id FROM user_card WHERE tel = ?", (tel,))
existing_user = self.cursor.fetchone()
if existing_user:
QMessageBox.warning(self, "错误", "已存在该用户手机号")
return
current_datetime = QDateTime.currentDateTime()
formatted_datetime = current_datetime.toString(Qt.ISODate)
formatted_datetime = formatted_datetime[:10] + " " + formatted_datetime[11:]
self.cursor.execute("INSERT INTO consumption_record (name, tel, consumption, balance, consumption_time, remark) "
"VALUES (?, ?, ?, ?, ?, ?)",
(name, tel, remain, remain, formatted_datetime, remark))
self.cursor.execute("INSERT INTO user_card (name, tel, remain, remark) "
"VALUES (?, ?, ?, ?)",
(name, tel, remain, remark))
self.connection.commit()
self.update_user_table()
self.clear()
QMessageBox.information(self, "成功", "用户创建成功")
# 验证手机号
def validate_phone_number(self, phone_number):
pattern = r"^1[3-9]\d{9}$"
return re.match(pattern, phone_number) is not None
def search_user(self):
keyword = self.search_input.text()
self.cursor.execute(
"SELECT id, name, tel, remain, remark FROM user_card WHERE id LIKE ? OR name like ? OR tel LIKE ?",
(f"%{keyword}%", f"%{keyword}%", f"%{keyword}%"))
users = self.cursor.fetchall()
if len(users) == 0:
QMessageBox.warning(self, "错误", "未找到用户")
return
self.user_table.clearContents()
self.user_table.setRowCount(len(users))
for i, user in enumerate(users):
for j in range(len(user)):
item = QTableWidgetItem(str(user[j]))
item.setTextAlignment(Qt.AlignCenter)
self.user_table.setItem(i, j, item)
def clear(self):
self.id_input.clear()
self.name_input.clear()
self.tel_input.clear()
self.remain_input.clear()
self.remark_input.clear()
# self.discount_input.clear()
self.user_table.clearSelection()
# 重置当前选中的用户信息
self.current_user = None
def recharge(self):
if self.current_user is None:
QMessageBox.warning(self, "错误", "请先选择用户")
return
id = self.current_user['id']
name = self.current_user['name']
tel = self.current_user['tel']
remain = self.current_user['remain']
remark = self.current_user['remark']
# amount, ok = QInputDialog.getDouble(self, "充值", "请输入充值次数:", decimals=2)
amount, ok = QInputDialog.getInt(self, "充值", "请输入充值次数:")
if ok and amount > 0:
self.cursor.execute("UPDATE user_card SET remain = remain + ? WHERE id = ?", (amount, id))
try:
remain = int(remain)
amount = int(amount)
except ValueError:
QMessageBox.warning(self, "错误", "余额和折扣必须是数字")
return
current_datetime = QDateTime.currentDateTime()
formatted_datetime = current_datetime.toString(Qt.ISODate)
formatted_datetime = formatted_datetime[:10] + " " + formatted_datetime[11:]
self.cursor.execute("INSERT INTO consumption_record (name, tel, consumption, balance, consumption_time, remark) "
"VALUES (?, ?, ?, ?, ?, ?)",
(name, tel, amount, remain + amount, formatted_datetime, remark))
self.connection.commit()
self.update_user_table()
self.clear()
QMessageBox.information(self, "成功", "充值成功")
# 重置当前选中的用户信息
self.current_user = None
def consume(self):
if self.current_user is None:
QMessageBox.warning(self, "错误", "请先选择用户")
return
id = self.current_user['id']
name = self.current_user['name']
tel = self.current_user['tel']
remain = self.current_user['remain']
remark = self.current_user['remark']
# amount, ok = QInputDialog.getDouble(self, "消费", "请输入消费金额:", decimals=2)
amount, ok = QInputDialog.getInt(self, "消费", "请输入消费金额:")
if ok and amount > 0:
# self.cursor.execute("SELECT discount FROM user_card WHERE id = ?", (id,))
# discount = self.cursor.fetchone()[0]
try:
remain = int(remain)
# discount = float(discount)
amount = int(amount)
except ValueError:
QMessageBox.warning(self, "错误", "余额和折扣必须是数字")
return
# amount *= discount
if remain < amount:
QMessageBox.warning(self, "错误", "余额不足")
return
self.cursor.execute("UPDATE user_card SET remain = remain - ? WHERE id = ?", (amount, id))
current_datetime = QDateTime.currentDateTime()
formatted_datetime = current_datetime.toString(Qt.ISODate)
formatted_datetime = formatted_datetime[:10] + " " + formatted_datetime[11:]
self.cursor.execute(
"INSERT INTO consumption_record (name, tel, consumption, balance, consumption_time, remark) "
"VALUES (?, ?, ?, ?, ?, ?)",
(name, tel, -amount, remain - amount, formatted_datetime, remark))
self.connection.commit()
self.update_user_table()
self.clear()
QMessageBox.information(self, "成功", "消费成功")
# 重置当前选中的用户信息
self.current_user = None
def show_consumption_record(self):
if self.current_user is None:
QMessageBox.warning(self, "错误", "请先选择用户")
return
tel = self.current_user['tel']
self.cursor.execute(
"SELECT id, name, tel, consumption, balance, consumption_time, remark FROM consumption_record WHERE tel = ?",
(tel,))
records = self.cursor.fetchall()
dialog = QDialog(self)
dialog.setWindowTitle("消费记录")
dialog.resize(1400, 600)
table = QTableWidget(dialog)
table.setColumnCount(6)
table.setHorizontalHeaderLabels(["姓名", "电话", "消费", "剩余次数", "消费时间", "备注"])
table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
table.setSelectionBehavior(QTableWidget.SelectRows)
table.setEditTriggers(QTableWidget.NoEditTriggers)
table.setRowCount(len(records))
for i, record in enumerate(records):
for j in range(1, len(record)):
item = QTableWidgetItem(str(record[j]))
item.setTextAlignment(Qt.AlignCenter)
table.setItem(i, j - 1, item)
main_layout = QVBoxLayout()
main_layout.addWidget(table)
dialog.setLayout(main_layout)
dialog.exec_()
# def get_consumption_records(self, phone_number):
# self.cursor.execute("SELECT * FROM consumption_record WHERE tel=?",
# (phone_number,))
# return self.cursor.fetchall()
def closeEvent(self, event):
self.connection.close()
if __name__ == '__main__':
app = QApplication(sys.argv)
cashier = ConsumeCard()
cashier.show()
sys.exit(app.exec_())