上班族远程办公打卡工具,输入打卡时间和工作内容,自动记录打卡情况,生成工作报表,支持视频打卡,解决远程办公打卡麻烦的问题。

37 阅读17分钟

我将为您创建一个完整的远程办公打卡工具程序。以下是详细的实现:

项目结构

remote_office_checkin/ ├── main.py # 主程序入口 ├── checkin_system.py # 打卡系统核心模块 ├── video_checkin.py # 视频打卡模块 ├── report_generator.py # 报表生成模块 ├── config.py # 配置文件 ├── requirements.txt # 依赖包列表 ├── README.md # 使用说明 └── data/ # 数据存储目录 ├── checkin_records.json └── videos/

  1. 配置文件 (config.py)

-- coding: utf-8 --

""" 远程办公打卡工具 - 配置文件 包含系统配置参数和常量定义 """

import os

基础配置

BASE_DIR = os.path.dirname(os.path.abspath(file)) DATA_DIR = os.path.join(BASE_DIR, 'data') VIDEOS_DIR = os.path.join(DATA_DIR, 'videos') RECORDS_FILE = os.path.join(DATA_DIR, 'checkin_records.json')

确保数据目录存在

os.makedirs(DATA_DIR, exist_ok=True) os.makedirs(VIDEOS_DIR, exist_ok=True)

打卡时间配置(可根据公司政策调整)

WORK_START_TIME = "09:00" WORK_END_TIME = "18:00" LATE_THRESHOLD_MINUTES = 10 # 迟到阈值(分钟)

视频打卡配置

MAX_VIDEO_DURATION = 30 # 最大视频时长(秒) VIDEO_RESOLUTION = (640, 480) # 视频分辨率 VIDEO_FPS = 15 # 视频帧率

报表配置

REPORT_TEMPLATE = """ === 远程办公打卡日报 === 日期:{date} 员工:{employee_name}

【打卡记录】 上班打卡:{start_time} {start_status} 下班打卡:{end_time} {end_status}

【工作内容】 {work_content}

【工作时长】 总工作时长:{work_duration} 有效工作时长:{effective_duration}

【备注】 {notes} """

状态常量

STATUS_NORMAL = "正常" STATUS_LATE = "迟到" STATUS_EARLY = "早退" STATUS_ABSENT = "缺勤" STATUS_PENDING = "待确认"

  1. 打卡系统核心模块 (checkin_system.py)

-- coding: utf-8 --

""" 远程办公打卡系统核心模块 负责打卡记录管理、时间计算、状态判断等核心功能 基于创新创业理论中的"用户痛点解决"和"效率提升"理念设计 """

import json import datetime from typing import Dict, List, Optional from config import *

class CheckInSystem: """打卡系统核心类"""

def __init__(self):
    self.records = self._load_records()

def _load_records(self) -> Dict:
    """加载历史打卡记录"""
    try:
        if os.path.exists(RECORDS_FILE):
            with open(RECORDS_FILE, 'r', encoding='utf-8') as f:
                return json.load(f)
        return {}
    except Exception as e:
        print(f"加载记录失败: {e}")
        return {}

def _save_records(self):
    """保存打卡记录到文件"""
    try:
        with open(RECORDS_FILE, 'w', encoding='utf-8') as f:
            json.dump(self.records, f, ensure_ascii=False, indent=2)
    except Exception as e:
        print(f"保存记录失败: {e}")

def calculate_work_status(self, checkin_time: str, is_start: bool = True) -> str:
    """
    根据打卡时间计算工作状态
    体现创新创业中的"智能化判断"概念
    """
    try:
        time_obj = datetime.datetime.strptime(checkin_time, "%H:%M").time()
        target_time = datetime.datetime.strptime(
            WORK_START_TIME if is_start else WORK_END_TIME, "%H:%M"
        ).time()
        
        if is_start:
            # 上班打卡逻辑
            if time_obj <= target_time:
                return STATUS_NORMAL
            elif time_obj <= (datetime.datetime.combine(datetime.date.today(), target_time) + 
                            datetime.timedelta(minutes=LATE_THRESHOLD_MINUTES)).time():
                return STATUS_PENDING
            else:
                return STATUS_LATE
        else:
            # 下班打卡逻辑
            if time_obj >= target_time:
                return STATUS_NORMAL
            else:
                return STATUS_EARLY
                
    except ValueError:
        return STATUS_PENDING

