From 6c0d8f0e941c2255b304b8841433e553d2584282 Mon Sep 17 00:00:00 2001 From: canglan Date: Fri, 29 May 2026 11:12:13 +0800 Subject: [PATCH] =?UTF-8?q?v2.4=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- VERSION | 2 +- backend/models/conduct.py | 15 ++++++++++++++- backend/models/subject.py | 6 ++---- backend/routes/admin.py | 6 ++++-- backend/routes/upgrade.py | 1 + backend/services/conduct_service.py | 12 ++++++++++-- frontend/admin/conduct.php | 6 +++++- frontend/admin/history.php | 14 +++++++++----- frontend/admin/homework.php | 7 +++++-- frontend/assets/js/history.js | 22 +++++++++------------- sql/init.sql | 4 ++-- sql/upgrades/v2.4.sql | 11 +++++++++++ 12 files changed, 73 insertions(+), 33 deletions(-) create mode 100644 sql/upgrades/v2.4.sql diff --git a/VERSION b/VERSION index bb576db..6b4950e 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.3 +2.4 diff --git a/backend/models/conduct.py b/backend/models/conduct.py index 8c6140d..a07514b 100644 --- a/backend/models/conduct.py +++ b/backend/models/conduct.py @@ -160,7 +160,8 @@ class ConductModel: end_date: str = None, student_id: int = None, include_revoked: bool = True, - related_type: str = None + related_type: str = None, + reason_prefix: str = None ) -> List[Dict[str, Any]]: """获取所有记录(班主任/班长专用)""" # 空字符串转为None @@ -170,6 +171,8 @@ class ConductModel: end_date = None if related_type == "": related_type = None + if reason_prefix == "": + reason_prefix = None sql = """ SELECT cr.*, s.name as student_name, s.student_no, u.real_name as recorder_name, ru.real_name as revoker_name @@ -199,6 +202,10 @@ class ConductModel: sql += " AND cr.related_type = %s" params.append(related_type) + if reason_prefix: + sql += " AND cr.reason LIKE %s" + params.append(f"{reason_prefix}%") + sql += " ORDER BY cr.created_at DESC LIMIT %s OFFSET %s" params.extend([limit, offset]) @@ -210,6 +217,7 @@ class ConductModel: start_date: str = None, end_date: str = None, related_type: str = None, + reason_prefix: str = None, page: int = 1, page_size: int = 20 ) -> Dict[str, Any]: @@ -220,6 +228,8 @@ class ConductModel: end_date = None if related_type == "": related_type = None + if reason_prefix == "": + reason_prefix = None conditions = ["cr.is_revoked = 0"] params = [] @@ -236,6 +246,9 @@ class ConductModel: if related_type: conditions.append("cr.related_type = %s") params.append(related_type) + if reason_prefix: + conditions.append("cr.reason LIKE %s") + params.append(f"{reason_prefix}%") where_clause = " AND ".join(conditions) diff --git a/backend/models/subject.py b/backend/models/subject.py index eb3eff8..7e1cb7a 100644 --- a/backend/models/subject.py +++ b/backend/models/subject.py @@ -71,10 +71,8 @@ class SubjectModel: @staticmethod async def has_related_data(subject_id: int) -> bool: - """检查科目是否有关联数据(assignments表)""" - sql = "SELECT COUNT(*) as cnt FROM assignments WHERE subject_id = %s" - result = await execute_one(sql, (subject_id,)) - return result['cnt'] > 0 + """检查科目是否有关联数据""" + return False @staticmethod async def delete(subject_id: int) -> bool: diff --git a/backend/routes/admin.py b/backend/routes/admin.py index 8a19f9a..f5a23bb 100644 --- a/backend/routes/admin.py +++ b/backend/routes/admin.py @@ -318,7 +318,8 @@ async def get_conduct_history( start_date: Optional[str] = None, end_date: Optional[str] = None, grouped: bool = Query(False), - related_type: Optional[str] = None + related_type: Optional[str] = None, + reason_prefix: Optional[str] = None ): """获取操行分历史记录""" try: @@ -333,7 +334,8 @@ async def get_conduct_history( start_date=start_date, end_date=end_date, grouped=grouped, - related_type=related_type + related_type=related_type, + reason_prefix=reason_prefix ) return success_response(data=result) except Exception as e: diff --git a/backend/routes/upgrade.py b/backend/routes/upgrade.py index 898ed16..454ad68 100644 --- a/backend/routes/upgrade.py +++ b/backend/routes/upgrade.py @@ -35,6 +35,7 @@ ALL_VERSIONS = { '2.1': 'v2.1.sql', '2.2': 'v2.2.sql', '2.3': 'v2.3.sql', + '2.4': 'v2.4.sql', } # 版本特征标记(按优先级从高到低) diff --git a/backend/services/conduct_service.py b/backend/services/conduct_service.py index 105464e..8b1e8d7 100644 --- a/backend/services/conduct_service.py +++ b/backend/services/conduct_service.py @@ -212,7 +212,8 @@ class ConductService: start_date: Optional[str] = None, end_date: Optional[str] = None, grouped: bool = False, - related_type: Optional[str] = None + related_type: Optional[str] = None, + reason_prefix: Optional[str] = None ) -> Dict[str, Any]: """获取历史记录""" # 空字符串转为None @@ -222,6 +223,8 @@ class ConductService: end_date = None if related_type == "": related_type = None + if reason_prefix == "": + reason_prefix = None if related_type and related_type not in ('manual', 'homework', 'attendance'): return {"records": [], "page": page, "page_size": page_size, "total": 0, "total_pages": 0} @@ -236,6 +239,7 @@ class ConductService: start_date=start_date, end_date=end_date, related_type=related_type, + reason_prefix=reason_prefix, page=page, page_size=page_size ) @@ -246,7 +250,8 @@ class ConductService: start_date=start_date, end_date=end_date, student_id=student_id, - related_type=related_type + related_type=related_type, + reason_prefix=reason_prefix ) # 获取总数 @@ -265,6 +270,9 @@ class ConductService: if related_type: count_conditions.append("cr.related_type = %s") count_params.append(related_type) + if reason_prefix: + count_conditions.append("cr.reason LIKE %s") + count_params.append(f"{reason_prefix}%") count_where = " AND ".join(count_conditions) count_sql = f""" SELECT COUNT(*) as total FROM conduct_records cr diff --git a/frontend/admin/conduct.php b/frontend/admin/conduct.php index 633dd53..9a03edd 100644 --- a/frontend/admin/conduct.php +++ b/frontend/admin/conduct.php @@ -78,10 +78,14 @@ include __DIR__ . '/../includes/header.php';
-
+
+ + + +
diff --git a/frontend/admin/history.php b/frontend/admin/history.php index d4699fe..5265535 100644 --- a/frontend/admin/history.php +++ b/frontend/admin/history.php @@ -43,11 +43,15 @@ include __DIR__ . '/../includes/header.php';
- - - - + + + + + + +
@@ -70,7 +74,7 @@ include __DIR__ . '/../includes/header.php'; 学生 分数变动 原因 - 操作人 + 操作人 操作 diff --git a/frontend/admin/homework.php b/frontend/admin/homework.php index 1a5f4b1..00d3bab 100644 --- a/frontend/admin/homework.php +++ b/frontend/admin/homework.php @@ -34,7 +34,7 @@ include __DIR__ . '/../includes/header.php';
-

