Java GUI + JDBC 模拟ATM机系统(3.1)

用java GUI 界面和 JDBC 数据库实现ATM机系统

主要类

1、ATM类:

  • 用来获取信息和传送信息,进行简单判断,在程序结束释放Data类的资源
  • 窗口类使用ATM类
  • 从Data类获取信息传给窗口类
  • 从窗口获取的信息传给Data类

2、Data类:

  • Data类是是用来操作数据库的,改查操作
  • 验证、返回、保存信息

3、窗口类

  • 窗口类进行界面展示
  • 使用ATM类把获取的信息传给Data类
  • 从ATM类获取信息,简单判断,展示界面

4、JDBC_Util类

  • JDBC工具类

类的名字及里面的方法名都是我之前随便取的,没有改。
在这里插入图片描述

配置环境

1、jdk1.8;安装mysql
2、新建一个libs文件夹并导入mysql驱动的jar包,创建一个jdbc.properties配置文件
在这里插入图片描述

在这里插入图片描述
// jdbc.properties配置文件
// atm1是用的数据库名字,注意Data类里数据库语句中表名字

url=jdbc:mysql://localhost:3306/atm1
user=你的mysql的用户名
password=你的mysql用户密码
driver=com.mysql.jdbc.Driver

源代码

java代码

package Bank;

/**
 * 用来获取信息和传送信息,进行简单判断,在程序结束释放Data类的资源
 * 窗口类使用ATM类
 * 从Data类获取信息传给窗口类
 * 从窗口获取的信息传给Data类
 */
public class ATM {
    //有一个类操作数据的类
    private Data data = new Data();
    //ATM机里的数据
    private double userMoney;//用户账户里的钱

    //登录方法
    public boolean login(String inUserName,String inUserPassword){
        boolean b= false;
        if(data.isTrue(inUserName,inUserPassword)){
            b = true;
            userMoney = data.getMoney();
        }
        return b;
    }
    //获取账户余额
    public Double getMoney1(){
        userMoney = data.getMoney();
        return userMoney;
    }
    //存钱
    public boolean saveMoney(Double money){
        boolean b = false;
        if(money % 100 == 0) { //如果存的钱正确
            b = data.changeMoney(money, true);//存上
        }
        return b;
    }
    //取钱
    public boolean quMoney(Double money){
        boolean b = false;
        if(money % 100 == 0 && money <= userMoney){
            b = data.changeMoney(money, false);
        }
        return b;
    }
    //只判断用户账户是否存在
    public boolean anotherUser(String inUserName){
        //如果该账户存在
        boolean b = data.isUser(inUserName);
        return b;
    }
    //进行转账
    public void giveMoney(Double money){
        data.giveMoney(money);
    }
    //修改密码实现
    public boolean changePassword(String newPassword){
        return data.changePassword(newPassword);
    }

    // 程序结束
    public void over(){
        // 释放Data类的资源
        data.close();
    }

}

package Bank;

import JDBC_Utils.JDBC_Util;
import java.sql.*;

/**
 * Data类是是用来操作数据库的,改查操作
 * 验证、返回、保存信息
 */
public class Data {
    private double umoney;//用户余额
    private String uname; //用户
    private String gname;  //被转账用户
    private Connection coon = null;// 一般操作连接对象,程序结束时释放
    private Connection coon1 = null;// 转账连接对象,程序结束时释放
    private PreparedStatement pstmt = null; // 一般操作
    private PreparedStatement pstmt1 = null; // 转账时使用
    private ResultSet res = null;
    private String sql;//sql语句
    private String sql1;//sql语句,转账时使用

