Springboot实现求职招聘,校园招聘系统

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
简介: Springboot实现求职招聘,校园招聘系统

一,项目概述:


  本项目基于Springboot 开发实现了一个求职招聘网站,系统分为前端求职招聘和后台数据管理后台。主要分为四个角以:管理员,求职者,公司管理员,公司HR,不同的角色进入系统有不同的功能操作。用户身份可以在后台管理设定。系统功能完整,界面美观大方,适合做毕业设计使用。


运行环境:


开发工具:IDEA或ECLIPSE


数据库:MYSQL+REDIS


开发技术:Springboot+mybatis+mybatisPlus+shiro


前端开发:AJAX+Jquery+layui

2.1 功能需求


2.1.1 系统划分


image.png

2.1.1.1 用户角色划分



求职者

登录本网站的一种用户,可以检索并查看网站入驻的公司及其发布的岗位信息,创建自己的简历,与招聘者进行联系。


应聘者

      2.1、HR


             公司下的某一个HR,可以发布新岗位和取消自己发布的岗位招聘


      2.2、公司管理员


             公司管理员,填写公司相关信息入驻网站后成为该角色,可以管理本公司发布的所有岗位,以及管理所有员工


3、管理员


可以查看站内相关数据,对私信、系统、设置进行管理。


2.1.1.2 前台服务的用例图及说明



招聘者功能

image.png

  1. 查看个人信息:查看自己账号的基本信息及修改
  2. 修改密码:修改自己账号的登录密码
  3. 私信:与求职者私信
  4. 查看个人信息:查看自己账号的基本信息及修改
  5. 修改密码:修改自己账号的登录密码
  6. 私信:与求职者私信
  7. 查看个人信息:查看自己账号的基本信息及修改
  8. 修改密码:修改自己账号的登录密码
  9. 私信:与求职者私信

image.png

  1. 查看个人信息:查看自己账号的基本信息及修改
  2. 修改密码:修改自己账号的登录密码
  3. 私信:对感兴趣岗位的HR进行联系
  4. 个人简历:创建自己的简历,供HR查看
  5. 搜索岗位:搜索自己感兴趣的岗位
  1. 搜索公司:搜索自己感兴趣的公司

2.1.1.3 管理员后台用例图


image.png

  1. 查看个人信息:查看自己账号的基本信息及修改
  2. 修改密码:修改自己账号的登录密码
  3. 公司管理:管理站内所有入驻的公司
  4. 用户管理:管理站内所有用户
  5. 岗位管理:管理站内所有岗位
  6. 简历管理:管理站内所有简历
  7. 数据字典:管理站内数据字典
  8. 私信管理:查看所有用户的聊天关系、聊天记录等

三、数据库设计


3.1 实体关系图


2039e6ed19384579bbba7244075c3745.png

  1. 表结构暂略

五、系统界面


  1. 首页:

70ce90564f59484e8e3f3dd5b7013a8d.png

2.登录界面:

image.png

3.注册界面

image.png

4.岗位查看搜索

image.png

5.公司查看界面

9c74bcf792a34a3887c143f18f573f79.png

6.HR管理界面

a130c46b61644d3ebb2e6a61aed52ab1.png

7.岗位管理界面

23ea3e921558427583cbf469a4830a9f.png

8.员工管理

dc0629d3bffc4e0fbd830066daacf4e0.png

9.个人简历

dd6bd06176b443c2a281487d5a2a4707.png

10.管理员后台管理

4582a37d867447d8b7a9e2b7cb18bccc.png

系统部分核心代码:

package com.iurac.recruit.controller;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReUtil;
import cn.hutool.core.util.StrUtil;
import com.iurac.recruit.entity.Job;
import com.iurac.recruit.entity.User;
import com.iurac.recruit.exception.ManageException;
import com.iurac.recruit.security.RedisCacheManager;
import com.iurac.recruit.service.UserService;
import com.iurac.recruit.util.ImageUtil;
import com.iurac.recruit.util.Result;
import com.iurac.recruit.util.SaltUtil;
import com.iurac.recruit.util.TableResult;
import com.iurac.recruit.vo.PageResultVo;
import com.sun.org.apache.regexp.internal.RE;
import com.sun.org.apache.xpath.internal.operations.Mult;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.Objects;
@Controller
public class UserController {
    @Autowired
    private RedisCacheManager redisCacheManager;
    @Autowired
    private UserService userService;
    @GetMapping({"/","/index"})
    public String toIndex(Model model){
        User user = (User) SecurityUtils.getSubject().getPrincipal();
        if(ObjectUtil.isNotNull(user)){
            model.addAttribute("userInfo",user);
        }
        return "index";
    }
    @GetMapping("/login")
    public String toLogin(){
        return "login";
    }
    @GetMapping("/register")
    public String toRegister(){
        return "register";
    }
    @PostMapping("/login")
    @ResponseBody
    public Result login(String username, String password, String code, HttpSession session) {
        String codes = (String) session.getAttribute("KAPTCHA_SESSION_KEY");
        if (StrUtil.hasBlank(codes)) {
            throw new RuntimeException("验证码已超时!");
        }
        String msg = "";
        try {
            if (codes.equalsIgnoreCase(code)){
                //获取主体对象
                Subject subject = SecurityUtils.getSubject();
                subject.login(new UsernamePasswordToken(username, password));
                return Result.succ("登录成功");
            }else{
                throw new RuntimeException("验证码错误!");
            }
        } catch (UnknownAccountException e) {
            e.printStackTrace();
            msg="用户名错误!";
        } catch (IncorrectCredentialsException e) {
            e.printStackTrace();
            msg="密码错误!";
        }catch (Exception e){
            e.printStackTrace();
            msg=e.getMessage();
        }
        return Result.fail(msg);
    }
    @GetMapping("logout")
    public String logout() {
        Subject subject = SecurityUtils.getSubject();
        subject.logout();
        return "login";
    }
    @PostMapping("/register")
    @ResponseBody
    public Result register(User user, @RequestParam("role")String role) throws Exception {
        user.setImg("default.png");
        userService.register(user,role);
        return Result.succ("操作成功");
    }
    @PostMapping("/user/update")
    @ResponseBody
    public Result updateUserInfo(@RequestParam(value = "phone",required = false) String phone,
                                 @RequestParam(value = "email",required = false) String email,
                                 @RequestParam(value="imgFile",required = false) MultipartFile file) throws Exception {
        User user = (User) SecurityUtils.getSubject().getPrincipal();
        redisCacheManager.getCache("authenticationCacheName").remove(user);
        if(!StrUtil.hasBlank(phone)){
            if(ReUtil.isMatch("(13\\d|14[579]|15[^4\\D]|17[^49\\D]|18\\d)\\d{8}", phone)) {
                user.setPhone(phone);
            }else {
                return Result.fail("请输入正确的手机号");
            }
        }
        if(!StrUtil.hasBlank(email)){
            if(ReUtil.isMatch("\\w[-\\w.+]*@([A-Za-z0-9][-A-Za-z0-9]+\\.)+[A-Za-z]{2,14}", email)){
                user.setEmail(email);
            }else {
                return Result.fail("请输入正确的邮箱地址");
            }
        }
        if(ObjectUtil.isNotNull(file) && !file.isEmpty()){
            String originalFileName = file.getOriginalFilename();
            String imgName = user.getImg().equals("default.png")?ImageUtil.getFileName(originalFileName.substring(originalFileName.lastIndexOf("."))): user.getImg();
            user.setImg(imgName);
            ImageUtil.saveImage(file,user.getImg(),"userIcon");
        }
        if(!userService.updateById(user)){
            return Result.fail("系统错误");
        }
        redisCacheManager.getCache("authenticationCacheName").put(user.getUsername(),user);
        return Result.succ("操作成功");
    }
    @PutMapping("/user/updatePassword/{password}")
    @ResponseBody
    public Result updateUserInfo(@PathVariable("password") String password) throws Exception {
        User user = (User) SecurityUtils.getSubject().getPrincipal();
        if(ReUtil.isMatch("[\\S]{6,12}", password)) {
            Md5Hash md5Hash = new Md5Hash(password,user.getSalt(),1024);
            if(md5Hash.toHex().equals(user.getPassword())){
                return Result.fail("请输入新密码");
            }
            redisCacheManager.getCache("authorizationCacheName").remove(user.toString());
            redisCacheManager.getCache("authenticationCacheName").remove(user);
            user.setPassword(md5Hash.toHex());
            System.out.println(user.getPassword());
        }else {
            return Result.fail("密码必须6到12位,且不能出现空格");
        }
        if(!userService.updateById(user)){
            return Result.fail("系统错误");
        }
        redisCacheManager.getCache("authenticationCacheName").put(user.getUsername(),user);
        return Result.succ("操作成功");
    }
    @RequiresRoles("admin")
    @ResponseBody
    @GetMapping("/user/getByCondition")
    public TableResult<User> getByCondition(@RequestParam("page")Long page, @RequestParam("limit")Long limit,
                                           @RequestParam("username")String username, @RequestParam("role")String role,
                                           @RequestParam("startDate")String startDate, @RequestParam(value = "endDate",required = false)String endDate,
                                           @RequestParam("locked")String locked){
        PageResultVo<User> pageResultVo = userService.getByCondition(page,limit,username,role,locked,startDate,endDate);
        return new TableResult(0,"",pageResultVo.getTotal(),pageResultVo.getRecords());
    }
    @RequiresRoles("admin")
    @ResponseBody
    @PostMapping("/user/save")
    public Result saveUser(@RequestParam("username")String username, @RequestParam("role")String[] role,
                             @RequestParam("password")String password, @RequestParam(value = "imgFile",required = false) MultipartFile file,
                             @RequestParam("phone")String phone, @RequestParam("email")String email) throws IOException, ManageException {
        if(StrUtil.hasEmpty(username,password,phone,email) || role.length<=0){
            return Result.fail("请输入完整信息,避免输入空格");
        }
        if(!ReUtil.isMatch("[\\S]{6,12}", password)) {
            return Result.fail("密码必须6到12位,且不能出现空格");
        }
        if(!ReUtil.isMatch("(13\\d|14[579]|15[^4\\D]|17[^49\\D]|18\\d)\\d{8}", phone)) {
            return Result.fail("请输入正确的手机号");
        }
        if(!ReUtil.isMatch("\\w[-\\w.+]*@([A-Za-z0-9][-A-Za-z0-9]+\\.)+[A-Za-z]{2,14}", email)){
            return Result.fail("请输入正确的邮箱地址");
        }
        User user = new User();
        user.setId(IdUtil.simpleUUID());
        user.setUsername(username);
        user.setCreateTime(DateUtil.now());
        user.setSalt(SaltUtil.getSalt(8));
        Md5Hash md5Hash = new Md5Hash(password, user.getSalt(), 1024);
        user.setPassword(md5Hash.toHex());
        user.setLocked("0");
        user.setPhone(phone);
        user.setEmail(email);
        if(ObjectUtil.isNotNull(file) && !file.isEmpty()){
            String originalFileName = file.getOriginalFilename();
            user.setImg(ImageUtil.getFileName(originalFileName.substring(originalFileName.lastIndexOf("."))));
            ImageUtil.saveImage(file,user.getImg(),"userIcon");
        }else {
            user.setImg("default.png");
        }
        userService.saveUser(user,role);
        return Result.succ("操作成功");
    }
    @RequiresRoles("admin")
    @ResponseBody
    @PostMapping("/user/update/{id}")
    public Result updateUser(@PathVariable("id")String id,@RequestParam("role")String[] role,
                             @RequestParam("password")String password, @RequestParam(value = "imgFile",required = false) MultipartFile file,
                             @RequestParam("phone")String phone, @RequestParam("email")String email) throws IOException, ManageException {
        if(StrUtil.hasEmpty(password,phone,email) || role.length<=0){
            return Result.fail("请输入完整信息,避免输入空格");
        }
        if(!ReUtil.isMatch("[\\S]{6,12}", password)) {
            return Result.fail("密码必须6到12位,且不能出现空格");
        }
        if(!ReUtil.isMatch("(13\\d|14[579]|15[^4\\D]|17[^49\\D]|18\\d)\\d{8}", phone)) {
            return Result.fail("请输入正确的手机号");
        }
        if(!ReUtil.isMatch("\\w[-\\w.+]*@([A-Za-z0-9][-A-Za-z0-9]+\\.)+[A-Za-z]{2,14}", email)){
            return Result.fail("请输入正确的邮箱地址");
        }
        User user = userService.getById(id);
        redisCacheManager.getCache("authorizationCacheName").remove(user.toString());
        redisCacheManager.getCache("authenticationCacheName").remove(user);
        user.setSalt(SaltUtil.getSalt(8));
        Md5Hash md5Hash = new Md5Hash(password, user.getSalt(), 1024);
        user.setPassword(md5Hash.toHex());
        user.setPhone(phone);
        user.setEmail(email);
        if(ObjectUtil.isNotNull(file) && !file.isEmpty()){
            String originalFileName = file.getOriginalFilename();
            user.setImg(ImageUtil.getFileName(originalFileName.substring(originalFileName.lastIndexOf("."))));
            ImageUtil.saveImage(file,user.getImg(),"userIcon");
        }
        userService.updateUser(user,role);
        return Result.succ("操作成功");
    }
    @RequiresRoles("admin")
    @ResponseBody
    @PostMapping("/user/delete/{id}")
    public Result deleteUser(@PathVariable("id")String id) throws  ManageException {
        userService.deleteUser(id);
        return Result.succ("操作成功");
    }
    @RequiresRoles("admin")
    @ResponseBody
    @PostMapping("/user/lock/{id}")
    public Result lockUser(@PathVariable("id")String id) throws  ManageException {
        User user = userService.getById(id);
        user.setLocked("1".equals(user.getLocked())?"0":"1");
        userService.updateById(user);
        return Result.succ("操作成功");
    }
}
package com.iurac.recruit.controller;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.iurac.recruit.entity.Company;
import com.iurac.recruit.entity.Resume;
import com.iurac.recruit.entity.User;
import com.iurac.recruit.exception.ManageException;
import com.iurac.recruit.service.ResumeService;
import com.iurac.recruit.util.ImageUtil;
import com.iurac.recruit.util.Result;
import com.iurac.recruit.util.TableResult;
import com.iurac.recruit.vo.PageResultVo;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.apache.shiro.authz.annotation.RequiresUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.stereotype.Controller;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author iurac
 * @since 2021-06-03
 */
