sprint day1

1.项目预期任务量:15天
2.已花费时间:6天
3.剩余时间:9天
任务看板:

SCRUM会议照片:

产品状态:
登录界面以及登陆后系统的主页面
界面演示:

代码:
登录界面

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="https://cdn.tailwindcss.com"></script>
    <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/all.min.css" rel="stylesheet">
    <title>登录界面</title>
    <style>
        /* 添加自定义动画 */
        .animate-fade-in {
            animation: fadeIn 0.5s ease-in-out;
        }

        @keyframes fadeIn {
            from {
                opacity: 0;
                transform: translateY(-20px);
            }
            to {
                opacity: 1;
                transform: translateY(0);
            }
        }

        /* 按钮悬停动画 */
        .hover:scale-105 {
            transition: transform 0.3s ease;
        }
    </style>
</head>

<body class="bg-gradient-to-br from-blue-400 to-purple-500 h-screen flex justify-center items-center">
<div class="bg-white p-8 rounded-lg shadow-xl w-full max-w-md animate-fade-in">
    <h2 class="text-3xl font-extrabold text-center text-gray-800 mb-6">欢迎登录</h2>
    <form id="loginForm">
        <div class="mb-6">
            <label for="username" class="block text-gray-700 text-sm font-medium mb-2">
                <i class="fa-solid fa-user mr-1"></i> 用户名
            </label>
            <input type="text" id="username" name="username"
                   class="shadow appearance-none border border-gray-300 rounded w-full py-3 px-4 text-gray-700 leading-tight focus:outline-none focus:border-blue-500 focus:ring-blue-500 focus:ring-1"
                   placeholder="请输入用户名">
        </div>
        <div class="mb-8">
            <label for="password" class="block text-gray-700 text-sm font-medium mb-2">
                <i class="fa-solid fa-lock mr-1"></i> 密码
            </label>
            <input type="password" id="password" name="password"
                   class="shadow appearance-none border border-gray-300 rounded w-full py-3 px-4 text-gray-700 leading-tight focus:outline-none focus:border-blue-500 focus:ring-blue-500 focus:ring-1"
                   placeholder="请输入密码">
        </div>
        <div class="flex justify-center">
            <button type="submit"
                    class="bg-blue-500 hover:bg-blue-600 hover:scale-105 text-white font-bold py-3 px-6 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-400 focus:ring-opacity-50">
                <i class="fa-solid fa-sign-in mr-2"></i> 登录
            </button>
        </div>
    </form>
    <div id="errorMessage" class="text-red-500 text-center mt-6 hidden animate-fade-in">用户名或密码错误</div>
    <div id="serverError" class="text-red-500 text-center mt-6 hidden animate-fade-in">登录时发生错误,请稍后再试</div>
</div>

<script>
    const loginForm = document.getElementById('loginForm');
    const errorMessage = document.getElementById('errorMessage');
    const serverError = document.getElementById('serverError');

    loginForm.addEventListener('submit', function (e) {
        e.preventDefault();

        const username = document.getElementById('username').value;
        const password = document.getElementById('password').value;

        // 简单验证输入是否为空
        if (username === '' || password === '') {
            errorMessage.classList.remove('hidden');
            return;
        }

        const formData = new URLSearchParams();
        formData.append('username', username);
        formData.append('password', password);

        // 修改 fetch 部分为 POST 请求
        fetch('/login', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded'
            },
            body: new URLSearchParams({
                username: username,
                password: password
            })
        })
            .then(response => {
                if (response.ok) {
                    return response.json();
                }
                // 处理 HTTP 错误状态码
                if (response.status === 401) {
                    throw new Error('认证失败');
                }
                throw new Error('网络请求失败');
            })
            .then(data => {
                // 严格判断返回的 User 对象是否为 null
                if (data!== null && typeof data === 'object') {
                    // 使用 URL 参数传递数据
                    const queryString = Object.keys(data).map(key => `${encodeURIComponent(key)}=${encodeURIComponent(JSON.stringify(data[key]))}`).join('&');
                    window.location.href = `index.html?${queryString}`;
                } else {
                    // 处理业务逻辑错误
                    errorMessage.classList.remove('hidden');
                    serverError.classList.add('hidden');
                }
            })
            .catch(error => {
                console.error('Error:', error);
                if (error.message.includes('认证失败')) {
                    errorMessage.classList.remove('hidden');
                } else {
                    serverError.classList.remove('hidden');
                }
            });
    });
</script>
</body>

</html>

主功能界面

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <script src="https://cdn.tailwindcss.com"></script>
  <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/all.min.css" rel="stylesheet">
  <title>培训管理系统 - 首页</title>
  <style>
    body {
      font-family: 'Inter', sans-serif;
    }
  </style>
</head>

