免费分享一套SpringBoot+Vue员工管理(职工管理,考勤管理,奖惩管理,合同管理)管理系统【论文+源码+SQL脚本】,帅呆了~~

大家好,我是java1234_小锋老师,看到一个不错的SpringBoot+Vue员工管理(职工管理,考勤管理,奖惩管理,合同管理)管理系统,分享下哈。

项目视频演示

【免费】SpringBoot+Vue员工管理(职工管理,考勤管理,奖惩管理,合同管理)管理系统 Java毕业设计_哔哩哔哩_bilibili

项目介绍

在数字化转型的浪潮中,员工业正积极采用先进的信息技术来优化客户体验和运营效率。本研究旨在开发一款基于Spring Boot后端框架和Vue.js前端框架的员工客房预订管理系统,以满足现代员工对高效、便捷、安全的预订管理需求。

系统采用Spring Boot作为后端技术栈的核心,负责处理业务逻辑、数据存储与安全控制。数据库采用关系型数据库MySQL,以确保数据的一致性和事务性。此外,使用Redis作为缓存层,提高数据读取速度,减少数据库压力。

前端界面采用Vue.js构建,提供直观、响应式的用户界面,包括客房查询、预订、取消、支付等功能。通过Axios与后端API进行交互,实现动态数据展示和实时更新。系统还集成了地图服务API,为用户提供员工位置信息及周边设施详情,增强用户体验。

安全性方面,系统采用JWT(JSON Web Token)进行身份验证,确保通信过程中的数据安全。

本系统的实施不仅提升了员工的预订管理效率,也极大地改善了顾客的在线预订体验。通过性能测试和用户反馈,证明了该系统在响应时间、易用性和安全性方面的优越性,为员工业提供了有力的技术支撑,推动了行业的数字化进程。

系统展示

部分代码

package com.rabbiter.staff.controller;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.rabbiter.staff.entity.Role;
import com.rabbiter.staff.entity.User;
import com.rabbiter.staff.entity.vo.UserInfoVo;
import com.rabbiter.staff.entity.vo.UserVo;
import com.rabbiter.staff.service.RoleService;
import com.rabbiter.staff.service.UserService;
import com.rabbiter.staff.utils.JwtUtils;
import com.rabbiter.staff.utils.MD5;
import com.rabbiter.staff.utils.R;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * 用户表 前端控制器
 * </p>
 */
@RestController
@RequestMapping("/staff/user")
@CrossOrigin
public class UserController {
    @Autowired
    private UserService userService;
    @Autowired
    private RoleService roleService;
    @PostMapping("/login")
    public R login(@RequestBody UserVo userVo) {
        String token = userService.login(userVo);
        try {
            if (!StringUtils.isEmpty(token)) {
                return R.ok().data("token",token);
            } else {
                return R.error().message("用户名和密码不匹配");
            }
        } catch (Exception e){
            e.printStackTrace();
        }
        return R.error().message("用户名和密码不匹配");
    }
    
    @GetMapping("/info")
    public R info(@RequestParam("token") String token){
        //验证token是否合法
        String userId = JwtUtils.getMemberIdByToken(token);
        User byId = userService.getById(userId);
        UserInfoVo userInfoVo = new UserInfoVo();
        if (!StringUtils.isEmpty(byId)) {
            QueryWrapper<Role> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("userid",byId.getId());
            List<Role> list = roleService.list(queryWrapper);

            BeanUtils.copyProperties(byId,userInfoVo);
            List<String> roles = new ArrayList<>();
            for (Role role:list) {

                roles.add(role.getName());
            }
            userInfoVo.setRoles(roles);
            return R.ok().data("roles",roles).data("introduction",userInfoVo.getIntroduction()).data("avatar",userInfoVo.getAvatar()).data("name",userInfoVo.getName());
        } else {
            return R.error().message("请先登录");
        }
    }

