基于微信小程序的校园水电费管理平台设计与实现
目录
摘要
系统展示
技术介绍
MySQL数据库
Vue框架
代码实现
管理员实现登录后端代码
连接数据库
前端代码实现
获取源码
摘要
随着社会的发展,社会的方方面面都在利用信息化时代的优势。互联网的优势和普及使得各种系统的开发成为必需。
本文以实际运用为开发背景,运用软件工程原理和开发方法,它主要是采用java语言技术和mysql数据库来完成对系统的设计。整个开发过程首先对校园水电费管理小程序进行需求分析,得出校园水电费管理小程序主要功能。接着对校园水电费管理小程序进行总体设计和详细设计。总体设计主要包括小程序功能设计、小程序总体结构设计、小程序数据结构设计和小程序安全设计等;详细设计主要包括校园水电费管理小程序数据库访问的实现,主要功能模块的具体实现,模块实现关键代码等。最后对校园水电费管理小程序进行了功能测试,并对测试结果进行了分析总结,得出校园水电费管理小程序存在的不足及需要改进的地方,为以后的校园水电费管理小程序维护提供了方便,同时也为今后开发类似校园水电费管理小程序提供了借鉴和帮助。
校园水电费管理小程序开发使系统能够更加方便快捷,同时也促使校园水电费管理小程序变的更加系统化、有序化。系统界面较友好,易于操作。
系统展示
学生注册,在学生注册页面可以填写学号、密码、姓名、性别、寝室、电话、邮箱、照片等信息,进行注册如图5-1所示。
学生登录,在学生登录页面填写账号、密码进行登录如图5-2所示。
学生登录到校园水电费管理小程序可以查看首页、我的等内容进行相对应操作,如图5-3所示。
公告信息,在公告信息页面可以填写标题、简介、内容等信息进行提交,如图5-4所示。
在我的页面可以填写学生缴费等信息,并可根据需要进行提交,如图5-5所示。
在用户信息页面可以填写学号、密码、姓名、性别、寝室、电话、邮箱、照片等信息,并可根据需要对用户信息进行保存、退出登录,如图5-6所示。
在学生缴费页面可以填写年份、月份、学号、姓名、照片、寝室、类型、用量、金额、日期、是否支付等信息,并可根据需要对学生缴费进行支付,如图5-7所示。
教师登录,在教师登录页面填写账号、密码进行登录如图5-8所示。
教师登录到校园水电费管理小程序可以查看首页、我的等内容,如图5-9所示。
我的,在我的页面可以填写教师缴费等信息进行提交,如图5-10所示。
在用户信息页面可以填写工号、密码、姓名、性别、寝室、电话、邮箱、照片等信息,并可根据需要进行保存、退出登录,如图5-11所示。
在教师缴费页面可以填写年份、月份、工号、姓名、照片、寝室、类型、用量、金额、日期、是否支付等信息,并可根据需要对教师缴费进行支付,如图5-12所示。
管理员通过填写用户名、密码、角色进行登录如图5-13所示。
学生管理,通过填写学号、密码、姓名、性别、寝室、电话、邮箱、照片等信息进行详情、修改操作,如图5-14所示。
宿舍信息管理,通过填写宿舍楼号、宿舍类型、宿舍类别、宿舍名称、宿舍状态等信息进行详情、修改、删除操作,如图5-15所示。
教师管理,通过填写工号、密码、姓名、性别、寝室、电话、邮箱、照片等信息进行详情、修改、删除操作,如图5-16所示。
学生缴费管理,通过填写年份、月份、学号、姓名、照片、寝室、类型、用量、金额、日期、是否支付等信息进行详情、修改、删除操作,如图5-17所示。
教师缴费管理,通过填写年份、月份、工号、姓名、照片、寝室、类型、用量、金额、日期、是否支付等信息进行详情、修改、删除操作,如图5-18示。
校园公告,通过填写标题、简介、图片等信息进行详情、修改、删除操作,如图5-19所示。
轮播图;该页面为轮播图管理界面。管理员可以在此页面进行首页轮播图的管理,通过新建操作可在轮播图中加入新的图片,还可以对以上传的图片进行修改操作,以及图片的删除操作,如图5-20所示。
技术介绍
MySQL数据库
MySQL由瑞典的MySQL AB公司开发,后来被Sun Microsystems收购,最终成为Oracle公司的产品。它是一个关系型数据库管理系统,关系数据库将数据保存在不同的表中,而不是将所有数据放在一个大仓库内,这样就增加了速度并提高了灵活性。MySQL支持SQL(结构化查询语言),这是数据库操作的标准语言,可以使用SQL来执行数据查询、插入、更新、删除等操作。
Vue框架
Vue的发音类似于“view”,其设计理念是简单、灵活和高效。Vue框架的核心库只关注视图层,使得它非常轻量级和高效。Vue不仅易于上手,还便于与第三方库或既有项目整合。同时,当与现代化的工具链以及各种支持类库结合使用时,Vue也能够为复杂的单页应用提供驱动。
代码实现
管理员实现登录后端代码
package com.cl.controller;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.text.ParseException;
import java.util.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import com.cl.utils.ValidatorUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.cl.annotation.IgnoreAuth;
import com.cl.entity.UsersEntity;
import com.cl.entity.view.UsersView;
import com.cl.service.UsersService;
import com.cl.service.TokenService;
import com.cl.utils.PageUtils;
import com.cl.utils.R;
import com.cl.utils.MPUtil;
import com.cl.utils.MapUtils;
import com.cl.utils.CommonUtil;
/**
* 管理员
* 后端接口
* @author
* @email
* @date 2024-12-04 12:11:29
*/
@RestController
@RequestMapping("/users")
public class UsersController {
@Autowired
private UsersService usersService;
@Autowired
private TokenService tokenService;
/**
* 登录
*/
@IgnoreAuth
@RequestMapping(value = "/login")
public R login(String username, String password, String captcha, HttpServletRequest request) {
UsersEntity u = usersService.selectOne(new EntityWrapper<UsersEntity>().eq("username", username));
if(u==null || !u.getPassword().equals(password)) {
return R.error("账号或密码不正确");
}
String token = tokenService.generateToken(u.getId(), username,"users", "管理员" );
return R.ok().put("token", token);
}
/**
* 注册
*/
@IgnoreAuth
@RequestMapping("/register")
public R register(@RequestBody UsersEntity users){
//ValidatorUtils.validateEntity(users);
UsersEntity u = usersService.selectOne(new EntityWrapper<UsersEntity>().eq("username", users.getUsername()));
if(u!=null) {
return R.error("注册用户已存在");
}
Long uId = new Date().getTime();
users.setId(uId);
users.setPassword(users.getPassword());
usersService.insert(users);
return R.ok();
}
/**
* 退出
*/
@RequestMapping("/logout")
public R logout(HttpServletRequest request) {
request.getSession().invalidate();
return R.ok("退出成功");
}
/**
* 获取用户的session用户信息
*/
@RequestMapping("/session")
public R getCurrUser(HttpServletRequest request){
Long id = (Long)request.getSession().getAttribute("userId");
return R.ok().put("data", usersService.selectView(new EntityWrapper<UsersEntity>().eq("id", id)));
}
/**
* 密码重置
*/
@IgnoreAuth
@RequestMapping(value = "/resetPass")
public R resetPass(String username, HttpServletRequest request){
UsersEntity u = usersService.selectOne(new EntityWrapper<UsersEntity>().eq("username", username));
if(u==null) {
return R.error("账号不存在");
}
u.setPassword("123456");
usersService.updateById(u);
return R.ok("密码已重置为:123456");
}
/**
* 后台列表
*/
@RequestMapping("/page")
public R page(@RequestParam Map<String, Object> params,UsersEntity users,
HttpServletRequest request){
EntityWrapper<UsersEntity> ew = new EntityWrapper<UsersEntity>();
PageUtils page = usersService.queryPage(params, MPUtil.sort(MPUtil.between(MPUtil.likeOrEq(ew, users), params), params));
return R.ok().put("data", page);
}
/**
* 前端列表
*/
@IgnoreAuth
@RequestMapping("/list")
public R list(@RequestParam Map<String, Object> params,UsersEntity users,
HttpServletRequest request){
EntityWrapper<UsersEntity> ew = new EntityWrapper<UsersEntity>();
PageUtils page = usersService.queryPage(params, MPUtil.sort(MPUtil.between(MPUtil.likeOrEq(ew, users), params), params));
return R.ok().put("data", page);
}
/**
* 列表
*/
@RequestMapping("/lists")
public R list( UsersEntity users){
EntityWrapper<UsersEntity> ew = new EntityWrapper<UsersEntity>();
ew.allEq(MPUtil.allEQMapPre( users, "users"));
return R.ok().put("data", usersService.selectListView(ew));
}
/**
* 查询
*/
@RequestMapping("/query")
public R query(UsersEntity users){
EntityWrapper< UsersEntity> ew = new EntityWrapper< UsersEntity>();
ew.allEq(MPUtil.allEQMapPre( users, "users"));
UsersView usersView = usersService.selectView(ew);
return R.ok("查询管理员成功").put("data", usersView);
}
/**
* 后端详情
*/
@RequestMapping("/info/{id}")
public R info(@PathVariable("id") Long id){
UsersEntity users = usersService.selectById(id);
users = usersService.selectView(new EntityWrapper<UsersEntity>().eq("id", id));
return R.ok().put("data", users);
}
/**
* 前端详情
*/
@IgnoreAuth
@RequestMapping("/detail/{id}")
public R detail(@PathVariable("id") Long id){
UsersEntity users = usersService.selectById(id);
users = usersService.selectView(new EntityWrapper<UsersEntity>().eq("id", id));
return R.ok().put("data", users);
}
/**
* 后端保存
*/
@RequestMapping("/save")
public R save(@RequestBody UsersEntity users, HttpServletRequest request){
users.setId(new Date().getTime()+new Double(Math.floor(Math.random()*1000)).longValue());
//ValidatorUtils.validateEntity(users);
UsersEntity u = usersService.selectOne(new EntityWrapper<UsersEntity>().eq("username", users.getUsername()));
if(u!=null) {
return R.error("用户已存在");
}
users.setId(new Date().getTime());
users.setPassword(users.getPassword());
usersService.insert(users);
return R.ok();
}
/**
* 前端保存
*/
@RequestMapping("/add")
public R add(@RequestBody UsersEntity users, HttpServletRequest request){
users.setId(new Date().getTime()+new Double(Math.floor(Math.random()*1000)).longValue());
//ValidatorUtils.validateEntity(users);
UsersEntity u = usersService.selectOne(new EntityWrapper<UsersEntity>().eq("username", users.getUsername()));
if(u!=null) {
return R.error("用户已存在");
}
users.setId(new Date().getTime());
users.setPassword(users.getPassword());
usersService.insert(users);
return R.ok();
}
/**
* 修改
*/
@RequestMapping("/update")
@Transactional
public R update(@RequestBody UsersEntity users, HttpServletRequest request){
//ValidatorUtils.validateEntity(users);
usersService.updateById(users);//全部更新
return R.ok();
}
/**
* 删除
*/
@RequestMapping("/delete")
public R delete(@RequestBody Long[] ids){
usersService.deleteBatchIds(Arrays.asList(ids));
return R.ok();
}
}
连接数据库
# Tomcat
server:
tomcat:
uri-encoding: UTF-8
port: 8080
servlet:
context-path: /cl93339466
spring:
datasource:
driverClassName: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3308/cl93339466?useUnicode=true&characterEncoding=utf-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2B8&useSSL=false
username: root
password: root
# driverClassName: com.microsoft.sqlserver.jdbc.SQLServerDriver
# url: jdbc:sqlserver://127.0.0.1:1433;DatabaseName=cl93339466
# username: sa
# password: 123456
servlet:
multipart:
max-file-size: 300MB
max-request-size: 300MB
resources:
static-locations: classpath:static/,file:static/
#mybatis
mybatis-plus:
mapper-locations: classpath*:mapper/*.xml
#实体扫描,多个package用逗号或者分号分隔
typeAliasesPackage: com.cl.entity
global-config:
#主键类型 0:"数据库ID自增", 1:"用户输入ID",2:"全局唯一ID (数字类型唯一ID)", 3:"全局唯一ID UUID";
id-type: 1
#字段策略 0:"忽略判断",1:"非 NULL 判断"),2:"非空判断"
field-strategy: 1
#驼峰下划线转换
db-column-underline: true
#刷新mapper 调试神器
refresh-mapper: true
#逻辑删除配置
logic-delete-value: -1
logic-not-delete-value: 0
#自定义SQL注入器
sql-injector: com.baomidou.mybatisplus.mapper.LogicSqlInjector
configuration:
map-underscore-to-camel-case: true
cache-enabled: false
call-setters-on-nulls: true
#springboot 项目mybatis plus 设置 jdbcTypeForNull (oracle数据库需配置JdbcType.NULL, 默认是Other)
jdbc-type-for-null: 'null'
前端代码实现
<template>
<div>
<div class="login_view">
<el-form :model="loginForm" class="login_form">
<div class="title_view">基于SpringBoot框架信息管理系统登录</div>
<div class="tabView" v-if="userList.length>1">
<div class="tab" :style="{'width':`calc(100% / ${userList.length})`}"
:class="loginForm.role==item.roleName?'tabActive':''" v-for="(item,index) in userList"
:key="index" @click="tabClick(item.roleName)">{
{item.roleName}}</div>
</div>
<div class="list_item" v-if="loginType==1">
<div class="list_label">
账号:
</div>
<input class="list_inp" v-model="loginForm.username" placeholder="请输入账号" name="username" />
</div>
<div class="list_item" v-if="loginType==1">
<div class="list_label">
密码:
</div>
<input class="list_inp" v-model="loginForm.password" type="password" placeholder="请输入密码" @keydown.enter.native="handleLogin" />
</div>
<div class="btn_view">
<el-button class="login" v-if="loginType==1" type="success" @click="handleLogin">登录</el-button>
<el-button class="register" type="primary" @click="handleRegister('huanzhexinxi')">注册患者信息</el-button>
</div>
</el-form>
</div>
</div>
</template>
<script setup>
import {
ref,
getCurrentInstance,
nextTick,
onMounted,
} from "vue";
import { useStore } from 'vuex'
const store = useStore()
const userList = ref([])
const menus = ref([])
const loginForm = ref({
role: '',
username: '',
password: ''
})
const tableName = ref('')
const loginType = ref(1)
const context = getCurrentInstance()?.appContext.config.globalProperties;
//注册
const handleRegister = (tableName) => {
context?.$router.push(`/${tableName}Register`)
}
//登录用户tab切换
const tabClick = (role) => {
loginForm.value.role = role
}
const handleLogin = () => {
if (!loginForm.value.username) {
context?.$toolUtil.message('请输入用户名', 'error')
return;
}
if (!loginForm.value.password) {
context?.$toolUtil.message('请输入密码', 'error')
return;
}
if (userList.value.length > 1) {
if (!loginForm.value.role) {
context?.$toolUtil.message('请选择角色', 'error')
verifySlider.value.reset()
return;
}
for (let i = 0; i < menus.value.length; i++) {
if (menus.value[i].roleName == loginForm.value.role) {
tableName.value = menus.value[i].tableName;
}
}
} else {
tableName.value = userList.value[0].tableName;
loginForm.value.role = userList.value[0].roleName;
}
login()
}
const login = () => {
context?.$http({
url: `${tableName.value}/login?username=${loginForm.value.username}&password=${loginForm.value.password}`,
method: 'post'
}).then(res => {
context?.$toolUtil.storageSet("Token", res.data.token);
context?.$toolUtil.storageSet("role", loginForm.value.role);
context?.$toolUtil.storageSet("sessionTable", tableName.value);
context?.$toolUtil.storageSet("adminName", loginForm.value.username);
store.dispatch('user/getSession') //vuex中获取用户信息并保存
context?.$router.push('/')
}, err => {
})
}
//获取菜单
const getMenu=()=> {
let params = {
page: 1,
limit: 1,
sort: 'id',
}
context?.$http({
url: "menu/list",
method: "get",
params: params
}).then(res => {
menus.value = JSON.parse(res.data.data.list[0].menujson)
for (let i = 0; i < menus.value.length; i++) {
if (menus.value[i].hasBackLogin=='是') {
userList.value.push(menus.value[i])
}
}
loginForm.value.role = userList.value[0].roleName
context?.$toolUtil.storageSet("menus", JSON.stringify(menus.value));
})
}
//初始化
const init = () => {
getMenu();
}
onMounted(()=>{
init()
document.querySelector('.login_view').insertAdjacentHTML('beforeend',`<div id="particles-js" class="diy-bg" style="width: 100vw;height: 100vh;position: fixed;top: 0;left: 0;"><canvas class="particles-js-canvas-el" style="width:100%;height:100%;"></canvas></div>`)
const script = document.createElement('script');
script.src = 'https://cdn.bootcdn.net/ajax/libs/particles.js/2.0.0/particles.min.js';
script.onload = () => {
// script加载后执行
particlesJS("particles-js",{
particles: {
number: {
value: 120,
density: {
value_area: 500
}
},
size: {
value: 1,
random: true,
anim: {
speed: 20,
size_min: .1,
sync: false
}
},
line_linked: {
enable: true,
distance: 40,
color: "#fff",
opacity: 1,
width: 2
},
},
});
};
document.head.appendChild(script);
})
</script>
<style lang="scss" scoped>
.login_view {
background-image: url("");
// 表单盒子
.login_form {
}
.title_view {
}
// item盒子
.list_item {
// label
.list_label {
}
// 输入框
.list_inp {
}
}
// 用户类型样式
.tabView{
// 默认样式
.tab{
}
// 选中样式
.tabActive{
}
}
// 按钮盒子
.btn_view {
// 登录
.login {
}
// 注册
.register {
}
}
}
</style>
<style>
.login_view {
min-height: 100vh;
position: relative;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
background-position: center center;
background-size: 100% 100% !important;
background-repeat: no-repeat;
background-attachment: initial;
background-origin: initial;
background-clip: initial;
background-color: initial;
background: linear-gradient(0deg, #249BEF, #7CC9FF)!important;
}
/*表单盒子*/
.login_form{width:500px;margin:0 auto;padding:30px 50px 40px 50px;font-size:16px;-webkit-transform:scale(1);z-index:5;background: rgba(255,255,255,0.5);border-radius: 10px 10px 10px 10px;border: 2px solid #FFFFFF;}
/*标题*/
.login_form .title_view{width:100%;float:left;line-height:46px;font-size:24px;font-weight:600;letter-spacing:2px;color: var(--theme);position:relative;margin-bottom:20px;text-align: center;}
/*list_item*/
.login_form .list_item{display: flex;align-items: center;width: 100%;justify-content: flex-start;margin: 24px auto;background: #fff;padding: 0 16px;border-radius: 26px;line-height: 40px;}
.login_form .list_item .list_label {margin-right:10px;font-size:16px;white-space:nowrap;color: var(--theme);width: 60px;flex-shrink: 0;text-align: center;}
.login_form .list_item .list_label i { font-size:24px; color:#999; }
.login_form .list_item .list_inp{ width:100%; border:none; border-bottom:1px solid #ddd; height:40px; line-height:40px; font-size:inherit; }
.login_form .list_item .el-select{ }
/*用户类型*/
.login_form .list_type{ display: flex; align-items: center; width: 100%; justify-content: center; padding: 10px 0px;margin-bottom:10px; }
.login_form .list_type .el-radio{ }
.login_form .list_type .el-radio .el-radio__label{ color: #666; font-size: 16px; }
.login_form .list_type .el-radio.is-checked{ }
.login_form .list_type .el-radio.is-checked .el-radio__label{ color: rgb(139, 92, 126); font-size: 16px; }
.login_form .list_type .el-radio__input{ }
.login_form .list_type .el-radio__input.is-checked{ }
.login_form .list_type .el-radio__input .el-radio__inner{ background: rgb(255, 255, 255); border: 1px solid rgb(220, 223, 230); }
.login_form .list_type .el-radio__input.is-checked .el-radio__inner{ background-color: rgb(139, 92, 126); border-color: rgb(139, 92, 126); }
/*记住密码*/
.login_form .remember_view{ margin-bottom:20px; }
.login_form .remember_view .el-checkbox{ width: 20%; margin: 0px; display: flex; justify-content: center; align-items: center; }
.login_form .remember_view .el-checkbox .el-checkbox__label{ background: rgb(255, 255, 255); }
.login_form .remember_view .el-checkbox .el-checkbox__inner{ color: rgb(153, 153, 153); }
.login_form .remember_view .el-checkbox.is-checked .el-checkbox__label{ color:#8b5c7e; font-size: 15px; }
.login_form .remember_view .el-checkbox.is-checked .el-checkbox__inner{ background: #8b5c7e; border-color: #8b5c7e; font-size: 16px; }
/* 按钮 */
.login_form .btn_view{text-align:center;margin-top: 60px;position: relative;}
.login_form .btn_view .login{width: 100%;height: 50px;line-height: 46px;background: var(--theme);border: 0px solid #ccc;font-weight: 600;font-size: 20px;color: #fff;margin-bottom:20px;padding:0;border-radius: 26px;}
.login_form .btn_view .login:hover {}
.login_form .btn_view .register{background: #D3EDFA;border: 0px solid #ccc;font-size:16px;color: var(--theme);}
.login_form .btn_view .register:hover {color: #fff;background: var(--theme);}
.login_form .btn_view .forget{background: none;border: 0px solid #ccc;font-size:16px;color: #fff;width: 120px;position: absolute;top: -50px;left: calc(50% - 60px);}
.login_form .btn_view .forget:hover {border: none;color: var(--theme);}
.login_form .face{width:100%;height: 46px;line-height: 40px;background: #fff;border: 3px solid #ccc;font-weight: 600;font-size: 20px;color: #999;margin-bottom:20px;text-align:center;margin-top:20px;padding:0;cursor: pointer;}
.login_form .face:hover {color: var(--theme);border-color: var(--theme);}
.tabView {
display: flex;
width: 100%;
column-gap: 12px;
}
.tab {
flex: 1;
text-align: center;
background: #FFFFFF;
border-radius: 37px 37px 37px 37px;
border: 1px solid #EEEEEE;
line-height: 40px;
color: var(--theme);
border: none;
}
.tab.tabActive {
color: #fff;
background: var(--theme);
}
.listCode_view {
display: flex;
background: #fff;
line-height: 40px;
padding: 0 16px;
border-radius: 26px;
}
.listCode_label {
color: var(--theme);
flex-shrink: 0;
}
input.listCode_inp {
border: none;
flex: 1;
}
.listCode_btn {
padding: 0 12px;
}
</style>
获取源码
大家点赞、收藏、关注、评论啦 、查看👇🏻获取联系方式👇🏻