基于javaweb+mysql的springboot在线游戏商城系统(java+springboot+mybatis+mysql+maven+layui+thymeleaf+html)

基于javaweb+mysql的springboot在线游戏商城系统(java+springboot+mybatis+mysql+maven+layui+thymeleaf+html)

运行环境

Java≥8、MySQL≥5.7

开发工具

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

适用

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

功能说明

基于javaweb+mysql的SpringBoot在线游戏商城系统(java+springboot+mybatis+mysql+maven+layui+thymeleaf+html)

一、项目简述功能包括: 用户管理,游戏商品管理,在线购买,上传,售卖记录,商品审核等等。

二、项目运行环境配置:

Jdk1.8 + Tomcat8.5 + mysql + Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)

项目技术:

JSP +Spring + SpringBoot + MyBatis + html+ css + JavaScript + JQuery + Ajax + layui+ maven等等


/**
 * <p>
 *  收藏控制器
 * </p>
 *
 */
@Controller
public class CollectController {
    @Autowired
    private CollectService collectService;

    /**
     * 商品详情界面:收藏商品or取消收藏
     * 前端传入收藏操作(colloperate:1收藏,2取消收藏),获取session中用户id信息,判断是否登录
     * (1). 收藏商品
     * 1.前端传入商品id(commid)、商品名(commname)、商品描述(commdesc)、商品用户id(cmuserid)
     *   商品用户名(username)、商品所在游戏(server)
     * 2.session中获取收藏用户id(couserid)
     * 3.进行收藏操作
     * (2). 取消收藏
     * 1.前端传入商品id(commid)
     * 2.判断是否本人取消收藏
     * 3.进行取消收藏操作
     */
    @ResponseBody
    @PostMapping("/collect/operate")
    public ResultVo insertcollect(@RequestBody Collect collect, HttpSession session){
        String couserid = (String) session.getAttribute("userid");
        Integer colloperate = collect.getColloperate();
        collect.setCouserid(couserid);

        if (StringUtils.isEmpty(couserid)){
            return new ResultVo(false, StatusCode.ACCESSERROR,"请先登录");
        }
                return new ResultVo(true, StatusCode.OK,"删除成功");
            }
            return new ResultVo(false, StatusCode.ERROR,"删除失败");
        }
        return new ResultVo(false,StatusCode.ACCESSERROR,"禁止操作");
    }

    /**
     * 删除评论回复
     * 1.获取session中用户id信息
     * 2.对比用户id信息和回复者id信息:是否满足评论回复者本人或商品发布者
     * 3.进行删除操作
     */
    @ResponseBody
    @PutMapping("/reply/delete/{rid}")
    public ResultVo deletereply(@PathVariable("rid") String rid,HttpSession session){
        String ruserid = (String) session.getAttribute("userid");
        Reply reply = replyService.queryById(rid);
        /**如果是回复者本人或者商品发布者则进行删除操作*/
        if (reply.getRuserid().equals(ruserid) || reply.getSpuserid().equals(ruserid)){
            Integer i = replyService.deleteReply(new Reply().setRid(rid));
            if (i == 1){
                return new ResultVo(true, StatusCode.OK,"删除成功");
            }
            return new ResultVo(false, StatusCode.ERROR,"删除失败");
        }
        return new ResultVo(false,StatusCode.ACCESSERROR,"禁止操作");
    }

}

}

/**
 * @ServerEndpoint 注解是一个类层次的注解,它的功能主要是将目前的类定义成一个websocket服务器端,
 * 注解的值将被用于监听用户连接的终端访问URL地址,客户端可以通过这个URL来连接到WebSocket服务器端
 * @ServerEndpoint 可以把当前类变成websocket服务类
 */
@Controller
@ServerEndpoint(value = "/websocket/{userno}")
public class ChatWebSocket {
    // 这里使用静态,让 service 属于类
    private static ChatmsgService chatMsgService;
    private static UserInfoService mineService;
    // 注入的时候,给类的 service 注入
    @Autowired
    public void setChatService(ChatmsgService chatService,UserInfoService mineService) {
       ChatWebSocket.chatMsgService = chatService;
       ChatWebSocket.mineService=mineService;
    }
    //注入通知类
    @Autowired
    private NoticesService noticesService;

