图书管理系统简易版(Java)

具体需求

在管理控制台实现图书管理操作

任务概述

管理员注册or登陆
登陆成功,进行图书管理

  • 图书新增
  • 图书修改
  • 图书删除
  • 根据图书名称模糊查找图书
  • 查看所有图书 (三种排序)
    1.价格从高到低排序
    2.价格从低到高排序
    3.新旧排序(出版日期排序)

任务过程

  1. 思考图书对象包含哪些属性
  2. 使用合理的数据结构存储
  3. 进行编码(有意识的进行异常处理)
  4. 测试

思路及代码实现

※第一部分: 管理员注册与登录

一、对象

创建一个pojo包,新建类Manager(管理员)

Manager
  • 定义成员变量,并通过setter和getter来赋值和取值
	private String name;//用户名
    private String password;//密码

 	 /**
     * setter和getter设置和获取
     * @return
     */
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

  • 构造无参和全参的构造方法
 /**
     * 无参构造方法
     */
    public Manager() {
    }

    /**
     * 全参构造方法
     */
    public Manager(String name, String password) {
        this.name = name;
        this.password = password;
    }
  • equals进行比较
	/**
     * equals进行比较
     */
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Manager manager = (Manager) o;
        return Objects.equals(name, manager.name) &&
                Objects.equals(password, manager.password);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, password);
    }

二、自定义异常

OutNumberBoundException

创建一个exception包,新建异常OutNumberBoundException

public class OutNumberBoundException extends Throwable {
    public OutNumberBoundException(String s) {
        super(s);
    }
}

三、视图分析

主要负责输入输出的视图交互模块

创建一个view包,新建类ManagerView

ManagerView
  • 进入系统和退出系统
    /**
     * 进入系统
     */
	public static void welcome(){
        System.out.println("欢迎进入图书管理系统!");
    }

    /**
     * 退出系统
     */
    public static void bye(){
        System.out.println("感谢使用图书管理系统!");
    }
主界面

编写主界面main,通过输入来进入图书管理系统主界面(选择注册or登录)
1.管理员登录
2.管理员注册
0.退出系统

由于输入012三位数才有效,其它值均无效,因此可以自定义函数vaildNum来处理输入、捕获异常,
当输入的值不为012或输入为字符时,输出异常并重新输入,因此用while循环进行输入,当输入值符合时break;
返回输入的值

/**
     *图书管理系统主界面(选择注册or登录)
     */
    public static int main(){
        int mainNum = 0;
        do{
            System.out.println("请选择您要进行的操作:");
            System.out.println("1.管理员登录");
            System.out.println("2.管理员注册");
            System.out.println("0.退出系统");
            String s = input.nextLine();
            try{
                mainNum = validNum(s,0,2);
                break;
            }catch(NumberFormatException | OutNumberBoundException e){
                System.out.println(e.getMessage());
            }
        }while(true);
        return mainNum;
    }

  • vaildNum处理输入、捕获异常(判断输入是否为数字、是否在有效范围内)
   /**
     * 判断输入是否为数字、是否在有效范围内
     * @param s
     * @param begin
     * @param end
     * @return
     * @throws NumberFormatException
     * @throws OutNumberBoundException
     */
    static int validNum(String s, int begin, int end) throws NumberFormatException, OutNumberBoundException {
        try{
            int num = Integer.parseInt(s);
            if (num < begin || num > end){
                throw new OutNumberBoundException("数字的范围必须在" + begin + "和" + end +"之间");
            }
            return num;
        }catch(NumberFormatException e){
            throw new NumberFormatException("输入的必须是数字!");
        }
    }

1.管理员登录界面

编写管理员登录界面,输入登录名和密码,返回包含用户名和密码的Manager对象

  • 输入用户信息login
/**
     *管理员登录界面,输入用户信息
     */
    public static Manager login(){
        Manager m = new Manager();
        System.out.println("=========管理员登录=========");
        System.out.print("登录名:");
        String name = input.nextLine();
        System.out.print("密码:");
        String password = input.nextLine();
        m.setName(name);
        m.setPassword(password);
        return m;
    }
2. 管理员注册界面

