v0.2测试
This commit is contained in:
@@ -9,8 +9,8 @@
|
||||
# 版权所有 © Sea Network Technology Studio
|
||||
# ===========================================
|
||||
|
||||
# 后端API地址
|
||||
API_BASE_URL=https://api.your-domain.com
|
||||
# 后端API地址,修改为实际地址
|
||||
API_BASE_URL=https://your-api-domain.com
|
||||
|
||||
# API超时时间(秒)
|
||||
API_TIMEOUT=30
|
||||
|
||||
@@ -17,24 +17,29 @@ if (!isset($_SESSION['user_id']) || $_SESSION['user_type'] !== 'admin') {
|
||||
exit();
|
||||
}
|
||||
|
||||
$page_title = '管理员管理';
|
||||
$role = $_SESSION['role'] ?? '';
|
||||
|
||||
if ($role !== '班主任') {
|
||||
header('Location: /admin/dashboard.php');
|
||||
exit();
|
||||
}
|
||||
|
||||
$page_title = '管理员管理';
|
||||
include __DIR__ . '/../includes/header.php';
|
||||
?>
|
||||
|
||||
<div class="nav">
|
||||
<a href="/admin/dashboard.php" class="nav-item">首页</a>
|
||||
<a href="/admin/students.php" class="nav-item">学生管理</a>
|
||||
<?php if ($role === '班主任' || $role === '班长'): ?>
|
||||
<a href="/admin/conduct.php" class="nav-item">操行分管理</a>
|
||||
<?php endif; ?>
|
||||
<?php if ($role === '班主任' || $role === '学习委员'): ?>
|
||||
<a href="/admin/homework.php" class="nav-item">作业管理</a>
|
||||
<a href="/admin/attendance.php" class="nav-item">考勤管理</a>
|
||||
<a href="/admin/subjects.php" class="nav-item">科目管理</a>
|
||||
<?php endif; ?>
|
||||
<?php if ($role === '班主任' || $role === '考勤委员'): ?>
|
||||
<a href="/admin/attendance.php" class="nav-item">考勤管理</a>
|
||||
<?php endif; ?>
|
||||
<a href="/admin/admins.php" class="nav-item active">管理员管理</a>
|
||||
<a href="/admin/history.php" class="nav-item">历史记录</a>
|
||||
<a href="/admin/password.php" class="nav-item">修改密码</a>
|
||||
@@ -45,15 +50,10 @@ include __DIR__ . '/../includes/header.php';
|
||||
<div class="action-bar">
|
||||
<button class="btn btn-primary" onclick="showAddAdminModal()">添加管理员</button>
|
||||
</div>
|
||||
|
||||
<div class="table-wrapper">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>用户名</th>
|
||||
<th>姓名</th>
|
||||
<th>角色</th>
|
||||
</tr>
|
||||
<tr><th>用户名</th><th>姓名</th><th>角色</th><th>关联科目</th></tr>
|
||||
</thead>
|
||||
<tbody id="adminList"></tbody>
|
||||
</table>
|
||||
@@ -87,7 +87,7 @@ include __DIR__ . '/../includes/header.php';
|
||||
<select id="adminRole" required>
|
||||
<option value="">请选择角色</option>
|
||||
<option value="班长">班长</option>
|
||||
<option value="科代表">科代表</option>
|
||||
<option value="学习委员">学习委员</option>
|
||||
<option value="考勤委员">考勤委员</option>
|
||||
<option value="劳动委员">劳动委员</option>
|
||||
</select>
|
||||
@@ -110,15 +110,52 @@ async function loadAdmins() {
|
||||
<td>${escapeHtml(admin.username)}</td>
|
||||
<td>${escapeHtml(admin.real_name)}</td>
|
||||
<td>${escapeHtml(admin.role_type)}</td>
|
||||
<td>${admin.subject_name || '-'}</td>
|
||||
</tr>`;
|
||||
});
|
||||
if (res.data.admins.length === 0) {
|
||||
html = '<tr><td colspan="3" style="text-align:center;">暂无管理员</td></tr>';
|
||||
html = '<tr><td colspan="4" style="text-align:center;">暂无管理员</td></tr>';
|
||||
}
|
||||
document.getElementById('adminList').innerHTML = html;
|
||||
}
|
||||
}
|
||||
|
||||
function showAddAdminModal() {
|
||||
document.getElementById('addAdminModal').style.display = 'flex';
|
||||
document.getElementById('addAdminForm')?.reset();
|
||||
}
|
||||
|
||||
async function submitAddAdmin() {
|
||||
const username = document.getElementById('adminUsername').value.trim();
|
||||
const realName = document.getElementById('adminRealName').value.trim();
|
||||
const password = document.getElementById('adminPassword').value;
|
||||
const roleType = document.getElementById('adminRole').value;
|
||||
if (!username || !realName || !roleType) {
|
||||
showToast('请填写完整信息', 'warning');
|
||||
return;
|
||||
}
|
||||
const res = await apiPost('/api/admin/add', {
|
||||
username: username,
|
||||
real_name: realName,
|
||||
password: password || undefined,
|
||||
role_type: roleType
|
||||
});
|
||||
if (res && res.success) {
|
||||
let msg = `管理员 ${res.data.username} 添加成功`;
|
||||
if (res.data.password) msg += `,密码: ${res.data.password}`;
|
||||
showToast(msg);
|
||||
closeModal('addAdminModal');
|
||||
loadAdmins();
|
||||
} else {
|
||||
showToast(res?.message || '添加失败', 'error');
|
||||
}
|
||||
}
|
||||
|
||||
function closeModal(modalId) {
|
||||
const modal = document.getElementById(modalId);
|
||||
if (modal) modal.style.display = 'none';
|
||||
}
|
||||
|
||||
loadAdmins();
|
||||
</script>
|
||||
<script src="/assets/js/admin.js"></script>
|
||||
|
||||
@@ -28,14 +28,14 @@ include __DIR__ . '/../includes/header.php';
|
||||
<?php if ($role === '班主任' || $role === '班长'): ?>
|
||||
<a href="/admin/conduct.php" class="nav-item">操行分管理</a>
|
||||
<?php endif; ?>
|
||||
<?php if ($role === '班主任' || $role === '科代表'): ?>
|
||||
<?php if ($role === '班主任' || $role === '学习委员'): ?>
|
||||
<a href="/admin/homework.php" class="nav-item">作业管理</a>
|
||||
<a href="/admin/subjects.php" class="nav-item">科目管理</a>
|
||||
<?php endif; ?>
|
||||
<?php if ($role === '班主任' || $role === '考勤委员'): ?>
|
||||
<a href="/admin/attendance.php" class="nav-item">考勤管理</a>
|
||||
<?php endif; ?>
|
||||
<?php if ($role === '班主任'): ?>
|
||||
<a href="/admin/subjects.php" class="nav-item">科目管理</a>
|
||||
<a href="/admin/admins.php" class="nav-item">管理员管理</a>
|
||||
<?php endif; ?>
|
||||
<a href="/admin/history.php" class="nav-item">历史记录</a>
|
||||
@@ -65,18 +65,16 @@ include __DIR__ . '/../includes/header.php';
|
||||
|
||||
<script>
|
||||
async function loadDashboard() {
|
||||
// 加载学生统计
|
||||
const studentsRes = await apiGet('/api/admin/students');
|
||||
if (studentsRes && studentsRes.success) {
|
||||
document.getElementById('dashboardStats').innerHTML = `
|
||||
<div class="stat-card">
|
||||
<div class="stat-label">班级学生数</div>
|
||||
<div class="stat-label">学生总数</div>
|
||||
<div class="stat-value">${studentsRes.data.total || 0}</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
// 快捷操作按钮
|
||||
let quickActions = '';
|
||||
if ('<?php echo $role; ?>' === '班主任' || '<?php echo $role; ?>' === '班长') {
|
||||
quickActions += '<button class="btn btn-primary" onclick="location.href=\'/admin/conduct.php\'">操行分管理</button>';
|
||||
@@ -86,19 +84,16 @@ async function loadDashboard() {
|
||||
}
|
||||
document.getElementById('quickActions').innerHTML = quickActions || '<p>暂无快捷操作</p>';
|
||||
|
||||
// 加载排行榜
|
||||
const rankingRes = await apiGet('/api/student/ranking', { limit: 10 });
|
||||
if (rankingRes && rankingRes.success) {
|
||||
let html = '';
|
||||
rankingRes.data.ranking.forEach((student, index) => {
|
||||
html += `
|
||||
<tr>
|
||||
<td>${index + 1}</td>
|
||||
<td>${escapeHtml(student.student_no)}</td>
|
||||
<td>${escapeHtml(student.name)}</td>
|
||||
<td>${student.total_points}</td>
|
||||
</tr>
|
||||
`;
|
||||
html += `<tr>
|
||||
<td>${index + 1}</td>
|
||||
<td>${escapeHtml(student.student_no)}</td>
|
||||
<td>${escapeHtml(student.name)}</td>
|
||||
<td>${student.total_points}</td>
|
||||
</tr>`;
|
||||
});
|
||||
if (rankingRes.data.ranking.length === 0) {
|
||||
html = '<tr><td colspan="4" style="text-align:center;">暂无数据</td></tr>';
|
||||
|
||||
@@ -17,25 +17,32 @@ if (!isset($_SESSION['user_id']) || $_SESSION['user_type'] !== 'admin') {
|
||||
exit();
|
||||
}
|
||||
|
||||
$page_title = '科目管理';
|
||||
$role = $_SESSION['role'] ?? '';
|
||||
|
||||
if ($role !== '班主任') {
|
||||
if (!in_array($role, ['班主任', '学习委员'])) {
|
||||
header('Location: /admin/dashboard.php');
|
||||
exit();
|
||||
}
|
||||
|
||||
$page_title = '科目管理';
|
||||
include __DIR__ . '/../includes/header.php';
|
||||
?>
|
||||
|
||||
<div class="nav">
|
||||
<a href="/admin/dashboard.php" class="nav-item">首页</a>
|
||||
<a href="/admin/students.php" class="nav-item">学生管理</a>
|
||||
<?php if ($role === '班主任' || $role === '班长'): ?>
|
||||
<a href="/admin/conduct.php" class="nav-item">操行分管理</a>
|
||||
<?php endif; ?>
|
||||
<?php if ($role === '班主任' || $role === '学习委员'): ?>
|
||||
<a href="/admin/homework.php" class="nav-item">作业管理</a>
|
||||
<a href="/admin/attendance.php" class="nav-item">考勤管理</a>
|
||||
<a href="/admin/subjects.php" class="nav-item active">科目管理</a>
|
||||
<?php endif; ?>
|
||||
<?php if ($role === '班主任' || $role === '考勤委员'): ?>
|
||||
<a href="/admin/attendance.php" class="nav-item">考勤管理</a>
|
||||
<?php endif; ?>
|
||||
<?php if ($role === '班主任'): ?>
|
||||
<a href="/admin/admins.php" class="nav-item">管理员管理</a>
|
||||
<?php endif; ?>
|
||||
<a href="/admin/history.php" class="nav-item">历史记录</a>
|
||||
<a href="/admin/password.php" class="nav-item">修改密码</a>
|
||||
</div>
|
||||
@@ -138,10 +145,7 @@ async function loadSubjects() {
|
||||
}
|
||||
|
||||
async function toggleSubject(subjectId, enable) {
|
||||
const res = await apiPut(`/api/subject/update/${subjectId}`, {
|
||||
is_active: enable
|
||||
});
|
||||
|
||||
const res = await apiPut(`/api/subject/update/${subjectId}`, { is_active: enable });
|
||||
if (res && res.success) {
|
||||
showToast(enable ? '科目已启用' : '科目已禁用');
|
||||
loadSubjects();
|
||||
@@ -150,6 +154,36 @@ async function toggleSubject(subjectId, enable) {
|
||||
}
|
||||
}
|
||||
|
||||
function showAddSubjectModal() {
|
||||
document.getElementById('addSubjectModal').style.display = 'flex';
|
||||
document.getElementById('addSubjectForm')?.reset();
|
||||
}
|
||||
|
||||
async function submitAddSubject() {
|
||||
const subjectName = document.getElementById('subjectName').value.trim();
|
||||
const subjectCode = document.getElementById('subjectCode').value.trim();
|
||||
if (!subjectName) {
|
||||
showToast('请填写科目名称', 'warning');
|
||||
return;
|
||||
}
|
||||
const res = await apiPost('/api/subject/create', {
|
||||
subject_name: subjectName,
|
||||
subject_code: subjectCode
|
||||
});
|
||||
if (res && res.success) {
|
||||
showToast('科目添加成功');
|
||||
closeModal('addSubjectModal');
|
||||
loadSubjects();
|
||||
} else {
|
||||
showToast(res?.message || '添加失败', 'error');
|
||||
}
|
||||
}
|
||||
|
||||
function closeModal(modalId) {
|
||||
const modal = document.getElementById(modalId);
|
||||
if (modal) modal.style.display = 'none';
|
||||
}
|
||||
|
||||
loadSubjects();
|
||||
</script>
|
||||
<script src="/assets/js/admin.js"></script>
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
* 版权所有 © Sea Network Technology Studio
|
||||
*/
|
||||
|
||||
// API基础地址
|
||||
const API_BASE_URL = window.API_BASE_URL || 'http://localhost:8000';
|
||||
// API 使用相对路径,由 Nginx 反向代理 /api/ 到后端
|
||||
const API_BASE_URL = '';
|
||||
const JWT_STORAGE_KEY = 'class_system_token';
|
||||
const USER_STORAGE_KEY = 'class_system_user';
|
||||
|
||||
@@ -54,23 +54,24 @@ function checkAuth() {
|
||||
// API请求封装
|
||||
async function apiRequest(url, options = {}) {
|
||||
const token = getToken();
|
||||
|
||||
const headers = {
|
||||
'Content-Type': 'application/json',
|
||||
...options.headers
|
||||
};
|
||||
|
||||
if (token) {
|
||||
headers['Authorization'] = `Bearer ${token}`;
|
||||
}
|
||||
|
||||
// 确保 url 以 /api/ 开头
|
||||
const fullUrl = url.startsWith('/api/') ? url : `/api${url}`;
|
||||
|
||||
const config = {
|
||||
...options,
|
||||
headers
|
||||
};
|
||||
|
||||
try {
|
||||
const response = await fetch(`${API_BASE_URL}${url}`, config);
|
||||
const response = await fetch(fullUrl, config);
|
||||
const data = await response.json();
|
||||
|
||||
if (response.status === 401) {
|
||||
@@ -78,7 +79,6 @@ async function apiRequest(url, options = {}) {
|
||||
window.location.href = '/index.php';
|
||||
return null;
|
||||
}
|
||||
|
||||
return data;
|
||||
} catch (error) {
|
||||
console.error('API请求错误:', error);
|
||||
@@ -121,7 +121,6 @@ function showToast(message, type = 'success') {
|
||||
toast.className = `toast toast-${type}`;
|
||||
toast.textContent = message;
|
||||
document.body.appendChild(toast);
|
||||
|
||||
setTimeout(() => {
|
||||
toast.remove();
|
||||
}, 3000);
|
||||
@@ -156,10 +155,8 @@ function getStatusBadge(status, type = 'homework') {
|
||||
'leave': '请假'
|
||||
}
|
||||
};
|
||||
|
||||
const texts = statusMap[type] || statusMap.homework;
|
||||
const text = texts[status] || status;
|
||||
|
||||
let className = 'status-badge ';
|
||||
switch (status) {
|
||||
case 'submitted':
|
||||
@@ -179,7 +176,6 @@ function getStatusBadge(status, type = 'homework') {
|
||||
default:
|
||||
className += 'status-not_submitted';
|
||||
}
|
||||
|
||||
return `<span class="${className}">${text}</span>`;
|
||||
}
|
||||
|
||||
@@ -216,7 +212,6 @@ async function changePassword(newPassword) {
|
||||
old_password: newPassword,
|
||||
new_password: newPassword
|
||||
});
|
||||
|
||||
if (res && res.success) {
|
||||
showToast('密码修改成功,请重新登录');
|
||||
setTimeout(() => logout(), 1500);
|
||||
@@ -226,17 +221,25 @@ async function changePassword(newPassword) {
|
||||
}
|
||||
}
|
||||
|
||||
// HTML转义
|
||||
function escapeHtml(str) {
|
||||
if (!str) return '';
|
||||
return str.replace(/[&<>]/g, function(m) {
|
||||
if (m === '&') return '&';
|
||||
if (m === '<') return '<';
|
||||
if (m === '>') return '>';
|
||||
return m;
|
||||
});
|
||||
}
|
||||
|
||||
// 页面加载时初始化
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
loadUserInfo();
|
||||
|
||||
const logoutBtn = document.getElementById('logoutBtn');
|
||||
if (logoutBtn) {
|
||||
logoutBtn.addEventListener('click', logout);
|
||||
}
|
||||
|
||||
// 学生端检查强制修改密码
|
||||
if (window.location.pathname.includes('/student/')) {
|
||||
if (window.location.pathname.includes('/student/') || window.location.pathname.includes('/parent/')) {
|
||||
checkNeedChangePassword();
|
||||
}
|
||||
});
|
||||
@@ -10,44 +10,72 @@
|
||||
* 版权所有 © Sea Network Technology Studio
|
||||
*/
|
||||
|
||||
// 加载环境变量
|
||||
// 读取.env文件
|
||||
$envFile = __DIR__ . '/.env';
|
||||
if (file_exists($envFile)) {
|
||||
$lines = file($envFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
|
||||
foreach ($lines as $line) {
|
||||
if (strpos(trim($line), '#') === 0) {
|
||||
continue;
|
||||
}
|
||||
if (strpos($line, '=') !== false) {
|
||||
list($key, $value) = explode('=', $line, 2);
|
||||
putenv(trim($key) . '=' . trim($value));
|
||||
}
|
||||
$config = [];
|
||||
|
||||
if (!file_exists($envFile)) {
|
||||
die('错误: 配置文件 .env 不存在,请复制 .env.example 并修改配置');
|
||||
}
|
||||
|
||||
$lines = file($envFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
|
||||
if ($lines === false) {
|
||||
die('错误: 无法读取配置文件 .env');
|
||||
}
|
||||
|
||||
foreach ($lines as $line) {
|
||||
$line = trim($line);
|
||||
// 跳过注释行
|
||||
if (strpos($line, '#') === 0 || empty($line)) {
|
||||
continue;
|
||||
}
|
||||
// 解析 KEY=VALUE
|
||||
if (strpos($line, '=') !== false) {
|
||||
$parts = explode('=', $line, 2);
|
||||
$key = trim($parts[0]);
|
||||
$value = trim($parts[1]);
|
||||
// 去除可能的引号
|
||||
$value = trim($value, '"\'');
|
||||
$config[$key] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
// 检查必要配置是否存在
|
||||
$requiredKeys = ['API_BASE_URL', 'API_TIMEOUT', 'JWT_STORAGE_KEY', 'USER_STORAGE_KEY', 'SITE_NAME', 'SESSION_TIMEOUT'];
|
||||
$missingKeys = [];
|
||||
|
||||
foreach ($requiredKeys as $key) {
|
||||
if (!isset($config[$key]) || $config[$key] === '') {
|
||||
$missingKeys[] = $key;
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($missingKeys)) {
|
||||
die('错误: 配置文件 .env 缺少必要配置项: ' . implode(', ', $missingKeys));
|
||||
}
|
||||
|
||||
// 定义常量
|
||||
define('API_BASE_URL', getenv('API_BASE_URL') ?: 'http://localhost:8000');
|
||||
define('API_TIMEOUT', (int)(getenv('API_TIMEOUT') ?: 30));
|
||||
define('JWT_STORAGE_KEY', getenv('JWT_STORAGE_KEY') ?: 'class_system_token');
|
||||
define('USER_STORAGE_KEY', getenv('USER_STORAGE_KEY') ?: 'class_system_user');
|
||||
define('SITE_NAME', getenv('SITE_NAME') ?: '班级操行分管理系统');
|
||||
define('SESSION_TIMEOUT', (int)(getenv('SESSION_TIMEOUT') ?: 30));
|
||||
define('API_BASE_URL', '''');
|
||||
define('API_TIMEOUT', (int)$config['API_TIMEOUT']);
|
||||
define('JWT_STORAGE_KEY', $config['JWT_STORAGE_KEY']);
|
||||
define('USER_STORAGE_KEY', $config['USER_STORAGE_KEY']);
|
||||
define('SITE_NAME', $config['SITE_NAME']);
|
||||
define('SESSION_TIMEOUT', (int)$config['SESSION_TIMEOUT']);
|
||||
|
||||
// 会话配置
|
||||
ini_set('session.cookie_httponly', 1);
|
||||
ini_set('session.use_only_cookies', 1);
|
||||
ini_set('session.cookie_secure', 1);
|
||||
ini_set('session.cookie_samesite', 'Lax');
|
||||
ini_set('session.cookie_domain', '.sea-studio.top');
|
||||
ini_set('session.gc_maxlifetime', 7200);
|
||||
session_name('CLASS_SESSION');
|
||||
|
||||
session_start();
|
||||
|
||||
// 时区设置
|
||||
date_default_timezone_set('Asia/Shanghai');
|
||||
|
||||
// 错误报告(生产环境关闭)
|
||||
if (getenv('APP_ENV') === 'production') {
|
||||
error_reporting(0);
|
||||
ini_set('display_errors', 0);
|
||||
} else {
|
||||
error_reporting(E_ALL);
|
||||
ini_set('display_errors', 1);
|
||||
}
|
||||
?>
|
||||
// 生产环境关闭错误显示
|
||||
error_reporting(0);
|
||||
ini_set('display_errors', 0);
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
/**
|
||||
* 班级操行分管理系统 - 家长端主页
|
||||
* 班级操行分管理系统 - 家长端首页
|
||||
*
|
||||
* 开发者: Canglan
|
||||
* 联系方式: admin@sea-studio.top
|
||||
@@ -12,261 +12,58 @@
|
||||
|
||||
require_once __DIR__ . '/../config.php';
|
||||
|
||||
// 检查登录状态
|
||||
if (!isset($_SESSION['user_id']) || $_SESSION['user_type'] !== 'parent') {
|
||||
header('Location: /index.php');
|
||||
exit();
|
||||
}
|
||||
|
||||
$student_id = $_SESSION['student_id'];
|
||||
$page_title = '首页';
|
||||
include __DIR__ . '/../includes/header.php';
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title><?php echo SITE_NAME; ?> - 家长端</title>
|
||||
<link rel="stylesheet" href="/assets/css/style.css">
|
||||
<style>
|
||||
.child-info {
|
||||
text-align: center;
|
||||
padding: 20px;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
border-radius: 12px;
|
||||
color: white;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.child-name {
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.child-no {
|
||||
font-size: 14px;
|
||||
opacity: 0.9;
|
||||
}
|
||||
.conduct-score {
|
||||
text-align: center;
|
||||
padding: 30px;
|
||||
}
|
||||
.score-number {
|
||||
font-size: 72px;
|
||||
font-weight: bold;
|
||||
color: #667eea;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="header">
|
||||
<h1><?php echo SITE_NAME; ?> - 家长端</h1>
|
||||
<div class="header-info">
|
||||
<span class="user-name" id="userName"></span>
|
||||
<button class="btn-logout" id="logoutBtn">退出登录</button>
|
||||
|
||||
<div class="nav">
|
||||
<a href="/parent/dashboard.php" class="nav-item active">首页</a>
|
||||
<a href="/parent/attendance.php" class="nav-item">考勤记录</a>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
<div class="child-info">
|
||||
<div class="child-name" id="childName">--</div>
|
||||
<div class="child-no" id="childNo">--</div>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="conduct-score">
|
||||
<div class="score-number" id="totalPoints">--</div>
|
||||
<div class="score-label">当前操行分</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="nav">
|
||||
<button class="nav-item active" data-page="dashboard">首页</button>
|
||||
<button class="nav-item" data-page="homework">作业情况</button>
|
||||
<button class="nav-item" data-page="attendance">考勤记录</button>
|
||||
</div>
|
||||
<style>
|
||||
.child-info {
|
||||
text-align: center;
|
||||
padding: 20px;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
border-radius: 12px;
|
||||
color: white;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.child-name { font-size: 24px; font-weight: bold; margin-bottom: 8px; }
|
||||
.child-no { font-size: 14px; opacity: 0.9; }
|
||||
.score-number { font-size: 72px; font-weight: bold; color: #667eea; text-align: center; }
|
||||
</style>
|
||||
|
||||
<div class="container" id="pageContainer">
|
||||
<!-- 首页内容 -->
|
||||
<div id="page-dashboard" class="page-content">
|
||||
<div class="child-info" id="childInfo">
|
||||
<div class="child-name" id="childName">--</div>
|
||||
<div class="child-no" id="childNo">--</div>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="conduct-score">
|
||||
<div class="score-number" id="totalPoints">--</div>
|
||||
<div class="score-label">当前操行分</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
async function loadDashboard() {
|
||||
const res = await apiGet('/api/parent/child/conduct');
|
||||
if (res && res.success) {
|
||||
document.getElementById('childName').textContent = res.data.student_name;
|
||||
document.getElementById('childNo').textContent = res.data.student_no;
|
||||
document.getElementById('totalPoints').textContent = res.data.total_points;
|
||||
}
|
||||
}
|
||||
loadDashboard();
|
||||
</script>
|
||||
<script src="/assets/js/parent.js"></script>
|
||||
|
||||
<!-- 作业情况页 -->
|
||||
<div id="page-homework" class="page-content" style="display: none;">
|
||||
<div class="card">
|
||||
<div class="card-title">作业列表</div>
|
||||
<div class="table-wrapper">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>科目</th>
|
||||
<th>作业标题</th>
|
||||
<th>截止日期</th>
|
||||
<th>状态</th>
|
||||
<th>备注</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="homeworkList"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 考勤记录页 -->
|
||||
<div id="page-attendance" class="page-content" style="display: none;">
|
||||
<div class="stats-grid">
|
||||
<div class="stat-card">
|
||||
<div class="stat-label">出勤</div>
|
||||
<div class="stat-value" id="attPresent">0</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-label">缺勤</div>
|
||||
<div class="stat-value" id="attAbsent">0</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-label">迟到</div>
|
||||
<div class="stat-value" id="attLate">0</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-label">请假</div>
|
||||
<div class="stat-value" id="attLeave">0</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="card-title">考勤记录明细</div>
|
||||
<div class="table-wrapper">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>日期</th>
|
||||
<th>状态</th>
|
||||
<th>原因</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="attendanceList"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const API_BASE_URL = '<?php echo API_BASE_URL; ?>';
|
||||
const STUDENT_ID = <?php echo $student_id ?: 0; ?>;
|
||||
|
||||
// 页面切换
|
||||
function showPage(pageName) {
|
||||
document.querySelectorAll('.page-content').forEach(page => {
|
||||
page.style.display = 'none';
|
||||
});
|
||||
document.getElementById(`page-${pageName}`).style.display = 'block';
|
||||
|
||||
document.querySelectorAll('.nav-item').forEach(item => {
|
||||
item.classList.remove('active');
|
||||
if (item.dataset.page === pageName) {
|
||||
item.classList.add('active');
|
||||
}
|
||||
});
|
||||
|
||||
switch(pageName) {
|
||||
case 'dashboard':
|
||||
loadDashboard();
|
||||
break;
|
||||
case 'homework':
|
||||
loadHomework();
|
||||
break;
|
||||
case 'attendance':
|
||||
loadAttendance();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 加载首页
|
||||
async function loadDashboard() {
|
||||
try {
|
||||
// 获取子女信息
|
||||
const childRes = await apiGet(`/api/parent/child/conduct`);
|
||||
if (childRes && childRes.success) {
|
||||
document.getElementById('childName').textContent = childRes.data.student_name;
|
||||
document.getElementById('childNo').textContent = childRes.data.student_no;
|
||||
document.getElementById('totalPoints').textContent = childRes.data.total_points;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('加载首页失败:', error);
|
||||
}
|
||||
}
|
||||
|
||||
// 加载作业
|
||||
async function loadHomework() {
|
||||
try {
|
||||
const res = await apiGet(`/api/parent/child/homework`);
|
||||
if (res && res.success) {
|
||||
let html = '';
|
||||
res.data.homework.forEach(hw => {
|
||||
html += `
|
||||
<tr>
|
||||
<td>${hw.subject}</td>
|
||||
<td>${hw.title}</td>
|
||||
<td>${hw.deadline}</td>
|
||||
<td>${getStatusBadge(hw.status, 'homework')}</td>
|
||||
<td>${hw.comments || '-'}</td>
|
||||
</tr>
|
||||
`;
|
||||
});
|
||||
if (res.data.homework.length === 0) {
|
||||
html = '<tr><td colspan="5" style="text-align:center;">暂无作业</td></tr>';
|
||||
}
|
||||
document.getElementById('homeworkList').innerHTML = html;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('加载作业失败:', error);
|
||||
}
|
||||
}
|
||||
|
||||
// 加载考勤
|
||||
async function loadAttendance() {
|
||||
try {
|
||||
const res = await apiGet(`/api/parent/child/attendance`);
|
||||
if (res && res.success) {
|
||||
const records = res.data.records;
|
||||
let present = 0, absent = 0, late = 0, leave = 0;
|
||||
|
||||
let html = '';
|
||||
records.forEach(record => {
|
||||
html += `
|
||||
<tr>
|
||||
<td>${record.date}</td>
|
||||
<td>${getStatusBadge(record.status, 'attendance')}</td>
|
||||
<td>${record.reason || '-'}</td>
|
||||
</tr>
|
||||
`;
|
||||
switch(record.status) {
|
||||
case 'present': present++; break;
|
||||
case 'absent': absent++; break;
|
||||
case 'late': late++; break;
|
||||
case 'leave': leave++; break;
|
||||
}
|
||||
});
|
||||
|
||||
document.getElementById('attPresent').textContent = present;
|
||||
document.getElementById('attAbsent').textContent = absent;
|
||||
document.getElementById('attLate').textContent = late;
|
||||
document.getElementById('attLeave').textContent = leave;
|
||||
|
||||
if (records.length === 0) {
|
||||
html = '<tr><td colspan="3" style="text-align:center;">暂无考勤记录</td></tr>';
|
||||
}
|
||||
document.getElementById('attendanceList').innerHTML = html;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('加载考勤失败:', error);
|
||||
}
|
||||
}
|
||||
|
||||
// 初始化
|
||||
document.querySelectorAll('.nav-item').forEach(btn => {
|
||||
btn.addEventListener('click', () => {
|
||||
showPage(btn.dataset.page);
|
||||
});
|
||||
});
|
||||
|
||||
loadDashboard();
|
||||
</script>
|
||||
<script src="/assets/js/common.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
<?php include __DIR__ . '/../includes/footer.php'; ?>
|
||||
@@ -1,66 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* 班级操行分管理系统 - 家长端作业情况
|
||||
*
|
||||
* 开发者: Canglan
|
||||
* 联系方式: admin@sea-studio.top
|
||||
* 版权归属: Sea Network Technology Studio
|
||||
* 许可证: MIT License
|
||||
*
|
||||
* 版权所有 © Sea Network Technology Studio
|
||||
*/
|
||||
|
||||
require_once __DIR__ . '/../config.php';
|
||||
|
||||
if (!isset($_SESSION['user_id']) || $_SESSION['user_type'] !== 'parent') {
|
||||
header('Location: /index.php');
|
||||
exit();
|
||||
}
|
||||
|
||||
$page_title = '作业情况';
|
||||
include __DIR__ . '/../includes/header.php';
|
||||
?>
|
||||
|
||||
<div class="nav">
|
||||
<a href="/parent/dashboard.php" class="nav-item">首页</a>
|
||||
<a href="/parent/homework.php" class="nav-item active">作业情况</a>
|
||||
<a href="/parent/attendance.php" class="nav-item">考勤记录</a>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
<div class="card">
|
||||
<div class="card-title">作业列表</div>
|
||||
<div class="table-wrapper">
|
||||
<table class="table">
|
||||
<thead><tr><th>科目</th><th>作业标题</th><th>截止日期</th><th>状态</th><th>备注</th></tr></thead>
|
||||
<tbody id="homeworkList"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
async function loadHomework() {
|
||||
const res = await apiGet('/api/parent/child/homework');
|
||||
if (res && res.success) {
|
||||
let html = '';
|
||||
res.data.homework.forEach(hw => {
|
||||
html += `<tr>
|
||||
<td>${escapeHtml(hw.subject)}</td>
|
||||
<td>${escapeHtml(hw.title)}</td>
|
||||
<td>${hw.deadline}</td>
|
||||
<td>${getStatusBadge(hw.status, 'homework')}</td>
|
||||
<td>${escapeHtml(hw.comments || '-')}</td>
|
||||
</tr>`;
|
||||
});
|
||||
if (res.data.homework.length === 0) {
|
||||
html = '<tr><td colspan="5" style="text-align:center;">暂无作业</td></tr>';
|
||||
}
|
||||
document.getElementById('homeworkList').innerHTML = html;
|
||||
}
|
||||
}
|
||||
loadHomework();
|
||||
</script>
|
||||
<script src="/assets/js/parent.js"></script>
|
||||
|
||||
<?php include __DIR__ . '/../includes/footer.php'; ?>
|
||||
Reference in New Issue
Block a user