<body class="bg-gray-100">
<!-- 导航栏 -->
<nav class="bg-blue-600 p-4 text-white">
  <div class="container mx-auto flex justify-between items-center">
    <h1 class="text-2xl font-bold">培训管理系统</h1>
    <div class="flex space-x-4">
      <a href="#" class="hover:text-gray-300">首页</a>
      <a href="#" class="hover:text-gray-300">关于我们</a>
      <a href="#" class="hover:text-gray-300">联系我们</a>
      <button id="logoutButton" class="hover:text-gray-300 bg-red-500 px-4 py-2 rounded-md">退出登录</button>
    </div>
  </div>
</nav>

<!-- 主内容区域 -->
<!-- 主内容区域 -->
<main class="container mx-auto p-8">
  <h2 class="text-3xl font-bold text-gray-800 mb-6">功能列表</h2>
  <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
    <!-- 课程管理(保留原链接逻辑) -->
    <a href="#" id="courseManagement"
       class="bg-white p-6 rounded-lg shadow-md hover:shadow-lg transform hover:scale-105 transition duration-300">
      <i class="fa-solid fa-chalkboard-user text-3xl text-blue-600 mb-4"></i>
      <h3 class="text-xl font-bold text-gray-800 mb-2">课程管理</h3>
      <p class="text-gray-600">管理培训课程的相关信息。</p>
    </a>
    <!-- 培训管理(链接置空) -->
    <a href="#" id="trainingManagement"
       class="bg-white p-6 rounded-lg shadow-md hover:shadow-lg transform hover:scale-105 transition duration-300">
      <i class="fa-solid fa-graduation-cap text-3xl text-blue-600 mb-4"></i>
      <h3 class="text-xl font-bold text-gray-800 mb-2">培训管理</h3>
      <p class="text-gray-600">管理培训活动的安排与进度。</p>
    </a>
    <!-- 新员工培训(链接置空) -->
    <a href="#" id="newEmployeeTraining"
       class="bg-white p-6 rounded-lg shadow-md hover:shadow-lg transform hover:scale-105 transition duration-300">
      <i class="fa-solid fa-users text-3xl text-blue-600 mb-4"></i>
      <h3 class="text-xl font-bold text-gray-800 mb-2">新员工培训</h3>
      <p class="text-gray-600">为新员工提供入职培训。</p>
    </a>
    <!-- 试卷管理(链接置空) -->
    <a href="#" id="examPaperManagement"
       class="bg-white p-6 rounded-lg shadow-md hover:shadow-lg transform hover:scale-105 transition duration-300">
      <i class="fa-solid fa-file-lines text-3xl text-blue-600 mb-4"></i>
      <h3 class="text-xl font-bold text-gray-800 mb-2">试卷管理</h3>
      <p class="text-gray-600">管理培训相关的试卷。</p>
    </a>
    <!-- 题库管理(链接置空) -->
    <a href="#" id="questionBankManagement"
       class="bg-white p-6 rounded-lg shadow-md hover:shadow-lg transform hover:scale-105 transition duration-300">
      <i class="fa-solid fa-database text-3xl text-blue-600 mb-4"></i>
      <h3 class="text-xl font-bold text-gray-800 mb-2">题库管理</h3>
      <p class="text-gray-600">管理培训所需的题目。</p>
    </a>
    <!-- 独立考试(链接置空) -->
    <a href="#" id="independentExam"
       class="bg-white p-6 rounded-lg shadow-md hover:shadow-lg transform hover:scale-105 transition duration-300">
      <i class="fa-solid fa-pencil text-3xl text-blue-600 mb-4"></i>
      <h3 class="text-xl font-bold text-gray-800 mb-2">独立考试</h3>
      <p class="text-gray-600">安排独立的培训考试。</p>
    </a>
    <!-- 阅卷管理(链接置空) -->
    <a href="#" id="gradingManagement"
       class="bg-white p-6 rounded-lg shadow-md hover:shadow-lg transform hover:scale-105 transition duration-300">
      <i class="fa-solid fa-check text-3xl text-blue-600 mb-4"></i>
      <h3 class="text-xl font-bold text-gray-800 mb-2">阅卷管理</h3>
      <p class="text-gray-600">管理考试的阅卷工作。</p>
    </a>
    <!-- 题库练习(链接置空) -->
    <a href="#" id="questionBankPractice"
       class="bg-white p-6 rounded-lg shadow-md hover:shadow-lg transform hover:scale-105 transition duration-300">
      <i class="fa-solid fa-book-open text-3xl text-blue-600 mb-4"></i>
      <h3 class="text-xl font-bold text-gray-800 mb-2">题库练习</h3>
      <p class="text-gray-600">进行题库练习。</p>
    </a>
    <!-- 分类管理(链接置空) -->
    <a href="#" id="categoryManagement"
       class="bg-white p-6 rounded-lg shadow-md hover:shadow-lg transform hover:scale-105 transition duration-300">
      <i class="fa-solid fa-tags text-3xl text-blue-600 mb-4"></i>
      <h3 class="text-xl font-bold text-gray-800 mb-2">分类管理</h3>
      <p class="text-gray-600">管理培训内容的分类。</p>
    </a>
    <!-- 数据中心(链接置空) -->
    <a href="#" id="dataCenter"
       class="bg-white p-6 rounded-lg shadow-md hover:shadow-lg transform hover:scale-105 transition duration-300">
      <i class="fa-solid fa-chart-line text-3xl text-blue-600 mb-4"></i>
      <h3 class="text-xl font-bold text-gray-800 mb-2">数据中心</h3>
      <p class="text-gray-600">查看和分析培训相关的数据。</p>
    </a>
  </div>