@Controller
public class ResumeController {
    @Autowired
    private ResumeService resumeService;
    @PostMapping("/resume/saveOrUpdate")
    @ResponseBody
    public Result saveOrUpdate(Resume resume,
                                 @RequestParam(value="imgFile",required = false) MultipartFile file) throws Exception {
        if(StrUtil.hasBlank(resume.getName(),resume.getTechnology(),resume.getSalary(), resume.getMajor(),resume.getJob(),
                resume.getIntroduction(),resume.getExperience(),resume.getCollege(),resume.getBirth(),resume.getEducation(),
                resume.getPolitical(),resume.getMarriage(),resume.getSex())){
            return Result.fail("请输入完成信息,避免输入空格");
        }
        if(!ReUtil.isMatch("(13\\d|14[579]|15[^4\\D]|17[^49\\D]|18\\d)\\d{8}", resume.getPhone())) {
            return Result.fail("请输入正确的手机号");
        }
        if(!ReUtil.isMatch("\\w[-\\w.+]*@([A-Za-z0-9][-A-Za-z0-9]+\\.)+[A-Za-z]{2,14}", resume.getEmail())){
            return Result.fail("请输入正确的邮箱地址");
        }
        User user = (User) SecurityUtils.getSubject().getPrincipal();
        resume.setUserId(user.getId());
        QueryWrapper<Resume> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id",user.getId());
        Resume exitedResume = resumeService.getOne(queryWrapper);
        resume.setPhoto("default.png");
        boolean isUpdate = true;
        if(ObjectUtil.isNull(exitedResume)){//判断是新增还是更新
            resume.setId(IdUtil.simpleUUID());
            isUpdate = false;
        }else {
            resume.setId(exitedResume.getId());
            resume.setPhoto(exitedResume.getPhoto());
        }
        if(ObjectUtil.isNotNull(file) && !file.isEmpty()){
            String originalFileName = file.getOriginalFilename();
            String photoName = resume.getPhoto().equals("default.png")?ImageUtil.getFileName(originalFileName.substring(originalFileName.lastIndexOf("."))): resume.getPhoto();
            resume.setPhoto(photoName);
            ImageUtil.saveImage(file,resume.getPhoto(),"photo");
        }
        boolean flag = isUpdate?resumeService.updateById(resume):resumeService.save(resume);
        if(flag){
            return Result.succ("操作成功");
        }else {
            return Result.fail("系统错误");
        }
    }
    @RequiresRoles("admin")
    @ResponseBody
    @GetMapping("/resume/getByCondition")
    public TableResult<Resume> getByCondition(@RequestParam("page")Long page, @RequestParam("limit")Long limit,
                                               @RequestParam("username")String username){
        PageResultVo<Resume> pageResultVo = resumeService.getByCondition(page,limit,username);
        return new TableResult(0,"",pageResultVo.getTotal(),pageResultVo.getRecords());
    }
    @RequiresRoles("admin")
    @ResponseBody
    @PostMapping("/resume/update/{id}")
    public Result updateResume(@PathVariable("id")String id, @RequestParam(value = "imgFile",required = false) MultipartFile file,
                               Resume resume) throws IOException {
        if(StrUtil.hasEmpty(resume.getSex(),resume.getMarriage(),resume.getPolitical(),resume.getEducation(),
                resume.getEmail(),resume.getAge(),resume.getPhone(),resume.getName(),resume.getExperience(),
                resume.getTechnology(),resume.getSalary(),resume.getMajor(),resume.getIntroduction(),resume.getCollege(),
                resume.getBirth(),resume.getJob())){
            return Result.fail("请输入完整信息,避免输入空格");
        }
        Resume exitedResume = resumeService.getById(id);
        resume.setId(id);
        resume.setUserId(exitedResume.getUserId());
        resume.setPhoto(exitedResume.getPhoto());
        if(ObjectUtil.isNotNull(file) && !file.isEmpty()){
            String originalFileName = file.getOriginalFilename();
            resume.setPhoto(ImageUtil.getFileName(originalFileName.substring(originalFileName.lastIndexOf("."))));
            ImageUtil.saveImage(file,resume.getPhoto(),"companyIcon");
        }
        return resumeService.updateById(resume)?Result.succ("操作成功"):Result.fail("操作失败");
    }
    @RequiresRoles("admin")
    @ResponseBody
    @PostMapping("/resume/delete/{id}")
    public Result deleteResume(@PathVariable("id")String id) {
        resumeService.removeById(id);
        return Result.succ("操作成功");
    }
    /**
     *
     * @param id  用户ID
     * @param model
     * @return
     */
    @RequiresUser
    @GetMapping("/resume/detail/{id}")
    public String detail(@PathVariable("id")String id, Model model) {
        Resume resume = resumeService.getByUserId(id);
        model.addAttribute("resumeInfo",resume);
        return "service/detail_resume";
    }
}
相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
1天前
|
JavaScript NoSQL Java
基于SpringBoot+Vue实现的大学生就业服务平台设计与实现(系统源码+文档+数据库+部署等)
面向大学生毕业选题、开题、任务书、程序设计开发、论文辅导提供一站式服务。主要服务:程序设计开发、代码修改、成品部署、支持定制、论文辅导,助力毕设!
18 6
|
1天前
|
JavaScript Java 测试技术
基于Java+SpringBoot+Vue实现的车辆充电桩系统设计与实现(系统源码+文档+部署讲解等)
面向大学生毕业选题、开题、任务书、程序设计开发、论文辅导提供一站式服务。主要服务:程序设计开发、代码修改、成品部署、支持定制、论文辅导,助力毕设!
22 6
|
1天前
|
JavaScript NoSQL Java
基于SpringBoot+Vue实现的大学生体质测试管理系统设计与实现(系统源码+文档+数据库+部署)
面向大学生毕业选题、开题、任务书、程序设计开发、论文辅导提供一站式服务。主要服务:程序设计开发、代码修改、成品部署、支持定制、论文辅导,助力毕设!
17 2
|
1天前
|
JavaScript NoSQL Java
基于SpringBoot+Vue实现的冬奥会科普平台设计与实现(系统源码+文档+数据库+部署)
面向大学生毕业选题、开题、任务书、程序设计开发、论文辅导提供一站式服务。主要服务:程序设计开发、代码修改、成品部署、支持定制、论文辅导,助力毕设!
17 0
|
3月前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 实现动态路由和菜单功能,快速搭建前后端分离的应用框架
本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 实现动态路由和菜单功能,快速搭建前后端分离的应用框架。首先,确保开发环境已安装必要的工具,然后创建并配置 Spring Boot 项目,包括添加依赖和配置 Spring Security。接着,创建后端 API 和前端项目,配置动态路由和菜单。最后,运行项目并分享实践心得,包括版本兼容性、安全性、性能调优等方面。
220 1
|
1天前
|
JavaScript Java 测试技术
基于SpringBoot+Vue实现的留守儿童爱心网站设计与实现(计算机毕设项目实战+源码+文档)
博主是一位全网粉丝超过100万的CSDN特邀作者、博客专家,专注于Java、Python、PHP等技术领域。提供SpringBoot、Vue、HTML、Uniapp、PHP、Python、NodeJS、爬虫、数据可视化等技术服务,涵盖免费选题、功能设计、开题报告、论文辅导、答辩PPT等。系统采用SpringBoot后端框架和Vue前端框架,确保高效开发与良好用户体验。所有代码由博主亲自开发,并提供全程录音录屏讲解服务,保障学习效果。欢迎点赞、收藏、关注、评论,获取更多精品案例源码。
27 10
|
1天前
|
JavaScript Java 测试技术
基于SpringBoot+Vue实现的家政服务管理平台设计与实现(计算机毕设项目实战+源码+文档)
面向大学生毕业选题、开题、任务书、程序设计开发、论文辅导提供一站式服务。主要服务:程序设计开发、代码修改、成品部署、支持定制、论文辅导,助力毕设!
20 8
|
1天前
|
JavaScript 搜索推荐 Java
基于SpringBoot+Vue实现的家乡特色推荐系统设计与实现(源码+文档+部署)
面向大学生毕业选题、开题、任务书、程序设计开发、论文辅导提供一站式服务。主要服务:程序设计开发、代码修改、成品部署、支持定制、论文辅导,助力毕设!
19 8
|
1天前
|
JavaScript NoSQL Java
基于SpringBoot+Vue的班级综合测评管理系统设计与实现(系统源码+文档+数据库+部署等)
✌免费选题、功能需求设计、任务书、开题报告、中期检查、程序功能实现、论文辅导、论文降重、答辩PPT辅导、会议视频一对一讲解代码等✌
21 4
|
1天前
|
JavaScript Java 测试技术
基于SpringBoot+Vue实现的高校食堂移动预约点餐系统设计与实现(源码+文档+部署)
面向大学生毕业选题、开题、任务书、程序设计开发、论文辅导提供一站式服务。主要服务:程序设计开发、代码修改、成品部署、支持定制、论文辅导,助力毕设!
21 3