输入用户名和密码,返回包含新用户名和密码的对象

  • 输入注册信息register
 /**
     *管理员注册
     */
    public static Manager register(){
        Manager m = new Manager();
        System.out.println("=========管理员注册=========");
        System.out.print("请输入用户名:");
        String name = input.nextLine();
        System.out.print("请输入密码:");
        String password = input.nextLine();
        m.setName(name);
        m.setPassword(password);
        return m;
    }
其它操作
  • 输出管理员用户名已存在
    /**
     * 管理员用户名已存在
     */
    public static void isExist(){
        System.out.println("用户名已存在!");
    }
  • 输出管理员用户名不存在
 /**
     * 管理员用户名不存在
     */
    public static void noExist(){
        System.out.println("用户名不存在!");
    }

  • 输出注册成功
    /**
     * 注册成功
     */
    public static void print(){
        System.out.println("注册成功!");
    }

四、数据存取

主要负责数据处理的模块

创建一个dao包,新建类ManagerDao

ManagerDao
  • 初始化用户信息,默认几个用户名和密码
    public static Map<String, Manager> managerMap = new HashMap<>();

    /**
     * 初始化图书管理员数据
     */
    public ManagerDao(){
        managerMap.put("zs123456",new Manager("张三","zs123456"));
        managerMap.put("ls123456",new Manager("李四","ls123456"));
        managerMap.put("ww123456",new Manager("王五","ww123456"));
    }
  • 判断用户名是否存在
 /**
     * 判断用户名是否存在
     */
    public static int isManagerExist(Manager m){
        for(Manager m1:managerMap.values()){
            if(m.getName().equals(m1.getName())){
                return 1;//1代表用户名存在
            }
        }
        return -1;//-1代表用户名不存在
    }
  • 判断用户名和密码是否匹配
 /**
     * 判断登录时用户名密码是否正确
     */
    public static int login(Manager m){
        for (Manager m1:managerMap.values()) {
            if(m.getName().equals(m1.getName())){
                if(m.getPassword().equals(m1.getPassword())){
                    System.out.println("登陆成功!");
                    return 1;//1 登陆成功
                }
            }
        }
        System.out.println("用户名或密码错误!请重新输入!");
        return -1;//密码错误
    }
  • 注册,添加管理员的信息
/**
     * 添加管理员信息
     */
    public static void add(Manager m){
        managerMap.put(m.getName(),m);
    }

※第二部分:图书管理操作

一、对象

在前面创建的pojo包中新建类Book(书籍)

Book
  • 定义成员变量,并通过setter和getter来赋值和取值
	private String name;//书名
    private Double price;//价格
    private Integer year;//出版年
    private Integer month;//出版月

	/**
     * setter和getter设置和获取
     */
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Double getPrice() {
        return price;
    }

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

    public Integer getYear() {
        return year;
    }

    public void setYear(Integer year) {
        this.year = year;
    }

    public Integer getMonth() {
        return month;
    }

    public void setMonth(Integer month) {
        this.month = month;
    }

  • 构造无参和全参的构造方法
    /**
     * 无参构造方法
     */
    public Book() {
    }

    /**
     * 全参构造方法
     */
    public Book(String name, Double price, Integer year, Integer month) {
        this.name = name;
        this.price = price;
        this.year = year;
        this.month = month;
    }
  • 将信息转化为字符串
	 /**
     * 将信息转换为字符串
     */
    @Override
    public String toString() {
        return  "《" + name + "》" +
                "\t¥" + price +
                "\t出版年份:" + year +
                "年" + month +
                "月";
    }

二、自定义异常

即前面自定义的异常:OutNumberBoundException

三、视图分析

主要负责输入输出的视图交互模块

在前面创建的view包中新建类BookView

BookView
图书管理主界面
  /**
     * 图书管理主界面
     */
    public static int bookMain(){
        int mainNum = 0;
        do{
            System.out.println("请选择您要进行的操作:");
            System.out.println("1.图书新增");
            System.out.println("2.图书修改");
            System.out.println("3.图书删除");
            System.out.println("4.图书查找");//根据书名
            System.out.println("5.查看所有图书");
            System.out.println("0.退出登录");
            String s = input.nextLine();
            try{
                mainNum = mView.validNum(s,0,5);
                break;
            }catch(NumberFormatException | OutNumberBoundException e){
                System.out.println(e.getMessage());
            }
        }while(true);
        return mainNum;
    }
