diff --git a/backend/backups/database-2025-12-22T15-39-29-371Z.sqlite b/backend/backups/database-2025-12-22T15-39-29-371Z.sqlite new file mode 100644 index 0000000..362bda2 Binary files /dev/null and b/backend/backups/database-2025-12-22T15-39-29-371Z.sqlite differ diff --git a/backend/database.sqlite b/backend/database.sqlite index 8b85f52..ccabe1a 100644 Binary files a/backend/database.sqlite and b/backend/database.sqlite differ diff --git a/frontend/public/js/admin.js b/frontend/public/js/admin.js index faefaec..530a929 100644 --- a/frontend/public/js/admin.js +++ b/frontend/public/js/admin.js @@ -221,28 +221,91 @@ class AdminManager { } } - renderPagination(pagination) { - const el = document.getElementById('pagination'); + renderGenericPagination(containerId, pagination, callbackName) { + const el = document.getElementById(containerId); + if (!el) return; + + const { page, pages } = pagination; + if (pages <= 0) { + el.innerHTML = ''; + return; + } + let html = ''; - if (pagination.page > 1) { - html += `
  • 上一页
  • `; + // Previous page + if (page > 1) { + html += `
  • 上一页
  • `; } else { - html += `
  • 上一页
  • `; + html += `
  • 上一页
  • `; } - for (let i = 1; i <= pagination.pages; i++) { - html += `
  • ${i}
  • `; + // Page numbers with ellipsis + if (pages <= 7) { + for (let i = 1; i <= pages; i++) { + html += `
  • ${i}
  • `; + } + } else { + // First page + html += `
  • 1
  • `; + + if (page > 4) { + html += `
  • ...
  • `; + } + + // Middle pages + let start = Math.max(2, page - 2); + let end = Math.min(pages - 1, page + 2); + + if (page <= 4) { + start = 2; + end = 5; + } else if (page >= pages - 3) { + start = pages - 4; + end = pages - 1; + } + + for (let i = start; i <= end; i++) { + html += `
  • ${i}
  • `; + } + + if (page < pages - 3) { + html += `
  • ...
  • `; + } + + // Last page + html += `
  • ${pages}
  • `; } - if (pagination.page < pagination.pages) { - html += `
  • 下一页
  • `; + // Next page + if (page < pages) { + html += `
  • 下一页
  • `; } else { - html += `
  • 下一页
  • `; + html += `
  • 下一页
  • `; } + + // Jump to page + html += ` +
  • +
    + 跳转至 + + 页 / 共 ${pages} 页 +
    +
  • + `; el.innerHTML = html; } + + renderPagination(pagination) { + this.renderGenericPagination('pagination', pagination, 'changePage'); + } changePage(page) { this.currentPage = page; @@ -426,26 +489,7 @@ class AdminManager { } renderStudentPagination(pagination) { - const el = document.getElementById('studentPagination'); - let html = ''; - - if (pagination.page > 1) { - html += `
  • 上一页
  • `; - } else { - html += `
  • 上一页
  • `; - } - - for (let i = 1; i <= pagination.pages; i++) { - html += `
  • ${i}
  • `; - } - - if (pagination.page < pagination.pages) { - html += `
  • 下一页
  • `; - } else { - html += `
  • 下一页
  • `; - } - - el.innerHTML = html; + this.renderGenericPagination('studentPagination', pagination, 'changeStudentPage'); } changeStudentPage(page) { @@ -626,26 +670,7 @@ class AdminManager { } renderTeacherPagination(pagination) { - const el = document.getElementById('teacherPagination'); - let html = ''; - - if (pagination.page > 1) { - html += `
  • 上一页
  • `; - } else { - html += `
  • 上一页
  • `; - } - - for (let i = 1; i <= pagination.pages; i++) { - html += `
  • ${i}
  • `; - } - - if (pagination.page < pagination.pages) { - html += `
  • 下一页
  • `; - } else { - html += `
  • 下一页
  • `; - } - - el.innerHTML = html; + this.renderGenericPagination('teacherPagination', pagination, 'changeTeacherPage'); } changeTeacherPage(page) { diff --git a/frontend/views/admin/data_export.html b/frontend/views/admin/data_export.html index f83f998..6bbd4c1 100644 --- a/frontend/views/admin/data_export.html +++ b/frontend/views/admin/data_export.html @@ -121,6 +121,12 @@ .main-content { margin-left: 0; } .sidebar.active { left: 0; } } + + /* 表单控件聚焦样式优化 */ + .form-control:focus, .form-select:focus { + border-color: var(--primary-color); + box-shadow: 0 0 0 0.2rem rgba(78, 115, 223, 0.1); + } diff --git a/frontend/views/admin/grade_statistics.html b/frontend/views/admin/grade_statistics.html index 3c50d5b..bcc65d5 100644 --- a/frontend/views/admin/grade_statistics.html +++ b/frontend/views/admin/grade_statistics.html @@ -121,6 +121,12 @@ .main-content { margin-left: 0; } .sidebar.active { left: 0; } } + + /* 表单控件聚焦样式优化 */ + .form-control:focus, .form-select:focus { + border-color: var(--primary-color); + box-shadow: 0 0 0 0.2rem rgba(78, 115, 223, 0.1); + } diff --git a/frontend/views/admin/operation_logs.html b/frontend/views/admin/operation_logs.html index 752f13b..c5b69f1 100644 --- a/frontend/views/admin/operation_logs.html +++ b/frontend/views/admin/operation_logs.html @@ -121,6 +121,12 @@ .main-content { margin-left: 0; } .sidebar.active { left: 0; } } + + /* 表单控件聚焦样式优化 */ + .form-control:focus, .form-select:focus { + border-color: var(--primary-color); + box-shadow: 0 0 0 0.2rem rgba(78, 115, 223, 0.1); + } diff --git a/frontend/views/admin/student_management.html b/frontend/views/admin/student_management.html index 220f571..68c0fc3 100644 --- a/frontend/views/admin/student_management.html +++ b/frontend/views/admin/student_management.html @@ -121,6 +121,40 @@ .main-content { margin-left: 0; } .sidebar.active { left: 0; } } + + /* 输入框聚焦样式优化 */ + .input-group { + border: 1px solid #dee2e6; + border-radius: 0.5rem; + overflow: hidden; + transition: all 0.2s; + background-color: #fff; + } + + .input-group:focus-within { + border-color: var(--primary-color); + box-shadow: 0 0 0 0.2rem rgba(78, 115, 223, 0.1); + } + + .input-group-text { + background-color: transparent; + border: none; + color: var(--secondary-color); + padding-left: 1rem; + padding-right: 0.5rem; + } + + .form-control { + border: none !important; + } + + .form-control:focus { + box-shadow: none; + } + + .input-group:focus-within .input-group-text { + color: var(--primary-color); + } diff --git a/frontend/views/admin/system_settings.html b/frontend/views/admin/system_settings.html index 49c01b4..853616b 100644 --- a/frontend/views/admin/system_settings.html +++ b/frontend/views/admin/system_settings.html @@ -121,6 +121,12 @@ .main-content { margin-left: 0; } .sidebar.active { left: 0; } } + + /* 表单控件聚焦样式优化 */ + .form-control:focus, .form-select:focus { + border-color: var(--primary-color); + box-shadow: 0 0 0 0.2rem rgba(78, 115, 223, 0.1); + } diff --git a/frontend/views/admin/teacher_management.html b/frontend/views/admin/teacher_management.html index 58d9d8a..c3ffb1a 100644 --- a/frontend/views/admin/teacher_management.html +++ b/frontend/views/admin/teacher_management.html @@ -121,6 +121,40 @@ .main-content { margin-left: 0; } .sidebar.active { left: 0; } } + + /* 输入框聚焦样式优化 */ + .input-group { + border: 1px solid #dee2e6; + border-radius: 0.5rem; + overflow: hidden; + transition: all 0.2s; + background-color: #fff; + } + + .input-group:focus-within { + border-color: var(--primary-color); + box-shadow: 0 0 0 0.2rem rgba(78, 115, 223, 0.1); + } + + .input-group-text { + background-color: transparent; + border: none; + color: var(--secondary-color); + padding-left: 1rem; + padding-right: 0.5rem; + } + + .form-control { + border: none !important; + } + + .form-control:focus { + box-shadow: none; + } + + .input-group:focus-within .input-group-text { + color: var(--primary-color); + } diff --git a/frontend/views/admin/user_management.html b/frontend/views/admin/user_management.html index 4ecfb3d..9f8d832 100644 --- a/frontend/views/admin/user_management.html +++ b/frontend/views/admin/user_management.html @@ -121,6 +121,40 @@ .main-content { margin-left: 0; } .sidebar.active { left: 0; } } + + /* 输入框聚焦样式优化 */ + .input-group { + border: 1px solid #dee2e6; + border-radius: 0.5rem; + overflow: hidden; + transition: all 0.2s; + background-color: #fff; + } + + .input-group:focus-within { + border-color: var(--primary-color); + box-shadow: 0 0 0 0.2rem rgba(78, 115, 223, 0.1); + } + + .input-group-text { + background-color: transparent; + border: none; + color: var(--secondary-color); + padding-left: 1rem; + padding-right: 0.5rem; + } + + .form-control { + border: none !important; + } + + .form-control:focus { + box-shadow: none; + } + + .input-group:focus-within .input-group-text { + color: var(--primary-color); + } diff --git a/frontend/views/auth/login.html b/frontend/views/auth/login.html index 10ce4c0..56dc5c1 100644 --- a/frontend/views/auth/login.html +++ b/frontend/views/auth/login.html @@ -66,11 +66,6 @@ margin-bottom: 1.25rem; } - .form-control:focus { - box-shadow: none; - border-color: #764ba2; - } - .btn-login { background: var(--primary-gradient); border: none; @@ -104,19 +99,38 @@ text-decoration: underline; } + .input-group { + border: 1px solid #dee2e6; + border-radius: 0.75rem; + overflow: hidden; + transition: border-color 0.2s, box-shadow 0.2s; + background-color: #fff; + } + + .input-group:focus-within { + border-color: #764ba2; + box-shadow: 0 0 0 0.2rem rgba(118, 75, 162, 0.1); + } + .input-group-text { background-color: transparent; - border-right: none; + border: none; color: #adb5bd; + padding-left: 1rem; + padding-right: 0.5rem; } - .form-control { - border-left: none; + .form-control, .form-select { + border: none !important; + padding-left: 0.5rem; } - .form-control:focus + .input-group-text, - .input-group-text:focus-within { - border-color: #764ba2; + .form-control:focus, .form-select:focus { + box-shadow: none; + } + + .input-group:focus-within .input-group-text i { + color: #764ba2; } /* 角色图标 */ diff --git a/frontend/views/auth/register.html b/frontend/views/auth/register.html index 0cebd74..994e42e 100644 --- a/frontend/views/auth/register.html +++ b/frontend/views/auth/register.html @@ -96,26 +96,39 @@ text-decoration: underline; } + .input-group { + border: 1px solid #dee2e6; + border-radius: 0.75rem; + overflow: hidden; + transition: border-color 0.2s, box-shadow 0.2s; + background-color: #fff; + } + + .input-group:focus-within { + border-color: #764ba2; + box-shadow: 0 0 0 0.2rem rgba(118, 75, 162, 0.1); + } + .input-group-text { background-color: transparent; - border-right: none; + border: none; color: #adb5bd; width: 45px; justify-content: center; + padding-left: 1rem; } .form-control, .form-select { - border-left: none; + border: none !important; + padding-left: 0.5rem; } .form-control:focus, .form-select:focus { box-shadow: none; - border-color: #764ba2; } - .form-control:focus + .input-group-text, - .input-group-text:focus-within { - border-color: #764ba2; + .input-group:focus-within .input-group-text i { + color: #764ba2; } #classField {