springboot+bootstrap实现图书商城管理(大三下学期课程设计)

在csdn上记一次自己的课程设计过程(已经实习两个月了、感觉这个很容易做。支付可能需要多花点时间、):

在此框架基础之上权限认证管理设置成功:https://blog.csdn.net/weixin_43304253/article/details/121111530
动态搜索书籍信息(包括在一定价格范围内查询)https://blog.csdn.net/weixin_43304253/article/details/120920214
课程名称:企业项目实训II
设计题目:大学当图书商城

已知技术参数和设计要求:

1.问题描述(功能要求):
1.1 顾客端
1)注册登录:游客可浏览所有图书,只有注册用户才能添加购物车、下订单购买、评论;
2)图书分类浏览:图书分三个层级进行分类浏览;
3)动态搜索图书:可以按书名、作者、出版社及价格范围进行搜索,搜索的图书分页显示;
4)图书详情:可从图书列表中进一步看到图书的详细信息,包括书号、书名、作者、出版社、印次、内容简介等信息;
5)添加并管理购物车:登录用户可以选择图书加入到购物车,并可对购物车的图书进行增删改查的操作;
6)下订单:登录用户可对图书进行下订单,同时可查看订单当前的状态,订单状态包括待付款(模拟)、待发货(模拟)、待收货(模拟)、待评论;
7)模拟支付:所有注册用户都有一个余额钱包,可模拟充值,充值记录保存下来并可查看,利用余额钱包进行付款。或者使用支付宝的模拟支付接口进行支付;
8)商品评论:购买完图书后进行评价,给一个1-5等级及相应的评论内容。
1.2商家
1)商家注册登录:注册信息包括商家名称,商家地址、经营类型、注册资金、log图片等基本信息,刚注册的商家处于未审核状态,只有等待区域运营方审核后才能正常登录。区域运营方由管理员在后台直接添加;
2)商家管理自家商品:可对商品进行相应的增、删、改、查的操作;
3)商家管理自家店铺:商家可根据平台提供的模板,对店铺进行管理;
4)商家管理订单:商家可对顾客下的订单进行相应的操作,如查看订单、发货(模拟)、查看评论。

  1. 运行环境要求:
    (1)客户端:
    Windows操作系统
    浏览器
    (2)服务器:
    windows操作系统
    Tomcat 服务器
    MySQL 数据库服务器

  2. 技术要求:
    (1)需求分析规格说明书与用例规约
    (2)系统数据库设计,时序图,类图
    (3)系统采用SSM框架技术,完整编码(采用spring boot和vue)
    (4)为保证系统安全性,要求用到日志
    (5)在必要地方使用事务技术
    (6)在必要地方使用2个以上设计模式

设计工作量:
8周

工作计划:
共安排8周时间进行集中实训,软件开发步骤如下,
第1-2周:需求分析、数据库设计、系统设计
第3-7周:编码
第8周:系统测试、答辩、撰写设计说明书

工作进展:在开始编辑这篇文章的时候、距离课程设计已经过了两个周(本人在实习、只能抽出空闲时间来写和周六、周日的时间)现在这个系统的后台逻辑几乎都实现了、还有支付功能未实现。前端页面的美化后来进一步处理吧。

目前的目录结构、后续还需要改进
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

1、搭建框架
(我花了一天的时间将整个项目的框架搭建起来、使用spring boot整合mybatis、thymeleaf和shiro)
使用spring boot是真的爽到上天、spring简直就是配置地狱。

  • 整合mybatis的目的是简化sql的编写管理
  • 整合thymeleaf的目的是数据的交互
  • 整合shiro的目的是简化权限认证以及授权…

使用到的maven依赖

    <dependencies>
        <!--整合shiro
            subject:用户
            security manager:管理所有的用户
            realm:连接数据库

        -->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.4.1</version>
        </dependency>
        <dependency>
            <groupId>com.github.theborakompanioni</groupId>
            <artifactId>thymeleaf-extras-shiro</artifactId>
            <version>2.0.0</version>
        </dependency>


        <!--整合mybatis-->
        <!-- https://mvnrepository.com/artifact/org.mybatis.spring.boot/mybatis-spring-boot-starter -->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.0</version>
        </dependency>


        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
      <!--   JDBC-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>

        <!--  Mysql-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.6</version>
        </dependency>

        <!-- 导入页面依赖
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>    -->