图书新增
  • 通过提示输入新增图书信息
    /**
     * 图书新增
     */
    public static Book add(){
        String name;
        double price;
        int year;
        int month;
        System.out.println("请输入以下信息:");//输入书名
        System.out.print("书名:");
        name = input.nextLine();
        do {//输入价格,进行异常处理
            System.out.print("价格:");
            String s = input.nextLine();
            try {
                price = validPrice(s);
                break;
            } catch (NumberFormatException | OutNumberBoundException e) {
                System.out.println(e.getMessage());
            }
        }while(true);
        do {//输入年份,进行异常处理
            System.out.print("出版年份:");
            String s = input.nextLine();
            try {
                year = mView.validNum(s,1900,2021);
                break;
            } catch (NumberFormatException | OutNumberBoundException e) {
                System.out.println(e.getMessage());
            }
        }while(true);
        do {//出入月份,进行异常处理
            System.out.print("出版月份:");
            String s = input.nextLine();
            try {
                month = mView.validNum(s,1,12);
                break;
            } catch (NumberFormatException | OutNumberBoundException e) {
                System.out.println(e.getMessage());
            }
        }while(true);
        Book b = new Book();//添加book信息
        b.setName(name);
        b.setPrice(price);
        b.setYear(year);
        b.setMonth(month);
        return b;
    }
  • 判断输入的价格是否合法有效
/**
     * 判断输入的价格是否有效
     */
    static double validPrice(String s) throws NumberFormatException, OutNumberBoundException {
        try{
            double num = Double.parseDouble(s);
            if (num < 0 || num > 10000){
                throw new OutNumberBoundException("输入的价格不合理!");
            }
            return num;
        }catch(NumberFormatException e){
            throw new NumberFormatException("输入的必须是数字!");
        }
    }
图书修改
  • 输入需要更新的图书的书名,先判断要更新的书籍是否存在,不存在则重新输入
	/**
     * 图书修改
     */
    public static String updateBook(){
        String name;
        while(true){
            System.out.print("请输入要更新的书籍名称:");
            name = input.nextLine();
            if(bDao.search(name) != null){
                return name;
            }else{
                System.out.println("您要更新的书籍不存在,请重新输入!");
            }
        }
    }
   
  • 根据书名来进行图书信息的修改
 public static Book updateInformation(String name){
        double price;
        int year;
        int month;
        do {
            System.out.print("请输入新的价格:");
            String s = input.nextLine();
            try {
                price = validPrice(s);
                break;
            } catch (NumberFormatException | OutNumberBoundException e) {
                System.out.println(e.getMessage());
            }
        }while(true);
        do {
            System.out.print("请输入新的出版年份:");
            String s = input.nextLine();
            try {
                year = mView.validNum(s,1900,2021);
                break;
            } catch (NumberFormatException | OutNumberBoundException e) {
                System.out.println(e.getMessage());
            }
        }while(true);
        do {
            System.out.print("请输入新的出版月份:");
            String s = input.nextLine();
            try {
                month = mView.validNum(s,1,12);
                break;
            } catch (NumberFormatException | OutNumberBoundException e) {
                System.out.println(e.getMessage());
            }
        }while(true);
        Book b = new Book();
        b.setName(name);
        b.setPrice(price);
        b.setYear(year);
        b.setMonth(month);
        return b;
    }
图书删除
  • 输入要删除的书名
    /**
     * 图书删除
     */
    public static String delete(){
        System.out.print("请输入要删除的书名:");
        String s = input.nextLine();
        return s;
    }
  • 确认是否删除图书
 /**
     * 确认图书是否删除
     */
    public static int isDelete(){
        int num = 1;
        do{
            System.out.println("是否删除图书?");
            System.out.println("1.是");
            System.out.println("0.否");
            String s = input.nextLine();
            try{
                num = mView.validNum(s,0,1);
                break;
            }catch(NumberFormatException | OutNumberBoundException e){
                System.out.println(e.getMessage());
            }
        }while(true);
        return num;
    }
