diff --git a/app.html b/app.html index a171c98..a239687 100644 --- a/app.html +++ b/app.html @@ -1,13 +1,11 @@ - 运动会报名系统 -
@@ -22,30 +20,22 @@
- +
-

个人信息

-

查看并维护当前登录人员的基础资料。

+

系统首页

+

欢迎进入运动会报名系统。

-
- - - +
+ - + - - \ No newline at end of file + diff --git a/assets/css/style.css b/assets/css/style.css index 8f9f6fb..4fcf920 100644 --- a/assets/css/style.css +++ b/assets/css/style.css @@ -295,6 +295,7 @@ select[name="college"]:valid { display: grid; grid-template-columns: 220px 1fr; gap: 18px; + align-items: start; } .sidebar { @@ -302,6 +303,8 @@ select[name="college"]:valid { display: grid; gap: 10px; align-content: start; + min-height: 720px; + background: linear-gradient(180deg, #23364d 0%, #32465f 100%); } .nav-item { @@ -310,19 +313,31 @@ select[name="college"]:valid { padding: 16px 18px; border-radius: 18px; background: transparent; - color: var(--text); + color: rgba(255, 255, 255, 0.86); font-weight: 700; + border: 1px solid transparent; } -.nav-item.active, -.tab-item.active { - background: linear-gradient(135deg, rgba(15, 118, 110, 0.14), rgba(20, 184, 166, 0.24)); - color: #115e59; +.nav-item.active { + background: rgba(255, 255, 255, 0.12); + color: #ffffff; + border-color: rgba(255, 255, 255, 0.16); +} + +.nav-item:hover { + background: rgba(255, 255, 255, 0.08); } .content-area { display: grid; gap: 18px; + align-content: start; + align-items: start; +} + +.content-card { + align-self: start; + height: auto; } .content-header, @@ -342,7 +357,15 @@ select[name="college"]:valid { padding: 12px 18px; border-radius: 14px; background: rgba(255, 255, 255, 0.72); + color: var(--text); font-weight: 700; + border: 1px solid rgba(148, 163, 184, 0.2); +} + +.tab-item.active { + background: linear-gradient(135deg, rgba(15, 118, 110, 0.14), rgba(20, 184, 166, 0.24)); + color: #115e59; + border-color: rgba(15, 118, 110, 0.18); } .profile-grid, @@ -355,6 +378,7 @@ select[name="college"]:valid { .summary-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); margin-bottom: 22px; + align-items: start; } .info-card, @@ -363,6 +387,8 @@ select[name="college"]:valid { border-radius: 20px; background: rgba(248, 250, 252, 0.96); border: 1px solid rgba(226, 232, 240, 0.9); + height: auto; + align-self: start; } .summary-card strong, @@ -519,4 +545,4 @@ select[name="college"]:valid { display: block; overflow-x: auto; } -} \ No newline at end of file +} diff --git a/assets/js/app-main.js b/assets/js/app-main.js new file mode 100644 index 0000000..ce2b005 --- /dev/null +++ b/assets/js/app-main.js @@ -0,0 +1,714 @@ +document.addEventListener('DOMContentLoaded', function () { + var currentUserName = document.getElementById('currentUserName'); + var logoutBtn = document.getElementById('logoutBtn'); + var sidebarNav = document.getElementById('sidebarNav'); + var sectionTitle = document.getElementById('sectionTitle'); + var sectionDesc = document.getElementById('sectionDesc'); + var subTabs = document.getElementById('subTabs'); + var mainView = document.getElementById('mainView'); + + var state = { + user: null, + currentView: '', + currentTab: 'all', + events: [], + myEvents: [], + adminUsers: [], + adminRegistrations: [], + adminEvents: [], + editingEventId: null + }; + + var genderOptions = ['男', '女']; + var collegeOptions = [ + '文学院与文化传播学院', + '马克思主义学院', + '教育学院', + '外国语学院', + '历史文化学院', + '商学院', + '化学工程与技术学院', + '电子信息与电气工程学院', + '数学与统计学院', + '生物工程与技术学院', + '机电工程学院', + '土木工程学院', + '资源与环境工程学院', + '体育学院', + '美术与设计学院', + '音乐舞蹈学院', + '卫生健康学院', + '继续教育学院(培训中心)' + ]; + var categoryOptions = ['青年组', '老年组']; + + var studentMenus = [ + { key: 'profile', label: '个人信息', desc: '查看并修改个人信息。' }, + { key: 'events', label: '运动会报名', desc: '查看项目、报名和取消报名。' } + ]; + + var adminMenus = [ + { key: 'admin-home', label: '运动会管理', desc: '查看系统概览。' }, + { key: 'team-info', label: '团体信息管理', desc: '管理学院、班级等团体信息。' }, + { key: 'user-manage', label: '用户信息管理', desc: '管理用户资料、权限和状态。' }, + { key: 'event-manage', label: '项目管理', desc: '新增、编辑和删除比赛项目。' }, + { key: 'athlete-manage', label: '参赛运动员管理', desc: '查看所有已报名人员和项目。' }, + { key: 'score-manage', label: '参赛成绩管理', desc: '录入和维护成绩。' }, + { key: 'record-manage', label: '项目记录管理', desc: '维护项目记录和赛事资料。' }, + { key: 'system-manage', label: '系统管理', desc: '维护系统配置。' } + ]; + + function escapeHtml(value) { + return String(value == null ? '' : value) + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"') + .replace(/'/g, '''); + } + + function getMenus() { + return state.user && state.user.role === 'ADMIN' ? adminMenus : studentMenus; + } + + function getMeta(viewKey) { + var menu = getMenus().find(function (item) { + return item.key === viewKey; + }); + return menu || { label: '系统首页', desc: '欢迎进入运动会报名系统。' }; + } + + function renderSidebar() { + sidebarNav.innerHTML = getMenus().map(function (item) { + return ''; + }).join(''); + + Array.prototype.slice.call(sidebarNav.querySelectorAll('.nav-item')).forEach(function (button) { + button.addEventListener('click', function () { + switchView(button.getAttribute('data-view')); + }); + }); + } + + function renderTabs() { + if (state.currentView !== 'events') { + subTabs.innerHTML = ''; + subTabs.classList.add('hidden'); + return; + } + + subTabs.innerHTML = '' + + '' + + ''; + subTabs.classList.remove('hidden'); + + Array.prototype.slice.call(subTabs.querySelectorAll('.tab-item')).forEach(function (button) { + button.addEventListener('click', function () { + state.currentTab = button.getAttribute('data-tab'); + renderTabs(); + renderCurrentView(); + }); + }); + } + + function renderProfile() { + mainView.innerHTML = '' + + '
' + + '

基础资料

当前账号信息如下。

' + + '
' + + infoCard('身份证号', state.user.idCard) + + infoCard('登录账号', state.user.username) + + infoCard('姓名', state.user.name) + + infoCard('联系电话', state.user.phone) + + infoCard('性别', state.user.gender) + + infoCard('学院', state.user.college) + + infoCard('班级', state.user.className) + + infoCard('学号', state.user.studentNo) + + infoCard('类别', state.user.category) + + infoCard('角色', state.user.role) + + '
' + + '
' + + '
' + + '

修改个人信息

可在此更新姓名、电话、学院、班级、学号等信息。

' + + '
' + + fieldInput('姓名', 'name', state.user.name, '请输入姓名') + + fieldInput('联系电话', 'phone', state.user.phone, '请输入电话') + + fieldSelect('性别', 'gender', state.user.gender, genderOptions, '请选择性别') + + fieldSelect('学院', 'college', state.user.college, collegeOptions, '请选择学院') + + fieldInput('班级', 'className', state.user.className, '请输入班级') + + fieldInput('学号', 'studentNo', state.user.studentNo, '请输入学号') + + fieldSelect('类别', 'category', state.user.category, categoryOptions, '请选择类别', true) + + '
' + + ' ' + + '
' + + '

' + + '
' + + '
'; + + var form = document.getElementById('profileForm'); + var messageEl = document.getElementById('profileMessage'); + form.addEventListener('submit', function (event) { + event.preventDefault(); + var formData = new FormData(form); + appUtils.ajax({ + method: 'PUT', + url: '/api/users/me', + data: { + name: String(formData.get('name') || '').trim(), + phone: String(formData.get('phone') || '').trim(), + gender: String(formData.get('gender') || '').trim(), + college: String(formData.get('college') || '').trim(), + className: String(formData.get('className') || '').trim(), + studentNo: String(formData.get('studentNo') || '').trim(), + category: String(formData.get('category') || '').trim() + }, + success: function (response) { + if (!response.success || !response.data) { + appUtils.showMessage(messageEl, response.message || '保存失败', false); + return; + } + state.user = response.data; + updateCurrentUserName(); + renderProfile(); + appUtils.showMessage(document.getElementById('profileMessage'), '个人信息修改成功', true); + }, + error: function (xhr, response) { + appUtils.showMessage(messageEl, (response && response.message) || '保存失败', false); + } + }); + }); + } + + function renderEventTable(list, isMine) { + if (!list.length) { + mainView.innerHTML = '

暂无数据

' + (isMine ? '你还没有报名任何项目。' : '当前暂无可展示项目。') + '

'; + return; + } + + mainView.innerHTML = '' + + '' + + ' ' + + ' ' + + list.map(function (item) { + var buttonHtml = isMine + ? '' + : ''; + return '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + ''; + }).join('') + + ' ' + + '
项目名称项目分类比赛时间比赛地点报名情况项目说明操作
' + escapeHtml(item.eventName) + '' + escapeHtml(item.eventCategory) + '' + escapeHtml(item.eventTime) + '' + escapeHtml(item.location) + '' + escapeHtml((item.registeredCount || 0) + '/' + (item.quota || 0)) + '' + escapeHtml(item.description) + '' + buttonHtml + '
'; + + Array.prototype.slice.call(document.querySelectorAll('.register-btn')).forEach(function (button) { + button.addEventListener('click', function () { + var eventId = button.getAttribute('data-id'); + appUtils.ajax({ + method: 'POST', + url: '/api/events/' + eventId + '/register', + success: function (response) { + if (!response.success) { + window.alert(response.message || '报名失败'); + return; + } + loadEventData(); + }, + error: function (xhr, response) { + window.alert((response && response.message) || '报名失败'); + } + }); + }); + }); + + Array.prototype.slice.call(document.querySelectorAll('.cancel-btn')).forEach(function (button) { + button.addEventListener('click', function () { + var eventId = button.getAttribute('data-id'); + appUtils.ajax({ + method: 'DELETE', + url: '/api/events/' + eventId + '/register', + success: function (response) { + if (!response.success) { + window.alert(response.message || '取消报名失败'); + return; + } + loadEventData(); + }, + error: function (xhr, response) { + window.alert((response && response.message) || '取消报名失败'); + } + }); + }); + }); + } + + function renderAdminHome() { + mainView.innerHTML = '' + + '
' + + '

系统概览

管理员可在此查看系统整体情况。

' + + '
' + + summaryCard('用户总数', state.adminUsers.length) + + summaryCard('报名记录', state.adminRegistrations.length) + + summaryCard('比赛项目', state.adminEvents.length) + + '
' + + '
'; + } + + function renderUserManage() { + if (!state.adminUsers.length) { + mainView.innerHTML = '

暂无用户

当前系统中还没有用户数据。

'; + return; + } + + mainView.innerHTML = '' + + '
' + + '

数据概览

查看当前系统内用户整体情况。

' + + '
' + + summaryCard('用户总数', state.adminUsers.length) + + summaryCard('管理员数量', state.adminUsers.filter(function (item) { return item.role === 'ADMIN'; }).length) + + summaryCard('禁用账号数量', state.adminUsers.filter(function (item) { return item.status === 'DISABLED'; }).length) + + '
' + + '
' + + '
' + + '

用户列表

支持重置密码、禁用、解除禁用和删除账号。

' + + ' ' + + ' ' + + ' ' + + state.adminUsers.map(function (item) { + var isAdmin = item.role === 'ADMIN'; + var statusText = item.status === 'DISABLED' ? '已禁用' : '正常'; + var enableOrDisable = isAdmin ? '' : (item.status === 'DISABLED' + ? '' + : ''); + var deleteAction = isAdmin ? '' : ''; + return '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + ''; + }).join('') + + ' ' + + '
姓名账号身份证号电话性别学院班级学号类别角色状态操作
' + escapeHtml(item.name) + '' + escapeHtml(item.username) + '' + escapeHtml(item.idCard) + '' + escapeHtml(item.phone) + '' + escapeHtml(item.gender) + '' + escapeHtml(item.college) + '' + escapeHtml(item.className) + '' + escapeHtml(item.studentNo) + '' + escapeHtml(item.category) + '' + escapeHtml(item.role) + '' + escapeHtml(statusText) + ' ' + enableOrDisable + ' ' + deleteAction + '
' + + '
'; + + bindAdminUserActions(); + } + + function renderAthleteManage() { + if (!state.adminRegistrations.length) { + mainView.innerHTML = '

