lichong 9 months ago
parent
commit
3eb3d3e5a8
  1. 163
      api/main.py
  2. 5
      front/package.json
  3. 11
      front/src/api/login.js
  4. 20
      front/src/api/user.js
  5. 20
      front/src/router/index.js
  6. 24
      front/src/views/login.vue
  7. 200
      front/src/views/user.vue
  8. 2
      front/vite.config.js

163
api/main.py

@ -1,18 +1,122 @@
from flask import Flask
from flask import Flask, request, jsonify
from pymongo import MongoClient
from bson import ObjectId
import hashlib
import json
from flask import Flask, render_template, request
from flask_socketio import SocketIO, Namespace, emit
app = Flask(__name__)
client = MongoClient("mongodb://localhost:27019/")
db = client["back"]
collection = db["users"]
# sockitIo
socketio = SocketIO()
# 解决跨域问题
socketio.init_app(app, cors_allowed_origins="*")
# 用来存放客户端的 sid,即 session id
# 可以不单独定义字典存放 sid与namespace,flask-socketio 默认将 sid 存放在 room 中
socket_pool = {}
# Websocket 通过namespace 和 sid 标识具体客户端
# 第一个 Websocket 类
class MyCustomNamespace(Namespace):
name_space = "/msg"
# 连接成功调用的方法
def on_connect(self):
global socket_pool
print("connect..")
print("-----------------")
print(self.server.manager)
print(self.socketio)
print("-----------------")
print(request.namespace)
socket_pool[request.sid] = self.name_space
print(socket_pool)
# 断开连接调用的方法
def on_disconnect(self):
global socket_pool
print("disconnect...")
del socket_pool[request.sid]
print(socket_pool)
# 往 接收客户端标消息识为 'message' 的方法
def on_message(self, data):
print(data)
# 把消息发送到客户端的 'response' 标识的方法中, 一般是 on_response()
emit("response", "123", to=request.sid)
print("--------------")
print(request.sid)
print("--------------")
print(socketio.server.manager.rooms)
# 往 接收客户端标消息识为 'hello' 的方法
def on_hello(self, data):
print("hello world")
# 发送消息
def send(self, data):
# 向 namespace中的所有 Websocket 连接广播消息, namespace参数不能少, to缺省是广播模式
emit("response", data, namespace=self.name_space)
# 向 sid 所标识的客户端 单播
emit("response", data, namespace=self.name_space, to=request.sid)
# 为了详细展示不同类,这里就不做继承
# 第二个 Websocket 类
class MyCustomNamespace1(Namespace):
name_space = "/vedio"
def on_connect(self):
global socket_pool
print("connect..")
print(request.namespace)
socket_pool[request.sid] = self.name_space
print(socket_pool)
def on_disconnect(self):
global socket_pool
print("disconnect...")
del socket_pool[request.sid]
print(socket_pool)
def on_message(self, data):
print(data)
emit("response", "123")
self.send("asd")
# 发送消息
def send(self, data):
emit("response", data, namespace=self.name_space)
@app.route("/sendMsg")
def sendMsg():
for sid, namespace_value in socket_pool.items():
print(sid)
emit("response", "123456", namespace=namespace_value, to=sid)
print("ok")
return "ok"
# md5加密
def md5_encrypt(data):
md5 = hashlib.md5()
md5.update(data.encode("utf-8"))
return md5.hexdigest()
# 初始化数据
def initData():
isAdmin = collection.find_one({"isAdmin": 1, "isExit": 1})
if isAdmin is None:
# 学校名称、学校代号、专业名称、专业代号、年级、班级、学生姓名、学号、成绩、作弊情况(作弊类型、作弊时间、作弊图片)、考试类型、考试科目、考试时间段、是否是管理员、是否删除、创建时间、更新时间
# xuexiaomingcheng、xuexiaodaihao、zhuanyemingcheng、zhuanyedaihao、nianji、banji、xueshengxingming、xuehao、chengji、zuobiqingkuang(zuobileixing、zuobishijian、zuobitupian)、kaoshileixing、kaoshikemu、kaoshishijianduan、isAdmin、isExit、chuangjianshijian、gengxinshijian
admin = collection.find_one({"isAdmin": 1, "isExit": 1})
if admin is None:
# 学校名称、学校代号、专业名称、专业代号、年级、班级、学生姓名、学号、密码、成绩、作弊情况(作弊类型、作弊时间、作弊图片)、考试类型、考试科目、考试时间段、是否是管理员、是否删除、创建时间、更新时间
# xuexiaomingcheng、xuexiaodaihao、zhuanyemingcheng、zhuanyedaihao、nianji、banji、xueshengxingming、xuehao、mima、chengji、zuobiqingkuang(zuobileixing、zuobishijian、zuobitupian)、kaoshileixing、kaoshikemu、kaoshishijianduan、isAdmin、isExit、chuangjianshijian、gengxinshijian
user = {
"xuexiaomingcheng": "",
"xuexiaodaihao": "",
@ -22,6 +126,7 @@ def initData():
"banji": "",
"xueshengxingming": "老师",
"xuehao": "0000",
"mima": md5_encrypt("0000"),
"chengji": "",
"zuobiqingkuang": [],
"kaoshileixing": "",
@ -33,18 +138,46 @@ def initData():
"gengxinshijian": "",
}
collection.insert_one(user)
print("管理账号'老师'已被初始化新建")
else:
print(888, isAdmin)
print(f"管理账号'{admin['xueshengxingming']}'已存在")
# 判断是否是管理员
def isAdmin(id):
mongoId = ObjectId(id)
userObj = collection.find_one({"_id": mongoId, "isExit": 1})
# 检查 userObj 是否为 None
if userObj is None:
return False
# 默认返回 False 如果 isAdmin 字段不存在
adminBool = userObj.get("isAdmin", False)
return bool(adminBool)
# 测试
@app.route("/")
def hello():
return "Hello World!"
# 用户登录
@app.route("/userLogin", methods=["post"])
def login():
resData = request.data
# 检测是否有数据
if not resData:
return {"code": 200, "msg": "请填写信息后登录", "list": [], "hasError": True}
# 获取到POST过来的数据,转为json形式
userJson = json.loads(resData)
res = collection.find_one({"xuehao": userJson["xuehao"], "mima": userJson["mima"]})
if res is None:
return {"code": 200, "msg": "暂无此用户", "list": [], "hasError": True}
# serialized_data = []
# for item in data:
# item["_id"] = str(item["_id"]) # 将ObjectId转换为字符串
# serialized_data.append(item)
# 将ObjectId转换为字符串
res["_id"] = str(res["_id"])
return {"code": 200, "msg": "登陆成功", "list": [res], "hasError": False}
# 新增用户
@app.route("/insert")
@app.route("/addUser", methods=["post"])
def insert_data():
user = {"name": "John Doe", "age": 25, "city": "New York"}
collection.insert_one(user)
@ -52,7 +185,7 @@ def insert_data():
# 查询用户
@app.route("/query")
@app.route("/getUser", methods=["post"])
def query_data():
users = collection.find()
result = ""
@ -62,7 +195,7 @@ def query_data():
# 更新用户
@app.route("/update")
@app.route("/updateUser", methods=["post"])
def update_data():
query = {"name": "John Doe"}
new_data = {"$set": {"age": 30, "city": "San Francisco"}}
@ -71,7 +204,7 @@ def update_data():
# 删除用户
@app.route("/delete")
@app.route("/delUser", methods=["post"])
def delete_data():
query = {"name": "John Doe"}
collection.delete_one(query)
@ -80,4 +213,4 @@ def delete_data():
if __name__ == "__main__":
initData()
app.run()
app.run(debug=True)

