当前位置:   article > 正文

满汉楼(餐厅系统)——纯JAVA后端项目_满汉楼java项目

满汉楼java项目

项目涉及知识点:MySQL数据库,JDBC连接,面向对象(oop)...


 在观看完韩顺平老师的满汉楼项目之后我也是动手跟着写了一下,顺便也是融入了自己的思考使得项目更加完善

1,账单显示时间问题

在写代码的时候就发现这个问题了,由于mysql5版本以上不支持Java的Date类型到数据库的Date类型,因此载Bill类中定义BillDate的时候可以使用LocalDateTime来定义就不会报错了。

2,新增能够重复点餐功能

自己新增多次点菜功能,其实就是一次while,continue循环来点多份菜品:
 

while (looping) {
            System.out.print("请输入点餐的菜品号(-1退出):");
            int orderMenuId = Utility.readInt();
            if (orderMenuId == -1) {
                System.out.println("============取消点餐============");
                return;
            }
            System.out.print("请输入点餐的菜品量(-1退出):");
            int orderNums = Utility.readInt();
            if (orderNums == -1) {
                System.out.println("============取消点餐============");
                return;
            }

            //验证餐桌号是否存在
            DiningTable diningTable = diningTableService.getDiningTableById(orderDiningTableId);
            if (diningTable == null) {
                System.out.println("============餐桌号不存在============");
                return;
            }
            //验证菜品编号
            Menu menu = menuService.getMenuById(orderMenuId);
            if (menu == null) {
                System.out.println("============菜品号不存在============");
                return;
            }

            //点餐
            if (billService.orderMenu(orderMenuId, orderNums, orderDiningTableId)) {
                System.out.println("============点餐成功============");
            } else {
                System.out.println("============点餐失败============");
            }

            //新增是否还要继续点餐功能,用循环实现
            System.out.print("请确认是否还要继续点餐(Y/N): ");
            Scanner scanner = new Scanner(System.in);
            String continueOrdering = scanner.nextLine().trim().toUpperCase();
            if (continueOrdering.equals("Y")) {
                continue;
            } else if (continueOrdering.equals("N")) {
                looping = false;
            }
        }

在进入点餐服务并输入餐桌号后开始进入循环
looping = true; //切记不要忘记在最后要把looping即循环条件重新置为true
具体实现如下图: 

 

细节:我将while循环放在了输入点餐桌号之后的代码里,这样就不用再次输入一次餐桌号点餐了,也符合连续点餐的逻辑。

3,消除账单

--在观看过程中我也是想到既然已经成功支付了账单,那按逻辑来说这一个餐桌的账单就应该从数-据库中被抹除,不然会造成账单冗余问题。
--方法依旧是非常简单,其实就是一个对表的删除语句编写。
--我同样是写在了BillService的类中,新增一个方法用于传给数据库删除的sql语句。

//完成结账后将账单删除的方法
    public void deleteBill(int diningTableId) {
        int update = billDAO.update("DELETE FROM bill WHERE diningTableId=?", diningTableId);
    }
 

 

然后在界面类中结账完成之后对方法进行一次调用即可
billService.deleteBill(diningTableId);
具体实现如下图所示:

 4,视频最后分表查询功能扩展问题

 最后老韩布置的任务即分表查询问题,我的思路是创建了一张detailEmployee表显示雇员的详细信息
然后在java 中创建对应的domain和DAO来对员工的详细信息进行查询
我将界面菜单设置成了这样两层(如下)

1代表顾客登录进行点餐等一些列操作, 2代表员工登录并显示该员工的详细信息,然后进行判断是否要显示该员工的详细信息(如下)

 

case "2":
                    while (loop3) {
                        System.out.print("输入员工号:");
                        String empId = Utility.readString(50);
                        System.out.print("输入密  码:");
                        String pwd = Utility.readString(50);
                        Employee employee = employeeService.getEmployeeByIdAndPwd(empId, pwd);
                        if (employee != null) {
                            System.out.println("===============登陆成功[" + employee.getName() + "]===============\n");
                            System.out.print("是否要显示员工信息(Y/N):");
                            Scanner scanner = new Scanner(System.in);
                            String emp = scanner.nextLine().trim().toUpperCase();
                            if (emp.equals("Y")) {
                                List<DetailedEmployeeTable> list = detailedEmployeeService.PersonManage(empId);
                                System.out.println("员工编号\t\t员工姓名\t\t岗位\t\t学历\t\t电话号码\t\t\t结婚情况");
                                for (DetailedEmployeeTable detailedEmployeeTable : list) {
                                    System.out.println(detailedEmployeeTable.getEmpId() + "\t\t" + detailedEmployeeTable.getName()
                                            + "\t\t\t" + detailedEmployeeTable.getJob() + "\t\t" + detailedEmployeeTable.getEducation()
                                            + "\t\t" + detailedEmployeeTable.getTel() + "\t\t" + detailedEmployeeTable.getMarry());
                                }
                                System.out.println("==========显示完毕==========");
                                break;
                            } else if (emp.equals("N")) {
                                break;
                            }
                        } else {
                            System.out.println("登陆失败");
                            loop3 = false;
                        }
                    }
                    break; 

如上将登录操作和查询详细表的操作放在一个case情况下完成分表查询的任务 。

5,SQL语句实现