<!--        thymeleaf,都是基于3.x开发的-->
        <dependency>
            <groupId>org.thymeleaf</groupId>
            <artifactId>thymeleaf-spring5</artifactId>
        </dependency>

        <dependency>
            <groupId>org.thymeleaf.extras</groupId>
            <artifactId>thymeleaf-extras-java8time</artifactId>
        </dependency>


        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

<!--        简化set和get方法-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.16.10</version>
            <scope>provided</scope>
        </dependency>

<!--        导入日志依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <!-- 日志文件 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-log4j</artifactId>
            <version>1.3.8.RELEASE</version>
        </dependency>

        <!-- 分页插件 -->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper-spring-boot-starter</artifactId>
            <version>1.2.5</version>
        </dependency>

    </dependencies>

2、接下来就是编写相应的代码(太简单了、几乎是无脑操作)

随便展示一个书籍的操作、从前台页面到后端代码的编写

先看效果图
在这里插入图片描述

前端页面代码


<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>书籍列表</title>
    <!-- 新 Bootstrap 核心 CSS 文件 -->
    <link href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">

</head>
<body>


<div class="container">

    <!--导航栏部分-->
    <nav class="navbar navbar-inverse">
        <div class="container-fluid">
            <!-- Brand and toggle get grouped for better mobile display -->
            <div class="navbar-header">
                <a class="navbar-brand" href="#">书籍商城</a>
            </div>

            <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
                <ul class="nav navbar-nav">
                    <li>
                        <a th:href="@{/customer/toCustomerIndex}">个人信息</a>
                    </li>
                    <li>
                        <a href="#">购买记录</a>
                    </li>
                    <li>
                        <a href="#">购物车</a>
                    </li>
                    <li>
                        <a th:href="@{/book/bookList}">书籍商城</a>
                    </li>

                </ul>


            </div>
            <!-- /.navbar-collapse -->
        </div>
        <!-- /.container-fluid -->
    </nav>
    <hr>

    <div class="row ">
        <form  th:action="@{/book/bookList}" style="float: left">

            <div class="col-md-2">
                <input type="text" name="queryBookName" class="form-control" placeholder="书籍名">
            </div>
            <div class="col-md-2" >
                <input type="text" name="queryBookAuthor" class="form-control" placeholder="作者名">
            </div>
            <div class="col-md-2" >
                <input type="text" name="queryBookAddress" class="form-control" placeholder="出版社">
            </div>

                <div class="col-md-4" >
                    <div class="col-row">
                        <div class="col-md-5">
                            <input type="text" name="minPrice" class="form-control" placeholder="最低价格">
                        </div>
                           <div class="col-md-1">
                               <span><strong>:</strong></span>
                           </div>
                        <div class="col-md-5">
                            <input type="text" name="maxPrice" class="form-control" placeholder="最高价格">
                        </div>
                    </div>

                </div>
            <input type="submit" value="查询" class="btn btn-primary">
        </form>

    </div>
<hr>
    <div class="row clearfix">
        <div class="col-md-12 column">
            <table class="table table-hover table-striped">
                <thead>
                <tr>
<!--                    <th>书籍编号</th>-->
                    <th>书籍名称</th>
                    <th>书籍作者</th>
                    <th>书籍价格</th>
                    <th>书籍出版社</th>
                    <th>操作</th>
                </tr>
                </thead>
                <!--查询书籍处理-->
                <tbody>
                <tr th:each="book:${bookList}">
