task_auto_plan/include/app.hpp

241 lines
6.9 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#ifndef ATTENDANCE_SYSTEM_APP_HPP
#define ATTENDANCE_SYSTEM_APP_HPP
#include <string>
#include <vector>
#include <map>
#include <ctime>
#include <memory>
#include <functional>
#include <algorithm>
#include <sstream>
#include <iomanip>
#include <stdexcept>
#include <cassert>
// ============================================================
// 常量与枚举
// ============================================================
/// 打卡类型
enum class CheckType {
Unknown,
ClockIn, // 上班打卡
ClockOut // 下班打卡
};
/// 异常标记
enum class AbnormalFlag {
None,
Late, // 迟到
EarlyLeave, // 早退
Absenteeism // 旷工
};
/// 报表输出格式
enum class ReportFormat {
Excel,
PDF
};
/// 预警发送状态
enum class AlertStatus {
Pending,
Sent,
Failed,
Read
};
/// 角色类型RBAC
enum class RoleType {
Employee,
DeptManager,
HRAdmin,
SystemAdmin
};
// ============================================================
// 数据结构定义
// ============================================================
/// 员工信息
struct Employee {
std::string employeeId;
std::string name;
std::string department;
std::string position;
std::string shiftId;
std::string phone;
RoleType role{RoleType::Employee};
// 脱敏手机号显示后4位明文
std::string maskedPhone() const {
if (phone.length() != 11) return "***";
return "*******" + phone.substr(7);
}
};
/// 排班规则
struct ShiftRule {
std::string shiftId;
std::string shiftName;
int startHour{9}; // 上班小时
int startMin{0}; // 上班分钟
int endHour{18}; // 下班小时
int endMin{0}; // 下班分钟
int flexWindow{30}; // 弹性时间窗口(分钟)
int graceLate{15}; // 迟到宽限分钟
/// 获取上班时间(分钟偏移量)
int workStartMinutes() const { return startHour * 60 + startMin; }
/// 获取下班时间(分钟偏移量)
int workEndMinutes() const { return endHour * 60 + endMin; }
};
/// 打卡流水记录
struct CheckInRecord {
std::string recordId;
std::string employeeId;
std::time_t timestamp{0};
CheckType type{CheckType::Unknown};
std::string deviceId;
std::string latitude;
std::string longitude;
bool verified{false};
};
/// 考勤核算结果(按天)
struct DailyAttendance {
std::string dateStr;
std::string employeeId;
int expectedMinutes{0}; // 应出勤分钟
int actualMinutes{0}; // 实际出勤分钟
int overtimeMinutes{0}; // 加班分钟
int leaveDeduction{0}; // 调休抵扣分钟
AbnormalFlag abnormal{AbnormalFlag::None};
/// 有效出勤率(%
double attendanceRate() const {
if (expectedMinutes == 0) return 100.0;
return 100.0 * actualMinutes / expectedMinutes;
}
/// 是否异常
bool hasAbnormal() const { return abnormal != AbnormalFlag::None; }
std::string abnormalStr() const {
switch (abnormal) {
case AbnormalFlag::Late: return "迟到";
case AbnormalFlag::EarlyLeave: return "早退";
case AbnormalFlag::Absenteeism: return "旷工";
default: return "正常";
}
}
};
/// 异常预警日志
struct AlertLog {
std::string alertId;
std::string employeeId;
AbnormalFlag type{AbnormalFlag::None};
std::time_t occurTime{0};
std::string channel; // 通知渠道:站内信/短信/企业微信
AlertStatus status{AlertStatus::Pending};
int retryCount{0};
};
/// 报表任务
struct ReportTask {
std::string taskId;
std::string requester;
std::string deptId;
std::string dateRangeBegin;
std::string dateRangeEnd;
ReportFormat format{ReportFormat::Excel};
std::string status{"Pending"}; // Pending / Running / Done / Failed
std::string downloadUrl;
std::time_t createTime{0};
};
/// 权限配置RBAC
struct Permission {
std::string resource; // 资源路径,如 "/api/v1/reports"
std::string action; // 操作READ / WRITE / DELETE
};
// ============================================================
// 业务逻辑类
// ============================================================
class AttendanceService {
public:
AttendanceService();
// ---- 员工管理 ----
void addEmployee(const Employee& emp);
const Employee* findEmployee(const std::string& id) const;
std::vector<Employee> getEmployeesByDept(const std::string& dept) const;
// ---- 排班管理 ----
void addShiftRule(const ShiftRule& rule);
const ShiftRule* findShift(const std::string& shiftId) const;
// ---- 打卡处理 ----
CheckInRecord processCheckIn(const std::string& employeeId,
CheckType type,
const std::string& deviceId,
std::time_t timestamp);
std::vector<CheckInRecord> getRecords(const std::string& employeeId) const;
// ---- 考勤核算 ----
DailyAttendance calculateDaily(const std::string& employeeId,
const std::string& dateStr);
std::vector<DailyAttendance> generateReport(const std::string& deptId,
const std::string& dateBegin,
const std::string& dateEnd);
// ---- 异常预警 ----
AlertLog createAlert(const std::string& employeeId, AbnormalFlag type);
std::vector<AlertLog> getAlerts(const std::string& employeeId) const;
// ---- 报表任务 ----
ReportTask createReportTask(const std::string& requester,
const std::string& deptId,
const std::string& dateBegin,
const std::string& dateEnd,
ReportFormat fmt);
void completeTask(const std::string& taskId, const std::string& url);
// ---- 工具 ----
static std::string timeToString(std::time_t t);
static std::string currentDateStr();
static std::time_t parseDate(const std::string& dateStr);
private:
std::map<std::string, Employee> employees_;
std::map<std::string, ShiftRule> shifts_;
std::vector<CheckInRecord> records_;
std::vector<AlertLog> alerts_;
std::vector<ReportTask> tasks_;
int idCounter_{0};
std::string nextId();
int minutesFromMidnight(std::time_t t) const;
bool isSameDate(std::time_t t, const std::string& dateStr) const;
};
// ============================================================
// 工具函数声明
// ============================================================
/// 脱敏工具:将敏感字符串中间部分替换为 '*'
std::string maskSensitive(const std::string& input, size_t visibleHead = 2, size_t visibleTail = 2);
/// 格式化输出一行分隔线
void printSeparator(char ch = '=', size_t count = 60);
#endif // ATTENDANCE_SYSTEM_APP_HPP