    {
        try {
            // 获取连接对象
            coon = JDBC_Util.getConnection();
            coon1 = JDBC_Util.getConnection();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取该账户的余额
     * @return 余额
     */
    public double getMoney(){
        try {
            sql = "select * from atm1 where uname= ?";//查询语句
            pstmt = coon.prepareStatement(sql);
            pstmt.setString(1, uname);
            res = pstmt.executeQuery();
            if(res.next()){
                umoney = res.getDouble("money");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            JDBC_Util.close(res, pstmt, null);//释放资源
        }
        return umoney;
    }

    /**
     * 判断登录是否成功
     */
    public boolean isTrue(String user,String password){
        if(user == null || password == null){
            return false;
        }
        try {
            sql = "select * from atm1 where uname = ? and password = ?";
            pstmt = coon.prepareStatement(sql);
            pstmt.setString(1,user);
            pstmt.setString(2,password);
            res = pstmt.executeQuery();
            uname = user;
            return res.next();
        } catch (SQLException e) {
            e.printStackTrace();
        }finally{
            JDBC_Util.close(res, pstmt, null);
        }
        return false;
    }


    /**
     * 取钱、存钱操作
     * @param money 钱数
     * @param isOrNot 存钱or取钱
     */
    public boolean changeMoney(double money,boolean isOrNot){
        if(isOrNot){
            sql = "update atm1 set money = money + ? where uname = ?";
        }else{
            sql = "update atm1 set money = money - ? where uname = ?";
        }
        return runSql(money,null);
    }

    /**
     * 修改密码
     * @param newPassword 新密码
     * @return
     */
    public boolean changePassword(String newPassword){
        if(newPassword == null){
            return false;
        }
        sql = "update atm1 set password = ? where uname = ?";
        return runSql(0,newPassword);
    }

    //执行sql修改操作
    private boolean runSql(double money,String newPassword){
        try {
            if(sql == null){
                return false;
            }
            pstmt = coon.prepareStatement(sql);
            if(newPassword == null){
                pstmt.setDouble(1, money);
            }else{
                pstmt.setString(1, newPassword);
            }
            pstmt.setString(2,uname);
            int count = pstmt.executeUpdate();
            if(count != 0){
                return true;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally{
            sql = null;
            JDBC_Util.close(res, pstmt, null);
        }
        return false;
    }

    /**
     * 判断被转帐用户是否存在
     * @param user 被转账用户名
     * @return
     */
    public boolean isUser(String user){
        if(user == null){
            return false;
        }
        try {
            sql = "select * from atm1 where uname = ?";
            pstmt = coon.prepareStatement(sql);
            pstmt.setString(1,user);
            res = pstmt.executeQuery();
            gname = user;
            return res.next();
        } catch (SQLException e) {
            e.printStackTrace();
        }finally{
            JDBC_Util.close(res, pstmt, null);
        }
        return false;
    }

    /**
     * 转账操作,事务
     * @param money 转账数
     * @return
     */
    public boolean giveMoney(double money){
        try {
            coon1.setAutoCommit(false); //开启事务
            sql = "update atm1 set money = money - ? where uname = ?";
            sql1 = "update atm1 set money = money + ? where uname = ?";
            pstmt = coon.prepareStatement(sql);
            pstmt1 = coon.prepareStatement(sql1);
            pstmt.setDouble(1,money);
            pstmt.setString(2,uname);
            pstmt1.setDouble(1,money);
            pstmt1.setString(2,gname);
            int a = pstmt.executeUpdate();
            int b = pstmt1.executeUpdate();
            coon1.commit();//提交事务
            if(a !=0 && b!=0) {
                return true;
            }
        } catch (Exception e) {
            try {
                if(coon1 !=null)
                    coon1.rollback();//回滚
            } catch (SQLException e1) {
                e1.printStackTrace();
            }
            e.printStackTrace();
        }finally{
            JDBC_Util.close(res, pstmt, null);
            JDBC_Util.close(null, pstmt1, null);
        }
        return false;
    }

    /**
     * 释放所有的资源
     */
    public void close(){
        JDBC_Util.close(res, pstmt, coon);
        JDBC_Util.close(res, pstmt1, coon1);
    }

}

package JDBC_Utils;

import com.sun.org.apache.bcel.internal.util.ClassLoader;

import java.io.FileReader;
import java.io.IOException;
import java.net.URL;
import java.sql.*;
import java.util.Properties;

/**
 * JDBC工具类
 */
public class JDBC_Util {
    private static String url;
    private static String user;
    private static String password;
    private static String driver;

    /**
     * 从配置文件读取所需要的数据
     */
    static{
        try {
            //创建Properties集合类
            Properties pro = new Properties();
            //获取src下文件路径---->ClassLoader 类加载器(文件路径不有为中文)
            ClassLoader classLoader = new ClassLoader();
            URL res = classLoader.getResource("jdbc.properties");
            String path = res.getPath();
            //加载文件
            //pro.load(new FileReader("/D:/java-idea2018File/jdbc/out/production/atm-gui-jdbc/jdbc.properties"));
            pro.load(new FileReader(path));
            //获取数据赋值
            url = pro.getProperty("url");
            user = pro.getProperty("user");
            password = pro.getProperty("password");
            driver = pro.getProperty("driver");

            //注册驱动
            Class.forName(driver);

        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取连接
     * @return 连接对象
     */
    public static Connection getConnection() throws SQLException {
        return DriverManager.getConnection(url,user,password);
    }

    /**
     * 释放资源
     * @param stmt
     * @param coon
     */
    public static void close(Statement stmt, Connection coon){
        close(null,stmt,coon);
    }

    public static void close(ResultSet res,Statement stmt,Connection coon){
        if(res != null){
            try{
                res.close();
            }catch (SQLException e){
                e.printStackTrace();
            }
        }
        if (stmt != null) {
            try{
                stmt.close();
            }catch (SQLException e){
                e.printStackTrace();
            }
        }
        if (coon != null) {
            try{
                coon.close();
            }catch (SQLException e){
                e.printStackTrace();
            }
        }
    }
}

package MyJFrame;

import Bank.ATM;

import javax.swing.*;
import java.awt.*;

/**
 * 窗口类进行界面展示
 * 使用ATM类把获取的信息传给Data类
 * 从ATM类获取信息,简单判断,展示界面
 * 自己创造的界面的父类
 */
public class MyJFrame extends JFrame {
    //设置字体供子类使用
    public static final Font FONT_SIZE_10 = new Font("宋体",Font.PLAIN,18);
    public static final Font FONT_SIZE_20 = new Font("宋体",Font.PLAIN,20);
    public static final Font FONT_SIZE_25 = new Font("宋体",Font.PLAIN,25);
    //给一个静态公共不可改变的ATM对象作为属性,供子类使用
    public static final ATM atm = new ATM();

    //创建窗体
    public MyJFrame(String title){
        super(title);
        //设置窗体不可改变
        setResizable(false);
        //设置窗体大小
        setSize(600,600);
        //设置窗体居中
        setLocationRelativeTo(null);
    }

    //无参构造,创建无标题窗体
    public MyJFrame(){
        this("");
    }

    //设置弹窗方法供子类使用(传入字符串并显示出)
    protected void showMessageDialog(String str){
        JOptionPane.showMessageDialog(this,str);
    }

}

package MyJFrame;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

/**
 * 登录界面
 * 继承MyJFrame
 */
public class LoginJFrame extends MyJFrame {
    public LoginJFrame(){
        super("欢迎使用ATM机");
        //设置窗体可关闭
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        //设置组件
        init();
        //界面可视化
        setVisible(true);
    }
    //初始化界面
    private void init(){
        //创建面板对象,并定义为空布局
        JPanel jp = new JPanel(null);
        //添加标签
        JLabel jl1 = new JLabel("账号:");
        JLabel jl2 = new JLabel("密码:");
        //设置标签字体
        jl1.setFont(FONT_SIZE_20);
        jl2.setFont(FONT_SIZE_20);
        //设置标签在面板中的位置
        jl1.setBounds(100,100,70,70);
        jl2.setBounds(100,250,70,70);
        //添加文本框
        JTextField jtf = new JTextField(20);
        //添加密码文本框
        JPasswordField jpf = new JPasswordField(20);
        //设置文本框位置
        jtf.setBounds(200,115,200,40);
        jpf.setBounds(200,265,200,40);
        //添加按钮
        JButton jb = new JButton("登录");
        //设置按钮文字大小
        jb.setFont(FONT_SIZE_20);
        //设置按钮位置及大小
        jb.setBounds(250,400,100,50);
        //设置面板背景颜色
        jp.setBackground(Color.YELLOW);
        //内部类进行事件处理
        jb.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                //获取输入的账号和密码
                String userName = jtf.getText();
                String userPassword = new String(jpf.getPassword());
                //验证是否正确
                boolean aBoolean = atm.login(userName,userPassword);
                if(aBoolean){
                    //登录成功
                    dispose();//关闭登录界面
                    //打开功能界面
                    new WorkingJFrame();
                }
                else
                    showMessageDialog("账号或密码错误");//调用父类弹窗方法
            }
        });
        //添加组件
        jp.add(jl1);
        jp.add(jtf);
        jp.add(jl2);
        jp.add(jpf);
        jp.add(jb);
        //窗体添加面板
        add(jp);
    }
    public static void main(String[] args) {
        new LoginJFrame();//先创建登录界面
    }
}

package MyJFrame;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

/**
 * 功能界面
 * extends MyJFrame
 */
public class WorkingJFrame extends MyJFrame {
    public WorkingJFrame(){
        super("功能界面");
        init();
        setVisible(true);
    }
    //初始化功能界面
    private void init(){
        //设置第一个面板对象
        JPanel jp1 = new JPanel();
        //创建标签,将标签添加到第一个面板上
        JLabel jb = new JLabel("请选择要进行的操作:");
        jb.setFont(FONT_SIZE_25);//设置标签字体大小
        jp1.add(jb);
        jp1.setBackground(Color.CYAN);
        //将第一个面板添加到窗体上方(JFrame窗体是边界布局)
        add(jp1, BorderLayout.NORTH);

        //创建第二个面板对象(空布局,自己设置按钮位置及大小),然后将按钮添加
        JPanel jp2 = new JPanel(null);
        //字符串数组存储各个按钮名字,然后循环设置按钮名字
        String[] str = {"1、余额查询","2、取钱","3、存钱","4、转账","5、修改密码","6、退出系统"};
        //int二维数组储存各个按钮位置及大小信息,循环设置
        int[][] xy = new int[][]{{50,100,200,50},{350,100,200,50},{50,200,200,50},{350,200,200,50},{50,300,200,50},{350,300,200,50}};
        for(int i = 0;i < str.length;i ++){
            JButton jButton = new JButton(str[i]);//创建按钮
            jButton.setFont(FONT_SIZE_20);//设置按钮字体大小
            jButton.setBounds(xy[i][0],xy[i][1],xy[i][2],xy[i][3]);//设置按钮位置及大小
            jButton.addActionListener(listener);//按钮注册监听器
            jp2.add(jButton);//将按钮添加
        }
        //设置jp2背景颜色
        jp2.setBackground(Color.GRAY);
        //将第二个面板添加到窗体(JFrame窗体中间)
        add(jp2);
    }
    //创建事件监听器
    private ActionListener listener = new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            String actionCommand = e.getActionCommand();//获取按钮上的字
            //switch选择功能,且每次功能结束回到该界面,关闭已操作完的功能界面
            switch(actionCommand){
                case "1、余额查询":
                    getMoney();
                    break;
                case "2、取钱":
                    quMoney();
                    break;
                case "3、存钱":
                    cunMoney();
                    break;
                case "4、转账":
                    giveMoney();
                    break;
                case "5、修改密码":
                    changePassword();
                    break;
                case "6、退出系统":

                    over();
                    break;
            }
        }
    };
    //查询余额功能
    private void getMoney(){
        showMessageDialog("您的账户余额为:" + atm.getMoney1());//调用父类方法弹窗
    }
    //取钱功能
    private void quMoney(){
        new QuMoneyJFrame();//创建取钱界面
        dispose();//关闭该界面
    }
    //存钱功能
    private void cunMoney(){
        new CunMoneyJFrame();
        dispose();
    }
    //转账功能
    private void giveMoney(){
        new GiveMoneyJFrame();
        dispose();
    }
    //修改密码功能
    private void changePassword(){
        new ChangePasswordJFrame();
        dispose();
    }
    //退出系统功能
    private void over(){
        atm.over();//调用方法操作文件
        dispose();
    }
}

package MyJFrame;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 中间窗口,存钱、取钱、转账、修改密码界面的父类
 * 组装存钱、取钱、转账、修改密码界面
 */
public class CentreJFrame extends MyJFrame {
    //空布局面板,自己设置组件位置及大小
    protected JPanel jp = new JPanel(null);
    //输入金额标签
    protected JLabel jl = new JLabel("请输入金额:");
    //输入金额文件框
    protected JTextField jtf = new JTextField(20);
    //确认、取消按钮
    protected JButton jb1 = new JButton("确认");
    protected JButton jb2 = new JButton("取消");

    //转账时转账账号标签
    protected JLabel jLabel = new JLabel("请输入转账账号:");
    //转账时转账账号文本框
    protected JTextField jTextField = new JTextField(20);

    //修改密码时新密码标签
    protected JLabel jLabelCP = new JLabel("请输入新密码(只能为数字):");
    //修改密码时新密码文本框
    protected JTextField jTextFieldCP = new JTextField(20);

    //提醒用户输入金额为100的倍数
    private JLabel jle = new JLabel("( 提示:只能输入100的倍数(转账不算) )");


    public CentreJFrame(String str){
        super(str);
        //判断要进行的操作
        if(str.equals("转账"))
            init1();
        else if(str.equals("修改密码"))
            init2();
        else
            init();
        one();//最后调用共有
    }
    //取钱和取钱特有组件
    private void init(){
        //输入金额标签,设置字体,位置及大小
        jl.setFont(FONT_SIZE_25);
        jl.setBounds(100,100,200,100);
        //输入金额文本框
        jtf.setBounds(300,250,200,50);
        //添加输入金额标签和输入金额文本框
        jp.add(jl);
        jp.add(jtf);
        setJLE();
    }
    //转账特有组件
    private void init1(){
        init();
        //输入账户标签
        jLabel.setFont(FONT_SIZE_25);
        jLabel.setBounds(100,10,200,40);
        //输入账户文本
        jTextField.setBounds(300,80,200,50);
        //添加输入账户标签和输入账户文本
        jp.add(jLabel);
        jp.add(jTextField);
    }
    //修改密码特有组件
    private void init2(){
        //输入新密码标签
        jLabelCP.setFont(FONT_SIZE_25);
        jLabelCP.setBounds(50,100,400,70);
        //输入新密码文本框
        jTextFieldCP.setBounds(300,215,200,40);
        //添加输入新密码标签和输入新密码文本框
        jp.add(jLabelCP);
        jp.add(jTextFieldCP);
    }
    //共有组件及操作
    private void one(){
        //按钮设置
        jb1.setFont(FONT_SIZE_20);
        jb2.setFont(FONT_SIZE_20);
        jb1.setBounds(300,350,100,50);
        jb2.setBounds(450,350,100,50);
        jp.add(jb1);
        jp.add(jb2);
        jp.setBackground(Color.GREEN);
        jb1.addActionListener(listener);
        jb2.addActionListener(listener);
        //添加到窗体
        add(jp);
        setVisible(true);
    }

    //设置提示
    private void setJLE(){
        jle.setFont(FONT_SIZE_10);
        jle.setBounds(100,180,300,50);
        jp.add(jle);
    }

    //创建监听器
    private ActionListener listener = new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {//按钮被点击后
            String actionCommand = e.getActionCommand();//获取按钮上的字
            switch(actionCommand){
                case "确认":
                    change();
                    break;
                case "取消":
                    new WorkingJFrame();//创建功能界面
                    dispose();//关闭此界面
                    break;
            }
        }
    };
    //点击确认按钮执行的操作,子类重写覆盖实现各自功能
    protected void change(){
    }

    //正则表达式判断输入是否为数字
    protected boolean isNumber(String str){
        Pattern pattern = Pattern.compile("[0-9]*");
        Matcher isNum = pattern.matcher(str);
        if(!isNum.matches())
            return false;
        return true;
    }

}

package MyJFrame;

/**
 * 取钱界面
 * extends CentreJFrame
 */
public class QuMoneyJFrame extends CentreJFrame {
    public QuMoneyJFrame(){
        super("取钱");
    }
    protected void change(){
        String s = jtf.getText();
        if(isNumber(s)){
            Double money = Double.parseDouble(s);
            boolean b = atm.quMoney(money);
            if(b){
                showMessageDialog("请收好您的钱\n您的账户余额为:" + atm.getMoney1());
            }
            else
                showMessageDialog("您输入有误" );
        }
        else
            showMessageDialog("您输入有误" );
        jtf.setText("");
    }

}

package MyJFrame;

/**
 * 存钱界面
 * extends CentreJFrame
 */
public class CunMoneyJFrame extends CentreJFrame {
    public CunMoneyJFrame(){
        super("存钱");
    }
    protected void change(){
        String s = jtf.getText();
        if(isNumber(s)){
            Double money = Double.parseDouble(s);
            boolean b = atm.saveMoney(money);
            if(b)
                showMessageDialog("您的钱钱已存入\n您的账户余额为:" + atm.getMoney1());
            else
                showMessageDialog("您输入有误" );
        }
        else
            showMessageDialog("您输入有误" );
        jtf.setText("");
    }

}

package MyJFrame;

/**
 * 转账界面
 * extends CentreJFrame
 */
public class GiveMoneyJFrame extends CentreJFrame {
    public GiveMoneyJFrame(){
        super("转账");
    }
    protected void change(){
        String s = jTextField.getText();
        boolean b = atm.anotherUser(s);
        if(b){
            //获取输入金额
            String s1 = jtf.getText();
            if(isNumber(s1)){//如果输入是数字
                Double money = Double.parseDouble(s1);
                atm.giveMoney(money);
                showMessageDialog("钱已转入\n您的账户余额为:" + atm.getMoney1());
            }
            else
                showMessageDialog("您输入有误" );
        }
        else
            showMessageDialog("您输入有误" );
        new WorkingJFrame();//创建功能界面
        dispose();//关闭此界面
    }
}


package MyJFrame;

/**
 * 修改密码界面
 * extends CentreJFrame
 */
public class ChangePasswordJFrame extends CentreJFrame{
    public ChangePasswordJFrame(){
        super("修改密码");
    }

