吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 9494|回复: 155
收起左侧

[原创工具] 用python实现美容院会员储值管理系统【4月22日更新】

    [复制链接]
Hell 发表于 2023-7-27 16:55
本帖最后由 Hell 于 2024-4-22 11:14 编辑

【2024年4月22日更新】
更新了很多功能,包括UI界面、销售功能、库存管理等。
其中微信预约、微信消息推送功能也支持,只是比较复杂,删除了此部分的功能代码,需要微信消息推送功能的朋友可以留言私信交流一下 。
慢慢探索。
打包了新的部署说明,小白也能看懂如何部署!
源码+打包成品链接:


链接:https://pan.baidu.com/s/1A7WQkWGLKRmQ4cf7wbs5gA?pwd=pugf
提取码:pugf


1.jpg 2.jpg 3.jpg
-------------【2023年8月9日更新】---------------------------------------------------------------------------------------------------------------------
更新内容:
1、数据库,移除本地数据库,更改成云数据库。需要更改代码中的:
[Python] 纯文本查看 复制代码
# 创建数据库连接
        conn = pymysql.connect(host='你数据库IP地址', user='登录名', password='登陆密码', db='表名', connect_timeout=60)
        cursor = conn.cursor()

2、增加系统设置,允许修改密码、注销、退出等
3、选择行高亮显示
4、增加按钮快捷键
5、增加冲账功能
6、优化消费逻辑,消费项目会判断是否购买了该项目,购买了就会扣减次数,如未购买则按单次价格收费
7、不记得了。。自己体验吧!
部署方法:
1、创建一台服务器,阿里云、华为云都可以。
2、导入数据库文件
123.png
3、更改源码中的链接数据库信息
[Python] 纯文本查看 复制代码
# 创建数据库连接
conn = pymysql.connect(host='你数据库IP地址', user='登录名', password='登陆密码', db='表名', connect_timeout=60)
cursor = conn.cursor()

4、打包源码成exe文件,打包命令这源码里面
[Python] 纯文本查看 复制代码
pyinstaller --onefile --noconsole --icon=icon.ico crm.py


1.jpg 2.jpg 4.jpg 5.jpg



------------------【7月27日】-----------------------------分割线--------------------------------------------------------
简单实现美容院会员管理系统
1、实现会员基本资料管理
2、实现会员充值、消费管理
3、实现美容项目管理
4、本地数据库,带有数据库备份功能

默认帐号:admin 密码:123

1.jpg 2.jpg 3.jpg
[Python] 纯文本查看 复制代码
import sys
from PyQt5.QtWidgets import QApplication,QDateEdit,QDialog,QMainWindow,QDateTimeEdit, QLabel, QComboBox,QGridLayout,QDialog, QWidget, QTableWidget, QTableWidgetItem, QPushButton, QVBoxLayout, QHBoxLayout, QLineEdit, QMessageBox, QTabWidget,QFileDialog
from PyQt5.QtCore import Qt,QDate
from PyQt5.QtGui import QFont
import sqlite3
import re
import os
import shutil
import openpyxl
from datetime import datetime
import glob

# 建立数据库连接
conn = sqlite3.connect('members.db')
cursor = conn.cursor()
# 创建会员表
cursor.execute('''CREATE TABLE IF NOT EXISTS members (
                    id INTEGER PRIMARY KEY AUTOINCREMENT,
                    name TEXT NOT NULL,
                    phone TEXT NOT NULL,
                    register_date TEXT NOT NULL,
                    last_consume_date TEXT,
                    birthday DATE,
                    balance REAL,
                    remark TEXT
                )''')
# 创建充值/消费记录表
cursor.execute('''CREATE TABLE IF NOT EXISTS transactions (
                    id INTEGER PRIMARY KEY AUTOINCREMENT,
                    member_id INTEGER,
                    amount REAL,
                    transaction_date TEXT,
                    remark TEXT,
                    project TEXT,
                    balance REAL, 
                    clerk_id INTEGER,
                    FOREIGN KEY (member_id) REFERENCES members (id)
                )''')
# 创建美容项目表
cursor.execute('''CREATE TABLE IF NOT EXISTS beauty_projects (
                    id INTEGER PRIMARY KEY AUTOINCREMENT,
                    name TEXT NOT NULL,
                    times INTEGER NOT NULL,
                    datetime TEXT,
                    remark TEXT
                )''')

# 创建会员美容项目表
cursor.execute('''CREATE TABLE IF NOT EXISTS member_beauty_projects (
                    member_id INTEGER,
                    beauty_project_id INTEGER,
                    sessions INTEGER,
                    FOREIGN KEY (member_id) REFERENCES members (id),
                    FOREIGN KEY (beauty_project_id) REFERENCES beauty_projects (id)
                )''')
#创建营业员表
cursor.execute("CREATE TABLE IF NOT EXISTS clerks (id INTEGER PRIMARY KEY, name TEXT,is_deleted INTEGER DEFAULT 0)")

search_entry = None
search_table = None
transaction_table = None
transaction_member_entry = None
#备份数据库
def backup_database():
    DATABASE = 'members.db'  # Replace this with your actual database file path
    BACKUP_DIR = 'database_backups'  # The name of the backup directory

    # 获取当前运行的脚本路径
    current_path = os.path.dirname(os.path.abspath(__file__))
    backup_dir_path = os.path.join(current_path, BACKUP_DIR)
    
    # Create the backup directory if it doesn't exist
    os.makedirs(backup_dir_path, exist_ok=True)
    
    # 根据当前日期时间创建备份文件名
    backup_name = f"backup_{datetime.now().strftime('%Y%m%d%H%M%S')}.db"
    # 拼接出备份文件的完整路径
    backup_path = os.path.join(backup_dir_path, backup_name)
    # 复制数据库文件到备份路径
    shutil.copyfile(DATABASE, backup_path)
    
    # 获取当前目录下所有的备份文件
    all_backups = glob.glob(os.path.join(backup_dir_path, "backup_*.db"))
    
    # 如果备份文件数量超过 30,删除最早的备份文件
    if len(all_backups) > 30:
        all_backups.sort()
        os.remove(all_backups[0])

