Python+OpenCV系列:【打卡系统-服务模块设计】服务模块大揭秘,考勤智能中枢的奇幻之旅

在智能考勤的浩瀚星空中,Python+OpenCV 员工打卡系统的服务模块宛如一颗璀璨的恒星,散发着无尽的光芒与能量,驱动着整个考勤体系高效且精准地运转。今天,就让我们一同踏上这充满奇幻与创新的服务模块探索之旅!

一、人事服务模块:企业人事管理的智慧大脑

人事服务模块无疑是整个打卡系统的人事管理智慧大脑,掌控着员工信息与考勤数据的核心命脉。

导入模块,恰似打开知识宝库的大门,引入丰富的功能资源,为后续操作奠定坚实基础。加载所有数据,犹如开启数据的时光隧道,将企业员工的全方位信息瞬间呈现在眼前,无论是员工的基本资料,还是过往的考勤历史,皆一目了然。

添加和删除员工功能,宛如人事变动的神奇魔法棒。新员工入职时,轻点鼠标,便可将其详细信息精准录入系统,如同为企业大家庭迎来一位新成员;而员工离职时,又能迅速清理其数据痕迹,确保系统数据的精简与高效,维持人事数据的鲜活与准确。

添加打卡记录,则像是一位严谨的史官,如实记载员工的出勤时刻,每一次打卡都被精准铭刻,为考勤统计提供了最原始、最可靠的数据素材。

获取员工数据功能,仿若一把数据检索的万能钥匙,无论需要查询特定员工的哪类信息,都能在瞬间定位并提取,极大地提高了人事管理的工作效率。

验证管理员账号和密码,犹如一座坚固的数字城堡大门,只有持有正确“通行证”的管理员才能进入系统核心区域,进行关键操作,确保了企业人事数据的安全性与保密性。

保存上下班时间以及打印考勤日报、月报,是将考勤数据精心雕琢成可供决策参考的宝贵资料。上下班时间的准确记录,为工资核算、绩效评估等提供了关键依据;而考勤日报、月报则以直观的形式展示员工出勤全貌,管理层借此可洞察企业运营中的人事动态,及时发现问题并制定策略,推动企业持续发展。

"""
人事管理服务
"""

from entity import organizations as o
from util import public_tools as tool
from util import io_tools as io
import datetime
import calendar


# 添加新员工
def add_new_employee(name):
    code = tool.randomCode()  # 生成随机特征码
    newEmp = o.Employee(o.get_new_id(), name, code)  # 创建员工对象
    o.add(newEmp)  # 组织结构中添加新员工
    io.save_employee_all()  # 保存最新的员工信息
    return code  # 新员工的特征码


# 删除某个员工
def remove_employee(id):
    io.remove_pics(id)  # 删除该员工所有图片
    o.remove(id)  # 从组织结构中删除
    io.save_employee_all()  # 保存最新的员工信息
    io.save_lock_record()  # 保存最新的打卡记录


# 所有员工信息报表
def get_employee_report():
    # report = list()   # 员工信息列表
    report = "###########################################\n"
    report += "员工名单如下:\n"
    i = 0  # 换行计数器
    for emp in o.EMPLOYEES:  # 遍历所有员工
        report += "(" + str(emp.id) + ")" + emp.name + "\t"
        i += 1  # 计数器自增
        if i == 4:  # 每四个员工换一行
            report += "\n"
            i = 0  # 计数器归零
    report = report.strip()  # 清除报表结尾可能出现的换行符
    report += "\n###########################################"
    return report


# 通过特征码获取员工姓名
def get_name_with_code(code):
    for emp in o.EMPLOYEES:
        if str(code) == str(emp.code):
            return emp.name


# 通过id获取员工特征码
def get_code_with_id(id):
    for emp in o.EMPLOYEES:
        if str(id) == str(emp.id):
            return emp.code


# 获取所有员工的打卡记录信息
def get_record_all():
    record = o.LOCK_RECORD  # 获得打卡记录字典
    report = ""  # 报表内容
    for name in record.keys():  # 遍历所有名字
        report += "-----------------------------------\n"
        report += name + "  打卡记录如下:\n"
        for date in record[name]:  # 遍历所有时间字符串
            report += date + "\n"
    return report