暂无报名记录

当前还没有参赛人员数据。

'; + return; + } + + var coveredEvents = {}; + state.adminRegistrations.forEach(function (item) { + coveredEvents[item.eventName] = true; + }); + + mainView.innerHTML = '' + + '
' + + '

数据概览

查看当前参赛人员和报名记录。

' + + '
' + + summaryCard('报名记录总数', state.adminRegistrations.length) + + summaryCard('已覆盖项目', Object.keys(coveredEvents).length) + + summaryCard('系统用户数', state.adminUsers.length) + + '
' + + '
' + + '
' + + '

参赛名单

显示所有已报名人员和项目详情。

' + + ' ' + + ' ' + + ' ' + + state.adminRegistrations.map(function (item) { + return '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + ''; + }).join('') + + ' ' + + '
姓名账号电话学院类别项目名称项目分类时间地点状态报名时间
' + escapeHtml(item.studentName) + '' + escapeHtml(item.username) + '' + escapeHtml(item.phone) + '' + escapeHtml(item.college) + '' + escapeHtml(item.category) + '' + escapeHtml(item.eventName) + '' + escapeHtml(item.eventCategory) + '' + escapeHtml((item.eventTime || '') + ' / ' + (item.location || '')) + '' + escapeHtml(item.status) + '' + escapeHtml(item.createdAt) + '
' + + '
'; + } + + function renderEventManage() { + var editingItem = state.adminEvents.find(function (item) { + return item.id === state.editingEventId; + }) || { + eventName: '', + eventCategory: '', + location: '', + quota: '', + eventTime: '', + description: '' + }; + + mainView.innerHTML = '' + + '
' + + '

' + (state.editingEventId ? '编辑项目' : '新增项目') + '

在这里维护比赛项目基础信息。

' + + '
' + + fieldInput('项目名称', 'eventName', editingItem.eventName, '请输入项目名称') + + fieldInput('项目分类', 'eventCategory', editingItem.eventCategory, '请输入项目分类') + + fieldInput('比赛地点', 'location', editingItem.location, '请输入比赛地点') + + ' ' + + fieldInput('比赛时间', 'eventTime', editingItem.eventTime, '例如 2026-05-20 08:30', true) + + fieldInput('项目说明', 'description', editingItem.description, '请输入项目说明', true) + + '
' + + ' ' + + ' ' + + '
' + + '

' + + '
' + + '
' + + '
' + + '

项目列表

查看、编辑和删除当前项目。

' + + (state.adminEvents.length ? '' + + '' + + ' ' + + ' ' + + state.adminEvents.map(function (item) { + return '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + ''; + }).join('') + + ' ' + + '
项目名称项目分类比赛时间比赛地点人数上限已报名项目说明操作
' + escapeHtml(item.eventName) + '' + escapeHtml(item.eventCategory) + '' + escapeHtml(item.eventTime) + '' + escapeHtml(item.location) + '' + escapeHtml(item.quota) + '' + escapeHtml(item.registeredCount || 0) + '' + escapeHtml(item.description) + '
' + : '

