文章目录
一:前置操作
https://blog.csdn.net/Abraxs/article/details/139552598?spm=1001.2014.3001.5501
项目结构:
二:登录页面
主要流程说明
登录交互逻辑:
Login.vue 点击登录发送请求 api /api/base/login 然后localStorage存储登录信息
关键代码:
前端
vbnet
const submitForm = () => {
loginForm.value.validate((valid) => {
if (valid) {
axios.post("/api/base/login",
{
jobNumber: form.username,
pwd: form.password
}
).then(resp => {
debugger
if (resp.data.code == 500) {
alert(resp.data.message)
}
if (resp.data.code == 200) {
localStorage.setItem('id', resp.data.data.id)
localStorage.setItem('username', resp.data.data.name)
router.push('/page')
}
})
// Handle login logic here
} else {
alert('登录失败');
}
});
后端
vbnet
@ApiOperation(value = "教师登录", notes = "教师登录", produces = MediaType.APPLICATION_JSON_VALUE)
@PostMapping("/login")
public R<BaseTeacher> login(@RequestBody LoginReq req){
BaseTeacher back = baseTeacherService.getOne(new LambdaQueryWrapper<BaseTeacher>()
.eq(BaseTeacher::getJobNumbers, req.getJobNumber())
.eq(BaseTeacher::getPwd, req.getPwd()));
if (ObjectUtils.isEmpty(back)) {
return R.error("教师不存在");
}
return R.ok( "登录成功", back);
}
运行截图
前端代码Login.vue
bash
<template>
<div>
<el-form ref="loginForm" :model="form" :rules="rules">
<div class="title-container" style="margin-top: 20px;">
<h3 class="title">学生管理平台</h3>
</div>
<el-form-item prop="username">
<el-input v-model="form.jobNumber" placeholder="登录工号"></el-input>
</el-form-item>
<el-form-item prop="password">
<el-input type="password" v-model="form.password" placeholder="登录密码"></el-input>
</el-form-item>
<el-form-item>
<el-button @click="submitForm">Login</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script>
import { ref, reactive } from 'vue';
import { useRouter } from 'vue-router';
import axios from "axios";
export default {
name: 'Login',
setup() {
const showAlertFlag = ref(false);
const alertMessage = ref('');
const loginForm = ref(null);
const form = reactive({
jobNumber: '',
password: ''
});
const rules = {
jobNumber: [
{ required: true, message: 'Please input username', trigger: 'blur' }
],
password: [
// { required: true, message: 'Please input password', trigger: 'blur' },
// { min: 6, message: 'Password length should be greater than 6', trigger: 'blur' }
]
};
const router = useRouter();
const submitForm = () => {
loginForm.value.validate((valid) => {
if (valid) {
axios.post("/api/base/login",
{
jobNumber: form.jobNumber,
pwd: form.password
}
).then(resp => {
debugger
if (resp.data.code == 500) {
alert(resp.data.message)
}
if (resp.data.code == 200) {
localStorage.setItem('id', resp.data.data.id)
localStorage.setItem('username', resp.data.data.name)
showAlertFlag.value = true;
window.alert(resp.data.message);
showAlertFlag.value = false;
router.push('/page')
}
})
// Handle login logic here
} else {
alert('登录失败');
}
});
};
return {
loginForm,
form,
rules,
submitForm,
alertMessage
};
}
};
</script>
三:列表页面
交互逻辑:涉及页面Page02.vue (登录成功跳转学生选课页面)
登录成功跳转学生选课页面同时发送请求 /api/baseStudentCourse/list
携带当前localStorage登录用户信息
关键代码:
vbnet
前端:
const tableData = ref([]); // 使用ref来创建响应式数据
onMounted(async () => {
const response = await axios.post("/api/baseStudentCourse/list", {
id: localStorage.getItem('id')});
tableData.value = response.data.data; // 将请求结果赋值给响应式数据
});
后端:
@ApiOperation(value = "列表", notes = "列表", produces = MediaType.APPLICATION_JSON_VALUE)
@PostMapping("/list")
public R<List<BaseStudentCourse>> list(@RequestBody CommonReqById req){
// 该教师所绑定课程
List<BaseCourse> baseCourses = baseCourseService.list(new LambdaQueryWrapper<BaseCourse>()
.eq(BaseCourse::getTeacherId, req.getId()));
// 判断是否为空,空择返回空数组
if (CollectionUtils.isEmpty(baseCourses)) {
return R.ok(new ArrayList<>());
}
// 教师绑定课程ids
Set<Long> courseIds = baseCourses.stream().map(BaseCourse::getId).collect(Collectors.toSet());
// 传入教师绑定课程参数聚合查询所教课程
List<BaseStudentCourse> baseTeacherCourses = baseStudentCourseService.list(new LambdaQueryWrapper<BaseStudentCourse>()
.in(BaseStudentCourse::getCourseId, courseIds));
if (CollectionUtils.isEmpty(baseTeacherCourses)) {
return R.ok(new ArrayList<>(0));
}
Map<Long, String> mapCourse = baseCourseService.list().stream()
.collect(Collectors.toMap(BaseCourse::getId, BaseCourse::getName));
Map<Long, String> mapTeacher = baseTeacherService.list().stream()
.collect(Collectors.toMap(BaseTeacher::getId, BaseTeacher::getName));
Map<Long, BaseStudent> mapStudent = baseStudentService.list().stream()
.collect(Collectors.toMap(BaseStudent::getId, Function.identity()));
baseTeacherCourses.forEach(v -> {
v.setCourseName(mapCourse.get(v.getCourseId()));
v.setTeacherName(mapTeacher.get(req.getId()));
v.setStudentName(mapStudent.get(v.getStudentId()).getName());
v.setMajorName(mapStudent.get(v.getStudentId()).getMajorId());
});
return R.ok(baseTeacherCourses);
}
运行截图
##页面Page02.vue代码
vbnet
<template>
<div class="container">
<div class="title-container" style="margin-top: 20px;">
<h3 class="title">学生管理平台</h3>
</div>
<div class="user-info">
<div class="buttons">
<el-button size="mini" class="user-button primary" @click="handleAddCourse()" :closeCourseModal = "closeModal">添加选课</el-button>
            
            
            
            
<span><b>当前用户:</b></span>{{currentUser}}
<el-button size="mini" class="user-button" @click="resetUser()">注销当前用户</el-button>
</div>
<!-- <h5 class="user-name">当前登录用户:{{ localStorageValue }}</h5>-->
</div>
<el-table :data="tableData">
<el-table-column prop="id" label="编码" width="100"></el-table-column>
<el-table-column prop="studentId" label="学号" width="100"></el-table-column>
<el-table-column prop="studentName" label="学生" width="100"></el-table-column>
<el-table-column prop="courseName" label="课程" width="180"></el-table-column>
<el-table-column prop="majorName" label="专业" width="100"></el-table-column>
<el-table-column prop="score" label="分数" width="100"></el-table-column>
<el-table-column prop="teacherName" label="教师" width="100"></el-table-column>
<el-table-column label="操作" width="380">
<template #default="{ row, $index }">
<el-button size="mini" type="warning" @click="editItem(row, $index)" @updateData="handleData" >成绩修改</el-button>
<el-button size="mini" type="warning" @click="addItem(row, $index)" @updateData="handleData" >成绩添加</el-button>
<el-button size="mini" type="danger" @click="handleDeleteCourse(row, $index)" @updateData="handleData" >删除选课</el-button>
</template>
</el-table-column>
</el-table>
<ModalEdit v-model:visible="showModal" :edit-data="editData" :show-flag = "showFlag" @refreshData="refreshData" />
<ModalCourseAdd v-model:visible="showModalAddCourse" @refreshData="refreshData" />
</div>
</template>
<script setup>
import { useRouter } from 'vue-router';
import {onMounted, ref} from 'vue';
import axios from "axios";
import ModalEdit from "./ModalEdit.vue";
import ModalCourseAdd from "./ModalCourseAdd.vue";
const tableData = ref([]); // 使用ref来创建响应式数据
onMounted(async () => {
const response = await axios.post("/api/baseStudentCourse/list", {
id: localStorage.getItem('id')});
tableData.value = response.data.data; // 将请求结果赋值给响应式数据
});
const currentUser = localStorage.getItem("username");
const showModal = ref(false);
const showModalAddCourse = ref(false);
const editData = ref(null);
const showFlag = ref(String);
const editItem = (item, index) => {
editData.value = item;
showModal.value = true;
showFlag.value = '成绩修改';
};
const addItem = (item, index) => {
editData.value = item;
showModal.value = true;
showFlag.value = '成绩添加';
};
const closeModal = () => {
showModalAddCourse.value = false
};
const handleData = () => {
console.log("Page02 handleData")
const response = axios.post("/api/baseStudentCourse/list", {
id: localStorage.getItem('id')});
tableData.value = response.data.data; // 将请求结果赋值给响应式数据;
console.log(response)
};
const router = useRouter();
const resetUser = () => {
// 编辑逻辑
const key = 'id'; // 替换为你需要获取的localStorage的key
const value = localStorage.getItem(key);
// 如果需要解析JSON,可以在这里进行解析
try {
axios.post("/api/base/reset", {
id: localStorage.getItem('id')
}).then(resp => {
if (resp.data.code === 200) {
alert(resp.data.message);
localStorage.removeItem(localStorage.getItem('id'))
router.push('/')
} else {
alert(resp.data.message);
}
})
} catch (error) {
console.error(error);
// 处理错误
}
};
// 添加选课
const handleAddCourse = () => {
debugger
// editData.value = item;
showModalAddCourse.value = true;
};
// 删除选课
const handleDeleteCourse = (row, index) => {
console.log(row)
axios.post("/api/baseStudentCourse/delete", {
id: row.id
}).then(resp => {
if (resp.data.code === 200) {
alert(resp.data.message);
axios.post("/api/baseStudentCourse/list", {
id: localStorage.getItem('id')}).then(resp => {
if (resp.data.code === 200) {
tableData.value = resp.data.data
} else {
alert(resp.data.message);
}
})
} else {
alert(resp.data.message);
}
})
};
const updateList = (updatedItem) => {
// 假设使用index来更新list,但这种方式不推荐,如果数据顺序改变会有问题
const index = tableData.value.findIndex(item => item.id === updatedItem.id);
tableData.value.splice(index, 1, updatedItem);
showModal.value = false;
};
// 成绩修改
const refreshData = () => {
axios.post("/api/baseStudentCourse/list", {
id: localStorage.getItem('id')}).then(resp => {
if (resp.data.code === 200) {
tableData.value = resp.data.data
} else {
alert(resp.data.message);
}
})
showModal.value = false;
showModalAddCourse.value = false;
} ;
// console.log(""")
</script>