    //静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
    private static int onlineCount = 0;
    //concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。若要实现服务端与单一客户端通信的话,可以使用Map来存放,其中Key可以为用户标识
    private static ConcurrentHashMap<String, ChatWebSocket> webSocketSet = new ConcurrentHashMap<String, ChatWebSocket>();
    //与某个客户端的连接会话,需要通过它来给客户端发送数据
    private Session WebSocketsession;
    //当前发消息的人员编号
    private String userno = "";
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

    }
}

/**
 */

@ControllerAdvice
public class GloableExceptionAop {
    /**
     * shiro异常
     * */
    @ExceptionHandler(value = UnauthorizedException.class)//处理访问方法时权限不足问题
    public String defaultErrorHandler() {
        return "redirect:/noAuth";
    }

    /**
     * runtime异常
     * */
    @ExceptionHandler(RuntimeException.class)
    @ResponseBody
    public String runtimeException(){
        return "出现runtime异常了,这里在捕获全局异常,相当于手写AOP捕获异常。";
    }
}

                .setWhys("您的商品 <a href=/product-detail/"+commid+" style=\"color:#08bf91\" target=\"_blank\" >"+commodity.getCommname()+"</a> 进入待审核队列,请您耐心等待。");
        noticesService.insertNotices(notices);
        return "0";
    }

    /**
     * 上传视频和主图
     */
    @PostMapping("/relgoods/video")
    @ResponseBody
    public JSONObject relgoodsvideo(@RequestParam(value = "file", required = false) MultipartFile file) throws IOException {
        JSONObject res = new JSONObject();
        JSONObject resUrl = new JSONObject();
        String filename = UUID.randomUUID().toString().replaceAll("-", "");
        String ext = FilenameUtils.getExtension(file.getOriginalFilename());
        String filenames = filename + "." + ext;
        String pathname = "D:/file/" + filenames;
        file.transferTo(new File(pathname));
        resUrl.put("src", "/pic/"+filenames);
        res.put("msg", "");
        res.put("code", 0);
        res.put("data", resUrl);
        return res;
    }

    /**
     * 上传其他图片
     */
    @PostMapping(value="/relgoods/images")
    @ResponseBody
    public JSONObject relgoodsimages(@RequestParam(value = "file", required = false) MultipartFile[] file) throws IOException {
        JSONObject res = new JSONObject();
        JSONObject resUrl = new JSONObject();
        List<String> imageurls=new ArrayList<>();
        for (MultipartFile files:file){
            String filename = UUID.randomUUID().toString().replaceAll("-", "");
            String ext = FilenameUtils.getExtension(files.getOriginalFilename());
            String filenames = filename + "." + ext;
            String pathname = "D:/file/" + filenames;
            files.transferTo(new File(pathname));
            imageurls.add("/pic/"+filenames);
            res.put("msg", "");
            res.put("code", 0);
 */
@Controller
public class CommodityController {
    @Autowired
    private CommodityService commodityService;
    @Autowired
    private CommimagesService commimagesService;
    @Autowired
    private LoginService loginService;
    @Autowired
    private UserInfoService userInfoService;
    @Autowired
    private SoldrecordService soldrecordService;
    @Autowired
    private CollectService collectService;
    @Autowired
    private NoticesService noticesService;

    /**
     * 跳转到发布商品
     */
    @GetMapping("/user/relgoods")
    public String torelgoods(HttpSession session){
        /*String userid = (String)session.getAttribute("userid");
        if(userid==null){
            return "redirect:/:";
        }*/
        return "/user/product/relgoods";
    }

    /**
     * 跳转到修改商品
     *  --不能修改已删除、已完成的商品
     *  1、查询商品详情
     *  2、查询商品得其他图
     */
    @GetMapping("/user/editgoods/{commid}")
    public String toeditgoods(@PathVariable("commid")String commid, HttpSession session, ModelMap modelMap){
        /*String userid = (String)session.getAttribute("userid");
        if(userid==null){
            return "redirect:/:";
        }*/
 */
@Controller
public class AdminController {
    @Autowired
    private UserRoleService userRoleService;
    @Autowired
    private LoginService loginService;
    @Autowired
    private UserInfoService userInfoService;
    @Autowired
    private CommodityService commodityService;
    @Autowired
    private NoticesService noticesService;

    /**
     * 管理员跳转登录
     */
    @GetMapping("/admin")
    public String admintologin() {
        return "admin/login/login";
    }

    /**
     * 管理员登录
     * 1.判断输入账号的类型
     * 2.判断是否为管理员或者超级管理员
     * 3.登录
     * */
    @ResponseBody
    @PostMapping("/admin/login")
    public ResultVo adminlogin(@RequestBody Login login, HttpSession session){
        System.out.println("测试是否进入!!!");
        String account=login.getUsername();
        String password=login.getPassword();
        String vercode=login.getVercode();
        UsernamePasswordToken token;
        if(!ValidateCode.code.equalsIgnoreCase(vercode)){
            return new ResultVo(false,StatusCode.ERROR,"请输入正确的验证码");
        }
        //判断输入的账号是否手机号
        if (!JustPhone.justPhone(account)) {
            //输入的是用户名
            String username = account;
            //盐加密
            token=new UsernamePasswordToken(username, new Md5Hash(password,"Game-shops").toString());
        }else {
            //输入的是手机号
            String mobilephone = account;
            login.setMobilephone(mobilephone);
    @GetMapping("/tochatlog")
    public String tochatlog(){
        return "/user/chat/chatlog";
    }
    /**
     * TODO 查询聊天记录
     * */
    @GetMapping("/chatlog/{uid}")
    @ResponseBody
    public List<UserInfo> chatlog(@PathVariable("uid")String uid,HttpSession session){
        String userid=(String) session.getAttribute("userid");
        List<UserInfo> mines = chatmsgService.LookChatMsg(new ChatMsg().setSenduserid(userid).setReciveuserid(uid));
        return mines;
    }
    /**
     * TODO 初始化聊天
     * */
    @GetMapping("/initim")
    @ResponseBody
    public InitImVo initim(HttpSession session){
        String userid = (String) session.getAttribute("userid");
        InitImVo initImVo=new InitImVo();
        //个人信息
        UserInfo mine=friendsService.LookUserMine(userid);
        //好友列表
        List<UserInfo> list=friendsService.LookUserFriend(userid);
        Friend friend=new Friend().setId("2").setGroupname("分组").setList(list);
        List<Friend> friendList=new ArrayList<>();
        friendList.add(friend);
        //群组信息
        List<Groups> groupList=new ArrayList<>();
        //Data数据
        ImData imData=new ImData().setMine(mine).setFriend(friendList).setGroup(groupList);
        initImVo.setCode(0).setMsg("").setData(imData);
        return initImVo;
    }
}

@Controller
public class IndexController {
    /**
                return new ResultVo(false,StatusCode.ERROR,"删除失败");
            }else {
                return new ResultVo(false,StatusCode.ACCESSERROR,"权限不足,无法删除");
            }
        }
    }

    /**
     *查看公告详情
     * **/
    @GetMapping("/news/detail/{id}")
    public String queryNewsById (@PathVariable("id") String id,ModelMap modelMap){
        //浏览量+1
        newsService.addNewsRednumber(id);
        News news = newsService.queryNewsById(id);
        if (StringUtils.isEmpty(news)){
            return "/error/404";
        }
        modelMap.put("news",news);
        return "/common/newsdetail";
    }
    /**
     *跳转到发布公告
     * **/
    @GetMapping("/news/torelnews")
    public String torelnews (){
        return "/admin/news/relnews";
    }

    /**
     *跳转到修改公告
     * **/
    @GetMapping("/news/toupdate/{id}")
    public String toupdate (@PathVariable("id") String id, ModelMap modelMap, HttpSession session){
        String username=(String) session.getAttribute("username");
        News news = newsService.queryNewsById(id);
        /**如果是本人则可以跳转修改*/
        if (news.getUsername().equals(username)){
            modelMap.put("qx",1);
            modelMap.put("news",news);
            return "/admin/news/updatenews";
    public String queryNewsById (@PathVariable("id") String id,ModelMap modelMap){
        //浏览量+1
        newsService.addNewsRednumber(id);
        News news = newsService.queryNewsById(id);
        if (StringUtils.isEmpty(news)){
            return "/error/404";
        }
        modelMap.put("news",news);
        return "/common/newsdetail";
    }
    /**
     *跳转到发布公告
     * **/
    @GetMapping("/news/torelnews")
    public String torelnews (){
        return "/admin/news/relnews";
    }

    /**
     *跳转到修改公告
     * **/
    @GetMapping("/news/toupdate/{id}")
    public String toupdate (@PathVariable("id") String id, ModelMap modelMap, HttpSession session){
        String username=(String) session.getAttribute("username");
        News news = newsService.queryNewsById(id);
        /**如果是本人则可以跳转修改*/
        if (news.getUsername().equals(username)){
            modelMap.put("qx",1);
            modelMap.put("news",news);
            return "/admin/news/updatenews";
        }
        modelMap.put("news",news);
        modelMap.put("qx",0);
        return "/admin/news/updatenews";
    }

    /**
     *修改公告
     * **/
    @ResponseBody
    @PutMapping("/news/update")
    public ResultVo updateNews (@RequestBody News news){
        Integer i = newsService.updateNews(news);
        if (i == 1){
            return new ResultVo(true,StatusCode.OK,"修改成功");
        }
    public ResultVo deletecollect(@PathVariable("id") String id,HttpSession session){
        String couserid = (String) session.getAttribute("userid");
        Collect collect = new Collect().setId(id).setCouserid(couserid);
        Collect collect1 = collectService.queryCollectStatus(collect);
        /**判断是否为本人操作*/
        if (collect1.getCouserid().equals(couserid)){
            collect.setColloperate(2);
            Integer i = collectService.updateCollect(collect);
            if (i == 1){
                return new ResultVo(true, StatusCode.OK,"取消成功");
            }
            return new ResultVo(false,StatusCode.ERROR,"取消失败");
        }
        return new ResultVo(false,StatusCode.ACCESSERROR,"禁止操作");
    }

    /**
     * 分页查看用户所有收藏内容
     * 前端传入页码、分页数量
     * 查询分页数据
     */
    @ResponseBody
    @GetMapping("/user/collect/queryall")
    public LayuiPageVo usercollect(int limit, int page, HttpSession session) {
        String couserid = (String) session.getAttribute("userid");
        List<Collect> collectList = collectService.queryAllCollect((page - 1) * limit, limit, couserid);
        Integer dataNumber = collectService.queryCollectCount(couserid);
        return new LayuiPageVo("",0,dataNumber,collectList);
    }
}

            commodity.setOtherimg(imagesList);
        }
        return new ResultVo(true,StatusCode.OK,"查询成功",commodityList);
    }

    /**
     * 产品清单分页数据
     * 前端传入商品类别(category)、区域(area)
     * 最低价(minmoney)、最高价(maxmoney)
     * 后端根据session查出个人本校信息(server)
     * */
    @GetMapping("/list-number/{category}/{area}/{minmoney}/{maxmoney}")
    @ResponseBody
    public PageVo productListNumber(@PathVariable("category") String category, @PathVariable("area") String area,
                                    @PathVariable("minmoney") BigDecimal minmoney, @PathVariable("maxmoney") BigDecimal maxmoney,
                                    HttpSession session) {
        String server=null;
        if(!area.equals("全部")){
            String userid = (String) session.getAttribute("userid");
            UserInfo userInfo = userInfoService.LookUserinfo(userid);
            server = userInfo.getServer();
        }
        Integer dataNumber = commodityService.queryAllCommodityByCategoryCount(area, server, category, minmoney, maxmoney);
        return new PageVo(StatusCode.OK,"查询成功",dataNumber);
    }

    /**
     * 产品清单界面
     * 前端传入商品类别(category)、当前页码(nowPaging)、区域(area)
     * 最低价(minmoney)、最高价(maxmoney)、价格升序降序(price:0.不排序 1.升序 2.降序)
     * 后端根据session查出个人本校信息(server)
     * */
    @GetMapping("/product-listing/{category}/{nowPaging}/{area}/{minmoney}/{maxmoney}/{price}")
    @ResponseBody
    public ResultVo productlisting(@PathVariable("category") String category, @PathVariable("nowPaging") Integer page,
                                 @PathVariable("area") String area, @PathVariable("minmoney") BigDecimal minmoney, @PathVariable("maxmoney") BigDecimal maxmoney,
                                 @PathVariable("price") Integer price, HttpSession session) {
        String server=null;
        if(!area.equals("全部")) {
            String userid = (String) session.getAttribute("userid");
            UserInfo userInfo = userInfoService.LookUserinfo(userid);
            server = userInfo.getServer();
        }
        List<Commodity> commodityList = commodityService.queryAllCommodityByCategory((page - 1) * 16, 16, area, server, category, minmoney, maxmoney);
        for (Commodity commodity : commodityList) {
            /**查询商品对应的其它图片*/
            List<String> imagesList = commimagesService.LookGoodImages(commodity.getCommid());
            commodity.setOtherimg(imagesList);
                        }
                        return i;
                    }
                });
            }
        }
        return new ResultVo(true,StatusCode.OK,"查询成功",commodityList);
    }

    /**
     * 分页展示个人各类商品信息
     *前端传入页码、分页数量
     *前端传入商品信息状态码(commstatus)-->全部:100,已审核:1,待审核:3,违规:0,已完成:4
     */
    @GetMapping("/user/commodity/{commstatus}")
    @ResponseBody
    public LayuiPageVo userCommodity(@PathVariable("commstatus") Integer commstatus, int limit, int page, HttpSession session) {
        String userid = (String) session.getAttribute("userid");
        //如果未登录,给一个假id
        if(StringUtils.isEmpty(userid)){
            userid = "123456";
        }
        List<Commodity> commodityList=null;
        Integer dataNumber;
        if(commstatus==100){
            commodityList = commodityService.queryAllCommodity((page - 1) * limit, limit, userid,null);
            dataNumber = commodityService.queryCommodityCount(userid,null);
        }else{
            commodityList = commodityService.queryAllCommodity((page - 1) * limit, limit, userid,commstatus);
            dataNumber = commodityService.queryCommodityCount(userid,commstatus);
        }
        return new LayuiPageVo("",0,dataNumber,commodityList);
    }

    /**
     * 个人对商品的操作
     * 前端传入商品id(commid)
     * 前端传入操作的商品状态(commstatus)-->删除:2  已完成:4
     * */
    @ResponseBody
    @GetMapping("/user/changecommstatus/{commid}/{commstatus}")
    public ResultVo ChangeCommstatus( @PathVariable("commid") String commid, @PathVariable("commstatus") Integer commstatus, HttpSession session) {
        Integer i = commodityService.ChangeCommstatus(commid, commstatus);
        if (i == 1){
            /**如果商品已售出*/
            // dddd
            if (commstatus == 4){

                    i = 1;
                }
                return i;
            }
        });

        System.out.println("排序后的商品为:");
        for (Commodity commodity : commodityList) {
            System.out.println(commodity);
        }

        System.out.println("查询的服务器为:" + server);
        System.out.println("查询的商品分页为:" + pages);
        System.out.println("查询的商品数量为:" + dataNumber);
    }

}

