JavaSE实现电影院系统

这篇文章主要为大家详细介绍了JavaSE实现电影院系统,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

本文实例为大家分享了JavaSE实现电影院系统的具体代码,供大家参考,具体内容如下

利用Java的面向对象进阶知识,结合日志,创建一个简单电影院系统

一.定义一个User作为父类,减少代码冗余

public class User {
    //用户类,充当父类
    private String loginName;       //假名(昵称),不重复
    private String username;        //真名
    private String passWord;
    private String sex;
    private String phone;
    private double money;
 
 
    public User() {
    }
 
    public User(String loginName, String username, String passWord, String sex, String phone) {
        this.loginName = loginName;
        this.username = username;
        this.passWord = passWord;
        this.sex = sex;
        this.phone = phone;
    }
 
    public String getLoginName() {
        return loginName;
    }
 
    public void setLoginName(String loginName) {
        this.loginName = loginName;
    }
 
    public String getUsername() {
        return username;
    }
 
    public void setUsername(String username) {
        this.username = username;
    }
 
    public String getPassWord() {
        return passWord;
    }
 
    public void setPassWord(String passWord) {
        this.passWord = passWord;
    }
 
    public String getSex() {
        return sex;
    }
 
    public void setSex(String sex) {
        this.sex = sex;
    }
 
    public String getPhone() {
        return phone;
    }
 
    public void setPhone(String phone) {
        this.phone = phone;
    }
 
    public double getMoney() {
        return money;
    }
 
    public void setMoney(double money) {
        this.money = money;
    }
}

二.定义顾客类,以及商家类

public class Business extends User {
    //商家角色,独有属性
    private String shopName;        //店铺名称
 
    private String address;
 
 
    public String getShopName() {
        return shopName;
    }
 
    public void setShopName(String shopName) {
        this.shopName = shopName;
    }
 
    public String getAddress() {
        return address;
    }
 
    public void setAddress(String address) {
        this.address = address;
    }
}
 
 
public class Customer extends User{
    //客户角色
}

三.定义一个电影类

import java.util.*;
 
public class Movie {
    private String name;
    private String actor;
    private double score;
    private double time;
    private double price;
    private int number;         //余票
    private Date startTime;     //放映时间
 
    public Movie() {
    }
 
    public Movie(String name, String actor, double time, double price, int number, Date startTime) {
        this.name = name;
        this.actor = actor;
        this.score = score;
        this.time = time;
        this.price = price;
        this.number = number;
        this.startTime = startTime;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public String getActor() {
        return actor;
    }
 
    public void setActor(String actor) {
        this.actor = actor;
    }
 
    public double getScore() {
        return score;
    }
 
    public void setScore(double score) {
        this.score = score;
    }
 
    public double getTime() {
        return time;
    }
 
    public void setTime(double time) {
        this.time = time;
    }
 
    public double getPrice() {
        return price;
    }
 
    public void setPrice(double price) {
        this.price = price;
    }
 
    public int getNumber() {
        return number;
    }
 
    public void setNumber(int number) {
        this.number = number;
    }
 
    public Date getStartTime() {
        return startTime;
    }
 
    public void setStartTime(Date startTime) {
        this.startTime = startTime;
    }
}

四.添加logback.xml配置文件

注意:输出日志的格式为ERROR即可,如果设置ALL,不要在控制台打印

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <!--定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径-->
    <property name="LOG_HOME" value="E:/log" />
    <!-- 控制台输出 -->
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <!-- 日志输出编码 -->
        <Encoding>UTF-8</Encoding>
        <layout class="ch.qos.logback.classic.PatternLayout">
            <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n
            </pattern>
        </layout>
    </appender>
    <!-- 按照每天生成日志文件 -->
    <appender name="FILE"  class="ch.qos.logback.core.rolling.RollingFileAppender">
        <Encoding>UTF-8</Encoding>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!--日志文件输出的文件名-->
            <FileNamePattern>${LOG_HOME}/myApp.log.%d{yyyy-MM-dd}.log</FileNamePattern>
            <MaxHistory>30</MaxHistory>
        </rollingPolicy>
        <layout class="ch.qos.logback.classic.PatternLayout">
            <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n
            </pattern>
        </layout>
        <!--日志文件最大的大小-->
        <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
            <MaxFileSize>1MB</MaxFileSize>
        </triggeringPolicy>
    </appender>
 