图书查找
  • 输入要查找的书名
/**
     * 图书查找
     */
    public static String search(){
        System.out.print("请输入要查找的书名:");
        String s = input.nextLine();
        return s;
    }
查看所有图书
  • 选择图书输出打印的方式,查看所有图书
	 /**
     * 查看所有图书
     */
    public static int print(){
        int num = 0;
        do{
            System.out.println("请选择图书的打印输出方式:");
            System.out.println("1.价格从高到低排序");
            System.out.println("2.价格从低到高排序");
            System.out.println("3.出版日期从旧到新排序");
            String s = input.nextLine();
            try{
                num = mView.validNum(s,1,3);
                break;
            }catch(NumberFormatException | OutNumberBoundException e){
                System.out.println(e.getMessage());
            }
        }while(true);
        return num;
    }
    
其它操作
  • 打印单条图书信息
  /**
     * 打印单条图书信息
     */
    public static void printOne(Book b){
        System.out.println("图书信息如下:");
        System.out.println(b);
    }
    
  • 输出图书不存在
    /**
     * 图书不存在
     */
    public static void noExist(){
        System.out.println("查找的图书不存在!");
    }

  • 输出操作成功
    /**
     * 操作成功
     */
    public static void success(){
        System.out.println("操作成功!");
    }
    

四、数据存取

在前面创建的dao包中新建类BookDao

BookDao
  • 数据初始化,默认添加几本书
    /**
     * 初始化,默认添加几本书
     */
    public static ArrayList<Book> book = new ArrayList<>();
     	
    public BookDao() {
        book.add(new Book("C++ primer(第一版)",89.99,2010,10));
        book.add(new Book("C++ primer(第二版)",99.99,2020,10));
        book.add(new Book("Java编程思想(第一版)",77.77,2010,6));
        book.add(new Book("Java核心技术(第一版)",66.88,2010,2));
        book.add(new Book("Java编程思想(第二版)",79.99,2019,6));
        book.add(new Book("Java核心技术(第二版)",88.88,2021,2));
    }
    
图书新增
  • 将view视图中输入的信息添加至book
    /**
     * 图书新增
     */
    public static void add(Book b){
        book.add(b);
    }
图书修改
  • 修改b1的信息:b2为修改后的新信息,将b1的价格和出版年月修改成新信息
	/**
     * 图书修改
     */
    public static Book update(Book b1,Book b2){
        b1.setPrice(b2.getPrice());
        b1.setYear(b2.getYear());
        b1.setMonth(b2.getMonth());
        return b1;
    }
    
图书删除
  • 通过view输入要删除的书籍名称,通过名称查找书籍全部信息,进行删除(在test中对图书信息已经经过查找,书籍存在则进行删除)
	/**
     * 图书删除
     */
    public static void delete(String name){
        Book b = search(name);//找到书籍名称对应的书籍信息
        book.remove(b);//list中的remove方法,删除书籍
    }
    
图书查找
  • 通过遍历来模糊查找是否存在输入书名的书籍,有则返回
	/**
     * 图书查找
     */
    public static Book search(String bookName){
        for (Book b:book) {
            if(bookName.equals(b.getName())){
                return b;//如果找到了,返回图书信息
            }
        }
        return null;//没找到,返回null
    }

(下面的方法考虑到了重名的图书,但是此次简易版管理系统目前不考虑)

//    /**
//     * 图书查找(考虑到重名的图书,本系统目前不考虑)
//     */
//    public static int searchAll(String bookName){
//        int num = 0;
//        for (Book b:book) {
//            if(bookName.equals(b.getName())){
//                num ++;//记录书的数量
//                bView.printOne(b);//如果找到名称相同的图书,则打印
//            }
//        }
//        return num;//返回查找到的图书的数量
//    }
查看所有图书
  • 获取书籍的信息
	 /**
     * 获取全部book信息
     */
    public static ArrayList<Book> getBook(){
        return book;
    }
  • 通过遍历输出全部书籍信息
 	/**
     * 查看所有图书
     */
    public static void print(ArrayList<Book> book){
        for (Book b:book) {
            System.out.println(b);
        }
    }
