系列文章目录
本项目是学生社团管理系统一个基于Spring Boot + Vue.js构建的一个前后端分离项目框架的后端项目代码部分。
前端是基于Vue+elementUI+bootstrap(仅活动展示页面)+axios 的开发框架。
前言
本项目是学生社团管理系统一个基于Spring Boot + Vue.js构建的一个前后端分离项目框架的后端项目代码部分。
前端是基于Vue+elementUI+bootstrap(仅活动展示页面)+axios 的开发框架。
功能
管理员功能
- 管理社团:增加新社团(设置社长)、修改社长、删除社团、社团活动管理(报名活动查询、结束活动查询、活动删除)、社团活动报名者的管理(查看、删除)
- 成员管理:成员信息管理(成员条件查询、删除)
- 社团申请:审批社团申请(同意、不同意)
- 活动审批:审批活动申请(同意、不同意)
- 个人信息修改:用户名、密码、电话号码、个性签名、性别
- 系统公告:修改系统公告
社长功能
- 社团报名:查看社团已有活动、报名社团
- 社长中心:社团成员管理(条件查询、删除)、审批成员申请社团(同意、不同意)
- 活动管理:活动管理(新增活动、活动报名通知展示、活动结束通知展示、活动名单(成员管理(审批通过、审批不通过、删除))、新增结束活动通知、报名结束)
- 我的中心:活动记录、我的社团(活动报名、社团公告)
- 个人信息修改:用户名、密码、电话号码、个性签名、性别
- 公告:系统公告、社团公告编辑
成员功能
- 社团成立:新增社团等待审批
- 社团报名:查看社团已有活动、报名社团、活动查询(报名活动、结束通知)
- 活动记录:活动信息(报名活动、结束通知)
- 我的社团:社团公告、社团活动(查看报名活动、查看结束通知、申请活动)
- 个人信息修改:用户名、密码、电话号码、个性签名、性别
- 系统公告查看
登录、注册功能
运行截图
二、使用步骤
1.pom文件
代码如下(示例):
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>cn.edu.shu.xj</groupId>
<artifactId>ser</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>ser</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.4.0</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.29</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.2.0</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.4</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.7.0</version>
</dependency>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>2.0.4</version>
</dependency>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>swagger-bootstrap-ui</artifactId>
<version>1.9.6</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.7.0</version>
</dependency>
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.4.0</version>
</dependency>
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>3.10.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.9</version>
</dependency>
<!-- 验证码 -->
<dependency>
<groupId>com.github.axet</groupId>
<artifactId>kaptcha</artifactId>
<version>0.0.9</version>
</dependency>
<!-- <dependency>-->
<!-- <groupId>org.thymeleaf.extras</groupId>-->
<!-- <artifactId>thymeleaf-extras-springsecurity5</artifactId>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>org.springframework.boot</groupId>-->
<!-- <artifactId>spring-boot-starter-security</artifactId>-->
<!-- </dependency>-->
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>aliyun</id>
<name>aliyun</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<layout>default</layout>
<releases>
<enabled>true</enabled>
<updatePolicy>never</updatePolicy>
</releases>
<snapshots>
<enabled>true</enabled>
<updatePolicy>never</updatePolicy>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>aliyun</id>
<name>aliyun</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
</project>
前端登录页面
<template>
<!--登录表单的容器-->
<div class="login_container">
<div class="video-container">
<div :style="fixStyle" class="filter">
<div class="title">
<span>学生社团管理系统</span>
</div>
<!--登录区域-->
<div class="login_box" style="margin-top: 50px">
<!--头像-->
<div class="avatar_box">
<img src="../assets/img/timg.jpg">
</div>
<!--表单-->
<el-form :model="loginForm" :rules="loginRules" ref="loginForm" label- width="0px" class="login_form">
<el-form-item prop="number">
<el-input v-model="loginForm.number" placeholder="请输入学号" prefix-icon="el-icon-user-solid"></el-input>
</el-form-item>
<el-form-item prop="password">
<el-input type="password" v-model="loginForm.password" placeholder="请输入登录密码" prefix-icon="el-icon-lock"></el-input>
</el-form-item>
<el-form-item prop="verifyCode">
<div class="verifyCode_box">
<el-input v-model="loginForm.verifyCode" placeholder="请输入计算结果" prefix-icon="el-icon-mobile" class="verifyCode"></el-input>
<img src="../assets/img/mskKPg.png" alt="" class="verifyCode_img">
</div>
</el-form-item>
<el-form-item class="login_btn">
<el-button type="warning" @click="back">返回</el-button>
<el-button type="primary" @click="submitForm('loginForm')">登录</el-button>
<el-button @click="resetForm('loginForm')">重置</el-button>
</el-form-item>
</el-form>
</div>
</div>
<video :style="fixStyle" autoplay loop muted class="fillWidth" v-on:canplay="canplay">
<source src="../assets/video/background.mp4" type="video/mp4"/>
浏览器不支持 video 标签,建议升级浏览器。
</video>
</div>
</div>
</template>
<script>
import { userLogin } from '@/api/user'
import { findLeaderAss } from '@/api/assData'
export default {
name: 'Login',
data () {
return {
loginForm: {
number: '',
password: '',
verifyCode: ''
},
loginRules: {
number: [
{ required: true, message: '请输入学号', trigger: 'blur' },
{ min: 4, max: 9, message: '学号格式不正确', trigger: 'blur' }
],
password: [
{ required: true, message: '请输入登录密码', trigger: 'blur' },
{ min: 1, max: 16, message: '长度在 1 到 16 个字符', trigger: 'blur' }
],
verifyCode: [
{ required: true, message: '请输入计算结果', trigger: 'blur' }
]
},
vedioCanPlay: false,
fixStyle: ''
}
},
mounted: function () {
window.onresize = () => {
const windowWidth = document.body.clientWidth
const windowHeight = document.body.clientHeight
const windowAspectRatio = windowHeight / windowWidth
let videoWidth
let videoHeight
if (windowAspectRatio < 0.5625) {
videoWidth = windowWidth
videoHeight = videoWidth * 0.5625
this.fixStyle = {
height: windowWidth * 0.5625 + 'px',
width: windowWidth + 'px',
'margin-bottom': (windowHeight - videoHeight) / 2 + 'px',
'margin-left': 'initial'
}
} else {
videoHeight = windowHeight
videoWidth = videoHeight / 0.5625
this.fixStyle = {
height: windowHeight + 'px',
width: windowHeight / 0.5625 + 'px',
'margin-left': (windowWidth - videoWidth) / 2 + 'px',
'margin-bottom': 'initial'
}
}
}
window.onresize()
},
methods: {
canplay () {
this.vedioCanPlay = true
},
submitForm (loginForm) {
// eslint-disable-next-line no-unused-expressions
this.$refs[loginForm].validate(valid => {
if (!valid) {
this.$notify({
message: '请完整输入',
type: 'warning',
duration: 1200
})
return false
}
})
this.getuserLogin()
// 获取admin的信息
},
back () {
this.$router.push('/home')
},
resetForm (formName) {
this.$refs[formName].resetFields()
},
async getLeaderAss () {
const { data } = await findLeaderAss(this.$root.USER.id)
this.$root.ASS.assId = data.data.ass.assId
this.$root.ASS.assName = data.data.ass.assName
this.$root.ASS.assPosition = data.data.ass.assPositon
this.$root.ASS.assTeacher = data.data.ass.assTeacher
this.$root.ASS.assCapital = data.data.ass.assCapital
this.$root.ASS.assNotice = data.data.ass.assNotice
console.log(data)
console.log(this.$root.ASS.assId)
},
async getuserLogin () {
const { data } = await userLogin(this.loginForm.number, this.loginForm.password)
console.log(data)
if (data.code === 3012) {
this.$notify({
title: '警告',
message: data.message,
type: 'warning',
duration: 2000
})
} else if (data.code === 3018) {
this.$notify({
title: '警告',
message: data.message,
type: 'warning',
duration: 2000
})
} else if (data.code === 20000) {
this.$root.USER.id = data.data.user.userId
this.$root.USER.name = data.data.user.userName
this.$root.USER.pwd = data.data.user.userPwd
this.$root.USER.trueName = data.data.user.userTrueName
this.$root.USER.authority = data.data.user.userAuthority
this.$root.USER.score = data.data.user.userScore
this.$root.USER.number = data.data.user.userNumber
this.$root.USER.gender = data.data.user.userGender
this.$root.USER.position = data.data.user.userPosition
this.$root.USER.phone = data.data.user.userPhone
this.$root.USER.pic = data.data.user.userPic
this.$root.USER.token = data.data.token
this.$root.USER.signature = data.data.user.userSignature
console.log(this.$root.USER.id)
console.log(this.$root.USER.name)
console.log(this.$root.USER.signature)
// eslint-disable-next-line eqeqeq
this.$notify({
title: '成功',
message: '登录成功',
type: 'success',
duration: 2000,
onClose: () => {
// eslint-disable-next-line eqeqeq
if (this.$root.USER.authority == 0) {
this.$router.push('/main')
// eslint-disable-next-line eqeqeq
} else if (this.$root.USER.authority == 1) {
// 获取社长的社团信息
this.getLeaderAss()
this.$router.push('/main1')
} else {
this.$router.push('/main2')
}
}
})
}
}
// async getadminLogin () {
// // eslint-disable-next-line no-unused-vars
// const { data } = await adminLogin(this.loginForm.admin, this.loginForm.password)
// console.log(data)
// // eslint-disable-next-line no-undef
// this.$store.commit('getToken', data.data.token)
// this.$store.commit('getData', data.data.shop)
// console.log(this.$store.state.token)
// console.log(this.$store.state.data)
// if (data.code === 4001) {
// this.$message({
// message: '本管理员用户名不存在',
// type: 'warning',
// duration: 2000
// })
// } else if (data.code === 4002) {
// this.$message({
// message: '管理员用户名对应密码错误',
// type: 'warning',
// duration: 2000
// })
// } else if (data.code === 20000) {
// this.$message({
// message: '登录成功',
// type: 'success',
// duration: 2000,
// onClose: () => {
// this.$router.push('/main')
// }
// })
// }
// }
}
}
</script>
<style lang="less" scoped>
.title {
color: dimgray;
-webkit-text-stroke: 1px black;
letter-spacing: 0.04em;
background-color: #FFFFFF;
font-size: 50px;
font-weight: bold;
text-shadow: 1px -1px black, 2px -2px white;
text-align: center;
opacity: 0.55;
}
.login_box {
width: 450px;
height: 380px;
background-color: #FFFFFF;
border-radius: 3px;
position: absolute;
left: 50%;
top: 40%;
transform: translate(-50%, -50%);
.avatar_box{
width: 130px;
height: 130px;
border: 1px solid #EEEEEE;
border-radius: 50%;
padding: 10px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
margin: -65px auto;
background-color: #FFFFFF;
img{
width: 100%;
height: 100%;
border-radius: 50%;
background-color: #EEEEEE;
}
}
.login_form{
position: absolute;
bottom: 0px;
width: 100%;
padding: 0px 20px;
box-sizing: border-box;
.login_btn{
display: flex;
justify-content: flex-end;
}
.verifyCode_box{
display: flex;
.verifyCode{
width: 70%;
justify-content: left;
}
.verifyCode_img{
width: 30%;
height: 45px;
justify-content: flex-end;
}
}
}
}
.login_container{
background: url(../assets/img/pic3.jpg) no-repeat;
background-size: 100% 770px;
overflow: hidden;
height: 100%;
}
.home,
.video-container {
position: relative;
height: 100vh;
overflow: hidden;
}
.video-container .filter {
z-index: 1;
position: absolute;
background: rgba(0, 0, 0, 0.4);
width: 100%;
}
</style>
源码下载
提示:这里对文章进行总结:
https://pan.baidu.com/s/1HdmGCmAMFIQu37NKvZU0Bw?pwd=3212
提取码:3212