基于javaweb+mysql的springboot校园宿舍管理系统(java+springboot+vue+maven+redis+mysql)

基于javaweb+mysql的springboot校园宿舍管理系统(java+springboot+vue+maven+redis+mysql)

运行环境

Java≥8、MySQL≥5.7、Node.js≥10

开发工具

后端:eclipse/idea/myeclipse/sts等均可配置运行

前端:WebStorm/VSCode/HBuilderX等均可

适用

课程设计,大作业,毕业设计,项目练习,学习演示等

功能说明

基于javaweb+mysql的SpringBoot校园宿舍管理系统(java+springboot+vue+maven+redis+mysql)

项目介绍

这个项目是一个基于SpringBoot+Vue的校园宿舍管理系统,前后端分离。 主要有超级管理员和宿舍管理员两种角色;

超级管理员权限包括: 首页; 学生宿舍管理:宿舍管理、学生管理、班级管理、宿舍楼管理; 记录:维修记录、晚归记录、请假记录; 系统管理:用户管理、角色管理、菜单管理、日志管理等。

宿舍管理员权限包括: 首页; 学生宿舍管理:宿舍管理、学生管理、班级管理; 记录:维修记录、晚归记录、请假记录;

环境需要

1.运行环境:最好是java jdk 1.8,我们在这个平台上运行的。其他版本理论上也可以。 2.IDE环境:IDEA,Eclipse,Myeclipse都可以。推荐IDEA; 3.硬件环境:windows 7/8/10 1G内存以上;或者 Mac OS; 4.数据库:MySql 5.7/8.0版本均可; 5.是否Maven项目:是;

技术栈

1.后端:SpringBoot+Mysql+redis 2.前端:Vue

使用说明

后端项目运行: 1. 使用Navicat或者其它工具,在mysql中创建对应名称的数据库,并导入项目的sql文件; 2. 使用IDEA/Eclipse/MyEclipse导入项目,导入成功后请执行maven clean;maven install命令,然后运行; 3. 将项目中application-dev.yaml配置文件中的数据库配置改为自己的配置; 4. 运行项目,控制台提示运行成功后再去运行前端项目;

前端项目运行:

  1. 安装好node环境 2. 在dms目录下运行 npm install 安装所需要的包 3. 在dms目录下运行 npm run dev 4. 运行成功后,在浏览器中访问http://localhost:8087,登录账号即可
            return true;
        }
        Method method = handlerMethod.getMethod();
        //获取请求方法所需的权限
        String[] requiredPermissions;
        Match match;
        if (method.isAnnotationPresent(RequirePermission.class)) {
            RequirePermission hasPermission = method.getAnnotation(RequirePermission.class);
            requiredPermissions = hasPermission.permissions();
            match = hasPermission.matchType();
        } else {
            //方法不需要权限(无 RequirePermission 注解)
            return true;
        }

        String token = request.getHeader(Constant.HEADER_TOKEN);

        Long id = redisUtil.get(token);

        //获取该用户的权限
        List<SystemRole> roleList = systemRoleService.listByUserId(id);
        Set<String> permissions;
        if (roleList.size() == 0) {
            permissions = new HashSet<>();
        } else {
            permissions = systemFunctionService.getPermission(roleList);
        }

        //验证权限
        if (VALIDATE_MAP.get(match).validate(permissions, requiredPermissions)) {
            return true;
        }
        //权限验证失败
        throw new HttpException(HttpCode.HAS_NO_PERMISSIONS, "没有权限,请联系管理员");
    }

    private interface Validate {
        /**
         * 验证权限
         * @param userPermission 用户拥有的权限
         * @param methodPermission 方法需要的权限
         * @return 是否通过
         */
        Boolean validate(Set<String> userPermission, String[] methodPermission);
    }
}

/**
 */
@RestController
@RequestMapping("/backlate")
public class BackLateController {
    @Autowired
    private BackLateService backLateService;
    @Autowired
    private RedisUtil redisUtil;

    @PostMapping("/saveOrUpdate")
    @RequirePermission(permissions = {"back:save","back:update"})
    @Log
    public Result<?> saveOrUpdate(@RequestBody @Validated BackLate backLate) {
        backLateService.saveOrUpdate(backLate);
        return Result.ok("操作成功");
    }