    <!-- 日志输出级别 -->
    <root level="ERROR">
        <appender-ref ref="CONSOLE" />
        <appender-ref ref="FILE" />
    </root>
 
</configuration>

五.测试类

import com.lll.bean.Business;
import com.lll.bean.Customer;
import com.lll.bean.Movie;
import com.lll.bean.User;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
 
 
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
 
public class MovieSystem {
    //定义系统的数据容器,用于存储数据
//    1。存储很多用户(客户,商家)
 
    public static final List<User> ALL_USERS = new ArrayList<>();
 
    public static Map<List<Movie>,Double>MOVIE_SCORE=new HashMap<>();
 
 
    /*
     * 存储商家拍片信息
     * 商家1=【p1,p2,p3】
     * 商家2=【p1,p2,p3】
     * */
    public static final Map<Business, List<Movie>> ALL_MOVIES = new HashMap<>();
 
    public static final Scanner sc = new Scanner(System.in);
 
 
    public static User loginUser;
 
    public static SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
 
    public static final Logger LOGGER = LoggerFactory.getLogger("MovieSystem.class");
 
    /*
     * 准备一些测试数据
     *
     * */
    static {
        Customer c = new Customer();
        c.setLoginName("lzb123");
        c.setPassWord("123456");
        c.setUsername("刘六");
        c.setSex("男");
        c.setMoney(1000);
        c.setPhone("110011");
        ALL_USERS.add(c);
 
        Customer c1 = new Customer();
        c1.setLoginName("w123");
        c1.setPassWord("123456");
        c1.setUsername("老王");
        c1.setSex("男");
        c1.setMoney(0);
        c1.setPhone("110111");
        ALL_USERS.add(c1);
 
        Business b = new Business();
        b.setLoginName("马化腾66");
        b.setPassWord("123456");
        b.setUsername("马化腾");
        b.setMoney(0);
        b.setSex("男");
        b.setPhone("8888");
        b.setShopName("腾讯影视");
        b.setAddress("北京市海淀区中关村1号");
        ALL_USERS.add(b);
        List<Movie> movies = new ArrayList<>();
        ALL_MOVIES.put(b, movies);
 
        Business b1 = new Business();
        b1.setLoginName("马云66");
        b1.setPassWord("123456");
        b1.setUsername("马云");
        b1.setMoney(10000);
        b1.setSex("男");
        b1.setPhone("6666");
        b1.setShopName("阿里影视");
        b1.setAddress("北京市海淀区中关村2号");
        ALL_USERS.add(b1);
        List<Movie> movies1 = new ArrayList<>();
        ALL_MOVIES.put(b1, movies1);
 
    }
 
 
    public static void main(String[] args) {
        shouMain();
 
    }
 
    public static void NewCustomer()
    {
        System.out.println("==========用户注册==========");
        System.out.println("输入用户名:");
        String loginName=sc.nextLine();
        System.out.println("输入姓名:");
        String username=sc.nextLine();
        while (true) {
            System.out.println("输入密码:");
            String passWord=sc.nextLine();
            System.out.println("请再次输入密码:");
            String passWord2=sc.nextLine();
            if(passWord.equals(passWord2)==false)
            {
                System.out.println("两次密码输入不一致!");
            }
            else
            {
                System.out.println("输入性别:");
                String sex=sc.nextLine();
                while (true) {
                    System.out.println("输入手机号码:");
                    String phone=sc.nextLine();
                    if(phone.matches("^1[3|4|5|7|8][0-9]\\d{4,8}$"))
                    {
                        System.out.println("注册成功!");
                        User user=new User(loginName,username,passWord,sex,phone);
                        ALL_USERS.add(user);
                        return;
                    }
                    else
                    {
                        System.out.println("手机号输入不合法!");
                    }
                }
            }
        }
    }
 
