前端登录增加权限认识,增加学生端试卷中心

main
yuan 1 week ago
parent d8cf875a85
commit 9ba848b72c

@ -2,6 +2,8 @@ package com.ruoyi.web.controller.system;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import com.ruoyi.system.service.ISysRoleService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
@ -27,6 +29,9 @@ import com.ruoyi.system.service.ISysMenuService;
@RestController @RestController
public class SysLoginController public class SysLoginController
{ {
@Autowired
private ISysRoleService roleService;
@Autowired @Autowired
private SysLoginService loginService; private SysLoginService loginService;
@ -48,13 +53,12 @@ public class SysLoginController
@PostMapping("/login") @PostMapping("/login")
public AjaxResult login(@RequestBody LoginBody loginBody) public AjaxResult login(@RequestBody LoginBody loginBody)
{ {
System.out.println("==============="+loginBody.getUuid());
AjaxResult ajax = AjaxResult.success(); AjaxResult ajax = AjaxResult.success();
// 生成令牌 // 生成令牌
String token = loginService.login(loginBody.getUsername(), loginBody.getPassword(), loginBody.getCode(), String token = loginService.login(loginBody.getUsername(), loginBody.getPassword(), loginBody.getCode(),
loginBody.getUuid()); loginBody.getUuid());
ajax.put(Constants.TOKEN, token); ajax.put(Constants.TOKEN, token);
System.out.println("======="+ajax);
return ajax; return ajax;
} }
@ -81,6 +85,11 @@ public class SysLoginController
ajax.put("user", user); ajax.put("user", user);
ajax.put("roles", roles); ajax.put("roles", roles);
ajax.put("permissions", permissions); ajax.put("permissions", permissions);
Long roleId = roleService.getRoleByUserId(user.getUserId());
roleService.checkRoleDataScope(roleId);
ajax.put("role", roleService.selectRoleById(roleId).getRoleName());
System.out.println("------------------"+ajax);
return ajax; return ajax;
} }

@ -2,6 +2,8 @@ package com.ruoyi.web.controller.system;
import java.util.List; import java.util.List;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
@ -259,4 +261,5 @@ public class SysRoleController extends BaseController
ajax.put("depts", deptService.selectDeptTreeList(new SysDept())); ajax.put("depts", deptService.selectDeptTreeList(new SysDept()));
return ajax; return ajax;
} }
} }

@ -63,7 +63,6 @@ public class SysLoginService
*/ */
public String login(String username, String password, String code, String uuid) public String login(String username, String password, String code, String uuid)
{ {
System.out.println("======"+uuid);
// 验证码校验 // 验证码校验
validateCaptcha(username, code, uuid); validateCaptcha(username, code, uuid);
// 登录前置校验 // 登录前置校验
@ -179,4 +178,13 @@ public class SysLoginService
sysUser.setLoginDate(DateUtils.getNowDate()); sysUser.setLoginDate(DateUtils.getNowDate());
userService.updateUserProfile(sysUser); userService.updateUserProfile(sysUser);
} }
/**
*
*
* @
*/
public boolean checkrole(){
return true;
}
} }

@ -1,6 +1,8 @@
package com.ruoyi.system.mapper; package com.ruoyi.system.mapper;
import java.util.List; import java.util.List;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ruoyi.common.core.domain.entity.SysRole; import com.ruoyi.common.core.domain.entity.SysRole;
/** /**
@ -104,4 +106,5 @@ public interface SysRoleMapper
* @return * @return
*/ */
public int deleteRoleByIds(Long[] roleIds); public int deleteRoleByIds(Long[] roleIds);
} }

@ -59,4 +59,9 @@ public interface SysUserRoleMapper
* @return * @return
*/ */
public int deleteUserRoleInfos(@Param("roleId") Long roleId, @Param("userIds") Long[] userIds); public int deleteUserRoleInfos(@Param("roleId") Long roleId, @Param("userIds") Long[] userIds);
/**
* userid
*/
public Long getRoleByUserId(Long userId);
} }

@ -170,4 +170,9 @@ public interface ISysRoleService
* @return * @return
*/ */
public int insertAuthUsers(Long roleId, Long[] userIds); public int insertAuthUsers(Long roleId, Long[] userIds);
/**
* userid
*/
public Long getRoleByUserId(Long userId);
} }