/**
 * @ServerEndpoint 注解是一个类层次的注解,它的功能主要是将目前的类定义成一个websocket服务器端,
 * 注解的值将被用于监听用户连接的终端访问URL地址,客户端可以通过这个URL来连接到WebSocket服务器端
 * @ServerEndpoint 可以把当前类变成websocket服务类
 */
@Controller
@ServerEndpoint(value = "/websocket/{userno}")
public class ChatWebSocket {
    // 这里使用静态,让 service 属于类
    private static ChatmsgService chatMsgService;
    private static UserInfoService mineService;
            return new ResultVo(false,StatusCode.ERROR,"请重新获取验证码");
        }
        if (rel.equalsIgnoreCase(vercode)) {//验证码正确
            Login login = new Login().setUserid(userid).setMobilephone(mobilephone);
            UserInfo userInfo = new UserInfo().setUserid(userid).setMobilephone(mobilephone);
            Integer integer = loginService.updateLogin(login);
            Integer integer1 = userInfoService.UpdateUserInfo(userInfo);
            if (integer == 1 && integer1 == 1) {
                return new ResultVo(true, StatusCode.OK, "更换手机号成功");
            }
            return new ResultVo(false, StatusCode.SERVERERROR, "系统错误,更换失败");
        }
        return new ResultVo(false,StatusCode.ERROR,"验证码错误");
    }

}