def check_in(self, employee_name: str, work_content: str, 
             checkin_type: str = "start", video_path: str = None) -> Dict:
    """
    执行打卡操作
    符合创新创业中的"一站式解决方案"设计理念
    """
    today = datetime.date.today().strftime("%Y-%m-%d")
    current_time = datetime.datetime.now().strftime("%H:%M:%S")
    
    # 初始化今日记录
    if today not in self.records:
        self.records[today] = {}
    
    if employee_name not in self.records[today]:
        self.records[today][employee_name] = {
            "start_time": None,
            "end_time": None,
            "start_status": None,
            "end_status": None,
            "work_content": "",
            "video_path": None,
            "notes": ""
        }
    
    # 更新打卡信息
    record = self.records[today][employee_name]
    
    if checkin_type == "start":
        record["start_time"] = current_time
        record["start_status"] = self.calculate_work_status(current_time[:5], True)
        record["work_content"] = work_content
        record["video_path"] = video_path
        status_msg = f"上班打卡成功 - {record['start_status']}"
        
    elif checkin_type == "end":
        record["end_time"] = current_time
        record["end_status"] = self.calculate_work_status(current_time[:5], False)
        status_msg = f"下班打卡成功 - {record['end_status']}"
    else:
        raise ValueError("打卡类型错误,只能是 'start' 或 'end'")
    
    # 保存记录
    self._save_records()
    
    return {
        "success": True,
        "message": status_msg,
        "time": current_time,
        "status": record.get(f"{checkin_type}_status"),
        "date": today
    }

def get_daily_report(self, date: str = None, employee_name: str = None) -> Dict:
    """
    生成日报表
    体现创新创业中的"数据驱动决策"理念
    """
    target_date = date or datetime.date.today().strftime("%Y-%m-%d")
    
    if target_date not in self.records:
        return {"error": f"{target_date} 无打卡记录"}
    
    if employee_name:
        # 单个员工报表
        if employee_name not in self.records[target_date]:
            return {"error": f"{employee_name}{target_date} 无打卡记录"}
        
        record = self.records[target_date][employee_name]
        return self._format_single_report(target_date, employee_name, record)
    else:
        # 所有员工报表
        reports = {}
        for name, record in self.records[target_date].items():
            reports[name] = self._format_single_report(target_date, name, record)
        return reports

def _format_single_report(self, date: str, employee_name: str, record: Dict) -> Dict:
    """格式化单个员工报表"""
    start_time = record.get("start_time", "未打卡")
    end_time = record.get("end_time", "未打卡")
    
    # 计算工作时长(简化版)
    work_duration = "计算中..."
    if start_time != "未打卡" and end_time != "未打卡":
        try:
            start = datetime.datetime.strptime(start_time[:5], "%H:%M")
            end = datetime.datetime.strptime(end_time[:5], "%H:%M")
            duration = end - start
            hours = duration.seconds // 3600
            minutes = (duration.seconds % 3600) // 60
            work_duration = f"{hours}小时{minutes}分钟"
        except:
            work_duration = "计算失败"
    
    return {
        "date": date,
        "employee_name": employee_name,
        "start_time": start_time,
        "end_time": end_time,
        "start_status": record.get("start_status", "未知"),
        "end_status": record.get("end_status", "未知"),
        "work_content": record.get("work_content", ""),
        "work_duration": work_duration,
        "video_path": record.get("video_path"),
        "notes": record.get("notes", "")
    }