<!--                    <td  th:text="${book.getBookId()}">编号</td>-->
                    <td th:text="${book.getBookName()}">书名</td>
                    <td th:text="${book.getBookAuthor()}">作者</td>
                    <td th:text="${book.getPrice()}"></td>
                    <td th:text="${book.getAddress()}">出版社</td>
                    <td><a  th:href="@{/book/todetail(bookId=${book.getBookId()})}" >详情</a>&nbsp;&nbsp;|&nbsp;&nbsp;<a  th:href="@{/shop/addshop(bookId=${book.getBookId()})}" >加入购物车</a></td>


                </tr>
                </tbody>
            </table>
            <div class="col-md-3">
                <a class="btn btn-primary" th:href="@{/book/bookList}">返回查询首页</a>
            </div>
            <div class="col-md-5">
                <p ><strong>当前</strong> <span th:text="${pageInfo.pageNum}"></span><strong> 页,总 </strong><span th:text="${pageInfo.pages}"></span><strong> 页,共</strong> <span th:text="${pageInfo.total}"></span><strong> 条记录</strong></p>

            </div>

            <div class="col-md-4">
                <div class="row">
                    <div class="col-md-12">
                        <a class="btn btn-primary" th:href="@{/book/bookList}">首页</a>
                        <a class="btn btn-primary" th:href="@{/book/bookList(pageNum=${pageInfo.hasPreviousPage}?${pageInfo.prePage}:1)}">上一页</a>
                        <a class="btn btn-primary" th:href="@{/book/bookList(pageNum=${pageInfo.hasNextPage}?${pageInfo.nextPage}:${pageInfo.pages})}">下一页</a>
                        <a class="btn btn-primary" th:href="@{/book/bookList(pageNum=${pageInfo.pages})}">尾页</a>
                    </div>
                </div>
            </div>

        </div>
    </div>

</div>
</body>
</html>



编写的书籍实体类

(没有使用lombox、失去了Java的灵魂、不喜欢用)

package com.example.zheng.pojo;

public class Books {
    private String bookId;
    private String bookName;
    private String bookAuthor;
    private Double price;
    private String address;
    private String impression;
    private String introduce;

    //新增这两个字段的原因,将前台传入的价格范围封装、在编写sql语句的时候动态替换价格参数
    private Double minPrice;//最小价格
    private Double maxPrice;//最大价格

    public Books(String bookId, String bookName, String bookAuthor, Double price, String address, String impression, String introduce, Double minPrice, Double maxPrice) {
        this.bookId = bookId;
        this.bookName = bookName;
        this.bookAuthor = bookAuthor;
        this.price = price;
        this.address = address;
        this.impression = impression;
        this.introduce = introduce;
        this.minPrice = minPrice;
        this.maxPrice = maxPrice;
    }

    public Double getPrice() {
        return price;
    }

    public void setPrice(Double price) {
        this.price = price;
    }

    public Double getMinPrice() {
        return minPrice;
    }

    public void setMinPrice(Double minPrice) {
        this.minPrice = minPrice;
    }

    public Double getMaxPrice() {
        return maxPrice;
    }

    public void setMaxPrice(Double maxPrice) {
        this.maxPrice = maxPrice;
    }

    public Books() { }


    public String getBookId() {
        return bookId;
    }

    public void setBookId(String bookId) {
        this.bookId = bookId;
    }

    public String getBookName() {
        return bookName;
    }

    public void setBookName(String bookName) {
        this.bookName = bookName;
    }

    public String getBookAuthor() {
        return bookAuthor;
    }

    public void setBookAuthor(String bookAuthor) {
        this.bookAuthor = bookAuthor;
    }



    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public String getImpression() {
        return impression;
    }

    public void setImpression(String impression) {
        this.impression = impression;
    }

    public String getIntroduce() {
        return introduce;
    }

    public void setIntroduce(String introduce) {
        this.introduce = introduce;
    }
}

controller层

(这里的传输数据可以使用其他的方式ajax等等、我这里是暂时走通前后端。后期会进一步改造)

package com.example.zheng.controller;


import com.example.zheng.pojo.Books;
import com.example.zheng.service.BooksService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

import java.util.List;

@Controller
public class BooksController {

    @Autowired
    BooksService booksService;


