├── .gitattributes ├── .gitignore ├── .prettierrc ├── .vscode └── extensions.json ├── LICENSE ├── README.md ├── index.html ├── js-modules.d.ts ├── package-lock.json ├── package.json ├── public ├── images │ └── user.jpeg └── vite.svg ├── server ├── app.js ├── babel.config.json ├── bin │ └── www ├── db │ ├── sql.js │ └── usersql.js ├── package-lock.json ├── package.json ├── public │ ├── images │ │ └── user.jpeg │ └── stylesheets │ │ └── style.css ├── router_handler │ ├── authorityHandler.js │ ├── classHandler.js │ └── teacherHandler.js ├── routes │ ├── index.js │ ├── nodemailer.js │ └── users.js └── views │ ├── error.ejs │ └── index.ejs ├── src ├── App.vue ├── assets │ ├── img │ │ └── user.jpeg │ └── vue.svg ├── auto-import.d.ts ├── components │ ├── Login.vue │ ├── common │ │ ├── Dialog.vue │ │ ├── colorBack.vue │ │ ├── sakura.js │ │ └── uploadImg.vue │ └── contant │ │ ├── Control │ │ └── userInfo.vue │ │ ├── Header.vue │ │ ├── LeftNav.vue │ │ └── upLoad.vue ├── hooks │ ├── getUserData.js │ └── showMsg.js ├── main.ts ├── network │ └── request.js ├── router │ └── index.js ├── store │ ├── index.ts │ └── store-name.ts ├── style.css ├── views │ ├── Class │ │ └── ClassShow.vue │ ├── Control │ │ └── Control.vue │ ├── Home.vue │ ├── Login.vue │ ├── My │ │ └── editMy.vue │ ├── Student │ │ ├── AddStudent.vue │ │ ├── SelectStudent.vue │ │ └── showStudent.vue │ ├── Teacher │ │ ├── AddTeacher.vue │ │ ├── SelectTeacher.vue │ │ └── ShowTeacher.vue │ └── authority │ │ └── userManager.vue └── vite-env.d.ts ├── tsconfig.json ├── tsconfig.node.json └── vite.config.ts /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "bracketSameLine":true, 3 | "vueIndentScriptAndStyle":true, 4 | "tabWidth": 4, 5 | "printWidth":150, 6 | "prettier.singleQuote": true 7 | } 8 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["Vue.volar", "Vue.vscode-typescript-vue-plugin"] 3 | } 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 kumudada 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Vue 3 + TypeScript + Vite 2 | 3 | This template should help get you started developing with Vue 3 and TypeScript in Vite. The template uses Vue 3 ` 12 | 13 | 14 | -------------------------------------------------------------------------------- /js-modules.d.ts: -------------------------------------------------------------------------------- 1 | declare module '@/network/request.js'; -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "studypinia", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "vite build", 9 | "preview": "vite preview" 10 | }, 11 | "dependencies": { 12 | "@element-plus/icons-vue": "^2.0.10", 13 | "animate.css": "^3.5.1", 14 | "axios": "^1.2.3", 15 | "element-plus": "^2.2.28", 16 | "less": "^4.1.3", 17 | "pinia": "^2.0.29", 18 | "vanilla-tilt": "^1.8.0", 19 | "vue": "^3.2.45", 20 | "vue-router": "^4.1.6", 21 | "vue-wechat-title": "^2.0.7", 22 | "xlsx": "^0.18.5" 23 | }, 24 | "devDependencies": { 25 | "@types/node": "^18.11.18", 26 | "@vitejs/plugin-vue": "^4.0.0", 27 | "typescript": "^4.9.3", 28 | "unplugin-auto-import": "^0.12.2", 29 | "vite": "^4.0.0", 30 | "vue-tsc": "^1.0.11" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /public/images/user.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kumudada/studentManager/b9b34c615f388ad30ba3cab2fd5eddaa396284a3/public/images/user.jpeg -------------------------------------------------------------------------------- /public/vite.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /server/app.js: -------------------------------------------------------------------------------- 1 | var createError = require("http-errors"); 2 | var express = require("express"); 3 | var path = require("path"); 4 | var cookieParser = require("cookie-parser"); 5 | var logger = require("morgan"); 6 | var bodyParser = require("body-parser"); 7 | 8 | var indexRouter = require("./routes/index"); 9 | var usersRouter = require("./routes/users"); 10 | var app = express(); 11 | app.use(express.static("./public")); 12 | // 解决跨域 13 | const cors = require("cors"); 14 | app.use(cors()); 15 | 16 | // view engine setup 17 | app.set("views", path.join(__dirname, "views")); 18 | app.set("view engine", "ejs"); 19 | 20 | app.use(logger("dev")); 21 | app.use(bodyParser.json({ limit: "100mb" })); 22 | app.use(bodyParser.urlencoded({ limit: "100mb", extended: true })); 23 | app.use(express.json()); 24 | app.use(express.urlencoded({ extended: false })); 25 | app.use(cookieParser()); 26 | app.use(express.static(path.join(__dirname, "public"))); 27 | 28 | app.use("/", indexRouter); 29 | app.use("/users", usersRouter); 30 | 31 | // catch 404 and forward to error handler 32 | app.use(function (req, res, next) { 33 | next(createError(404)); 34 | }); 35 | 36 | // error handler 37 | app.use(function (err, req, res, next) { 38 | // set locals, only providing error in development 39 | res.locals.message = err.message; 40 | res.locals.error = req.app.get("env") === "development" ? err : {}; 41 | 42 | // render the error page 43 | res.status(err.status || 500); 44 | res.render("error"); 45 | }); 46 | 47 | module.exports = app; 48 | -------------------------------------------------------------------------------- /server/babel.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | [ 4 | "@babel/preset-env", 5 | { 6 | "targets": { 7 | "edge": "17", 8 | "firefox": "60", 9 | "chrome": "67", 10 | "safari": "11.1" 11 | }, 12 | "useBuiltIns": "usage", 13 | "corejs": "3.6.5" 14 | } 15 | ] 16 | ] 17 | } -------------------------------------------------------------------------------- /server/bin/www: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | /** 4 | * Module dependencies. 5 | */ 6 | 7 | var app = require("../app"); 8 | var debug = require("debug")("server:server"); 9 | var http = require("http"); 10 | 11 | /** 12 | * Get port from environment and store in Express. 13 | */ 14 | 15 | var port = normalizePort(process.env.PORT || "3007"); 16 | app.set("port", port); 17 | 18 | /** 19 | * Create HTTP server. 20 | */ 21 | 22 | var server = http.createServer(app); 23 | 24 | /** 25 | * Listen on provided port, on all network interfaces. 26 | */ 27 | 28 | server.listen(port); 29 | server.on("error", onError); 30 | server.on("listening", onListening); 31 | 32 | /** 33 | * Normalize a port into a number, string, or false. 34 | */ 35 | 36 | function normalizePort(val) { 37 | var port = parseInt(val, 10); 38 | 39 | if (isNaN(port)) { 40 | // named pipe 41 | return val; 42 | } 43 | 44 | if (port >= 0) { 45 | // port number 46 | return port; 47 | } 48 | 49 | return false; 50 | } 51 | 52 | /** 53 | * Event listener for HTTP server "error" event. 54 | */ 55 | 56 | function onError(error) { 57 | if (error.syscall !== "listen") { 58 | throw error; 59 | } 60 | 61 | var bind = typeof port === "string" ? "Pipe " + port : "Port " + port; 62 | 63 | // handle specific listen errors with friendly messages 64 | switch (error.code) { 65 | case "EACCES": 66 | console.error(bind + " requires elevated privileges"); 67 | process.exit(1); 68 | break; 69 | case "EADDRINUSE": 70 | console.error(bind + " is already in use"); 71 | process.exit(1); 72 | break; 73 | default: 74 | throw error; 75 | } 76 | } 77 | 78 | /** 79 | * Event listener for HTTP server "listening" event. 80 | */ 81 | 82 | function onListening() { 83 | var addr = server.address(); 84 | var bind = typeof addr === "string" ? "pipe " + addr : "port " + addr.port; 85 | debug("Listening on " + bind); 86 | } 87 | -------------------------------------------------------------------------------- /server/db/sql.js: -------------------------------------------------------------------------------- 1 | const mysql = require("mysql"); 2 | 3 | const db = mysql.createPool({ 4 | host: "127.0.0.1", 5 | user: "root", 6 | password: "15612168583", 7 | database: "student_manage", 8 | }); 9 | 10 | module.exports = db; 11 | -------------------------------------------------------------------------------- /server/db/usersql.js: -------------------------------------------------------------------------------- 1 | // 验证数据库中的用户 2 | const user = { 3 | // 查询用户手机号 4 | queryUserTell(option) { 5 | return "select * from user where tel = " + option.userTel + ""; 6 | }, 7 | // 更新token 8 | updateToken(option) { 9 | return `update user set token = '${option.token}' where email = '${option.email}'`; 10 | }, 11 | // 更改学生信息 12 | updataStudent(option) { 13 | return `update studentinfo set stuNumber = '${option.number}', name = '${option.name}',sex = '${option.gender}',age = '${option.age}',grade = '${option.reged}',class=' ${option.class}',major = '${option.major}',province ='${option.province}',city = '${option.city}' WHERE id = ${option.id}`; 14 | }, 15 | // 添加学生信息 16 | addStudent(option) { 17 | return `insert into studentinfo(stuNumber,name,sex,age,tel,class,grade,major,city,province,teacher) values('${option.stuNumber}','${option.name}','${option.sex}','${option.age}','${option.tel}','${option.class}','${option.grade}','${option.major}','${option.city}','${option.province}','${option.manager}')`; 18 | }, 19 | // 搜索学生信息 20 | searchStudent(option) { 21 | // 使用学号查询 22 | if (option.select == "1") { 23 | return `select * from studentinfo where stuNumber like '%${option.input}%'`; 24 | } 25 | // 使用手机号查询 26 | if (option.select == "3") { 27 | return `select * from studentinfo where tel like '%${option.input}%'`; 28 | } 29 | // 使用姓名查询 30 | if (option.select == "2") { 31 | return `select * from studentinfo where name like '%${option.input}%'`; 32 | } 33 | }, 34 | // 更改教师信息 35 | updateTeacher(option) { 36 | return `UPDATE teacher SET workid = '${option.number}',name = '${option.name}',age = '${option.age}',gender = "${option.gender}",tel = "${option.tel}",department = "${option.department}",professional = "${option.professional}" WHERE id = ${option.id}`; 37 | }, 38 | // 添加教师信息 39 | addTeacher(option) { 40 | return `insert into teacher(workid,name,age,gender,tel,department,professional) values('${option.workid}','${option.name}','${option.age}','${option.gender}','${option.tel}','${option.department}','${option.professional}'`; 41 | }, 42 | // 搜索教师信息 43 | searchTeacher(option) { 44 | // 使用编号搜素 45 | if (option.select == "1") { 46 | return `select * from teacher where workid like '%${option.input}%'`; 47 | } 48 | // 使用姓名搜素 49 | if (option.select == "2") { 50 | return `select * from teacher where name like '%${option.input}%'`; 51 | } 52 | // 使用手机号搜素 53 | if (option.select == "3") { 54 | return `select * from teacher where tel like '%${option.input}%'`; 55 | } 56 | }, 57 | // 搜索班级信息 58 | searchClass(option) { 59 | // 全部班级 60 | if (option.select == 1) { 61 | return `select * from classes`; 62 | } 63 | // 班级名称 64 | if (option.select == 2) { 65 | return `select * from classes where class like '%${option.input}%'`; 66 | } 67 | // 负责导师 68 | if (option.select == 3) { 69 | return `select * from classes where manager like '%${option.input}%'`; 70 | } 71 | // 专业名称 72 | if (option.select == 4) { 73 | return `select * from classes where major like '%${option.input}%'`; 74 | } 75 | }, 76 | // 添加新的班级数据 77 | addClass(option) { 78 | return `insert into classes(class,manager,major,college) values('${option.class}','${option.manager}','${option.major}','${option.college}')`; 79 | }, 80 | // 更新班级数据 81 | updateClassData(option) { 82 | return `update classes set class = '${option.class}',manager = '${option.manager}',major = '${option.major}',college = '${option.college}' where id = '${option.id}'`; 83 | }, 84 | // 搜索用户数据 85 | userData(option) { 86 | if (option.select == "1") { 87 | return `select * from user`; 88 | } 89 | if (option.select == "2") { 90 | return `select * from user where username like '%${option.input}%'`; 91 | } 92 | if (option.select == "3") { 93 | return `select * from user where email like '%${option.input}%'`; 94 | } 95 | }, 96 | }; 97 | exports = module.exports = user; 98 | -------------------------------------------------------------------------------- /server/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "server", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "start": "node ./bin/www" 7 | }, 8 | "dependencies": { 9 | "cors": "^2.8.5", 10 | "debug": "~2.6.9", 11 | "ejs": "~2.6.1", 12 | "express": "~4.16.1", 13 | "formidable": "^2.1.1", 14 | "http-errors": "~1.6.3", 15 | "jsonwebtoken": "^9.0.0", 16 | "morgan": "~1.9.1", 17 | "multiparty": "^4.2.3", 18 | "mysql": "^2.18.1", 19 | "nodemailer": "^6.9.1", 20 | "nodemailer-smtp-transport": "^2.7.4", 21 | "qcloudsms_js": "^0.1.1", 22 | "xlsx": "^0.18.5" 23 | }, 24 | "devDependencies": { 25 | "@babel/cli": "^7.20.7", 26 | "@babel/core": "^7.20.12", 27 | "@babel/preset-env": "^7.20.2", 28 | "cookie-parser": "^1.4.6" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /server/public/images/user.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kumudada/studentManager/b9b34c615f388ad30ba3cab2fd5eddaa396284a3/server/public/images/user.jpeg -------------------------------------------------------------------------------- /server/public/stylesheets/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding: 50px; 3 | font: 14px "Lucida Grande", Helvetica, Arial, sans-serif; 4 | } 5 | 6 | a { 7 | color: #00B7FF; 8 | } 9 | -------------------------------------------------------------------------------- /server/router_handler/authorityHandler.js: -------------------------------------------------------------------------------- 1 | // 导入db模块 2 | const db = require("../db/sql"); 3 | // 导入express模块 4 | const express = require("express"); 5 | 6 | const sql = require("../db/usersql"); 7 | 8 | exports.userData = (req, res) => { 9 | const parmas = req.body; 10 | db.query(sql.userData(parmas), (error, result) => { 11 | if (error) { 12 | res.send({ 13 | code: 500, 14 | success: false, 15 | msg: "服务器错误", 16 | }); 17 | } 18 | res.send({ 19 | code: 200, 20 | success: true, 21 | msg: "搜索成功", 22 | data: result, 23 | }); 24 | }); 25 | }; 26 | 27 | exports.change_authority = (req, res) => { 28 | const parmas = req.body; 29 | db.query(`update user set username = '${req.body.user}',authority = '${req.body.region}' where id = ${req.body.userid}`, (error, result) => { 30 | if (error) { 31 | res.send({ 32 | code: 400, 33 | success: false, 34 | msg: "Error!", 35 | }); 36 | return; 37 | } 38 | res.send({ 39 | code: 200, 40 | success: true, 41 | msg: "Success", 42 | }); 43 | }); 44 | }; 45 | -------------------------------------------------------------------------------- /server/router_handler/classHandler.js: -------------------------------------------------------------------------------- 1 | // 导入db模块 2 | const db = require("../db/sql"); 3 | // 导入express模块 4 | const express = require("express"); 5 | 6 | const sql = require("../db/usersql"); 7 | // 获取班级数据 8 | exports.getClass = (req, res) => { 9 | db.query(`select * from classes`, (errors, results) => { 10 | if (errors) { 11 | res.send({ 12 | code: 500, 13 | success: false, 14 | msg: "服务器错误", 15 | }); 16 | } else { 17 | res.send({ 18 | code: 200, 19 | success: true, 20 | data: results, 21 | }); 22 | } 23 | }); 24 | }; 25 | // 删除班级数据 26 | exports.delClass = (req, res) => { 27 | db.query(`delete from classes where id =?`, [req.body.id], (errors, results) => { 28 | if (errors) { 29 | res.send({ 30 | code: 500, 31 | success: false, 32 | msg: "服务器错误", 33 | }); 34 | } else { 35 | res.send({ 36 | code: 200, 37 | success: true, 38 | msg: "删除成功", 39 | }); 40 | } 41 | }); 42 | }; 43 | 44 | // 搜索班级数据 45 | exports.searchClass = (req, res) => { 46 | // 将select转换为int 47 | req.body.select._value = Number(req.body.select._value); 48 | // 存储数据 49 | let parmas = { input: req.body.input._value, select: req.body.select._value }; 50 | db.query(sql.searchClass(parmas), (error, result) => { 51 | if (error) { 52 | res.send({ 53 | code: 500, 54 | success: false, 55 | msg: "服务器错误", 56 | }); 57 | return; 58 | } else { 59 | res.send({ 60 | code: 200, 61 | success: true, 62 | data: result, 63 | }); 64 | } 65 | }); 66 | }; 67 | 68 | exports.getCollegeList = (req, res) => { 69 | db.query("select * from college", (error, result) => { 70 | if (error) { 71 | res.send({ 72 | code: 500, 73 | success: false, 74 | msg: "服务器错误", 75 | }); 76 | } else { 77 | res.send({ 78 | code: 200, 79 | success: true, 80 | data: result, 81 | }); 82 | } 83 | }); 84 | }; 85 | 86 | // 添加班级数据 87 | exports.addClassData = (req, res) => { 88 | let parmas = req.body; 89 | // 查询是否重复添加 90 | db.query(`select * from classes where class = '${parmas.class}'`, (err, resu) => { 91 | if (resu[0]) { 92 | res.send({ 93 | code: 300, 94 | success: false, 95 | msg: "该班级已存在", 96 | }); 97 | return; 98 | } else { 99 | // 添加数据 100 | db.query(sql.addClass(parmas), (error, result) => { 101 | if (error) { 102 | res.send({ 103 | code: 500, 104 | success: false, 105 | msg: "服务器错误", 106 | }); 107 | return; 108 | } 109 | res.send({ 110 | code: 200, 111 | success: true, 112 | msg: "添加成功", 113 | }); 114 | }); 115 | } 116 | }); 117 | }; 118 | // 更新班级信息 119 | exports.updateClassData = (req, res) => { 120 | let params = req.body; 121 | console.log(params); 122 | // 更新数据 123 | db.query(sql.updateClassData(params), (err, result) => { 124 | if (err) { 125 | res.send({ 126 | code: 500, 127 | success: false, 128 | msg: "服务器错误", 129 | }); 130 | } else { 131 | res.send({ 132 | code: 200, 133 | success: true, 134 | msg: "修改成功", 135 | }); 136 | } 137 | }); 138 | }; 139 | -------------------------------------------------------------------------------- /server/router_handler/teacherHandler.js: -------------------------------------------------------------------------------- 1 | // 导入db模块 2 | const db = require("../db/sql"); 3 | // 导入express模块 4 | const express = require("express"); 5 | 6 | const sql = require("../db/usersql"); 7 | // 获取教师信息 8 | exports.getTeacherData = (req, res) => { 9 | db.query("select * from teacher", (error, result) => { 10 | if (error) { 11 | console.log(error); 12 | res.send({ 13 | code: 500, 14 | msg: "服务器错误", 15 | }); 16 | } else { 17 | res.send({ 18 | code: 200, 19 | success: true, 20 | msg: "获取成功", 21 | data: result, 22 | }); 23 | } 24 | }); 25 | }; 26 | // 删除教师信息 27 | exports.deleteTeacher = (req, res) => { 28 | let id = req.body.id; 29 | db.query(`DELETE FROM teacher WHERE id = ${id}`, (error, result) => { 30 | if (result.affectedRows) { 31 | res.send({ 32 | code: 200, 33 | success: true, 34 | msg: "删除成功", 35 | }); 36 | } else { 37 | res.send({ 38 | code: 300, 39 | success: false, 40 | msg: "删除失败", 41 | }); 42 | } 43 | }); 44 | }; 45 | 46 | exports.getDepartment = (req, res) => { 47 | db.query(`SELECT * FROM department`, (error, result) => { 48 | if (error) { 49 | console.log(error); 50 | } else { 51 | res.send({ 52 | code: 200, 53 | success: true, 54 | data: result, 55 | }); 56 | } 57 | }); 58 | }; 59 | // 获得职称列表 60 | exports.getProfessional = (req, res) => { 61 | db.query(`SELECT * FROM professional`, (error, result) => { 62 | if (error) { 63 | console.log(error); 64 | } else { 65 | res.send({ 66 | code: 200, 67 | success: true, 68 | data: result, 69 | }); 70 | } 71 | }); 72 | }; 73 | // 更改教师信息 74 | exports.updateTeacher = (req, res) => { 75 | const params = req.body; 76 | db.query(sql.updateTeacher(params), (error, results) => { 77 | if (error) { 78 | console.log(error); 79 | res.send({ 80 | code: 500, 81 | success: false, 82 | msg: "服务器错误", 83 | }); 84 | } else { 85 | res.send({ 86 | code: 200, 87 | success: true, 88 | msg: "修改成功", 89 | }); 90 | } 91 | }); 92 | }; 93 | 94 | // 添加教师信息 95 | exports.addTeacher = (req, res) => { 96 | const parmas = req.body; 97 | db.query(`select * from teacher where workid = '${parmas.workid}'`, (error, result) => { 98 | if (result == []) { 99 | db.query(sql.addTeacher(parmas), (err, resu) => { 100 | res.send({ 101 | code: 200, 102 | success: true, 103 | msg: "添加成功", 104 | }); 105 | }); 106 | } else { 107 | res.send({ 108 | code: 300, 109 | success: false, 110 | msg: "请勿重复添加", 111 | }); 112 | } 113 | }); 114 | }; 115 | // 搜索教师信息 116 | exports.searchTeacher = (req, res) => { 117 | const params = req.body; 118 | console.log(req.body); 119 | db.query(sql.searchTeacher(params), (error, result) => { 120 | if (error) { 121 | console.log(error); 122 | res.send({ 123 | code: 500, 124 | success: false, 125 | msg: "服务器错误", 126 | }); 127 | } else { 128 | res.send({ 129 | code: 200, 130 | success: true, 131 | msg: "查询成功", 132 | data: result, 133 | }); 134 | } 135 | }); 136 | }; 137 | -------------------------------------------------------------------------------- /server/routes/index.js: -------------------------------------------------------------------------------- 1 | var express = require("express"); 2 | var router = express.Router(); 3 | let fs = require("fs"); 4 | let path = require("path"); 5 | let formidable = require("formidable"); 6 | // 引入数据库 7 | let db = require("../db/sql"); 8 | // 引入token 9 | let jwt = require("jsonwebtoken"); 10 | const usersql = require("../db/usersql.js"); 11 | // 引入发送邮件的模块 12 | const nodemailer = require("nodemailer"); 13 | const smtpTransport = require("nodemailer-smtp-transport"); 14 | const { abort } = require("process"); 15 | // import nodeMail from "./nodemailer.js"; 16 | // 引入教师信息处理函数 17 | const teacherHandler = require("../router_handler/teacherHandler.js"); 18 | // 引入班级信息处理函数 19 | const classHandler = require("../router_handler/classHandler.js"); 20 | 21 | const authorityHandler = require("../router_handler/authorityHandler.js"); 22 | 23 | /* GET home page. */ 24 | // 测试主页 25 | router.get("/", function (req, res, next) { 26 | res.render("index", { title: "Express" }); 27 | next(); 28 | }); 29 | // 测试 30 | router.get("/api/test", function (req, res, next) { 31 | res.send({ 32 | code: 200, 33 | success: true, 34 | msg: "成功", 35 | }); 36 | }); 37 | 38 | /** 39 | * 存储文件方法 40 | */ 41 | function saveFile(file, callback) { 42 | // 定义存储文件地址 43 | let savePath = path.resolve(__dirname, `../public/images/${file.name}`); 44 | let sourcePath = file.path; 45 | // 创建读写流 46 | let readStream = fs.createReadStream(sourcePath); 47 | let writeStream = fs.createWriteStream(savePath); 48 | // 读写进程开始 49 | readStream.pipe(writeStream); 50 | // 监听读取完成事件 51 | readStream.on("end", () => { 52 | // 读取完成后,释放读取源文件链接 53 | fs.unlinkSync(sourcePath); 54 | callback(); 55 | }); 56 | } 57 | 58 | // 登录 59 | router.post("/api/login", function (req, res, next) { 60 | // 获取数据 61 | let email = req.body.email; 62 | let password = req.body.password; 63 | // 用户信息 64 | let payload = { email: email }; 65 | // 口令 66 | let secret = "lijiale"; 67 | // 生成token 68 | let token = jwt.sign(payload, secret, { expiresIn: "2h" }); 69 | let params = { 70 | email: email, 71 | token: token, 72 | }; 73 | db.query(`SELECT * FROM user WHERE email = "${email}" AND pwd = "${password}"`, (results, errors) => { 74 | if (errors != null && errors.length) { 75 | db.query(`SELECT * FROM user WHERE email = '${email}'`, (result, err) => { 76 | // 登录更新token 77 | db.query(usersql.updateToken(params), (r, e) => { 78 | res.send({ 79 | code: 200, 80 | success: true, 81 | msg: "登录成功", 82 | data: { 83 | userid: err[0].id, 84 | username: err[0].username, 85 | email: err[0].email, 86 | pwd: err[0].pwd, 87 | token: err[0].token, 88 | imgUrl: err[0].imgUrl, 89 | authority: err[0].authority, 90 | }, 91 | }); 92 | }); 93 | }); 94 | } else { 95 | res.send({ 96 | code: 300, 97 | success: false, 98 | msg: "账号不存在,请注册", 99 | }); 100 | } 101 | }); 102 | }); 103 | 104 | // 注册 105 | router.post("/api/register", (req, res, next) => { 106 | // 获取数据 107 | let userName = req.body.userName; 108 | let email = req.body.email; 109 | let password = req.body.password; 110 | 111 | db.query(`SELECT * FROM user WHERE email = '${email}'`, (results, errors) => { 112 | if (errors != null && errors.length) { 113 | res.send({ 114 | code: 200, 115 | success: false, 116 | msg: "邮箱已存在", 117 | }); 118 | } else { 119 | // 引入token 120 | let jwt = require("jsonwebtoken"); 121 | // 用户信息 122 | let payload = { email: email }; 123 | // 口令 124 | let secret = "lijiale"; 125 | // 生成token 126 | let token = jwt.sign(payload, secret, { expiresIn: "2h" }); 127 | let imgUrl = `http://127.0.0.1:5173/public/images/user.jpeg`; // 默认头像 128 | const introduce = `该用户很懒,暂未设置简介`; // 默认简介内容 129 | let authority = "ordinary"; // 默认权限 130 | db.query( 131 | `insert into user(username,email,pwd,token,imgUrl,authority,introduce) values("${userName}","${email}","${password}","${token}","${imgUrl}","${authority}",'${introduce}')`, 132 | (result, error) => { 133 | res.send({ 134 | code: 200, 135 | success: true, 136 | msg: "注册成功", 137 | }); 138 | } 139 | ); 140 | } 141 | }); 142 | }); 143 | 144 | // 重置密码 145 | router.post("/api/resetPassword", (req, res) => { 146 | // 获取前端传入的input 147 | const email = req.body.email; 148 | const code = req.body.code; 149 | const newPassword = req.body.password; 150 | // 查询数据库 151 | db.query(`SELECT * FROM user WHERE email = '${email}'`, (error, result) => { 152 | if (result.length) { 153 | // 更改密码 154 | db.query(`UPDATE user SET pwd = "${newPassword}" WHERE useremail = "${email}"`, (err, resu) => { 155 | res.send({ 156 | status: 200, 157 | msg: "密码修改成功", 158 | success: true, 159 | }); 160 | }); 161 | } else { 162 | res.send({ 163 | status: 300, 164 | success: false, 165 | msg: "该账号不存在,请注册账号", 166 | }); 167 | } 168 | }); 169 | }); 170 | 171 | // 发送验证码 172 | router.post("/api/email", async (req, res) => { 173 | // 获取前端传入的input 174 | const email = req.body.email; 175 | // 生成随机验证码函数 及 邮箱验证正则 176 | const randomFns = () => { 177 | // 生成6位随机数 178 | let code = ""; 179 | for (let i = 0; i < 6; i++) { 180 | code += parseInt(Math.random() * 10); 181 | } 182 | return code; 183 | }; 184 | const code = randomFns(); 185 | const regEmail = /^([a-zA-Z0-9]+[_|\_|\.]?)*[a-zA-Z0-9]+@([a-zA-Z0-9]+[_|\_|\.]?)*[a-zA-Z0-9]+\.[a-zA-Z]{2,3}$/; //验证邮箱正则 186 | //发送邮件 187 | let nodeMail = nodemailer.createTransport({ 188 | service: "163", //类型163邮箱 189 | port: 465, // smtp端口 默认无需改动 190 | secure: true, //上文获取的secure 191 | auth: { 192 | user: "a3066684712@163.com", // 用户名 193 | pass: "YJEBFROVYOJIQURE", // SMTP授权码 194 | }, 195 | }); 196 | const mail = { 197 | from: `"落梦科技"`, // 发件人 198 | subject: "验证码", //邮箱主题 199 | to: email, //收件人,这里由post请求传递过来 200 | // 邮件内容,用html格式编写 201 | html: ` 202 |

您好!

203 |

您的验证码是:${code}

204 |

如果不是您本人操作,请无视此邮件

205 | `, 206 | }; 207 | await nodeMail.sendMail(mail, (err, info) => { 208 | if (!err) { 209 | res.send({ 210 | status: 200, 211 | msg: "验证码发送成功", 212 | code: code, 213 | }); 214 | } else { 215 | res.json({ 216 | status: 500, 217 | msg: "验证码发送失败,请稍后重试", 218 | }); 219 | } 220 | }); 221 | }); 222 | 223 | // 根据token获取用户数据 224 | router.get("/api/getItem", (req, res) => { 225 | // 获取传入的token 226 | let token = req.headers.token; 227 | // 解密 228 | let email = jwt.decode(token).email; 229 | db.query(`SELECT * FROM user WHERE email = '${email}'`, (results, error) => { 230 | res.send({ 231 | code: 200, 232 | success: true, 233 | data: { 234 | user: error[0], 235 | }, 236 | }); 237 | }); 238 | }); 239 | 240 | // 查询学生表 241 | router.get("/api/getStudent", (req, res) => { 242 | db.query(`SELECT * FROM studentinfo`, (error, results) => { 243 | // console.log(results); 244 | res.send({ 245 | code: 200, 246 | success: true, 247 | data: results, 248 | }); 249 | }); 250 | }); 251 | 252 | // 获取教师列表 253 | router.get("/api/getTeacherList", (req, res) => { 254 | db.query(`SELECT name FROM teacher`, (error, result) => { 255 | res.send({ 256 | code: 200, 257 | success: true, 258 | data: result, 259 | }); 260 | }); 261 | }); 262 | 263 | // 获取专业列表 264 | router.get("/api/getMajorData", (req, res) => { 265 | db.query(`SELECT * FROM major`, (error, result) => { 266 | res.send({ 267 | code: 200, 268 | success: true, 269 | data: result, 270 | }); 271 | }); 272 | }); 273 | // 获取班级列表 274 | router.get("/api/getClassData", (req, res) => { 275 | db.query(`SELECT class FROM classes`, (error, result) => { 276 | res.send({ 277 | code: 200, 278 | success: true, 279 | data: result, 280 | }); 281 | }); 282 | }); 283 | 284 | // 删除学生数据 285 | router.post("/api/delectStudent", (req, res) => { 286 | let stuNumber = req.body.stuNumber; 287 | db.query(`DELETE FROM studentinfo WHERE stuNumber = ${stuNumber}`, (results, errors) => { 288 | res.send({ 289 | code: 200, 290 | success: true, 291 | msg: "删除成功", 292 | }); 293 | }); 294 | }); 295 | 296 | // 更改学生数据 297 | router.post("/api/editStudent", (req, res) => { 298 | let parmas = req.body; 299 | // 更新学生数据 300 | db.query(usersql.updataStudent(parmas), (result, error) => { 301 | res.send({ 302 | code: 200, 303 | success: true, 304 | msg: "修改成功", 305 | }); 306 | }); 307 | }); 308 | 309 | // 添加学生数据 310 | router.post("/api/addStudentData", (req, res) => { 311 | let parmas = req.body; // 获取传入的数据 312 | db.query(`SELECT * FROM studentinfo WHERE stuNumber = '${parmas.stuNumber}'`, (error, result) => { 313 | if (result[0]) { 314 | res.send({ 315 | code: 200, 316 | success: false, 317 | msg: "该学生已存在", 318 | }); 319 | } else { 320 | db.query(usersql.addStudent(parmas), (errors, results) => { 321 | res.send({ 322 | code: 200, 323 | success: true, 324 | msg: "添加成功", 325 | }); 326 | }); 327 | } 328 | }); 329 | }); 330 | 331 | // 查询学生数据 332 | router.post("/api/searchStudent", (req, res) => { 333 | let parmas = req.body; 334 | db.query(usersql.searchStudent(parmas), (errors, results) => { 335 | res.send({ 336 | code: 200, 337 | success: true, 338 | data: results, 339 | }); 340 | }); 341 | }); 342 | 343 | // 获取教师全部信息 344 | router.get("/api/getTeacherData", teacherHandler.getTeacherData); 345 | // 删除教师信息 346 | router.post("/api/deleteTeacher", teacherHandler.deleteTeacher); 347 | // 获取部门列表 348 | router.get("/api/getDepartment", teacherHandler.getDepartment); 349 | // 获取职称列表 350 | router.get("/api/getProfessional", teacherHandler.getProfessional); 351 | // 更新教师信息 352 | router.post("/api/updateTeacher", teacherHandler.updateTeacher); 353 | // 添加教师消息 354 | router.post("/api/addTeacher", teacherHandler.addTeacher); 355 | // 搜索教师信息 356 | router.post("/api/searchTeacher", teacherHandler.searchTeacher); 357 | 358 | // 班级信息模块 359 | // 获取全部班级信息 360 | router.get("/api/getClass", classHandler.getClass); 361 | // 删除班级信息 362 | router.post("/api/delClass", classHandler.delClass); 363 | // 搜索班级信息 364 | router.post("/api/searchClass", classHandler.searchClass); 365 | // 获取学院信息 366 | router.get("/api/getCollegeList", classHandler.getCollegeList); 367 | // 添加班级信息 368 | router.post("/api/addClassData", classHandler.addClassData); 369 | // 更新班级信息 370 | router.post("/api/updateClassData", classHandler.updateClassData); 371 | 372 | // 修改个人信息 373 | router.post("/api/editMyInformation", function (req, res, next) { 374 | let parmas = req.body; 375 | db.query( 376 | `update user set username = '${parmas.name}',introduce = '${parmas.introduve}',imgUrl = '${parmas.imgUrl}' where id = ${parmas.id}`, 377 | (error, result) => { 378 | if (error) { 379 | res.send({ 380 | code: 500, 381 | success: false, 382 | msg: "服务器错误", 383 | }); 384 | } else { 385 | res.send({ 386 | code: 200, 387 | success: true, 388 | msg: "修改成功", 389 | }); 390 | } 391 | } 392 | ); 393 | }); 394 | 395 | // 权限管理 396 | router.post("/api/userData", authorityHandler.userData); 397 | // 更改权限 398 | router.post("/api/change_authority",authorityHandler.change_authority); 399 | module.exports = router; 400 | -------------------------------------------------------------------------------- /server/routes/nodemailer.js: -------------------------------------------------------------------------------- 1 | const nodemailer = require("nodemailer"); 2 | 3 | let nodeMail = nodemailer.createTransport({ 4 | service: "163", //类型163邮箱 5 | port: 465, // smtp端口 默认无需改动 6 | secure: true, //上文获取的secure 7 | auth: { 8 | user: "a3066684712@163.com", // 用户名 9 | pass: "YJEBFROVYOJIQURE", // SMTP授权码 10 | }, 11 | }); 12 | 13 | module.export = nodeMail; 14 | -------------------------------------------------------------------------------- /server/routes/users.js: -------------------------------------------------------------------------------- 1 | var express = require("express"); 2 | var router = express.Router(); 3 | 4 | /* GET users listing. */ 5 | router.get("/", function (req, res, next) { 6 | res.send("respond with a resource"); 7 | }); 8 | 9 | module.exports = router; 10 | -------------------------------------------------------------------------------- /server/views/error.ejs: -------------------------------------------------------------------------------- 1 |

<%= message %>

2 |

<%= error.status %>

3 |
<%= error.stack %>
4 | -------------------------------------------------------------------------------- /server/views/index.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | <%= title %> 5 | 6 | 7 | 8 |

<%= title %>

9 |

Welcome to <%= title %>

10 | 11 | 12 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 16 | 19 | -------------------------------------------------------------------------------- /src/assets/img/user.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kumudada/studentManager/b9b34c615f388ad30ba3cab2fd5eddaa396284a3/src/assets/img/user.jpeg -------------------------------------------------------------------------------- /src/assets/vue.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/auto-import.d.ts: -------------------------------------------------------------------------------- 1 | // Generated by 'unplugin-auto-import' 2 | export {} 3 | declare global { 4 | const EffectScope: typeof import('vue')['EffectScope'] 5 | const computed: typeof import('vue')['computed'] 6 | const createApp: typeof import('vue')['createApp'] 7 | const customRef: typeof import('vue')['customRef'] 8 | const defineAsyncComponent: typeof import('vue')['defineAsyncComponent'] 9 | const defineComponent: typeof import('vue')['defineComponent'] 10 | const effectScope: typeof import('vue')['effectScope'] 11 | const getCurrentInstance: typeof import('vue')['getCurrentInstance'] 12 | const getCurrentScope: typeof import('vue')['getCurrentScope'] 13 | const h: typeof import('vue')['h'] 14 | const inject: typeof import('vue')['inject'] 15 | const isProxy: typeof import('vue')['isProxy'] 16 | const isReactive: typeof import('vue')['isReactive'] 17 | const isReadonly: typeof import('vue')['isReadonly'] 18 | const isRef: typeof import('vue')['isRef'] 19 | const markRaw: typeof import('vue')['markRaw'] 20 | const nextTick: typeof import('vue')['nextTick'] 21 | const onActivated: typeof import('vue')['onActivated'] 22 | const onBeforeMount: typeof import('vue')['onBeforeMount'] 23 | const onBeforeRouteLeave: typeof import('vue-router')['onBeforeRouteLeave'] 24 | const onBeforeRouteUpdate: typeof import('vue-router')['onBeforeRouteUpdate'] 25 | const onBeforeUnmount: typeof import('vue')['onBeforeUnmount'] 26 | const onBeforeUpdate: typeof import('vue')['onBeforeUpdate'] 27 | const onDeactivated: typeof import('vue')['onDeactivated'] 28 | const onErrorCaptured: typeof import('vue')['onErrorCaptured'] 29 | const onMounted: typeof import('vue')['onMounted'] 30 | const onRenderTracked: typeof import('vue')['onRenderTracked'] 31 | const onRenderTriggered: typeof import('vue')['onRenderTriggered'] 32 | const onScopeDispose: typeof import('vue')['onScopeDispose'] 33 | const onServerPrefetch: typeof import('vue')['onServerPrefetch'] 34 | const onUnmounted: typeof import('vue')['onUnmounted'] 35 | const onUpdated: typeof import('vue')['onUpdated'] 36 | const provide: typeof import('vue')['provide'] 37 | const reactive: typeof import('vue')['reactive'] 38 | const readonly: typeof import('vue')['readonly'] 39 | const ref: typeof import('vue')['ref'] 40 | const resolveComponent: typeof import('vue')['resolveComponent'] 41 | const resolveDirective: typeof import('vue')['resolveDirective'] 42 | const shallowReactive: typeof import('vue')['shallowReactive'] 43 | const shallowReadonly: typeof import('vue')['shallowReadonly'] 44 | const shallowRef: typeof import('vue')['shallowRef'] 45 | const toRaw: typeof import('vue')['toRaw'] 46 | const toRef: typeof import('vue')['toRef'] 47 | const toRefs: typeof import('vue')['toRefs'] 48 | const triggerRef: typeof import('vue')['triggerRef'] 49 | const unref: typeof import('vue')['unref'] 50 | const useAttrs: typeof import('vue')['useAttrs'] 51 | const useCssModule: typeof import('vue')['useCssModule'] 52 | const useCssVars: typeof import('vue')['useCssVars'] 53 | const useLink: typeof import('vue-router')['useLink'] 54 | const useRoute: typeof import('vue-router')['useRoute'] 55 | const useRouter: typeof import('vue-router')['useRouter'] 56 | const useSlots: typeof import('vue')['useSlots'] 57 | const watch: typeof import('vue')['watch'] 58 | const watchEffect: typeof import('vue')['watchEffect'] 59 | const watchPostEffect: typeof import('vue')['watchPostEffect'] 60 | const watchSyncEffect: typeof import('vue')['watchSyncEffect'] 61 | } 62 | -------------------------------------------------------------------------------- /src/components/Login.vue: -------------------------------------------------------------------------------- 1 | 71 | 72 | 337 | 338 | 608 | -------------------------------------------------------------------------------- /src/components/common/Dialog.vue: -------------------------------------------------------------------------------- 1 | 25 | 26 | 69 | 70 | 161 | -------------------------------------------------------------------------------- /src/components/common/colorBack.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 154 | 155 | 184 | -------------------------------------------------------------------------------- /src/components/common/uploadImg.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 31 | 32 | -------------------------------------------------------------------------------- /src/components/contant/Control/userInfo.vue: -------------------------------------------------------------------------------- 1 | 21 | 22 | 43 | 44 | 121 | -------------------------------------------------------------------------------- /src/components/contant/Header.vue: -------------------------------------------------------------------------------- 1 | 12 | 20 | 21 | 85 | -------------------------------------------------------------------------------- /src/components/contant/LeftNav.vue: -------------------------------------------------------------------------------- 1 | 63 | 64 | 166 | 167 | 175 | -------------------------------------------------------------------------------- /src/components/contant/upLoad.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 107 | 108 | 109 | -------------------------------------------------------------------------------- /src/hooks/getUserData.js: -------------------------------------------------------------------------------- 1 | import { request } from "@/network/request.js"; 2 | import { useTestStore } from "@/store"; 3 | const Test = useTestStore(); 4 | 5 | export default function(): object{ 6 | let userC = reactive({ 7 | email: "", 8 | id: "", 9 | imgUrl: "", 10 | username: "", 11 | authority: "", 12 | }); 13 | // 请求用户数据 14 | let token = sessionStorage.getItem("token"); 15 | request( 16 | { 17 | url: "getItem", 18 | method: "get", 19 | headers: { 20 | token: token, 21 | }, 22 | }, 23 | (res) => { 24 | let userInfo = res.data.data.user; 25 | Test.user = userInfo; 26 | let { email, id, imgUrl, pwd, username, authority } = userInfo; 27 | // 储存数据 28 | userC.email = email; 29 | userC.id = id; 30 | userC.imgUrl = imgUrl; 31 | userC.username = username; 32 | userC.authority = authority; 33 | }, 34 | (err) => {} 35 | ); 36 | 37 | } 38 | 39 | -------------------------------------------------------------------------------- /src/hooks/showMsg.js: -------------------------------------------------------------------------------- 1 | import { ElMessage } from "element-plus"; 2 | // 信息提示 3 | let showMsg = { 4 | // 弹出错误信息 5 | errMsg(msg) { 6 | ElMessage({ 7 | showClose: true, 8 | message: msg, 9 | type: "error", 10 | }); 11 | }, 12 | successMsg(msg) { 13 | ElMessage({ 14 | showClose: true, 15 | message: msg, 16 | type: "success", 17 | }); 18 | }, 19 | }; 20 | export default showMsg; 21 | -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue' 2 | import {createPinia} from 'pinia' 3 | import router from "./router"; 4 | // import axios from '@/network/index'; 5 | const store = createPinia(); 6 | import VueWechatTitle from 'vue-wechat-title'; 7 | 8 | 9 | // 引入ElementPlus 10 | import ElementPlus from 'element-plus' 11 | import 'element-plus/dist/index.css' 12 | // 引入ElementPlus icon 13 | import * as ElementPlusIconsVue from '@element-plus/icons-vue' 14 | 15 | import App from './App.vue' 16 | let app = createApp(App) 17 | 18 | for (const [key, component] of Object.entries(ElementPlusIconsVue)) { 19 | app.component(key, component) 20 | } 21 | 22 | 23 | app.use(store) 24 | app.use(ElementPlus) 25 | app.use(router) 26 | app.use(VueWechatTitle) 27 | // app.config.globalProperties.axios = axios 28 | app.mount('#app') 29 | 30 | -------------------------------------------------------------------------------- /src/network/request.js: -------------------------------------------------------------------------------- 1 | import axios from "axios"; 2 | import router from "@/router"; 3 | import { ElLoading } from "element-plus"; 4 | 5 | let loadingInstance = ""; 6 | export function request(config, success, error) { 7 | // 创建一个axios实例 8 | const instance = axios.create({ 9 | baseURL: "http://127.0.0.1:3007/api", 10 | timeout: 3000, 11 | }); 12 | // 添加请求拦截器 13 | instance.interceptors.request.use( 14 | function (config) { 15 | // 在发送请求之前做些什么 16 | // 如果没有token转到登录界面 17 | if (sessionStorage.getItem("token") != null) { 18 | } else { 19 | function GoLogin() { 20 | router.push("/user/login"); 21 | } 22 | GoLogin(); 23 | return config; 24 | } 25 | return config; 26 | }, 27 | function (error) { 28 | // 对请求错误做些什么 29 | return Promise.reject(error); 30 | } 31 | ); 32 | // 添加响应拦截器 33 | instance.interceptors.response.use( 34 | function (response) { 35 | // 2xx 范围内的状态码都会触发该函数。 36 | // 对响应数据做点什么 37 | return response; 38 | }, 39 | function (error) { 40 | // 超出 2xx 范围的状态码都会触发该函数。 41 | // 对响应错误做点什么 42 | // console.log("响应错误"); 43 | return Promise.reject(error); 44 | } 45 | ); 46 | 47 | instance(config) 48 | .then((res) => { 49 | success(res); 50 | }) 51 | .catch((err) => { 52 | error(err); 53 | }); 54 | } 55 | -------------------------------------------------------------------------------- /src/router/index.js: -------------------------------------------------------------------------------- 1 | import { createRouter, createWebHistory } from "vue-router"; 2 | 3 | const routes = [ 4 | { 5 | path: "/", 6 | children: [ 7 | { 8 | path: "/", 9 | redirect: "control", 10 | }, 11 | { 12 | path: "control", 13 | name: "Control", // 控制面板 14 | component: () => import("@/views/Control/Control.vue"), 15 | meta: { 16 | title: "主页", 17 | }, 18 | }, 19 | // 学生信息模块 20 | { 21 | path: "/student/show", 22 | name: "showStudent", 23 | meta: { 24 | title: "学生信息管理系统", 25 | }, 26 | component: () => import("@/views/Student/showStudent.vue"), 27 | }, 28 | { 29 | path: "/student/add", 30 | name: "AddStudent", 31 | meta: { 32 | title: "学生信息管理系统", 33 | }, 34 | component: () => import("@/views/Student/AddStudent.vue"), 35 | }, 36 | { 37 | path: "/student/select", 38 | name: "SelectStudent", 39 | meta: { 40 | title: "学生信息管理系统", 41 | }, 42 | component: () => import("@/views/Student/SelectStudent.vue"), 43 | }, 44 | // 教师信息模块 45 | { 46 | path: "/teacher/show", 47 | name: "ShowTeacher", 48 | meta: { 49 | title: "学生信息管理系统", 50 | }, 51 | component: () => import("@/views/Teacher/ShowTeacher.vue"), 52 | }, 53 | { 54 | path: "/teacher/add", 55 | name: "AddTeacher", 56 | meta: { 57 | title: "学生信息管理系统", 58 | }, 59 | component: () => import("@/views/Teacher/AddTeacher.vue"), 60 | }, 61 | { 62 | path: "/teacher/select", 63 | name: "SelectTeacher", 64 | meta: { 65 | title: "学生信息管理系统", 66 | }, 67 | component: () => import("@/views/Teacher/SelectTeacher.vue"), 68 | }, 69 | // 班级模块 70 | { 71 | path: "/class/show", 72 | name: "ShowClass", 73 | meta: { 74 | title: "学生信息管理系统", 75 | }, 76 | component: () => import("@/views/Class/ClassShow.vue"), 77 | }, 78 | // 修改个人信息 79 | { 80 | path: "/my/edit", 81 | name: "editMy", 82 | meta: { 83 | title: "学生信息管理系统", 84 | }, 85 | component: () => import("@/views/My/editMy.vue"), 86 | }, 87 | //用户权限管理 88 | { 89 | path: "/authority/manager", 90 | name: "authority", 91 | meta: { 92 | title: "学生信息管理系统", 93 | }, 94 | component: () => import("@/views/authority/userManager.vue"), 95 | }, 96 | ], 97 | component: () => import("@/views/Home.vue"), 98 | }, 99 | { 100 | path: "/user/login", 101 | name: "login", 102 | meta: { 103 | title: "登录", 104 | }, 105 | component: () => import("@/views/Login.vue"), 106 | }, 107 | ]; 108 | 109 | // 创建路由 110 | const router = createRouter({ 111 | // history模式:createWebHistory 112 | history: createWebHistory(), 113 | routes, 114 | }); 115 | 116 | // 输出对象 117 | export default router; 118 | -------------------------------------------------------------------------------- /src/store/index.ts: -------------------------------------------------------------------------------- 1 | import {defineStore} from 'pinia' 2 | import {Names} from './store-name' 3 | 4 | export const useTestStore = defineStore(Names.TEST,{ 5 | state:()=>{ 6 | return { 7 | // 用户信息 8 | user:{}, 9 | student:[],//储存学生信息 10 | teacher:[],//储存教师信息, 11 | professionalList:[],// 职称列表 12 | departmentList:[],// 部门列表 13 | classList:[],// 班级列表 14 | ManagerList:[],// 教师列表 15 | MajorList:[],// 专业列表 16 | CollegeList:[],// 学院列表 17 | UserList:[], 18 | } 19 | }, 20 | // 类似computed 修饰一些值 21 | getters:{ 22 | 23 | }, 24 | // 类似methods 同步和异步都可以做 提交state 25 | actions:{ 26 | setTeacherData(value:any):void{ 27 | this.teacher = value; 28 | }, 29 | setClassData(value:any):void{ 30 | this.classList = value; 31 | }, 32 | setManagerList(value:any){ 33 | this.ManagerList = value; 34 | }, 35 | setMajorList(value:any):void{ 36 | this.MajorList = value; 37 | }, 38 | setCollegeList(value:any):void{ 39 | this.CollegeList = value; 40 | }, 41 | // 设置用户信息 42 | setUser(value: any):void{ 43 | this.user = value; 44 | }, 45 | // 设置用户表信息 46 | setUserList(value: any):void{ 47 | this.UserList = value; 48 | } 49 | } 50 | }) 51 | -------------------------------------------------------------------------------- /src/store/store-name.ts: -------------------------------------------------------------------------------- 1 | export const enum Names{ 2 | TEST = 'TEST' 3 | } -------------------------------------------------------------------------------- /src/style.css: -------------------------------------------------------------------------------- 1 | :root { 2 | font-family: Inter, Avenir, Helvetica, Arial, sans-serif; 3 | font-size: 16px; 4 | line-height: 24px; 5 | font-weight: 400; 6 | 7 | color-scheme: light dark; 8 | color: rgba(255, 255, 255, 0.87); 9 | background-color: #242424; 10 | 11 | font-synthesis: none; 12 | text-rendering: optimizeLegibility; 13 | -webkit-font-smoothing: antialiased; 14 | -moz-osx-font-smoothing: grayscale; 15 | -webkit-text-size-adjust: 100%; 16 | } 17 | 18 | * { 19 | margin: 0; 20 | padding: 0; 21 | box-sizing: border-box; 22 | } 23 | 24 | a { 25 | font-weight: 500; 26 | color: #646cff; 27 | text-decoration: none; 28 | } 29 | 30 | a:hover { 31 | color: #535bf2; 32 | } 33 | 34 | body { 35 | background-color: rgb(255, 255, 255); 36 | } 37 | 38 | h1 { 39 | font-size: 3.2em; 40 | line-height: 1.1; 41 | } -------------------------------------------------------------------------------- /src/views/Class/ClassShow.vue: -------------------------------------------------------------------------------- 1 | 143 | 144 | 409 | 410 | 477 | -------------------------------------------------------------------------------- /src/views/Control/Control.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 49 | 50 | 55 | -------------------------------------------------------------------------------- /src/views/Home.vue: -------------------------------------------------------------------------------- 1 | 26 | 27 | 84 | 85 | 159 | -------------------------------------------------------------------------------- /src/views/Login.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 8 | 9 | 26 | -------------------------------------------------------------------------------- /src/views/My/editMy.vue: -------------------------------------------------------------------------------- 1 | 32 | 33 | 136 | 137 | 155 | -------------------------------------------------------------------------------- /src/views/Student/AddStudent.vue: -------------------------------------------------------------------------------- 1 | 74 | 75 | 186 | 187 | 203 | -------------------------------------------------------------------------------- /src/views/Student/SelectStudent.vue: -------------------------------------------------------------------------------- 1 | 46 | 47 | 92 | 93 | 167 | -------------------------------------------------------------------------------- /src/views/Student/showStudent.vue: -------------------------------------------------------------------------------- 1 | 109 | 110 | 342 | 343 | 410 | -------------------------------------------------------------------------------- /src/views/Teacher/AddTeacher.vue: -------------------------------------------------------------------------------- 1 | 50 | 51 | 147 | 148 | 162 | -------------------------------------------------------------------------------- /src/views/Teacher/SelectTeacher.vue: -------------------------------------------------------------------------------- 1 | 46 | 47 | 87 | 88 | 162 | -------------------------------------------------------------------------------- /src/views/Teacher/ShowTeacher.vue: -------------------------------------------------------------------------------- 1 | 96 | 97 | 306 | 307 | 374 | -------------------------------------------------------------------------------- /src/views/authority/userManager.vue: -------------------------------------------------------------------------------- 1 | 60 | 61 | 151 | 152 | 218 | -------------------------------------------------------------------------------- /src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ESNext", 4 | "useDefineForClassFields": true, 5 | "module": "ESNext", 6 | "moduleResolution": "Node", 7 | "strict": true, 8 | "jsx": "preserve", 9 | "resolveJsonModule": true, 10 | "isolatedModules": true, 11 | "esModuleInterop": true, 12 | "lib": ["ESNext", "DOM"], 13 | "skipLibCheck": true, 14 | "noEmit": true, 15 | "baseUrl": ".", 16 | "paths": { 17 | "@/*": [ 18 | "src/*" 19 | ] 20 | }, 21 | }, 22 | "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"], 23 | "references": [{ "path": "./tsconfig.node.json" }] 24 | } 25 | -------------------------------------------------------------------------------- /tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "module": "ESNext", 5 | "moduleResolution": "Node", 6 | "allowSyntheticDefaultImports": true 7 | }, 8 | "include": ["vite.config.ts"] 9 | } 10 | -------------------------------------------------------------------------------- /vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import vue from '@vitejs/plugin-vue' 3 | import path from 'path'; 4 | // 引入 AutoImport 5 | import AutoImport from 'unplugin-auto-import/vite' 6 | // https://vitejs.dev/config/ 7 | export default defineConfig({ 8 | plugins: [vue(), 9 | // 配置AutoImport 10 | AutoImport({ 11 | imports:["vue","vue-router"], 12 | dts:'src/auto-import.d.ts' // 路径下自动生成文件夹存放全局指令 13 | }), 14 | ], 15 | resolve: { 16 | // 配置路径别名 17 | alias: { 18 | '@': path.resolve(__dirname, './src'), 19 | }, 20 | }, 21 | }) 22 | --------------------------------------------------------------------------------