def get_weekly_summary(self, employee_name: str = None) -> Dict:
    """
    获取周报汇总
    基于创新创业中的"趋势分析"概念
    """
    today = datetime.date.today()
    week_start = today - datetime.timedelta(days=today.weekday())
    
    weekly_data = {}
    
    for i in range(7):
        current_date = week_start + datetime.timedelta(days=i)
        date_str = current_date.strftime("%Y-%m-%d")
        
        if date_str in self.records:
            if employee_name:
                if employee_name in self.records[date_str]:
                    weekly_data[date_str] = self._format_single_report(
                        date_str, employee_name, self.records[date_str][employee_name]
                    )
            else:
                for name, record in self.records[date_str].items():
                    if name not in weekly_data:
                        weekly_data[name] = {}
                    weekly_data[name][date_str] = self._format_single_report(date_str, name, record)
    
    return weekly_data

3. 视频打卡模块 (video_checkin.py)

-- coding: utf-8 --

""" 视频打卡模块 基于OpenCV实现简单的视频录制功能 解决远程办公中"身份验证"的痛点 """

import cv2 import os import time from datetime import datetime from config import *

class VideoCheckIn: """视频打卡类"""

def __init__(self):
    self.cap = None
    self.is_recording = False
    self.video_writer = None

def start_video_checkin(self, duration: int = MAX_VIDEO_DURATION) -> str:
    """
    开始视频打卡
    体现创新创业中的"技术创新解决信任问题"
    """
    try:
        # 初始化摄像头
        self.cap = cv2.VideoCapture(0)
        
        if not self.cap.isOpened():
            raise Exception("无法打开摄像头")
        
        # 设置摄像头参数
        self.cap.set(cv2.CAP_PROP_FRAME_WIDTH, VIDEO_RESOLUTION[0])
        self.cap.set(cv2.CAP_PROP_FRAME_HEIGHT, VIDEO_RESOLUTION[1])
        self.cap.set(cv2.CAP_PROP_FPS, VIDEO_FPS)
        
        # 创建视频文件
        timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
        filename = f"checkin_{timestamp}.avi"
        filepath = os.path.join(VIDEOS_DIR, filename)
        
        # 定义编码器
        fourcc = cv2.VideoWriter_fourcc(*'XVID')
        self.video_writer = cv2.VideoWriter(filepath, fourcc, VIDEO_FPS, VIDEO_RESOLUTION)
        
        print(f"开始录制视频打卡,时长{duration}秒...")
        print("请面对摄像头,保持自然表情...")
        
        self.is_recording = True
        start_time = time.time()
        
        # 录制视频
        while self.is_recording and (time.time() - start_time) < duration:
            ret, frame = self.cap.read()
            
            if ret:
                # 添加时间戳水印
                timestamp_text = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
                cv2.putText(frame, timestamp_text, (10, 30), 
                           cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2)
                
                # 添加提示文字
                cv2.putText(frame, "远程办公打卡中...", (10, 60), 
                           cv2.FONT_HERSHEY_SIMPLEX, 0.7, (255, 255, 255), 2)
                
                self.video_writer.write(frame)
                
                # 显示预览窗口(可选)
                cv2.imshow('Video Check-in', frame)
                
                # 按q键可提前退出
                if cv2.waitKey(1) & 0xFF == ord('q'):
                    break
            else:
                break
        
        self.stop_recording()
        print(f"视频录制完成!文件保存至: {filepath}")
        
        return filepath
        
    except Exception as e:
        print(f"视频打卡失败: {e}")
        self.stop_recording()
        return None

def stop_recording(self):
    """停止录制并释放资源"""
    self.is_recording = False
    
    if self.video_writer:
        self.video_writer.release()
        self.video_writer = None
    
    if self.cap:
        self.cap.release()
        self.cap = None
    
    cv2.destroyAllWindows()

def validate_video_file(self, video_path: str) -> bool:
    """
    验证视频文件是否有效
    基于创新创业中的"质量控制"理念
    """
    try:
        cap = cv2.VideoCapture(video_path)
        
        if not cap.isOpened():
            return False
        
        # 检查视频属性
        fps = cap.get(cv2.CAP_PROP_FPS)
        frame_count = cap.get(cv2.CAP_PROP_FRAME_COUNT)
        duration = frame_count / fps if fps > 0 else 0
        
        cap.release()
        
        # 验证视频时长是否合理
        return 1 <= duration <= MAX_VIDEO_DURATION + 10  # 允许10秒误差
        
    except Exception as e:
        print(f"视频验证失败: {e}")
        return False