    @RequestMapping("/book/bookList")
    public String bookList(@RequestParam(defaultValue = "1",value = "pageNum") Integer pageNum,Double minPrice,Double maxPrice, String queryBookAuthor, String queryBookAddress, String queryBookName, Model model){
        PageHelper.startPage(pageNum,10);
        Books books =new Books();
        books.setBookAuthor(queryBookAuthor);
        books.setBookName(queryBookName);
        books.setAddress(queryBookAddress);
        books.setMinPrice(minPrice);
        books.setMaxPrice(maxPrice);

        try {
            List<Books> list = booksService.queryBookList(books);
            PageInfo<Books> pageInfo = new PageInfo<Books>(list);
            model.addAttribute("pageInfo",pageInfo);
            if(list == null){
                model.addAttribute("error","书籍列表为空");
            }else{
                model.addAttribute("bookList",list);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "allBook";

    }

    @RequestMapping("/book/todetail")
    public String bookDetail(String bookId,Model model){
        try {
            Books books = booksService.queryBookById(bookId);
            if(books == null){
                model.addAttribute("error","查询书籍详细信息失败");
            }else{
                model.addAttribute("books",books);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return "bookDetail";


    }

}

service层

package com.example.zheng.service;

import com.example.zheng.pojo.Books;

import java.util.List;

public interface BooksService {
    /**
     * 查询图书
     */
    public List<Books> queryBookList(Books books);

    /**
     * 查询书籍的详细信息通过书籍编号
     */

    public Books queryBookById(String bookId);
}

实现类

package com.example.zheng.service.impl;

import com.example.zheng.mapper.BooksMapper;
import com.example.zheng.pojo.Books;
import com.example.zheng.service.BooksService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class BooksServiceImpl implements BooksService {

    @Autowired
    BooksMapper booksMapper;

    //查询所有书籍
    @Override
    public List<Books> queryBookList(Books books) {
        return booksMapper.queryBookList(books);
    }

    //根据id查询具体书籍信息
    @Override
    public Books queryBookById(String bookId) {
        return booksMapper.queryBookById(bookId);
    }
}

Dao层

package com.example.zheng.mapper;

import com.example.zheng.pojo.Books;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;

import java.util.List;

@Mapper    //这个注解表示这个是mybatis的mapeper
@Repository
public interface BooksMapper {

    /**
     * 查询图书
     */
    public List<Books> queryBookList(Books books);



    /**
     * 查询书籍的详细信息通过书籍编号
     */

    public Books queryBookById(String id);



}

sql语句

<?xml version="1.0" encoding="UTF8"?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.zheng.mapper.BooksMapper">

    <select id="queryBookList" parameterType="com.example.zheng.pojo.Books" resultType="com.example.zheng.pojo.Books">
        select * from bookss
        <where>
             1=1
        <if test="bookName != null and bookName != ''">
            And bookName =#{bookName}
        </if>
        <if test="bookAuthor != null and bookAuthor != ''">
            And bookAuthor =#{bookAuthor}
        </if>
        <if test="address != null and address !=''">
            And address =#{address}
        </if>

        <if test="minPrice !=null and minPrice !=''">
            And price > #{minPrice}
            <if test="maxPrice !=null and maxPrice !=''">
                And price &lt; #{maxPrice}
            </if>
        </if>

        </where>
    </select>




    <select id="queryBookById" resultType="com.example.zheng.pojo.Books">
        select * from bookss where bookId=#{bookId}
    </select>


</mapper>

差不多整个流程就是这样。大差不差。

在开发中遇到的问题以及解决的办法?

一、在整合框架的时候遇到的奇葩问题:

1、跳转到指定页面出现问题?必须要在properties中配置,这样的目的是,说白了是个视图解析器。和我以前写的不一样,这个也太简单了
2、必须在pom依赖中添加试图解析的依赖。
3、图片路径的问题,添加static则不显示图片,这个是相对路径,找不出来。就很离谱。解决方法:把static删除,然后重启idea。
4、@Controller。跳转到指定页面中要使用这个注解,另外一个出现问题

二、使用thymeleaf在进行传输数据的时候遇到的奇葩

这里需要注意的是,怎样获取当前书籍的主键、以及怎样将这个主键传递到controller层对应的方法中。将这个主键作为查询条件。
解决的方法:<a th:href="@{/book/todetail(bookId=${book.getBookId()})}" >详情</a>
这个方法是thymleaf特有的传输形式

1、改进书籍展示的信息、将书籍编号隐藏。只给顾客展示、书名、作者、出版社、价格

图片
解决办法:1、首先是想到隐藏该列信息、但是没能成功。2、直接将该列信息代码删除、在点击详情需要根据改行的图书主键搜索数据库。由于当前的对象中,已经包含该图书的所有信息。可以直接拿来使用。当前行图书主键存在的意义不是很大。

三、实现在一定价格区间内搜索图书。

遇到的问题:编写的问题sql语句中的价格参数是变动的。不能将其写死在sql中。

解决办法:直接在前端页面设置两个输入框,用来接受数据。同时在实体类书籍中添加最大价格和最小价格两个属性、将前端的数据封装到实体类中,然后将数据直接传输到sql中。

遇到的问题:在新增两个属性后、查询不到数据、爆空指针异常。

经过分析发现、在实体类中书籍的价格应使用Double而不是double.idea没有给我报错、离谱。这种错误我也是醉了。我还真找了好一会。

遇到的问题:获得了参数、在写入sql中,<号不能使用。总是爆红、上网搜索、需要使用转移字符:&lt;
图片

四、遇到的问题? 怎样将查询到的用户权限放入shiro中、进行接下来的认证。

解决办法:将查询到的用户
已经查询到当前用户具有的权限

 //授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {

        System.out.println("执行了授权");

        //拿到当前登录的这个对象
        Subject subject = SecurityUtils.getSubject();
        Customer currentCustomer = (Customer) subject.getPrincipal();//拿到对象
       //设置当前用户的权限
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
         //设置集合
        Collection<String> perStringCollection = new HashSet<String>();

        //已经查询到当前用户具有的权限
        Set<Roles> permissionSet =rolesService.queryRoles(currentCustomer.getUsercount());
        for(Roles perm : permissionSet){
            //将每一个当前用户的权限加入
            perStringCollection.add(perm.getAuthName());
        }
        info.addStringPermissions(perStringCollection);
        return info;


    }

五、根据登录用户、在查询购物车的时候、查询当前用户的购物车。在购买商品的时候加入到当前用户的购物车中

主要的代码是:

Customer parent = (Customer) SecurityUtils.getSubject().getPrincipal();

待编辑

  • 12
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 12
    评论
### 回答1: 以下是软件工程课程设计管理系统的基本时序图: 1. 学生提交课程设计申请 学生在系统中提交课程设计申请,系统验证并保存数据。 2. 教师审核课程设计申请 教师登录系统后,可以查看学生提交的课程设计申请,审核通过或驳回申请。 3. 学生查看课程设计状态 学生登录系统后,可以查看自己提交的课程设计申请状态,包括审核中、通过或驳回等。 4. 教师指导学生进行课程设计 教师审核通过学生的课程设计申请后,可以与学生进行沟通和指导,帮助其完成课程设计。 5. 学生提交课程设计成果 学生完成课程设计后,提交课程设计成果,系统验证并保存数据。 6. 教师评审课程设计成果 教师登录系统后,可以查看学生提交的课程设计成果,评审成果并给出评价。 7. 学生查看课程设计成果评审结果 学生登录系统后,可以查看自己提交的课程设计成果评审结果,包括评审通过或未通过等。 8. 系统管理员维护系统 系统管理员登录系统后,可以对系统进行维护和管理,包括用户管理、数据备份等操作。 ### 回答2: 软件工程课程设计管理系统主要用于管理和协调课程设计项目的开发过程,包括任务分配、进度跟踪、资源管理等功能。以下是软件工程课程设计管理系统的时序图设计: 1. 学生提交课程设计: 学生通过系统界面提交课程设计的相关信息和文档。系统接收到请求后,验证学生身份并保存提交的信息。 2. 教师审核课程设计: 教师通过系统界面查看学生提交的课程设计。系统向教师发送通知,教师查看并审核课程设计,可以选择通过或拒绝。系统根据审核结果发送通知给学生。 3. 任务分配: 教师在系统界面中分配课程设计任务给学生或小组。系统发送任务分配通知给学生,并记录任务分配的相关信息。 4. 进度跟踪: 学生通过系统界面随时更新课程设计的进度,并上传相关文档。系统记录学生的进度更新和文档上传信息。 5. 资源管理: 系统根据学生提交的课程设计进度和需求,自动为学生分配相关资源,包括人力、设备和软件工具。系统发送资源分配通知给学生和相关教师。 6. 提醒和通知: 系统根据设定的时间节点自动发送提醒和通知给学生和教师,包括任务截止日期、进度更新等。学生和教师可以通过系统界面查看和回复通知。 7. 结题评审: 学生完成课程设计后,可以申请结题评审。系统接收评审申请后,通知相关教师进行评审,并记录评审结果。 8. 成绩录入: 教师根据结题评审结果,在系统界面中录入学生的课程设计成绩。系统保存成绩信息,并发送成绩通知给学生。 通过以上时序图设计,软件工程课程设计管理系统可以实现学生提交课程设计、教师审核任务、任务分配、进度跟踪、资源管理、提醒和通知、结题评审和成绩录入等功能,提高课程设计管理的效率和准确性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Mr.Aholic

整理不易、多谢支持

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值