    public static void NewBusiness()
    {
        System.out.println("==========商家入驻==========");
        System.out.println("输入用户名:");
        String loginName=sc.nextLine();
        System.out.println("输入姓名:");
        String username=sc.nextLine();
        while (true) {
            System.out.println("输入密码:");
            String passWord=sc.nextLine();
            System.out.println("请再次输入密码:");
            String passWord2=sc.nextLine();
            if(passWord.equals(passWord2)==false)
            {
                System.out.println("两次密码输入不一致!");
            }
            else
            {
                System.out.println("输入性别:");
                String sex=sc.nextLine();
                while (true) {
                    System.out.println("输入手机号码:");
                    String phone=sc.nextLine();
                    if(phone.matches("^1[3|4|5|7|8][0-9]\\d{4,8}$"))
                    {
                        System.out.println("请输入店铺名称:");
                        String shopName=sc.nextLine();
                        System.out.println("请输入店铺地址:");
                        String address=sc.nextLine();
 
                        System.out.println("注册成功!");
                        Business b=new Business();
                        b.setLoginName(loginName);
                        b.setPassWord(passWord);
                        b.setUsername(username);
                        b.setSex(sex);
                        b.setPhone(phone);
                        b.setShopName(shopName);
                        b.setAddress(address);
                        ALL_USERS.add(b);
                        List<Movie> movies = new ArrayList<>();
                        ALL_MOVIES.put(b, movies);
                        return;
                    }
                    else
                    {
                        System.out.println("手机号输入不合法!");
                    }
                }
            }
        }
    }
 
 
    private static void shouMain() {
        while (true) {
            System.out.println("==========ZB电影首页==========");
            System.out.println("1.登录");
            System.out.println("2.用户注册");
            System.out.println("3.商家入驻");
            System.out.println("请输入操作命令");
            String command = sc.nextLine();
            switch (command) {
                case "1":
                    //登录
                    longin();
                    break;
                case "2":
                    //注册
                    NewCustomer();
                    break;
                case "3":
                    NewBusiness();
                    break;
                default:
                    System.out.println("命令有误!请重新输入!");
                    break;
            }
        }
    }
 
    private static void longin() {
        while (true) {
            System.out.println("请输入登录名称:");
            String loginName = sc.nextLine();
            System.out.println("请输入登录密码:");
            String passWord = sc.nextLine();
            //根据登录名查询用户对象
            User u = getUserByLoginName(loginName);
            //判断用户对象是否存在
            if (u != null) {
                if (u.getPassWord().equals(passWord)) {
                    System.out.println("登录成功!");
                    loginUser = u;
                    LOGGER.info(u.getUsername() + "登录系统");
                    //判断登录为用户是商家还是顾客
                    if (u instanceof Customer)     //  对象运算符(instanceof)用来判断一个对象是否属于某个指定的类或其子类的实例,如果是,返回真(true),否则返回假(false)。
                    {
                        //登录为顾客
                        showCustomerMain();
 
                    } else {
                        //登录为商家
                        showBusinessMain();
                    }
                    return;
                } else {
                    System.out.println("密码错误!");
                }
            } else {
                System.out.println("登录名称错误,请重新输入!");
 
            }
        }
 
 
    }
 
 
    //商家操作
 
    private static void showBusinessMain() {
        while (true) {
            System.out.println("==========商家界面==========");
            System.out.println(loginUser.getUsername() + (loginUser.getSex() .equals("男") ? "先生" : "女士") + "您好," + "请选择商家操作的功能:");
            while (true) {
                System.out.println("1.展示详情:");
                System.out.println("2.上架电影:");
                System.out.println("3.下架电影:");
                System.out.println("4.修改电影:");
                System.out.println("5.退出");
                System.out.println("选择操作命令:");
                String command = sc.nextLine();
                switch (command) {
                    case "1":
                        showBusinessInfos();
                        break;
                    case "2":
                        addMovie();
                        break;
                    case "3":
                        deleteMovie();
                        break;
                    case "4":
                        updateMovie();
                        break;
                    case "5":
                        System.out.println("退出系统成功!");
                        return;
                    default:
                        System.out.println("您输入的命令有误!请重新输入");
                        break;
                }
            }
        }
    }
 