    @GetMapping("delete/{id}")
    @RequirePermission(permissions = {"back:delete"})
    @Log
    public Result<?> delete(@PathVariable Long id) {
        backLateService.delete(id);
        return Result.ok("删除成功");
    }

    @PostMapping("/list")
    @RequirePermission(permissions = {"back:list"})
    public Result<PageInfo<BackLate>> list(@RequestBody ListQuery<BackLate> listQuery,
                       @RequestHeader(Constant.HEADER_TOKEN) String token) {
        SystemUser systemUser = redisUtil.exchange(token).get();
        PageInfo<BackLate> pageInfo = backLateService.list(listQuery, systemUser.getBuildingId());
        return Result.<PageInfo<BackLate>>ok().add(pageInfo);
    }

    @GetMapping("/query/{id}")
    @RequirePermission(permissions = {"back:query"})

/**
 */
@RestController
@RequestMapping("/login")
public class LoginController {
    private final RedisUtil redisUtil;
    private final SystemUserService systemUserService;

    public LoginController(RedisUtil redisUtil, SystemUserService systemUserService) {
        this.redisUtil = redisUtil;
        this.systemUserService = systemUserService;
    }

    @PostMapping("/login")
    public Result<String> login(SystemUser user, @RequestParam(value = "redirectUrl") String redirectUrl) {
        List<SystemUser> userList = systemUserService.listUserByLoginName(user.getLoginName());
        if (userList.size() == 0) {
            throw new HttpException(HttpCode.LOGIN_FAILED, "没有此用户");
        } else if (userList.size() > 1) {
            throw new HttpException(HttpCode.LOGIN_FAILED, "存在多个登录名,请联系管理员");
        } else {
            SystemUser systemUser = userList.get(0);
            if (systemUser.getPassword().equals(MD5Util.md5(user.getPassword()))) {
                String token = UUID.randomUUID().toString();
                redisUtil.put(token, systemUser.getId());
                return Result.<String>ok().add(redirectUrl + "#/token=" + token);
            } else {
                throw new HttpException(HttpCode.LOGIN_FAILED, "登陆失败,密码错误");
            }
        }

    }

    @GetMapping("/logout")
    public Result<?> logout(@RequestHeader(HEADER_TOKEN) String token) {
        if (redisUtil.hasToken(token)) {
            redisUtil.deleteToken(token);
        }
        return Result.ok();
    }
}

    public PermissionController(RedisUtil redisUtil,
                                SystemUserService systemUserService,
                                SystemFunctionService systemFunctionService,
                                SystemRoleService systemRoleService,
                                NoticeService noticeService,
                                DepartApplicationService departApplicationService,
                                ImageService imageService) {
        this.redisUtil = redisUtil;
        this.systemUserService = systemUserService;
        this.systemFunctionService = systemFunctionService;
        this.systemRoleService = systemRoleService;
        this.noticeService = noticeService;
        this.departApplicationService = departApplicationService;
        this.imageService = imageService;
    }

    /**
     * 获取登录用户权限,头像,名称,菜单信息
     *
     * @param token token
     * @return
     */
    @GetMapping("/info")
    public Result<SystemUser> info(@RequestHeader(HEADER_TOKEN) String token) {
        SystemUser user = redisUtil.exchange(token).orElseThrow(() -> new HttpException(HttpCode.FAILED, "没有该用户"));
        List<SystemRole> systemRoles = systemRoleService.listByUserId(user.getId());
        Set<String> permissions;
        if (systemRoles.size() == 0) {
            permissions = new HashSet<>();
        } else {
            permissions = systemFunctionService.getPermission(systemRoles);
        }
        user.setPermissions(permissions);
        List<SystemFunction> functionList = systemFunctionService.listFunctionByParentIdAndIds(null, user.getUserRoleId());
        user.setFunctions(functionList);
        return Result.<SystemUser>ok().add(user);
    }