# 为指定员工添加打卡记录
def add_lock_record(name):
    record = o.LOCK_RECORD  # 所有打卡记录
    now_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")  # 当前时间
    if name in record.keys():  # 如果这个人有打卡记录
        r_list = record[name]  # 去除他的记录
        if len(r_list) == 0:  # 如果记录为空
            r_list = list()  # 创建新列表
        r_list.append(now_time)  # 记录当前时间
    else:  # 如果这个人从未打过卡
        r_list = list()  # 创建新列表
        r_list.append(now_time)  # 记录当前时间
        record[name] = r_list  # 将记录保存在字典中
    io.save_lock_record()  # 保存所有打卡记录


# 验证管理员账号和密码
def valid_user(username, password):
    if username in o.USERS.keys():  # 如果有这个账号
        if o.USERS.get(username) == password:  # 如果账号和密码匹配
            return True  # 验证成功
    return False  # 验证失败


# 打印今天的打卡日报
def get_today_report():
    date = datetime.datetime.now().strftime("%Y-%m-%d")  # 今天的日期
    get_day_report(str(date))  # 打印今天的日报


# 打印指定日期的打卡日报
def get_day_report(date):
    io.load_work_time_config()  # 读取上下班时间

    earliest_time = datetime.datetime.strptime(date + " 00:00:00", "%Y-%m-%d %H:%M:%S")  # 今天0点
    noon_time = datetime.datetime.strptime(date + " 12:00:00", "%Y-%m-%d %H:%M:%S")  # 今天中午12点
    latest_time = datetime.datetime.strptime(date + " 23:59:59", "%Y-%m-%d %H:%M:%S")  # 今晚0点之前
    work_time = datetime.datetime.strptime(date + " " + o.WORK_TIME, "%Y-%m-%d %H:%M:%S")  # 上班时间
    closing_time = datetime.datetime.strptime(date + " " + o.CLOSING_TIME, "%Y-%m-%d %H:%M:%S")  # 下班时间

    late_list = []  # 迟到名单
    left_early = []  # 早退名单
    absent_list = []  # 缺席名单

    for emp in o.EMPLOYEES:  # 遍历所有员工
        if emp.name in o.LOCK_RECORD.keys():  # 如果该员工有打卡记录
            emp_lock_list = o.LOCK_RECORD.get(emp.name)  # 获取该员工所有的打卡记录
            is_absent = True  # 缺席状态
            for lock_time_str in emp_lock_list:  # 遍历所有打卡记录
                lock_time = datetime.datetime.strptime(lock_time_str, "%Y-%m-%d %H:%M:%S")  # 打卡记录转为日期格式
                if earliest_time < lock_time < latest_time:  # 如果当天有打卡记录
                    is_absent = False  # 不缺席
                    if work_time < lock_time <= noon_time:  # 上班时间后、中午之前打卡
                        late_list.append(emp.name)  # 加入迟到名单
                    if noon_time < lock_time < closing_time:  # 中午之后、下班之前打卡
                        left_early.append(emp.name)  # 加入早退名单
            if is_absent:  # 如果仍然是缺席状态
                absent_list.append(emp.name)  # 加入缺席名单
        else:  # 该员工没有打卡记录
            absent_list.append(emp.name)  # 加入缺席名单

    emp_count = len(o.EMPLOYEES)  # 员工总人数
    print("--------" + date + "--------")
    print("应到人数:" + str(emp_count))
    print("缺席人数:" + str(len(absent_list)))
    absent_name = ""  # 缺席名单
    if len(absent_list) == 0:  # 如果没有缺席的
        absent_name = "(空)"
    else:  # 有缺席的
        for name in absent_list:  # 遍历缺席列表
            absent_name += name + " "  # 拼接名字
    print("缺席名单:" + absent_name)
    print("迟到人数:" + str(len(late_list)))
    late_name = ""  # 迟到名单
    if len(late_list) == 0:  # 如果没有迟到的
        late_name = "(空)"
    else:  # 有迟到的
        for name in late_list:  # 遍历迟到列表
            late_name += name + " "  # 拼接名字
    print("迟到名单:" + str(late_name))
    print("早退人数:" + str(len(left_early)))
    early_name = ""  # 早退名单
    if len(left_early) == 0:  # 如果没有早退的
        early_name = "(空)"
    else:  # 有早退的
        for name in left_early:  # 遍历早退列表
            early_name += name + " "  # 拼接名字
    print("早退名单:" + early_name)


