学生和教师管理系统设计

AI Content Team
22 分钟阅读

详细讲解在线教育平台中的用户管理、权限控制和交互流程

学生和教师管理系统设计

有效的用户管理是在线教育平台的核心。本文讲解如何设计灵活且高效的管理系统。

用户角色模型

角色定义

const roles = {
  ADMIN: {
    id: 'admin',
    name: '平台管理员',
    permissions: ['manage_all', 'view_all', 'edit_all', 'delete_all'],
  },
  TEACHER: {
    id: 'teacher',
    name: '教师',
    permissions: ['create_course', 'manage_student', 'grade_assignment', 'view_analytics'],
  },
  STUDENT: {
    id: 'student',
    name: '学生',
    permissions: ['view_course', 'submit_assignment', 'view_grade', 'participate_discussion'],
  },
  PARENT: {
    id: 'parent',
    name: '家长',
    permissions: ['view_student_progress', 'communicate_teacher'],
  },
};

// 权限检查
function hasPermission(user, requiredPermission) {
  const userRole = roles[user.role];
  return userRole.permissions.includes(requiredPermission);
}

教师管理功能

教师信息管理

function TeacherProfile() {
  const [teacher, setTeacher] = useState({
    id: '',
    name: '',
    email: '',
    phone: '',
    subject: '',
    qualification: '',
    experience: '',
    bio: '',
    avatar: '',
    courses: [],
    schedule: [],
  });
  
  const [courses, setCourses] = useState([]);
  
  useEffect(() => {
    // 获取教师课程列表
    fetchTeacherCourses().then(setCourses);
  }, [teacher.id]);
  
  return (
    <div className="teacher-profile">
      <section className="profile-header">
        <img src={teacher.avatar} alt={teacher.name} />
        <h1>{teacher.name}</h1>
        <p>{teacher.subject} 教师</p>
      </section>
      
      <section className="courses">
        <h2>我的课程</h2>
        <div className="course-list">
          {courses.map(course => (
            <CourseCard key={course.id} course={course} />
          ))}
        </div>
      </section>
      
      <section className="students">
        <h2>学生管理</h2>
        <StudentsList courses={courses} />
      </section>
    </div>
  );
}

学生管理功能

学生注册流程

function StudentSignup() {
  const [form, setForm] = useState({
    name: '',
    email: '',
    password: '',
    dateOfBirth: '',
    enrollClass: '',
  });
  
  const [courses, setCourses] = useState([]);
  
  useEffect(() => {
    // 获取可用课程
    fetchAvailableCourses().then(setCourses);
  }, []);
  
  const handleSubmit = async (e) => {
    e.preventDefault();
    
    try {
      const response = await api.post('/students/register', form);
      
      // 创建初始学习档案
      await api.post('/students/profile', {
        studentId: response.id,
        enrolledCourses: [form.enrollClass],
        enrollmentDate: new Date(),
      });
      
      // 重定向到仪表板
      navigate('/student/dashboard');
    } catch (error) {
      console.error('Registration failed:', error);
    }
  };
  
  return (
    <form onSubmit={handleSubmit}>
      <input
        type="text"
        placeholder="姓名"
        value={form.name}
        onChange={(e) => setForm({...form, name: e.target.value})}
      />
      <input
        type="email"
        placeholder="邮箱"
        value={form.email}
        onChange={(e) => setForm({...form, email: e.target.value})}
      />
      <input
        type="password"
        placeholder="密码"
        value={form.password}
        onChange={(e) => setForm({...form, password: e.target.value})}
      />
      
      <select
        value={form.enrollClass}
        onChange={(e) => setForm({...form, enrollClass: e.target.value})}
      >
        <option value="">选择课程</option>
        {courses.map(course => (
          <option key={course.id} value={course.id}>
            {course.name}
          </option>
        ))}
      </select>
      
      <button type="submit">注册</button>
    </form>
  );
}

学生进度追踪

学习档案数据模型

const studentProfile = {
  studentId: 'STU_001',
  enrolledCourses: [
    {
      courseId: 'CRS_001',
      courseName: 'Web 开发基础',
      enrollmentDate: '2025-01-01',
      status: 'active', // active, completed, dropped
      progress: 65, // 0-100 百分比
      totalModules: 10,
      completedModules: 6,
      assignments: [
        {
          id: 'ASG_001',
          title: 'HTML 基础',
          dueDate: '2025-01-15',
          status: 'submitted', // pending, submitted, graded
          grade: 90,
          feedback: '很好的工作!',
        },
      ],
      quizzes: [
        {
          id: 'QZ_001',
          title: 'CSS 基础测试',
          score: 85,
          totalScore: 100,
          date: '2025-01-10',
        },
      ],
    },
  ],
  overallGPA: 3.8,
  learningPath: 'Basic',
};