# 登录界面
class LoginWindow(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("会员储值管理系统")
        self.setGeometry(300, 300, 350, 200)
        layout = QVBoxLayout()

        username_label = QLabel("用户名:")
        self.username_entry = QLineEdit()
        password_label = QLabel("密码:")
        self.password_entry = QLineEdit()
        self.password_entry.setEchoMode(QLineEdit.Password)

        login_button = QPushButton("登录")
        login_button.clicked.connect(self.login)

        font = QFont()
        font.setBold(True)
        username_label.setFont(font)
        password_label.setFont(font)
        login_button.setFont(font)

        layout.addWidget(username_label)
        layout.addWidget(self.username_entry)
        layout.addWidget(password_label)
        layout.addWidget(self.password_entry)
        layout.addWidget(login_button)

        self.setLayout(layout)

    def login(self):
        username = self.username_entry.text()
        password = self.password_entry.text()
        if username == "admin" and password == "123":
            self.close()  # 关闭登录窗口
            self.main_window = MainWindow()  # 创建主窗口
            self.main_window.show()  # 显示主窗口
        else:
            QMessageBox.warning(self, "警告", "用户名或密码错误!")
#主界面
class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("会员管理系统")
        self.setGeometry(20, 20, 1000, 700)

        main_widget = QWidget()
        self.setCentralWidget(main_widget)

        # 创建Tab控件
        tab_widget = QTabWidget()

        # 创建会员查询界面
        search_widget = QWidget()
        search_layout = QVBoxLayout()
        
        # 会员查询界面
        search_label = QLabel("请输入会员姓名或手机号:")
        self.search_entry = QLineEdit()
        self.search_entry.returnPressed.connect(self.search_member)
        search_button = QPushButton("查询")
        search_button.clicked.connect(self.search_member)

        search_layout.addWidget(search_label)
        search_layout.addWidget(self.search_entry)
        search_layout.addWidget(search_button)

        # 创建按钮布局
        button_layout = QHBoxLayout()

        add_button = QPushButton("新增会员")
        add_button.clicked.connect(self.create_add_member_window)
        edit_button = QPushButton("修改会员信息")
        edit_button.clicked.connect(self.edit_member)
        delete_button = QPushButton("删除会员")
        delete_button.clicked.connect(self.delete_member)
        recharge_button = QPushButton("充值")
        recharge_button.clicked.connect(self.recharge_dialog)
        transaction_button = QPushButton("会员消费")
        transaction_button.clicked.connect(self.create_consume_dialog)
        buy_beauty_project_button = QPushButton("购买美容项目")
        buy_beauty_project_button.clicked.connect(self.buy_beauty_project)
        #设置CSS样式
        font = QFont()
        font.setBold(True)

        search_label.setStyleSheet("color: red;")
        search_label.setFont(font)
        search_button.setFont(font)
        add_button.setFont(font)
        edit_button.setFont(font)
        delete_button.setFont(font)
        recharge_button.setFont(font)
        transaction_button.setFont(font)
        buy_beauty_project_button.setFont(font)

        ####################################################
        button_layout.addWidget(add_button)
        button_layout.addWidget(edit_button)
        button_layout.addWidget(delete_button)
        button_layout.addWidget(recharge_button)
        button_layout.addWidget(transaction_button)
        button_layout.addWidget(buy_beauty_project_button)
        
        self.search_table = QTableWidget()

        self.search_table.setColumnCount(8)
        self.search_table.setHorizontalHeaderLabels([ "姓名", "手机号", "生日", "注册日期", "最后消费日期", "余额", "备注","ID"])
        self.search_table.setSelectionBehavior(QTableWidget.SelectRows)
        self.search_table.doubleClicked.connect(self.edit_member) #双击事件
                        
        self.search_table.setColumnWidth(0, 80)  # 第一列宽度为80
        self.search_table.setColumnWidth(1, 150)  
        self.search_table.setColumnWidth(2, 150)  
        self.search_table.setColumnWidth(3, 200)  
        self.search_table.setColumnWidth(4, 200)  
        self.search_table.setColumnWidth(5, 120)  
        self.search_table.setColumnWidth(6, 100)
        self.search_table.setColumnWidth(7, 10)    


        search_layout.addLayout(button_layout)
        search_layout.addWidget(self.search_table)

        search_widget.setLayout(search_layout)

        # 创建充值/消费记录界面
        transaction_widget = QWidget()
        transaction_layout = QVBoxLayout()
        transaction_label = QLabel("请输入会员姓名或手机号:")
        transaction_label.setStyleSheet("color: red;")
        transaction_label.setFont(font)
        self.transaction_member_entry = QLineEdit()
        self.transaction_member_entry.returnPressed.connect(self.search_transaction)
        transaction_button = QPushButton("查询")
        transaction_button.clicked.connect(self.search_transaction)
        export_button = QPushButton("导出")
        export_button.clicked.connect(self.export_transaction_table)
        

        self.transaction_table = QTableWidget()
        self.transaction_table.setColumnCount(8)
        self.transaction_table.setHorizontalHeaderLabels(["姓名", "手机号", "金额", "时间", "项目", "备注", "余额","营业员"])

        self.transaction_table.setColumnWidth(0, 80)  # 第一列宽度为80
        self.transaction_table.setColumnWidth(1, 150)  
        self.transaction_table.setColumnWidth(2, 100)  
        self.transaction_table.setColumnWidth(3, 200)  
        self.transaction_table.setColumnWidth(4, 200)  
        self.transaction_table.setColumnWidth(5, 80)  
        self.transaction_table.setColumnWidth(6, 100)
        self.transaction_table.setColumnWidth(7, 80)  

        transaction_layout.addWidget(transaction_label)
        transaction_layout.addWidget(self.transaction_member_entry)
        transaction_layout.addWidget(transaction_button)
        transaction_layout.addWidget(self.transaction_table)
        transaction_layout.addWidget(export_button)

        transaction_widget.setLayout(transaction_layout)
        # 创建美容项目管理界面
        beauty_project_widget = QWidget()
        beauty_project_layout = QVBoxLayout()
        # 美容项目管理界面
        beauty_project_label = QLabel("请输入美容项目名称:")
        beauty_project_label.setStyleSheet("color: red;")
        beauty_project_label.setFont(font)
        self.beauty_project_entry = QLineEdit()
        self.beauty_project_entry.returnPressed.connect(self.search_beauty_project)
        beauty_project_button = QPushButton("查询")
        beauty_project_button.clicked.connect(self.search_beauty_project)

        beauty_project_layout.addWidget(beauty_project_label)
        beauty_project_layout.addWidget(self.beauty_project_entry)
        beauty_project_layout.addWidget(beauty_project_button)
        # 创建按钮布局
        beauty_project_button_layout = QHBoxLayout()

        add_beauty_project_button = QPushButton("新增美容项目")
        add_beauty_project_button.clicked.connect(self.create_add_beauty_project_window)
        edit_beauty_project_button = QPushButton("修改美容项目信息")
        edit_beauty_project_button.clicked.connect(self.edit_beauty_project)
        delete_beauty_project_button = QPushButton("删除美容项目")
        delete_beauty_project_button.clicked.connect(self.delete_beauty_project)

        beauty_project_button_layout.addWidget(add_beauty_project_button)
        beauty_project_button_layout.addWidget(edit_beauty_project_button)
        beauty_project_button_layout.addWidget(delete_beauty_project_button)

        self.beauty_project_table = QTableWidget()

        self.beauty_project_table.setColumnCount(4)
        self.beauty_project_table.setHorizontalHeaderLabels(["ID", "美容项目名称","次数","新建时间"])
        self.beauty_project_table.setSelectionBehavior(QTableWidget.SelectRows)
        self.beauty_project_table.doubleClicked.connect(self.edit_beauty_project) #双击事件
    


        self.beauty_project_table.setColumnWidth(0, 30)  # 第一列宽度为80
        self.beauty_project_table.setColumnWidth(1, 250) 
        self.beauty_project_table.setColumnWidth(2, 100)
        self.beauty_project_table.setColumnWidth(3, 200)    

        beauty_project_layout.addLayout(beauty_project_button_layout)
        beauty_project_layout.addWidget(self.beauty_project_table)

        beauty_project_widget.setLayout(beauty_project_layout)

        # 创建营业员管理界面
        clerks_widget = QWidget()
        clerks_layout = QVBoxLayout()
        # 营业员管理界面
        clerks_label = QLabel("请输入营业员名称:")
        clerks_label.setStyleSheet("color: red;")
        clerks_label.setFont(font)
        self.clerks_entry = QLineEdit()
        self.clerks_entry.returnPressed.connect(self.search_clerk)
        clerks_button = QPushButton("查询")
        clerks_button.clicked.connect(self.search_clerk)

        clerks_layout.addWidget(clerks_label)
        clerks_layout.addWidget(self.clerks_entry)
        clerks_layout.addWidget(clerks_button)
        # 创建按钮布局
        clerks_button_layout = QHBoxLayout()

        add_clerks_button = QPushButton("新增营业员")
        add_clerks_button.clicked.connect(self.create_add_clerk_window)
        delete_clerks_button = QPushButton("删除营业员")
        delete_clerks_button.clicked.connect(self.delete_clerks)

        clerks_button_layout.addWidget(add_clerks_button)
        clerks_button_layout.addWidget(delete_clerks_button)

        self.clerks_table = QTableWidget()

        self.clerks_table.setColumnCount(2)
        self.clerks_table.setHorizontalHeaderLabels(["ID", "营业员名称"])

        self.clerks_table.setColumnWidth(0, 80)  # 第一列宽度为80
        self.clerks_table.setColumnWidth(1, 200)  

        clerks_layout.addLayout(clerks_button_layout)
        clerks_layout.addWidget(self.clerks_table)

        clerks_widget.setLayout(clerks_layout)

        # 创建会员美容项目次数报表界面
        report_widget = QWidget()
        report_layout = QVBoxLayout()
        report_label = QLabel("请输入会员姓名或手机号:")
        report_label.setStyleSheet("color: red;")
        report_label.setFont(font)
        self.report_entry = QLineEdit()
        self.report_entry.returnPressed.connect(self.search_report)
        report_button = QPushButton("查询")
        report_button.clicked.connect(self.search_report)

        self.report_table = QTableWidget()
        self.report_table.setColumnCount(4)
        self.report_table.setHorizontalHeaderLabels(["会员姓名", "手机号码","美容项目", "剩余次数"])

        report_layout.addWidget(report_label)
        report_layout.addWidget(self.report_entry)
        report_layout.addWidget(report_button)
        report_layout.addWidget(self.report_table)

        report_widget.setLayout(report_layout)

        tab_widget.addTab(search_widget, "会员查询")
        tab_widget.addTab(transaction_widget, "会员充值/消费记录")
        tab_widget.addTab(report_widget, "会员项目次数查询") 
        tab_widget.addTab(beauty_project_widget, "美容项目设置")
        tab_widget.addTab(clerks_widget, "营业员设置")
    
        main_layout = QVBoxLayout()
        main_layout.addWidget(tab_widget)
    
        main_widget.setLayout(main_layout)
        self.sort_order = Qt.AscendingOrder  # 初始排序顺序为升序
        # 点击充值/消费记录表头进行排序
        self.transaction_table.horizontalHeader().sectionClicked.connect(self.sort_transaction_table)

    # 会员查询功能
    def search_member(self):
        keyword = self.search_entry.text()
        query = f"SELECT members.name, members.phone, members.birthday, members.register_date, MAX(transactions.transaction_date), members.balance, members.remark,members.id FROM members LEFT JOIN transactions ON transactions.member_id = members.id WHERE members.name LIKE '%{keyword}%' OR members.phone LIKE '%{keyword}%' GROUP BY members.id ORDER BY MAX(transactions.transaction_date) DESC"
        cursor.execute(query)
        members = cursor.fetchall()
        self.search_table.setRowCount(0)
        for row, member in enumerate(members):
            self.search_table.insertRow(row)
            for col, data in enumerate(member):
                item = QTableWidgetItem(str(data))
                item.setFlags(Qt.ItemIsEnabled)
                self.search_table.setItem(row, col, item)  
    # 会员新增
    def create_add_member_window(self):
        add_member_window = AddMemberWindow(self)
        add_member_window.exec_()
    # 会员修改
    def edit_member(self):
        selected_row = self.search_table.currentRow()
        if selected_row != -1:
            member_id = self.search_table.item(selected_row, 7).text()
            edit_member_window = EditMemberWindow(member_id, self)
            edit_member_window.exec_()
        else:
            QMessageBox.warning(self, "警告", "请选择要修改的会员。")
    # 会员删除
    def delete_member(self):
        selected_row = self.search_table.currentRow()
        if selected_row != -1:
            member_id = self.search_table.item(selected_row, 7).text()
            query = f"SELECT * FROM members WHERE id = {member_id}"
            cursor.execute(query)
            member = cursor.fetchone()
            if member:
                confirm = QMessageBox.question(self, "确认", "【警告】确定要删除该会员吗?")
                if confirm == QMessageBox.Yes:
                    query = f"DELETE FROM members WHERE id = {member_id}"
                    cursor.execute(query)
                    conn.commit()
                    QMessageBox.information(self, "提示", "会员删除成功。")
                    self.search_member()
            else:
                QMessageBox.warning(self, "错误", "选择的会员不存在。")
        else:
            QMessageBox.warning(self, "警告", "请选择要删除的会员。")
    # 会员充值
    def recharge_dialog(self):
        selected_row = self.search_table.currentRow()
        if selected_row != -1:
            member_id = self.search_table.item(selected_row, 7).text()
            recharge_dialog = RechargeDialog(member_id, self)
            recharge_dialog.exec_()
        else:
            QMessageBox.warning(self, "警告", "请选择要充值的会员。")
    # 会员消费
    def create_consume_dialog(self):
        selected_row = self.search_table.currentRow()
        if selected_row != -1:
            member_id = self.search_table.item(selected_row, 7).text()
            consume_dialog = ConsumeDialog(member_id, self)
            consume_dialog.exec_()
        else:
            QMessageBox.warning(self, "警告", "请选择要消费的会员。")      
    # 会员购卡
    def buy_beauty_project(self):
        selected_row = self.search_table.currentRow()
        if selected_row != -1:
            member_id = self.search_table.item(selected_row, 7).text()
            buy_beauty_project_dialog = BuyBeautyProjectDialog(member_id, self)
            buy_beauty_project_dialog.exec_()
        else:
            QMessageBox.warning(self, "警告", "请选择要购买美容项目的会员。")
    

    # 会员充值消费记录查询
    def search_transaction(self):
        keyword = self.transaction_member_entry.text()
        query = f"SELECT members.name, members.phone, transactions.amount, strftime('%Y-%m-%d %H:%M:%S', transactions.transaction_date), transactions.project, transactions.remark, transactions.balance, clerks.name FROM transactions LEFT JOIN members ON transactions.member_id = members.id LEFT JOIN clerks ON transactions.clerk_id = clerks.id WHERE members.name LIKE '%{keyword}%' OR members.phone LIKE '%{keyword}%' ORDER BY transactions.transaction_date DESC"
        cursor.execute(query)
        transactions = cursor.fetchall()
        self.transaction_table.setRowCount(0)
        for row, transaction in enumerate(transactions):
            self.transaction_table.insertRow(row)
            for col, data in enumerate(transaction):
                item = QTableWidgetItem(str(data))
                item.setFlags(Qt.ItemIsEnabled)
                self.transaction_table.setItem(row, col, item)
    #导出会员充值/消费记录
    def export_transaction_table(self):
        workbook = openpyxl.Workbook()
        sheet = workbook.active

        # 添加表头
        headers = ["姓名", "手机号", "金额", "时间", "项目", "备注", "余额", "营业员"]
        for col_num, header in enumerate(headers, 1):
            sheet.cell(row=1, column=col_num, value=header)

        # 添加数据
        cursor.execute("SELECT members.name, members.phone, transactions.amount, transactions.transaction_date, transactions.project, transactions.remark, transactions.balance, clerks.name FROM transactions JOIN members ON transactions.member_id = members.id JOIN clerks ON transactions.clerk_id = clerks.id")
        transactions = cursor.fetchall()
        for row_num, transaction in enumerate(transactions, 2):
            for col_num, value in enumerate(transaction, 1):
                sheet.cell(row=row_num, column=col_num, value=value)

        # 选择保存路径
        filename, _ = QFileDialog.getSaveFileName(self, "保存文件", "", "Excel Files (*.xlsx)")
        if filename:
            workbook.save(filename)
            QMessageBox.information(self, "提示", f"会员充值/消费记录表已成功导出为:{filename}")
    
    #排序
    def sort_transaction_table(self, column):
        self.transaction_table.sortItems(column, self.sort_order)
        self.sort_order = Qt.DescendingOrder if self.sort_order == Qt.AscendingOrder else Qt.AscendingOrder
    #查询美容项目
    def search_beauty_project(self):
        keyword = self.beauty_project_entry.text()
        query = f"SELECT id, name,  times, strftime('%Y-%m-%d %H:%M:%S', datetime) FROM beauty_projects WHERE name LIKE '%{keyword}%'"
        cursor.execute(query)
        beauty_projects = cursor.fetchall()
        self.beauty_project_table.setRowCount(0)
        for row, beauty_project in enumerate(beauty_projects):
            self.beauty_project_table.insertRow(row)
            for col, data in enumerate(beauty_project):
                item = QTableWidgetItem(str(data))
                item.setFlags(Qt.ItemIsEnabled)
                self.beauty_project_table.setItem(row, col, item)
    #新建美容项目
    def create_add_beauty_project_window(self):
        add_beauty_project_window = AddBeautyProjectWindow(self)
        add_beauty_project_window.exec_()
    #修改美容项目
    def edit_beauty_project(self):
        selected_row = self.beauty_project_table.currentRow()
        if selected_row != -1:
            beauty_project_id = self.beauty_project_table.item(selected_row, 0).text()
            edit_beauty_project_window = EditBeautyProjectWindow(beauty_project_id, self)
            edit_beauty_project_window.exec_()
        else:
            QMessageBox.warning(self, "警告", "请选择要修改的美容项目。")
    #删除美容项目
    def delete_beauty_project(self):
        selected_row = self.beauty_project_table.currentRow()
        if selected_row != -1:
            beauty_project_id = self.beauty_project_table.item(selected_row, 0).text()
            query = f"SELECT * FROM beauty_projects WHERE id = {beauty_project_id}"
            cursor.execute(query)
            beauty_project = cursor.fetchone()
            if beauty_project:
                confirm = QMessageBox.question(self, "确认", "【警告】确定要删除该美容项目吗?")
                if confirm == QMessageBox.Yes:
                    query = f"DELETE FROM beauty_projects WHERE id = {beauty_project_id}"
                    cursor.execute(query)
                    conn.commit()
                    QMessageBox.information(self, "提示", "美容项目删除成功。")
                    self.search_beauty_project()
            else:
                QMessageBox.warning(self, "错误", "选择的美容项目不存在。")
        else:
            QMessageBox.warning(self, "警告", "请选择要删除的美容项目。")
    #查询营业员
    def search_clerk(self):
        keyword = self.clerks_entry.text()
        query = f"SELECT id, name FROM clerks WHERE name LIKE '%{keyword}%' AND is_deleted = 0"
        cursor.execute(query)
        clerks = cursor.fetchall()
        self.clerks_table.setRowCount(0)
        for row, clerks in enumerate(clerks):
            self.clerks_table.insertRow(row)
            for col, data in enumerate(clerks):
                item = QTableWidgetItem(str(data))
                item.setFlags(Qt.ItemIsEnabled)
                self.clerks_table.setItem(row, col, item)
    #新增营业员窗口
    def create_add_clerk_window(self):
        add_clerk_window = AddClerkWindow(self)
        add_clerk_window.exec_()
    # 营业员删除
    def delete_clerks(self):
        selected_row = self.clerks_table.currentRow()
        if selected_row != -1:
            clerks_id = self.clerks_table.item(selected_row, 7).text()
            query = f"SELECT * FROM clerks WHERE id = {clerks_id}"
            cursor.execute(query)
            clerks = cursor.fetchone()
            if clerks:
                confirm = QMessageBox.question(self, "确认", "【警告】确定要删除该营业员吗?")
                if confirm == QMessageBox.Yes:
                    # 不真正删除营业员,而是将其标记为已删除
                    query = f"UPDATE clerks SET is_deleted = 1 WHERE id = {clerks_id}"
                    cursor.execute(query)
                    conn.commit()
                    QMessageBox.information(self, "提示", "营业员删除成功。")
                    self.search_clerk()
            else:
                QMessageBox.warning(self, "错误", "选择的营业员不存在。")
        else:
            QMessageBox.warning(self, "警告", "请选择要删除的营业员。")




    #查询会员项目
    def search_report(self):
        keyword = self.report_entry.text()
        query = f"SELECT members.name, members.phone, beauty_projects.name, member_beauty_projects.sessions FROM member_beauty_projects JOIN members ON member_beauty_projects.member_id = members.id JOIN beauty_projects ON member_beauty_projects.beauty_project_id = beauty_projects.id WHERE members.name LIKE '%{keyword}%' OR members.phone LIKE '%{keyword}%'"
        cursor.execute(query)
        reports = cursor.fetchall()
        self.report_table.setRowCount(0)
        for row, report in enumerate(reports):
            self.report_table.insertRow(row)
            for col, data in enumerate(report):
                item = QTableWidgetItem(str(data))
                item.setFlags(Qt.ItemIsEnabled)
                self.report_table.setItem(row, col, item)

#新增会员对话框
class AddMemberWindow(QDialog):
    def __init__(self, parent):
        super().__init__(parent)
        self.setWindowTitle("新增会员")

        name_label = QLabel("会员姓名:")
        self.name_entry = QLineEdit()
        phone_label = QLabel("手机号:")
        self.phone_entry = QLineEdit()
        birthday_label = QLabel("生日:")  # 新增
        self.birthday_entry = QDateEdit()  # 新增
        self.birthday_entry.setCalendarPopup(True)  # 新增

        layout = QGridLayout()
        layout.addWidget(name_label, 0, 0)
        layout.addWidget(self.name_entry, 0, 1)
        layout.addWidget(phone_label, 1, 0)
        layout.addWidget(self.phone_entry, 1, 1)
        layout.addWidget(birthday_label, 2, 0)  # 新增
        layout.addWidget(self.birthday_entry, 2, 1)  # 新增

        add_button = QPushButton("确定")
        add_button.clicked.connect(self.add_member)

        layout.addWidget(add_button, 3, 0, 1, 2)  # 修改

        self.setLayout(layout)

    def validate_phone(self, phone):
        pattern = r"^1[3456789]\d{9}$"
        if not re.match(pattern, phone):
            return False
        return True
    
    def check_phone_exists(self, phone):
        query = f"SELECT * FROM members WHERE phone = '{phone}'"
        cursor.execute(query)
        member = cursor.fetchone()
        if member:
            return True
        return False

    def add_member(self):
        name = self.name_entry.text()
        phone = self.phone_entry.text()
        birthday = self.birthday_entry.date().toString("yyyy-MM-dd")  # 新增
        if not self.validate_phone(phone):
            QMessageBox.warning(self, "错误", "手机号格式不正确。")
            return
        if self.check_phone_exists(phone):
            QMessageBox.warning(self, "错误", "手机号已存在,请输入其他手机号。")
            return
        query = f"INSERT INTO members (name, phone, birthday, register_date, balance) VALUES ('{name}', '{phone}', '{birthday}', '{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}', 0)"  # 修改
        cursor.execute(query)
        conn.commit()
        QMessageBox.information(self, "提示", "会员添加成功。")
        self.parent().search_member()
        self.close()

#修改会员信息
class EditMemberWindow(QDialog):
    def __init__(self, member_id, parent):
        super().__init__(parent)
        self.setWindowTitle("修改会员信息")

        self.member_id = member_id

        query = f"SELECT * FROM members WHERE id = {self.member_id}"
        cursor.execute(query)
        member = cursor.fetchone()
        self.old_balance = member[6]

        name_label = QLabel("会员姓名:")
        self.name_entry = QLineEdit()
        self.name_entry.setText(member[1])
        phone_label = QLabel("手机号:")
        self.phone_entry = QLineEdit()
        self.phone_entry.setText(member[2])
        birthday_label = QLabel("生日:")  # 新增
        self.birthday_entry = QDateEdit()  # 新增
        self.birthday_entry.setCalendarPopup(True)  # 新增
        self.birthday_entry.setDate(QDate.fromString(member[5], "yyyy-MM-dd"))  # 新增
        balance_label = QLabel("余额:")
        self.balance_entry = QLineEdit()
        self.balance_entry.setText(str(member[6]))

        layout = QGridLayout()
        layout.addWidget(name_label, 0, 0)
        layout.addWidget(self.name_entry, 0, 1)
        layout.addWidget(phone_label, 1, 0)
        layout.addWidget(self.phone_entry, 1, 1)
        layout.addWidget(birthday_label, 2, 0)  # 新增
        layout.addWidget(self.birthday_entry, 2, 1)  # 新增
        layout.addWidget(balance_label, 3, 0)  # 修改
        layout.addWidget(self.balance_entry, 3, 1)  # 修改

        save_button = QPushButton("保存")
        save_button.clicked.connect(self.save_member)

        layout.addWidget(save_button, 4, 0, 1, 2)  # 修改

        self.setLayout(layout)
    def validate_phone(self, phone):
        pattern = r"^1[3456789]\d{9}$"
        if not re.match(pattern, phone):
            return False
        return True
    
    def check_phone_exists(self, phone):
        query = f"SELECT * FROM members WHERE phone = '{phone}'"
        cursor.execute(query)
        member = cursor.fetchone()
        if member:
            return True
        return False

    def save_member(self):
        name = self.name_entry.text()
        phone = self.phone_entry.text()
        birthday = self.birthday_entry.date().toString("yyyy-MM-dd")  # 新增
        balance = self.balance_entry.text()

        # 检查手机号是否已经被修改
        query = f"SELECT phone FROM members WHERE id = {self.member_id}"
        cursor.execute(query)
        old_phone = cursor.fetchone()[0]
        if phone != old_phone and self.check_phone_exists(phone):
            QMessageBox.warning(self, "错误", "手机号已存在,请输入其他手机号。")
            return
        if not self.validate_phone(phone):
            QMessageBox.warning(self, "错误", "手机号格式不正确。")
            return
        
        query = f"UPDATE members SET name = '{name}', phone = '{phone}', birthday = '{birthday}', balance = {balance} WHERE id = {self.member_id}"  # 修改
        cursor.execute(query)
        conn.commit()
        query = f"SELECT * FROM members WHERE id = {self.member_id}"
        cursor.execute(query)
        updated_member = cursor.fetchone()
        new_balance = updated_member[6]
        if self.old_balance != new_balance:
            amount = float(new_balance) - float(self.old_balance)
            transaction_query = f"INSERT INTO transactions (member_id, amount, project,transaction_date, balance, remark) VALUES ({self.member_id}, {amount}, '无','{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}', {new_balance},'修改余额')"
            cursor.execute(transaction_query)
            conn.commit()
        QMessageBox.information(self, "提示", "会员信息修改成功。")
        self.parent().search_transaction()
        self.parent().search_member()
        self.close()
#会员充值
class RechargeDialog(QDialog):
    def __init__(self, member_id, parent):
        super().__init__(parent)
        self.setWindowTitle("会员充值")

        self.member_id = member_id

        amount_label = QLabel("充值金额:")
        self.amount_entry = QLineEdit()

        clerk_label = QLabel("营业员:")
        self.clerk_combo = QComboBox()
        self.load_clerks()

        layout = QVBoxLayout()  # 定义布局
        layout.addWidget(amount_label)
        layout.addWidget(self.amount_entry)
        layout.addWidget(clerk_label)
        layout.addWidget(self.clerk_combo)

        confirm_button = QPushButton("确认")
        confirm_button.clicked.connect(self.confirm_recharge)

        layout.addWidget(confirm_button)

        self.setLayout(layout)
    #读取营业员信息
    def load_clerks(self):
        cursor.execute("SELECT name FROM clerks")
        clerks = cursor.fetchall()
        for clerk in clerks:
            self.clerk_combo.addItem(clerk[0])
    #确认充值信息
    def confirm_recharge(self):
        try:
            amount = float(self.amount_entry.text())
            if amount > 0:
                query = f"SELECT balance FROM members WHERE id = {self.member_id}"
                cursor.execute(query)
                member = cursor.fetchone()
                if member:
                    current_balance = member[0]
                    new_balance = current_balance + amount

                    clerk_name = self.clerk_combo.currentText()
                    cursor.execute("SELECT id FROM clerks WHERE name = ?", (clerk_name,))
                    clerk = cursor.fetchone()
                    if clerk is not None:
                        clerk_id = clerk[0]

                        query = f"UPDATE members SET balance = {new_balance} WHERE id = {self.member_id}"
                        cursor.execute(query)
                        conn.commit()

                        transaction_query = f"INSERT INTO transactions (member_id, amount, project,transaction_date, balance, remark, clerk_id) VALUES ({self.member_id}, {amount}, '无','{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}',{new_balance}, '充值', {clerk_id})"
                        cursor.execute(transaction_query)
                        conn.commit()

                        QMessageBox.information(self, "提示", "充值成功。")
                        self.parent().search_member()
                        self.parent().search_transaction()
                        self.close()
                    else:
                        QMessageBox.information(self, "提示", "请输入营业员!")
                        return
                        
                else:
                    QMessageBox.warning(self, "错误", "选择的会员不存在。")
            else:
                QMessageBox.warning(self, "错误", "充值金额必须大于0。")
        except ValueError:
            QMessageBox.warning(self, "错误", "请输入有效的充值金额。")

#会员消费窗口
class ConsumeDialog(QDialog):
    def __init__(self, member_id, parent):
        super().__init__(parent)
        self.setWindowTitle("会员消费")

        self.member_id = member_id

        amount_label = QLabel("消费金额:")
        self.amount_entry = QLineEdit("0")

        project_label = QLabel("美容项目:")
        self.project_combo = QComboBox()
        self.load_projects()

        clerk_label = QLabel("营业员:")
        self.clerk_combo = QComboBox()
        self.load_clerks()
        

        layout = QVBoxLayout()
        layout.addWidget(clerk_label)
        layout.addWidget(self.clerk_combo)
        layout.addWidget(amount_label)
        layout.addWidget(self.amount_entry)
        layout.addWidget(project_label)
        layout.addWidget(self.project_combo)

        confirm_button = QPushButton("确认")
        confirm_button.clicked.connect(self.confirm_consume)

        layout.addWidget(confirm_button)

        self.setLayout(layout)
    #读取营业员信息    
    def load_clerks(self):
        cursor.execute("SELECT name FROM clerks")
        clerks = cursor.fetchall()
        for clerk in clerks:
            self.clerk_combo.addItem(clerk[0])
    #读取会员美容项目
    def load_projects(self):
        self.project_combo.addItem("无")  # Add "无" option
        query = f"SELECT beauty_projects.name FROM beauty_projects JOIN member_beauty_projects ON beauty_projects.id = member_beauty_projects.beauty_project_id WHERE member_beauty_projects.member_id = {self.member_id}"
        cursor.execute(query)
        projects = cursor.fetchall()
        if projects:
            for project in projects:
                self.project_combo.addItem(project[0])
    #确认消费
    def confirm_consume(self):
        project_name = self.project_combo.currentText()
        clerk_name = self.clerk_combo.currentText()
        cursor.execute("SELECT id FROM clerks WHERE name = ?", (clerk_name,))
        clerk = cursor.fetchone()
        if clerk is not None:
            clerk_id = clerk[0]
        else:
            QMessageBox.warning(self, "错误", "请输入营业员!")
            return

        amount = float(self.amount_entry.text())

        if project_name != "无":
            # 获取项目ID
            cursor.execute("SELECT id FROM beauty_projects WHERE name = ?", (project_name,))
            project_id = cursor.fetchone()[0]

            # 使用项目ID替换项目名
            query = f"SELECT * FROM member_beauty_projects WHERE member_id = {self.member_id} AND beauty_project_id = {project_id}"
            cursor.execute(query)
            member_project = cursor.fetchone()
            if member_project:
                if member_project[2] > 0:  # 检查剩余次数
                    # 使用项目ID替换项目名
                    query = f"UPDATE member_beauty_projects SET sessions = sessions - 1 WHERE member_id = {self.member_id} AND beauty_project_id = {project_id}"
                    cursor.execute(query)
                    conn.commit()
                    QMessageBox.information(self, "提示", "消费成功。")

                    # 获取当前余额
                    query = f"SELECT balance FROM members WHERE id = {self.member_id}"
                    cursor.execute(query)
                    member = cursor.fetchone()
                    current_balance = member[0]
                    new_balance = current_balance - amount

                    transaction_query = f"INSERT INTO transactions (member_id, amount, project, transaction_date, balance, remark, clerk_id) VALUES ({self.member_id}, {-amount}, '{self.project_combo.currentText()}','{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}',{new_balance}, '消费', {clerk_id})"
                    cursor.execute(transaction_query)
                    conn.commit()
                    self.parent().search_member()
                    self.parent().search_transaction()
                    self.close()
                else:
                    QMessageBox.warning(self, "错误", "该会员的此项目次数已用完。")
            else:
                QMessageBox.warning(self, "错误", "该会员没有购买此项目。")            
        else:
            if amount > 0:
                query = f"SELECT balance FROM members WHERE id = {self.member_id}"
                cursor.execute(query)
                member = cursor.fetchone()
                if member:
                    current_balance = member[0]
                    if current_balance >= amount:
                        new_balance = current_balance - amount
                    
                        query = f"UPDATE members SET balance = {new_balance}, last_consume_date = '{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}' WHERE id = {self.member_id}"
                        cursor.execute(query)
                        conn.commit()

                        transaction_query = f"INSERT INTO transactions (member_id, amount, transaction_date, balance, project, remark, clerk_id) VALUES ({self.member_id}, {-amount}, '{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}',{new_balance}, '{self.project_combo.currentText()}','消费', {clerk_id})"
                        cursor.execute(transaction_query)
                        conn.commit()

                        QMessageBox.information(self, "提示", "消费成功。")
                        self.parent().search_member()
                        self.parent().search_transaction()
                        self.close()
                    else:
                        QMessageBox.warning(self, "错误", "余额不足,无法消费。")

#会员购卡
class BuyBeautyProjectDialog(QDialog):
    def __init__(self, member_id, parent):
        super().__init__(parent)
        self.setWindowTitle("购买美容项目")

        self.member_id = member_id

        project_label = QLabel("选择美容项目:")
        self.project_combo = QComboBox()
        self.load_beauty_projects()

        clerk_label = QLabel("营业员:")
        self.clerk_combo = QComboBox()
        self.load_clerks()
        
        layout = QVBoxLayout()  # 定义布局
        layout.addWidget(clerk_label)
        layout.addWidget(self.clerk_combo)
        layout.addWidget(project_label)
        layout.addWidget(self.project_combo)

        confirm_button = QPushButton("确认")
        confirm_button.clicked.connect(self.buy_beauty_project)

        layout.addWidget(confirm_button)

        self.setLayout(layout)
    #读取营业员信息
    def load_clerks(self):
        cursor.execute("SELECT name FROM clerks")
        clerks = cursor.fetchall()
        for clerk in clerks:
            self.clerk_combo.addItem(clerk[0])
    #读取美容项目
    def load_beauty_projects(self):
        cursor.execute("SELECT name FROM beauty_projects")
        beauty_projects = cursor.fetchall()
        for project in beauty_projects:
            self.project_combo.addItem(project[0])
    #购买美容项目
    def buy_beauty_project(self):
        project_name = self.project_combo.currentText()
        cursor.execute("SELECT id, times FROM beauty_projects WHERE name = ?", (project_name,))
        project = cursor.fetchone()
        project_id = project[0]
        project_times = project[1]  # 获取项目的次数

        # 检查会员是否已经购买了这个项目
        cursor.execute("SELECT * FROM member_beauty_projects WHERE member_id = ? AND beauty_project_id = ?", (self.member_id, project_id))
        if cursor.fetchone():
            # 如果会员已经购买了这个项目,那么显示一个错误消息并返回
            QMessageBox.warning(self, "错误", "你已经购买了这个项目。")
            return

        cursor.execute("INSERT INTO member_beauty_projects (member_id, beauty_project_id, sessions) VALUES (?, ?, ?)", (self.member_id, project_id, project_times))
        conn.commit()

        clerk_name = self.clerk_combo.currentText()
        cursor.execute("SELECT id FROM clerks WHERE name = ?", (clerk_name,))
        clerk_id = cursor.fetchone()[0]
        transaction_query = f"INSERT INTO transactions (member_id, project, transaction_date, remark, clerk_id) VALUES ({self.member_id}, '{project_name}', '{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}', '购卡', {clerk_id})"
        cursor.execute(transaction_query)
        conn.commit()

        QMessageBox.information(self, "提示", "购买成功。")
        self.close()

#新增美容项目对话框
class AddBeautyProjectWindow(QDialog):
    def __init__(self, parent):
        super().__init__(parent)
        self.setWindowTitle("新增美容项目")

        name_label = QLabel("美容项目名称:")
        self.name_entry = QLineEdit()
        times_label = QLabel("次数:")
        self.times_entry = QLineEdit()
        datetime_label = QLabel("新建时间:")
        self.datetime_entry = QDateTimeEdit(datetime.now())
        self.datetime_entry.setDisplayFormat("yyyy-MM-dd HH:mm:ss")

        layout = QGridLayout()
        layout.addWidget(name_label, 0, 0)
        layout.addWidget(self.name_entry, 0, 1)
        layout.addWidget(times_label, 1, 0)
        layout.addWidget(self.times_entry, 1, 1)
        layout.addWidget(datetime_label, 2, 0)
        layout.addWidget(self.datetime_entry, 2, 1)

        add_button = QPushButton("确定")
        add_button.clicked.connect(self.add_beauty_project)

        layout.addWidget(add_button, 3, 0, 1, 2)

        self.setLayout(layout)

    def add_beauty_project(self):
        name = self.name_entry.text()
        times = self.times_entry.text()
        datetime = self.datetime_entry.dateTime().toString("yyyy-MM-dd HH:mm:ss")
        if self.check_beauty_project_exists(name):
            QMessageBox.warning(self, "错误", "美容项目已存在,请输入其他美容项目。")
            return
        query = f"INSERT INTO beauty_projects (name, times, datetime) VALUES ('{name}', {times}, '{datetime}')"
        cursor.execute(query)
        conn.commit()
        QMessageBox.information(self, "提示", "美容项目添加成功。")
        self.parent().search_beauty_project()
        self.close()

    def check_beauty_project_exists(self, name):
        query = f"SELECT * FROM beauty_projects WHERE name = '{name}'"
        cursor.execute(query)
        beauty_project = cursor.fetchone()
        if beauty_project:
            return True
        return False
#修改美容项目对话框
class EditBeautyProjectWindow(QDialog):
    def __init__(self, beauty_project_id, parent):
        super().__init__(parent)
        self.setWindowTitle("修改美容项目")

        self.beauty_project_id = beauty_project_id

        query = f"SELECT * FROM beauty_projects WHERE id = {self.beauty_project_id}"
        cursor.execute(query)
        beauty_project = cursor.fetchone()

        name_label = QLabel("美容项目名称:")
        self.name_entry = QLineEdit()
        self.name_entry.setText(beauty_project[1])
        times_label = QLabel("次数:")
        self.times_entry = QLineEdit()
        self.times_entry.setText(str(beauty_project[2]))

        layout = QGridLayout()
        layout.addWidget(name_label, 0, 0)
        layout.addWidget(self.name_entry, 0, 1)
        layout.addWidget(times_label, 1, 0)
        layout.addWidget(self.times_entry, 1, 1)

        save_button = QPushButton("保存")
        save_button.clicked.connect(self.save_beauty_project)

        layout.addWidget(save_button, 2, 0, 1, 2)

        self.setLayout(layout)

    def save_beauty_project(self):
        name = self.name_entry.text()
        times = self.times_entry.text()
        query = f"UPDATE beauty_projects SET name = '{name}', times = {times} WHERE id = {self.beauty_project_id}"
        cursor.execute(query)
        conn.commit()
        QMessageBox.information(self, "提示", "美容项目信息修改成功。")
        self.parent().search_beauty_project()
        self.close()
#新增营业员对话框
class AddClerkWindow(QDialog):
    def __init__(self, parent):
        super().__init__(parent)
        self.setWindowTitle("新增营业员")

        name_label = QLabel("营业员名称:")
        self.name_entry = QLineEdit()

        layout = QGridLayout()
        layout.addWidget(name_label, 0, 0)
        layout.addWidget(self.name_entry, 0, 1)

        add_button = QPushButton("确定")
        add_button.clicked.connect(self.add_clerk)

        layout.addWidget(add_button, 3, 0, 1, 2)

        self.setLayout(layout)

    def add_clerk(self):
        name = self.name_entry.text()
        if self.check_clerk_exists(name):
            QMessageBox.warning(self, "错误", "营业员已存在,请输入其他营业员。")
            return
        query = f"INSERT INTO clerks (name) VALUES ('{name}')"
        cursor.execute(query)
        conn.commit()
        QMessageBox.information(self, "提示", "营业员添加成功。")
        self.parent().search_clerk()
        self.close()

    def check_clerk_exists(self, name):
        query = f"SELECT * FROM clerks WHERE name = '{name}'"
        cursor.execute(query)
        clerk = cursor.fetchone()
        if clerk:
            return True
        return False

if __name__ == "__main__":
    backup_database()
    app = QApplication(sys.argv)
    login_window = LoginWindow()
    login_window.show()
    sys.exit(app.exec_())
    





【2023年8月9日】源码下载: https://pan.baidu.com/s/1_94DCdONpmYzRyYDC_7CRQ?pwd=9ep6 提取码: 9ep6


【旧版】成品下载:链接:https://pan.baidu.com/s/1FlupRHGkVGOZK6Z6q_gshg?pwd=o2gv提取码:o2gv

免费评分

参与人数 31吾爱币 +31 热心值 +26 收起 理由
godsoncai + 1 + 1 鼓励转贴优秀软件安全工具和文档!
yufei025 + 1 + 1 我很赞同!
十次方 + 1 + 1 我很赞同!
模糊的幻觉。 + 1 + 1 期待修复BUG
gavin168 + 1 谢谢@Thanks!
zchao + 1 + 1 热心回复!
aabbcc123123 + 1 + 1 谢谢@Thanks!
ichiban123 + 1 鼓励转贴优秀软件安全工具和文档!
rebornlv + 1 + 1 谢谢@Thanks!
gdp123gd + 1 + 1 我很赞同!
zleizero + 1 谢谢@Thanks!
波波爆炸了 + 1 + 1 谢谢@Thanks!
ETFBI + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
yiqu + 1 热心回复!
aria1983 + 2 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
真不懂 + 1 我很赞同!
wj340881 + 1 + 1 着实不易
kikizhu + 1 谢谢@Thanks!
qytjc + 1 + 1 有会员生日提醒吗?连续提醒三天。
寒江雪2018 + 1 我很赞同!
hsyjxp + 1 + 1 我很赞同!
twl859588 + 1 谢谢@Thanks!
taotaofox + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
mazh369 + 1 热心回复!
pentium + 1 我很赞同!
fageceshi + 1 热心回复!
giood525 + 1 + 1 谢谢@Thanks!
hetiwz + 1 我很赞同!
a85401234 + 1 + 1 谢谢@Thanks!
yuanshuzhen + 1 + 1 我很赞同!
风之暇想 + 7 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!

查看全部评分

本帖被以下淘专辑推荐:

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

land001 发表于 2023-8-2 10:58
Hell 发表于 2023-8-2 10:53
需求是什么样的?

部门大概是10个人,
班次分:早,中,晚,备用,4个班次。
每个人每月可以休息6天。
正常情况下排版是:早班,2人,中班1人。晚班2人。备用2人。剩余的休息。
特殊情况下,可以早班3人,中班2人,晚班3人等。这个可以调节。
这系统自动排班之前,可以先勾选哪天,哪些员工休息。或者哪些员工想上什么班次。确定好后  则自动安排需要的班次。

大概是这样的功能。
 楼主| Hell 发表于 2024-4-19 13:44
jun269 发表于 2024-4-19 12:40
楼主,这个能不能也给打包成exe的成品啊?谢谢

我晚点打包个最新版出来。自己配置数据库链接就行
suibianzhuce001 发表于 2023-7-28 16:37
tianwufeng 发表于 2023-7-28 22:35
楼主好厉害, 定时回来看版本更新, 加油
lefina 发表于 2023-7-29 00:12
学习了,谢谢分享, 加油
头像被屏蔽
source888 发表于 2023-7-29 00:32
提示: 作者被禁止或删除 内容自动屏蔽
andy512 发表于 2023-7-29 04:27
可以考虑做个通用模版
pqr34352cy 发表于 2023-7-29 07:39
学习了,谢谢分享
头像被屏蔽
marvelci 发表于 2023-7-29 08:19
提示: 作者被禁止或删除 内容自动屏蔽
52老牛 发表于 2023-7-29 08:23
厉害,也可以这样用,学习
february 发表于 2023-7-29 10:59
可以用到其他行业不?顺便问下,项目里的大保健是什么项目
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 提醒:禁止复制他人回复等『恶意灌水』行为,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-4-29 09:41

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表