暂无项目

请先新增比赛项目。

') + + '
'; + + bindEventManageActions(); + } + + function renderPlaceholder(title, desc) { + mainView.innerHTML = '' + + '
' + + '

' + escapeHtml(title) + '

' + escapeHtml(desc) + '

' + + '

功能持续完善中

这个模块的详细功能可以继续在现有框架上补充。

' + + '
'; + } + + function renderCurrentView() { + var meta = getMeta(state.currentView); + sectionTitle.textContent = meta.label; + sectionDesc.textContent = meta.desc; + renderTabs(); + + if (state.currentView === 'profile') { + renderProfile(); + return; + } + if (state.currentView === 'events') { + renderEventTable(state.currentTab === 'mine' ? state.myEvents : state.events, state.currentTab === 'mine'); + return; + } + if (state.currentView === 'admin-home') { + renderAdminHome(); + return; + } + if (state.currentView === 'user-manage') { + renderUserManage(); + return; + } + if (state.currentView === 'athlete-manage') { + renderAthleteManage(); + return; + } + if (state.currentView === 'event-manage') { + renderEventManage(); + return; + } + if (state.currentView === 'team-info') { + renderPlaceholder('团体信息管理', '可继续补充学院、班级、代表队等团体信息管理功能。'); + return; + } + if (state.currentView === 'score-manage') { + renderPlaceholder('参赛成绩管理', '可继续补充成绩录入、成绩维护、成绩查询等功能。'); + return; + } + if (state.currentView === 'record-manage') { + renderPlaceholder('项目记录管理', '可继续补充项目记录、秩序册和赛事档案管理功能。'); + return; + } + if (state.currentView === 'system-manage') { + renderPlaceholder('系统管理', '可继续补充系统配置、权限设置和运行维护功能。'); + return; + } + + renderPlaceholder('系统首页', '欢迎进入运动会报名系统。'); + } + + function switchView(view) { + state.currentView = view; + if (view === 'events' && state.currentTab !== 'mine') { + state.currentTab = 'all'; + } + renderSidebar(); + renderCurrentView(); + } + + function loadEventData() { + appUtils.ajax({ + method: 'GET', + url: '/api/events', + success: function (response) { + if (response.success) { + state.events = response.data || []; + if (state.currentView === 'events') { + renderCurrentView(); + } + } + } + }); + + appUtils.ajax({ + method: 'GET', + url: '/api/events/my', + success: function (response) { + if (response.success) { + state.myEvents = response.data || []; + if (state.currentView === 'events') { + renderCurrentView(); + } + } + } + }); + } + + function loadAdminData() { + if (!state.user || state.user.role !== 'ADMIN') { + return; + } + + appUtils.ajax({ + method: 'GET', + url: '/api/admin/users', + success: function (response) { + if (response.success) { + state.adminUsers = response.data || []; + renderCurrentView(); + } + } + }); + + appUtils.ajax({ + method: 'GET', + url: '/api/admin/registrations', + success: function (response) { + if (response.success) { + state.adminRegistrations = response.data || []; + renderCurrentView(); + } + } + }); + + appUtils.ajax({ + method: 'GET', + url: '/api/admin/events', + success: function (response) { + if (response.success) { + state.adminEvents = response.data || []; + renderCurrentView(); + } + } + }); + } + + function bindAdminUserActions() { + bindUserAction('.reset-password-btn', 'POST', '/api/admin/users/{id}/reset-password', '重置密码成功'); + bindUserAction('.disable-user-btn', 'POST', '/api/admin/users/{id}/disable', '账号已禁用'); + bindUserAction('.enable-user-btn', 'POST', '/api/admin/users/{id}/enable', '账号已解除禁用'); + bindUserAction('.delete-user-btn', 'DELETE', '/api/admin/users/{id}', '用户已删除'); + } + + function bindUserAction(selector, method, urlTemplate, successText) { + Array.prototype.slice.call(document.querySelectorAll(selector)).forEach(function (button) { + button.addEventListener('click', function () { + var userId = button.getAttribute('data-id'); + appUtils.ajax({ + method: method, + url: urlTemplate.replace('{id}', userId), + success: function (response) { + if (!response.success) { + window.alert(response.message || '操作失败'); + return; + } + if (successText) { + window.alert(successText); + } + loadAdminData(); + }, + error: function (xhr, response) { + window.alert((response && response.message) || '操作失败'); + } + }); + }); + }); + } + + function bindEventManageActions() { + var form = document.getElementById('eventForm'); + var resetButton = document.getElementById('resetEventForm'); + var messageEl = document.getElementById('eventFormMessage'); + + if (form) { + form.addEventListener('submit', function (event) { + event.preventDefault(); + var formData = new FormData(form); + var payload = { + eventName: String(formData.get('eventName') || '').trim(), + eventCategory: String(formData.get('eventCategory') || '').trim(), + location: String(formData.get('location') || '').trim(), + quota: Number(formData.get('quota') || 0), + eventTime: String(formData.get('eventTime') || '').trim(), + description: String(formData.get('description') || '').trim() + }; + + appUtils.ajax({ + method: state.editingEventId ? 'PUT' : 'POST', + url: state.editingEventId ? '/api/admin/events/' + state.editingEventId : '/api/admin/events', + data: payload, + success: function (response) { + if (!response.success) { + appUtils.showMessage(messageEl, response.message || '保存失败', false); + return; + } + state.editingEventId = null; + loadAdminData(); + }, + error: function (xhr, response) { + appUtils.showMessage(messageEl, (response && response.message) || '保存失败', false); + } + }); + }); + } + + if (resetButton) { + resetButton.addEventListener('click', function () { + state.editingEventId = null; + renderCurrentView(); + }); + } + + Array.prototype.slice.call(document.querySelectorAll('.edit-event-btn')).forEach(function (button) { + button.addEventListener('click', function () { + state.editingEventId = Number(button.getAttribute('data-id')); + renderCurrentView(); + }); + }); + + Array.prototype.slice.call(document.querySelectorAll('.delete-event-btn')).forEach(function (button) { + button.addEventListener('click', function () { + var eventId = button.getAttribute('data-id'); + appUtils.ajax({ + method: 'DELETE', + url: '/api/admin/events/' + eventId, + success: function (response) { + if (!response.success) { + window.alert(response.message || '删除失败'); + return; + } + if (state.editingEventId === Number(eventId)) { + state.editingEventId = null; + } + loadAdminData(); + }, + error: function (xhr, response) { + window.alert((response && response.message) || '删除失败'); + } + }); + }); + }); + } + + function loadCurrentUser() { + appUtils.ajax({ + method: 'GET', + url: '/api/users/me', + success: function (response) { + if (!response.success || !response.data) { + window.location.href = './login.html'; + return; + } + + state.user = response.data; + state.currentView = state.user.role === 'ADMIN' ? 'admin-home' : 'profile'; + updateCurrentUserName(); + renderSidebar(); + renderCurrentView(); + loadEventData(); + loadAdminData(); + }, + error: function () { + window.location.href = './login.html'; + } + }); + } + + function updateCurrentUserName() { + currentUserName.textContent = state.user.name + (state.user.role === 'ADMIN' ? ' 管理员' : ' 用户'); + } + + function fieldInput(label, name, value, placeholder, fullRow) { + return ' '; + } + + function fieldSelect(label, name, value, options, placeholder, fullRow) { + return ' '; + } + + function infoCard(label, value) { + return '
' + label + '

' + escapeHtml(value) + '

'; + } + + function summaryCard(label, value) { + return '
' + label + '

' + escapeHtml(value) + '