// 计算学习进度
function calculateProgress(course) {
  const completionRate = (course.completedModules / course.totalModules) * 100;
  
  const assignmentScore = course.assignments.length > 0
    ? course.assignments.reduce((sum, a) => sum + a.grade, 0) / course.assignments.length
    : 0;
  
  const quizScore = course.quizzes.length > 0
    ? course.quizzes.reduce((sum, q) => sum + (q.score / q.totalScore * 100), 0) / course.quizzes.length
    : 0;
  
  return {
    completion: completionRate,
    assignmentScore,
    quizScore,
    overall: (completionRate * 0.4 + assignmentScore * 0.4 + quizScore * 0.2),
  };
}

权限管理系统

权限检查中间件

// Express 中间件
function checkPermission(requiredPermission) {
  return async (req, res, next) => {
    try {
      const user = req.user;
      const role = roles[user.role];
      
      if (!role || !role.permissions.includes(requiredPermission)) {
        return res.status(403).json({
          error: 'Forbidden',
          message: '你没有权限执行此操作',
        });
      }
      
      next();
    } catch (error) {
      res.status(500).json({ error: 'Internal server error' });
    }
  };
}

// 使用示例
router.post('/courses/:id/grades', checkPermission('grade_assignment'), gradeAssignment);
router.post('/courses', checkPermission('create_course'), createCourse);
router.delete('/courses/:id', checkPermission('delete_all'), deleteCourse);

完整管理仪表板

function AdminDashboard() {
  const [stats, setStats] = useState({
    totalStudents: 0,
    totalTeachers: 0,
    activeCourses: 0,
    completionRate: 0,
  });
  
  const [users, setUsers] = useState([]);
  const [filter, setFilter] = useState('all'); // all, active, inactive
  
  useEffect(() => {
    fetchDashboardStats().then(setStats);
    fetchUsers().then(setUsers);
  }, []);
  
  return (
    <div className="admin-dashboard">
      <section className="stats-grid">
        <StatCard title="学生总数" value={stats.totalStudents} />
        <StatCard title="教师总数" value={stats.totalTeachers} />
        <StatCard title="活跃课程" value={stats.activeCourses} />
        <StatCard title="完成率" value={`${stats.completionRate}%`} />
      </section>
      
      <section className="users-management">
        <h2>用户管理</h2>
        
        <div className="filter-tabs">
          <button
            className={filter === 'all' ? 'active' : ''}
            onClick={() => setFilter('all')}
          >
            全部用户
          </button>
          <button
            className={filter === 'active' ? 'active' : ''}
            onClick={() => setFilter('active')}
          >
            活跃用户
          </button>
          <button
            className={filter === 'inactive' ? 'active' : ''}
            onClick={() => setFilter('inactive')}
          >
            非活跃用户
          </button>
        </div>
        
        <table className="users-table">
          <thead>
            <tr>
              <th>姓名</th>
              <th>邮箱</th>
              <th>角色</th>
              <th>加入日期</th>
              <th>状态</th>
              <th>操作</th>
            </tr>
          </thead>
          <tbody>
            {users.map(user => (
              <tr key={user.id}>
                <td>{user.name}</td>
                <td>{user.email}</td>
                <td>{roles[user.role].name}</td>
                <td>{formatDate(user.createdAt)}</td>
                <td>
                  <span className={`status status-${user.isActive ? 'active' : 'inactive'}`}>
                    {user.isActive ? '活跃' : '非活跃'}
                  </span>
                </td>
                <td>
                  <button onClick={() => editUser(user.id)}>编辑</button>
                  <button onClick={() => deleteUser(user.id)}>删除</button>
                </td>
              </tr>
            ))}
          </tbody>
        </table>
      </section>
    </div>
  );
}

最佳实践

应该做的事:

  • 实现清晰的角色权限模型
  • 定期备份用户数据
  • 提供用户活动审计日志
  • 建立数据隐私保护
  • 支持多种登录方式

不应该做的事:

  • 存储明文密码
  • 过度复杂的权限系统
  • 忽视用户隐私
  • 缺乏审计跟踪
  • 不安全的数据传输

测试清单

  • 所有权限检查工作正常
  • 数据隐私得到保护
  • 用户活动被正确记录
  • 性能在大用户量下可接受
  • 错误处理恰当