</main>

<script>
  // 移除原链接批量设置逻辑(仅保留课程管理的原有逻辑,其他链接已手动置空)
  // 退出登录和角色控制逻辑保持不变
  const urlParams = new URLSearchParams(window.location.search);
  const userData = {};
  urlParams.forEach((value, key) => {
    try {
      userData[key] = JSON.parse(value);
    } catch (error) {
      userData[key] = value;
    }
  });

  // 仅为课程管理链接设置带参数的 href
  const courseLink = document.getElementById('courseManagement');
  if (courseLink) {
    const queryString = Object.keys(userData)
            .map(key => `${encodeURIComponent(key)}=${encodeURIComponent(JSON.stringify(userData[key]))}`)
            .join('&');
    courseLink.href = `course.html?${queryString}`; // 目标页面改为实际地址
  }

  const classLink = document.getElementById('categoryManagement');
  if (classLink) {
    const queryString = Object.keys(userData)
            .map(key => `${encodeURIComponent(key)}=${encodeURIComponent(JSON.stringify(userData[key]))}`)
            .join('&');
    classLink.href = `classification_management.html?${queryString}`; // 目标页面改为实际地址
  }

  const dataLink = document.getElementById('dataCenter');
  if (dataLink) {
    const queryString = Object.keys(userData)
            .map(key => `${encodeURIComponent(key)}=${encodeURIComponent(JSON.stringify(userData[key]))}`)
            .join('&');
    dataLink.href = `data_center.html?${queryString}`; // 目标页面改为实际地址
  }

  const independentExamLink = document.getElementById('independentExam');
  if (independentExamLink) {
    const queryString = Object.keys(userData)
            .map(key => `${encodeURIComponent(key)}=${encodeURIComponent(JSON.stringify(userData[key]))}`)
            .join('&');
    independentExamLink.href = `exam.html?${queryString}`;
  }

  const examPaperManagementLink = document.getElementById('examPaperManagement');
  if (examPaperManagementLink) {
    const queryString = Object.keys(userData)
            .map(key => `${encodeURIComponent(key)}=${encodeURIComponent(JSON.stringify(userData[key]))}`)
            .join('&');
    examPaperManagementLink.href = `exam-paper-management.html?${queryString}`;
  }

  const gradingManagementLink = document.getElementById('gradingManagement');
  if (gradingManagementLink) {
    const queryString = Object.keys(userData)
            .map(key => `${encodeURIComponent(key)}=${encodeURIComponent(JSON.stringify(userData[key]))}`)
            .join('&');
    gradingManagementLink.href = `marking.html?${queryString}`;
  }

  const newEmployeeTrainingLink = document.getElementById('newEmployeeTraining');
  if (newEmployeeTrainingLink) {
    const queryString = Object.keys(userData)
            .map(key => `${encodeURIComponent(key)}=${encodeURIComponent(JSON.stringify(userData[key]))}`)
            .join('&');
    newEmployeeTrainingLink.href = `New-employee-training-management.html?${queryString}`;
  }

  const questionBankManagementLink = document.getElementById('questionBankManagement');
  if (questionBankManagementLink) {
    const queryString = Object.keys(userData)
            .map(key => `${encodeURIComponent(key)}=${encodeURIComponent(JSON.stringify(userData[key]))}`)
            .join('&');
    questionBankManagementLink.href = `question-bank-management.html?${queryString}`;
  }

  const questionBankPracticeLink = document.getElementById('questionBankPractice');
  if (questionBankPracticeLink) {
    const queryString = Object.keys(userData)
            .map(key => `${encodeURIComponent(key)}=${encodeURIComponent(JSON.stringify(userData[key]))}`)
            .join('&');
    questionBankPracticeLink.href = `question_practice.html?${queryString}`;
  }

  const trainingManagementLink = document.getElementById('trainingManagement');
  if (trainingManagementLink) {
    const queryString = Object.keys(userData)
            .map(key => `${encodeURIComponent(key)}=${encodeURIComponent(JSON.stringify(userData[key]))}`)
            .join('&');
    trainingManagementLink.href = `training-management.html?${queryString}`;
  }



  const logoutButton = document.getElementById('logoutButton');
  logoutButton.addEventListener('click', () => {
    window.location.href = 'login.html';
  });

  const role = userData.role;
  if (role === '学生') {
    const allowedLinks = ['courseManagement', 'questionBankManagement', 'questionBankPractice', 'independentExam'];
    links.forEach(linkId => {
      const link = document.getElementById(linkId);
      if (!allowedLinks.includes(linkId)) {
        link.style.display = 'none';
      }
    });
  }
</script>
</body>

</html>

posted @ 2025-04-18 22:18  她会回来对不队  阅读(37)  评论(0)    收藏  举报