    /**
     * 获取登录用户基本信息
     *
     * @param token 用于获取请求头中的token
    @RequirePermission(permissions = {"system:user:list"})
    public Result<List<SystemUser>> list() {
        List<SystemUser> systemUserList = systemUserService.listAll();
        return Result.<List<SystemUser>>ok().add(systemUserList);
    }

    /**
     * 修改密码
     *
     * @param token    token
     * @param password 包括原密码,修改后的密码,再次输入的密码
     * @return 密码是否修改成功
     */
    @PostMapping("/change")
    public Result<?> validate(@RequestHeader(HEADER_TOKEN) String token, @RequestBody Password password) {
        if (!password.getCurrent1().equals(password.getCurrent2())) {
            throw new HttpException(HttpCode.FAILED, "两次密码输入不一致");
        }
        Long id = redisUtil.get(token);
        Boolean bool = systemUserService.validatePassword(password.getOldPassword(), id);
        if (bool) {
            systemUserService.changePassword(password.getCurrent1(), id);

            //移除token
            redisUtil.deleteToken(token);
            return Result.ok("密码修改成功,请重新登录");
        } else {
            throw new HttpException(HttpCode.FAILED, "原密码不正确");
        }
    }

    /**
     * 修改登录用户信息
     *
     * @param systemUser 修改的用户
     * @return 修改成功后将修改后的用户返回
     */
    @PostMapping("/update")
    public Result<SystemUser> update(@RequestBody SystemUser systemUser, @RequestHeader(HEADER_TOKEN) String token) {
        systemUser.setId(redisUtil.get(token));
        systemUserService.saveOrUpdate(systemUser);
        return Result.<SystemUser>ok("修改成功").add(systemUser);
    }

    @GetMapping("/changeIcon/{icon}")
    public Result<?> changeIcon(@PathVariable String icon , @RequestHeader(HEADER_TOKEN) String token) {
        systemUserService.changeIcon(icon, redisUtil.get(token));
        return Result.ok("修改成功");
    }
        }

    }

    @PostMapping("/saveOrUpdate")
    @RequirePermission(permissions = {"system:user:save", "system:user:update"})
    @Log("添加修改用户")
    public Result<?> saveOrUpdate(@RequestBody @Validated SystemUser user) {
        Boolean validate = systemUserService.validateLoginName(user.getLoginName(),user.getId());
        if (!validate) {
            throw new HttpException(HttpCode.FAILED, "登录名称已存在");
        }
        systemUserService.saveOrUpdate(user);
        return Result.ok("操作成功");
    }

    @GetMapping("/resetPassword")
    @RequirePermission(permissions = {"system:user:update"})
    @Log("重置用户密码")
    public Result<?> resetPassword(@RequestParam("id") Long id) {
        systemUserService.changePassword(Constant.DEFAULT_PASSWORD, id);
        return Result.ok("密码重置成功");
    }

    @GetMapping("/listAll")
    @RequirePermission(permissions = {"system:user:list"})
    public Result<List<SystemUser>> list() {
        List<SystemUser> systemUserList = systemUserService.listAll();
        return Result.<List<SystemUser>>ok().add(systemUserList);
    }

    /**
     * 修改密码
     *
     * @param token    token
     * @param password 包括原密码,修改后的密码,再次输入的密码
     * @return 密码是否修改成功
     */
    @PostMapping("/change")
            //获取类名
            String clas = jp.getTarget().getClass().getSimpleName();

            //获取操作用户id
            String token = request.getHeader(Constant.HEADER_TOKEN);
            Long userId = redisUtil.get(token);

            //获取url
            String url = request.getRequestURI();

            //获取方法名
            String method = targetMethod.getName();

            //获取参数,并转成json
            ObjectMapper objectMapper = new ObjectMapper();
            objectMapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
            Object[] args = jp.getArgs();
            Map<String, Object> param = new HashMap<>(2);
            for (Object arg : args) {
                String className = arg.getClass().getSimpleName();
                className = className.substring(0, 1).toLowerCase() + className.substring(1);
                param.put(className, arg);
            }

            //获取ip
            String ip = request.getRemoteAddr();

            //获取方法注解上的value
            Log l = targetMethod.getAnnotation(Log.class);
            log.info(l.value());

            SystemLog systemLog = new SystemLog()
                    .setClas(clas)
                    .setUserId(userId)
                    .setIp(ip)
                    .setUserId(userId)
                    .setMethod(method)
                    .setUrl(url)
                    .setDescription(l.value())
                    .setParam(objectMapper.writeValueAsString(param));
            Object result;

/**
 */