/**
 * <p>
 *  评论和回复控制器
 * </p>
 *
 */
@Controller
public class CommentReplyController {
    @Autowired
    private CommodityService commodityService;
    @Autowired
    private CommentService commentService;
    @Autowired
    private ReplyService replyService;
    @Autowired
     * 后台分页查看公告列表
     * 1.前端传入页码、分页数量
     * 2.查询分页数据
     */
    @ResponseBody
    @GetMapping("/news/queryall")
    public LayuiPageVo queryAllNews(int limit, int page) {
        List<News> newsList = newsService.queryAllNews((page - 1) * limit, limit);
        Integer dataNumber = newsService.LookNewsCount();
        return new LayuiPageVo("",0,dataNumber,newsList);
    }

    /**
     * 首页公告分页数据
     * */
    @GetMapping("/news/index/number")
    @ResponseBody
    public PageVo newsNumber(){
        Integer dataNumber = newsService.LookNewsCount();
        return new PageVo(StatusCode.OK,"查询成功",dataNumber);
    }

    /**
     * 首页网站公告
     * 1.前端传入页码、分页数量
     * 2.查询分页数据
     * */
    @GetMapping("/news/index/{page}")
    @ResponseBody
    public ResultVo newsIndex(@PathVariable("page") Integer page){
        List<News> newsList = newsService.queryAllNews((page - 1) * 9, 9);
        return new ResultVo(true,StatusCode.OK,"查询成功",newsList);
    }

}

     * 用户列表
     * */
    @GetMapping("/admin/userlist")
    public String userlist(){
        return "/admin/user/userlist";
    }

    /**
     * 管理员列表
     * */
    @RequiresPermissions("admin:set")
    @GetMapping("/admin/adminlist")
    public String adminlist(){
        return "/admin/user/adminlist";
    }

    /**
     * 分页查询不同角色用户信息
     * roleid:1普通成员 2管理员
     * userstatus:1正常 0封号
     */
    @GetMapping("/admin/userlist/{roleid}/{userstatus}")
    @ResponseBody
    public LayuiPageVo userlist(int limit, int page,@PathVariable("roleid") Integer roleid,@PathVariable("userstatus") Integer userstatus) {
        List<UserInfo> userInfoList = userInfoService.queryAllUserInfo((page - 1) * limit, limit,roleid,userstatus);
        Integer dataNumber = userInfoService.queryAllUserCount(roleid);
        return new LayuiPageVo("",0,dataNumber,userInfoList);
    }

    /**
     * 设置为管理员或普通成员(roleid)
     * 1:普通成员   2:管理员
     */
    @PutMapping("/admin/set/administrator/{userid}/{roleid}")
    @ResponseBody
    public ResultVo setadmin(@PathVariable("userid") String userid,@PathVariable("roleid") Integer roleid) {
        if (roleid == 2){
            Integer i = loginService.updateLogin(new Login().setUserid(userid).setRoleid(roleid));
            if (i == 1){
                userRoleService.UpdateUserRole(new UserRole().setUserid(userid).setRoleid(2).setIdentity("网站管理员"));
                /**发出设置为管理员的系统通知*/
                Notices notices = new Notices().setId(KeyUtil.genUniqueKey()).setUserid(userid).setTpname("系统通知")
                        .setWhys("恭喜您已被设置为网站管理员,努力维护网站的良好氛围。");
                noticesService.insertNotices(notices);
                return new ResultVo(true, StatusCode.OK, "设置管理员成功");
            }

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值