    private static void updateMovie() {
        Business business = (Business) loginUser;
        List<Movie> movies = ALL_MOVIES.get(business);
        if (movies.size() == 0) {
            System.out.println("您的系统内无影视资源!无法修改");
            return;
        }
        while (true) {
            System.out.println("请您输入需要修改的电影名称:");
            String movieName = sc.nextLine();
            Movie movie = getMovieByName(movieName);
            if (movie != null) {
                System.out.println("请输入修改后的片名:");
                String name = sc.nextLine();
                System.out.println("请输入修改后的主演:");
                String actor = sc.nextLine();
                System.out.println("请输入修改后的时长:");
                String time = sc.nextLine();
                System.out.println("请输入修改后的票价:");
                String price = sc.nextLine();
                System.out.println("请输入修改后的票数:");
                String totalNumber = sc.nextLine();
                while (true) {
                    try {
                        System.out.println("请输入影片修改后的放映时间:");
                        String startTime = sc.nextLine();
                        movie.setName(name);
                        movie.setActor(actor);
                        movie.setTime(Double.valueOf(time));
                        movie.setPrice(Double.valueOf(price));
                        movie.setNumber(Integer.valueOf(totalNumber));
                        movie.setStartTime(sdf.parse(startTime));
                        System.out.println("您已经成功修改!");
                        System.out.println("==========影片详情==========");
                        showBusinessInfos();
                        return;
                    } catch (ParseException e) {
                        e.printStackTrace();
                        LOGGER.error("时间解析错误!");
                    }
                }
            } else {
                System.out.println("不存在该影片!");
                System.out.println("继续修改按1,退出按其他任意键");
                String command = sc.nextLine();
                switch (command) {
                    case "1":
                        break;
                    default:
                        return;
 
                }
            }
        }
    }
 
 
    //影片下架功能
    private static void deleteMovie() {
        System.out.println("==========下架电影===========");
        Business business = (Business) loginUser;
        List<Movie> movies = ALL_MOVIES.get(business);
        if (movies.size() == 0) {
            System.out.println("您的系统内无影视资源!无法下架");
            return;
        }
        while (true) {
            System.out.println("请您输入需要下架的电影名称:");
            String movieName = sc.nextLine();
            Movie movie = getMovieByName(movieName);
            if (movie != null) {
                movies.remove(movie);
                System.out.println(movieName + "下架成功!");
                System.out.println("==========影片详情==========");
                showBusinessInfos();
                return;
            } else {
                System.out.println("不存在该影片!");
                System.out.println("继续下架按1,退出按其他任意键");
                String command = sc.nextLine();
                switch (command) {
                    case "1":
                        break;
                    default:
                        return;
 
                }
            }
        }
    }
 
    //根据影片名查找影片
    public static Movie getMovieByName(String movieName) {
        Business business = (Business) loginUser;
        List<Movie> movies = ALL_MOVIES.get(business);
        for (Movie movie : movies) {
            if (movie.getName().contains(movieName))
            //equals只能判断两个变量的值是否相等。 contains常用与集合中判断某个对象是否含有这个元素
            {
                return movie;
            }
        }
        return null;
    }
 
 
    //展示当前商家详细信息
    private static void showBusinessInfos() {
        System.out.println("==========商家详情==========");
        LOGGER.info(loginUser.getUsername() + "查看详情");
        //根据商家对象提取相应的值   Map<Business List<Movie>>
        Business business = (Business) loginUser;
        System.out.println(business.getShopName() + "\t\t电话:" + business.getPhone() + "\t\t地址:" + business.getAddress());
        List<Movie> movies = ALL_MOVIES.get(business);
        if (movies.size() > 0) {
            System.out.println("片名" + "\t\t" + "主演" + "\t\t" + "时长" + "\t\t" + "评分" + "\t\t" + "票价" + "\t\t" + "余票" + "\t\t" + "放映时间");
            for (Movie movie : movies) {
                System.out.println(movie.getName() + "\t\t" + movie.getActor() + "\t\t" + movie.getTime() + "\t\t" + movie.getScore() + "\t\t" + movie.getPrice() + "\t\t" + movie.getNumber() + "\t\t" + sdf.format(movie.getStartTime()));
            }
        } else {
            System.out.println("您的店铺当前没有影视资源!");
        }
 
    }
 
