Files
student_manger/server/api/stats/index.get.ts
寒寒 05c33b1fe8 feat: initial commit with Nuxt 3 student management system
- Add Nuxt 3 + Prisma + SQLite full-stack setup
- Add student CRUD API with batch import/export
- Add stats dashboard with gender/class distribution
- Add target community settings feature
- Add Docker deployment support (Dockerfile + docker-compose)
- Add README with development and deployment instructions
2026-03-21 02:00:55 +08:00

88 lines
2.8 KiB
TypeScript

import { prisma, defaultCommunities } from '~/server/utils/prisma'
export default defineEventHandler(async (event) => {
const students = await prisma.student.findMany()
// 获取设置的目标小区
const settings = await prisma.settings.findMany({
where: { key: 'targetCommunities' }
})
const targetCommunities = settings.length > 0
? JSON.parse(settings[0].value)
: defaultCommunities
// 基础统计
const total = students.length
const genderStats = {
male: students.filter(s => s.gender === '男').length,
female: students.filter(s => s.gender === '女').length
}
// 班级统计
const classStats: Record<string, { count: number; male: number; female: number }> = {}
students.forEach(s => {
if (!classStats[s.className]) {
classStats[s.className] = { count: 0, male: 0, female: 0 }
}
classStats[s.className].count++
if (s.gender === '男') classStats[s.className].male++
else if (s.gender === '女') classStats[s.className].female++
})
// 年龄段统计
const currentYear = new Date().getFullYear()
const ageGroups = {
'3岁以下': 0,
'3-4岁': 0,
'4-5岁': 0,
'5-6岁': 0,
'6岁以上': 0
}
students.forEach(s => {
if (!s.birthday) return
const birthYear = parseInt(s.birthday.substring(0, 4))
if (isNaN(birthYear)) return
const age = currentYear - birthYear
if (age < 3) ageGroups['3岁以下']++
else if (age < 4) ageGroups['3-4岁']++
else if (age < 5) ageGroups['4-5岁']++
else if (age <= 6) ageGroups['5-6岁']++
else ageGroups['6岁以上']++
})
// 目标小区统计
const addressStats: Record<string, { count: number; male: number; female: number }> = {}
targetCommunities.forEach(name => {
addressStats[name] = { count: 0, male: 0, female: 0 }
})
students.forEach(s => {
if (!s.address) return
targetCommunities.forEach(community => {
if (s.address.includes(community)) {
addressStats[community].count++
if (s.gender === '男') addressStats[community].male++
else if (s.gender === '女') addressStats[community].female++
}
})
})
const filteredAddressStats = Object.entries(addressStats)
.filter(([_, v]) => v.count > 0)
.map(([name, v]) => ({ name, ...v }))
.sort((a, b) => b.count - a.count)
const targetCommunityTotal = filteredAddressStats.reduce((sum, s) => sum + s.count, 0)
return {
total,
genderStats,
classStats: Object.entries(classStats).map(([name, v]) => ({ name, ...v })),
ageGroups,
targetCommunities,
addressStats: filteredAddressStats,
targetCommunityTotal,
targetCommunityMale: filteredAddressStats.reduce((sum, s) => sum + s.male, 0),
targetCommunityFemale: filteredAddressStats.reduce((sum, s) => sum + s.female, 0)
}
})