我使用的是NaviCat,但是sql语句都大相径庭,操作方面NaviCat想要写sql语句需要点击数据库并新建一个查询(如图所示)

  1. --创建emp表(主键id,empid,name,pwd,job等
  2. CREATE TABLE employee(
  3. id INT PRIMARY KEY AUTO_INCREMENT, -- 自增
  4. empId VARCHAR(50) UNIQUE NOT NULL DEFAULT '', -- 员工号
  5. pwd CHAR(32) NOT NULL DEFAULT '', -- 密码md5
  6. name VARCHAR(50) NOT NULL DEFAULT '', -- 姓名
  7. job VARCHAR(50) NOT NULL DEFAULT '' -- 岗位
  8. ) CHARACTER SET utf8;
  9. --添加测试数据
  10. INSERT INTO employee VALUES(NULL, '6668612',MD5('123456'),'张三丰','经理');
  11. INSERT INTO employee VALUES(NULL, '6668622',MD5('123456'),'小龙女','服务员');
  12. INSERT INTO employee VALUES(NULL, '6668633',MD5('123456'),'张无忌','收银员');
  13. INSERT INTO employee VALUES(NULL, '666666',MD5('123456'),'老韩','经理');
  14. SELECT* FROM diningTable;
  15. SELECT* FROM employee;
  16. DROP TABLE bill;
  17. DROP TABLE diningTable;
  18. --创建diningTable表(id,state,orderName,orderTel...)
  19. CREATE TABLE diningTable(
  20. id INT PRIMARY KEY AUTO_INCREMENT, #自增,表示餐桌编号
  21. state VARCHAR(20) NOT NULL DEFAULT '', #餐桌的状态
  22. orderName VARCHAR(50) NOT NULL DEFAULT '', #预定人的名字
  23. orderTel VARCHAR(20) NOT NULL DEFAULT '' #电话号码
  24. ) CHARACTER SET utf8;
  25. INSERT INTO diningTable VALUES (NULL, '空','','');
  26. INSERT INTO diningTable VALUES (NULL, '空','','');
  27. INSERT INTO diningTable VALUES (NULL, '空','','');
  28. update diningTable SET state = '空', orderName='', orderTel='' where id=1;
  29. --创建menu表(id,name,type,price)
  30. #菜谱
  31. CREATE TABLE menu (
  32. id INT PRIMARY KEY AUTO_INCREMENT, #自增,表示菜谱编号
  33. NAME VARCHAR(50) NOT NULL DEFAULT '', #菜品名称
  34. TYPE VARCHAR(50) NOT NULL DEFAULT '', #菜品种类
  35. price DOUBLE NOT NULL DEFAULT 0 #价格
  36. ) CHARACTER SET utf8;
  37. #测试数据
  38. INSERT INTO menu VALUES(NULL, '八宝饭', '主食', 10);
  39. INSERT INTO menu VALUES(NULL, '叉烧包', '主食', 20);
  40. INSERT INTO menu VALUES(NULL, '宫保鸡丁', '热菜', 30);
  41. INSERT INTO menu VALUES(NULL, '山药鲅鱼', '凉菜', 14);
  42. INSERT INTO menu VALUES(NULL, '银丝卷', '甜食', 9);
  43. INSERT INTO menu VALUES(NULL, '水煮鱼', '热菜', 26);
  44. INSERT INTO menu VALUES(NULL, '甲鱼汤', '汤类', 100);
  45. INSERT INTO menu VALUES(NULL, '鸡蛋汤', '汤类', 16);
  46. SELECT * FROM menu;
  47. #增加表bill账单表(id,billId,menuId,nums,billDate,money,state,diningTableId)
  48. CREATE TABLE bill (
  49. id INT PRIMARY KEY AUTO_INCREMENT, #自增主键
  50. billID VARCHAR(50) NOT NULL DEFAULT '', #账单号可以按照自己的规则生成 UUID
  51. menuId INT NOT NULL DEFAULT 0, #菜品的编号,也可以使用外键
  52. nums INT NOT NULL DEFAULT 0, #份数
  53. money DOUBLE NOT NULL DEFAULT 0, #金额
  54. diningTableId INT NOT NULL DEFAULT 0, #餐桌
  55. billDate DATETIME NOT NULL, #订单日期
  56. state VARCHAR(50) NOT NULL DEFAULT '' #状态'未结账', '已经结账', '挂单'
  57. ) CHARACTER SET utf8;
  58. SELECT * FROM bill;
  59. #分表查询,先将详细的雇员表建起来然后后面再根据雇员的id进行对详细雇员表的查询
  60. CREATE TABLE detailEmployee(
  61. /* 自增 */ id INT PRIMARY KEY AUTO_INCREMENT,
  62. /* 员工号 */ empId VARCHAR(50) UNIQUE NOT NULL DEFAULT '',
  63. /* 姓名 */ name VARCHAR(50) NOT NULL DEFAULT '',
  64. /* 岗位 */ job VARCHAR(50) NOT NULL DEFAULT '',
  65. /* 学历 */ education VARCHAR(50) NOT NULL DEFAULT '',
  66. /* 电话号码 */ Tel INT NOT NULL DEFAULT 0,
  67. /* 是否结婚 */ Marry VARCHAR(50) NOT NULL DEFAULT ''
  68. ) CHARACTER SET utf8;
  69. #添加数据进表
  70. INSERT INTO detailEmployee VALUES(NULL, '6668612','张三丰','经理','博士','13333333','已婚');
  71. INSERT INTO detailEmployee VALUES(NULL, '6668622','小龙女','服务员','大专','13455555','未婚');
  72. INSERT INTO detailEmployee VALUES(NULL, '6668633','张无忌','收银员', '本科','1223455','未婚');
  73. INSERT INTO detailEmployee VALUES(NULL, '666666','老韩','经理','硕士','66668788','已婚');
  74. SELECT * FROM detailEmployee;

 以上是所有表和其中数据的sql代码。

6,具体代码实现

Utils类

JDBCUtilsByDruid

  1. import com.alibaba.druid.pool.DruidDataSourceFactory;
  2. import javax.sql.DataSource;
  3. import java.io.FileInputStream;
  4. import java.io.IOException;
  5. import java.sql.Connection;
  6. import java.sql.ResultSet;
  7. import java.sql.SQLException;
  8. import java.sql.Statement;
  9. import java.util.Properties;
  10. /**
  11. * 基于 Druid数据库连接池的工具类
  12. */
  13. public class JDBCUtilsByDruid {
  14. private static DataSource ds;
  15. //在静态代码块完成ds初始化
  16. static {
  17. Properties properties = new Properties();
  18. try {
  19. properties.load(new FileInputStream("src\\druid.properties"));
  20. ds = DruidDataSourceFactory.createDataSource(properties);
  21. } catch (Exception e) {
  22. throw new RuntimeException(e);
  23. }
  24. }
  25. //编写getConnection方法
  26. public static Connection getConnection() throws SQLException {
  27. return ds.getConnection();
  28. }
  29. //关闭连接,在数据库连接池技术中,close不是真的断掉连接,而是把Connection放回连接池
  30. public static void close(ResultSet resultSet, Statement statement, Connection connection) {
  31. try {
  32. if (resultSet != null) {
  33. resultSet.close();
  34. }
  35. if (statement != null) {
  36. statement.close();
  37. }
  38. if (connection != null) {
  39. connection.close();
  40. }
  41. } catch (SQLException e) {
  42. throw new RuntimeException(e);
  43. }
  44. }
  45. }

Utility

  1. /**
  2. * 工具类的作用:
  3. * 处理各种情况的用户输入,并且能够按照程序员的需求,得到用户的控制台输入。
  4. */
  5. import java.util.Scanner;
  6. /**
  7. *
  8. */
  9. public class Utility {
  10. //静态属性。。。
  11. private static Scanner scanner = new Scanner(System.in);
  12. /**
  13. * 功能:读取键盘输入的一个菜单选项,值:1——5的范围
  14. *
  15. * @return 1——5
  16. */
  17. public static char readMenuSelection() {
  18. char c;
  19. for (; ; ) {
  20. String str = readKeyBoard(1, false);//包含一个字符的字符串
  21. c = str.charAt(0);//将字符串转换成字符char类型
  22. if (c != '1' && c != '2' &&
  23. c != '3' && c != '4' && c != '5') {
  24. System.out.print("选择错误,请重新输入:");
  25. } else break;
  26. }
  27. return c;
  28. }
  29. /**
  30. * 功能:读取键盘输入的一个字符
  31. *
  32. * @return 一个字符
  33. */
  34. public static char readChar() {
  35. String str = readKeyBoard(1, false);//就是一个字符
  36. return str.charAt(0);
  37. }
  38. /**
  39. * 功能:读取键盘输入的一个字符,如果直接按回车,则返回指定的默认值;否则返回输入的那个字符
  40. *
  41. * @param defaultValue 指定的默认值
  42. * @return 默认值或输入的字符
  43. */
  44. public static char readChar(char defaultValue) {
  45. String str = readKeyBoard(1, true);//要么是空字符串,要么是一个字符
  46. return (str.length() == 0) ? defaultValue : str.charAt(0);
  47. }
  48. /**
  49. * 功能:读取键盘输入的整型,长度小于2位
  50. *
  51. * @return 整数
  52. */
  53. public static int readInt() {
  54. int n;
  55. for (; ; ) {
  56. String str = readKeyBoard(10, false);//一个整数,长度<=10位
  57. try {
  58. n = Integer.parseInt(str);//将字符串转换成整数
  59. break;
  60. } catch (NumberFormatException e) {
  61. System.out.print("数字输入错误,请重新输入:");
  62. }
  63. }
  64. return n;
  65. }
  66. /**
  67. * 功能:读取键盘输入的 整数或默认值,如果直接回车,则返回默认值,否则返回输入的整数
  68. *
  69. * @param defaultValue 指定的默认值
  70. * @return 整数或默认值
  71. */
  72. public static int readInt(int defaultValue) {
  73. int n;
  74. for (; ; ) {
  75. String str = readKeyBoard(10, true);
  76. if (str.equals("")) {
  77. return defaultValue;
  78. }
  79. //异常处理...
  80. try {
  81. n = Integer.parseInt(str);
  82. break;
  83. } catch (NumberFormatException e) {
  84. System.out.print("数字输入错误,请重新输入:");
  85. }
  86. }
  87. return n;
  88. }
  89. /**
  90. * 功能:读取键盘输入的指定长度的字符串
  91. *
  92. * @param limit 限制的长度
  93. * @return 指定长度的字符串
  94. */
  95. public static String readString(int limit) {
  96. return readKeyBoard(limit, false);
  97. }
  98. /**
  99. * 功能:读取键盘输入的指定长度的字符串或默认值,如果直接回车,返回默认值,否则返回字符串
  100. *
  101. * @param limit 限制的长度
  102. * @param defaultValue 指定的默认值
  103. * @return 指定长度的字符串
  104. */
  105. public static String readString(int limit, String defaultValue) {
  106. String str = readKeyBoard(limit, true);
  107. return str.equals("") ? defaultValue : str;
  108. }
  109. /**
  110. * 功能:读取键盘输入的确认选项,Y或N
  111. * 将小的功能,封装到一个方法中.
  112. *
  113. * @return Y或N
  114. */
  115. public static char readConfirmSelection() {
  116. System.out.print("确认是否预定(Y/N): ");
  117. char c;
  118. for (; ; ) {//无限循环
  119. //在这里,将接受到字符,转成了大写字母
  120. //y => Y n=>N
  121. String str = readKeyBoard(1, false).toUpperCase();
  122. c = str.charAt(0);
  123. if (c == 'Y' || c == 'N') {
  124. break;
  125. } else {
  126. System.out.print("选择错误,请重新输入:");
  127. }
  128. }
  129. return c;
  130. }
  131. /**
  132. * 功能: 读取一个字符串
  133. *
  134. * @param limit 读取的长度
  135. * @param blankReturn 如果为true ,表示 可以读空字符串。
  136. * 如果为false表示 不能读空字符串。
  137. * <p>
  138. * 如果输入为空,或者输入大于limit的长度,就会提示重新输入。
  139. * @return
  140. */
  141. private static String readKeyBoard(int limit, boolean blankReturn) {
  142. //定义了字符串
  143. String line = "";
  144. //scanner.hasNextLine() 判断有没有下一行
  145. while (scanner.hasNextLine()) {
  146. line = scanner.nextLine();//读取这一行
  147. //如果line.length=0, 即用户没有输入任何内容,直接回车
  148. if (line.length() == 0) {
  149. if (blankReturn) return line;//如果blankReturn=true,可以返回空串
  150. else continue; //如果blankReturn=false,不接受空串,必须输入内容
  151. }
  152. //如果用户输入的内容大于了 limit,就提示重写输入
  153. //如果用户如的内容 >0 <= limit ,我就接受
  154. if (line.length() < 1 || line.length() > limit) {
  155. System.out.print("输入长度(不能大于" + limit + ")错误,请重新输入:");
  156. continue;
  157. }
  158. break;
  159. }
  160. return line;
  161. }
  162. }

DAO类

BasicDAO

  1. import com.ryy.mhl.utils.JDBCUtilsByDruid;
  2. import org.apache.commons.dbutils.QueryRunner;
  3. import org.apache.commons.dbutils.handlers.BeanHandler;
  4. import org.apache.commons.dbutils.handlers.BeanListHandler;
  5. import org.apache.commons.dbutils.handlers.ScalarHandler;
  6. import java.sql.Connection;
  7. import java.sql.SQLException;
  8. import java.util.List;
  9. /**
  10. * 开发BasicDAo,是其他DAO的父类
  11. *
  12. * @param <T>
  13. */
  14. public class BasicDAO<T> {
  15. private QueryRunner qr = new QueryRunner();
  16. //开发通用的dml方法,针对任意的表
  17. public int update(String sql, Object... parameters) {
  18. Connection connection = null;
  19. try {
  20. connection = JDBCUtilsByDruid.getConnection(); //通过Druid连接池拿到连接
  21. int update = qr.update(connection, sql, parameters); //执行dml操作的方法
  22. return update;
  23. } catch (SQLException e) {
  24. throw new RuntimeException(e);
  25. } finally {
  26. JDBCUtilsByDruid.close(null, null, connection);
  27. }
  28. }
  29. //如果是执行SELECT语句返回多行多列
  30. /**
  31. * @param sql sql语句,可以有?
  32. * @param clazz 传入一个类的class对象 比如Actor.class
  33. * @param parameters 传入?的具体的值,可以是多个
  34. * @return 根据Actor.class返回对应的ArrayList集合
  35. */
  36. public List<T> queryMulti(String sql, Class<T> clazz, Object... parameters) {
  37. Connection connection = null;
  38. try {
  39. connection = JDBCUtilsByDruid.getConnection(); //通过Druid连接池拿到连接
  40. return qr.query(connection, sql, new BeanListHandler<T>(clazz), parameters);
  41. } catch (SQLException e) {
  42. throw new RuntimeException(e);
  43. } finally {
  44. JDBCUtilsByDruid.close(null, null, connection);
  45. }
  46. }
  47. //返回单行多列
  48. public T querySingle(String sql, Class<T> clazz, Object... parameters) {
  49. Connection connection = null;
  50. try {
  51. connection = JDBCUtilsByDruid.getConnection(); //通过Druid连接池拿到连接
  52. return qr.query(connection, sql, new BeanHandler<T>(clazz), parameters);
  53. } catch (SQLException e) {
  54. throw new RuntimeException(e);
  55. } finally {
  56. JDBCUtilsByDruid.close(null, null, connection);
  57. }
  58. }
  59. //若要返回单值
  60. public Object queryScalar(String sql, Object... parameters) {
  61. Connection connection = null;
  62. try {
  63. connection = JDBCUtilsByDruid.getConnection(); //通过Druid连接池拿到连接
  64. return qr.query(connection, sql, new ScalarHandler(), parameters);
  65. } catch (SQLException e) {
  66. throw new RuntimeException(e);
  67. } finally {
  68. JDBCUtilsByDruid.close(null, null, connection);
  69. }
  70. }
  71. }

BillDAO

DetailedEmployeeTableDAO

DiningTableDAO

 EmployeeDAO

MenuDAO

MultiTableDAO

以上这些DAO全部都只需要继承BasicDAO即可,没有其他多余代码

domain类

Bill

  1. import java.time.LocalDateTime;
  2. import java.util.Date;
  3. /**
  4. * javabean 和bill表对应
  5. */
  6. public class Bill {
  7. private Integer id;
  8. private String billId;
  9. private Integer menuId;
  10. private Integer nums;
  11. private Double money;
  12. private Integer diningTableId;
  13. private LocalDateTime billDate;
  14. private String state;
  15. public Bill() {
  16. }
  17. public Bill(Integer id, String billId, Integer menuId, Integer nums, Double money,
  18. Integer diningTableId, LocalDateTime billDate, String state) {
  19. this.id = id;
  20. this.billId = billId;
  21. this.menuId = menuId;
  22. this.nums = nums;
  23. this.money = money;
  24. this.diningTableId = diningTableId;
  25. this.billDate = billDate;
  26. this.state = state;
  27. }
  28. public Integer getId() {
  29. return id;
  30. }
  31. public void setId(Integer id) {
  32. this.id = id;
  33. }
  34. public String getBillId() {
  35. return billId;
  36. }
  37. public void setBillId(String billId) {
  38. this.billId = billId;
  39. }
  40. public Integer getMenuId() {
  41. return menuId;
  42. }
  43. public void setMenuId(Integer menuId) {
  44. this.menuId = menuId;
  45. }
  46. public Integer getNums() {
  47. return nums;
  48. }
  49. public void setNums(Integer nums) {
  50. this.nums = nums;
  51. }
  52. public Double getMoney() {
  53. return money;
  54. }
  55. public void setMoney(Double money) {
  56. this.money = money;
  57. }
  58. public Integer getDiningTableId() {
  59. return diningTableId;
  60. }
  61. public void setDiningTableId(Integer diningTableId) {
  62. this.diningTableId = diningTableId;
  63. }
  64. public LocalDateTime getBillDate() {
  65. return billDate;
  66. }
  67. public void setBillDate(LocalDateTime billDate) {
  68. this.billDate = billDate;
  69. }
  70. public String getState() {
  71. return state;
  72. }
  73. public void setState(String state) {
  74. this.state = state;
  75. }
  76. @Override
  77. public String toString() {
  78. return id +
  79. "\t\t" + menuId +
  80. "\t\t\t" + nums +
  81. "\t\t\t" + money +
  82. "\t" + diningTableId +
  83. "\t\t" + billDate +
  84. "\t\t" + state ;
  85. }
  86. }

DetailedEmployeeTable

  1. public class DetailedEmployeeTable {
  2. private Integer id;
  3. private String empId;
  4. private String name;
  5. private String job;
  6. private String education;
  7. private Integer Tel;
  8. private String Marry;
  9. public DetailedEmployeeTable() {
  10. }
  11. public DetailedEmployeeTable(Integer id, String empId, String name,
  12. String job, String education, Integer tel, String marry) {
  13. this.id = id;
  14. this.empId = empId;
  15. this.name = name;
  16. this.job = job;
  17. this.education = education;
  18. Tel = tel;
  19. Marry = marry;
  20. }
  21. public Integer getId() {
  22. return id;
  23. }
  24. public void setId(Integer id) {
  25. this.id = id;
  26. }
  27. public String getEmpId() {
  28. return empId;
  29. }
  30. public void setEmpId(String empId) {
  31. this.empId = empId;
  32. }
  33. public String getName() {
  34. return name;
  35. }
  36. public void setName(String name) {
  37. this.name = name;
  38. }
  39. public String getJob() {
  40. return job;
  41. }
  42. public void setJob(String job) {
  43. this.job = job;
  44. }
  45. public String getEducation() {
  46. return education;
  47. }
  48. public void setEducation(String education) {
  49. this.education = education;
  50. }
  51. public Integer getTel() {
  52. return Tel;
  53. }
  54. public void setTel(Integer tel) {
  55. Tel = tel;
  56. }
  57. public String getMarry() {
  58. return Marry;
  59. }
  60. public void setMarry(String marry) {
  61. Marry = marry;
  62. }
  63. }

DiningTable

  1. /**
  2. * 这是一个javabean和diningTable对应
  3. */
  4. public class DiningTable {
  5. private Integer id;
  6. private String state;
  7. private String orderName;
  8. private String oderTel;
  9. public DiningTable() {
  10. }
  11. public DiningTable(Integer id, String state, String orderName, String oderTel) {
  12. this.id = id;
  13. this.state = state;
  14. this.orderName = orderName;
  15. this.oderTel = oderTel;
  16. }
  17. public Integer getId() {
  18. return id;
  19. }
  20. public void setId(Integer id) {
  21. this.id = id;
  22. }
  23. public String getState() {
  24. return state;
  25. }
  26. public void setState(String state) {
  27. this.state = state;
  28. }
  29. public String getOrderName() {
  30. return orderName;
  31. }
  32. public void setOrderName(String orderName) {
  33. this.orderName = orderName;
  34. }
  35. public String getOderTel() {
  36. return oderTel;
  37. }
  38. public void setOderTel(String oderTel) {
  39. this.oderTel = oderTel;
  40. }
  41. @Override
  42. public String toString() {
  43. return id + "\t\t\t" + state;
  44. }
  45. }

Employee

  1. /**
  2. * 这是一个javabean和 employee表对应
  3. */
  4. public class Employee {
  5. private Integer id;
  6. private String empId;
  7. private String pwd;
  8. private String name;
  9. private String job;
  10. public Employee() { //一定先提供无参构造器,底层apache-dbutils反射需要
  11. }
  12. public Employee(Integer id, String empId, String pwd, String name, String job) {
  13. this.id = id;
  14. this.empId = empId;
  15. this.pwd = pwd;
  16. this.name = name;
  17. this.job = job;
  18. }
  19. public Integer getId() {
  20. return id;
  21. }
  22. public void setId(Integer id) {
  23. this.id = id;
  24. }
  25. public String getEmpId() {
  26. return empId;
  27. }
  28. public void setEmpId(String empId) {
  29. this.empId = empId;
  30. }
  31. public String getPwd() {
  32. return pwd;
  33. }
  34. public void setPwd(String pwd) {
  35. this.pwd = pwd;
  36. }
  37. public String getName() {
  38. return name;
  39. }
  40. public void setName(String name) {
  41. this.name = name;
  42. }
  43. public String getJob() {
  44. return job;
  45. }
  46. public void setJob(String job) {
  47. this.job = job;
  48. }
  49. }

Menu

  1. public class Menu {
  2. private Integer id;
  3. private String name;
  4. private String type;
  5. private Double price;
  6. public Menu() {
  7. }
  8. public Menu(Integer id, String name, String type, Double price) {
  9. this.id = id;
  10. this.name = name;
  11. this.type = type;
  12. this.price = price;
  13. }
  14. public Integer getId() {
  15. return id;
  16. }
  17. public void setId(Integer id) {
  18. this.id = id;
  19. }
  20. public String getName() {
  21. return name;
  22. }
  23. public void setName(String name) {
  24. this.name = name;
  25. }
  26. public String getType() {
  27. return type;
  28. }
  29. public void setType(String type) {
  30. this.type = type;
  31. }
  32. public Double getPrice() {
  33. return price;
  34. }
  35. public void setPrice(Double price) {
  36. this.price = price;
  37. }
  38. @Override
  39. public String toString() {
  40. return id + "\t\t\t" + name + "\t\t" + type + "\t\t" + price;
  41. }
  42. }

MultiTableBean

  1. import java.time.LocalDateTime;
  2. /**
  3. * 这是一个javabean 可以和多张表进行对应
  4. */
  5. public class MultiTableBean {
  6. private Integer id;
  7. private String billId;
  8. private Integer menuId;
  9. private Integer nums;
  10. private Double money;
  11. private Integer diningTableId;
  12. private LocalDateTime billDate;
  13. private String state;
  14. //增加一个来自menu表的列 name
  15. private String name;
  16. public MultiTableBean() {
  17. }
  18. public MultiTableBean(Integer id, String billId, Integer menuId, Integer nums, Double money,
  19. Integer diningTableId, LocalDateTime billDate, String state, String name) {
  20. this.id = id;
  21. this.billId = billId;
  22. this.menuId = menuId;
  23. this.nums = nums;
  24. this.money = money;
  25. this.diningTableId = diningTableId;
  26. this.billDate = billDate;
  27. this.state = state;
  28. this.name = name;
  29. }
  30. public String getName() {
  31. return name;
  32. }
  33. public void setName(String name) {
  34. this.name = name;
  35. }
  36. public Integer getId() {
  37. return id;
  38. }
  39. public void setId(Integer id) {
  40. this.id = id;
  41. }
  42. public String getBillId() {
  43. return billId;
  44. }
  45. public void setBillId(String billId) {
  46. this.billId = billId;
  47. }
  48. public Integer getMenuId() {
  49. return menuId;
  50. }
  51. public void setMenuId(Integer menuId) {
  52. this.menuId = menuId;
  53. }
  54. public Integer getNums() {
  55. return nums;
  56. }
  57. public void setNums(Integer nums) {
  58. this.nums = nums;
  59. }
  60. public Double getMoney() {
  61. return money;
  62. }
  63. public void setMoney(Double money) {
  64. this.money = money;
  65. }
  66. public Integer getDiningTableId() {
  67. return diningTableId;
  68. }
  69. public void setDiningTableId(Integer diningTableId) {
  70. this.diningTableId = diningTableId;
  71. }
  72. public LocalDateTime getBillDate() {
  73. return billDate;
  74. }
  75. public void setBillDate(LocalDateTime billDate) {
  76. this.billDate = billDate;
  77. }
  78. public String getState() {
  79. return state;
  80. }
  81. public void setState(String state) {
  82. this.state = state;
  83. }
  84. @Override
  85. public String toString() {
  86. return id +
  87. "\t\t" + menuId +
  88. "\t\t\t" + nums +
  89. "\t\t\t" + money +
  90. "\t" + diningTableId +
  91. "\t\t" + billDate +
  92. "\t\t" + state +
  93. "\t" + name;
  94. }
  95. }

Service类

BillService

  1. import com.ryy.mhl.dao.BillDAO;
  2. import com.ryy.mhl.dao.MultiTableDAO;
  3. import com.ryy.mhl.domain.Bill;
  4. import com.ryy.mhl.domain.MultiTableBean;
  5. import java.util.List;
  6. import java.util.UUID;
  7. /**
  8. * 处理和账单相关的业务逻辑
  9. */
  10. public class BillService {
  11. //定义BillDAO属性
  12. private BillDAO billDAO = new BillDAO();
  13. //定义MenuService属性
  14. private MenuService menuService = new MenuService();
  15. //定义DiningTableService属性
  16. private DiningTableService diningTableService = new DiningTableService();
  17. //定义MultiTableDAO属性
  18. private MultiTableDAO multiTableDAO = new MultiTableDAO();
  19. //编写点餐的方法
  20. //1.生成账单
  21. //2.需要更新对应餐桌的状态
  22. //3.如果成功返回真,失败就返回false
  23. public boolean orderMenu(int menuId, int nums, int diningTableId) {
  24. //生成一个账单号,UUID
  25. String billID = UUID.randomUUID().toString();
  26. //将账单生成到bill表,要求直接计算账单金额
  27. /*注意此时要拿到菜品的价格就要去MenuService类中再创建一个方法能够返回菜品的价格进行计算*/
  28. int update = billDAO.update("insert into bill values(null,?,?,?,?,?,now(),'未结账')",
  29. billID, menuId, nums, menuService.getMenuById(menuId).getPrice() * nums, diningTableId);
  30. if (update <= 0) {
  31. return false;
  32. }
  33. //需要更新对应餐桌的状态
  34. return diningTableService.updateDiningTableState(diningTableId, "就餐中");
  35. }
  36. //返回所有的账单,提供给View调用
  37. public List<Bill> list() {
  38. return billDAO.queryMulti("select * from bill", Bill.class);
  39. }
  40. //使用多表查询返回在一张表内(返回所有账单并显示菜品名
  41. public List<MultiTableBean> list2() { //注意在拼接sql语句的时候最后一定要带上空格
  42. return multiTableDAO.queryMulti("SELECT bill.*,NAME "
  43. + "FROM bill,menu "
  44. + "WHERE bill.menuId = menu.id",MultiTableBean.class);
  45. }
  46. //查看某个餐桌是否有未结账的账单
  47. public boolean hasPayBillByDiningTableId(int diningTableId) {
  48. Bill bill = billDAO.querySingle("SELECT * FROM bill WHERE diningTableId=? AND state='未结账' LIMIT 0, 1",
  49. Bill.class, diningTableId);
  50. return bill != null;
  51. }
  52. //完成结账[如果餐桌存在,并且该餐桌有未结账的账单]
  53. public boolean payBill(int dinningTableId, String payMode) {
  54. //1. 修改bill表
  55. int update = billDAO.update("update bill set state=? where diningTableId=? and state='未结账'",
  56. payMode, dinningTableId);
  57. if (update <= 0) { //更新失败情况
  58. return false;
  59. }
  60. //2. 修改diningTable表
  61. //注:不要直接在这里操作,而应该调用DiningTableService方法,更新餐桌就应该在餐桌类里修改以体现出各司其职
  62. if (!diningTableService.updateDiningTableToFree(dinningTableId, "空")) {
  63. return false;
  64. }
  65. return true;
  66. }
  67. //完成结账后将账单删除的方法
  68. public void deleteBill(int diningTableId) {
  69. int update = billDAO.update("DELETE FROM bill WHERE diningTableId=?", diningTableId);
  70. }
  71. }

DetailedEmployeeService

  1. import com.ryy.mhl.dao.DetailedEmployeeTableDAO;
  2. import com.ryy.mhl.domain.DetailedEmployeeTable;
  3. import java.util.List;
  4. public class DetailedEmployeeService {
  5. private DetailedEmployeeTableDAO detailedEmployeeTableDAO = new DetailedEmployeeTableDAO();
  6. public List<DetailedEmployeeTable> PersonManage(String empId) {
  7. List<DetailedEmployeeTable> list =
  8. detailedEmployeeTableDAO.queryMulti("select * from detailEmployee where empId=?",
  9. DetailedEmployeeTable.class, empId);
  10. return list;
  11. }
  12. }

DiningTableService

  1. import com.ryy.mhl.dao.DiningTableDAO;
  2. import com.ryy.mhl.domain.DiningTable;
  3. import java.util.List;
  4. public class DiningTableService {
  5. //定义一个DiningTableDAO对象以后要对DAo里面的内容进行调用
  6. private DiningTableDAO diningTableDAO = new DiningTableDAO();
  7. //返回所有餐桌的信息
  8. public List<DiningTable> list() {
  9. List<DiningTable> diningTables =
  10. diningTableDAO.queryMulti("select id, state from diningTable", DiningTable.class);
  11. return diningTables;
  12. }
  13. //根据id,查询对应餐桌的DiningTable对象
  14. //如果返回null,表示餐桌的id不存在
  15. public DiningTable getDiningTableById(int id) {
  16. return diningTableDAO.querySingle("select * from diningTable where id = ?", DiningTable.class, id);
  17. }
  18. //如果餐桌可以预定,调用方法,对其状态进行更新(包括预定人的名字和电话)
  19. public boolean orderDiningTable(int id, String orderName, String orderTel) {
  20. int update = diningTableDAO.update
  21. ("update diningTable set state = '已经预定', orderName=?, orderTel=? where id=?",
  22. orderName, orderTel, id);
  23. return update > 0; //大于0表示更新成功了
  24. }
  25. //需要提供一个更新餐桌状态的方法
  26. public boolean updateDiningTableState(int id, String state) {
  27. int update = diningTableDAO.update("update diningTable set state=? where id=?", state, id);
  28. return update > 0;
  29. }
  30. //提供方法,将指定的餐桌设置为空闲状态
  31. public boolean updateDiningTableToFree(int id, String state) {
  32. int update = diningTableDAO.update("update diningTable set state=?,orderName='',orderTel='' where id=?", state, id);
  33. return update > 0;
  34. }
  35. }

EmployeeService

  1. import com.ryy.mhl.dao.EmployeeDAO;
  2. import com.ryy.mhl.domain.Employee;
  3. /**
  4. * 该类完成对employee表的各种操作(通过调用EmployeeDAO完成)
  5. */
  6. public class EmployeeService {
  7. //定义一个EmployeeDAO属性
  8. private EmployeeDAO employeeDAO = new EmployeeDAO();
  9. //方法,根据 empId 和 pwd 返回一个Employee对象
  10. //如果查询不到就返回null
  11. public Employee getEmployeeByIdAndPwd(String empId, String pwd) {
  12. Employee employee = employeeDAO.querySingle("select * from employee where empId=? and pwd=MD5(?)",
  13. Employee.class, empId, pwd);
  14. return employee;
  15. }
  16. }

MenuService

  1. import com.ryy.mhl.dao.MenuDAO;
  2. import com.ryy.mhl.domain.Menu;
  3. import java.util.List;
  4. /**
  5. * 完成对menu表的各种操作(通过调用MenuDAO)
  6. */
  7. public class MenuService {
  8. //定义MenuDAO属性
  9. private MenuDAO menuDAO = new MenuDAO();
  10. //返回所有的菜品,返回给界面使用
  11. public List<Menu> list() {
  12. return menuDAO.queryMulti("select * from menu", Menu.class);
  13. }
  14. //需要方法,根据id,返回Menu对象
  15. //验证菜品是否存在的方法
  16. public Menu getMenuById (int id) {
  17. return menuDAO.querySingle("select * from menu where id=?", Menu.class, id);
  18. }
  19. }

View类

MHLView

  1. import com.ryy.mhl.domain.*;
  2. import com.ryy.mhl.service.*;
  3. import com.ryy.mhl.utils.Utility;
  4. import java.util.List;
  5. import java.util.Scanner;
  6. public class MHLView {
  7. //控制是否退出菜单
  8. private boolean loop = true;
  9. private boolean loop2 = true;
  10. private boolean loop3 = true;
  11. private String key = ""; //接收用户选择
  12. //定义EmployeeService属性
  13. private EmployeeService employeeService = new EmployeeService();
  14. //调用DiningTable的属性
  15. private DiningTableService diningTableService = new DiningTableService();
  16. //定义MenuService属性
  17. private MenuService menuService = new MenuService();
  18. //定义BillService属性
  19. private BillService billService = new BillService();
  20. //定义DetailedEmployeeService属性
  21. private DetailedEmployeeService detailedEmployeeService = new DetailedEmployeeService();
  22. public static void main(String[] args) {
  23. new MHLView().mainMenu();
  24. }
  25. //完成结账
  26. public void payBill() {
  27. System.out.println("============结账服务============");
  28. System.out.print("请选择要结账的餐桌编号(-1退出):");
  29. int diningTableId = Utility.readInt();
  30. if (diningTableId == -1) {
  31. System.out.println("============取消结账============");
  32. return;
  33. }
  34. //验证餐桌是否存在
  35. DiningTable diningTable = diningTableService.getDiningTableById(diningTableId);
  36. if (diningTable == null) {
  37. System.out.println("============结账的餐桌不存在============");
  38. return;
  39. }
  40. //验证餐桌是否有需要结账的账单
  41. if (!billService.hasPayBillByDiningTableId(diningTableId)) {
  42. System.out.println("============该餐桌没有未结账账单============");
  43. return;
  44. }
  45. System.out.print("结账方式(现金/微信/支付宝)回车表示退出:");
  46. String payMode = Utility.readString(20, ""); //说明:如果回车,就是返回“”
  47. if ("".equals(payMode)) {
  48. System.out.println("============取消结账============");
  49. return;
  50. }
  51. char key = Utility.readConfirmSelection();
  52. if (key == 'Y') {
  53. //调用BillService里的结账方法
  54. if (billService.payBill(diningTableId, payMode)) {
  55. System.out.println("============完成结账!============");
  56. billService.deleteBill(diningTableId);
  57. } else {
  58. System.out.println("============结账失败...============");
  59. }
  60. } else {
  61. System.out.println("============取消结账============");
  62. }
  63. }
  64. //显示账单信息
  65. public void listBill() {
  66. // List<Bill> bills = billService.list();
  67. // System.out.println("\n编号\t\t菜品号\t\t菜品量\t\t金额\t\t桌号\t\t日期\t\t\t\t\t\t状态");
  68. // for (Bill bill : bills) {
  69. // System.out.println(bill);
  70. // }
  71. // System.out.println("============显示完毕============");
  72. List<MultiTableBean> multiTableBeans = billService.list2();
  73. System.out.println("\n编号\t\t菜品号\t\t菜品量\t\t金额\t\t桌号\t\t日期\t\t\t\t\t\t状态\t\t菜品名");
  74. for (MultiTableBean bill : multiTableBeans) {
  75. System.out.println(bill);
  76. }
  77. System.out.println("============显示完毕============");
  78. }
  79. //完成点餐
  80. public void orderMenu() {
  81. System.out.println("============点餐服务============");
  82. System.out.print("请输入点餐的桌号(-1退出):");
  83. int orderDiningTableId = Utility.readInt();
  84. if (orderDiningTableId == -1) {
  85. System.out.println("============取消点餐============");
  86. return;
  87. }
  88. while (loop2) {
  89. System.out.print("请输入点餐的菜品号(-1退出):");
  90. int orderMenuId = Utility.readInt();
  91. if (orderMenuId == -1) {
  92. System.out.println("============取消点餐============");
  93. return;
  94. }
  95. System.out.print("请输入点餐的菜品量(-1退出):");
  96. int orderNums = Utility.readInt();
  97. if (orderNums == -1) {
  98. System.out.println("============取消点餐============");
  99. return;
  100. }
  101. //验证餐桌号是否存在
  102. DiningTable diningTable = diningTableService.getDiningTableById(orderDiningTableId);
  103. if (diningTable == null) {
  104. System.out.println("============餐桌号不存在============");
  105. return;
  106. }
  107. //验证菜品编号
  108. Menu menu = menuService.getMenuById(orderMenuId);
  109. if (menu == null) {
  110. System.out.println("============菜品号不存在============");
  111. return;
  112. }
  113. //点餐
  114. if (billService.orderMenu(orderMenuId, orderNums, orderDiningTableId)) {
  115. System.out.println("============点餐成功============");
  116. } else {
  117. System.out.println("============点餐失败============");
  118. }
  119. //新增是否还要继续点餐功能,用循环实现
  120. System.out.print("请确认是否还要继续点餐(Y/N): ");
  121. Scanner scanner = new Scanner(System.in);
  122. String continueOrdering = scanner.nextLine().trim().toUpperCase();
  123. if (continueOrdering.equals("Y")) {
  124. continue;
  125. } else if (continueOrdering.equals("N")) {
  126. loop2 = false;
  127. }
  128. }
  129. loop2 = true;
  130. }
  131. //显示所有菜品
  132. public void listMenu() {
  133. List<Menu> list = menuService.list();
  134. System.out.println("\n菜品编号\t\t菜品名\t\t类别\t\t价格");
  135. for (Menu menu : list) {
  136. System.out.println(menu);
  137. }
  138. System.out.println("===============显示完毕===============");
  139. }
  140. //完成定座
  141. public void orderDiningTable() {
  142. System.out.println("==========预定餐桌===========");
  143. System.out.print("请选择要预定的餐桌编号(-1退出):");
  144. int orderId = Utility.readInt();
  145. if (orderId == -1) {
  146. System.out.println("===============取消预定餐桌===============");
  147. return;
  148. }
  149. char key = Utility.readConfirmSelection();
  150. if (key == 'Y') {
  151. //根据orderId返回对应的DiningTable对象,如果为null,说明该对象不存在
  152. DiningTable diningTable = diningTableService.getDiningTableById(orderId);
  153. if (diningTable == null) {
  154. System.out.println("==========预定餐桌不存在==========");
  155. return;
  156. }
  157. //判断该餐桌的状态是否为“空”
  158. if (!("空".equals(diningTable.getState()))) { //说明当前这个餐桌不是“空”状态
  159. System.out.println("==========该餐桌已被预定或处于就餐中==========");
  160. return;
  161. }
  162. System.out.print("预定人的名字:");
  163. String orderName = Utility.readString(50);
  164. System.out.print("预定人的电话:");
  165. String orderTel = Utility.readString(50);
  166. //更新餐桌状态
  167. if (diningTableService.orderDiningTable(orderId, orderName, orderTel)) {
  168. System.out.println("==========预定餐桌成功==========");
  169. } else {
  170. System.out.println("==========预定失败==========");
  171. }
  172. } else {
  173. System.out.println("==========取消预定餐桌==========");
  174. }
  175. }
  176. public void listDiningTable() {
  177. List<DiningTable> list = diningTableService.list();
  178. System.out.println("\n餐桌编号\t\t餐桌状态");
  179. for (DiningTable diningTable : list) {
  180. System.out.println(diningTable);
  181. }
  182. System.out.println("===============显示完毕===============");
  183. }
  184. //显示主菜单
  185. public void mainMenu() {
  186. while (loop) {
  187. System.out.println("===============满汉楼===============");
  188. System.out.println("\t\t 1 登录满汉楼");
  189. System.out.println("\t\t 2 登录满汉楼(员工)");
  190. System.out.println("\t\t 3 退出满汉楼");
  191. System.out.print("请输入你的选择:");
  192. key = Utility.readString(1);
  193. switch (key) {
  194. case "1":
  195. //显示二级菜单
  196. while (loop) {
  197. System.out.println("\n===============满汉楼(二级菜单)===============");
  198. System.out.println("\t\t 1 显示餐桌状态");
  199. System.out.println("\t\t 2 预定餐桌");
  200. System.out.println("\t\t 3 显示所有菜品");
  201. System.out.println("\t\t 4 点餐服务");
  202. System.out.println("\t\t 5 查看账单");
  203. System.out.println("\t\t 6 结账");
  204. System.out.println("\t\t 9 退出满汉楼");
  205. System.out.print("请输入你的选择:");
  206. key = Utility.readString(1);
  207. switch (key) {
  208. case "1":
  209. listDiningTable();
  210. break;
  211. case "2":
  212. orderDiningTable();
  213. break;
  214. case "3":
  215. listMenu();
  216. break;
  217. case "4":
  218. orderMenu();
  219. break;
  220. case "5":
  221. listBill();
  222. break;
  223. case "6":
  224. payBill();
  225. break;
  226. case "9":
  227. loop = false;
  228. break;
  229. default:
  230. System.out.println("你的输入有误,请重新输入");
  231. break;
  232. }
  233. }
  234. break;
  235. case "2":
  236. while (loop3) {
  237. System.out.print("输入员工号:");
  238. String empId = Utility.readString(50);
  239. System.out.print("输入密 码:");
  240. String pwd = Utility.readString(50);
  241. Employee employee = employeeService.getEmployeeByIdAndPwd(empId, pwd);
  242. if (employee != null) {
  243. System.out.println("===============登陆成功[" + employee.getName() + "]===============\n");
  244. System.out.print("是否要显示员工信息(Y/N):");
  245. Scanner scanner = new Scanner(System.in);
  246. String emp = scanner.nextLine().trim().toUpperCase();
  247. if (emp.equals("Y")) {
  248. List<DetailedEmployeeTable> list = detailedEmployeeService.PersonManage(empId);
  249. System.out.println("员工编号\t\t员工姓名\t\t岗位\t\t学历\t\t电话号码\t\t\t结婚情况");
  250. for (DetailedEmployeeTable detailedEmployeeTable : list) {
  251. System.out.println(detailedEmployeeTable.getEmpId() + "\t\t" + detailedEmployeeTable.getName()
  252. + "\t\t\t" + detailedEmployeeTable.getJob() + "\t\t" + detailedEmployeeTable.getEducation()
  253. + "\t\t" + detailedEmployeeTable.getTel() + "\t\t" + detailedEmployeeTable.getMarry());
  254. }
  255. System.out.println("==========显示完毕==========");
  256. break;
  257. } else if (emp.equals("N")) {
  258. break;
  259. }
  260. } else {
  261. System.out.println("登陆失败");
  262. loop3 = false;
  263. }
  264. }
  265. break;
  266. case "3":
  267. loop = false;
  268. break;
  269. default:
  270. System.out.println("你的输入有误,请重新输入...");
  271. }
  272. System.out.println("你退出了满汉楼系统");
  273. }
  274. }
  275. }

制作不易,喜欢的话请点个赞吧

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/花生_TL007/article/detail/716640
推荐阅读
相关标签
  

闽ICP备14008679号