    protected void change(){
        String s = jTextFieldCP.getText();
        if(isNumber(s)){
            if(atm.changePassword(s))
                showMessageDialog("密码修改成功");
            else
                showMessageDialog("密码修改失败");

        }
        else
            showMessageDialog("您输入有误" );
        new WorkingJFrame();//创建功能界面
        dispose();//关闭此界面
    }

}

mysql代码

CREATE DATABASE atm1;
CREATE TABLE atm1(
	id INT PRIMARY KEY AUTO_INCREMENT,
	uname VARCHAR(30),
	PASSWORD VARCHAR(6),
	money DOUBLE(6,2)
);

INSERT INTO atm1(id,uname,PASSWORD,money)  VALUES(
	NULL,
	'张三',
	'123',
	0
);

INSERT INTO atm1(id,uname,PASSWORD,money)  VALUES(
	NULL,
	'李四',
	'456',
	0
);

INSERT INTO atm1(id,uname,PASSWORD,money)  VALUES(
	NULL,
	'王五',
	'789',
	0
);

SELECT * FROM atm1; # 查询语句

效果图

功能界面都可以实现,就是有点丑。
代码还有很多不总,可以改进的地方还有很多,可以用图片作为背景,类与类之间的关系可以更合理。。。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

源代码和依赖的jar包下载地址

评论 21
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

不不树

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

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

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

打赏作者

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

抵扣说明:

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

余额充值