    //上架电影
 
    private static void addMovie() {
        System.out.println("==========上架电影==========");
        Business business = (Business) loginUser;
        List<Movie> movies = ALL_MOVIES.get(business);  //键值对
        System.out.println("请输入新片名:");
        String name = sc.nextLine();
        System.out.println("请输入主演:");
        String actor = sc.nextLine();
        System.out.println("请输入时长:");
        String time = sc.nextLine();
        System.out.println("请输入票价:");
        String price = sc.nextLine();
        System.out.println("请输入票数:");
        String totalNumber = sc.nextLine();
        while (true) {
            try {
                System.out.println("请输入影片放映时间:");
                String startTime = sc.nextLine();
                Movie movie = new Movie(name, actor, Double.valueOf(time), Double.valueOf(price), Integer.valueOf(totalNumber), sdf.parse(startTime));
                movies.add(movie);
                System.out.println("您已经成功上架《" + movie.getName() + "》");
                return;
            } catch (ParseException e) {
                e.printStackTrace();
                LOGGER.error("时间解析错误!");
            }
        }
    }
 
 
    //顾客操作
    private static void showCustomerMain() {
        System.out.println("==========客户界面==========");
        while (true) {
            System.out.println(loginUser.getUsername() + (loginUser.getSex().equals("男") ? "先生" : "女士") + "您好," + "请选择客户操作的功能:");
            System.out.println("账户余额" + loginUser.getMoney());
            System.out.println("1.展示全部影片信息功能:");
            System.out.println("2.根据电影名称查询电影信息:");
            System.out.println("3.购票系统:");
            System.out.println("4.退出系统:");
            String command = sc.nextLine();
            switch (command) {
                case "1":
                    showAllMovies();
                    break;
                case "2":
                    NameMovie();
                    break;
                case "3":
                    buyMovie();
                    break;
                case "4":
                    System.out.println("退出系统成功!");
                    return;
                default:
                    System.out.println("您输入的命令有误!请重新输入");
                    break;
            }
        }
 
    }
 
 
    private static void NameMovie() {
        System.out.println("===========根据影片名查询电影===========");
        System.out.println("请输入影片名:");
        String Findname = sc.nextLine();
        ALL_MOVIES.forEach((business, movies) -> {
            System.out.println(business.getShopName() + "\t\t电话:" + business.getPhone() + "\t\t地址:" + business.getAddress());
            System.out.println("\t\t\t" + "片名" + "\t\t" + "主演" + "\t\t" + "时长" + "\t\t" + "评分" + "\t\t" + "票价" + "\t\t" + "余票" + "\t\t" + "放映时间");
            for (Movie movie : movies) {
                if (movie.getName().equals(Findname))
                    System.out.println("\t\t\t" + movie.getName() + "\t\t" + movie.getActor() + "\t\t" + movie.getTime() + "\t\t" + movie.getScore() + "\t\t" + movie.getPrice() + "\t\t" + movie.getNumber() + "\t\t" + sdf.format(movie.getStartTime()));
            }
        });
 
    }
 