# 创建上个月打卡记录月报
def get_pre_month_report():
    today = datetime.date.today()  # 得到今天的日期
    pre_month_first_day = datetime.date(today.year, today.month - 1, 1)  # 获得上个月的第一天的日期
    pre_month = pre_month_first_day.strftime("%Y-%m")  # 转成年月格式字符串
    get_month_report(pre_month)  # 生成上个月的月报


# 创建指定月份的打卡记录月报
def get_month_report(month):
    io.load_work_time_config()  # 读取上下班时间
    date = datetime.datetime.strptime(month, "%Y-%m")  # 月份转为时间对象
    monthRange = calendar.monthrange(date.year, date.month)[1]  # 该月最后一天的天数
    month_first_day = datetime.date(date.year, date.month, 1)  # 该月的第一天
    month_last_day = datetime.date(date.year, date.month, monthRange)  # 该月的最后一天

    clock_in = "I"  # 正常上班打卡标志
    clock_out = "O"  # 正常下班打卡标志
    late = "L"  # 迟到标志
    left_early = "E"  # 早退标志
    absent = "A"  # 缺席标志

    lock_report = dict()  # 键为员工名,值为员工打卡情况列表

    for emp in o.EMPLOYEES:
        emp_lock_data = []  # 员工打卡情况列表
        if emp.name in o.LOCK_RECORD.keys():  # 如果员工有打卡记录
            emp_lock_list = o.LOCK_RECORD.get(emp.name)  # 从打卡记录中获取该员工的记录
            index_day = month_first_day  # 遍历日期,从该月第一天开始
            while index_day <= month_last_day:
                is_absent = True  # 缺席状态
                earliest_time = datetime.datetime.strptime(str(index_day) + " 00:00:00", "%Y-%m-%d %H:%M:%S")  # 当天0点
                noon_time = datetime.datetime.strptime(str(index_day) + " 12:00:00", "%Y-%m-%d %H:%M:%S")  # 当天中午12点
                latest_time = datetime.datetime.strptime(str(index_day) + " 23:59:59", "%Y-%m-%d %H:%M:%S")  # 当天0点之前
                work_time = datetime.datetime.strptime(str(index_day) + " " + o.WORK_TIME,
                                                       "%Y-%m-%d %H:%M:%S")  # 当天上班时间
                closing_time = datetime.datetime.strptime(str(index_day) + " "
                                                          + o.CLOSING_TIME, "%Y-%m-%d %H:%M:%S")  # 当天下班时间
                emp_today_data = ""  # 员工打卡标记汇总

                for lock_time_str in emp_lock_list:  # 遍历所有打卡记录
                    lock_time = datetime.datetime.strptime(lock_time_str, "%Y-%m-%d %H:%M:%S")  # 打卡记录转为日期格式
                    if earliest_time < lock_time < latest_time:  # 如果当前日期有打卡记录
                        is_absent = False  # 不缺席
                        if lock_time <= work_time:  # 上班时间前打卡
                            emp_today_data += clock_in  # 追加正常上班打卡标志
                        elif lock_time >= closing_time:  # 下班时间后打卡
                            emp_today_data += clock_out  # 追加正常下班打卡标志
                        elif work_time < lock_time <= noon_time:  # 上班时间后、中午之前打卡
                            emp_today_data += late  # 追加迟到标志
                        elif noon_time < lock_time < closing_time:  # 中午之后、下班之前打卡
                            emp_today_data += left_early  # 追加早退标志
                if is_absent:  # 如果缺席
                    emp_today_data = absent  # 直接赋予缺席标志
                emp_lock_data.append(emp_today_data)  # 员工打卡标记添加到打卡情况列表中
                index_day = index_day + datetime.timedelta(days=1)  # 遍历天数递增
        else:  # 没有打卡记录的员工
            index_day = month_first_day  # 从该月第一天开始
            while index_day <= month_last_day:  # 遍历整月
                emp_lock_data.append(absent)  # 每天都缺席
                index_day = index_day + datetime.timedelta(days=1)  # 日期递增
        lock_report[emp.name] = emp_lock_data  # 将打卡情况列表保存到该员工之下

    report = "\"姓名/日期\""  # cvs文件的文本内容,第一行第一列
    index_day = month_first_day  # 从该月第一天开始
    while index_day <= month_last_day:  # 遍历整月
        report += ",\"" + str(index_day) + "\""  # 添加每一天的日期
        index_day = index_day + datetime.timedelta(days=1)  # 日期递增
    report += "\n"

    for emp in lock_report.keys():  # 遍历报表中的所有员工
        report += "\"" + emp + "\""  # 第一列为员工名
        data_list = lock_report.get(emp)  # 取出员工的打卡情况列表
        for data in data_list:  # 取出每一天的打卡情况
            text = ""  # CSV中显示的内容
            if absent == data:  # 如果是缺席
                text = "【缺席】"
            elif clock_in in data and clock_out in data:  # 如果是全勤,不考虑迟到和早退
                text = ""  # 显示空白
            else:  # 如果不是全勤
                if late in data and clock_in not in data:  # 有迟到记录且无上班打卡
                    text += "【迟到】"
                if left_early in data and clock_out not in data:  # 有早退记录且无下班打卡
                    text += "【早退】"
                if clock_out not in data and left_early not in data:  # 无下班打卡和早退记录
                    text += "【下班未打卡】"
                if clock_in not in data and late not in data:  # 有无上班打卡和迟到记录
                    text += "【上班未打卡】"
            report += ",\"" + text + "\""
        report += "\n"

    title_date = month_first_day.strftime("%Y{y}%m{m}").format(y="年", m="月")  # csv文件标题日期
    file_name = title_date + "考勤月报"  # CSV的文件名
    io.create_CSV(file_name, report)  # 生成csv文件