价格从高到低排序
	/**
     * 价格从高到低排序,降序
     */
    public static void priceDescendingSort(ArrayList<Book> book){
        Collections.sort(book, new PriceDescendingComparator());
        print(book);
    }
价格从低到高排序
 /**
     * 价格从低到高排序,升序
     */
    public static void priceAscendingSort(ArrayList<Book> book){
        Collections.sort(book,new PriceAscendingComparator());
        print(book);
    }
根据出版日期新旧排序
/**
     * 出版日期,从老到新排序
     */
    public static void dataAscendingSort(ArrayList<Book> book){
        Collections.sort(book,new DataAscendingComparator());
        print(book);
    }

五、 比较器

新建包comparator,使用比较器接口自定义排序

Comparator的功能和用法可参考文章:Comparable和Comparator接口

价格从高到低排序
  • 在comparator包中新建类PriceDescendingComparator 实现Comparator< Book >
public class PriceDescendingComparator implements Comparator<Book> {
    @Override
    public int compare(Book o1, Book o2) {
        int flag = (int)(o1.getPrice() - o2.getPrice());
        if(flag < 0) {//o1 < o2(升序)
            return 1;//因为想要降序而不是升序,因此不想要o1 < o2,所以要调整顺序,返回1
        }else{
            return -1;
        }
    }
}

//tips:可以将return的值理解为是否同意改变当前的顺序
//如果return 1,则调整顺序
//如果return -1,则不调整顺序
价格从低到高排序
  • 在comparator包中新建类PriceAscendingComparator实现Comparator< Book >
public class PriceAscendingComparator implements Comparator<Book> {
    @Override
    public int compare(Book o1, Book o2) {
        int flag = (int)(o1.getPrice() - o2.getPrice());
        if(flag < 0) {//o1 < o2(升序)
            return -1;//因为想要升序,而数据本身已经升序,所以不需要调整顺序,返回-1
        }else{
            return 1;
        }
    }
}

//tips:可以将return的值理解为是否同意改变当前的顺序
//如果return 1,则调整顺序
//如果return -1,则不调整顺序
根据出版日期新旧排序
  • 在comparator包中新建类PriceAscendingComparator实现Comparator< Book >
public class DataAscendingComparator implements Comparator<Book> {
    @Override
    public int compare(Book o1, Book o2) {
        int flag1 = o1.getYear() - o2.getYear();
        int flag2 = o1.getMonth() - o2.getMonth();
        if(flag1 < 0) {//o1 < o2(升序)
            return -1;//因为想要升序,而数据本身已经升序,所以不需要调整顺序,返回-1
        }else if (flag1 > 0){
            return 1;
        }else{//o1.getYear() == o2.getYear(),年份相同时比较月份
            if(flag2 < 0){
                return -1;
            }else{
                return 1;
            }
        }//end if
    }//end compare
}//end class

//tips:可以将return的值理解为是否同意改变当前的顺序
//如果return 1,则调整顺序
//如果return -1,则不调整顺序

※第三部分:图书管理系统控制台

初始界面

	 /**
     * main,管理员登录or注册
     * @param args
     */
    public static void main(String[] args) {
        mView.welcome();
        w:while(true){
            int menuNum = mView.main();
            switch(menuNum) {
                case 0://退出系统
                    break w;//!!!!!attention,这里是退出循环,即退出系统
                case 1: //登录,进入用户登录平台
                    managerLogin();
                    break w;//!!!!!attention,这里是退出循环
                case 2: //注册,进入用户注册平台
                    managerRegister();
                    break;!!!!!attention,这里仅仅是退出switch:注册完成之后,选择退出系统或者登录进行图书管理操作,因此这里不退出循环
            }
        }
        mView.bye();
    }//end main

注册界面

	/**
     * 管理员注册界面
     */
    static void managerRegister(){
        int exist = 1;
        do{
            Manager m = mView.register();//输入注册的用户信息
            exist = mDao.isManagerExist(m);//1用户存在,-1用户不存在
            if(exist == 1) {//用户已存在,重新输入
                mView.isExist();
                continue;
            }else{//用户不存在,添加信息
                mDao.add(m);
                mView.print();//注册成功
                break;
            }
        }while(exist == 1);//输入注册信息,如果用户名存在,则重新输入
    }//end managerRegister
    