    private static void buyMovie() {
        showAllMovies();
        System.out.println("==========用户购票==========");
        while (true) {
            System.out.println("请输入需要购票的门店");
            String shopName = sc.nextLine();
            Business business = getUserByShopName(shopName);
            if (business != null) {
                List<Movie> movies = ALL_MOVIES.get(business);
                if (movies.size() > 0) {
                    while (true) {
                        System.out.println("请输入需要购买的电影名称");
                        String MovieName = sc.nextLine();
                        Movie movie = getMovieByShopName(business, MovieName);
                        if (movie != null) {
                            while (true) {
                                System.out.println("输入购买电影票数:");
                                String Number = sc.nextLine();
                                int buyNumber = Integer.valueOf(Number);
                                if (movie.getNumber() >= buyNumber) {
                                    double money = BigDecimal.valueOf(movie.getPrice()).multiply(BigDecimal.valueOf(buyNumber))
                                            .doubleValue();
                                    System.out.println("当前需要花费的金额为" + money);
                                    if (loginUser.getMoney() >= money) {
                                        System.out.println("购票成功!");
                                        System.out.println("您成功购买了" + movie.getName() + "的" + buyNumber + "张票"
                                                + "总金额为" + money);
                                        loginUser.setMoney(loginUser.getMoney() - money);
                                        business.setMoney(business.getMoney() + money);
                                        movie.setNumber(movie.getNumber() - buyNumber);
                                        return;
                                    } else {
                                        System.out.println("账户余额不足!");
                                        System.out.println("继续购买按1,退出按其他任意键");
                                        String command = sc.nextLine();
                                        switch (command) {
                                            case "1":
                                                break;
                                            default:
                                                return;
                                        }
                                    }
                                } else {
                                    System.out.println("余票不足!还剩" + movie.getNumber() + "张票");
                                    System.out.println("继续购买按1,退出按其他任意键");
                                    String command = sc.nextLine();
                                    switch (command) {
                                        case "1":
                                            break;
                                        default:
                                            return;
                                    }
                                }
                            }
 
                        } else {
                            System.out.println("该电影不存在!");
                        }
                    }
                } else {
                    System.out.println("该店铺无影视资源!");
                    System.out.println("继续购买按1,退出按其他任意键");
                    String command = sc.nextLine();
                    switch (command) {
                        case "1":
                            break;
                        default:
                            return;
                    }
                }
                return;
            } else {
                System.out.println("不存在该店铺!");
                System.out.println("继续购买按1,退出按其他任意键");
                String command = sc.nextLine();
                switch (command) {
                    case "1":
                        break;
                    default:
                        return;
                }
            }
        }
 
 
    }
 
    private static void showAllMovies() {
        System.out.println("==========展示全部商家信息==========");
        ALL_MOVIES.forEach((business, movies) -> {
 
            System.out.println(business.getShopName() + "\t\t电话:" + business.getPhone() + "\t\t地址:" + business.getAddress());
            System.out.println("\t\t\t" + "片名" + "\t\t" + "主演" + "\t\t" + "时长" + "\t\t" + "评分" + "\t\t" + "票价" + "\t\t" + "余票" + "\t\t" + "放映时间");
            for (Movie movie : movies) {
                System.out.println("\t\t\t" + movie.getName() + "\t\t" + movie.getActor() + "\t\t" + movie.getTime() + "\t\t" + movie.getScore() + "\t\t" + movie.getPrice() + "\t\t" + movie.getNumber() + "\t\t" + sdf.format(movie.getStartTime()));
            }
        });
    }
 
    //根据商家店铺名称查询商家对象
    public static Business getUserByShopName(String shopName) {
        Set<Business> businesses = ALL_MOVIES.keySet();
        for (Business business : businesses) {
            if (business.getShopName().equals(shopName)) {
                return business;
            }
        }
        return null;
    }
 
 
    //查询商家的电影
    public static Movie getMovieByShopName(Business business, String name) {
        List<Movie> movies = ALL_MOVIES.get(business);
        for (Movie movie : movies) {
            if (movie.getName().contains(name)) {
                return movie;
 
            }
        }
        return null;
    }
 
    public static User getUserByLoginName(String loginName) {
        for (User user : ALL_USERS) {
            //判断用户登录名
            if (user.getLoginName().equals(loginName)) {
                return user;
            }
        }
        return null;   //查无此人
    }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程学习网。

本文标题为:JavaSE实现电影院系统

基础教程推荐