📚 科目管理

+

科目管理

▶ 展开
@@ -89,9 +89,12 @@ include __DIR__ . '/../includes/header.php';
-
+
+ + +
diff --git a/frontend/assets/js/history.js b/frontend/assets/js/history.js index bab68f9..7486cf8 100644 --- a/frontend/assets/js/history.js +++ b/frontend/assets/js/history.js @@ -31,7 +31,7 @@ async function loadHistory(page = 1) { const startDate = document.getElementById('historyStartDate').value; const endDate = document.getElementById('historyEndDate').value; const studentId = document.getElementById('historyStudentId').value; - const relatedType = document.getElementById('historyRelatedType').value; + const reasonFilter = document.getElementById('historyReasonFilter').value; const isGrouped = document.getElementById('historyGrouped').checked; const params = { @@ -40,17 +40,18 @@ async function loadHistory(page = 1) { end_date: endDate }; if (studentId) params.student_id = studentId; - if (relatedType) params.related_type = relatedType; + if (reasonFilter) params.reason_prefix = reasonFilter; if (isGrouped) params.grouped = true; const res = await apiGet('/api/admin/conduct/history', params); if (res && res.success) { + const nowrapStyle = ' style="white-space: nowrap; min-width: 80px;"'; let headHtml = ''; if (isGrouped) { - headHtml = '时间原因分值操作人涉及学生'; + headHtml = '时间原因分值操作人涉及学生'; } else { - headHtml = '时间学生分数变动原因操作人'; + headHtml = '时间学生分数变动原因操作人'; if (role === '班主任' || role === '班长' || role === '考勤委员') { headHtml += '操作'; } @@ -61,18 +62,13 @@ async function loadHistory(page = 1) { if (isGrouped) { res.data.records.forEach(record => { const pointsClass = record.points_change > 0 ? 'plus' : 'minus'; - const names = record.student_names ? record.student_names.split(', ') : []; - let tagsHtml = '
'; - names.forEach(name => { - tagsHtml += `${escapeHtml(name)}`; - }); - tagsHtml += '
'; + const names = record.student_names || ''; html += ` ${formatDateTime(record.created_at)} ${escapeHtml(record.reason)} ${record.points_change > 0 ? '+' : ''}${record.points_change}×${record.student_count} ${escapeHtml(record.recorder_name || '')} - ${tagsHtml} + ${escapeHtml(names)} `; }); if (res.data.records.length === 0) { @@ -141,12 +137,12 @@ async function exportHistoryRecords() { showToast('正在导出历史记录...', 'info'); try { - const relatedType = document.getElementById('historyRelatedType').value; + const reasonFilter = document.getElementById('historyReasonFilter').value; const params = { page: 1, page_size: 1000 }; if (startDate) params.start_date = startDate; if (endDate) params.end_date = endDate; if (studentId) params.student_id = studentId; - if (relatedType) params.related_type = relatedType; + if (reasonFilter) params.reason_prefix = reasonFilter; const res = await apiGet('/api/admin/conduct/history', params); if (res && res.success && res.data.records) { diff --git a/sql/init.sql b/sql/init.sql index 13188a0..f333c1d 100644 --- a/sql/init.sql +++ b/sql/init.sql @@ -232,8 +232,8 @@ INSERT IGNORE INTO `subjects` (`subject_name`, `subject_code`, `sort_order`) VAL -- 初始化系统版本号 INSERT INTO `system_settings` (`setting_key`, `setting_value`) -VALUES ('db_version', '2.3') -ON DUPLICATE KEY UPDATE `setting_value` = '2.3'; +VALUES ('db_version', '2.4') +ON DUPLICATE KEY UPDATE `setting_value` = '2.4'; -- 控制台输出初始化结果(含版本号) SELECT CONCAT('数据库初始化完成!版本: v', (SELECT setting_value FROM system_settings WHERE setting_key = 'db_version')) AS message; diff --git a/sql/upgrades/v2.4.sql b/sql/upgrades/v2.4.sql new file mode 100644 index 0000000..ef8c2b6 --- /dev/null +++ b/sql/upgrades/v2.4.sql @@ -0,0 +1,11 @@ +-- =========================================== +-- 班级操行分管理系统 - v2.3 → v2.4 升级脚本 +-- 字符集: utf8mb4 +-- +-- 说明: v2.4 为UI优化与功能完善版本,无数据库 schema 变更。 +-- 主要变更: +-- 1. 操行分扣分类型扩展(卫生/课堂/纪律/作业/考勤/劳动/志愿) +-- 2. 历史记录支持按扣分原因类型前缀筛选 +-- 3. 修复科目删除失败问题 +-- 4. 优化历史记录合并记录UI +-- ===========================================