From 70ee94f39e0fd55eb282d816f197b0ee83b469de Mon Sep 17 00:00:00 2001 From: zhoulexin Date: Fri, 12 Jun 2026 17:25:41 +0800 Subject: [PATCH] =?UTF-8?q?fix:=E8=80=83=E5=8B=A4=E7=AE=A1=E7=90=86?= =?UTF-8?q?=E8=B0=83=E6=95=B4=E3=80=81=E5=AD=A6=E7=94=9F=E4=BF=A1=E6=81=AF?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E4=BA=BA=E8=84=B8=E5=BD=95=E5=85=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package-lock.json | 106 ++++++++- package.json | 3 +- src/api/attendance.js | 7 +- src/api/dashboard.js | 4 +- src/assets/avatar.png | Bin 0 -> 20772 bytes src/styles/variables.scss | 2 +- src/utils/fileHttp.js | 2 + src/utils/request.js | 4 + src/views/behavior/index.vue | 2 +- .../dashboard/components/AttendanceDetail.vue | 204 ++++++++++++++---- .../dashboard/components/AttendanceManage.vue | 36 +++- .../dashboard/components/ClassRanking.vue | 48 ++++- src/views/dashboard/index.vue | 10 +- .../info/components/ClassCourseDialog.vue | 10 +- src/views/info/student.vue | 185 ++++++++++++++-- 15 files changed, 534 insertions(+), 89 deletions(-) create mode 100644 src/assets/avatar.png create mode 100644 src/utils/fileHttp.js diff --git a/package-lock.json b/package-lock.json index 1839c25..36edace 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,7 +15,8 @@ "pinia": "^2.1.7", "pinia-plugin-persistedstate": "^3.2.3", "vue": "^3.4.21", - "vue-router": "^4.3.0" + "vue-router": "^4.3.0", + "xlsx": "^0.18.5" }, "devDependencies": { "@vitejs/plugin-vue": "^5.0.4", @@ -1367,6 +1368,15 @@ "vue": "^3.5.0" } }, + "node_modules/adler-32": { + "version": "1.3.1", + "resolved": "https://registry.npmmirror.com/adler-32/-/adler-32-1.3.1.tgz", + "integrity": "sha512-ynZ4w/nUUv5rrsR8UUGoe1VC9hZj6V5hU9Qw1HlMDJGEJw5S7TfTErWTjMys6M7vr0YWcPqs3qAr4ss0nDfP+A==", + "license": "Apache-2.0", + "engines": { + "node": ">=0.8" + } + }, "node_modules/agent-base": { "version": "6.0.2", "resolved": "https://registry.npmmirror.com/agent-base/-/agent-base-6.0.2.tgz", @@ -1416,6 +1426,19 @@ "node": ">= 0.4" } }, + "node_modules/cfb": { + "version": "1.2.2", + "resolved": "https://registry.npmmirror.com/cfb/-/cfb-1.2.2.tgz", + "integrity": "sha512-KfdUZsSOw19/ObEWasvBP/Ac4reZvAGauZhs6S/gqNhXhI7cKwvlH7ulj+dOEYnca4bm4SGo8C1bTAQvnTjgQA==", + "license": "Apache-2.0", + "dependencies": { + "adler-32": "~1.3.0", + "crc-32": "~1.2.0" + }, + "engines": { + "node": ">=0.8" + } + }, "node_modules/chokidar": { "version": "5.0.0", "resolved": "https://registry.npmmirror.com/chokidar/-/chokidar-5.0.0.tgz", @@ -1432,6 +1455,15 @@ "url": "https://paulmillr.com/funding/" } }, + "node_modules/codepage": { + "version": "1.15.0", + "resolved": "https://registry.npmmirror.com/codepage/-/codepage-1.15.0.tgz", + "integrity": "sha512-3g6NUTPd/YtuuGrhMnOMRjFc+LJw/bnMp3+0r/Wcz3IXUuCosKRJvMphm5+Q+bvTVGcJJuRvVLuYba+WojaFaA==", + "license": "Apache-2.0", + "engines": { + "node": ">=0.8" + } + }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmmirror.com/combined-stream/-/combined-stream-1.0.8.tgz", @@ -1444,6 +1476,18 @@ "node": ">= 0.8" } }, + "node_modules/crc-32": { + "version": "1.2.2", + "resolved": "https://registry.npmmirror.com/crc-32/-/crc-32-1.2.2.tgz", + "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", + "license": "Apache-2.0", + "bin": { + "crc32": "bin/crc32.njs" + }, + "engines": { + "node": ">=0.8" + } + }, "node_modules/csstype": { "version": "3.2.3", "resolved": "https://registry.npmmirror.com/csstype/-/csstype-3.2.3.tgz", @@ -1681,6 +1725,15 @@ "node": ">= 6" } }, + "node_modules/frac": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/frac/-/frac-1.1.2.tgz", + "integrity": "sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA==", + "license": "Apache-2.0", + "engines": { + "node": ">=0.8" + } + }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.3.tgz", @@ -2125,6 +2178,18 @@ "node": ">=0.10.0" } }, + "node_modules/ssf": { + "version": "0.11.2", + "resolved": "https://registry.npmmirror.com/ssf/-/ssf-0.11.2.tgz", + "integrity": "sha512-+idbmIXoYET47hH+d7dfm2epdOMUDjqcB4648sTZ+t2JwoyBFL/insLfB/racrDmsKB3diwsDA696pZMieAC5g==", + "license": "Apache-2.0", + "dependencies": { + "frac": "~1.1.2" + }, + "engines": { + "node": ">=0.8" + } + }, "node_modules/tslib": { "version": "2.3.0", "resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.3.0.tgz", @@ -2261,6 +2326,45 @@ "vue": "^3.5.0" } }, + "node_modules/wmf": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/wmf/-/wmf-1.0.2.tgz", + "integrity": "sha512-/p9K7bEh0Dj6WbXg4JG0xvLQmIadrner1bi45VMJTfnbVHsc7yIajZyoSoK60/dtVBs12Fm6WkUI5/3WAVsNMw==", + "license": "Apache-2.0", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/word": { + "version": "0.3.0", + "resolved": "https://registry.npmmirror.com/word/-/word-0.3.0.tgz", + "integrity": "sha512-OELeY0Q61OXpdUfTp+oweA/vtLVg5VDOXh+3he3PNzLGG/y0oylSOC1xRVj0+l4vQ3tj/bB1HVHv1ocXkQceFA==", + "license": "Apache-2.0", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/xlsx": { + "version": "0.18.5", + "resolved": "https://registry.npmmirror.com/xlsx/-/xlsx-0.18.5.tgz", + "integrity": "sha512-dmg3LCjBPHZnQp5/F/+nnTa+miPJxUXB6vtk42YjBBKayDNagxGEeIdWApkYPOf3Z3pm3k62Knjzp7lMeTEtFQ==", + "license": "Apache-2.0", + "dependencies": { + "adler-32": "~1.3.0", + "cfb": "~1.2.1", + "codepage": "~1.15.0", + "crc-32": "~1.2.1", + "ssf": "~0.11.2", + "wmf": "~1.0.1", + "word": "~0.3.0" + }, + "bin": { + "xlsx": "bin/xlsx.njs" + }, + "engines": { + "node": ">=0.8" + } + }, "node_modules/zrender": { "version": "5.6.1", "resolved": "https://registry.npmmirror.com/zrender/-/zrender-5.6.1.tgz", diff --git a/package.json b/package.json index 2d8cd1f..7a69564 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,8 @@ "pinia": "^2.1.7", "pinia-plugin-persistedstate": "^3.2.3", "vue": "^3.4.21", - "vue-router": "^4.3.0" + "vue-router": "^4.3.0", + "xlsx": "^0.18.5" }, "devDependencies": { "@vitejs/plugin-vue": "^5.0.4", diff --git a/src/api/attendance.js b/src/api/attendance.js index 719ccb7..56bbdfb 100644 --- a/src/api/attendance.js +++ b/src/api/attendance.js @@ -2,5 +2,10 @@ import request from '@/utils/request' /** 分页查询考勤记录 */ export const getRecordPage = (params) => { - return request.get('/attendance/record/page', { params }) + return request.get('/attendance/task/page', { params }) +} + +/** 分页查询考勤详情 */ +export const getDetailPage = (params) => { + return request.get('/attendance/detail/page', { params }) } diff --git a/src/api/dashboard.js b/src/api/dashboard.js index 908e50a..6ecb8e4 100644 --- a/src/api/dashboard.js +++ b/src/api/dashboard.js @@ -11,6 +11,6 @@ export const getTrend = () => { } /** 获取各班级出勤率排名 */ -export const getRanking = () => { - return request.get('/dashboard/ranking') +export const getRanking = (params) => { + return request.get('/dashboard/ranking', { params }) } diff --git a/src/assets/avatar.png b/src/assets/avatar.png new file mode 100644 index 0000000000000000000000000000000000000000..0c3ff57b3094e34eaf91cf390105198e58de6082 GIT binary patch literal 20772 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 literal 0 HcmV?d00001 diff --git a/src/styles/variables.scss b/src/styles/variables.scss index 8a29544..32fcac1 100644 --- a/src/styles/variables.scss +++ b/src/styles/variables.scss @@ -58,7 +58,7 @@ $font-family-mono: 'SF Mono', 'Monaco', 'Consolas', 'Courier New', monospace; // 布局 $sidebar-width: 240px; $sidebar-collapsed-width: 64px; -$navbar-height: 56px; +$navbar-height: 90px; // 过渡 $transition-fast: 0.15s ease; diff --git a/src/utils/fileHttp.js b/src/utils/fileHttp.js new file mode 100644 index 0000000..4c302a4 --- /dev/null +++ b/src/utils/fileHttp.js @@ -0,0 +1,2 @@ +const fileHttp = 'https://shipllm.ngsk.tech:7001/storage' +export default fileHttp \ No newline at end of file diff --git a/src/utils/request.js b/src/utils/request.js index 5300531..86a4082 100644 --- a/src/utils/request.js +++ b/src/utils/request.js @@ -17,6 +17,10 @@ request.interceptors.request.use( if (store.token) { config.headers.Authorization = `Bearer ${store.token}` } + // FormData:让浏览器自动设置带 boundary 的 Content-Type + if (config.data instanceof FormData) { + delete config.headers['Content-Type'] + } return config }, (error) => Promise.reject(error) diff --git a/src/views/behavior/index.vue b/src/views/behavior/index.vue index c65831d..29dd77a 100644 --- a/src/views/behavior/index.vue +++ b/src/views/behavior/index.vue @@ -20,7 +20,7 @@