# 检查id是否存在
def check_id(id):
    for emp in o.EMPLOYEES:
        if str(id) == str(emp.id):
            return True
    return False


# 保存上下班时间
def save_work_time(work_time, close_time):
    o.WORK_TIME = work_time
    o.CLOSING_TIME = close_time
    io.save_work_time_config()  # 上下班时间保存到文件中


# 加载数据
def load_emp_data():
    io.checking_data_files()  # 文件自检
    io.load_users()  # 载入管理员账号
    io.load_lock_record()  # 载入打卡记录
    io.load_employee_info()  # 载入员工信息
    io.load_employee_pic()  # 载入员工照片

二、人脸识别服务模块:身份验证的超级慧眼

人脸识别服务模块宛如拥有一双超级慧眼,在员工打卡的瞬间洞察一切,精准识别身份。

导入包,为这双慧眼注入强大的识别能力源泉。全局变量则像是为慧眼设定的独特视角与敏感度参数,使其能在复杂环境中迅速锁定目标。

训练识别器,犹如对慧眼进行高强度的特训,通过大量数据的学习与分析,让其能够准确区分每一张人脸的细微差异,不断提升识别的准确率与速度。

发现人脸功能,恰似慧眼扫视人群的瞬间感知,在摄像头捕捉到画面的刹那,便能精准定位人脸位置,无论光线明暗、角度各异,都难以逃脱其敏锐的目光。

识别人脸,则是这双慧眼的核心使命,在瞬间完成对员工身份的确认,将识别结果反馈给系统,决定打卡的成功与否。这一过程快速而精准,有效防止了代打卡等作弊行为,为企业考勤的公正性与严肃性保驾护航。

"""
人脸识别服务
"""

import cv2
import numpy as np
import os

RECOGNIZER = cv2.face.LBPHFaceRecognizer_create()  # LBPH识别器
# RECOGNIZER = cv2.face.EigenFaceRecognizer_create()#特征脸识别器
# RECOGNIZER = cv2.face.FisherFaceRecognizer_create()  # LBPH识别器
PASS_CONF = 45  # 最高评分,LBPH最高建议用45,特征脸最高建议用22000
FACE_CASCADE = cv2.CascadeClassifier(os.getcwd() + "\\cascades\\haarcascade_frontalface_default.xml")  # 加载人脸识别级联分类器


# 训练识别器
def train(photos, lables):
    RECOGNIZER.train(photos, np.array(lables))  # 识别器开始训练


# 识别器识别图像中的人脸
def recognise_face(photo):
    label, confidence = RECOGNIZER.predict(photo)  # 识别器开始分析人脸图像
    if confidence > PASS_CONF:  # 忽略评分大于最高评分的结果
        return -1
    return label


# 判断图像中是否有正面人脸
def found_face(gary_img):
    faces = FACE_CASCADE.detectMultiScale(gary_img, 1.15, 4)  # 找出图像中所有的人脸
    return len(faces) > 0  # 返回人脸数量大于0的结果

这两大服务模块相辅相成、协同作战,共同构建起 Python+OpenCV 员工打卡系统坚不可摧的智能中枢。关注我们的博客,更多关于打卡系统的深度奥秘即将揭晓,带你领略智能考勤技术的无限魅力与广阔前景!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

手搓人生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值