[Vue3:axios]:实现登录跳转页面展示列表(查看教师所承担课程的学生选课情况)

news2025/1/16 21:41:44

文章目录

  • 一:前置操作
    • 项目结构:
  • 二:登录页面
    • 主要流程说明
    • 运行截图
    • 前端代码Login.vue
  • 三:列表页面
    • 交互逻辑:涉及页面Page02.vue (登录成功跳转学生选课页面)
    • 运行截图

一:前置操作

https://blog.csdn.net/Abraxs/article/details/139552598?spm=1001.2014.3001.5501
在这里插入图片描述

项目结构:

在这里插入图片描述

二:登录页面

主要流程说明

登录交互逻辑:
Login.vue 点击登录发送请求 api /api/base/login 然后localStorage存储登录信息
关键代码:
前端

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('登录失败');
    }
  });

后端

@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

<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登录用户信息
关键代码:

前端:
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代码

 <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>
        &emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;
        &emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;
        &emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;
        &emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;
        <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>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1810280.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Linux】进程间通信之命名管道

&#x1f466;个人主页&#xff1a;Weraphael ✍&#x1f3fb;作者简介&#xff1a;目前正在学习c和算法 ✈️专栏&#xff1a;Linux &#x1f40b; 希望大家多多支持&#xff0c;咱一起进步&#xff01;&#x1f601; 如果文章有啥瑕疵&#xff0c;希望大佬指点一二 如果文章对…

【PB案例学习笔记】-18制作一个IP地址编辑框

写在前面 这是PB案例学习笔记系列文章的第18篇&#xff0c;该系列文章适合具有一定PB基础的读者。 通过一个个由浅入深的编程实战案例学习&#xff0c;提高编程技巧&#xff0c;以保证小伙伴们能应付公司的各种开发需求。 文章中设计到的源码&#xff0c;小凡都上传到了gite…

46-4 等级保护 - 网络安全等级保护概述

一、网络安全等级保护概述 原文:没有网络安全就没有国家安全 二、网络安全法 - 安全立法 中华人民共和国主席令 第五十三号 《中华人民共和国网络安全法》已于2016年11月7日由中华人民共和国第十二届全国人民代表大会常务委员会第二十四次会议通过,并自2017年6月1日起正式…

LabVIEW图像采集处理项目中相机选择与应用

在LabVIEW图像采集处理项目中&#xff0c;选择合适的相机是确保项目成功的关键。本文将详细探讨相机选择时需要关注的参数、黑白相机与彩色相机的区别及其适用场合&#xff0c;帮助工程师和开发者做出明智的选择。 相机选择时需要关注的参数 1. 分辨率 定义&#xff1a;分辨率…

C++ - Clion安装Qt msvc2017版本教程,基础环境配置clion+ Qt5.12.12 msvc2017 + VS2019

背景&#xff1a;平时代码开发使用clion&#xff0c;但使用项目要制定mscv2017版本Qt。先装过mingw版本Qt无法运行&#xff0c;但msvc版本依赖装有Visual Studio&#xff0c;本地装的又是2019版。就出现了这个大坑&#xff0c;需要配置好clion Qt msvc2017 VS2019。 文章目录 …

立创EDA专业版设置位号居中并调整字体大小

选择某一个器件位号&#xff0c;右键->查找&#xff1a; 选择查找全部&#xff1a; 下面会显示查找结果&#xff1a; 查看&#xff0c;所有的位号都被选中了&#xff1a; 然后布局->属性位置&#xff1a; 属性位置选择中间&#xff1a; 然后位号就居中了 调整字体大小&a…

串口通信技术基础

1.0 串口通信基础 数据通信的两种常用形式&#xff1a; 1&#xff1a;并行通信 和 串行通信 并行方式&#xff1a;数据的各位使用多条数据线同时发送或同时接收 特点&#xff1a;传送速度快&#xff0c;但因需要多根传输线&#xff0c;曾经在近距离、高速率通信中使用 串行方式…

01——生产监控平台——WPF