@ -424,4 +424,9 @@ public class SysRoleServiceImpl implements ISysRoleService
} }
return userRoleMapper.batchUserRole(list); return userRoleMapper.batchUserRole(list);
} }
@Override
public Long getRoleByUserId(Long userId){
return userRoleMapper.getRoleByUserId(userId);
}
} }

@ -148,5 +148,5 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
#{roleId} #{roleId}
</foreach> </foreach>
</delete> </delete>
</mapper> </mapper>

@ -41,4 +41,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
#{userId} #{userId}
</foreach> </foreach>
</delete> </delete>
<select id="getRoleByUserId" parameterType="Long" resultType="Long">
select role_id from sys_user_role where user_id=#{userId}
</select>
</mapper> </mapper>

@ -0,0 +1,45 @@
<template>
<el-menu :default-openeds="['1', '3']" style="min-height: 100%; overflow-x: hidden"
background-color="rgb(48,65,86)"
text-color="#fff"
active-text-color="#ffd04b"
:collapse-transition="false"
:collapse="isCollapse"
router
>
<div style="height: 60px;line-height: 60px;text-align: center">
<img src="../assets/logo.png" alt="" style="width: 20px;position: relative;top: 5px;margin-right: 5px">
<b style="color: white" v-show="logoTextShow">线</b>
</div>
<el-menu-item index="1">
<template slot="title"><i class="el-icon-house"></i>
<span slot="title">主页</span>
</template>
</el-menu-item>
<el-menu-item index="/student/exam">
<template slot="title"><i class="el-icon-message"></i>
<span slot="title">试卷中心</span>
</template>
</el-menu-item>
<el-menu-item index="3">
<template slot="title"><i class="el-icon-message"></i>
<span slot="title">考试记录</span>
</template>
</el-menu-item>
</el-menu>
</template>
<script>
export default {
name: "Aside",
props: {
isCollapse: Boolean,
logoTextShow: Boolean
},
}
</script>
<style scoped lang="scss">
</style>

@ -0,0 +1,32 @@
<template>
<div style="font-size: 12px;line-height: 60px;display: flex">
<div style="flex: 1;font-size: 20px">
<span :class="collapseBtnClass" style="cursor:pointer" @click="collapse"></span>
</div>
<el-dropdown style="width: 70px; cursor: pointer">
<span>王小虎</span>
<i class="el-icon-arrow-down" style="margin-left: 5px"></i>
<!-- <i class="el-icon-setting" style="margin-right: 15px"></i>-->
<el-dropdown-menu slot="dropdown">
<el-dropdown-item>个人信息</el-dropdown-item>
<el-dropdown-item>退出</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
</template>
<script>
export default {
name: "Header",
props:{
collapseBtnClass:String,
collapse:Boolean,
}
}
</script>
<style scoped lang="scss">
</style>