@RestController
@RequestMapping("/depart")
public class DepartApplicationController {
    @Autowired
    private DepartApplicationService departApplicationService;
    @Autowired
    private StudentService studentService;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private SystemUserService systemUserService;

    @PostMapping("/listMy")
    public Result<PageInfo<DepartApplication>> listMyApplication(@RequestBody ListQuery<DepartApplication> listQuery,
                                    @RequestHeader(Constant.HEADER_TOKEN) String token) {
        Long id = redisUtil.get(token);
        PageHelper.startPage(listQuery.getPage(), listQuery.getRows());
        List<DepartApplication> list = departApplicationService.listMyApplication(id);
        PageInfo<DepartApplication> pageInfo = new PageInfo<>(list);
        return Result.<PageInfo<DepartApplication>>ok().add(pageInfo);
    }

    @PostMapping("/listMyFlow")
    public Result<PageInfo<DepartApplicationUser>> listMyFlow(@RequestBody ListQuery<DepartApplication> listQuery,
                             @RequestHeader(Constant.HEADER_TOKEN) String token) {
        Long id = redisUtil.get(token);
        PageHelper.startPage(listQuery.getPage(), listQuery.getRows());
        List<DepartApplicationUser> list = departApplicationService.listMyFlow(id);
        PageInfo<DepartApplicationUser> pageInfo = new PageInfo<>(list);
        return Result.<PageInfo<DepartApplicationUser>>ok().add(pageInfo);
    }

    @GetMapping("/listFlow/{id}")
    public Result<List<DepartApplicationUser>> listApplicationFlow(@PathVariable("id") Long id) {
        List<DepartApplicationUser> list = departApplicationService.listApplicationFlow(id);
        return Result.<List<DepartApplicationUser>>ok().add(list);
    }


/**
 */
@RestController
@RequestMapping("/student")
public class StudentController {
    @Autowired
    private StudentService studentService;

    @Autowired
    private DepartApplicationService departApplicationService;

    @Autowired
    private SystemUserService systemUserService;
    @Autowired
    private RedisUtil redisUtil;

    @PostMapping("/list")
    @RequirePermission(permissions = {"student:list"})
    public Result<PageInfo<Student>> list(@RequestBody ListQuery<Student> listQuery, @RequestHeader(Constant.HEADER_TOKEN) String token) {
        SystemUser systemUser = redisUtil.exchange(token).get();
        PageInfo<Student> pageInfo = studentService.list(listQuery, systemUser.getBuildingId());
        return Result.<PageInfo<Student>>ok().add(pageInfo);
    }

    @GetMapping("/list")
        user.setPermissions(permissions);
        List<SystemFunction> functionList = systemFunctionService.listFunctionByParentIdAndIds(null, user.getUserRoleId());
        user.setFunctions(functionList);
        return Result.<SystemUser>ok().add(user);
    }