'; + } + + logoutBtn.addEventListener('click', function () { + appUtils.ajax({ + method: 'POST', + url: '/api/auth/logout', + success: function () { + window.location.href = './login.html'; + }, + error: function () { + window.location.href = './login.html'; + } + }); + }); + + loadCurrentUser(); +}); diff --git a/assets/js/app.js b/assets/js/app.js index 059cb0c..661d585 100644 --- a/assets/js/app.js +++ b/assets/js/app.js @@ -1,31 +1,40 @@ -document.addEventListener('DOMContentLoaded', function () { +document.addEventListener('DOMContentLoaded', function () { var currentUserName = document.getElementById('currentUserName'); var logoutBtn = document.getElementById('logoutBtn'); - var navItems = document.querySelectorAll('.nav-item'); + var sidebarNav = document.getElementById('sidebarNav'); var sectionTitle = document.getElementById('sectionTitle'); var sectionDesc = document.getElementById('sectionDesc'); var subTabs = document.getElementById('subTabs'); - var profileView = document.getElementById('profileView'); - var eventsView = document.getElementById('eventsView'); - var adminView = document.getElementById('adminView'); - var registrationsView = document.getElementById('registrationsView'); - var adminNavBtn = document.getElementById('adminNavBtn'); - var registrationsNavBtn = document.getElementById('registrationsNavBtn'); + var mainView = document.getElementById('mainView'); var state = { - currentView: 'profile', - currentTab: 'all', user: null, + currentView: '', + currentTab: 'all', events: [], myEvents: [], adminUsers: [], adminRegistrations: [], - eventPage: 1, - myEventPage: 1, - registrationsPage: 1, - pageSize: 7 + adminEvents: [], + editingEventId: null }; + var studentMenus = [ + { key: 'profile', label: '涓汉淇℃伅', desc: '鏌ョ湅骞剁淮鎶ゅ綋鍓嶇櫥褰曚汉鍛樼殑鍩虹璧勬枡銆? }, + { key: 'events', label: '杩愬姩浼氭姤鍚?, desc: '娴忚鎵€鏈夐」鐩苟瀹屾垚鎶ュ悕锛屼篃鍙互鏌ョ湅鑷繁鐨勬姤鍚嶄俊鎭€? } + ]; + + var adminMenus = [ + { key: 'admin-home', label: '杩愬姩浼氱鐞?, desc: '鏌ョ湅鍚庡彴棣栭〉鍜岀郴缁熸瑙堛€? }, + { key: 'team-info', label: '鍥綋淇℃伅绠$悊', desc: '缁存姢鍙傝禌鍥綋涓庣粍缁囦俊鎭€? }, + { key: 'user-manage', label: '鐢ㄦ埛淇℃伅绠$悊', desc: '鏌ョ湅銆佺淮鎶ょ敤鎴疯祫鏂欏苟鎵ц璐﹀彿绠$悊鎿嶄綔銆? }, + { key: 'event-manage', label: '椤圭洰绠$悊', desc: '缁存姢璧涗簨椤圭洰銆佸垎绫汇€佺粍鍒拰鎶ュ悕鍙傛暟銆? }, + { key: 'athlete-manage', label: '鍙傝禌杩愬姩鍛樼鐞?, desc: '鏌ョ湅鎵€鏈夊凡鎶ュ悕杩愬姩鍛樺拰鍙傝禌鍚嶅崟銆? }, + { key: 'score-manage', label: '鍙傝禌鎴愮哗绠$悊', desc: '褰曞叆銆佹煡鐪嬪拰缁存姢姣旇禌鎴愮哗銆? }, + { key: 'record-manage', label: '椤圭洰璁板綍绠$悊', desc: '绠$悊椤圭洰璁板綍銆佺З搴忓唽鍜岃禌浜嬭褰曘€? }, + { key: 'system-manage', label: '绯荤粺绠$悊', desc: '缁存姢绯荤粺鍩虹閰嶇疆鍜屽悗鍙拌繍琛屼俊鎭€? } + ]; + function escapeHtml(value) { return String(value == null ? '' : value) .replace(/&/g, '&') @@ -35,76 +44,35 @@ document.addEventListener('DOMContentLoaded', function () { .replace(/'/g, '''); } - function buildOptions(list, current) { - return list.map(function (item) { - return ''; - }).join(''); + function getMenus() { + return state.user && state.user.role === 'ADMIN' ? adminMenus : studentMenus; } - function buildCollegeOptions(current) { - var colleges = [ - '文学与文化传播学院', - '马克思主义学院', - '教育学院', - '外国语学院', - '历史文化学院', - '商学院', - '化学工程与技术学院', - '电子信息与电气工程学院', - '数学与统计学院', - '生物工程与技术学院', - '机电工程学院', - '土木工程学院', - '资源与环境工程学院', - '体育学院', - '美术与设计学院', - '音乐舞蹈学院', - '卫生健康学院', - '继续教育学院(培训中心)' - ]; - return '' + colleges.map(function (item) { - return ''; + function renderSidebar() { + var menus = getMenus(); + sidebarNav.innerHTML = menus.map(function (item, index) { + return ''; }).join(''); - } - - function getPaginatedList(list, page) { - var start = (page - 1) * state.pageSize; - var end = start + state.pageSize; - return list.slice(start, end); - } - function getTotalPages(list) { - return Math.ceil(list.length / state.pageSize); - } - - function renderPagination(totalPages, currentPage, type) { - if (totalPages <= 1) { - return ''; - } - var html = ''; - return html; + Array.prototype.slice.call(sidebarNav.querySelectorAll('.nav-item')).forEach(function (button) { + button.addEventListener('click', function () { + switchView(button.getAttribute('data-view')); + }); + }); } function renderTabs() { var html = ''; if (state.currentView === 'events') { html = '' - + '' - + ''; - } else if (state.currentView === 'admin') { - html = ''; + + '' + + ''; } subTabs.innerHTML = html; subTabs.classList.toggle('hidden', !html); - Array.prototype.slice.call(subTabs.querySelectorAll('.tab-item')).forEach(function (item) { - item.addEventListener('click', function () { - state.currentTab = item.getAttribute('data-tab'); + Array.prototype.slice.call(subTabs.querySelectorAll('.tab-item')).forEach(function (button) { + button.addEventListener('click', function () { + state.currentTab = button.getAttribute('data-tab'); renderTabs(); renderCurrentView(); }); @@ -112,60 +80,104 @@ document.addEventListener('DOMContentLoaded', function () { } function renderProfile() { - if (!state.user) { - return; - } - profileView.innerHTML = '' + mainView.innerHTML = '' + '
' - + '

基础资料

支持在线更新姓名、电话、性别、学院和类别信息。

' + + '

鍩虹璧勬枡

褰撳墠璐﹀彿鐨勪釜浜轰俊鎭涓嬨€?/p>

' + '
' - + '
身份证号

' + escapeHtml(state.user.idCard) + '

' - + '
登录账号

' + escapeHtml(state.user.username) + '

' - + '
姓名

' + escapeHtml(state.user.name) + '

' - + '
联系电话

' + escapeHtml(state.user.phone) + '

' - + '
性别

' + escapeHtml(state.user.gender) + '

' - + '
学院

' + escapeHtml(state.user.college) + '

' - + '
类别

' + escapeHtml(state.user.category) + '

' + + '
韬唤璇佸彿

' + escapeHtml(state.user.idCard) + '

' + + '
鐧诲綍璐﹀彿

' + escapeHtml(state.user.username) + '

' + + '
濮撳悕

' + escapeHtml(state.user.name) + '

' + + '
鑱旂郴鐢佃瘽

' + escapeHtml(state.user.phone) + '

' + + '
鎬у埆

' + escapeHtml(state.user.gender) + '

' + + '
瀛﹂櫌

' + escapeHtml(state.user.college) + '

' + + '
鐝骇

' + escapeHtml(state.user.className) + '

' + + '
瀛﹀彿

' + escapeHtml(state.user.studentNo) + '

' + + '
绫诲埆

' + escapeHtml(state.user.category) + '

' + + '
瑙掕壊

' + escapeHtml(state.user.role) + '

' + + '
' + + '
'; + } + + function renderProfile() { + mainView.innerHTML = '' + + '
' + + '

鍩虹璧勬枡

褰撳墠璐﹀彿鐨勪釜浜轰俊鎭涓嬨€?/p>

' + + '
' + + '
韬唤璇佸彿

' + escapeHtml(state.user.idCard) + '

' + + '
鐧诲綍璐﹀彿

' + escapeHtml(state.user.username) + '

' + + '
濮撳悕

' + escapeHtml(state.user.name) + '

' + + '
鑱旂郴鐢佃瘽

' + escapeHtml(state.user.phone) + '

' + + '
鎬у埆

' + escapeHtml(state.user.gender) + '

' + + '
瀛﹂櫌

' + escapeHtml(state.user.college) + '

' + + '
鐝骇

' + escapeHtml(state.user.className) + '

' + + '
瀛﹀彿

' + escapeHtml(state.user.studentNo) + '

' + + '
绫诲埆

' + escapeHtml(state.user.category) + '

' + + '
瑙掕壊

' + escapeHtml(state.user.role) + '

' + '
' + '
' + '
' - + '

修改信息

请保持信息真实准确,方便赛事组织和通知。

' + + '

淇敼涓汉淇℃伅

鍙互鍦ㄨ繖閲屾洿鏂板鍚嶃€佺數璇濄€佸闄€佺彮绾у拰瀛﹀彿绛変俊鎭€?/p>

' + '
' - + ' ' - + ' ' - + ' ' - + ' ' - + ' ' - + '
' + + ' ' + + '
' + '

' + ' ' + ''; - document.getElementById('profileForm').addEventListener('submit', function (event) { + bindProfileForm(); + } + + function bindProfileForm() { + var form = document.getElementById('profileForm'); + var messageEl = document.getElementById('profileMessage'); + + if (!form) { + return; + } + + form.addEventListener('submit', function (event) { event.preventDefault(); - var formData = new FormData(event.target); + var formData = new FormData(form); + var payload = { + name: String(formData.get('name') || '').trim(), + phone: String(formData.get('phone') || '').trim(), + gender: String(formData.get('gender') || '').trim(), + college: String(formData.get('college') || '').trim(), + className: String(formData.get('className') || '').trim(), + studentNo: String(formData.get('studentNo') || '').trim(), + category: String(formData.get('category') || '').trim() + }; + appUtils.ajax({ method: 'PUT', url: '/api/users/me', - data: { - name: String(formData.get('name') || '').trim(), - phone: String(formData.get('phone') || '').trim(), - gender: String(formData.get('gender') || ''), - college: String(formData.get('college') || '').trim(), - category: String(formData.get('category') || '') - }, + data: payload, success: function (response) { - if (!response.success) { - appUtils.showMessage(document.getElementById('profileMessage'), response.message || '保存失败', false); + if (!response.success || !response.data) { + appUtils.showMessage(messageEl, response.message || '淇敼澶辫触', false); return; } + state.user = response.data; - currentUserName.textContent = state.user.name + (state.user.role === 'ADMIN' ? ' 管理员' : ' 老师'); + currentUserName.textContent = state.user.name + (state.user.role === 'ADMIN' ? ' 绠$悊鍛? : ' 鐢ㄦ埛'); renderProfile(); - appUtils.showMessage(document.getElementById('profileMessage'), '个人信息已更新', true); + appUtils.showMessage(document.getElementById('profileMessage'), 'Saved successfully', true); }, error: function (xhr, response) { - appUtils.showMessage(document.getElementById('profileMessage'), (response && response.message) || '保存失败', false); + appUtils.showMessage(messageEl, (response && response.message) || '淇敼澶辫触', false); } }); }); @@ -173,20 +185,18 @@ document.addEventListener('DOMContentLoaded', function () { function renderEventTable(list, isMine) { if (!list.length) { - return '

暂无数据

' + (isMine ? '你还没有报名任何项目。' : '当前暂无可报名项目。') + '

'; + mainView.innerHTML = '

鏆傛棤鏁版嵁

' + (isMine ? '褰撳墠杩樻病鏈夋姤鍚嶈褰曘€? : '褰撳墠娌℃湁鍙睍绀洪」鐩€?) + '

'; + return; } - var currentPage = isMine ? state.myEventPage : state.eventPage; - var totalPages = getTotalPages(list); - var paginatedList = getPaginatedList(list, currentPage); - - var html = '' + + mainView.innerHTML = '' + '' - + ' ' + + ' ' + ' ' - + paginatedList.map(function (item) { + + list.map(function (item) { var actionHtml = isMine - ? '' - : ''; + ? '' + : ''; return '' + '' + '' @@ -200,87 +210,163 @@ document.addEventListener('DOMContentLoaded', function () { }).join('') + ' ' + '
项目名称项目类别比赛时间比赛地点报名情况项目说明操作
椤圭洰鍚嶇О椤圭洰绫诲埆姣旇禌鏃堕棿姣旇禌鍦扮偣鎶ュ悕鎯呭喌椤圭洰璇存槑鎿嶄綔
' + escapeHtml(item.eventName) + '
'; - - html += renderPagination(totalPages, currentPage, isMine); - html += '
第 ' + currentPage + ' 页 / 共 ' + totalPages + ' 页,共 ' + list.length + ' 条记录
'; - return html; + + bindEventButtons(); } - function renderUserTable() { + function renderUserManage() { if (!state.adminUsers.length) { - return '

暂无用户

当前系统还没有用户数据。

'; + mainView.innerHTML = '

鏆傛棤鐢ㄦ埛

褰撳墠绯荤粺杩樻病鏈夌敤鎴锋暟鎹€?/p>

'; + return; } - return '' - + '' - + '' - + '' + + mainView.innerHTML = '' + + '
' + + '

鏁版嵁姒傝

鏌ョ湅褰撳墠绯荤粺鍐呯敤鎴锋€讳綋鎯呭喌銆?/p>

' + + '
' + + '
鐢ㄦ埛鎬绘暟

' + state.adminUsers.length + '

' + + '
绠$悊鍛樻暟閲?/strong>

' + state.adminUsers.filter(function (item) { return item.role === "ADMIN"; }).length + '

' + + '
绂佺敤璐﹀彿鏁伴噺

' + state.adminUsers.filter(function (item) { return item.status === "DISABLED"; }).length + '

' + + '
' + + '
' + + '
' + + '

鐢ㄦ埛鍒楄〃

鏌ョ湅绯荤粺鍐呮墍鏈夌敤鎴蜂俊鎭€?/p>

' + + '
姓名账号身份证号电话性别学院类别角色操作
' + + ' ' + + ' ' + state.adminUsers.map(function (item) { - return '' - + '' - + '' - + '' - + '' - + '' - + '' - + '' - + '' - + '' - + '' - + ''; - }).join('') - + '
濮撳悕璐﹀彿韬唤璇佸彿鐢佃瘽鎬у埆瀛﹂櫌绫诲埆瑙掕壊鐘舵€?/th>鎿嶄綔
' + escapeHtml(item.name) + '' + escapeHtml(item.username) + '' + escapeHtml(item.idCard) + '' + escapeHtml(item.phone) + '' + escapeHtml(item.gender) + '' + escapeHtml(item.college) + '' + escapeHtml(item.category) + '' + escapeHtml(item.role === 'ADMIN' ? '管理员' : '普通用户') + '' - + ' ' - + '' - + '
'; + var isAdmin = item.role === 'ADMIN'; + var statusText = item.status === 'DISABLED' ? '宸茬鐢? : '姝e父'; + var statusAction = isAdmin + ? '' + : (item.status === 'DISABLED' + ? '' + : ''); + var deleteAction = isAdmin ? '' : ''; + return '' + + '' + + '' + escapeHtml(item.name) + '' + + '' + escapeHtml(item.username) + '' + + '' + escapeHtml(item.idCard) + '' + + '' + escapeHtml(item.phone) + '' + + '' + escapeHtml(item.gender) + '' + + '' + escapeHtml(item.college) + '' + + '' + escapeHtml(item.category) + '' + + '' + escapeHtml(isAdmin ? '绠$悊鍛? : '鏅€氱敤鎴?) + '' + + '' + escapeHtml(statusText) + '' + + ' ' + statusAction + ' ' + deleteAction + '' + + ''; + }).join('') + + ' ' + + ' ' + + ''; + + bindUserManageActions(); } - function bindUserActions() { - // 绑定重置密码按钮事件 - Array.prototype.slice.call(document.querySelectorAll('.reset-btn')).forEach(function (button) { - button.addEventListener('click', function () { - var userId = button.getAttribute('data-id'); - if (confirm('确定要重置该用户的密码吗?重置后密码将变为默认值。')) { - appUtils.ajax({ - method: 'POST', - url: '/api/admin/users/' + userId + '/reset-password', - success: function (response) { - if (response.success) { - alert('密码重置成功!'); - } else { - alert('密码重置失败:' + (response.message || '未知错误')); - } - }, - error: function (xhr, response) { - alert('密码重置失败:' + (response && response.message) || '网络异常'); - } - }); - } - }); - }); + function renderAthleteManage() { + if (!state.adminRegistrations.length) { + mainView.innerHTML = '

鏆傛棤鎶ュ悕璁板綍

褰撳墠杩樻病鏈夊弬璧涜繍鍔ㄥ憳鏁版嵁銆?/p>

'; + return; + } - // 绑定删除账号按钮事件 - Array.prototype.slice.call(document.querySelectorAll('.delete-btn')).forEach(function (button) { - button.addEventListener('click', function () { - var userId = button.getAttribute('data-id'); - if (confirm('确定要删除该账号吗?此操作不可恢复。')) { - appUtils.ajax({ - method: 'DELETE', - url: '/api/admin/users/' + userId, - success: function (response) { - if (response.success) { - alert('账号删除成功!'); - loadAdminData(); - } else { - alert('账号删除失败:' + (response.message || '未知错误')); - } - }, - error: function (xhr, response) { - alert('账号删除失败:' + (response && response.message) || '网络异常'); - } - }); - } - }); - }); + mainView.innerHTML = '' + + '
' + + '

鏁版嵁姒傝

鏌ョ湅褰撳墠鍙傝禌杩愬姩鍛樼殑鎬讳綋缁熻銆?/p>

' + + '
' + + '
鎶ュ悕璁板綍鎬绘暟

' + state.adminRegistrations.length + '

' + + '
宸叉姤鍚嶇姸鎬?/strong>

' + state.adminRegistrations.filter(function (item) { return item.status === "宸叉姤鍚?; }).length + '

' + + '
瑕嗙洊椤圭洰鏁?/strong>

' + uniqueEventCount() + '

' + + '
' + + '
' + + '
' + + '

鍙傝禌鍚嶅崟

鏌ョ湅鎵€鏈夊凡鎶ュ悕杩愬姩鍛樺拰椤圭洰鏄庣粏銆?/p>

' + + ' ' + + ' ' + + ' ' + + state.adminRegistrations.map(function (item) { + return '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + ''; + }).join('') + + ' ' + + '
濮撳悕璐﹀彿鐢佃瘽瀛﹂櫌绫诲埆椤圭洰鍚嶇О椤圭洰绫诲埆鏃堕棿鍦扮偣鐘舵€?/th>鎶ュ悕鏃堕棿
' + escapeHtml(item.studentName) + '' + escapeHtml(item.username) + '' + escapeHtml(item.phone) + '' + escapeHtml(item.college) + '' + escapeHtml(item.category) + '' + escapeHtml(item.eventName) + '' + escapeHtml(item.eventCategory) + '' + escapeHtml(item.eventTime + ' / ' + item.location) + '' + escapeHtml(item.status) + '' + escapeHtml(item.createdAt) + '
' + + '
'; + } + + function renderEventManage() { + var formTitle = state.editingEventId ? '缂栬緫椤圭洰' : '鏂板椤圭洰'; + var editingItem = state.adminEvents.find(function (item) { + return item.id === state.editingEventId; + }) || { + eventName: '', + eventCategory: '', + location: '', + quota: '', + description: '', + eventTime: '' + }; + + mainView.innerHTML = '' + + '
' + + '

' + formTitle + '

鍙湪杩欓噷缁存姢姣旇禌椤圭洰鐨勫熀纭€淇℃伅銆?/p>

' + + '
' + + ' ' + + '
' + + '

' + + ' ' + + '' + + '
' + + '

椤圭洰鍒楄〃

褰撳墠绯荤粺鍐呯殑鍏ㄩ儴姣旇禌椤圭洰銆?/p>

' + + (state.adminEvents.length ? '' + + '' + + ' ' + + ' ' + + state.adminEvents.map(function (item) { + return '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + ''; + }).join('') + + ' ' + + '
椤圭洰鍚嶇О椤圭洰鍒嗙被姣旇禌鏃堕棿姣旇禌鍦扮偣浜烘暟涓婇檺宸叉姤鍚?/th>椤圭洰璇存槑鎿嶄綔
' + escapeHtml(item.eventName) + '' + escapeHtml(item.eventCategory) + '' + escapeHtml(item.eventTime) + '' + escapeHtml(item.location) + '' + escapeHtml(item.quota) + '' + escapeHtml(item.registeredCount || 0) + '' + escapeHtml(item.description) + '
' + : '

鏆傛棤椤圭洰

褰撳墠杩樻病鏈夋瘮璧涢」鐩紝璇峰厛鏂板椤圭洰銆?/p>

') + + '
'; + + bindEventManageActions(); + } + + function renderPlaceholder(title, text) { + mainView.innerHTML = '' + + '
' + + '

' + title + '

' + + '

' + text + '

' + + '
'; } function uniqueEventCount() { @@ -291,46 +377,7 @@ document.addEventListener('DOMContentLoaded', function () { return Object.keys(map).length; } - function renderRegistrationTable() { - var paginatedRegistrations = getPaginatedList(state.adminRegistrations, state.registrationsPage); - if (!paginatedRegistrations.length) { - return '

暂无报名记录

目前还没有用户完成项目报名。

'; - } - return '' - + '' - + '' - + '' - + paginatedRegistrations.map(function (item) { - return '' - + '' - + '' - + '' - + '' - + '' - + '' - + '' - + '' - + '' - + '' - + '' - + ''; - }).join('') - + '
姓名账号电话学院类别项目名称项目类别时间地点状态报名时间
' + escapeHtml(item.studentName) + '' + escapeHtml(item.username) + '' + escapeHtml(item.phone) + '' + escapeHtml(item.college) + '' + escapeHtml(item.category) + '' + escapeHtml(item.eventName) + '' + escapeHtml(item.eventCategory) + '' + escapeHtml(item.eventTime + ' / ' + item.location) + '' + escapeHtml(item.status) + '' + escapeHtml(item.createdAt) + '
'; - } - - function renderAdminContent() { - adminView.innerHTML = '' - + '
' - + '
用户总数

' + state.adminUsers.length + '

' - + '
管理员数量

' + state.adminUsers.filter(function (item) { return item.role === "ADMIN"; }).length + '

' - + '
普通用户数量

' + state.adminUsers.filter(function (item) { return item.role !== "ADMIN"; }).length + '

' - + '
' - + renderUserTable(); - bindUserActions(); - } - - function bindRegisterButtons() { - // 绑定报名按钮事件 + function bindEventButtons() { Array.prototype.slice.call(document.querySelectorAll('.register-btn')).forEach(function (button) { button.addEventListener('click', function () { appUtils.ajax({ @@ -338,142 +385,194 @@ document.addEventListener('DOMContentLoaded', function () { url: '/api/events/' + button.getAttribute('data-id') + '/register', success: function (response) { if (!response.success) { - window.alert(response.message || '报名失败'); + window.alert(response.message || '鎶ュ悕澶辫触'); return; } - window.alert('报名成功'); + window.alert('鎶ュ悕鎴愬姛'); loadEventData(); }, error: function (xhr, response) { - window.alert((response && response.message) || '报名失败'); + window.alert((response && response.message) || '鎶ュ悕澶辫触'); } }); }); }); - // 绑定取消报名按钮事件 Array.prototype.slice.call(document.querySelectorAll('.cancel-btn')).forEach(function (button) { button.addEventListener('click', function () { - if (confirm('确定要取消报名吗?')) { - appUtils.ajax({ - method: 'DELETE', - url: '/api/events/' + button.getAttribute('data-id') + '/register', - success: function (response) { - if (!response.success) { - window.alert(response.message || '取消报名失败'); - return; - } - window.alert('取消报名成功'); - loadEventData(); - }, - error: function (xhr, response) { - window.alert((response && response.message) || '取消报名失败'); + appUtils.ajax({ + method: 'DELETE', + url: '/api/events/' + button.getAttribute('data-id') + '/register', + success: function (response) { + if (!response.success) { + window.alert(response.message || '鍙栨秷鎶ュ悕澶辫触'); + return; } - }); - } + window.alert('鍙栨秷鎶ュ悕鎴愬姛'); + loadEventData(); + }, + error: function (xhr, response) { + window.alert((response && response.message) || '鍙栨秷鎶ュ悕澶辫触'); + } + }); }); }); } - function bindPaginationButtons(type) { - var totalPages, currentPage; - if (type === 'registrations') { - totalPages = getTotalPages(state.adminRegistrations); - currentPage = state.registrationsPage; - } else { - var isMine = type === 'mine'; - totalPages = getTotalPages(isMine ? state.myEvents : state.events); - currentPage = isMine ? state.myEventPage : state.eventPage; - } - - Array.prototype.slice.call(document.querySelectorAll('.pagination .page-btn')).forEach(function (button) { + function bindUserManageActions() { + Array.prototype.slice.call(document.querySelectorAll('.reset-password-btn')).forEach(function (button) { button.addEventListener('click', function () { - var page = button.getAttribute('data-page'); - - if (page === 'prev') { - currentPage = Math.max(1, currentPage - 1); - } else if (page === 'next') { - currentPage = Math.min(totalPages, currentPage + 1); - } else { - currentPage = parseInt(page, 10); - } - - if (type === 'registrations') { - state.registrationsPage = currentPage; - var totalPages = getTotalPages(state.adminRegistrations); - registrationsView.innerHTML = '' - + '
' - + '
报名记录总数

' + state.adminRegistrations.length + '

' - + '
已报名状态

' + state.adminRegistrations.filter(function (item) { return item.status === "已报名"; }).length + '

' - + '
覆盖项目数

' + uniqueEventCount() + '

' - + '
' - + renderRegistrationTable() - + renderPagination(totalPages, state.registrationsPage, 'registrations'); - bindPaginationButtons('registrations'); - } else { - var isMine = type === 'mine'; - if (isMine) { - state.myEventPage = currentPage; - } else { - state.eventPage = currentPage; + var id = button.getAttribute('data-id'); + appUtils.ajax({ + method: 'POST', + url: '/api/admin/users/' + id + '/reset-password', + success: function (response) { + if (!response.success) { + window.alert(response.message || '閲嶇疆瀵嗙爜澶辫触'); + return; + } + window.alert('瀵嗙爜宸查噸缃负 123456'); + }, + error: function (xhr, response) { + window.alert((response && response.message) || '閲嶇疆瀵嗙爜澶辫触'); + } + }); + }); + }); + + Array.prototype.slice.call(document.querySelectorAll('.disable-user-btn')).forEach(function (button) { + button.addEventListener('click', function () { + var id = button.getAttribute('data-id'); + appUtils.ajax({ + method: 'POST', + url: '/api/admin/users/' + id + '/disable', + success: function (response) { + if (!response.success) { + window.alert(response.message || '绂佺敤璐︽埛澶辫触'); + return; + } + loadAdminData(); + }, + error: function (xhr, response) { + window.alert((response && response.message) || '绂佺敤璐︽埛澶辫触'); + } + }); + }); + }); + + Array.prototype.slice.call(document.querySelectorAll('.enable-user-btn')).forEach(function (button) { + button.addEventListener('click', function () { + var id = button.getAttribute('data-id'); + appUtils.ajax({ + method: 'POST', + url: '/api/admin/users/' + id + '/enable', + success: function (response) { + if (!response.success) { + window.alert(response.message || '瑙i櫎绂佺敤澶辫触'); + return; + } + loadAdminData(); + }, + error: function (xhr, response) { + window.alert((response && response.message) || '瑙i櫎绂佺敤澶辫触'); } - - eventsView.innerHTML = renderEventTable(isMine ? state.myEvents : state.events, isMine); - bindRegisterButtons(); - bindPaginationButtons(type); + }); + }); + }); + + Array.prototype.slice.call(document.querySelectorAll('.delete-user-btn')).forEach(function (button) { + button.addEventListener('click', function () { + var id = button.getAttribute('data-id'); + if (!window.confirm('纭畾瑕佸垹闄よ繖涓处鍙峰悧锛?)) { + return; } + appUtils.ajax({ + method: 'DELETE', + url: '/api/admin/users/' + id, + success: function (response) { + if (!response.success) { + window.alert(response.message || '鍒犻櫎鐢ㄦ埛澶辫触'); + return; + } + loadAdminData(); + }, + error: function (xhr, response) { + window.alert((response && response.message) || '鍒犻櫎鐢ㄦ埛澶辫触'); + } + }); }); }); } function renderCurrentView() { - profileView.classList.toggle('hidden', state.currentView !== 'profile'); - eventsView.classList.toggle('hidden', state.currentView !== 'events'); - adminView.classList.toggle('hidden', state.currentView !== 'admin'); - registrationsView.classList.toggle('hidden', state.currentView !== 'registrations'); + var currentMenu = getMenus().find(function (item) { + return item.key === state.currentView; + }); + + if (currentMenu) { + sectionTitle.textContent = currentMenu.label; + sectionDesc.textContent = currentMenu.desc; + } + + renderTabs(); if (state.currentView === 'profile') { - sectionTitle.textContent = '个人信息'; - sectionDesc.textContent = '查看并维护当前登录人员的基础资料。'; - renderTabs(); renderProfile(); return; } if (state.currentView === 'events') { - sectionTitle.textContent = '运动会报名'; - sectionDesc.textContent = '浏览所有项目并完成报名,也可以查看自己的报名信息。'; - renderTabs(); - eventsView.innerHTML = renderEventTable(state.currentTab === 'mine' ? state.myEvents : state.events, state.currentTab === 'mine'); - bindRegisterButtons(); - bindPaginationButtons(state.currentTab === 'mine' ? 'mine' : 'all'); + renderEventTable(state.currentTab === 'mine' ? state.myEvents : state.events, state.currentTab === 'mine'); + return; + } + + if (state.currentView === 'user-manage') { + renderUserManage(); + return; + } + + if (state.currentView === 'athlete-manage') { + renderAthleteManage(); return; } - if (state.currentView === 'admin') { - sectionTitle.textContent = '管理员后台'; - sectionDesc.textContent = '查看系统内所有用户资料。'; - renderTabs(); - renderAdminContent(); + if (state.currentView === 'admin-home') { + renderPlaceholder('杩愬姩浼氱鐞?, '杩欓噷灏嗕綔涓虹鐞嗗憳鍚庡彴棣栭〉锛屽彲灞曠ず鎶ュ悕鎬昏銆佺郴缁熷叕鍛娿€佽繍鍔ㄤ細绠$悊鍏ュ彛绛夊唴瀹广€?); return; } - if (state.currentView === 'registrations') { - sectionTitle.textContent = '报名总览'; - sectionDesc.textContent = '查看所有用户的报名记录。'; - subTabs.classList.add('hidden'); - var totalPages = getTotalPages(state.adminRegistrations); - registrationsView.innerHTML = '' - + '
' - + '
报名记录总数

' + state.adminRegistrations.length + '

' - + '
已报名状态

' + state.adminRegistrations.filter(function (item) { return item.status === "已报名"; }).length + '

' - + '
覆盖项目数

' + uniqueEventCount() + '

' - + '
' - + renderRegistrationTable() - + renderPagination(totalPages, state.registrationsPage, 'registrations'); - bindPaginationButtons('registrations'); + if (state.currentView === 'team-info') { + renderPlaceholder('鍥綋淇℃伅绠$悊', '杩欓噷灏嗙户缁ˉ鍏呭闄€侀儴闂ㄣ€佷唬琛ㄩ槦绛夊洟浣撲俊鎭鐞嗗姛鑳姐€?); return; } + + if (state.currentView === 'event-manage') { + renderEventManage(); + return; + } + + if (state.currentView === 'score-manage') { + renderPlaceholder('鍙傝禌鎴愮哗绠$悊', '杩欓噷灏嗙户缁ˉ鍏呮垚缁╁綍鍏ャ€佹垚缁╃淮鎶ゃ€佹垚缁╂煡璇㈢瓑鍔熻兘銆?); + return; + } + + if (state.currentView === 'record-manage') { + renderPlaceholder('椤圭洰璁板綍绠$悊', '杩欓噷灏嗙户缁ˉ鍏呴」鐩褰曘€佽禌浜嬬З搴忓唽鍜岄」鐩。妗堢鐞嗗姛鑳姐€?); + return; + } + + if (state.currentView === 'system-manage') { + renderPlaceholder('绯荤粺绠$悊', '杩欓噷灏嗙户缁ˉ鍏呯郴缁熼厤缃€佽处鍙锋潈闄愬拰杩愯缁存姢鍔熻兘銆?); + } + } + + function switchView(view) { + state.currentView = view; + if (view === 'events' && state.currentTab !== 'mine') { + state.currentTab = 'all'; + } + renderSidebar(); + renderCurrentView(); } function loadEventData() { @@ -487,6 +586,7 @@ document.addEventListener('DOMContentLoaded', function () { } } }); + appUtils.ajax({ method: 'GET', url: '/api/events/my', @@ -503,6 +603,7 @@ document.addEventListener('DOMContentLoaded', function () { if (!state.user || state.user.role !== 'ADMIN') { return; } + appUtils.ajax({ method: 'GET', url: '/api/admin/users', @@ -513,6 +614,7 @@ document.addEventListener('DOMContentLoaded', function () { } } }); + appUtils.ajax({ method: 'GET', url: '/api/admin/registrations', @@ -523,17 +625,97 @@ document.addEventListener('DOMContentLoaded', function () { } } }); + + appUtils.ajax({ + method: 'GET', + url: '/api/admin/events', + success: function (response) { + if (response.success) { + state.adminEvents = response.data || []; + renderCurrentView(); + } + } + }); } - function switchView(view) { - state.currentView = view; - if (view === 'events') { - state.currentTab = state.currentTab === 'mine' ? 'mine' : 'all'; + function bindEventManageActions() { + var form = document.getElementById('eventForm'); + var resetButton = document.getElementById('resetEventForm'); + var messageEl = document.getElementById('eventFormMessage'); + + if (form) { + form.addEventListener('submit', function (event) { + event.preventDefault(); + var formData = new FormData(form); + var payload = { + eventName: String(formData.get('eventName') || '').trim(), + eventCategory: String(formData.get('eventCategory') || '').trim(), + location: String(formData.get('location') || '').trim(), + quota: Number(formData.get('quota') || 0), + description: String(formData.get('description') || '').trim(), + eventTime: String(formData.get('eventTime') || '').trim() + }; + var successText = state.editingEventId ? '椤圭洰淇敼鎴愬姛' : '椤圭洰鏂板鎴愬姛'; + + appUtils.ajax({ + method: state.editingEventId ? 'PUT' : 'POST', + url: state.editingEventId ? '/api/admin/events/' + state.editingEventId : '/api/admin/events', + data: payload, + success: function (response) { + if (!response.success) { + appUtils.showMessage(messageEl, response.message || '淇濆瓨澶辫触', false); + return; + } + state.editingEventId = null; + window.alert(successText); + loadAdminData(); + }, + error: function (xhr, response) { + appUtils.showMessage(messageEl, (response && response.message) || '淇濆瓨澶辫触', false); + } + }); + }); } - navItems.forEach(function (item) { - item.classList.toggle('active', item.getAttribute('data-view') === view); + + if (resetButton) { + resetButton.addEventListener('click', function () { + state.editingEventId = null; + renderCurrentView(); + }); + } + + Array.prototype.slice.call(document.querySelectorAll('.edit-event-btn')).forEach(function (button) { + button.addEventListener('click', function () { + state.editingEventId = Number(button.getAttribute('data-id')); + renderCurrentView(); + }); + }); + + Array.prototype.slice.call(document.querySelectorAll('.delete-event-btn')).forEach(function (button) { + button.addEventListener('click', function () { + var eventId = button.getAttribute('data-id'); + if (!window.confirm('纭畾瑕佸垹闄よ繖涓」鐩悧锛熷垹闄ゅ悗璇ラ」鐩殑鎶ュ悕璁板綍涔熶細涓€骞舵竻闄ゃ€?)) { + return; + } + appUtils.ajax({ + method: 'DELETE', + url: '/api/admin/events/' + eventId, + success: function (response) { + if (!response.success) { + window.alert(response.message || '鍒犻櫎澶辫触'); + return; + } + if (state.editingEventId === Number(eventId)) { + state.editingEventId = null; + } + loadAdminData(); + }, + error: function (xhr, response) { + window.alert((response && response.message) || '鍒犻櫎澶辫触'); + } + }); + }); }); - renderCurrentView(); } function loadCurrentUser() { @@ -545,18 +727,13 @@ document.addEventListener('DOMContentLoaded', function () { window.location.href = './login.html'; return; } + state.user = response.data; - currentUserName.textContent = state.user.name + (state.user.role === 'ADMIN' ? ' 管理员' : ' 同学'); - if (state.user.role === 'ADMIN') { - adminNavBtn.classList.remove('hidden'); - registrationsNavBtn.classList.remove('hidden'); - // 隐藏个人信息和运动会报名菜单 - document.querySelector('[data-view="profile"]').classList.add('hidden'); - document.querySelector('[data-view="events"]').classList.add('hidden'); - // 自动切换到管理员后台视图 - switchView('admin'); - } - renderProfile(); + currentUserName.textContent = state.user.name + (state.user.role === 'ADMIN' ? ' 绠$悊鍛? : ' 鐢ㄦ埛'); + state.currentView = state.user.role === 'ADMIN' ? 'admin-home' : 'profile'; + + renderSidebar(); + renderCurrentView(); loadEventData(); loadAdminData(); }, @@ -566,12 +743,6 @@ document.addEventListener('DOMContentLoaded', function () { }); } - navItems.forEach(function (item) { - item.addEventListener('click', function () { - switchView(item.getAttribute('data-view')); - }); - }); - logoutBtn.addEventListener('click', function () { appUtils.ajax({ method: 'POST', @@ -586,5 +757,4 @@ document.addEventListener('DOMContentLoaded', function () { }); loadCurrentUser(); - switchView('profile'); }); diff --git a/assets/js/register.js b/assets/js/register.js index 71ea933..a1646ed 100644 --- a/assets/js/register.js +++ b/assets/js/register.js @@ -25,6 +25,8 @@ document.addEventListener('DOMContentLoaded', function () { phone: String(formData.get('phone') || '').trim(), gender: String(formData.get('gender') || ''), college: String(formData.get('college') || '').trim(), + className: String(formData.get('className') || '').trim(), + studentNo: String(formData.get('studentNo') || '').trim(), category: String(formData.get('category') || '') }, success: function (response) { diff --git a/register.html b/register.html index 1ea119d..b930506 100644 --- a/register.html +++ b/register.html @@ -1,13 +1,11 @@ - 运动会报名系统 - 注册 -
@@ -72,6 +70,14 @@ + +