5
front/package.json

@ -5,8 +5,7 @@
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
"build": "vite build"
},
"dependencies": {
"@element-plus/icons-vue": "^2.3.1",
@ -27,4 +26,4 @@
"@vitejs/plugin-vue": "^4.6.2",
"vite": "^5.0.8"
}
}
}

11
front/src/api/login.js

@ -1,11 +0,0 @@
import _axios from "@/plugins/axios";
//登录、注册
export function loginFun(data) {
return _axios({
url: `/v1/login`,
method: "POST",
data,
});
}

20
front/src/api/user.js

@ -1,11 +1,21 @@
import _axios from "@/plugins/axios";
//登录、注册
export function loginFun(data) {
return _axios({
url: `/v1/userLogin`,
method: "POST",
data: { ...data },
});
}
//增加用户
export function addUser(data) {
return _axios({
url: `/v1/addUser`,
method: "POST",
data,
data: { ...data, id: localStorage.getItem("userId") },
});
}
@ -14,15 +24,15 @@ export function delUser(data) {
return _axios({
url: `/v1/delUser`,
method: "POST",
data,
data: { ...data, id: localStorage.getItem("userId") },
});
}
//修改用户
export function getUser(data) {
export function updateUser(data) {
return _axios({
url: `/v1/updateUser`,
method: "POST",
data,
data: { ...data, id: localStorage.getItem("userId") },
});
}
//查找用户
@ -30,7 +40,7 @@ export function getUser(data) {
return _axios({
url: `/v1/getUser`,
method: "POST",
data,
data: { ...data, id: localStorage.getItem("userId") },
});
}

20
front/src/router/index.js

@ -6,24 +6,20 @@ const routes = [
path: "/",
name: "home",
component: home,
redirect: "/bug",
children: [{
path: "bug",
name: "bug",
component: () => import("../views/bug.vue"),
},
{
path: "user",
name: "user",
component: () => import("../views/user.vue"),
},]
redirect: "/user",
children: [
{
path: "user",
name: "user",
component: () => import("../views/user.vue"),
},]
},
{
path: "/login",
name: "login",
component: () => import("../views/login.vue"),
},
{ name: "重定向", path: "/:catchAll(.*)", redirect: "/bug" },
{ name: "重定向", path: "/:catchAll(.*)", redirect: "/login" },
];
// 创建路由实例