    /**
     * 获取登录用户基本信息
     *
     * @param token 用于获取请求头中的token
     * @return
     */
    @GetMapping("/userinfo")
    public Result<SystemUser> userInfo(@RequestHeader(HEADER_TOKEN) String token) {
        Long id = redisUtil.get(token);
        SystemUser user = systemUserService.info(id).get();
        return Result.<SystemUser>ok().add(user);
    }
    /**
     * 上传图片
     *
     * @param file  图片
     * @param token token
     * @return
     */
    @PostMapping("/upload")
    public Result<String> upload(@RequestParam("file") MultipartFile file, @RequestHeader(HEADER_TOKEN) String token) {
        String fileName = UUID.randomUUID().toString() + ".png";
        if (file != null) {
            try {
                String md5 = MD5Util.getFileMD5(file.getInputStream());
                if (md5 == null) {
                    throw new HttpException(HttpCode.FAILED, "上传失败");
                }
                List<Image> list = imageService.selectByMd5(md5);
                if (list.size() == 0) {
                    file.transferTo(new File(Constant.UPLOAD_PATH, fileName));
                    Long userId = redisUtil.get(token);
                    Image image = new Image()
                            .setUploadUser(userId)
                            .setOriginalName(file.getOriginalFilename())
                            .setSaveName(fileName)
                            .setMd5(md5);
                    imageService.save(image);
                } else {
 */
@Component
public class SecurityInterceptor implements HandlerInterceptor {
    private final RedisUtil redisUtil;
    private final SystemFunctionService systemFunctionService;
    private final SystemRoleService systemRoleService;
    private static final Map<Match, Validate> VALIDATE_MAP = new HashMap<>();

    static {
        VALIDATE_MAP.put(Match.HAS_ANY, (userPermission, methodPermission) -> {
            for (String up : userPermission) {
                for (String mp : methodPermission) {
                    if (up.equalsIgnoreCase(mp)) {
                        return true;
                    }
                }
            }
            return false;
        });
        VALIDATE_MAP.put(Match.HAS_ALL, (userPermission, methodPermission) -> {
            int vote = 0;
            for (String up : userPermission) {
                for (String mp : methodPermission) {
                    if (up.equalsIgnoreCase(mp)) {
                        vote++;
                    }
                }
            }
            return vote == methodPermission.length;
        });
    }

    public SecurityInterceptor(RedisUtil redisUtil, SystemFunctionService systemFunctionService, SystemRoleService systemRoleService) {
        this.redisUtil = redisUtil;
        this.systemFunctionService = systemFunctionService;
        this.systemRoleService = systemRoleService;
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
public class LoginController {
    private final RedisUtil redisUtil;
    private final SystemUserService systemUserService;

    public LoginController(RedisUtil redisUtil, SystemUserService systemUserService) {
        this.redisUtil = redisUtil;
        this.systemUserService = systemUserService;
    }

    @PostMapping("/login")
    public Result<String> login(SystemUser user, @RequestParam(value = "redirectUrl") String redirectUrl) {
        List<SystemUser> userList = systemUserService.listUserByLoginName(user.getLoginName());
        if (userList.size() == 0) {
            throw new HttpException(HttpCode.LOGIN_FAILED, "没有此用户");
        } else if (userList.size() > 1) {
            throw new HttpException(HttpCode.LOGIN_FAILED, "存在多个登录名,请联系管理员");
        } else {
            SystemUser systemUser = userList.get(0);
            if (systemUser.getPassword().equals(MD5Util.md5(user.getPassword()))) {
                String token = UUID.randomUUID().toString();
                redisUtil.put(token, systemUser.getId());
                return Result.<String>ok().add(redirectUrl + "#/token=" + token);
            } else {
                throw new HttpException(HttpCode.LOGIN_FAILED, "登陆失败,密码错误");
            }
        }

    }

    @GetMapping("/logout")
    public Result<?> logout(@RequestHeader(HEADER_TOKEN) String token) {
        if (redisUtil.hasToken(token)) {
            redisUtil.deleteToken(token);
        }
        return Result.ok();
    }
}

                            .setOriginalName(file.getOriginalFilename())
                            .setSaveName(fileName)
                            .setMd5(md5);
                    imageService.save(image);
                } else {
                    fileName = list.get(0).getSaveName();
                }

            } catch (IOException e) {
                throw new HttpException(HttpCode.FAILED, "上传失败");
            }
        } else {
            throw new HttpException(HttpCode.FAILED, "上传失败");
        }
        return Result.<String>ok().add(fileName);
    }

    @GetMapping("/countUnread")
    public Result<Integer> count(@RequestHeader(HEADER_TOKEN) String token) {
        Long userId = redisUtil.get(token);
        int countNotice = noticeService.countByUserId(userId);
        int countDepartApplication = departApplicationService.countFlowAgreeIsNull(userId);
        return Result.<Integer>ok().add(countNotice + countDepartApplication);
    }
}

    }
}

/**
 */
@RestController
@RequestMapping("/backlate")
public class BackLateController {
    @Autowired
    private BackLateService backLateService;
    @Autowired
    private RedisUtil redisUtil;

    @PostMapping("/saveOrUpdate")
    @RequirePermission(permissions = {"back:save","back:update"})
    @Log
    public Result<?> saveOrUpdate(@RequestBody @Validated BackLate backLate) {
        backLateService.saveOrUpdate(backLate);
        return Result.ok("操作成功");
    }

    @GetMapping("delete/{id}")
    @RequirePermission(permissions = {"back:delete"})
    @Log
    public Result<?> delete(@PathVariable Long id) {
        backLateService.delete(id);
        return Result.ok("删除成功");
    }