    @PostMapping("/logout")
    public R logout(@RequestHeader("X-Token") String token) {
        boolean b = JwtUtils.checkToken(token);
        if (b){
            String id = JwtUtils.getMemberIdByToken(token);
            //移除redis中的标记
            return R.ok();
        }
        return R.error();
    }
    //修改信息
    //5.修改
    @PutMapping
    public R updateClerk(@RequestBody User user){
        boolean updateById = userService.updateById(user);
        if (updateById){
            return R.ok().message("修改成功");
        }
        return R.error().message("修改失败");
    }
    //查询自身密码是否与输入的相同
    @PostMapping("getPassword/{password}")
    public R getPassword(@RequestHeader("X-Token") String token,@PathVariable String password) {
        String id = JwtUtils.getMemberIdByToken(token);
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.eq("id",id);
        userQueryWrapper.eq("password",MD5.encrypt(password));
        long count = userService.count(userQueryWrapper);
        if (count > 0){
            return R.ok();
        }
        return R.error().message("密码错误,请重新输入!");
    }
    //修改密码
    @PutMapping("putPassword/{newPassword}")
    public R putPassword(@PathVariable String newPassword,@RequestHeader("X-Token") String token) {
        String id = JwtUtils.getMemberIdByToken(token);
        User user = new User();
        user.setPassword(MD5.encrypt(newPassword));
        user.setId(id);
        userService.updateById(user);
        return R.ok();
    }
}

<template>
    <div class="login-container">
        <el-form
            ref="loginForm"
            :model="loginForm"
            :rules="loginRules"
            class="login-form"
            autocomplete="on"
            label-position="left"
        >
            <div class="title-container">
                <h3 class="title">职工管理系统</h3>
            </div>

            <el-form-item prop="username">
                <span class="svg-container">
                    <i
                        class="iconfont icon-r-user1"
                        style="font-size: 22px"
                    ></i>
                </span>
                <el-input
                    ref="username"
                    v-model="loginForm.username"
                    placeholder="用户名"
                    name="username"
                    type="text"
                    tabindex="1"
                />
            </el-form-item>

            <el-tooltip
                v-model="capsTooltip"
                content="Caps lock is On"
                placement="right"
                manual
            >
                <el-form-item prop="password">
                    <span class="svg-container">
                        <i
                            class="iconfont icon-r-lock"
                            style="font-size: 22px"
                        ></i>
                    </span>
                    <el-input
                        :key="passwordType"
                        ref="password"
                        v-model="loginForm.password"
                        :type="passwordType"
                        placeholder="密码"
                        name="password"
                        tabindex="2"
                        @keyup.native="checkCapslock"
                        @blur="capsTooltip = false"
                        @keyup.enter.native="handleLogin"
                    />
                    <span class="show-pwd" @click="showPwd">
                        <svg-icon
                            :icon-class="
                                passwordType === 'password' ? 'eye' : 'eye-open'
                            "
                        />
                    </span>
                </el-form-item>
            </el-tooltip>

            <el-button
                :loading="loading"
                type="primary"
                style="width: 100%; margin-bottom: 30px; font-size: 22px"
                @click.native.prevent="handleLogin"
                >
                 登录</el-button
            >

        </el-form>
    </div>
</template>

<script>
import { validUsername } from "@/utils/validate";
import SocialSign from "./components/SocialSignin";