生产监控平台—— 一、介绍 VS2022 .net core(net6版本&#xff09; 1、文件夹&#xff1a;MVVM /静态资源&#xff08;图片、字体等&#xff09; 、用户空间、资源字典等。 2、图片资源库&#xff1a; https://www.iconfont.cn/ ; 1.资源字典Dictionary 1、…

验证码识别接口、多种样式验证码识别接口、中英文验证码识别接口

验证码识别接口、多种样式验证码识别接口、中英文验证码识别接口 本文提供一个基于OCR和机器学习的验证码识别接口&#xff0c;能够识别较复杂的中文、英文验证码&#xff0c;在OCR的基础上针对验证码进行算法优化。本接口是收费的&#xff08;最低0.5分1次调用&#xff0c;试…

【最新鸿蒙应用开发】——总结ArkUI生命周期

鸿蒙ArkUI相关的生命周期都有哪些? 1. UIAbility生命周期 onCreate、onWindowStageCreate、onForeground、onBackground、onWindowStageDestroy、onDestroy。 onCreate&#xff1a;Create状态为在应用加载过程中&#xff0c;UIAbility实例创建完成时触发&#xff0c;系统会调…

python tushare股票量化数据处理:笔记

1、安装python和tushare及相关库 matplotlib pyplot pandas pandas_datareader >>> import matplotlib.pyplot as plt >>> import pandas as pd >>> import datetime as dt >>> import pandas_datareader.data as web 失败的尝试yf…

计蒜客:C10 第四部分:深度优先搜索基础 引爆炸弹

【C代码】 #include<bits/stdc.h> using namespace std; int n,m,ans0; char maze[501][501]; bool vis[501][501]; void dfs(int x,int y){vi…

解析中断引起的调度延迟问题

解析软中断引起的调度延迟问题 一、导言二、线程调度的原理三、如何定位中断导致的调度延迟方法一:使用内核 ftrace工具方法二:使用开源ko工具方法三:修改内核源码添加打印一、导言 硬件中断和软件中断都有可能导致调度延迟,但两者的影响方式略有不同。 硬件中断:当硬件设…

stm32MP135裸机编程:启动流程分析

0 参考资料 轻松使用STM32MP13x - 如MCU般在cortex A核上裸跑应用程序.pdf STM32MP135AD数据手册.pdf1 stm32MP135裸机启动流程分析 1.1 启动方式 stm32MP135支持8种启动方式&#xff1a; 注&#xff1a; UART和USB启动并不是指通过UART/USB加载程序&#xff0c;而是通过UA…

Spring Boot 项目启动时在 prepareContext 阶段做了哪些事?

概览 如果你对Spring Boot 启动流程还不甚了解&#xff0c;可阅读《Spring Boot 启动流程详解》这篇文章。如果你已了解&#xff0c;那就让我们直接看看prepareContext() 源码。 private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironme…

2024.6.7

思维导图 代码 #include <iostream>using namespace std;//创建一个RMB类 class RMB {friend const RMB operator(const RMB &p1, const RMB &p2);friend const RMB operator-(const RMB &p1, const RMB &p2);friend bool operator>(const RMB &…

《Windows API每日一练》3.1 绘制文本

本节我们将讲述如何在窗口客户区绘制文本。如果在客户区绘制文本&#xff0c;需要将整个客户区或指定文本所在的矩形区域设置为无效区域&#xff0c;然后产生WM_PANIT消息&#xff0c;调用GDI函数绘制文本。此外&#xff0c;如果要绘制文本还需要使用设备环境上下文句柄&#x…

阿里发布最强开源大模型通义千问Qwen2,国产最好用的LLM

前言 近年来&#xff0c;大模型技术发展迅速&#xff0c;开源模型的出现为AI研究和应用带来了新的活力。在这一背景下&#xff0c;阿里云通义千问团队发布了全新升级的Qwen2系列开源模型&#xff0c;为国内外开发者提供了更强大的工具和更丰富的选择。 Huggingface模型下载&am…

springboot3 数据访问

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 数据访问 一、准备数据库表二、项目创建2.1、使用spring initializer 创建2.2、添加数据库配置2.3 mapper2.4 编写controller2.5 总结 三、其他数据源 一、准备数据库表 CRE…

追觅科技2025校园招聘测评已发(真题)

&#x1f4e3;追觅科技 2025校园招聘测评已发&#xff0c;正在申请的小伙伴看过来哦&#x1f440; ㊙本次校招面向全球于2023年7月 - 2025年12月期间毕业的同学&#xff0c;开放了四大类岗位&#xff1a;营销类、研发类、制作供应类、职能类~ ✅测评解析 &#x1f449; 测评自…