行为分布占比

- 今日 +
diff --git a/src/views/dashboard/components/AttendanceDetail.vue b/src/views/dashboard/components/AttendanceDetail.vue index 5994fc5..02e4bcc 100644 --- a/src/views/dashboard/components/AttendanceDetail.vue +++ b/src/views/dashboard/components/AttendanceDetail.vue @@ -3,7 +3,7 @@ :model-value="props.modelValue" @update:model-value="emit('update:modelValue', $event)" :title="`${props.detailData.courseName} - 考勤详情`" - width="720px" + width="1010px" destroy-on-close >
@@ -13,24 +13,52 @@
- - + + + + + - - - - + + + + + + + + + - - -
+
@@ -42,9 +70,9 @@ @@ -106,4 +211,11 @@ watch(detailTab, (val) => { font-size: 13px; color: #525252; } + +.search-bar { + display: flex; + gap: 12px; + align-items: center; + margin-bottom: 16px; +} diff --git a/src/views/dashboard/components/AttendanceManage.vue b/src/views/dashboard/components/AttendanceManage.vue index f38fee7..d6b5921 100644 --- a/src/views/dashboard/components/AttendanceManage.vue +++ b/src/views/dashboard/components/AttendanceManage.vue @@ -78,7 +78,7 @@ import { ref, reactive, computed, onMounted, watch } from 'vue' import { ElMessage } from 'element-plus' import { Search } from '@element-plus/icons-vue' -import { getRecordPage } from '@/api/attendance' +import { getRecordPage, getDetailPage } from '@/api/attendance' import { useNameMaps } from '@/composables/useNameMaps' defineEmits(['showDetail']) @@ -100,7 +100,8 @@ const mapRecord = (item) => ({ total: item.totalCount, actual: item.actualCount, absentCount: item.absentCount, - absentRate: item.absentRate ?? 0 + absentRate: item.absentRate ?? 0, + id: item.id }) const tableData = ref([]) @@ -160,7 +161,36 @@ const handleReset = () => { pagination.current = 1 fetchData() } -const handleExport = (row) => ElMessage.success(`正在导出 ${row.courseName} 考勤明细...`) +const handleExport = async () => { + try { + const res = await getDetailPage({ current: 1, size: 9999 }) + const list = res?.data?.records || [] + if (list.length === 0) { + ElMessage.warning('暂无考勤详情数据') + return + } + + const statusLabels = { 0: '未签到', 1: '正常', 2: '迟到', 3: '缺勤', 4: '早退', 5: '请假' } + const headers = ['学号', '姓名', '考勤日期', '签到时间', '签退时间', '人脸相似度', '考勤状态'] + const rows = list.map(r => [ + r.studentNo, r.studentName, r.attDate, r.checkInTime, r.checkOutTime, + r.faceSimilarity ? (r.faceSimilarity * 100).toFixed(1) + '%' : '', + statusLabels[r.attStatus] || '未知' + ]) + const csv = [headers, ...rows] + .map(r => r.map(c => `"${String(c ?? '').replace(/"/g, '""')}"`).join(',')) + .join('\n') + const blob = new Blob(['\uFEFF' + csv], { type: 'text/csv;charset=utf-8;' }) + const a = document.createElement('a') + a.href = URL.createObjectURL(blob) + a.download = `考勤明细_${new Date().toLocaleDateString()}.csv` + a.click() + URL.revokeObjectURL(a.href) + ElMessage.success(`已导出 ${list.length} 条记录`) + } catch { + ElMessage.error('导出失败') + } +} diff --git a/src/views/dashboard/index.vue b/src/views/dashboard/index.vue index 90b63b2..0215baa 100644 --- a/src/views/dashboard/index.vue +++ b/src/views/dashboard/index.vue @@ -55,6 +55,7 @@
+ - - - + @@ -149,7 +145,7 @@ const recentRecords = ref([]) const fetchRecentRecords = async () => { try { - const res = await getRecordPage({ current: 1, size: 10 }) + const res = await getRecordPage({ current: 1, size: 10, taskStatus: 2 }) const { records } = res.data if (Array.isArray(records)) { recentRecords.value = records.map(mapRecord) diff --git a/src/views/info/components/ClassCourseDialog.vue b/src/views/info/components/ClassCourseDialog.vue index f643294..83f1121 100644 --- a/src/views/info/components/ClassCourseDialog.vue +++ b/src/views/info/components/ClassCourseDialog.vue @@ -82,6 +82,9 @@ + + + @@ -109,6 +112,7 @@ {{ detailData.endSection }} {{ detailData.startWeek }} {{ detailData.endWeek }} + {{ detailData.firstClassTime }} {{ getBuildingName(detailData.classroomId) }} {{ getRoomName(detailData.classroomId) }} @@ -271,7 +275,8 @@ const addRules = { startSection: [{ required: true, message: '请输入开始节次', trigger: 'blur' }], endSection: [{ required: true, message: '请输入结束节次', trigger: 'blur' }], startWeek: [{ required: true, message: '请输入开始周', trigger: 'blur' }], - endWeek: [{ required: true, message: '请输入结束周', trigger: 'blur' }] + endWeek: [{ required: true, message: '请输入结束周', trigger: 'blur' }], + firstClassTime: [{ required: true, message: '请选择上课时间', trigger: 'change' }] } const defaultForm = () => ({ @@ -284,6 +289,7 @@ const defaultForm = () => ({ endSection: 2, startWeek: 1, endWeek: 16, + firstClassTime: '', semester: '', status: 1 }) @@ -315,6 +321,7 @@ const showEditDialog = (row) => { endSection: row.endSection, startWeek: row.startWeek, endWeek: row.endWeek, + firstClassTime: row.firstClassTime || '', semester: row.semester || '', status: row.status } @@ -339,6 +346,7 @@ const saveSchedule = async () => { endSection: addForm.value.endSection, startWeek: addForm.value.startWeek, endWeek: addForm.value.endWeek, + firstClassTime: addForm.value.firstClassTime, semester: addForm.value.semester, status: addForm.value.status } diff --git a/src/views/info/student.vue b/src/views/info/student.vue index 3b711e6..d18b017 100644 --- a/src/views/info/student.vue +++ b/src/views/info/student.vue @@ -2,7 +2,7 @@
@@ -20,6 +20,13 @@
+ + + @@ -56,12 +63,18 @@
- - - + +
+
+ + {{ form.name?.charAt(0) }} + +
+ + - + @@ -70,7 +83,7 @@ - + @@ -84,18 +97,72 @@ 离校 - + + + + + + + + + + + + + + + +
+ +
+ +
+ + + +
+ +
+