留言管理的业务实际上是分为管理员留言管理与普通用户留言管理
管理员留言管理
基于之前的需求,管理员可查看所有留言以及删除任一留言
使用Scene Builder开发页面
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.Font?>
<?import javafx.scene.text.Text?>
<?import javafx.geometry.Insets?>
<AnchorPane xmlns="http://javafx.com/javafx"
xmlns:fx="http://javafx.com/fxml"
fx:controller="LeaveMessageSystem.controller.UserMessageManageFrameController"
prefHeight="700.0" prefWidth="800.0">
<children>
<VBox alignment="CENTER" prefHeight="700.0" prefWidth="800.0">
<children>
<HBox alignment="CENTER" prefHeight="100.0" prefWidth="200.0">
<children>
<Label text="用户留言管理">
<font>
<Font name="System Bold" size="40.0" />
</font>
</Label>
</children>
</HBox>
<HBox alignment="CENTER" prefHeight="296.0" prefWidth="700.0">
<children>
<TableView fx:id="MessageTypeManageView" prefWidth="705.0" prefHeight="399.0" tableMenuButtonVisible="true">
<columns>
<TableColumn fx:id="messageIdColumn" prefWidth="50.0" text="编号"/>
<TableColumn fx:id="messageNameColumn" minWidth="0.0" prefWidth="100.0" text="用户昵称"/>
<TableColumn fx:id="messageTitleColumn" prefWidth="228.0" text="标题"/>
<TableColumn fx:id="messageContentColumn" prefWidth="220.0" text="内容"/>
<TableColumn fx:id="messageTimeColumn" prefWidth="101.0" text="留言时间"/>
</columns>
</TableView>
</children>
</HBox>
<HBox alignment="CENTER" prefHeight="263.0" prefWidth="700.0">
<children>
<VBox fx:id="formVbox" prefHeight="240.0" prefWidth="702.0">
<children>
<HBox alignment="CENTER_LEFT" prefHeight="100.0" prefWidth="200.0" spacing="10.0">
<children>
<Label text="编号:"/>
<TextField fx:id="messageIdField" prefHeight="30.0" prefWidth="50.0"/>
<Label text="用户昵称:"/>
<TextField fx:id="messageNameField" prefHeight="30.0" prefWidth="150.0"/>
<Label text="留言时间"/>
<TextField fx:id="messageTimeField" prefHeight="30.0" prefWidth="200.0"/>
</children>
<padding>
<Insets left="40.0"/>
<Insets bottom="20.0"/>
</padding>
</HBox>
<HBox prefHeight="100.0" prefWidth="200.0" spacing="10.0">
<children>
<Label text="标题:" />
<TextField fx:id="messageTitleField" prefHeight="30.0" prefWidth="265.0" />
</children>
<padding>
<Insets left="40.0"/>
<Insets bottom="20.0"/>
</padding>
</HBox>
<HBox prefHeight="260.0" prefWidth="500.0" spacing="10.0">
<children>
<Label text="内容:"/>
<TextField fx:id="messageContentField" prefHeight="250.0" prefWidth="400.0"/>
</children>
<padding>
<Insets left="40.0"/>
<Insets bottom="20.0"/>
</padding>
</HBox>
<HBox alignment="CENTER" prefWidth="100.0" prefHeight="200.0" spacing="100.0">
<children>
<Button fx:id="deleteButton" mnemonicParsing="false" onAction="#do_deleteButtom_event" text="删除"/>
</children>
<padding>
<Insets left="40.0"/>
</padding>
</HBox>
</children>
</VBox>
</children>
</HBox>
</children>
</VBox>
</children>
</AnchorPane>
效果如下:
在beans中开发Message的实体类
注意我在Message实体类封装了转换为Javafx中的类型
package LeaveMessageSystem.beans;
import javafx.beans.property.SimpleStringProperty;
public class Message {
private int id;
private String name;
private String title;
private String content;
public Message() {
}
public Message(int id, String name, String title, String content, String time) {
this.id = id;
this.name = name;
this.title = title;
this.content = content;
this.time = time;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getTime() {
return time;
}
public void setTime(String time) {
this.time = time;
}
private String time;
public SimpleStringProperty midProperty() {
String newid=id+"";
SimpleStringProperty idfx=new SimpleStringProperty(newid);
return idfx;
}
public SimpleStringProperty mnameProperty(){
SimpleStringProperty namefx=new SimpleStringProperty(name);
return namefx;
}
public SimpleStringProperty mtitleProperty(){
SimpleStringProperty tilefx=new SimpleStringProperty(title);
return tilefx;
}
public SimpleStringProperty mcontentProperty(){
SimpleStringProperty contentfx=new SimpleStringProperty(content);
return contentfx;
}
public SimpleStringProperty mtimeProperty(){
SimpleStringProperty timefx=new SimpleStringProperty(time);
return timefx;
}
}
在controller中新建java文件处理管理员留言管理的逻辑
细分为三个小事件
- 初始化界面
- 选中留言在下方展示
- 删除选中留言
package LeaveMessageSystem.controller;
import LeaveMessageSystem.beans.Message;
import LeaveMessageSystem.beans.UserTypeNewBeanData;
import LeaveMessageSystem.dao.MessageDao;
import LeaveMessageSystem.dao.UserDao;
import LeaveMessageSystem.tools.SimpleTools;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.scene.control.*;
import javafx.scene.layout.VBox;
import java.sql.SQLException;
import java.util.List;
public class UserMessageManageFrameController {
public TableView<Message> MessageTypeManageView;
public TableColumn<Message,String> messageIdColumn;
public TableColumn<Message,String> messageNameColumn;
public TableColumn<Message,String> messageTitleColumn;
public TableColumn<Message,String> messageContentColumn;
public TableColumn<Message,String> messageTimeColumn;
public VBox formVbox;
public TextField messageIdField;
public TextField messageNameField;
public TextField messageTimeField;
public TextField messageTitleField;
public TextField messageContentField;
public Button deleteButton;
// 实例化MesageDao对象
MessageDao messageDao=new MessageDao();
private SimpleTools simpleTools=new SimpleTools();
/**
* 删除选中的留言
* @param actionEvent
*/
public void do_deleteButtom_event(ActionEvent actionEvent) {
//获取到用户输入内容
String id=messageIdField.getText();
String name=messageNameField.getText();
//实例化UserDao对象
MessageDao messageDao=new MessageDao();
//更新结果
int result=0;
//删除
try {
result=messageDao.deleteByIdAndname(Integer.parseInt(id),name);
if(result>0){
//删除成功 清空各文本框并弹出提示框
initialize();
simpleTools.clearTextField(messageIdField,messageNameField,messageTimeField,messageContentField,messageTimeField);
simpleTools.informationDalog(Alert.AlertType.INFORMATION, "提示", "信息", "删除成功");
}
else {
simpleTools.informationDalog(Alert.AlertType.INFORMATION, "提示", "信息", "删除失败");
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
/**
* 初始化界面数据
*/
public void initialize(){
//为各种文本框设置不可编辑
messageIdField.setEditable(false);
messageNameField.setEditable(false);
messageTitleField.setEditable(false);
messageContentField.setEditable(false);
messageTimeField.setEditable(false);
//查询留言
List<Message> messageDataList=null;
try {
messageDataList=messageDao.findTableDataList();
//将数据库数据转换成javafx需要的数据
ObservableList<Message> data=simpleTools.getMessageTableViewData(messageDataList);
//将数据加入到表格中
simpleTools.setMessageTableViewData(MessageTypeManageView,data,messageIdColumn,messageNameColumn,messageTitleColumn,messageContentColumn,messageTimeColumn);
} catch (SQLException throwables) {
throwables.printStackTrace();
}
//为表格控件注册事件监听
MessageTypeManageView.getSelectionModel().selectedItemProperty().addListener(
((observable, oldValue, newValue) -> showMessageDetails(newValue)));
}
/**
* 选中行后将数据显示到下面文本框中
*/
private void showMessageDetails(Message newValue) {
//判断是否选中
if(newValue==null){
return;
} else {
//如果表格行被选中,把数据显示在下面
messageIdField.setText(newValue.getId()+"");
messageNameField.setText(newValue.getName());
messageTitleField.setText(newValue.getTitle());
messageContentField.setText(newValue.getContent());
messageTimeField.setText(newValue.getTime());
}
}
}
在MessageDao中开发初始化方法与删除方法
/**
* 查询所有的留言
* @return
*/
public List<Message> findTableDataList() throws SQLException {
MyDataSource dataSource=new MyDataSource();
QueryRunner runner=new QueryRunner(dataSource);
String sql="select * from message";
return runner.query(sql,new BeanListHandler<Message>(Message.class));
}
/**
* 删除留言
* @param parseInt
* @param name
* @return
*/
public int deleteByIdAndname(int parseInt, String name) throws SQLException{
MyDataSource dataSource=new MyDataSource();
QueryRunner runner=new QueryRunner(dataSource);
String sql="delete from message where id=? and name=?";
int result=runner.update(sql,parseInt,name);
return result;
}
普通用户留言管理与管理员留言管理是有区别的
- 普通用户只可以修改自己的留言
- 如用户被禁用,不可以修改留言
- 我这里自己加一个添加留言的业务
使用Scene Builder开发页面
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.Font?>
<?import javafx.scene.text.Text?>
<?import javafx.geometry.Insets?>
<AnchorPane xmlns="http://javafx.com/javafx"
xmlns:fx="http://javafx.com/fxml"
fx:controller="LeaveMessageSystem.controller.OrdinaryUserMessageManageFrameController"
prefHeight="700.0" prefWidth="800.0">
<children>
<VBox alignment="CENTER" prefHeight="700.0" prefWidth="800.0">
<children>
<HBox alignment="CENTER" prefHeight="100.0" prefWidth="200.0">
<children>
<Label text="普通用户留言管理">
<font>
<Font name="System Bold" size="40.0" />
</font>
</Label>
</children>
</HBox>
<HBox alignment="CENTER" prefHeight="296.0" prefWidth="700.0">
<children>
<TableView fx:id="MessageTypeManageView" prefWidth="705.0" prefHeight="399.0" tableMenuButtonVisible="true">
<columns>
<TableColumn fx:id="messageIdColumn" prefWidth="50.0" text="编号"/>
<TableColumn fx:id="messageNameColumn" minWidth="0.0" prefWidth="100.0" text="用户昵称"/>
<TableColumn fx:id="messageTitleColumn" prefWidth="228.0" text="标题"/>
<TableColumn fx:id="messageContentColumn" prefWidth="220.0" text="内容"/>
<TableColumn fx:id="messageTimeColumn" prefWidth="101.0" text="留言时间"/>
</columns>
</TableView>
</children>
</HBox>
<HBox alignment="CENTER" prefHeight="263.0" prefWidth="700.0">
<children>
<VBox fx:id="formVbox" prefHeight="240.0" prefWidth="702.0">
<children>
<HBox alignment="CENTER_LEFT" prefHeight="100.0" prefWidth="200.0" spacing="10.0">
<children>
<Label text="编号:"/>
<TextField fx:id="messageIdField" prefHeight="30.0" prefWidth="50.0"/>
<Label text="用户昵称:"/>
<TextField fx:id="messageNameField" prefHeight="30.0" prefWidth="150.0"/>
<Label text="留言时间"/>
<TextField fx:id="messageTimeField" prefHeight="30.0" prefWidth="200.0"/>
</children>
<padding>
<Insets left="40.0"/>
<Insets bottom="20.0"/>
</padding>
</HBox>
<HBox prefHeight="100.0" prefWidth="200.0" spacing="10.0">
<children>
<Label text="标题:" />
<TextField fx:id="messageTitleField" prefHeight="30.0" prefWidth="265.0" />
</children>
<padding>
<Insets left="40.0"/>
<Insets bottom="20.0"/>
</padding>
</HBox>
<HBox prefHeight="260.0" prefWidth="500.0" spacing="10.0">
<children>
<Label text="内容:"/>
<TextField fx:id="messageContentField" prefHeight="250.0" prefWidth="400.0"/>
</children>
<padding>
<Insets left="40.0"/>
<Insets bottom="20.0"/>
</padding>
</HBox>
<HBox alignment="CENTER" prefWidth="100.0" prefHeight="200.0" spacing="100.0">
<children>
<Button fx:id="alterButton" mnemonicParsing="false" onAction="#do_alterButtom_event" text="修改"/>
<Button fx:id="deleteButton" mnemonicParsing="false" onAction="#do_deleteButtom_event" text="删除"/>
</children>
<padding>
<Insets left="40.0"/>
</padding>
</HBox>
</children>
</VBox>
</children>
</HBox>
</children>
</VBox>
</children>
</AnchorPane>
效果如下
在controller中新建java文件处理留言管理逻辑
package LeaveMessageSystem.controller;
import LeaveMessageSystem.beans.LoginUser;
import LeaveMessageSystem.beans.Message;
import LeaveMessageSystem.beans.Session;
import LeaveMessageSystem.dao.MessageDao;
import LeaveMessageSystem.tools.SimpleTools;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.scene.control.*;
import javafx.scene.layout.VBox;
import java.sql.SQLException;
import java.util.List;
public class OrdinaryUserMessageManageFrameController {
public TableView<Message> MessageTypeManageView;
public TableColumn<Message,String> messageIdColumn;
public TableColumn<Message,String> messageNameColumn;
public TableColumn<Message,String> messageTitleColumn;
public TableColumn<Message,String> messageContentColumn;
public TableColumn<Message,String> messageTimeColumn;
public VBox formVbox;
public TextField messageIdField;
public TextField messageNameField;
public TextField messageTimeField;
public TextField messageTitleField;
public TextField messageContentField;
public Button deleteButton;
// 实例化MesageDao对象
MessageDao messageDao=new MessageDao();
private SimpleTools simpleTools=new SimpleTools();
LoginUser loginUser= Session.getLoginUser();
//获取到通话对象
String username=loginUser.getUsername();
int roled=loginUser.getRoled();
/**
* 删除选中的留言
* @param actionEvent
*/
public void do_deleteButtom_event(ActionEvent actionEvent) {
//获取到用户输入内容
String id=messageIdField.getText();
String name=messageNameField.getText();
if(!name.equals(username)){
simpleTools.informationDalog(Alert.AlertType.INFORMATION, "提示", "重要提示", "您无权删除!");
return;
}
if(roled!=0){
simpleTools.informationDalog(Alert.AlertType.WARNING, "提示", "重要提示", "您已被管理员禁用!");
return;
}
//实例化UserDao对象
MessageDao messageDao=new MessageDao();
//更新结果
int result=0;
//删除
try {
result=messageDao.deleteByIdAndname(Integer.parseInt(id),name);
if(result>0){
//删除成功 清空各文本框并弹出提示框
initialize();
simpleTools.clearTextField(messageIdField,messageNameField,messageTimeField,messageContentField,messageTimeField);
simpleTools.informationDalog(Alert.AlertType.INFORMATION, "提示", "信息", "删除成功");
}
else {
simpleTools.informationDalog(Alert.AlertType.INFORMATION, "提示", "信息", "删除失败");
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
/**
* 初始化界面数据
*/
public void initialize(){
//为各种文本框设置不可编辑
messageIdField.setEditable(false);
messageNameField.setEditable(false);
//查询留言
List<Message> messageDataList=null;
try {
messageDataList=messageDao.findTableDataList();
//将数据库数据转换成javafx需要的数据
ObservableList<Message> data=simpleTools.getMessageTableViewData(messageDataList);
//将数据加入到表格中
simpleTools.setMessageTableViewData(MessageTypeManageView,data,messageIdColumn,messageNameColumn,messageTitleColumn,messageContentColumn,messageTimeColumn);
} catch (SQLException throwables) {
throwables.printStackTrace();
}
//为表格控件注册事件监听
MessageTypeManageView.getSelectionModel().selectedItemProperty().addListener(
((observable, oldValue, newValue) -> showMessageDetails(newValue)));
}
/**
* 选中行后将数据显示到下面文本框中
*/
private void showMessageDetails(Message newValue) {
//判断是否选中
if(newValue==null){
return;
} else {
//如果表格行被选中,把数据显示在下面
messageIdField.setText(newValue.getId()+"");
messageNameField.setText(newValue.getName());
messageTitleField.setText(newValue.getTitle());
messageContentField.setText(newValue.getContent());
messageTimeField.setText(newValue.getTime());
}
}
/**
* 修改
* @param actionEvent
*/
public void do_alterButtom_event(ActionEvent actionEvent) {
//获取到用户输入
String id=messageIdField.getText();
String name=messageNameField.getText();
String time=messageTimeField.getText();
String title=messageTitleField.getText();
String content=messageContentField.getText();
if(!name.equals(username)){
simpleTools.informationDalog(Alert.AlertType.WARNING, "提示", "重要提示", "您无权修改!");
return;
}
if(roled!=0){
simpleTools.informationDalog(Alert.AlertType.WARNING, "提示", "重要提示", "您已被管理员禁用!");
return;
}
if(title==null||title.equals("")||time==null||time.equals("")||content==null||content.equals("")){
simpleTools.informationDalog(Alert.AlertType.WARNING, "提示", "警告", "修改不可为空!");
return;
}
//修改结果
int result=0;
//修改
try {
result=messageDao.updateById(Integer.parseInt(id),time,title,content);
if(result>0){
//删除成功 清空各文本框并弹出提示框
initialize();
simpleTools.clearTextField(messageIdField,messageNameField,messageTimeField,messageContentField,messageTimeField);
simpleTools.informationDalog(Alert.AlertType.INFORMATION, "提示", "成功", "修改成功!");
}
else {
simpleTools.informationDalog(Alert.AlertType.ERROR, "提示", "失败", "修改失败!");
}
} catch (SQLException throwables) {
throwables.printStackTrace();
simpleTools.informationDalog(Alert.AlertType.ERROR, "提示", "失败", "修改失败!");
}
}
}
这里就用到了登录时保存的session,我们在普通用户修改或者删除留言之前,要对用户的状态进行核实。
if(!name.equals(username)){
simpleTools.informationDalog(Alert.AlertType.INFORMATION, "提示", "重要提示", "您无权删除!");
return;
}
if(roled!=0){
simpleTools.informationDalog(Alert.AlertType.WARNING, "提示", "重要提示", "您已被管理员禁用!");
return;
}
在MessageDao中开发相应方法
/**
* 修改留言
* @param parseInt
* @param time
* @param title
* @param content
* @return
*/
public int updateById(int parseInt, String time, String title, String content) throws SQLException{
MyDataSource dataSource=new MyDataSource();
QueryRunner runner=new QueryRunner(dataSource);
String sql = "update message set title=?,content=?,time=? where id=?";
int result=runner.update(sql,title,content,time,parseInt);
return result;
}
留言的添加业务
使用Scene Builder开发页面
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane prefHeight="750.0" prefWidth="800.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1"
fx:controller="LeaveMessageSystem.controller.AddMessageFrameController">
<children>
<VBox alignment="CENTER" focusTraversable="true" layoutX="137.0" prefHeight="400.0" prefWidth="326.0"
spacing="20.0">
<children>
<HBox alignment="CENTER" prefHeight="100.0" prefWidth="200.0">
<children>
<Label fx:id="descriptionLabel" text="留言添加"/>
</children>
</HBox>
<HBox alignment="CENTER_LEFT" prefHeight="100.0" prefWidth="200.0">
<children>
<Label text="标题:"/>
<TextField fx:id="titleTextField" prefHeight="30.0" prefWidth="240.0" promptText="请填入标题:"/>
</children>
</HBox>
<HBox alignment="CENTER_LEFT" prefHeight="100.0" prefWidth="200.0">
<children>
<Label text="内容:"/>
<TextArea fx:id="contentTextField" prefHeight="200.0" prefWidth="240.0" promptText="请填入留言内容:"/>
</children>
</HBox>
<HBox alignment="CENTER_LEFT" prefHeight="100.0" prefWidth="200.0">
<children>
<Label text="日期:"/>
<DatePicker fx:id="datePickerTextField" prefHeight="30.0" prefWidth="240.0"
promptText="请选择日期:"/>
</children>
</HBox>
<HBox alignment="CENTER" prefHeight="100.0" prefWidth="200.0" spacing="80.0">
<children>
<Button fx:id="addButton" mnemonicParsing="false" onAction="#addButtonEvent" text="添加"/>
<Button fx:id="resetButton" mnemonicParsing="false" onAction="#resetButtonEvent" text="重置"/>
</children>
</HBox>
</children>
<opaqueInsets>
<Insets/>
</opaqueInsets>
<padding>
<Insets bottom="20.0"/>
</padding>
</VBox>
</children>
</AnchorPane>
效果如下
在controller中新建java文件处理逻辑
package LeaveMessageSystem.controller;
import LeaveMessageSystem.beans.LoginUser;
import LeaveMessageSystem.beans.Message;
import LeaveMessageSystem.beans.Session;
import LeaveMessageSystem.dao.MessageDao;
import LeaveMessageSystem.tools.SimpleTools;
import javafx.event.ActionEvent;
import javafx.scene.control.*;
import java.sql.SQLException;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
public class AddMessageFrameController {
public Label descriptionLabel;
public TextField titleTextField;
public TextArea contentTextField;
public DatePicker datePickerTextField;
public Button addButton;
public Button resetButton;
// 实例化MesageDao对象
MessageDao messageDao=new MessageDao();
private SimpleTools simpleTools=new SimpleTools();
LoginUser loginUser= Session.getLoginUser();
//获取到通话对象
String username=loginUser.getUsername();
int status= loginUser.getStatus();
/**
* 添加
* @param actionEvent
*/
public void addButtonEvent(ActionEvent actionEvent) {
if(status==1){
simpleTools.informationDalog(Alert.AlertType.INFORMATION, "提示", "信息", "您的账号尚未被管理员激活");
return;
}
//标题
String title=titleTextField.getText();
//内容
String content=contentTextField.getText();
// 日期
String date = datePickerTextField.getValue().toString();
if(title==null||title.equals("")||content==null||content.equals("")||date==null||date.equals("")){
simpleTools.informationDalog(Alert.AlertType.WARNING, "提示", "信息", "留言不可为空");
}
//实例化Message
Message message=new Message();
//封装
message.setName(username);
message.setTitle(title);
message.setContent(content);
message.setTime(date);
//添加结果
int result=0;
try {
result=messageDao.addMessage(message);
if(result>0){
simpleTools.informationDalog(Alert.AlertType.INFORMATION, "提示", "信息", "留言成功");
}
else {
simpleTools.informationDalog(Alert.AlertType.ERROR, "提示", "失败", "留言失败");
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
/**
* 重置
* @param actionEvent
*/
public void resetButtonEvent(ActionEvent actionEvent) {
titleTextField.setText("");
contentTextField.setText("");
//String转localdate
// String date="";
// DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd");
// LocalDate date2 = LocalDate.parse(date, fmt);
}
}
在MessageDao中开发添加留言记录<方法/font>
/**
* 添加留言
* @param message
* @return
*/
public int addMessage(Message message) throws SQLException{
MyDataSource dataSource=new MyDataSource();
QueryRunner runner=new QueryRunner(dataSource);
String sql="insert into message values(?,?,?,?,?)";
int r= runner.update(sql,null,message.getName(),message.getTitle(),message.getContent(),message.getTime());
return r;
}
代码已经放入GitHub,需要的同学自取。别忘了给一个star!!!