24
front/src/views/login.vue

@ -7,18 +7,19 @@
<el-button class="button" text @click="regist = false">
登录
</el-button>
<el-button class="button" text @click="regist = true">
<!-- <el-button class="button" text @click="regist = true">
注册
</el-button>
</el-button> -->
</div>
</template>
<div>
<el-form :model="regForm" label-suffix=":">
<el-form :model="regForm" label-suffix=":" @submit.prevent>
<el-form-item label="账号">
<el-input v-model="regForm.name" placeholder="请输入账号" />
</el-form-item>
<el-form-item label="密码">
<el-input v-model="regForm.password" type="password" placeholder="请输入密码" show-password />
<el-input v-model="regForm.password" type="password" placeholder="请输入密码" show-password
@keyup.enter="login" />
</el-form-item>
<el-form-item label="邮箱" v-if="regist">
<el-input v-model="regForm.email" placeholder="请输入邮箱" />
@ -40,7 +41,7 @@
<script>
import {
loginFun, //
} from "@/api/login";
} from "@/api/user";
import md5 from "md5"
export default {
name: "login",
@ -66,8 +67,8 @@ export default {
dealForm() {
return {
regist: this.regist,
name: this.regForm.name,
password: md5(this.regForm.password),
xuehao: this.regForm.name,
mima: md5(this.regForm.password),
email: this.regForm.email,
}
},
@ -75,11 +76,12 @@ export default {
async login() {
let formData = this.dealForm()
let res = await loginFun(formData)
console.log(999, res)
if (!res.hasError) {
ElMessage.success("登陆成功");
localStorage.setItem("userId", res.list._id)
localStorage.setItem("userName", res.list.name)
this.$router.push("/bug")
ElMessage.success(res.msg);
localStorage.setItem("userId", this.$_.get(res, ["list", 0, "_id"], ""))
localStorage.setItem("userName", this.$_.get(res, ["list", 0, "xueshengxingming"], ""))
this.$router.push("/user")
} else {
ElMessage.error(res.msg);
localStorage.clear()

200
front/src/views/user.vue

@ -12,12 +12,7 @@
</el-button>
</el-col>
<el-col :span="2">
<el-upload
:limit="1"
accept="text/csv"
:auto-upload="false"
:on-change="fileChange"
>
<el-upload :limit="1" accept="text/csv" :auto-upload="false" :on-change="fileChange">
<template #trigger>
<el-button type="primary">文件上传</el-button>
</template>
@ -25,11 +20,7 @@
</el-upload>
</el-col>
<el-col :span="6">
<el-input
v-model="searchValue"
placeholder="Please input email"
@keyup.enter="searchId"
>
<el-input v-model="searchValue" placeholder="Please input email" @keyup.enter="searchId">
<template #append>
<el-button @click="searchId" icon="Search" />
</template>
@ -37,36 +28,14 @@
</el-col>
</el-row>
<div v-loading="loading">
<vueTable
ref="userTableParent"
:refName="refName"
:tableHeader="tableHeader"
:tableData="tableData"
:currentPage="currentPage"
:pageSize="pageSize"
:pageSizes="pageSizes"
:total="total"
@detailInfo="detailInfo"
@editInfo="editInfo"
@handleSizeChange="handleSizeChange"
@handleCurrentChange="handleCurrentChange"
>
<vueTable ref="userTableParent" :tableHeader="tableHeader" :tableData="tableData" @detailInfo="detailInfo"
@editInfo="editInfo">
</vueTable>
</div>
<el-dialog
v-model="addDialog.show"
:title="addDialog.title"
width="80%"
draggable
:close-on-click-modal="formDisabled"
>
<changeItem
:formData="formData"
:formDisabled="formDisabled"
:type="addDialog.type"
:formHeader="formHeaderLocal"
>
<el-dialog v-model="addDialog.show" :title="addDialog.title" width="80%" draggable
:close-on-click-modal="formDisabled">
<changeItem :formData="formData" :formDisabled="formDisabled" :type="addDialog.type" :formHeader="formHeaderLocal">
</changeItem>
<template #footer v-if="!formDisabled">
<div class="dialog-footer">
@ -83,26 +52,135 @@ import md5 from "md5";
import Papa from "papaparse";
import vueTable from "../component/table.vue";
import changeItem from "../component/changeItem.vue";
import _ from "lodash";
import {
getUser, //user
addUser, //user
delUser, //user
updateUser, //user
getUser, //user
} from "@/api/user";
export default {
name: "user",
components: { vueTable, changeItem },
data() {
return {
refName: "userTable",
_: _,
loading: false,
tableHeader: [
{ prop: "name", label: "name" },
{ prop: "password", label: "password", type: "password" },
{ prop: "email", label: "email" },
{ prop: "loginTime", label: "loginTime", type: "time", minWidth: 120 },
{ prop: "create_at", label: "create_at", type: "time", minWidth: 120 },
{ prop: "update_at", label: "update_at", type: "time", minWidth: 120 },
localComponent: [
{
prop: "xuexiaomingcheng",
label: "学校名称",
type: "text",
tableShow: true,
formShow: true
},
{
prop: "xuexiaodaihao",
label: "学校代号",
type: "text",
tableShow: true,
formShow: true
},
{
prop: "zhuanyemingcheng",
label: "专业名称",
type: "text",
tableShow: true,
formShow: true
},
{
prop: "zhuanyedaihao",
label: "专业代号",
type: "text",
tableShow: true,
formShow: true
},
{
prop: "nianji",
label: "年级",
type: "text",
tableShow: true,
formShow: true
},
{
prop: "banji",
label: "班级",
type: "text",
tableShow: true,
formShow: true
},
{
prop: "xueshengxingming",
label: "学生姓名",
type: "text",
tableShow: true,
formShow: true
},
{
prop: "xuehao",
label: "学号",
type: "text",
tableShow: true,
formShow: true
},
{
prop: "mima",
label: "密码",
type: "text",
tableShow: true,
formShow: true
},
{
prop: "chengji",
label: "成绩",
type: "text",
tableShow: true,
formShow: true
},
{
prop: "zuobiqingkuang",
label: "作弊情况",
type: "text",
tableShow: true,
formShow: true
},
{
prop: "kaoshileixing",
label: "考试类型",
type: "text",
tableShow: true,
formShow: true
},
{
prop: "kaoshikemu",
label: "考试科目",
type: "text",
tableShow: true,
formShow: true
},
{
prop: "kaoshishijianduan",
label: "考试时间段",
type: "datetimerange",
tableShow: true,
formShow: true
},
{
prop: "chuangjianshijian",
label: "创建时间",
type: "text",
tableShow: false,
formShow: false
},
{
prop: "gengxinshijian",
label: "更新时间",
type: "text",
tableShow: false,
formShow: false
},
],
tableHeader: [],
tableData: [],
currentPage: 1,
pageSize: 16,
@ -168,32 +246,24 @@ export default {
watch: {},
computed: {},
async mounted() {
this.dealTableHeader()
this.dealFormHeader()
await this.init();
},
beforeUnmount() {},
beforeUnmount() { },
methods: {
async init(params = {}, isReload = true) {
if (isReload) {
this.searchValue = "";
}
dealTableHeader() {
this.tableData = _.filter(this.localComponent, o => o.tableShow)
},
dealFormHeader() {
this.formHeader = _.filter(this.localComponent, o => o.formShow)
},
async init(params = {}) {
this.loading = true;
let res = await getUser({
subType: "get",
returnData: [
"name",
"email",
"allowRegist",
"loginTime",
"create_at",
"update_at",
],
pageSize: this.pageSize,
currentPage: this.currentPage,
...params,
});
this.tableData = res.list;
this.total = res.count;
this.loading = false;
},
async addUserData() {

2
front/vite.config.js

@ -30,7 +30,7 @@ export default defineConfig({
port: 3000,
proxy: {
"/v1": {
target: "http://127.0.0.1:5000/v1",
target: "http://127.0.0.1:5000",
changeOrigin: true,
rewrite: (path) => path.replace(/^\/v1/, ""),
},

Loading…
Cancel
Save