登录界面

	/**
     * 管理员登录界面
     */
    static void managerLogin(){
        int exist = -1;
        int isLogin = 0;
        w :do{
            Manager m = mView.login(); //输入登录的信息
            exist = mDao.isManagerExist(m);//1代表用户名存在,-1代表用户名不存在
            if(exist == 1){//用户名存在
                isLogin = mDao.login(m);//判断用户名密码是否匹配,输入正确即登陆成功,开始操作
                if(isLogin == 1){//登录成功
                    bookManagement();//进入图书管理界面,
                    break w;
                }else{//用户名或密码错误,重新输入
                    exist = -1;
                }
            }else if(exist == -1){
                mView.noExist();//用户名不存在
            }
        }while(exist == -1);//如果用户名不存在,则一直循环输入
    }//end managerLogin
    

图书管理界面

主界面
	/**
     * 图书管理界面
     */
    public static void bookManagement(){
        System.out.println("----------------------------------------");
        System.out.println("尊敬的管理员,您好!");
        w:while(true){
            int mainNum = bView.bookMain();//选择需要进行的操作
            switch(mainNum){
                case 0:{//退出登录
                    return;
                }
                case 1:{//1.新增图书
                    add();
                }
                break ;
                case 2:{//2.修改图书
                    update();
                }
                break ;
                case 3:{//3.删除图书
                    delete();
                }
                break ;
                case 4:{//4.查找图书
                    search();
                }
                break ;
                case 5:{//5.查看所有图书
                    printAll();
                }
                break ;
            }// end switch
        }//end while
    }
    
图书新增
	/**
     * 图书新增
     */
    public static void add(){
        while(true){
            Book b = bView.add();//输入新增图书的信息
            Book b1 = bDao.search(b.getName());//通过书名查找图书是否存在
            if(b1 == null){//该书不存在,添加
                bDao.add(b);//添加图书
                bView.success();
                bView.printOne(b);//打印新添加的图书信息
                break;
            }else{//如果图书已经存在,则重新输入
                System.out.println("该图书已存在!请重新输入!");
            }
        }
    }
图书修改
	/**
     * 图书修改
     */
    public static void update(){
        String bookName = bView.updateBook();//输入要修改的图书的名称
        Book b = bDao.search(bookName);//要修改的图书
        bView.printOne(b);//打印要修改的图书的信息
        Book b1 = bView.updateInformation(bookName);//输入更新的信息
        b1 = bDao.update(b,b1);//进行更新
        bView.success();
        bView.printOne(b1);//打印输出更新后的该图书信息
    }
图书删除
	  /**
     * 图书删除
     */
    public static void delete(){
        String bookName = bView.delete();//输入要删除的图书name
        Book b = bDao.search(bookName);//查找图书,有则返回图书对象
        if(b != null){//如果存在该图书,则确认是否删除
            if(bView.isDelete() == 1){//确认删除
                bDao.delete(b.getName());
                System.out.println("删除成功!");
            }else{
                System.out.println("取消操作成功!");
            }
        }else{//不存在,则提示输出“不存在”
            bView.noExist();
        }
    }
图书查找
	/**
     * 图书查找
     */
    public static void search(){
        String bookName = bView.search();//输入要查找的书名
        Book b = bDao.search(bookName);//查找图书
        if(b != null){//如果存在该图书,则打印图书信息
            bView.printOne(b);
        }else{//不存在,则提示输出“不存在”
            bView.noExist();
        }
    }
查看所有图书
	 /**
     * 查看所有图书
     */
    public static void printAll(){
        int num = bView.print();//选择打印输出的形式
        switch(num){
            case 1://价格从高到低排序
                    bDao.priceDescendingSort(bDao.getBook());
                    break;
            case 2://价格从低到高排序
                    bDao.priceAscendingSort(bDao.getBook());
                    break;
            case 3://出版日期排序,从老到新
                    bDao.dataAscendingSort(bDao.getBook());
                    break;
        }
    }//end printAll
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Selcouther

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值