    @PostMapping("/list")
    @RequirePermission(permissions = {"back:list"})
    public Result<PageInfo<BackLate>> list(@RequestBody ListQuery<BackLate> listQuery,
                       @RequestHeader(Constant.HEADER_TOKEN) String token) {

    @PostMapping("/list")
    @RequirePermission(permissions = {"leave:list"})
    public Result<PageInfo<Leave>> list(@RequestBody ListQuery<Leave> listQuery,
                       @RequestHeader(Constant.HEADER_TOKEN) String token) {
        SystemUser user = redisUtil.exchange(token).get();
        PageInfo<Leave> pageInfo = leaveService.list(listQuery, user.getBuildingId());
        return Result.<PageInfo<Leave>>ok().add(pageInfo);
    }

    @GetMapping("/update/{id}")
    @RequirePermission(permissions = {"leave:update"})
    @Log
    public Result<?> update(@PathVariable Long id) {
        leaveService.update(id);
        return Result.ok("更新成功");
    }

    @GetMapping("/delete/{id}")
    @RequirePermission(permissions = {"leave:delete"})
    @Log
    public Result<?> delete(@PathVariable Long id) {
        leaveService.delete(id);
        return Result.ok("删除成功");
    }

    @GetMapping("/query/{id}")
    @RequirePermission(permissions = {"leave:query"})
    public Result<Leave> query(@PathVariable Long id) {
        Leave leave = leaveService.query(id);
        return Result.<Leave>ok().add(leave);
    }

}


/**
 */
@Aspect
@Component
@Log4j
public class LogAop {

    private final RedisUtil redisUtil;
    private final SystemLogService systemLogService;

    public LogAop(RedisUtil redisUtil, SystemLogService systemLogService) {
        this.redisUtil = redisUtil;
        this.systemLogService = systemLogService;
    }

    @Pointcut("execution(* com.hzvtc.myproject.controller.*.*(..))")
    public void pointcut1() {
    }

    /**
     * 记录系统日志
     * @param jp 。
     */
    @Around(value = "pointcut1()")
    public Object after(ProceedingJoinPoint jp) throws Throwable {
        MethodSignature signature = (MethodSignature)jp.getSignature();
        Method targetMethod = signature.getMethod();

/**
 */
@RestController
@RequestMapping("/room")
public class RoomController {
    @Autowired
    private RoomService roomService;

    @Autowired
    private StudentService studentService;

    @Autowired
    private RedisUtil redisUtil;

    @RequirePermission(permissions = {"room:list"})
    @PostMapping("/list")
    public Result<PageInfo<Room>> list(@RequestBody ListQuery<Room> listQuery, @RequestHeader(Constant.HEADER_TOKEN) String token) {
        SystemUser systemUser = redisUtil.exchange(token).orElseThrow(() -> new HttpException(HttpCode.FAILED, "登录用户不存在"));
        PageInfo<Room> pageInfo = roomService.list(listQuery, systemUser.getBuildingId());
        return Result.<PageInfo<Room>>ok().add(pageInfo);
    }

    @RequirePermission(permissions = {"room:list"})
    @GetMapping("/listAll")
    public Result<List<Room>> list(@RequestHeader(Constant.HEADER_TOKEN) String token) {
        SystemUser systemUser = redisUtil.exchange(token).orElseThrow(() -> new HttpException(HttpCode.FAILED, "登录用户不存在"));
        List<Room> list = roomService.list(systemUser.getBuildingId());
        return Result.<List<Room>>ok().add(list);
    }

    @GetMapping("/query/{id}")
    @RequirePermission(permissions = {"room:query"})
    public Result<Room> query(@PathVariable("id") Long id) {
}

/**
 */
@RestController
@RequestMapping("/system/user")
public class SystemUserController {
    @Autowired
    private SystemUserService systemUserService;
    @Autowired
    private RedisUtil redisUtil;

    @PostMapping("/list")
    @RequirePermission(permissions = {"system:user:list"})
    public Result<PageInfo<SystemUser>> list(@RequestBody ListQuery<SystemUser> listQuery) {
        //多对多查询,先获取符合条件的id,否则pageInfo中的数据会出错

请添加图片描述
请添加图片描述
请添加图片描述
请添加图片描述
请添加图片描述
请添加图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值