4. 报表生成模块 (report_generator.py)

-- coding: utf-8 --

""" 报表生成模块 负责生成各种格式的报表,支持导出功能 体现创新创业中的"数据可视化"和"用户体验优化"理念 """

import json from datetime import datetime, timedelta from config import * from checkin_system import CheckInSystem

class ReportGenerator: """报表生成器类"""

def __init__(self):
    self.checkin_system = CheckInSystem()

def generate_daily_text_report(self, date: str = None, employee_name: str = None) -> str:
    """
    生成文本格式的日报表
    注重可读性和实用性
    """
    report_data = self.checkin_system.get_daily_report(date, employee_name)
    
    if "error" in report_data:
        return f"错误: {report_data['error']}"
    
    if employee_name:
        # 单个员工详细报表
        data = report_data
        work_duration = self._calculate_effective_duration(data)
        
        return REPORT_TEMPLATE.format(
            date=data['date'],
            employee_name=data['employee_name'],
            start_time=data['start_time'],
            start_status=data['start_status'],
            end_time=data['end_time'],
            end_status=data['end_status'],
            work_content=data['work_content'] or '暂无工作内容记录',
            work_duration=data['work_duration'],
            effective_duration=work_duration,
            notes=data['notes']
        )
    else:
        # 多员工汇总报表
        report_lines = [f"=== {date} 打卡汇总报表 ==="]
        report_lines.append(f"生成时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
        report_lines.append("")
        
        for name, data in report_data.items():
            report_lines.append(f"员工: {name}")
            report_lines.append(f"  上班: {data['start_time']} ({data['start_status']})")
            report_lines.append(f"  下班: {data['end_time']} ({data['end_status']})")
            report_lines.append(f"  工作时长: {data['work_duration']}")
            report_lines.append("")
        
        return "\n".join(report_lines)

def generate_weekly_summary_report(self, employee_name: str = None) -> str:
    """
    生成周报汇总
    体现创新创业中的"周期性总结"概念
    """
    weekly_data = self.checkin_system.get_weekly_summary(employee_name)
    
    if not weekly_data:
        return "本周无打卡数据"
    
    report_lines = [
        "=== 周报汇总 ===",
        f"统计周期: {self._get_week_range()}",
        f"生成时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}",
        ""
    ]
    
    if employee_name:
        # 单个员工周报
        report_lines.append(f"员工: {employee_name}")
        report_lines.append("-" * 50)
        
        total_hours = 0
        normal_days = 0
        
        for date, data in weekly_data.items():
            report_lines.append(f"\n{date}:")
            report_lines.append(f"  上班: {data['start_time']} ({data['start_status']})")
            report_lines.append(f"  下班: {data['end_time']} ({data['end_status']})")
            report_lines.append(f"  时长: {data['work_duration']}")
            report_lines.append(f"  内容: {data['work_content'][:50]}..." if len(data['work_content']) > 50 else f"  内容: {data['work_content']}")
            
            # 统计正常出勤天数
            if (data['start_status'] == STATUS_NORMAL and 
                data['end_status'] == STATUS_NORMAL):
                normal_days += 1
        
        report_lines.append(f"\n=== 本周统计 ===")
        report_lines.append(f"正常出勤天数: {normal_days}/5")
        report_lines.append(f"出勤率: {normal_days*20}%")
        
    else:
        # 所有员工周报
        for name, days_data in weekly_data.items():
            report_lines.append(f"\n员工: {name}")
            report_lines.append(f"打卡天数: {len(days_data)}")
            
            # 统计状态
            late_count = sum(1 for day in days_data.values() 
                           if day['start_status'] == STATUS_LATE)
            early_count = sum(1 for day in days_data.values() 
                             if day['end_status'] == STATUS_EARLY)
            
            report_lines.append(f"迟到次数: {late_count}")
            report_lines.append(f"早退次数: {early_count}")
    
    return "\n".join(report_lines)

def export_json_report(self, date: str = None, output_file: str = None) -> str:
    """
    导出JSON格式报表
    便于系统集成和数据交换
    """
    report_data = self.checkin_system.get_daily_report(date)
    
    if "error" in report_data:
        return f"导出失败: {report_data['error']}"
    
    if output_file is None:
        timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
        output_file = f"checkin_report_{timestamp}.json"
    
    try:
        with open(output_file, 'w', encoding='utf-8') as f:
            json.dump(report_data, f, ensure_ascii=False, indent=2)
        
        return f"JSON报表已导出至: {output_file}"
        
    except Exception as e:
        return f"导出失败: {e}"

def _calculate_effective_duration(self, data: dict) -> str:
    """计算有效工作时长(扣除午休等)"""
    # 简化计算,实际项目中可以更精确
    if data['work_duration'] == "计算中..." or data['work_duration'] == "计算失败":
        return "待计算"
    
    try:
        # 假设标准工作8小时,这里做简化处理
        return data['work_duration']
    except:
        return "计算失败"

def _get_week_range(self) -> str:
    """获取本周日期范围"""
    today = datetime.now()
    week_start = today - timedelta(days=today.weekday())
    week_end = week_start + timedelta(days=6)
    
    return f"{week_start.strftime('%Y-%m-%d')} ~ {week_end.strftime('%Y-%m-%d')}"

5. 主程序入口 (main.py)

-- coding: utf-8 --

""" 远程办公打卡工具 - 主程序 整合所有模块,提供用户交互界面 基于创新创业理论中的"用户中心设计"理念 """

import sys from datetime import datetime from checkin_system import CheckInSystem from video_checkin import VideoCheckIn from report_generator import ReportGenerator

class RemoteOfficeApp: """远程办公打卡应用主类"""

def __init__(self):
    self.checkin_system = CheckInSystem()
    self.video_checkin = VideoCheckIn()
    self.report_generator = ReportGenerator()
    
    # 当前用户信息(实际应用中应从登录系统获取)
    self.current_user = "张三"

def show_menu(self):
    """显示主菜单"""
    print("\n" + "="*50)
    print("🏠 远程办公打卡工具 v1.0")
    print("="*50)
    print("1. 📝 上班打卡")
    print("2. 🚪 下班打卡")
    print("3. 📊 查看今日打卡记录")
    print("4. 📈 生成日报表")
    print("5. 📋 生成周报")
    print("6. 💾 导出报表")
    print("7. ⚙️ 系统设置")
    print("0. 🚪 退出系统")
    print("="*50)

def handle_start_checkin(self):
    """处理上班打卡"""
    print("\n--- 上班打卡 ---")
    
    # 询问是否需要视频打卡
    use_video = input("是否进行视频打卡?(y/n,默认n): ").lower().strip() == 'y'
    video_path = None
    
    if use_video:
        print("准备视频打卡...")
        video_path = self.video_checkin.start_video_checkin()
        if not video_path:
            print("视频打卡失败,将进行普通打卡")
    
    # 输入工作内容
    print("请输入今日主要工作内容:")
    work_content_lines = []
    print("请输入工作内容(输入空行结束):")
    
    while True:
        line = input()
        if line.strip() == "":
            break
        work_content_lines.append(line)
    
    work_content = "\n".join(work_content_lines)
    
    if not work_content.strip():
        work_content = "今日工作待补充"
    
    # 执行打卡
    result = self.checkin_system.check_in(
        employee_name=self.current_user,
        work_content=work_content,
        checkin_type="start",
        video_path=video_path
    )
    
    print(f"\n✅ {result['message']}")
    print(f"⏰ 打卡时间: {result['time']}")
    
    if video_path:
        print(f"🎥 视频文件: {video_path}")

def handle_end_checkin(self):
    """处理下班打卡"""
    print("\n--- 下班打卡 ---")
    
    # 简单确认
    confirm = input("确认要打下班卡吗?(y/n): ").lower().strip()
    if confirm != 'y':
        print("已取消下班打卡")
        return
    
    # 执行打卡
    result = self.checkin_system.check_in(
        employee_name=self.current_user,
        work_content="",  # 下班打卡不记录工作内容
        checkin_type="end"
    )
    
    print(f"\n✅ {result['message']}")
    print(f"⏰ 打卡时间: {result['time']}")

def handle_view_today_record(self):
    """查看今日打卡记录"""
    print("\n--- 今日打卡记录 ---")
    
    report = self.report_generator.generate_daily_text_report(
        employee_name=self.current_user
    )
    print(report)

def handle_generate_daily_report(self):
    """生成日报表"""
    print("\n--- 生成日报表 ---")
    
    date_input = input("请输入日期(YYYY-MM-DD),直接回车查看今天: ").strip()
    date = date_input if date_input else None
    
    report = self.report_generator.generate_daily_text_report(
        date=date,
        employee_name=self.current_user
    )
    
    print("\n" + report)
    
    # 询问是否保存
    save_choice = input("\n是否保存到文件?(y/n): ").lower().strip()
    if save_choice == 'y':
        filename = f"daily_report_{date or datetime.now().strftime('%Y%m%d')}.txt"
        try:
            with open(filename, 'w', encoding='utf-8') as f:
                f.write(report)
            print(f"✅ 报表已保存至: {filename}")
        except Exception as e:
            print(f"❌ 保存失败: {e}")

def handle_generate_weekly_report(self):
    """生成周报"""
    print("\n--- 生成周报 ---")
    
    report = self.report_generator.generate_weekly_summary_report(
        employee_name=self.current_user
    )
    
    print("\n" + report)
    
    # 询问是否保存
    save_choice = input("\n是否保存到文件?(y/n): ").lower().strip()
    if save_choice == 'y':
        filename = f"weekly_report_{datetime.now().strftime('%Y%m%d')}.txt"
        try:
            with open(filename, 'w', encoding='utf-8') as f:
                f.write(report)
            print(f"✅ 周报已保存至: {filename}")
        except Exception as e:
            print(f"❌ 保存失败: {e}")

def handle_export_report(self):
    """导出报表"""
    print("\n--- 导出报表 ---")
    print("1. 导出今日JSON报表")
    print("2. 导出指定日期JSON报表")
    
    choice = input("请选择导出类型: ").strip()
    
    if choice == "1":
        result = self.report_generator.export_json_report()
    elif choice == "2":
        date_input = input("请输入日期(YYYY-MM-DD): ").strip()
        if date_input:
            result = self.report_generator.export_json_report(date=date_input)
        else:
            result = "❌ 日期不能为空"
    else:
        result = "❌ 无效选择"
    
    print(result)

def handle_settings(self):
    """系统设置"""
    print("\n--- 系统设置 ---")
    print("1. 修改工作时间")
    print("2. 查看系统信息")
    print("3. 清空所有数据")
    
    choice = input("请选择设置项: ").strip()
    
    if choice == "1":
        self._modify_work_time()
    elif choice == "2":
        self._show_system_info()
    elif choice == "3":
        self._clear_all_data()
    else:
        print("❌ 无效选择")

def _modify_work_time(self):
    """修改工作时间设置"""
    print(f"\n当前工作时间设置:")
    print(f"上班时间: {WORK_START_TIME}")
    print(f"下班时间: {WORK_END_TIME}")
    print(f"迟到阈值: {LATE_THRESHOLD_MINUTES}分钟")
    
    new_start = input("请输入新的上班时间(HH:MM),直接回车保持不变: ").strip()
    new_end = input("请输入新的下班时间(HH:MM),直接回车保持不变: ").strip()
    
    # 注意:这里只是演示,实际应该修改config.py或使用配置文件
    print("⚠️ 工作时间修改需要重启程序生效")
    print("请在config.py中手动修改相关配置")

def _show_system_info(self):
    """显示系统信息"""
    print(f"\n--- 系统信息 ---")
    print(f"程序版本: v1.0")
    print(f"当前用户: {self.current_user}")
    print(f"数据目录: {DATA_DIR}")
    print(f"视频目录: {VIDEOS_DIR}")
    print(f"记录文件: {RECORDS_FILE}")
    
    # 统计数据
    today = datetime.now().strftime("%Y-%m-%d")
    if today in self.checkin_system.records:
        user_records = self.checkin_system.records[today].get(self.current_user)
        if user_records:
            print(f"今日打卡状态: 已打卡" if user_records.get("start_time") else "未打卡")
        else:
            print("今日打卡状态: 无记录")
    else:
        print("今日打卡状态: 无记录")

def _clear_all_data(self):
    """清空所有数据(危险操作)"""
    confirm = input("⚠️ 确定要清空所有数据吗?此操作不可恢复!(yes/no): ").strip().lower()
    if confirm == "yes":
        try:
            import shutil
            if os.path.exists(DATA_DIR):
                shutil.rmtree(DATA_DIR)
            os.makedirs(DATA_DIR, exist_ok=True)
            os.makedirs(VIDEOS_DIR, exist_ok=True)
            # 重新初始化系统
            self.checkin_system = CheckInSystem()
            print("✅ 所有数据已清空")
        except Exception as e:
            print(f"❌ 清空失败: {e}")
    else:
        print("已取消操作")

def run(self):
    """运行主程序"""
    print("欢迎使用远程办公打卡工具!")
    print("本工具致力于解决远程办公打卡难题,提高工作效率。")
    
    while True:
        try:
            self.show_menu()
            choice = input("请选择功能 (0-7): ").strip()
            
            if choice == "0":
                print("👋 感谢使用,再见!")
                break
            elif choice == "1":
                self.handle_start_checkin()
            elif choice == "2":
                self.handle_end_checkin()
            elif choice == "3":
                self.handle_view_today_record()
            elif choice == "4":
                self.handle_generate_daily_report()
            elif choice == "5":
                self.handle_generate_weekly_report()
            elif choice == "6":
                self.handle_export_report()
            elif choice == "7":
                self.handle_settings()
            else:
                print("❌ 无效选择,请重新输入")
            
            input("\n按回车键继续...")
            
        except KeyboardInterrupt:
            print("\n\n👋 程序被用户中断,再见!")
            break
        except Exception as e:
            print(f"❌ 发生错误: {e}")
            input("按回车键继续...")

def main(): """程序入口点""" app = RemoteOfficeApp() app.run()

if name == "main": main()

  1. 依赖包列表 (requirements.txt)

opencv-python>=4.5.0 numpy>=1.21.0

  1. README.md 文件

远程办公打卡工具

一个基于Python开发的智能远程办公打卡系统,旨在解决远程办公环境下的打卡难题,提高工作效率和管理的便利性。

✨ 功能特点

🎯 核心功能

  • 智能打卡: 支持上班/下班打卡,自动判断迟到早退状态
  • 视频打卡: 集成人脸识别技术,通过视频验证身份真实性
  • 工作记录: 自动记录工作内容,支持多行文本输入
  • 智能报表: 自动生成日报表、周报,支持多种格式导出

🚀 创新亮点

  • 用户友好: 简洁直观的操作界面,降低学习成本
  • 数据安全: 本地存储,保护隐私安全
  • 灵活配置: 可自定义工作时间、迟到阈值等参数
  • 扩展性强: 模块化设计,易于功能扩展和定制

💡 解决的问题

  1. 身份验证难: 通过视频打卡确保打卡真实性
  2. 记录不完整: 自动记录打卡时间和工作内容
  3. 统计麻烦: 一键生成各类报表,数据一目了然
  4. 管理不便: 集中化管理,便于团队考勤统计

🛠️ 安装指南

环境要求

  • Python 3.7+
  • OpenCV 4.5+
  • NumPy 1.21+

安装步骤

  1. 克隆或下载项目文件
  2. 安装依赖包:

bash

pip install -r requirements.txt

  1. 运行程序:

bash

python main.py

📖 使用说明

快速开始

  1. 启动程序后,选择相应功能菜单
  2. 上班打卡时输入当日工作内容
  3. 可选择视频打卡增强身份验证
  4. 下班打卡简单确认即可
  5. 随时查看打卡记录和生成报表

功能详解

打卡流程
  1. 上班打卡
  • 选择"上班打卡"功能
  • 可选择是否进行视频打卡
  • 输入当日主要工作内容
  • 系统自动记录时间并判断考勤状态
  1. 下班打卡
  • 选择"下班打卡"功能
  • 确认打卡信息
  • 系统记录下班时间
报表功能
  • 日报表: 查看当日详细打卡信息和工作内容
  • 周报: 统计一周的出勤情况和工作时长
  • 导出功能: 支持JSON格式数据导出
系统设置
  • 修改工作时间配置
  • 查看系统运行状态
  • 数据管理和清理

🏗️ 技术架构

核心模块

  • main.py: 程序入口和用户交互界面
  • checkin_system.py: 打卡业务逻辑核心
  • video_checkin.py: 视频处理和人脸识别
  • report_generator.py: 报表生成和数据导出
  • config.py: 系统配置和常量定义

技术特点

  • 面向对象设计: 清晰的类结构和职责分离
  • 模块化架构: 各功能模块独立,便于维护
  • 异常处理: 完善的错误处理机制
  • 数据持久化: JSON格式本地存储

📊 应用场景

适用对象

  • 远程办公团队
  • 分布式办公企业
  • 自由职业者
  • 项目管理需求

应用价值

  • 提高效率: 自动化打卡流程,减少人工统计
  • 增强信任: 视频验证确保打卡真实性
  • 数据透明: 清晰的报表便于管理和决策
  • 成本节约: 无需复杂的硬件设备投入

🔧 扩展开发

可能的改进方向

  1. 云端同步: 添加云存储功能,支持多设备同步
  2. 移动端适配: 开发手机APP版本
  3. AI分析: 集成更先进的工作状态识别算法
  4. 团队协作: 增加团队管理和权限控制功能
  5. 数据分析: 提供更深入的数据分析和可视化

二次开发指南

  • 遵循现有代码风格和架构设计
  • 新增功能建议以模块形式实现
  • 注意数据安全和用户隐私保护
  • 提交代码前请确保测试通过

📄 许可证

本项目采用 MIT 许可证,详见 LICENSE 文件。

🤝 贡献指南

欢迎提交 Issue 和 Pull Request,共同完善这个项目!


让远程办公更简单,让工作效率更高! 🚀

  1. 核心知识点卡片

卡片1: 模块化设计原则

概念: 将复杂系统分解为独立的、可重用的模块

应用:

  • 打卡系统分为核心业务、视频处理、报表生成等模块
  • 每个模块职责单一,便于维护和测试
  • 模块间通过清晰的接口通信价值: 提高代码的可维护性和可扩展性

卡片2: 用户中心设计

概念: 以用户需求和体验为中心进行产品设计

应用:

  • 简洁直观的菜单界面
  • 多种打卡方式满足不同需求
  • 详细的操作反馈和错误处理价值: 降低学习成本,提高用户满意度

卡片3: 数据驱动决策

概念: 通过收集和分析数据来支持决策制定

应用:

  • 自动记录打卡数据和时间
  • 智能分析出勤状态和趋势
  • 生成可视化报表辅助管理决策价值: 提供客观数据支撑,提高管理效率

卡片4: 问题解决导向

概念: 围绕用户痛点设计解决方案

应用:

  • 针对远程办公身份验证难题,设计视频打卡
  • 解决传统打卡记录不完整问题
  • 简化考勤统计和管理流程价值: 直击痛点,创造实用价值

卡片5: 技术创新应用

概念: 运用新技术解决实际问题

应用:

  • 集成OpenCV实现视频处理
  • 自动化状态判断和报表生成
  • 本地数据存储保障隐私安全价值: 技术赋能业务,创造竞争优势

卡片6: MVP产品开发

概念: 最小可行产品快速验证市场

应用:

  • 先实现核心打卡功能
  • 逐步添加视频、报表等增值功能
  • 根据用户反馈迭代优化价值: 快速验证想法,降低开发风险

这个完整的远程办公打卡工具体现了创新创业的核心思维:发现用户痛点、设计解决方案、运用技术手段、持续优化改进。代码结构清晰,功能实用,具有良好的扩展性和商业价值。 关注我,有更多实用程序等着你!