@ -3,20 +3,35 @@
<div class="login-box"> <div class="login-box">
<h2 style="color: white">登录</h2> <h2 style="color: white">登录</h2>
<form @submit.prevent="login"> <form @submit.prevent="login">
<!-- Dropdown for User Role -->
<div class="input-group">
<i class="fas fa-users"></i>
<select v-model="role" required>
<option value="teacher">老师</option>
<option value="student">学生</option>
</select>
</div>
<!-- Username Field -->
<div class="input-group"> <div class="input-group">
<i class="fas fa-user"></i> <i class="fas fa-user"></i>
<input type="text" v-model="username" placeholder="用户名" required /> <input type="text" v-model="username" placeholder="用户名" required />
</div> </div>
<!-- Password Field -->
<div class="input-group"> <div class="input-group">
<i class="fas fa-lock"></i> <i class="fas fa-lock"></i>
<input type="password" v-model="password" placeholder="密码" required /> <input type="password" v-model="password" placeholder="密码" required />
</div> </div>
<!-- Captcha Field -->
<div class="input-group captcha-group"> <div class="input-group captcha-group">
<i class="fas fa-shield-alt"></i> <i class="fas fa-shield-alt"></i>
<input type="text" v-model="code" placeholder="验证码" required /> <input type="text" v-model="code" placeholder="验证码" required />
<!-- 显示验证码图片 -->
<img :src="captchaUrl" @click="refreshCaptcha" alt="验证码" class="captcha-image" style="margin-top: 5px"/> <img :src="captchaUrl" @click="refreshCaptcha" alt="验证码" class="captcha-image" style="margin-top: 5px"/>
</div> </div>
<!-- Login Button -->
<button type="submit" class="login-button">登录</button> <button type="submit" class="login-button">登录</button>
</form> </form>
<p>没有账户<router-link to="/register">注册</router-link></p> <p>没有账户<router-link to="/register">注册</router-link></p>
@ -24,18 +39,18 @@
</div> </div>
</template> </template>
<script> <script>
import axios from 'axios'; import axios from 'axios';
import {mapActions} from "vuex"; import { mapActions } from "vuex";
export default { export default {
data() { data() {
return { return {
role: 'student', // Default value, either 'teacher' or 'student'
username: '', username: '',
password: '', password: '',
code: '', // code: '', //
captchaUrl: '' ,// URL captchaUrl: '', // URL
uuid: '' uuid: ''
}; };
}, },
@ -45,7 +60,6 @@ export default {
.then(response => response.json()) // JSON .then(response => response.json()) // JSON
.then(data => { .then(data => {
if (data.code === 200) { if (data.code === 200) {
// Base64 URL
this.captchaUrl = `data:image/jpeg;base64,${data.img}`; this.captchaUrl = `data:image/jpeg;base64,${data.img}`;
this.uuid = data.uuid; // uuid this.uuid = data.uuid; // uuid
} else { } else {
@ -59,51 +73,68 @@ export default {
async login() { async login() {
try { try {
const response = await axios.post('http://localhost:8080/login', { const response = await axios.post('http://localhost:8080/login', {
role: this.role, // Send the selected role (teacher or student)
username: this.username, username: this.username,
password: this.password, password: this.password,
code: this.code, // code: this.code, // Send the captcha
uuid: this.uuid, uuid: this.uuid,
}, { }, {
headers: { headers: {
'Content-Type': 'application/json', // 'Content-Type': 'application/json',
} }
}); });
if (response.data.code === 200) { if (response.data.code === 200) {
console.log('登录成功', response.data);
// token response.data.token
const token = response.data.token;
// token Vuex localStorage const res = await axios.get('http://localhost:8080/getInfo',{
this.setToken(token); // 使 Vuex action token method: 'GET',
headers: {
// // 'Authorization': response.data.token,
// this.$router.push('/HomeView'); 'Content-Type': 'application/json',
// }});
window.location.href = 'http://localhost:8081'; if(res.data.code==200){
console.log('登录成功,用户角色:', res.data);
const token = response.data.token;
this.setToken(token); // Store token using Vuex action
if (res.data.role === '超级管理员') {
//
window.location.href = res.data.role === '老师' ? 'http://localhost:8082' : 'http://localhost:8081';
} else if (res.data.role === role) {
//
if (role === '老师') {
window.location.href = 'http://localhost:8082';
} else if (role === '学生') {
window.location.href = 'http://localhost:8081';
}
} else {
alert('该角色无权限');
this.refreshCaptcha();
}
}else{
alert('登录失败,请重试');
this.refreshCaptcha(); // Handle error and refresh captcha
}
} else { } else {
console.error('登录失败', response.data.msg); console.error('登录失败', response.data.msg);
this.refreshCaptcha(); // alert('登录失败,' + response.data.msg);
this.refreshCaptcha(); // Refresh captcha on failure
} }
} catch (error) { } catch (error) {
console.error('登录失败', error); console.error('登录失败', error);
this.refreshCaptcha(); // alert('登录失败,' + error);
this.refreshCaptcha(); // Handle error and refresh captcha
} }
}, },
// Vuex action // Vuex action
...mapActions(['setToken']), ...mapActions(['setToken']),
// // Refresh captcha image
refreshCaptcha() { refreshCaptcha() {
this.fetchCaptcha(); this.fetchCaptcha();
} }
}, },
mounted() { mounted() {
this.fetchCaptcha(); // this.fetchCaptcha(); // Get captcha when component is mounted
//
this.refreshCaptcha();
} }
}; };
</script> </script>
@ -139,13 +170,14 @@ export default {
color: #aaa; color: #aaa;
} }
.input-group input { .input-group input,
.input-group select {
width: 100%; width: 100%;
padding: 10px 10px 10px 30px; padding: 10px 10px 10px 30px;
border: none; border: none;
border-radius: 4px; border-radius: 4px;
background-color: #465675; background-color: #e8f0fe; /* Set background color to #e8f0fe */
color: #fff; color: #333; /* Set text color to dark for readability */
} }
.captcha-image { .captcha-image {
@ -170,3 +202,4 @@ export default {
background-color: #0056b3; background-color: #0056b3;
} }
</style> </style>

@ -8,6 +8,11 @@ import store from '../store'; // 引入 Vuex store
Vue.use(VueRouter); Vue.use(VueRouter);
const routes = [ const routes = [
{
path:'/student/exam',
component: () => import(/* webpackChunkName: "about" */ '../views/Student/Exam.vue'),
meta: {requiresAuth: true}
},
{ {
path: '/', path: '/',
name: 'home', name: 'home',

@ -1,85 +1,12 @@
<template> <template>
<el-container style="min-height: 100vh"> <el-container style="min-height: 100vh">
<el-aside :width="sideWidth+'px'" style="background-color: rgb(238, 241, 246); box-shadow: 2px 0 6px rgb(0 21 41 / 35%)"> <el-aside :width="sideWidth+'px'" style="background-color: rgb(238, 241, 246); box-shadow: 2px 0 6px rgb(0 21 41 / 35%)">
<el-menu :default-openeds="['1', '3']" style="min-height: 100%; overflow-x: hidden" <Aside :isCollapse="isCollapse" :logoTextShow="logoTextShow"/>
background-color="rgb(48,65,86)"
text-color="#fff"
active-text-color="#ffd04b"
:collapse-transition="false"
:collapse="isCollapse"
>
<div style="height: 60px;line-height: 60px;text-align: center">
<img src="../assets/logo.png" alt="" style="width: 20px;position: relative;top: 5px;margin-right: 5px">
<b style="color: white" v-show="logoTextShow"></b>
</div>
<el-submenu index="1">
<template slot="title"><i class="el-icon-message"></i>
<span slot="title">导航一</span>
</template>
<el-menu-item-group>
<template slot="title">分组一</template>
<el-menu-item index="1-1">选项1</el-menu-item>
<el-menu-item index="1-2">选项2</el-menu-item>
</el-menu-item-group>
<el-menu-item-group title="分组2">
<el-menu-item index="1-3">选项3</el-menu-item>
</el-menu-item-group>
<el-submenu index="1-4">
<template slot="title">选项4</template>
<el-menu-item index="1-4-1">选项4-1</el-menu-item>
</el-submenu>
</el-submenu>
<el-submenu index="2">
<template slot="title"><i class="el-icon-menu"></i>
<span slot="title">导航二</span>
</template>
<el-menu-item-group>
<template slot="title">分组一</template>
<el-menu-item index="2-1">选项1</el-menu-item>
<el-menu-item index="2-2">选项2</el-menu-item>
</el-menu-item-group>
<el-menu-item-group title="分组2">
<el-menu-item index="2-3">选项3</el-menu-item>
</el-menu-item-group>
<el-submenu index="2-4">
<template slot="title">选项4</template>
<el-menu-item index="2-4-1">选项4-1</el-menu-item>
</el-submenu>
</el-submenu>
<el-submenu index="3">
<template slot="title"><i class="el-icon-setting"></i>
<span slot="title">导航三</span>
</template>
<el-menu-item-group>
<template slot="title">分组一</template>
<el-menu-item index="3-1">选项1</el-menu-item>
<el-menu-item index="3-2">选项2</el-menu-item>
</el-menu-item-group>
<el-menu-item-group title="分组2">
<el-menu-item index="3-3">选项3</el-menu-item>
</el-menu-item-group>
<el-submenu index="3-4">
<template slot="title">选项4</template>
<el-menu-item index="3-4-1">选项4-1</el-menu-item>
</el-submenu>
</el-submenu>
</el-menu>
</el-aside> </el-aside>
<el-container> <el-container>
<el-header style="font-size: 12px;border-bottom:1px solid #ccc;line-height: 60px;display: flex"> <el-header style="border-bottom:1px solid #ccc;">
<div style="flex: 1;font-size: 20px"> <Header :collapseBtnClass="collapseBtnClass" :collapse="collapse"/>
<span :class="collapseBtnClass" style="cursor:pointer" @click="collapse"></span>
</div>
<el-dropdown style="width: 70px; cursor: pointer">
<span>王小虎</span>
<i class="el-icon-arrow-down" style="margin-left: 5px"></i>
<!-- <i class="el-icon-setting" style="margin-right: 15px"></i>-->
<el-dropdown-menu slot="dropdown">
<el-dropdown-item>个人信息</el-dropdown-item>
<el-dropdown-item>退出</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</el-header> </el-header>
<el-main> <el-main>
@ -129,8 +56,12 @@
<script> <script>
import Aside from "@/components/Aside.vue";
import Header from "@/components/Header.vue";
export default { export default {
name: 'HomeView', name: 'HomeView',
components: {Aside,Header},
data(){ data(){
return { return {
tableData: [], tableData: [],

@ -0,0 +1,253 @@
<template>
<el-container style="min-height: 100vh">
<el-aside :width="sideWidth+'px'" style="background-color: rgb(238, 241, 246); box-shadow: 2px 0 6px rgb(0 21 41 / 35%)">
<Aside :isCollapse="isCollapse" :logoTextShow="logoTextShow"/>
</el-aside>
<el-container>
<el-header style="border-bottom:1px solid #ccc;">
<Header :collapseBtnClass="collapseBtnClass" :collapse="collapse"/>
</el-header>
<el-main>
<div id="app">
<div class="filter-container">
<div class="filter-group">
<label>试卷类型</label>
<button
v-for="(type, index) in paperTypes"
:key="index"
:class="{ active: selectedType === type }"
@click="handleTypeChange(type)"
>
{{ type }}
</button>
</div>
<div class="filter-group">
<label>试卷学科</label>
<button
v-for="(subject, index) in subjects"
:key="index"
:class="{ active: selectedSubject === subject }"
@click="handleSubjectChange(subject)"
>
{{ subject }}
</button>
</div>
</div>
<div v-if="loading" class="loading">...</div>
<div v-else-if="filteredPapers.length === 0" class="empty">暂无试卷</div>
<div v-else class="card-container">
<div
v-for="(paper, index) in filteredPapers"
:key="index"
class="card"
>
<h3>{{ paper.name }}</h3>
<p>学科{{ paper.subject }}</p>
<p>题目数{{ paper.questionCount }}</p>
<p>试卷总分{{ paper.totalScore }}</p>
<p>考试时长{{ paper.time }}</p>
<p>开始时间{{ paper.startTime || "未设置" }}</p>
<p>结束时间{{ paper.endTime || "未设置" }}</p>
<button class="start-button">开始答题</button>
</div>
</div>
</div>
</el-main>
</el-container>
</el-container>
</template>
<script>
import axios from "axios";
import { mapActions } from "vuex";
import Aside from "@/components/Aside.vue";
import Header from "@/components/Header.vue";
export default {
name: 'Exam',
components: {Aside, Header},
data() {
return {
paperTypes: ["固定试卷", "时段试卷", "班级试卷"], //
subjects: ["语文", "数学"], //
selectedType: "班级试卷", //
selectedSubject: "语文", //
papers: [], //
loading: true, //
tableData: [],
collapseBtnClass: 'el-icon-s-fold',
isCollapse: false,
sideWidth: 200,
logoTextShow: true
};
},
computed: {
filteredPapers() {
//
return this.papers.filter(
(paper) =>
paper.subject === this.selectedSubject
);
},
},
created() {
this.fetchPapers(); //
},
watch: {
// fetchPapers
selectedType() {
this.fetchPapers(); //
},
selectedSubject() {
this.fetchPapers(); //
},
},
methods: {
handleTypeChange(type) {
this.selectedType = type; //
},
handleSubjectChange(subject) {
this.selectedSubject = subject; //
},
async fetchPapers(page = 1, size = 10) {
try {
this.loading = true;
const token = this.$store.state.token; // token
if (!token) {
alert("用户未登录,请重新登录!");
this.$router.push('/login'); //
return;
}
// page size
const pageNumber = page || 1; // 使 1
const pageSize = size || 10; // 使 10
const response = await axios.get("http://localhost:8080/student/examPaper/examPaperByTypeAndSubject", {
params: {
pagenum: pageNumber,
pagesize: pageSize, // pagesize
type: this.selectedType, //
subject: this.selectedSubject, //
},
headers: {
Authorization: `Bearer ${token}`, // 使 Vuex token
'Content-Type': 'application/json',
},
});
if (response.data.code === 200) {
const {records} = response.data.data;
this.papers = records.map((record) => ({
name: record.name,
subject: record.subject,
questionCount: record.totalquestion,
totalScore: record.totalscore,
time: record.time + "分钟",
startTime: record.start_time || "未设置",
endTime: record.end_time || "未设置",
}));
console.log("试卷数据:", this.papers);
} else {
alert("数据加载失败:" + response.data.msg);
}
} catch (error) {
console.error("获取试卷数据失败:", error);
alert("试卷数据加载失败,请稍后重试!");
} finally {
this.loading = false;
}
}
}
};
</script>
<style scoped>
/* 顶部筛选部分 */
.filter-container {
margin: 20px;
display: flex;
flex-direction: column; /* 设置为垂直排列 */
gap: 15px; /* 使两个筛选组之间有一定的间距 */
}
.filter-group {
display: flex;
align-items: center;
}
.filter-group label {
margin-right: 10px;
font-weight: bold;
}
button {
margin: 5px 10px 5px 0; /* 设置按钮的间距 */
padding: 5px 10px;
border: none;
background-color: #f0f0f0;
cursor: pointer;
}
button.active {
background-color: #007bff;
color: white;
}
/* 卡片部分 */
.card-container {
display: flex;
flex-wrap: wrap;
gap: 20px;
padding: 20px;
justify-content: space-between; /* Ensures spacing between cards */
}
.card {
width: calc(33.333% - 20px); /* Each card takes up 1/3 of the container width, minus gap */
border: 1px solid #ccc;
border-radius: 5px;
padding: 15px;
background-color: #fff;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
box-sizing: border-box; /* Ensures padding and border are included in the width */
}
.card h3 {
margin: 0 0 10px;
font-size: 16px;
}
.card p {
margin: 5px 0;
font-size: 14px;
color: #333;
}
.start-button {
margin-top: 10px;
width: 100%;
padding: 5px;
background-color: #007bff;
color: white;
border: none;
border-radius: 3px;
cursor: pointer;
}
.start-button:hover {
background-color: #0056b3;
}
/* 加载和空状态 */
.loading,
.empty {
text-align: center;
padding: 20px;
font-size: 16px;
color: #666;
}
</style>

@ -0,0 +1,212 @@
<script>
export default {
name: "Class"
}
</script>
<template>
</template>
<style scoped lang="scss">
</style>
<template>
<el-container style="min-height: 100vh">
<el-aside :width="sideWidth+'px'" style="background-color: rgb(238, 241, 246); box-shadow: 2px 0 6px rgb(0 21 41 / 35%)">
<el-menu :default-openeds="['1', '3']" style="min-height: 100%; overflow-x: hidden"
background-color="rgb(48,65,86)"
text-color="#fff"
active-text-color="#ffd04b"
:collapse-transition="false"
:collapse="isCollapse"
>
<div style="height: 60px;line-height: 60px;text-align: center">
<img src="../assets/logo.png" alt="" style="width: 20px;position: relative;top: 5px;margin-right: 5px">
<b style="color: white" v-show="logoTextShow"></b>
</div>
<el-submenu index="1">
<template slot="title"><i class="el-icon-message"></i>
<span slot="title">导航一</span>
</template>
<el-menu-item-group>
<template slot="title">分组一</template>
<el-menu-item index="1-1">选项1</el-menu-item>
<el-menu-item index="1-2">选项2</el-menu-item>
</el-menu-item-group>
<el-menu-item-group title="分组2">
<el-menu-item index="1-3">选项3</el-menu-item>
</el-menu-item-group>
<el-submenu index="1-4">
<template slot="title">选项4</template>
<el-menu-item index="1-4-1">选项4-1</el-menu-item>
</el-submenu>
</el-submenu>
<el-submenu index="2">
<template slot="title"><i class="el-icon-menu"></i>
<span slot="title">导航二</span>
</template>
<el-menu-item-group>
<template slot="title">分组一</template>
<el-menu-item index="2-1">选项1</el-menu-item>
<el-menu-item index="2-2">选项2</el-menu-item>
</el-menu-item-group>
<el-menu-item-group title="分组2">
<el-menu-item index="2-3">选项3</el-menu-item>
</el-menu-item-group>
<el-submenu index="2-4">
<template slot="title">选项4</template>
<el-menu-item index="2-4-1">选项4-1</el-menu-item>
</el-submenu>
</el-submenu>
<el-submenu index="3">
<template slot="title"><i class="el-icon-setting"></i>
<span slot="title">导航三</span>
</template>
<el-menu-item-group>
<template slot="title">分组一</template>
<el-menu-item index="3-1">选项1</el-menu-item>
<el-menu-item index="3-2">选项2</el-menu-item>
</el-menu-item-group>
<el-menu-item-group title="分组2">
<el-menu-item index="3-3">选项3</el-menu-item>
</el-menu-item-group>
<el-submenu index="3-4">
<template slot="title">选项4</template>
<el-menu-item index="3-4-1">选项4-1</el-menu-item>
</el-submenu>
</el-submenu>
</el-menu>
</el-aside>
<el-container>
<el-header style="font-size: 12px;border-bottom:1px solid #ccc;line-height: 60px;display: flex">
<div style="flex: 1;font-size: 20px">
<span :class="collapseBtnClass" style="cursor:pointer" @click="collapse"></span>
</div>
<el-dropdown style="width: 70px; cursor: pointer">
<span>王小虎</span>
<i class="el-icon-arrow-down" style="margin-left: 5px"></i>
<!-- <i class="el-icon-setting" style="margin-right: 15px"></i>-->
<el-dropdown-menu slot="dropdown">
<el-dropdown-item>个人信息</el-dropdown-item>
<el-dropdown-item>退出</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</el-header>
<el-main>
<div style="padding: 10px 0">
<el-input style="width: 200px" placeholder="请输入名称" suffix-icon="el-icon-search"></el-input>
<el-input style="width: 200px" placeholder="请输入邮箱" suffix-icon="el-icon-message" class="ml-5"></el-input>
<el-input style="width: 200px" placeholder="请输入地址" suffix-icon="el-icon-position" class="ml-5"></el-input>
<el-button class="ml-5" type="primary">搜索</el-button>
</div>
<div style="margin:10px 0">
<el-button type="primary">新增<i class="el-icon-circle-plus-outline"></i></el-button>
<el-button type="danger">批量删除<i class="el-icon-circle-plus-outline"></i></el-button>
<el-button type="primary">导入<i class="el-icon-circle-plus-outline"></i></el-button>
<el-button type="primary">导出<i class="el-icon-circle-plus-outline"></i></el-button>
</div>
<el-table :data="tableData" border stripe header-row-class-name="headerBg">
<el-table-column prop="sumclass" label="班级总数" width="140">
</el-table-column>
<el-table-column prop="sunnumclass" label="班级人数总数" width="120">
</el-table-column>
<el-table-column prop="exampapersum" label="试卷总数">
</el-table-column>
<el-table-column prop="sumtimu" label="题目总数">
</el-table-column>
<el-table-column>
<template slot-scope="scope">
<el-button type="success">编辑 <i class="el-icon-edit"></i></el-button>
<el-button type="danger">删除 <i class="el-icon-circle-plus-outline"></i></el-button>
</template>
</el-table-column>
</el-table>
<div>
<el-pagination
:page-sizes="[5, 10, 15, 20]"
:page-size="10"
layout="total, sizes, prev, pager, next, jumper"
:total="total">
</el-pagination>
</div>
</el-main>
</el-container>
</el-container>
</template>
<script>
export default {
name: 'HomeView',
data(){
return {
tableData: [],
total:0,
collapseBtnClass:'el-icon-s-fold',
isCollapse: false,
sideWidth: 200,
logoTextShow: true
}
},
created() {
// 使 Vuex getter token
const token = this.$store.state.token;
console.log("token:",token);
if (!token) {
console.error('No token found, redirecting to login page...');
this.$router.push({ name: 'login' }); //
return;
}
this.fetchHomePageData(token);
},
methods: {
async fetchHomePageData(token) {
try {
const response = await fetch('http://localhost:8080/teacher/homepage/homepagesuju', {
method: 'GET',
headers: {
'Authorization': token,
'Content-Type': 'application/json',
}
});
const data = await response.json();
if (response.ok && data.code === 200) {
const { sumclass, sunnumclass, exampapersum, sumtimu } = data.data;
console.log("API Response:", data.data);
this.tableData = [
{ sumclass, sunnumclass, exampapersum, sumtimu }
];
} else {
console.error('Failed to fetch data:', data.msg || 'Unknown error');
}
} catch (error) {
console.error('Error fetching data:', error);
}
},
collapse(){
//
this.isCollapse = !this.isCollapse
if(this.isCollapse){
this.sideWidth = 64
this.collapseBtnClass = 'el-icon-s-unfold'
this.logoTextShow = false
}else{
this.sideWidth = 200
this.collapseBtnClass = 'el-icon-s-fold'
this.logoTextShow = true
}
}
}
}
</script>
Loading…
Cancel
Save