随着信息技术的快速发展,考勤管理作为组织管理的重要组成部分,需要更加高效、准确的系统来支持。传统的手工考勤方式存在效率低下、容易出错等问题。为了解决这些问题,我们提出了一个考勤模拟系统,旨在通过计算机程序实现自动化的考勤管理。
本系统旨在实现以下目标:
系统采用分层架构,主要分为以下几个层次:
typedef struct user {
char uid[30]; // 用户ID,用于唯一标识一个用户
char password[30]; // 用户密码,用于登录验证
} user;
typedef struct group {
char group_name[100]; // 组名,标识一个考勤组
int member[MAX_USER]; // 成员列表,记录属于该组的用户ID
int priority[MAX_USER]; // 成员优先级,通常管理员的优先级较高
} group;
typedef struct clockin {
time_t begin_time; // 打卡开始时间
time_t end_time; // 打卡结束时间
int in[MAX_USER]; // 用户打卡状态数组,记录哪些用户已打卡
int group_from; // 所属组,标识这个打卡记录属于哪个考勤组
} clockin;
user user_set[MAX_USER]; // 用户集合,存储所有用户的信息
int user_set_length = 0; // 用户集合的当前大小
group group_set[MAX_GROUP]; // 组集合,存储所有考勤组的信息
int group_set_length = 0; // 组集合的当前大小
clockin clockin_set[MAX_CLOCKIN]; // 打卡记录集合,存储所有打卡记录
int clockin_set_length = 0; // 打卡记录集合的当前大小
int current_user = -1; // 当前登录的用户ID
int global_target_group = -1; // 全局目标组,用于某些操作中的上下文信息
系统还提供了一些功能函数来处理数据集合,例如:
search_user(user usr)
: 在用户集合中搜索特定用户。search_uid(char *uid)
: 通过用户ID搜索用户。read_user_set()
和 write_user_set()
: 从文件读取和写入用户数据集合。read_group_set()
和 write_group_set()
: 从文件读取和写入组数据集合。read_clockin_set()
和 write_clockin_set()
: 从文件读取和写打卡记录集合。用户模块负责处理与用户相关的所有操作,包括用户注册、登录、信息管理等。
允许新用户创建账户,输入用户名和密码,并存储到用户数据集中。
允许用户通过输入用户名和密码登录系统,验证用户凭证。
用户可以查看和修改自己的个人信息,如更改密码等。
组模块管理用户的分组信息,包括创建组、管理组成员和查看组信息。
允许用户创建新的组,并设置组名,同时成为该组的管理员。
允许管理员邀请新成员加入组,设置成员的优先级(管理员或普通成员)。
允许用户查看自己所在的所有组及其成员信息。
打卡模块处理用户的日常打卡操作,包括打卡记录、打卡数据查看和打卡事件创建。
允许用户在指定时间内进行打卡操作,记录考勤时间。
允许用户查看自己的打卡记录,包括打卡时间和打卡状态。
允许有权限的用户(通常是管理员)发布新的打卡事件,设定打卡的起止时间和参与成员。
数据管理模块负责系统的数据持久化和读取,确保数据的一致性和完整性。
系统需要将用户数据、组数据和打卡数据存储在文件中,保证数据不会因程序关闭而 丢失。
系统启动时需要从文件中读取现有数据,恢复系统状态。
安全模块确保系统的安全性,包括密码加密和权限控制。
用户密码应进行加密存储,保证用户信息安全。
系统应提供基本的权限控制,确保用户只能访问授权的数据和功能。
用户界面模块提供与用户的交互界面,接收用户输入并展示处理结果。
系统通过命令行界面与用户交互,提供清晰的指令和反馈。
辅助功能模块提供一些辅助性的功能,如搜索、数据验证等。
提供搜索用户、组和打卡记录的功能。
对用户输入进行验证,确保数据的准确性和有效性。
目前所有打卡:
打卡编号: 0
起始时间: Fri Jan 20 09:00:00 2024
结束时间: Fri Jan 20 17:00:00 2024
组名: 组1
打卡情况:
用户1 - 已打卡
用户2 - 未打卡
管理员权限目录:
1. 查看打卡记录
2. 管理组成员
3. 创建打卡事件
打卡成功!
打卡时间:Fri Jan 20 09:30:00 2024
打卡时间:Fri Jan 20 09:30:00 2024
组名: 组1
成员打卡情况:
用户1 - 已打卡
用户2 - 未打卡
组名: 组1
打卡事件:
打卡编号: 0
起始时间: Fri Jan 20 09:00:00 2024
结束时间: Fri Jan 20 17:00:00 2024
在开发考勤模拟系统的过程中,我收获了许多宝贵的经验,也遇到了不少挑战。以下是我对整个项目过程的总结和反思。
项目启动初期,需求分析是关键步骤。通过与团队成员进行多轮讨论,我们明确了考勤模拟系统的核心需求,包括用户管理、组管理、打卡功能以及数据安全等。需求分析不仅帮助我们确定了系统目标和功能需求,还为后续的设计和实现奠定了坚实的基础。
系统设计阶段是将需求转化为具体实现的桥梁。我们采用了分层架构,明确了数据访问层、业务逻辑层和表示层的职责。分层架构提高了代码的可维护性和可扩展性,使得后续的功能扩展和维护更加方便。
数据结构的设计是系统设计的核心。我们定义了用户(User)、组(Group)和打卡记录(Clockin)三个主要的数据结构,并在全局变量中维护了这些数据集合的状态。在设计数据结构时,我们注重了数据的一致性和完整性,为后续的数据操作打下了坚实的基础。
在模块实现阶段,我们面临了如何高效管理用户、组和打卡数据的挑战。通过实现功能函数(如 search_user
、read_user_set
等),我们确保了数据操作的便利性和准确性。此外,我们还实现了数据持久化功能,确保系统的数据不会因为程序关闭而丢失。
用户界面是用户与系统交互的窗口。我们采用了命令行界面(CLI),因为它简单且易于实现。在设计用户界面时,我们注重了用户体验,提供了清晰的指令和反馈,使用户能够轻松地进行考勤操作。
安全性是系统设计中不可忽视的一部分。我们意识到用户密码的安全性至关重要,因此在设计安全模块时,采用了加密存储密码的策略。此外,我们还实现了基本的权限控制,以确保数据访问的安全性。
在测试与调试阶段,我们发现并解决了多个问题。通过不断的测试,我们优化了系统的性能,确保了系统的稳定性。调试过程中,我们使用了多种调试工具和技术,以确保及时发现并修复问题。
通过开发考勤模拟系统,我们团队学到了很多宝贵的经验。我们认识到了团队协作的重要性,以及在软件开发过程中持续沟通的必要性。此外,我们也意识到了代码的可读性和可维护性对于长期项目成功的重要性。
考勤模拟系统目前虽然已经实现了基本功能,但仍有改进和扩展的空间。未来,我们计划添加更多的功能,如图形用户界面(GUI)、移动设备兼容性以及更高级的安全特性。
以下是考勤模拟系统的完整代码实现:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<time.h>
// 定义最大用户数、最大组数和最大打卡记录数
#define MAX_USER 100
#define MAX_GROUP 1000
#define MAX_CLOCKIN 1000
// 打卡记录结构体
typedef struct clockin
{
time_t begin_time; // 打卡开始时间
time_t end_time; // 打卡结束时间
int in[MAX_USER]; // 用户打卡状态数组
int group_from; // 该打卡记录所属的组编号
}clockin;
// 用户组结构体
typedef struct group
{
char group_name[100]; // 组名
int member[MAX_USER]; // 组成员数组
int priority[MAX_USER]; // 用户在组中的优先级或角色
}group;
// 用户信息结构体
typedef struct user
{
char uid[30]; // 用户ID
char password[30]; // 用户密码
}user;
// 用户集合数组和长度
user user_set[MAX_USER];
int user_set_length = 0;
// 组集合数组和长度
group group_set[MAX_GROUP];
int group_set_length = 0;
// 打卡记录集合数组和长度
clockin clockin_set[MAX_CLOCKIN];
int clockin_set_length = 0;
// 用户界面功能选择变量
int ui_func;
// 当前登录用户编号和目标组编号
int current_user = -1;
int global_target_group = -1;
// 搜索用户函数
int search_user(user usr)
{
int i;
for (i = 0; i < user_set_length; i++)
{
if (strcmp(user_set[i].uid, usr.uid) == 0)
{
return i;
}
}
return -1;
}
// 根据用户ID搜索用户编号
int search_uid(char *uid)
{
int i;
for (i = 0; i < user_set_length; i++)
{
if (strcmp(user_set[i].uid, uid) == 0)
{
return i;
}
}
return -1;
}
// 读取用户数据函数
void read_user_set()
{
FILE *userdata = fopen("data/user_data", "r+");
if (userdata == NULL)
{
printf("读取用户数据失败\n");
return;
}
fseek(userdata, 0, SEEK_END);
if (ftell(userdata) == 0) // 空文件
{
return;
}
fseek(userdata, 0, SEEK_SET);
fscanf(userdata, "%d", &user_set_length);
for (int i = 0 ; i < user_set_length; i++)
{
fscanf(userdata, "%s", user_set[i].uid);
fscanf(userdata, "%s", user_set[i].password);
}
fclose(userdata);
return;
}
// 写入用户数据函数
void write_user_set()
{
FILE *userdata = fopen("data/user_data", "w");
if (userdata == NULL)
{
printf("读取用户数据失败\n");
return;
}
fprintf(userdata, "%d\n", user_set_length);
for (int i = 0 ; i < user_set_length; i++)
{
fprintf(userdata, "%s\n", user_set[i].uid);
fprintf(userdata, "%s\n", user_set[i].password);
}
fclose(userdata);
return;
}
// 读取组数据函数
void read_group_set()
{
FILE *groupdata = fopen("data/group_data", "r+");
if (groupdata == NULL)
{
printf("读取组数据失败\n");
return;
}
fseek(groupdata, 0, SEEK_END);
if (ftell(groupdata) == 0) // 空文件
{
return;
}
fseek(groupdata, 0, SEEK_SET);
fscanf(groupdata, "%d", &group_set_length);
for (int j = 0; j < group_set_length; j++)
{
char temp_str[110];
fscanf(groupdata, "%s", &temp_str);
strcpy(group_set[j].group_name, temp_str);
fscanf(groupdata, "%s", &temp_str);
for (int i = 0 ; i < MAX_USER; i++)
{
group_set[j].member[i] = temp_str[i] - 48;
}
fscanf(groupdata, "%s", &temp_str);
for (int i = 0 ; i < MAX_USER; i++)
{
group_set[j].priority[i] = temp_str[i] - 48;
}
}
fclose(groupdata);
return;
}
// 写入组数据函数
void write_group_set()
{
FILE *groupdata = fopen("data/group_data", "w");
if (groupdata == NULL)
{
printf("读取组数据失败\n");
return;
}
fprintf(groupdata, "%d\n", group_set_length);
for (int i = 0 ; i < group_set_length; i++)
{
fprintf(groupdata, "%s\n", group_set[i].group_name);
for (int j = 0; j < MAX_USER; j++)
{
fprintf(groupdata, "%d", group_set[i].member[j]);
}
fprintf(groupdata, "\n");
for (int j = 0; j < MAX_USER; j++)
{
fprintf(groupdata, "%d", group_set[i].priority[j]);
}
fprintf(groupdata, "\n");
}
fclose(groupdata);
return;
}
// 检查用户是否在组中
int is_usr_in_group(int groupNo, int usr)
{
return group_set[groupNo].member[usr];
}
// 检查打卡记录是否在组中
int is_clockin_in_group(int groupNo, int clockinNo)
{
return clockin_set[clockinNo].group_from == groupNo;
}
// 用户ID转换为用户编号
int uid_2_usr(char *uid)
{
for (int i = 0; i < MAX_USER; i++)
{
if (strcmp(user_set[i].uid, uid) == 0)
{
return i;
}
}
return -1;
}
// 读取打卡记录数据函数
void read_clockin_set()
{
FILE *clockindata = fopen("data/clockin_data", "r+");
if (clockindata == NULL)
{
printf("读取打卡数据失败\n");
return;
}
for (int i = 0; i < MAX_CLOCKIN; i++)
{
clockin_set[i].group_from = -1;
}
fseek(clockindata, 0, SEEK_END);
if (ftell(clockindata) == 0) // 空文件
{
return;
}
fseek(clockindata, 0, SEEK_SET);
fscanf(clockindata, "%d", &clockin_set_length);
for (int j = 0; j < clockin_set_length; j++)
{
char temp_str[110];
long temp_long;
int temp_int;
fscanf(clockindata, "%ld", &temp_long);
clockin_set[j].begin_time = temp_long;
fscanf(clockindata, "%ld", &temp_long);
clockin_set[j].end_time = temp_long;
fscanf(clockindata, "%s", &temp_str);
for (int i = 0 ; i < MAX_USER; i++)
{
clockin_set[j].in[i] = temp_str[i] - 48;
}
fscanf(clockindata, "%d", &temp_int);
clockin_set[j].group_from = temp_int;
}
fclose(clockindata);
return;
}
// 写入打卡记录数据函数
void write_clockin_set()
{
FILE *clockindata = fopen("data/clockin_data", "w");
if (clockindata == NULL)
{
printf("读取打卡数据失败\n");
return;
}
fprintf(clockindata, "%d\n", clockin_set_length);
for (int i = 0 ; i < clockin_set_length; i++)
{
fprintf(clockindata, "%ld\n", clockin_set[i].begin_time);
fprintf(clockindata, "%ld\n", clockin_set[i].end_time);
for (int j = 0; j < MAX_USER; j++)
{
fprintf(clockindata, "%d", clockin_set[i].in[j]);
}
fprintf(clockindata, "\n");
fprintf(clockindata, "%d\n", clockin_set[i].group_from);
}
fclose(clockindata);
return;
}
// 检查用户是否在打卡记录中
int is_usr_in_clockin(int clockinNo)
{
return group_set[clockin_set[clockinNo].group_from].member[current_user];
}
int main()
{
ui_func = -1;
// -2 -- welcome已登录
// -1 -- welcome未登录
// 0 -- 登录界面
// 1 -- 注册界面
read_user_set();
read_group_set();
read_clockin_set();
while (1)
{
system("cls");
if (ui_func == 0) // 登录界面
{
user login_user;
printf("请先登录\n用户名:");
scanf("%s", login_user.uid);
printf("密码:");
scanf("%s", login_user.password);
fflush(stdin);
if (search_user(login_user) == -1) // 未注册
{
printf("未找到该用户,是否注册?(y/n)\n");
int temp_i = 1;
char temp_c;
while (temp_i)
{
system("cls");
printf("未找到该用户,是否注册?(y/n)\n");
scanf("%c", &temp_c);
fflush(stdin);
if (temp_c == 'y' || temp_c == 'n')
break;
}
if (temp_c == 'y')
{
ui_func = 1;
continue;
}
else if (temp_c == 'n')
{
ui_func = -1;
continue;
}
}
else
{
int No = search_user(login_user);
if (strcmp(login_user.password, user_set[No].password) == 0)
{
printf("登录成功\n");
current_user = No;
ui_func = -2;
}
else
{
printf("密码错误\n");
getchar();
}
}
}
else if (ui_func == 1) // 注册界面
{
user register_user;
char re_password[30];
printf("请先注册\n用户名:");
scanf("%s", register_user.uid);
printf("密码:");
scanf("%s", register_user.password);
printf("请重复密码:");
scanf("%s", &re_password);
fflush(stdin);
if (search_user(register_user) != -1)
{
int temp_i = 1;
char temp_c;
while (temp_i)
{
system("cls");
printf("该用户已存在,是否跳转到登录?(y/n)\n");
scanf("%c", &temp_c);
fflush(stdin);
if (temp_c == 'y' || temp_c == 'n')
break;
}
if (temp_c == 'y')
{
ui_func = 0;
continue;
}
else if (temp_c == 'n')
{
ui_func = -1;
continue;
}
}
if (strcmp(re_password, register_user.password) != 0)
{
printf("两次密码不相同,请再次输入\n");
ui_func = 1;
continue;
}
else
{
printf("注册成功,将自动为您登录\n");
strcpy(user_set[user_set_length].uid, register_user.uid);
strcpy(user_set[user_set_length].password, register_user.password);
user_set_length++;
write_user_set();
current_user = user_set_length - 1;
ui_func = -2;
}
}
else if (ui_func == -1) // welcome未登录
{
char temp_c;
while (1)
{
system("cls");
printf("这是一句welcome\n输入序号以访问功能\n1 登录\n2 注册\n");
scanf("%c", &temp_c);
fflush(stdin);
if (temp_c == '1' || temp_c == '2')
break;
}
if (temp_c == '1')
ui_func = 0;
else
ui_func = 1;
}
else if (ui_func == -2) // welcome已登录
{
int temp_i;
while (1)
{
system("cls");
printf("你好%s\n输入序号以访问功能\n1 打卡\n2 发布新的打卡\n3 查看我所在的组\n4 创建组\n5 管理组\n9 退出登录\n", user_set[current_user].uid);
scanf("%d", &temp_i);
fflush(stdin);
if ((temp_i >= 1 && temp_i <= 5) || temp_i == 9)
break;
}
if (temp_i == 1)
ui_func = 20;
else if (temp_i == 4)
ui_func = 10;
else if (temp_i == 3)
ui_func = 11;
else if (temp_i == 2)
ui_func = 21;
else if (temp_i == 9)
ui_func = 99;
else if (temp_i == 5)
ui_func = 30;
}
else if (ui_func == 10) // 创建组
{
const char end_str[10] = "$end";
char temp_uid[30];
char temp_group_name[100];
group_set[group_set_length].member[current_user] = 1;
group_set[group_set_length].priority[current_user] = 1;
system("cls");
printf("请输入小组名称:");
scanf("%s", &temp_group_name);
strcpy(group_set[group_set_length].group_name, temp_group_name);
while (1)
{
system("cls");
printf("小组名称:%s\n", group_set[group_set_length].group_name);
printf("请输入其它用户的用户名进行邀请\n管理员:%s\n", user_set[current_user].uid);
printf("用户:");
for (int i = 0; i < MAX_USER; i++)
{
if (group_set[group_set_length].member[i] && i != current_user)
{
printf("%s ", user_set[i].uid);
}
}
printf("\n\n其它用户的用户名(或输入%cend结束):", 36);
scanf("%s", &temp_uid);
fflush(stdin);
if (strcmp(end_str, temp_uid) == 0)
break;
if (search_uid(temp_uid) == -1)
{
printf("未找到该用户(按下回车以继续)");
getchar();
}
else
{
group_set[group_set_length].member[search_uid(temp_uid)] = 1;
group_set[group_set_length].priority[search_uid(temp_uid)] = 0;
}
}
system("cls");
printf("小组创建完毕\n小组名称:%s\n管理员:%s\n", group_set[group_set_length].group_name, user_set[current_user].uid);
printf("用户:");
for (int i = 0; i < MAX_USER; i++)
{
if (group_set[group_set_length].member[i] && i != current_user)
{
printf("%s ", user_set[i].uid);
}
}
printf("\n");
group_set_length++;
write_group_set();
ui_func = -2;
printf("按下回车以返回主界面\n");
getchar();
}
else if (ui_func == 11)
{
system("cls");
printf("%s所在的所有组:\n", user_set[current_user].uid);
for (int i = 0; i < MAX_GROUP; i++)
{
if (is_usr_in_group(i, current_user))
{
printf("%s\n", group_set[i].group_name);
}
}
ui_func = -2;
printf("\n按下回车以返回主界面\n");
getchar();
}
else if (ui_func == 20)
{
system("cls");
printf("%s目前有的所有打卡:\n", user_set[current_user].uid);
for (int i = 0; i < MAX_CLOCKIN; i++)
{
if (group_set[clockin_set[i].group_from].member[current_user])
{
struct tm *showtime;
printf("打卡编号:%d\n", i);
showtime = localtime(&clockin_set[i].begin_time);
printf("起始:%s", asctime(showtime));
showtime = localtime(&clockin_set[i].end_time);
printf("结束:%s", asctime(showtime));
if (clockin_set[i].in[current_user] == 1)
{
printf("已打卡\n\n");
}
else
{
printf("未打卡\n\n");
}
}
}
int target_clockin = -2;
printf("输入打卡编号进行打卡(或输入-1返回主界面)\n");
scanf("%d", &target_clockin);
fflush(stdin);
if (target_clockin == -1 || is_usr_in_clockin(target_clockin))
{
if (target_clockin == -1)
{
ui_func = -2;
continue;
}
else if (clockin_set[target_clockin].in[current_user] == 1)
{
printf("已打卡,请勿重复打卡。\n");
getchar();
continue;
}
else
{
time_t now_time = time(0);
time(&now_time);
if (now_time >= clockin_set[target_clockin].begin_time && now_time <= clockin_set[target_clockin].end_time)
{
printf("打卡成功。\n");
getchar();
clockin_set[target_clockin].in[current_user] = 1;
write_clockin_set();
continue;
}
else
{
printf("打卡失败。未在指定时间\n");
getchar();
continue;
}
}
}
else
{
printf("输入有误,请重新输入\n");
getchar();
}
}
else if (ui_func == 21)
{
system("cls");
int have_any_p = 0;
for (int i = 0; i < MAX_GROUP; i++)
{
if (is_usr_in_group(i, current_user))
{
if (group_set[i].priority[current_user])
have_any_p = 1;
}
}
if (have_any_p == 0)
{
ui_func = -2;
printf("你目前没有任何权限,即将返回\n");
getchar();
continue;
}
printf("%s所有有权限的组:\n", user_set[current_user].uid);
for (int i = 0; i < MAX_GROUP; i++)
{
if (is_usr_in_group(i, current_user))
{
if (group_set[i].priority[current_user])
printf("%s\n", group_set[i].group_name);
}
}
printf("\n输入选择要创建打卡的组的名称:");
char temp_gn[100];
scanf("%s", &temp_gn);
fflush(stdin);
int target_group = 0;
int flag = 0;
for (; target_group < MAX_GROUP && flag == 0; target_group++)
{
if (is_usr_in_group(target_group, current_user))
{
if (group_set[target_group].priority[current_user])
{
if (strcmp(temp_gn, group_set[target_group].group_name) == 0)
{
flag = 1;
break;
}
}
}
}
if (flag == 0)
{
printf("\n未找到该组,请重新输入\n");
getchar();
continue;
}
else
{
clockin_set[clockin_set_length].group_from = target_group;
int holding = 0; // 分钟
time_t begin = time(0);
time_t end = time(0);
struct tm *time_show;
time(&begin);
system("cls");
printf("请输入打卡持续时间(分钟):");
scanf("%d", &holding);
fflush(stdin);
end = begin + holding * 60;
printf("小组:%s\n", group_set[target_group].group_name);
time_show = localtime(&begin);
printf("起始时间:%s", asctime(time_show));
time_show = localtime(&end);
printf("结束时间:%s", asctime(time_show));
clockin_set[clockin_set_length].begin_time = begin;
clockin_set[clockin_set_length].end_time = end;
for (int i = 0; i < MAX_USER; i++)
{
clockin_set[clockin_set_length].in[i] = 0;
}
clockin_set_length++;
write_clockin_set();
ui_func = -2;
printf("\n打卡创建完毕,回车以返回主界面\n");
getchar();
}
}
else if (ui_func == 99)
{
ui_func = -1;
current_user = -1;
printf("已退出登录,将返回登录界面\n");
getchar();
}
else if (ui_func == 30)
{
system("cls");
printf("%s所在的所有组:\n", user_set[current_user].uid);
for (int i = 0; i < MAX_GROUP; i++)
{
if (is_usr_in_group(i, current_user))
{
printf("%s\n", group_set[i].group_name);
}
}
printf("\n输入选择要查看的组的名称(输入$back返回):");
char temp_gn[100];
scanf("%s", &temp_gn);
fflush(stdin);
if (strcmp("$back", temp_gn) == 0)
{
ui_func = -2;
continue;
}
int target_group = 0;
int flag = 0;
for (; target_group < MAX_GROUP && flag == 0; target_group++)
{
if (is_usr_in_group(target_group, current_user))
{
if (strcmp(temp_gn, group_set[target_group].group_name) == 0)
{
flag = 1;
break;
}
}
}
if (flag == 0)
{
printf("\n未找到该组,请重新输入\n");
getchar();
continue;
}
else
{
system("cls");
printf("小组:%s\n", group_set[target_group].group_name);
printf("管理员:");
for (int i = 0; i < MAX_USER; i++)
{
if (group_set[target_group].member[i] && group_set[target_group].priority[i])
{
printf("%s ", user_set[i].uid);
}
}
printf("\n");
printf("其它成员:");
for (int i = 0; i < MAX_USER; i++)
{
if (group_set[target_group].member[i] && group_set[target_group].priority[i] == 0)
{
printf("%s ", user_set[i].uid);
}
}
printf("\n");
if (group_set[target_group].priority[current_user])
{
ui_func = 31;
global_target_group = target_group;
continue;
}
else
{
printf("您是一般成员\n(回车以返回)");
getchar();
}
}
}
else if (ui_func == 31)
{
int temp_i;
while (1)
{
system("cls");
printf("小组:%s\n", group_set[global_target_group].group_name);
printf("管理员:");
for (int i = 0; i < MAX_USER; i++)
{
if (group_set[global_target_group].member[i] && group_set[global_target_group].priority[i])
{
printf("%s ", user_set[i].uid);
}
}
printf("\n");
printf("其它成员:");
for (int i = 0; i < MAX_USER; i++)
{
if (group_set[global_target_group].member[i] && group_set[global_target_group].priority[i] == 0)
{
printf("%s ", user_set[i].uid);
}
}
printf("\n您是管理员\n输入序号以访问功能\n1 查看个人数据\n2 查看打卡数据\n9 返回\n");
scanf("%d", &temp_i);
fflush(stdin);
if ((temp_i >= 1 && temp_i <= 2) || temp_i == 9)
break;
}
if (temp_i == 1)
{
char temp_uid[30];
while (1)
{
system("cls");
printf("小组:%s\n", group_set[global_target_group].group_name);
printf("全部成员:");
for (int i = 0; i < MAX_USER; i++)
{
if (group_set[global_target_group].member[i])
{
printf("%s ", user_set[i].uid);
}
}
printf("\n输入成员的uid以查看其打卡数据\n");
scanf("%s", &temp_uid);
fflush(stdin);
if (is_usr_in_group(global_target_group, uid_2_usr(temp_uid)))
{
break;
}
else
{
printf("\n该成员不在小组中\n");
getchar();
}
}
system("cls");
printf("成员:%s目前在组内所有打卡:\n", user_set[uid_2_usr(temp_uid)].uid);
int all = 0, intime = 0, outtime = 0;
for (int i = 0; i < MAX_CLOCKIN; i++)
{
if (group_set[clockin_set[i].group_from].member[uid_2_usr(temp_uid)] && clockin_set[i].group_from == global_target_group)
{
all++;
struct tm *showtime;
printf("打卡编号:%d\n", i);
showtime = localtime(&clockin_set[i].begin_time);
printf("起始:%s", asctime(showtime));
showtime = localtime(&clockin_set[i].end_time);
printf("结束:%s", asctime(showtime));
if (clockin_set[i].in[uid_2_usr(temp_uid)] == 1)
{
printf("已打卡\n\n");
intime++;
}
else
{
printf("未打卡\n\n");
outtime++;
}
}
}
printf("\n总打卡%d次,准时%d次,迟到%d次,到勤率%.2lf\n", all, intime, outtime, (double)intime/(double)all);
getchar();
continue;
}
else if (temp_i == 2)
{
int temp_int;
while (1)
{
system("cls");
printf("小组:%s\n", group_set[global_target_group].group_name);
printf("全部打卡:\n");
for (int i = 0; i < clockin_set_length; i++)
{
if (clockin_set[i].group_from == global_target_group)
{
struct tm *showtime;
printf("打卡编号:%d\n", i);
showtime = localtime(&clockin_set[i].begin_time);
printf("起始:%s", asctime(showtime));
showtime = localtime(&clockin_set[i].end_time);
printf("结束:%s", asctime(showtime));
}
}
printf("\n输入打卡的编号以查看其打卡数据\n");
scanf("%d", &temp_int);
fflush(stdin);
if (is_clockin_in_group(global_target_group, temp_int))
{
break;
}
else
{
printf("\n小组中没有该打卡\n");
getchar();
}
}
struct tm *showtime;
system("cls");
printf("打卡编号:%d\n", temp_int);
showtime = localtime(&clockin_set[temp_int].begin_time);
printf("起始:%s", asctime(showtime));
showtime = localtime(&clockin_set[temp_int].end_time);
printf("结束:%s", asctime(showtime));
int all = 0, intime = 0, outtime = 0;
printf("已签到:\n");
for (int i = 0; i < MAX_USER; i++)
{
if (group_set[global_target_group].member[i])
{
all++;
if (clockin_set[temp_int].in[i])
{
intime++;
printf("%s ", user_set[i].uid);
}
}
}
printf("\n未签到:\n");
for (int i = 0; i < MAX_USER; i++)
{
if (group_set[global_target_group].member[i])
{
if (clockin_set[temp_int].in[i] == 0)
{
outtime++;
printf("%s ", user_set[i].uid);
}
}
}
printf("\n总共%d人参与打卡,准时%d人,迟到%d人,到勤率%.2lf\n", all, intime, outtime, (double)intime/(double)all);
}
else
{
global_target_group = -1;
ui_func = -2;
continue;
}
getchar();
}
}
}
嗨,我是[LucianaiB](https://lucianaib.blog.csdn.net/ “LucianaiB”)。如果你觉得我的分享有价值,不妨通过以下方式表达你的支持:👍 点赞来表达你的喜爱,📁 关注以获取我的最新消息,💬 评论与我交流你的见解。我会继续努力,为你带来更多精彩和实用的内容。
点击这里👉[LucianaiB](https://lucianaib.blog.csdn.net/ “LucianaiB”) ,获取最新动态,⚡️ 让信息传递更加迅速。