学生管理系统
学生管理系统基础版
需求
采取控制台的方式去书写学生管理系统.
分析
初始菜单
"-------------欢迎来到黑马学生管理系统----------------"
"1: 添加学生"
"2: 删除学生"
"3: 修改学生"
"4: 查询学生"
"5: 退出"
"请输入您的选择:"
学生类
属性: id, 姓名, 年龄, 家庭住址
添加功能
键盘录入每一个学生信息并添加, 需要满足以下要求:
- id 唯一
删除功能
键盘录入要删除的学生 id, 需要满足以下要求:
-
id 存在删除
-
id 不存在, 需要提示不存在, 并回到初始菜单
修改功能
键盘录入要修改的学生 id, 需要满足以下要求
-
id 存在, 继续录入其他信息
-
id 不存在, 需要提示不存在, 并回到初始菜单
查询功能
打印所有的学生信息, 需要满足以下要求
-
如果没有学生信息, 提示: 当前无学生信息, 请添加后再查询
-
如果有学生信息, 需要按照以下格式输出. (不用过于纠结对齐的问题)
id 姓名 年龄 家庭住址 heima001 张三 23 南京 heima002 李四 24 北京 heima003 王五 25 广州 heima004 赵六 26 深圳
根据需求文档画业务流程图:

代码
Javabean 类:
public class Student { private String name; private String id; private int age; private String address; public Student() { } public Student(String name, String id, int age, String address) { this.name = name; this.id = id; this.age = age; this.address = address; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getId() { return id; } public void setId(String id) { this.id = id; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } }
测试类:
import java.util.ArrayList; import java.util.Scanner; public class StudentSystem { public static void main(String[] args) { // 创建一个集合, 用来存储学生信息 ArrayList<Student> students = new ArrayList<>(); Scanner sc = new Scanner(System.in); String choose; // 接收用户输入 loop: while (true) { showMenu(); // 显示欢迎界面 choose = sc.next(); // 建议这里写 next() 而不是 nextInt(), 如果是 nextInt(), 而用户输入了例如 abc 这样的数据, // 则程序报错, 使用了 next() 则不论用户输入什么样的内容程序都不会报错, 不合法的输入可以放到 default 中处理 switch (choose) { case "1" -> addStudent(students); case "2" -> deleteStudent(students); case "3" -> updateStudent(students); case "4" -> queryStudent(students); case "5" -> { System.out.println("退出"); break loop; } default -> System.out.println("输入错误, 请重新输入."); } } } // 显示欢迎界面 public static void showMenu() { System.out.println("------------- 欢迎来到黑马学生管理系统 -------------"); System.out.println("1: 添加学生"); System.out.println("2: 删除学生"); System.out.println("3: 修改学生"); System.out.println("4: 查询学生"); System.out.println("5: 退出"); System.out.print("请输入您的选择: "); } // 添加学生 public static void addStudent(ArrayList<Student> students) { // 利用 Student 类的空参构造函数, 创建一个 Student 类的对象 Student student = new Student(); // 从键盘获取数据, 再用 set 方法存入这个对象中 Scanner sc = new Scanner(System.in); while (true) { System.out.print("请输入学生的 id: "); String id = sc.next(); boolean contains = contains(students, id); if (contains) { // 表示 id 已经存在, 需要重新输入 System.out.println("id 已经存在, 请重新录入"); } else { // 表示 id 已经存在 student.setId(id); break; // 跳出循环, 继续录入姓名等其他信息 } } System.out.print("请输入学生的姓名: "); String name = sc.next(); student.setName(name); System.out.print("请输入学生的年龄: "); int age = sc.nextInt(); student.setAge(age); System.out.print("请输入学生的地址: "); String address = sc.next(); student.setAddress(address); // 把学生对象添加到集合中 students.add(student); // 提示用户添加成功 System.out.println("学生信息添加成功"); } // 删除学生 public static void deleteStudent(ArrayList<Student> students) { Scanner sc = new Scanner(System.in); System.out.print("请输入要删除的 id: "); String id = sc.next(); // 查询 id 在集合中的索引 int index = getIndex(students, id); // 对 index 进行判断, 如果为 -1, 就表示索引不存在, 结束方法, 回到欢迎界面, if (index == -1) { System.out.println("id 不存在, 删除失败."); } else { students.remove(index); System.out.println("id 为 " + id + " 的学生删除成功."); } } // 修改学生 public static void updateStudent(ArrayList<Student> students) { Scanner sc = new Scanner(System.in); System.out.print("请输入要修改的学生的 id: "); String id = sc.next(); // 根据 id 找索引 int index = getIndex(students, id); if (index == -1) { System.out.println("要修改的 id " + id + " 不存在, 请重新输入."); } else { Student student = students.get(index); // 输入其他信息并修改 System.out.print("请输出要修改的学生的姓名: "); student.setName(sc.next()); System.out.print("请输出要修改的学生的年龄: "); student.setAge(sc.nextInt()); System.out.print("请输出要修改的学生的地址: "); student.setAddress(sc.next()); System.out.println("学生信息修改成功"); } } // 查询学生 public static void queryStudent(ArrayList<Student> students) { // 如果学生集合长度为 0, 说明当前没有学生信息 if (students.size() == 0) { System.out.println("当前无学生信息, 请添加学生信息后再查询"); return; } // 如果代码执行到了这里, 说明当前学生集合中是有信息的, 所以要遍历集合打印学生信息 // 但是要先打印表头信息 System.out.println("id\t\t\t姓名\t\t\t年龄\t\t\t家庭住址"); for (int i = 0; i < students.size(); i++) { Student s = students.get(i); System.out.println(s.getId() + "\t\t\t" + s.getName() + "\t\t\t" + s.getAge() + "\t\t\t" + s.getAddress()); } } // 根据 id 返回学生的索引, 不存在时返回 -1 public static int getIndex(ArrayList<Student> list, String id) { for (int i = 0; i < list.size(); i++) { if (list.get(i).getId().equals(id)) { return i; } } return -1; } // 判断 id 在集合中是否存在 private static boolean contains(ArrayList<Student> list, String id) { // 复用 getIndex() 方法 return getIndex(list, id) >= 0; } }
while 循环内有 switch, 想要在 switch 中跳出 while 循环的方法:
方法一: 使用标签.
代码:
import java.util.Scanner; public class StudentSystem { public static void main(String[] args) { Scanner sc = new Scanner(System.in); String choose; loop: while (true) { showMenu(); choose = sc.next(); // 建议这里写 next() 而不是 nextInt(), 如果是 nextInt(), 而用户输入了例如 abc 这样的数据, // 则程序报错, 使用了 next() 则不论用户输入什么样的内容程序都不会报错, 不合法的输入可以放到 default 中处理 switch (choose) { case "1": break; case "2": break; case "3": break; case "4": break; case "5": { System.out.println("退出"); break loop; // switch 里面的 break 只能跳出 switch, 不能跳出 while 循环, 这里指定标签则可以跳出 while 循环 } default: System.out.println("输入错误, 请重新输入."); break; } System.out.println("switch 语句后面的内容."); } } // 显示菜单 public static void showMenu() { System.out.println("------------- 欢迎来到黑马学生管理系统 -------------"); System.out.println("1: 添加学生"); System.out.println("2: 删除学生"); System.out.println("3: 修改学生"); System.out.println("4: 查询学生"); System.out.println("5: 退出"); System.out.print("请输入您的选择: "); } }
另一种方法, 使用语句 System.exit(0);
.
代码:
import java.util.Scanner; public class StudentSystem { public static void main(String[] args) { Scanner sc = new Scanner(System.in); String choose; while (true) { showMenu(); choose = sc.next(); // 建议这里写 next() 而不是 nextInt(), 如果是 nextInt(), 而用户输入了例如 abc 这样的数据, // 则程序报错, 使用了 next() 则不论用户输入什么样的内容程序都不会报错, 不合法的输入可以放到 default 中处理 switch (choose) { case "1": break; case "2": break; case "3": break; case "4": break; case "5": { System.out.println("退出"); System.exit(0); // 停止虚拟机运行 } default: System.out.println("输入错误, 请重新输入."); break; } System.out.println("switch 语句后面的内容."); } } // 显示菜单 public static void showMenu() { System.out.println("------------- 欢迎来到黑马学生管理系统 -------------"); System.out.println("1: 添加学生"); System.out.println("2: 删除学生"); System.out.println("3: 修改学生"); System.out.println("4: 查询学生"); System.out.println("5: 退出"); System.out.print("请输入您的选择: "); } }
再或者, 用一个布尔值作为 while 是否继续的标签:
import java.util.Scanner; public class StudentSystem { public static void main(String[] args) { Scanner sc = new Scanner(System.in); String choose; boolean flag = true; while (flag) { showMenu(); choose = sc.next(); // 建议这里写 next() 而不是 nextInt(), 如果是 nextInt(), 而用户输入了例如 abc 这样的数据, // 则程序报错, 使用了 next() 则不论用户输入什么样的内容程序都不会报错, 不合法的输入可以放到 default 中处理 switch (choose) { case "1": break; case "2": break; case "3": break; case "4": break; case "5": { System.out.println("退出"); flag = false; break; } default: System.out.println("输入错误, 请重新输入."); break; } System.out.println("switch 语句后面的内容."); } } // 显示菜单 public static void showMenu() { System.out.println("------------- 欢迎来到黑马学生管理系统 -------------"); System.out.println("1: 添加学生"); System.out.println("2: 删除学生"); System.out.println("3: 修改学生"); System.out.println("4: 查询学生"); System.out.println("5: 退出"); System.out.print("请输入您的选择: "); } }
添加学生信息的方法, 有两种写法:
第一种:
// 添加学生 public static void addStudent(ArrayList<Student> students) { Scanner sc = new Scanner(System.in); System.out.print("请输入学生的 id: "); String id = sc.next(); System.out.print("请输入学生的姓名: "); String name = sc.next(); System.out.print("请输入学生的年龄: "); int age = sc.nextInt(); System.out.print("请输入学生的地址: "); String address = sc.next(); // 利用 Student 类的带全部参数的构造函数, 创建一个 Student 类的对象 Student newStudent = new Student(id, name, age, address); // 把学生对象添加到集合中 students.add(newStudent); // 提示用户添加成功 System.out.println("学生信息添加成功"); }
第二种:
// 添加学生 public static void addStudent(ArrayList<Student> students) { // 利用 Student 类的空参构造函数, 创建一个 Student 类的对象 Student student = new Student(); // 从键盘获取数据, 再用 set 方法存入这个对象中 Scanner sc = new Scanner(System.in); System.out.print("请输入学生的 id: "); String id = sc.next(); student.setId(id); System.out.print("请输入学生的姓名: "); String name = sc.next(); student.setName(name); System.out.print("请输入学生的年龄: "); int age = sc.nextInt(); student.setAge(age); System.out.print("请输入学生的地址: "); String address = sc.next(); student.setAddress(address); // 把学生对象添加到集合中 students.add(student); // 提示用户添加成功 System.out.println("学生信息添加成功"); }
这种写法, 虽然可以结束 while 循环, 但是 switch 后面的语句还是会被打印出来.
学生管理系统升级版
需求
为学生管理系统书写一个登陆、注册、忘记密码的功能.
只有用户登录成功之后, 才能进入到学生管理系统中进行增删改查操作.
分析
登录界面
System.out.println("欢迎来到学生管理系统"); System.out.println("请选择操作: 1 登录 2 注册 3 忘记密码");
用户类
属性: 用户名、密码、身份证号码、手机号码
注册功能
1. 用户名需要满足以下要求:
验证要求:
用户名唯一
用户名长度必须在 3~15 位之间
只能是字母加数字的组合, 但是不能是纯数字
2. 密码键盘输入两次, 两次一致才可以进行注册.
3. 身份证号码需要验证.
验证要求:
长度为 18 位
不能以 0 为开头
前 17 位, 必须都是数字
最为一位可以是数字, 也可以是大写 X 或小写 x
4. 手机号验证.
验证要求:
长度为 11 位
不能以 0 为开头
必须都是数字
登录功能
1. 键盘录入用户名
2. 键盘录入密码
3. 键盘录入验证码
验证要求:
用户名如果未注册, 直接结束方法, 并提示: 用户名未注册, 请先注册
判断验证码是否正确, 如不正确, 重新输入
再判断用户名和密码是否正确, 有3次机会
忘记密码
1. 键盘录入用户名, 判断当前用户名是否存在, 如不存在, 直接结束方法, 并提示: 未注册
2. 键盘录入身份证号码和手机号码
3. 判断当前用户的身份证号码和手机号码是否一致,
如果一致, 则提示输入密码, 进行修改.
如果不一致, 则提示: 账号信息不匹配, 修改失败.
验证码规则
长度为 5
由 4 位大写或者小写字母和 1 位数字组成, 同一个字母可重复
数字可以出现在任意位置
比如: aQa1K
根据需求画出图解:
整体的图解:
注册的图解:
登录的图解:
修改密码的图解:
最终代码:
Javabean 类:
package studentsystem; public class Student { private String id; private String name; private int age; private String address; public Student() { } public Student(String id, String name, int age, String address) { this.id = id; this.name = name; this.age = age; this.address = address; } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } }
Javabean 类:
package studentsystem; public class User { private String userName; private String password; private String personID; private String phoneNumber; public User() { } public User(String userName, String password, String personID, String phoneNumber) { this.userName = userName; this.password = password; this.personID = personID; this.phoneNumber = phoneNumber; } 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 getPersonID() { return personID; } public void setPersonID(String personID) { this.personID = personID; } public String getPhoneNumber() { return phoneNumber; } public void setPhoneNumber(String phoneNumber) { this.phoneNumber = phoneNumber; } }
学生管理系统代码:
package studentsystem; import java.util.ArrayList; import java.util.Scanner; public class StudentSystem { public static void startStudentSystem() { ArrayList<Student> students = new ArrayList<>(); Scanner sc = new Scanner(System.in); // 循环显示菜单, 直到用户选择退出 while (true) { showMenu(); System.out.print("请输入您的选择: "); String choice = sc.next(); switch (choice) { case "1": // System.out.println("添加学生"); addStudent(students); break; case "2": // System.out.println("删除学生"); deleteStudent(students); break; case "3": // System.out.println("修改学生"); updateStudent(students); break; case "4": // System.out.println("查询学生"); getIndex(students); break; case "5": System.out.println("退出"); System.exit(0); break; } } } private static void showMenu() { // 打印菜单 System.out.println("------------ 欢迎来到黑马程序员学生管理系统 ------------"); System.out.println("1: 添加学生"); System.out.println("2: 删除学生"); System.out.println("3: 修改学生"); System.out.println("4: 查询学生"); System.out.println("5: 退出"); } public static void addStudent(ArrayList<Student> students) { // System.out.println("添加学生"); Scanner sc = new Scanner(System.in); String id = null; while (true) { System.out.print("请输入学生 id: "); id = sc.next(); if (isExistStudent(students, id)) { System.out.println("id 已经存在, 请重新输入."); } else { break; } } System.out.print("请输入学生年龄: "); int age = sc.nextInt(); System.out.print("请输入学生的姓名: "); String name = sc.next(); System.out.print("请输入学生的家庭住址: "); String address = sc.next(); Student student = new Student(id, name, age, address); students.add(student); } // 判断 id 是否唯一 public static boolean isExistStudent(ArrayList<Student> students, String id) { /*for (Student student : students) { if (student.getId().equals(id)) { return true; } } return false;*/ /*int index = getIndex(students, id); return index != -1;*/ return getIndex(students, id) >= 0; } // 根据 id 返回学生的索引, 不存在时返回 -1 public static int getIndex(ArrayList<Student> students, String id) { for (int i = 0; i < students.size(); i++) { if (students.get(i).getId().equals(id)) { return i; } } return -1; } public static void deleteStudent(ArrayList<Student> students) { // System.out.println("删除学生"); System.out.print("请输入要删除的 id: "); Scanner sc = new Scanner(System.in); String id = sc.next(); if (isExistStudent(students, id)) { students.remove(getIndex(students, id)); System.out.println("id 为 " + id + " 的学生删除成功。"); } else { System.out.println("学生 id 不存在。"); } } public static void getIndex(ArrayList<Student> students) { // System.out.println("查询学生"); if (students.size() == 0) { System.out.println("当前无学生信息, 请添加学生信息后再查询"); return; } System.out.println("id\t\t姓名\t年龄\t家庭住址"); for (int i = 0; i < students.size(); i++) { Student student = students.get(i); System.out.println(student.getId() + "\t" + student.getName() + "\t" + student.getAge() + "\t" + student.getAddress()); } } public static void updateStudent(ArrayList<Student> students) { // System.out.println("修改学生"); } }
程序入口:
package studentsystem; import java.util.ArrayList; import java.util.Random; import java.util.Scanner; public class App { public static void main(String[] args) { ArrayList<User> users = new ArrayList<>(); Scanner scanner = new Scanner(System.in); while (true) { System.out.println("欢迎来到学生管理系统"); System.out.println("请选择操作: 1 登录 2 注册 3 忘记密码 4 退出"); String choice = scanner.next(); switch (choice) { case "1" -> login(users); case "2" -> register(users); case "3" -> forgetPassword(users); case "4" -> { System.out.println("谢谢使用, 再见!"); System.exit(0); } default -> System.out.println("没有这个选项."); } } } private static void forgetPassword(ArrayList<User> users) { // System.out.println("3 忘记密码"); System.out.print("请输入用户名: "); Scanner scanner = new Scanner(System.in); String username = scanner.next(); boolean contains = isContains(users, username); if (!contains) { System.out.println("用户名未注册."); return; } System.out.print("请输入身份证号码: "); String personID = scanner.next(); System.out.print("请输入手机号码: "); String phoneNumber = scanner.next(); int index = getIndex(users, username); User rightUser = users.get(index); String rightPersonID = rightUser.getPersonID(); String rightPhoneNumber = rightUser.getPhoneNumber(); /*System.out.println(rightPersonID); System.out.println(rightPhoneNumber);*/ if (!(personID.equals(rightPersonID) && phoneNumber.equals(rightPhoneNumber))) { System.out.println("身份证号码或者手机号码输入错误."); return; } String password = ""; while (true) { System.out.print("请输入新的密码: "); password = scanner.next(); System.out.print("请再次输入新的密码: "); String passwordAgain = scanner.next(); if (passwordAgain.equals(password)) { System.out.println("两次密码输入一致."); break; } else { System.out.println("两次密码输入不一致, 请重新输入."); } } rightUser.setPassword(password); System.out.println("密码修改成功."); } private static void register(ArrayList<User> users) { // System.out.println("2 注册"); // 输入用户名 Scanner scanner = new Scanner(System.in); String username = null; while (true) { System.out.print("请输入用户名: "); username = scanner.next(); // 先判断用户名的格式是否正确 // 格式要求: // 1. 用户名长度在 3~15 之间 // 2. 用户名只能是数字加字母的组合 // 3. 用户名不能是纯数字 boolean isCorrect = isCorrectFormatUsername(username); if (!isCorrect) { System.out.println("用户名格式错误, 请重新输入用户名."); } else { break; } } // 输入密码 String password = null; String againPassword = null; while (true) { System.out.print("请输入密码: "); password = scanner.next(); System.out.print("请再次输入密码: "); againPassword = scanner.next(); if (password.equals(againPassword)) { System.out.println("两次密码一致"); break; } else { System.out.println("两次密码不一致, 请重新输入."); } } // 输入身份证号码 String personID = null; while (true) { System.out.print("请输入身份证号码: "); personID = scanner.next(); // 验证身份证号码的格式是否符合 boolean isCorrectID = isCorrectFormatID(personID); if (!isCorrectID) { System.out.println("身份证号码格式不符合, 请重新输入."); } else { System.out.println("身份证号码的格式符合."); break; } } // 输入手机号 String phone = null; while (true) { System.out.print("请输入手机号: "); phone = scanner.next(); // 验证手机号码的格式是否符合要求 boolean isCorrectPhone = isCorrectFormatPhone(phone); if (!isCorrectPhone) { System.out.println("手机号码格式错误, 请重新输入."); } else { System.out.println("手机号码格式正确."); break; } } // 创建一个用户对象, 将这些读取到的信息存进这个用户对象, 再将这个用户对象存入存放用户对象的集合中 User user = new User(username, password, personID, phone); users.add(user); System.out.println("用户注册成功."); } private static boolean isCorrectFormatPhone(String phone) { if (phone.length() != 11) { return false; } if (phone.charAt(0) == '0') { return false; } for (int i = 0; i < phone.length(); i++) { char c = phone.charAt(i); if (!(c >= '0' && c <= '9')) { return false; } } return true; } private static boolean isCorrectFormatID(String personID) { if (personID.length() != 18) { return false; } if (personID.charAt(0) == '0') { return false; } for (int i = 0; i < personID.length() - 1; i++) { char ch = personID.charAt(i); if (!(ch >= '0' && ch <= '9')) { return false; } } char ch = personID.charAt(personID.length() - 1); if (!(ch == 'x' || ch == 'X' || ch >= '0' && ch <= '9')) { return false; } return true; } // 判断用户名的格式是否正确 private static boolean isCorrectFormatUsername(String username) { // 格式要求: // 1. 用户名长度在 3~15 之间 // 2. 用户名只能是数字加字母的组合 // 3. 用户名不能是纯数字 if (username == null || username.length() < 3 || username.length() > 15) { return false; } for (int i = 0; i < username.length(); i++) { char ch = username.charAt(i); if (!(ch >= '0' && ch <= '9' || ch >= 'A' && ch <= 'Z' || ch >= 'a' && ch <= 'z')) { return false; } } for (int i = 0; i < username.length(); i++) { char ch = username.charAt(i); if (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z') { return true; } } return false; } private static void login(ArrayList<User> users) { // System.out.println("1 登录"); System.out.print("请输入用户名: "); Scanner scanner = new Scanner(System.in); String username = scanner.next(); boolean isContains = isContains(users, username); if (!isContains) { System.out.println("用户名未注册, 请先注册."); return; } System.out.print("请输入密码: "); String password = scanner.next(); String rightCertificateCode = getCode(); System.out.println("正确的验证码为: " + rightCertificateCode); System.out.print("请输入验证码: "); String certiCode = scanner.next(); if (!rightCertificateCode.equalsIgnoreCase(certiCode)) { System.out.println("验证码错误"); return; } int index = getIndex(users, username); if (!password.equals(users.get(index).getPassword())) { System.out.println("密码错误"); return; } System.out.println("登录成功"); // 启动学生管理系统 StudentSystem studentSystem=new StudentSystem(); studentSystem.startStudentSystem(); } // 判断用户名是否存在 public static boolean isContains(ArrayList<User> users, String username) { for (int i = 0; i < users.size(); i++) { if (users.get(i).getUserName().equals(username)) { return true; } } return false; } // 根据用户名返回索引 public static int getIndex(ArrayList<User> users, String username) { for (int i = 0; i < users.size(); i++) { if (users.get(i).getUserName().equals(username)) { return i; } } return -1; } // 生成验证码 public static String getCode() { ArrayList<Character> chCode = new ArrayList<>(); for (char ch = 'a'; ch <= 'z'; ch++) { chCode.add(ch); } for (char ch2 = 'A'; ch2 <= 'Z'; ch2++) { chCode.add(ch2); } ArrayList<Character> numberCode = new ArrayList<>(); for (char ch = '0'; ch <= '9'; ch++) { numberCode.add(ch); } // 先把第一个位置放数字, 等验证码生成之后, 再随机一个索引, 进行交换 String code = ""; Random random = new Random(); int index = random.nextInt(numberCode.size()); code += numberCode.get(index); for (int i = 0; i < 4; i++) { int index2 = random.nextInt(chCode.size()); code += chCode.get(index2); } int index3 = random.nextInt(code.length()); char[] chars = code.toCharArray(); char tmp = chars[0]; chars[0] = chars[index3]; chars[index3] = tmp; return new String(chars); } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!