赞
踩
作者主页:编程指南针
作者简介:Java领域优质创作者、CSDN博客专家 、CSDN内容合伙人、掘金特邀作者、阿里云博客专家、51CTO特邀作者、多年架构师设计经验、腾讯课堂常驻讲师
主要内容:Java项目、Python项目、前端项目、人工智能与大数据、简历模板、学习资料、面试题库、技术互助
收藏点赞不迷路 关注作者有好处
文末获取源码
项目编号:BS-QD-002
主要需求:
考虑到实用性,该系统需要拆分为两大子系统,一个是学生端系统,一个是后台管理端系统。学生端系统主要提供给学生使用,负责一些宿舍记录及个人信息记录的基本操作;后台管理模块则是主要负责对所有学生信息的整理,提供宿舍管理、楼层管理、数据查看等权限,提供给宿舍管理员使用的。
学生系统拥有以下功能:
管理系统拥有以下功能:
超级管理员在享有上述管理员同等权限的同时额外拥有如下功能:
前端:
后台(Nodejs):
数据库:
数据库设计一览:
下面展示一下系统的部分功能:
仪表盘概揽:选择不同的宿舍楼查看相关信息
管理员管理:
宿舍楼管理
楼层管理
宿舍信息
宿舍入住学生信息
查看学生起床记录
查看学生归宿信息
查看学生宿舍打扫信息
查看个人信息
学生注册
注册后登陆系统
入住宿舍
起床打卡
归宿记录
打扫记录
后端工程:
前端工程
部门核心代码:
- const { Building } = require("../model")
-
- module.exports = {
- getStudents: async function(buildingId) {
- const FloorController = require("./floor_controller")
- let users = []
- const building = await Building.findOne({ where: { id: buildingId } })
- const floors = await building.getFloors()
- for (let floor of floors) {
- const floorId = floor.id
- users = [...users, ...(await FloorController.getStudents(floorId))]
- }
- return users
- },
- delBuilding: async function(id) {
- const { setStudentRoomNull } = require("./user_controller")
- const students = await this.getStudents(id)
- students.forEach(student => {
- setStudentRoomNull(student.id)
- })
- return await Building.destroy({ where: { id } })
- }
- }
- const _ = require("lodash")
- const { User } = require("../model")
-
- module.exports = {
- async getEvaluatesInfo(evaluates) {
- const cpEvaluates = _.cloneDeep(evaluates)
- for (let evaluate of cpEvaluates) {
- const creator = await evaluate.getUser()
- evaluate.dataValues.userName = creator.name
- }
- return cpEvaluates
- }
- }
- const { Floor } = require("../model")
-
- module.exports = {
- getStudents: async function(floorId) {
- const { getStudentInfo } = require("./user_controller")
- let users = []
- const floor = await Floor.findOne({ where: { id: floorId } })
- const rooms = await floor.getRooms()
- for (let room of rooms) {
- const roomUsers = await room.getUsers()
- for (let user of roomUsers) {
- users.push(await getStudentInfo(user.id))
- }
- }
- return users
- }
- }
- module.exports = {
- UserController: require("./user_controller"),
- RoomController: require("./room_controller"),
- FloorController: require("./floor_controller"),
- BuildingController: require("./building_controller"),
- EvaluateController: require("./evaluate_controller"),
- RecordController: require("./record_controller")
- }
- const {
- User,
- GetupRecord,
- CleanRecord,
- BackRecord,
- Room,
- Floor,
- Building
- } = require("../model")
- const { Op } = require("sequelize")
- const moment = require("moment")
- const _ = require("lodash")
-
- const getupEarlyPoint = 8
- const backEarlyPoint = 22
-
- module.exports = {
- // getup 相关
- async addGetupRecord(userId) {
- const user = await User.findOne({ where: { id: userId } })
- const todyRecord = await GetupRecord.findOne({
- where: {
- userId: user.id,
- roomId: user.roomId,
- createdAt: {
- [Op.gt]: moment()
- .startOf("day")
- .toDate(),
- [Op.lt]: moment()
- .endOf("day")
- .toDate()
- }
- }
- })
- if (todyRecord) {
- throw new Error("当天已经有记录,记录失败!")
- }
- return await GetupRecord.create({ userId: user.id, roomId: user.roomId })
- },
- async getUserGetupRecords(userId, days, pure = false) {
- days = parseInt(days)
- const user = await User.findOne({ where: { id: userId } })
- const roomId = user.roomId
- const room = await Room.findOne({ where: { id: roomId } })
- // 获取最近 days 天的记录
- const startTime = moment()
- .subtract(days - 1 /* -1 代表查询天数包括今天 */, "days")
- .startOf("day")
- .toDate()
- const allRecords = []
- for (let i = 0; i < days; i++) {
- const todayStart = moment(startTime)
- .add(i, "days")
- .toDate()
- const todayEnd = moment(todayStart)
- .endOf("day")
- .toDate()
- let record = await GetupRecord.findOne({
- where: {
- userId,
- roomId,
- createdAt: {
- [Op.gt]: todayStart,
- [Op.lt]: todayEnd
- }
- },
- attributes: { exclude: ["updatedAt", "deletedAt"] }
- })
- if (record) {
- // 如果当天有记录就推入结果
- record = record.toJSON()
- record.time = moment(record.createdAt).format("HH:mm")
- } else if (!record && !pure) {
- // 如果获取的是全部数据且当前天无数据
- // 就建立一条空记录
- record = GetupRecord.build({
- id: "fake" + i,
- roomId,
- userId,
- createdAt: todayStart
- }).toJSON()
- record.time = null
- } else {
- continue
- }
- record.date = moment(record.createdAt).format("YYYY-MM-DD")
- record.userName = user.name
- record.roomNumber = room.number
- allRecords.push(record)
- }
- return allRecords.reverse()
- },
- async getRoomGetupRecords(roomId, days, pure = false) {
- days = parseInt(days)
- const room = await Room.findOne({ where: { id: roomId } })
- const users = await room.getUsers()
- const records = {}
- for (let user of users) {
- records[user.name] = await this.getUserGetupRecords(user.id, days, pure)
- }
- return records
- },
- async getGetupRecordLineCharData(roomId) {
- const room = await Room.findOne({ where: { id: roomId } })
- const users = await room.getUsers()
- const data = { columns: ["周期"], rows: [] }
- const dataCount = 5 // 获取的记录条数
- const dataStep = 7 // 每条记录相隔的条数
- // 初始化记录值
- for (let i = 0; i < dataCount; i++) {
- data.rows.push({ 周期: `最近${(i + 1) * dataStep}天` })
- }
- // 遍历当前宿舍的用户
- for (let user of users) {
- data.columns.push(user.name)
- for (let i = 0; i < dataCount; i++) {
- const days = (i + 1) * dataStep
- // 获取某学生最近 days 天的早起记录
- const records = await this.getUserGetupRecords(user.id, days, true)
- let earlyTimes = 0
- records.forEach(record => {
- // 统计这些记录中有几天是早起的
- const timeHour = parseInt(moment(record.createdAt).format("HH"))
- if (timeHour < getupEarlyPoint) {
- earlyTimes++
- }
- })
- // 计算早起率
- const probability = (earlyTimes / days).toFixed(4)
- data.rows[i][user.name] = probability
- }
- }
- return data
- },
- async getGetupTableData({
- current,
- step,
- buildingId,
- floorId,
- roomId,
- userId,
- startTime,
- endTime
- }) {
- // 初始化时间
- startTime = startTime
- ? moment(startTime)
- .startOf("day")
- .toDate()
- : moment(0).toDate()
- endTime = endTime
- ? moment(endTime)
- .endOf("day")
- .toDate()
- : moment()
- .endOf("day")
- .toDate()
- console.log("endTime: ", endTime)
- // 开始分情况获取数据
- let result
- if (userId) {
- result = await GetupRecord.findAndCountAll({
- where: {
- userId: userId,
- createdAt: {
- [Op.gt]: startTime,
- [Op.lt]: endTime
- }
- },
- limit: step,
- offset: step * (current - 1),
- order: [["createdAt", "DESC"]]
- })
- } else if (roomId) {
- result = await GetupRecord.findAndCountAll({
- where: {
- roomId: roomId,
- createdAt: {
- [Op.gt]: startTime,
- [Op.lt]: endTime
- }
- },
- limit: step,
- offset: step * (current - 1),
- order: [["createdAt", "DESC"]]
- })
- } else if (floorId) {
- result = await GetupRecord.findAndCountAll({
- where: {
- createdAt: {
- [Op.gt]: startTime,
- [Op.lt]: endTime
- }
- },
- include: [
- {
- model: Room,
- where: { floorId }
- }
- ],
- limit: step,
- offset: step * (current - 1),
- order: [["createdAt", "DESC"]]
- })
- } else if (buildingId) {
- result = await GetupRecord.findAndCountAll({
- where: {
- createdAt: {
- [Op.gt]: startTime,
- [Op.lt]: endTime
- }
- },
- include: [
- {
- model: Room,
- where: { buildingId }
- }
- ],
- limit: step,
- offset: step * (current - 1),
- order: [["createdAt", "DESC"]]
- })
- } else {
- result = await GetupRecord.findAndCountAll({
- where: {
- createdAt: {
- [Op.gt]: startTime,
- [Op.lt]: endTime
- }
- },
- limit: step,
- offset: step * (current - 1),
- order: [["createdAt", "DESC"]]
- })
- }
- const getStudentInfo = require("./user_controller").getStudentInfo
- let rows = []
- for (let record of result.rows) {
- record = record.toJSON()
- delete record.room
- const userInfo = await getStudentInfo(record.userId)
- record = Object.assign(userInfo, record)
- record.time = moment(record.createdAt).format("HH:mm")
- record.date = moment(record.createdAt).format("YYYY-MM-DD")
- if (parseInt(moment(record.createdAt).format("HH")) < getupEarlyPoint) {
- record.early = true
- } else {
- record.early = false
- }
- rows.push(record)
- }
- result.rows = rows
- return result
- },
-
- // back 相关
- async addBackRecord(userId) {
- const user = await User.findOne({ where: { id: userId } })
- const todyRecord = await BackRecord.findOne({
- where: {
- userId: user.id,
- roomId: user.roomId,
- createdAt: {
- [Op.gt]: moment()
- .startOf("day")
- .toDate(),
- [Op.lt]: moment()
- .endOf("day")
- .toDate()
- }
- }
- })
- if (todyRecord) {
- throw new Error("当天已经有记录,记录失败!")
- }
- return await BackRecord.create({ userId: user.id, roomId: user.roomId })
- },
- async getUserBackRecords(userId, days, pure = false) {
- days = parseInt(days)
- const user = await User.findOne({ where: { id: userId } })
- const roomId = user.roomId
- const room = await Room.findOne({ where: { id: roomId } })
- // 获取最近 days 天的记录
- const startTime = moment()
- .subtract(days - 1 /* -1 代表查询天数包括今天 */, "days")
- .startOf("day")
- .toDate()
- const allRecords = []
- for (let i = 0; i < days; i++) {
- const todayStart = moment(startTime)
- .add(i, "days")
- .toDate()
- const todayEnd = moment(todayStart)
- .endOf("day")
- .toDate()
- let record = await BackRecord.findOne({
- where: {
- userId,
- roomId,
- createdAt: {
- [Op.gt]: todayStart,
- [Op.lt]: todayEnd
- }
- },
- attributes: { exclude: ["updatedAt", "deletedAt"] }
- })
- if (record) {
- // 如果当天有记录就推入结果
- record = record.toJSON()
- record.time = moment(record.createdAt).format("HH:mm")
- } else if (!record && !pure) {
- // 如果获取的是全部数据且当前天无数据
- // 就建立一条空记录
- record = BackRecord.build({
- id: "fake" + i,
- roomId,
- userId,
- createdAt: todayStart
- }).toJSON()
- record.time = null
- } else {
- continue
- }
- record.date = moment(record.createdAt).format("YYYY-MM-DD")
- record.userName = user.name
- record.roomNumber = room.number
- allRecords.push(record)
- }
- return allRecords.reverse()
- },
- async getRoomBackRecords(roomId, days, pure = false) {
- days = parseInt(days)
- const room = await Room.findOne({ where: { id: roomId } })
- const users = await room.getUsers()
- const records = {}
- for (let user of users) {
- records[user.name] = await this.getUserBackRecords(user.id, days, pure)
- }
- return records
- },
- async getBackRecordLineCharData(roomId) {
- const room = await Room.findOne({ where: { id: roomId } })
- const users = await room.getUsers()
- const data = { columns: ["周期"], rows: [] }
- const dataCount = 5 // 获取的记录条数
- const dataStep = 7 // 每条记录相隔的条数
- // 初始化记录值
- for (let i = 0; i < dataCount; i++) {
- data.rows.push({ 周期: `最近${(i + 1) * dataStep}天` })
- }
- // 遍历当前宿舍的用户
- for (let user of users) {
- data.columns.push(user.name)
- for (let i = 0; i < dataCount; i++) {
- const days = (i + 1) * dataStep
- // 获取某学生最近 days 天的归宿记录
- const records = await this.getUserBackRecords(user.id, days, true)
- let earlyTimes = 0
- records.forEach(record => {
- // 统计这些记录中有几天是早归的
- const timeHour = parseInt(moment(record.createdAt).format("HH"))
- if (timeHour < backEarlyPoint) {
- earlyTimes++
- }
- })
- // 计算早起率
- const probability = (earlyTimes / days).toFixed(4)
- data.rows[i][user.name] = probability
- }
- }
- return data
- },
- async getBackTableData({
- current,
- step,
- buildingId,
- floorId,
- roomId,
- userId,
- startTime,
- endTime
- }) {
- // 初始化时间
- startTime = startTime
- ? moment(startTime)
- .startOf("day")
- .toDate()
- : moment(0).toDate()
- endTime = endTime
- ? moment(endTime)
- .endOf("day")
- .toDate()
- : moment()
- .endOf("day")
- .toDate()
- // 开始分情况获取数据
- let result
- if (userId) {
- result = await BackRecord.findAndCountAll({
- where: {
- userId: userId,
- createdAt: {
- [Op.gt]: startTime,
- [Op.lt]: endTime
- }
- },
- limit: step,
- offset: step * (current - 1),
- order: [["createdAt", "DESC"]]
- })
- } else if (roomId) {
- result = await BackRecord.findAndCountAll({
- where: {
- roomId: roomId,
- createdAt: {
- [Op.gt]: startTime,
- [Op.lt]: endTime
- }
- },
- limit: step,
- offset: step * (current - 1),
- order: [["createdAt", "DESC"]]
- })
- } else if (floorId) {
- result = await BackRecord.findAndCountAll({
- where: {
- createdAt: {
- [Op.gt]: startTime,
- [Op.lt]: endTime
- }
- },
- include: [
- {
- model: Room,
- where: { floorId }
- }
- ],
- limit: step,
- offset: step * (current - 1),
- order: [["createdAt", "DESC"]]
- })
- } else if (buildingId) {
- result = await BackRecord.findAndCountAll({
- where: {
- createdAt: {
- [Op.gt]: startTime,
- [Op.lt]: endTime
- }
- },
- include: [
- {
- model: Room,
- where: { buildingId }
- }
- ],
- limit: step,
- offset: step * (current - 1),
- order: [["createdAt", "DESC"]]
- })
- } else {
- result = await BackRecord.findAndCountAll({
- where: {
- createdAt: {
- [Op.gt]: startTime,
- [Op.lt]: endTime
- }
- },
- limit: step,
- offset: step * (current - 1),
- order: [["createdAt", "DESC"]]
- })
- }
- const getStudentInfo = require("./user_controller").getStudentInfo
- let rows = []
- for (let record of result.rows) {
- record = record.toJSON()
- delete record.room
- const userInfo = await getStudentInfo(record.userId)
- record = Object.assign(userInfo, record)
- record.time = moment(record.createdAt).format("HH:mm")
- record.date = moment(record.createdAt).format("YYYY-MM-DD")
- if (parseInt(moment(record.createdAt).format("HH")) < backEarlyPoint) {
- record.early = true
- } else {
- record.early = false
- }
- rows.push(record)
- }
- result.rows = rows
- return result
- },
-
- // clean 相关
- async addCleanRecord(userId) {
- const user = await User.findOne({ where: { id: userId } })
- const todyRecord = await CleanRecord.findOne({
- where: {
- roomId: user.roomId,
- createdAt: {
- [Op.gt]: moment()
- .startOf("day")
- .toDate(),
- [Op.lt]: moment()
- .endOf("day")
- .toDate()
- }
- }
- })
- if (todyRecord) {
- throw new Error("当天已经有清扫记录,记录失败")
- }
- return await CleanRecord.create({
- userId: user.id,
- roomId: user.roomId
- })
- },
- async getUserCleanRecords(userId, days) {
- // 获取打扫记录不会自动补全每一天的信息
- days = parseInt(days)
- const user = await User.findOne({ where: { id: userId } })
- const roomId = user.roomId
- const room = await Room.findOne({ where: { id: roomId } })
- // 获取最近 days 天的记录
- const startTime = moment()
- .subtract(days - 1 /* -1 代表查询天数包括今天 */, "days")
- .startOf("day")
- .toDate()
- const todayEnd = moment()
- .endOf("day")
- .toDate()
- const records = await CleanRecord.findAll({
- where: {
- userId,
- roomId,
- createdAt: {
- [Op.gt]: startTime,
- [Op.lt]: todayEnd
- }
- },
- attributes: { exclude: ["updatedAt", "deletedAt"] },
- order: [["createdAt", "DESC"]]
- })
- const allRecords = []
- records.forEach(record => {
- record = record.toJSON()
- record.time = moment(record.createdAt).format("HH:mm")
- record.date = moment(record.createdAt).format("YYYY-MM-DD")
- record.userName = user.name
- record.roomNumber = room.number
- allRecords.push(record)
- })
- return allRecords
- },
- async getRoomCleanRecords(roomId, days) {
- const room = await Room.findOne({ where: { id: roomId } })
- const startTime = moment()
- .subtract(days - 1 /* -1 代表查询天数包括今天 */, "days")
- .startOf("day")
- .toDate()
- const todayEnd = moment()
- .endOf("day")
- .toDate()
- const records = await room.getCleanRecords({
- where: {
- createdAt: {
- [Op.gt]: startTime,
- [Op.lt]: todayEnd
- }
- },
- attributes: { exclude: ["updatedAt", "deletedAt"] },
- order: [["createdAt", "DESC"]]
- })
- const allRecords = []
- for (let record of records) {
- const user = await record.getUser()
- record = record.toJSON()
- record.date = moment(record.createdAt).format("YYYY-MM-DD")
- record.time = moment(record.createdAt).format("HH:mm")
- record.userName = user.name
- record.roomNumber = room.number
- allRecords.push(record)
- }
- return allRecords
- },
- async getCleanTableData({
- current,
- step,
- buildingId,
- floorId,
- roomId,
- userId,
- startTime,
- endTime
- }) {
- // 初始化时间
- startTime = startTime
- ? moment(startTime)
- .startOf("day")
- .toDate()
- : moment(0).toDate()
- endTime = endTime
- ? moment(endTime)
- .endOf("day")
- .toDate()
- : moment()
- .endOf("day")
- .toDate()
- // 开始分情况获取数据
- let result
- if (userId) {
- result = await CleanRecord.findAndCountAll({
- where: {
- userId: userId,
- createdAt: {
- [Op.gt]: startTime,
- [Op.lt]: endTime
- }
- },
- limit: step,
- offset: step * (current - 1),
- order: [["createdAt", "DESC"]]
- })
- } else if (roomId) {
- result = await CleanRecord.findAndCountAll({
- where: {
- roomId: roomId,
- createdAt: {
- [Op.gt]: startTime,
- [Op.lt]: endTime
- }
- },
- limit: step,
- offset: step * (current - 1),
- order: [["createdAt", "DESC"]]
- })
- } else if (floorId) {
- result = await CleanRecord.findAndCountAll({
- where: {
- createdAt: {
- [Op.gt]: startTime,
- [Op.lt]: endTime
- }
- },
- include: [
- {
- model: Room,
- where: { floorId }
- }
- ],
- limit: step,
- offset: step * (current - 1),
- order: [["createdAt", "DESC"]]
- })
- } else if (buildingId) {
- result = await CleanRecord.findAndCountAll({
- where: {
- createdAt: {
- [Op.gt]: startTime,
- [Op.lt]: endTime
- }
- },
- include: [
- {
- model: Room,
- where: { buildingId }
- }
- ],
- limit: step,
- offset: step * (current - 1),
- order: [["createdAt", "DESC"]]
- })
- } else {
- result = await CleanRecord.findAndCountAll({
- where: {
- createdAt: {
- [Op.gt]: startTime,
- [Op.lt]: endTime
- }
- },
- limit: step,
- offset: step * (current - 1),
- order: [["createdAt", "DESC"]]
- })
- }
- const getStudentInfo = require("./user_controller").getStudentInfo
- let rows = []
- for (let record of result.rows) {
- record = record.toJSON()
- delete record.room
- const userInfo = await getStudentInfo(record.userId)
- record = Object.assign(userInfo, record)
- record.time = moment(record.createdAt).format("HH:mm")
- record.date = moment(record.createdAt).format("YYYY-MM-DD")
- record.early = null
- rows.push(record)
- }
- result.rows = rows
- return result
- },
-
- // 通用
- async getUserProbability(type, userId) {
- const user = await User.findById(userId)
- const startTime = user.checkTime
- let records = []
- let allRecords = []
- switch (type) {
- case "getup":
- allRecords = await user.getGetupRecords({
- where: {
- createdAt: { [Op.gt]: startTime }
- }
- })
- allRecords.forEach(record => {
- let hour = parseInt(moment(record.createdAt).format("HH"))
- if (hour < getupEarlyPoint) {
- records.push(record)
- }
- })
- break
- case "back":
- allRecords = await user.getBackRecords({
- where: {
- createdAt: { [Op.gt]: startTime }
- }
- })
- allRecords.forEach(record => {
- let hour = parseInt(moment(record.createdAt).format("HH"))
- if (hour < backEarlyPoint) {
- records.push(record)
- }
- })
- break
- case "clean":
- records = await user.getCleanRecords({
- where: {
- createdAt: { [Op.gt]: startTime }
- }
- })
- break
- default:
- throw new Error("参数传入错误")
- }
- // 计算从入住到现在有几天了
- const days = Math.abs(moment(startTime).diff(moment(), "days"))
- return (records.length / (days + 1)).toFixed(4)
- }
- }
- const { User } = require("../model")
- const _ = require("lodash")
- const RecordController = require("./record_controller")
-
- module.exports = {
- /**
- * 获取学生用户的完整信息
- * @param {Number} userId
- */
- async getStudentInfo(userId) {
- const student = await User.findOne({
- where: { id: userId },
- attributes: { exclude: ["password", "deletedAt"] }
- })
- const room = await student.getRoom()
- const floor = await room.getFloor()
- const building = await floor.getBuilding()
- const getupProb = await RecordController.getUserProbability("getup", userId)
- const backProb = await RecordController.getUserProbability("back", userId)
- const cleanProb = await RecordController.getUserProbability("clean", userId)
- const info = Object.assign(student.dataValues, {
- roomNumber: room.number,
- floorId: floor.id,
- floorLayer: floor.layer,
- buildingId: building.id,
- buildingName: building.name,
- getupProb,
- backProb,
- cleanProb
- })
- return info
- },
-
- /**
- * 获取学生用户们的完整信息
- * @param {Array} users
- */
- async getStudentsInfo(users) {
- const cloneUsers = _.cloneDeep(users)
- for (let user of cloneUsers) {
- delete user.dataValues.password
- delete user.dataValues.deletedAt
- const room = await user.getRoom()
- const floor = await room.getFloor()
- const building = await floor.getBuilding()
- Object.assign(user.dataValues, {
- roomNumber: room.number,
- floorId: floor.id,
- floorLayer: floor.layer,
- buildingId: building.id,
- buildingName: building.name
- })
- }
- return cloneUsers
- },
-
- async setStudentRoomNull(id) {
- const student = await User.findOne({ where: { id, role: "student" } })
- const result = await student.update({ roomId: null })
- return result
- }
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。