• 基于SpringBoot+Vue的校园招聘管理系统(Java毕业设计)


    【辰兮要努力】:hello你好我是辰兮,很高兴你能来阅读,昵称是希望自己能不断精进,向着优秀程序员前行!

    博客来源于项目以及编程中遇到的问题总结,偶尔会有读书分享,我会陆续更新Java前端、后台、数据库、项目案例等相关知识点总结,感谢你的阅读和关注,希望我的博客能帮助到更多的人,分享获取新知,大家一起进步!

    吾等采石之人,应怀大教堂之心,愿我们奔赴在各自的热爱里…

    一、选题背景介绍

    📖☕️🌊📝📚🎩🚀📣

    校园招聘管理系统:帮助企业招聘更好更优质的学生,帮助大学生更好的找工作

    📝推荐理由:选题新颖,实用,基于SpringBoot+Vue的前后端分离项目

    ⚡️系统包含的技术

    后端:SpringBoot(ssm)
    前端:vue + element等
    开发工具:IDEA
    数据库:MySQL
    JDK版本:jdk1.8
    
    • 1
    • 2
    • 3
    • 4
    • 5

    二、模块设计架构

    • 系统设计: 招聘端+管理端
    • 权限设计:有 管理员+用户+企业三种角色权限

    招聘端:首页,招聘信息,求职者信息,友情链接,留言板,后台
    管理,登录

    在这里插入图片描述

    管理端:管理员功能截图如下

    在这里插入图片描述
    管理端:分为 管理员+用户+企业 三种不同角色,每一种角色进入页面都不一样

    在这里插入图片描述

    系统设计的类图

    在这里插入图片描述

    用户登录时序图

    **加粗样式**
    列表相关时序图

    在这里插入图片描述

    如上时序图都可以用idea自动生成,节省时间和提高效率

    手把手教学时序图IDEA生成时序图和类图(案例超详解)


    三、项目模块截图

    备注:因为页面太多,本篇截取核心页面给大家展示

    招聘端截图

    在这里插入图片描述

    求职者信息

    在这里插入图片描述
    留言板截图
    在这里插入图片描述

    个人中心页截图

    在这里插入图片描述

    用户登录:

    在这里插入图片描述

    如下为求职者,及普通用户登录的相关页面
    在这里插入图片描述
    点击详情页,我们可以更新用户的信息等等

    在这里插入图片描述

    企业登录

    在这里插入图片描述
    新增招聘相关信息
    在这里插入图片描述

    管理员登录:系统管理员可以管理企业+普通用户

    在这里插入图片描述
    企业管理
    在这里插入图片描述

    岗位管理

    在这里插入图片描述

    学历管理
    在这里插入图片描述

    招聘信息管理

    在这里插入图片描述

    求职者信息管理
    在这里插入图片描述

    本篇给大家分享相关系统的模块设计思路,欢迎留言沟通交流!


    四、相关代码分享

    文件上传的相关前端代码

    <template>
      <div>
        <!-- 上传文件组件 -->
        <el-upload
          ref="upload"
          :action="getActionUrl"
          list-type="picture-card"
          :multiple="multiple"
          :limit="limit"
          :headers="myHeaders"
          :file-list="fileList"
          :on-exceed="handleExceed"
          :on-preview="handleUploadPreview"
          :on-remove="handleRemove"
          :on-success="handleUploadSuccess"
          :on-error="handleUploadErr"
          :before-upload="handleBeforeUpload"
        >
          <i class="el-icon-plus"></i>
          <div slot="tip" class="el-upload__tip" style="color:#838fa1;">{{tip}}</div>
        </el-upload>
        <el-dialog :visible.sync="dialogVisible" size="tiny" append-to-body>
          <img width="100%" :src="dialogImageUrl" alt>
        </el-dialog>
      </div>
    </template>
    <script>
    import storage from "@/utils/storage";
    import base from "@/utils/base";
    export default {
      data() {
        return {
          // 查看大图
          dialogVisible: false,
          // 查看大图
          dialogImageUrl: "",
          // 组件渲染图片的数组字段,有特殊格式要求
          fileList: [],
          fileUrlList: [],
          myHeaders:{}
        };
      },
      props: ["tip", "action", "limit", "multiple", "fileUrls"],
      mounted() {
        this.init();
        this.myHeaders= {
          'Token':storage.get("Token")
        }
      },
      watch: {
        fileUrls: function(val, oldVal) {
          //   console.log("new: %s, old: %s", val, oldVal);
          this.init();
        }
      },
      computed: {
        // 计算属性的 getter
        getActionUrl: function() {
          // return base.url + this.action + "?token=" + storage.get("token");
          return `/${this.$base.name}/` + this.action;
        }
      },
      methods: {
        // 初始化
        init() {
          //   console.log(this.fileUrls);
          if (this.fileUrls) {
            this.fileUrlList = this.fileUrls.split(",");
            let fileArray = [];
            this.fileUrlList.forEach(function(item, index) {
              var url = item;
              var name = index;
              var file = {
                name: name,
                url: url
              };
              fileArray.push(file);
            });
            this.setFileList(fileArray);
          }
        },
        handleBeforeUpload(file) {
    	
        },
        // 上传文件成功后执行
        handleUploadSuccess(res, file, fileList) {
          if (res && res.code === 0) {
            fileList[fileList.length - 1]["url"] =
              this.$base.url + "upload/" + file.response.file;
            this.setFileList(fileList);
            this.$emit("change", this.fileUrlList.join(","));
          } else {
            this.$message.error(res.msg);
          }
        },
        // 图片上传失败
        handleUploadErr(err, file, fileList) {
          this.$message.error("文件上传失败");
        },
        // 移除图片
        handleRemove(file, fileList) {
          this.setFileList(fileList);
          this.$emit("change", this.fileUrlList.join(","));
        },
        // 查看大图
        handleUploadPreview(file) {
          this.dialogImageUrl = file.url;
          this.dialogVisible = true;
        },
        // 限制图片数量
        handleExceed(files, fileList) {
          this.$message.warning(`最多上传${this.limit}张图片`);
        },
        // 重新对fileList进行赋值
        setFileList(fileList) {
          var fileArray = [];
          var fileUrlArray = [];
          // 有些图片不是公开的,所以需要携带token信息做权限校验
          var token = storage.get("token");
          fileList.forEach(function(item, index) {
            var url = item.url.split("?")[0];
            var name = item.name;
            var file = {
              name: name,
              url: url + "?token=" + token
            };
            fileArray.push(file);
            fileUrlArray.push(url);
          });
          this.fileList = fileArray;
          this.fileUrlList = fileUrlArray;
        }
      }
    };
    </script>
    <style lang="scss" scoped>
    </style>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138

    文件上传后端代码

    
    /**
     * 上传文件映射表
     */
    @RestController
    @RequestMapping("file")
    @SuppressWarnings({"unchecked","rawtypes"})
    public class FileController{
    	@Autowired
        private ConfigService configService;
    	/**
    	 * 上传文件
    	 */
    	@RequestMapping("/upload")
    	public R upload(@RequestParam("file") MultipartFile file,String type) throws Exception {
    		if (file.isEmpty()) {
    			throw new EIException("上传文件不能为空");
    		}
    		String fileExt = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(".")+1);
    		File path = new File(ResourceUtils.getURL("classpath:static").getPath());
    		if(!path.exists()) {
    		    path = new File("");
    		}
    		File upload = new File(path.getAbsolutePath(),"/upload/");
    		if(!upload.exists()) {
    		    upload.mkdirs();
    		}
    		String fileName = new Date().getTime()+"."+fileExt;
    		File dest = new File(upload.getAbsolutePath()+"/"+fileName);
    		file.transferTo(dest);
    		if(StringUtils.isNotBlank(type) && type.equals("1")) {
    			ConfigEntity configEntity = configService.selectOne(new EntityWrapper<ConfigEntity>().eq("name", "faceFile"));
    			if(configEntity==null) {
    				configEntity = new ConfigEntity();
    				configEntity.setName("faceFile");
    				configEntity.setValue(fileName);
    			} else {
    				configEntity.setValue(fileName);
    			}
    			configService.insertOrUpdate(configEntity);
    		}
    		return R.ok().put("file", fileName);
    	}
    	
    	/**
    	 * 下载文件
    	 */
    	@IgnoreAuth
    	@RequestMapping("/download")
    	public ResponseEntity<byte[]> download(@RequestParam String fileName) {
    		try {
    			File path = new File(ResourceUtils.getURL("classpath:static").getPath());
    			if(!path.exists()) {
    			    path = new File("");
    			}
    			File upload = new File(path.getAbsolutePath(),"/upload/");
    			if(!upload.exists()) {
    			    upload.mkdirs();
    			}
    			File file = new File(upload.getAbsolutePath()+"/"+fileName);
    			if(file.exists()){
    				HttpHeaders headers = new HttpHeaders();
    			    headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);    
    			    headers.setContentDispositionFormData("attachment", fileName);    
    			    return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(file),headers, HttpStatus.CREATED);
    			}
    		} catch (IOException e) {
    			e.printStackTrace();
    		}
    		return new ResponseEntity<byte[]>(HttpStatus.INTERNAL_SERVER_ERROR);
    	}
    	
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74

    登录功能相关代码

    <template>
        <div>
            <img class="bg" src="@/assets/img/bg.jpg">
            <el-form :model="rulesForm" :rules="rules" ref="rulesForm" class="login-form">
                <h1 class="h1">校园招聘系统登录</h1>
                <el-form-item label="账号" prop="username">
                    <el-input type="text" v-model="rulesForm.username"></el-input>
                </el-form-item>
                <el-form-item label="密码" prop="password">
                    <el-input type="password" v-model="rulesForm.password"></el-input>
                </el-form-item>
                <el-form-item label="" prop="role">
                    <el-radio v-for="item in menus" v-bind:key="item.roleName" v-model="rulesForm.role"
                              :label="item.roleName">{{item.roleName}}
                    </el-radio>
                </el-form-item>
                <el-form-item label="">
                    <a style="margin-right:10px" href="javascript:void(0)" @click="register('yonghu')">注册用户</a>
                    <a style="margin-right:10px" href="javascript:void(0)" @click="register('qiyexinxi')">注册企业信息</a>
                </el-form-item>
                <el-button @click="login()" class="btn-login" type="primary">登录</el-button>
            </el-form>
        </div>
    </template>
    <script>
        import menu from '@/utils/menu'
    
        export default {
            data() {
                return {
                    rulesForm: {
                        username: "",
                        password: "",
                        role: ""
                    },
                    menus: [],
                    tableName: "",
                    rules: {
                        username: [{required: true, message: "请输入账号", trigger: "blur"}],
                        password: [{required: true, message: "请输入密码", trigger: "blur"}],
                        role: [{required: true, message: "请选择角色", trigger: "blur"}]
                    }
                };
            },
            mounted() {
                let menus = menu.list();
                this.menus = menus;
            },
            methods: {
                register(tableName) {
                    this.$storage.set("loginTable", tableName);
                    this.$router.push({path: '/register'})
                },
                // 登录
                login() {
                    this.$refs["rulesForm"].validate(valid => {
                        let menus = this.menus;
                        for (let i = 0; i < menus.length; i++) {
                            if (menus[i].roleName == this.rulesForm.role) {
                                this.tableName = menus[i].tableName
                            }
                        }
                        if (valid) {
                            this.$http({
                                url: `${this.tableName}/login?username=${this.rulesForm.username}&password=${this.rulesForm.password}`,
                                method: "post"
                            }).then(({data}) => {
                                if (data && data.code === 0) {
                                    this.$storage.set("Token", data.token);
                                    this.$storage.set("role", this.rulesForm.role);
                                    this.$storage.set("sessionTable", this.tableName);
                                    this.$storage.set("adminName", this.rulesForm.username);
                                    this.$router.replace({path: "/index/"});
                                } else {
                                    this.$message.error(data.msg);
                                }
                            });
                        }
                    });
                }
            }
        };
    </script>
    <style lang="scss" scoped>
    </style>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85

    登录成功的时候会将token,role,sessionTable,adminName相关信息放入到storage缓存中

    在这里插入图片描述

    有源码 有源码 有源码


    五、毕设专栏介绍

    ☕️最近开设的专栏整理了很多优秀Java项目,详细的分享了设计思路,计算机毕业生可以参考学习数据库设计,论文写作,项目优化等,每一篇博文均整理了相关系统可以设计的具体模块,以及详细的业务讲解,祝大家学业进步!

    🚀Java项目精选:点击进入Java毕设专栏 关注走一波

    📝分享的所有Java项目源码均包含(前端+后台+数据库),可做毕业设计课程设计

    论文写作指南计算机专业毕业论文写作指导(案例超详解)


    📣非常感谢你阅读到这里,如果这篇文章对你有帮助,希望能留下你的点赞👍 关注❤️ 分享👥 留言💬thanks!!!

    📚愿我们奔赴在各自的热爱里!

  • 相关阅读:
    什么是 Spring?为什么学它?
    mybatis-plus 分页插件
    C++之std::holds_alternative、std::get、std::variant应用实例(二百一十九)
    振弦采集模块(智能振弦传感器测量模块)其它常见问题
    绑定支付卡表单页面html页面前端源码
    牛客 HJ16 购物单
    WISE 2019 | ML-GCN:多标签图节点分类的半监督图嵌入
    SpringBoot 关于异步与事务一起使用的问题
    测吧(北京)科技有限公司项目总监王雪冬一行访问计算机学院探讨合作
    这三个步骤让你知道WPS如何转换成WORD文档
  • 原文地址:https://blog.csdn.net/weixin_45393094/article/details/126804520