export default {
    name: "Login",
    components: { SocialSign },
    data() {
        const validateUsername = (rule, value, callback) => {
            if (!validUsername(value)) {
                callback(new Error("Please enter the correct user name"));
            } else {
                callback();
            }
        };
        const validatePassword = (rule, value, callback) => {
            if (value.length < 6) {
                callback(
                    new Error("The password can not be less than 6 digits")
                );
            } else {
                callback();
            }
        };
        return {
            loginForm: {
                username: "",
                password: "",
            },
            loginRules: {
                // username: [{ required: true, trigger: 'blur', validator: validateUsername }],
                // password: [{ required: true, trigger: 'blur', validator: validatePassword }]
            },
            passwordType: "password",
            capsTooltip: false,
            loading: false,
            showDialog: false,
            redirect: undefined,
            otherQuery: {},
        };
    },
    watch: {
        $route: {
            handler: function (route) {
                const query = route.query;
                if (query) {
                    this.redirect = query.redirect;
                    this.otherQuery = this.getOtherQuery(query);
                }
            },
            immediate: true,
        },
    },
    created() {
        // window.addEventListener('storage', this.afterQRScan)
    },
    mounted() {
        if (this.loginForm.username === "") {
            this.$refs.username.focus();
        } else if (this.loginForm.password === "") {
            this.$refs.password.focus();
        }
    },
    destroyed() {
        // window.removeEventListener('storage', this.afterQRScan)
    },
    methods: {
        checkCapslock(e) {
            const { key } = e;
            this.capsTooltip =
                key && key.length === 1 && key >= "A" && key <= "Z";
        },
        showPwd() {
            if (this.passwordType === "password") {
                this.passwordType = "";
            } else {
                this.passwordType = "password";
            }
            this.$nextTick(() => {
                this.$refs.password.focus();
            });
        },
        handleLogin() {
            this.$refs.loginForm.validate((valid) => {
                if (valid) {
                    this.loading = true;
                    this.$store
                        .dispatch("user/login", this.loginForm)
                        .then(() => {
                            this.$router.push({
                                path: this.redirect || "/",
                                query: this.otherQuery,
                            });
                            this.loading = false;
                        })
                        .catch((e) => {
                            this.loading = false;
                            console.log(e);
                            if (
                                e.response == undefined ||
                                e.response.data == undefined
                            ) {
                                this.$message({
                                    showClose: true,
                                    message: e,
                                    type: "error",
                                    duration: 6000,
                                });
                            } else {
                                this.$message({
                                    showClose: true,
                                    message: e.response.data,
                                    type: "error",
                                    duration: 6000,
                                });
                            }
                        });
                } else {
                    console.log("error submit!!");
                    return false;
                }
            });
        },
        getOtherQuery(query) {
            return Object.keys(query).reduce((acc, cur) => {
                if (cur !== "redirect") {
                    acc[cur] = query[cur];
                }
                return acc;
            }, {});
        },
    },
};
</script>

<style lang="scss">
/* 修复input 背景不协调 和光标变色 */
/* Detail see https://github.com/PanJiaChen/vue-element-admin/pull/927 */

$bg: #283443;
$light_gray: grey;
$cursor: black;

@supports (-webkit-mask: none) and (not (cater-color: $cursor)) {
    .login-container .el-input input {
        color: $cursor;
    }
}

/* reset element-ui css */
.login-container {
    background-image: url("../../assets/bg.png");
    background-size: cover;
    background-repeat: no-repeat;

    .el-input {
        display: inline-block;
        height: 47px;
        width: 85%;

        input {
            background: transparent;
            border: 0px;
            -webkit-appearance: none;
            border-radius: 0px;
            padding: 12px 5px 12px 15px;
            color: $light_gray;
            height: 47px;
            caret-color: $cursor;

            &:-webkit-autofill {
                box-shadow: 0 0 0px 1000px $bg inset !important;
                -webkit-text-fill-color: $cursor !important;
            }
        }
    }

    .el-form-item {
        border: 1px solid rgba(255, 255, 255, 0.1);
        background: white;
        border-radius: 5px;
        color: black;
    }
}
</style>

<style lang="scss" scoped>
$bg: #2d3a4b;
$dark_gray: black;
$light_gray: #eee;

.login-container {
    min-height: 100%;
    width: 100%;
    background-color: $bg;
    overflow: hidden;

    .login-form {
        position: relative;
        width: 520px;
        max-width: 100%;
        padding: 160px 35px 0;
        margin: 0 auto;
        overflow: hidden;
    }

    .tips {
        font-size: 14px;
        color: grey;
        margin-bottom: 10px;

        span {
            &:first-of-type {
                margin-right: 16px;
            }
        }
    }

    .svg-container {
        padding: 6px 5px 6px 15px;
        color: $dark_gray;
        vertical-align: middle;
        width: 30px;
        display: inline-block;
    }

    .title-container {
        position: relative;

        .title {
            font-size: 36px;
            color: black;
            margin: 0px auto 40px auto;
            text-align: center;
            -webkit-text-stroke: 0.5px green;
            font-weight: 600;
        }
    }

    .show-pwd {
        position: absolute;
        right: 10px;
        top: 7px;
        font-size: 16px;
        color: $dark_gray;
        cursor: pointer;
        user-select: none;
    }

    .thirdparty-button {
        position: absolute;
        right: 0;
        bottom: 6px;
    }

    @media only screen and (max-width: 470px) {
        .thirdparty-button {
            display: none;
        }
    }
}
</style>

源码代码

链接:https://pan.baidu.com/s/1qvymj7NI_jmgaZaTjnHNHA 
提取码:1234

  • 9
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值