|
@@ -0,0 +1,228 @@
|
|
|
|
|
+package space.anyi.chatServer.ui.controller;
|
|
|
|
|
+
|
|
|
|
|
+import com.sun.source.tree.IfTree;
|
|
|
|
|
+import javafx.application.Platform;
|
|
|
|
|
+import javafx.collections.ObservableList;
|
|
|
|
|
+import javafx.fxml.FXML;
|
|
|
|
|
+import javafx.geometry.Pos;
|
|
|
|
|
+import javafx.scene.control.*;
|
|
|
|
|
+import javafx.scene.input.MouseEvent;
|
|
|
|
|
+import javafx.scene.layout.HBox;
|
|
|
|
|
+import javafx.scene.layout.VBox;
|
|
|
|
|
+import javafx.scene.paint.Paint;
|
|
|
|
|
+import javafx.stage.Stage;
|
|
|
|
|
+import javafx.util.Callback;
|
|
|
|
|
+import lombok.Data;
|
|
|
|
|
+import space.anyi.chatCommom.Message;
|
|
|
|
|
+import space.anyi.chatServer.ChatServer;
|
|
|
|
|
+
|
|
|
|
|
+import java.time.Instant;
|
|
|
|
|
+import java.time.LocalDateTime;
|
|
|
|
|
+import java.time.ZoneId;
|
|
|
|
|
+import java.time.ZoneOffset;
|
|
|
|
|
+import java.time.format.DateTimeFormatter;
|
|
|
|
|
+import java.util.Objects;
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * @ProjectName: chat-gwng
|
|
|
|
|
+ * @FileName: ServerController
|
|
|
|
|
+ * @Author: 杨逸
|
|
|
|
|
+ * @Data:2025/9/25 17:56
|
|
|
|
|
+ * @Description:
|
|
|
|
|
+ */
|
|
|
|
|
+@Data
|
|
|
|
|
+public class ServerController {
|
|
|
|
|
+ private ChatServer chatServer;
|
|
|
|
|
+ private Stage stage;
|
|
|
|
|
+ @FXML
|
|
|
|
|
+ private Button bu;
|
|
|
|
|
+
|
|
|
|
|
+ @FXML
|
|
|
|
|
+ private ScrollPane messagePane;
|
|
|
|
|
+
|
|
|
|
|
+ @FXML
|
|
|
|
|
+ private TextArea inputMessage;
|
|
|
|
|
+
|
|
|
|
|
+ @FXML
|
|
|
|
|
+ private Label onlineLabel;
|
|
|
|
|
+
|
|
|
|
|
+ @FXML
|
|
|
|
|
+ private ListView<String> userList;
|
|
|
|
|
+ @FXML
|
|
|
|
|
+ void sendMessage(MouseEvent event) {
|
|
|
|
|
+ //禁用按钮
|
|
|
|
|
+ bu.setDisable(true);
|
|
|
|
|
+ System.out.println("发送消息");
|
|
|
|
|
+ String text = inputMessage.getText();
|
|
|
|
|
+ inputMessage.clear();
|
|
|
|
|
+ text.trim();
|
|
|
|
|
+ if (!"".equals(text)) {
|
|
|
|
|
+ chatServer.broadcast(createMessage(text));
|
|
|
|
|
+ }
|
|
|
|
|
+ bu.setDisable(false);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * @param text
|
|
|
|
|
+ * @return {@code Message }
|
|
|
|
|
+ * @description: 创建消息
|
|
|
|
|
+ * @author: 杨逸
|
|
|
|
|
+ * @data:2025/09/26 17:19:55
|
|
|
|
|
+ * @since 1.0.0
|
|
|
|
|
+ */
|
|
|
|
|
+ private Message createMessage(String text) {
|
|
|
|
|
+ Message message = new Message();
|
|
|
|
|
+ message.setContent(text);
|
|
|
|
|
+ message.setType(Message.MessageType.SYSTEM);
|
|
|
|
|
+ message.setTarget(Message.MessageTarget.CLIENT);
|
|
|
|
|
+ return message;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * @param message
|
|
|
|
|
+ * @description: 向信息列表添加一条信息
|
|
|
|
|
+ * @author: 杨逸
|
|
|
|
|
+ * @data:2025/09/26 17:19:23
|
|
|
|
|
+ * @since 1.0.0
|
|
|
|
|
+ */
|
|
|
|
|
+ public void addMessage(Message message) {
|
|
|
|
|
+ VBox content = (VBox) messagePane.getContent();
|
|
|
|
|
+ VBox msgUI = createMessageUI(message);
|
|
|
|
|
+ Platform.runLater(()->{
|
|
|
|
|
+ content.getChildren().add(msgUI);
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * @param message
|
|
|
|
|
+ * @return {@code VBox }
|
|
|
|
|
+ * @description: 创建一个信息UI
|
|
|
|
|
+ * @author: 杨逸
|
|
|
|
|
+ * @data:2025/09/26 17:22:59
|
|
|
|
|
+ * @since 1.0.0
|
|
|
|
|
+ */
|
|
|
|
|
+ private VBox createMessageUI(Message message) {
|
|
|
|
|
+ VBox result = new VBox();
|
|
|
|
|
+ HBox head = new HBox();
|
|
|
|
|
+ Label username = new Label(message.getSource());
|
|
|
|
|
+ Label mes = new Label(message.getContent());
|
|
|
|
|
+
|
|
|
|
|
+ //右键菜单
|
|
|
|
|
+ //result.setOnContextMenuRequested(event->{
|
|
|
|
|
+ // ContextMenu contextMenu = new ContextMenu();
|
|
|
|
|
+ // MenuItem delete = new MenuItem("删除");
|
|
|
|
|
+ // delete.setOnAction(event1->{
|
|
|
|
|
+ // //删除消息
|
|
|
|
|
+ // VBox content = (VBox) messagePane.getContent();
|
|
|
|
|
+ // content.getChildren().remove(result);
|
|
|
|
|
+ // });
|
|
|
|
|
+ // contextMenu.getItems().add(delete);
|
|
|
|
|
+ // contextMenu.show(result, event.getScreenX(), event.getScreenY());
|
|
|
|
|
+ //});
|
|
|
|
|
+ //内容
|
|
|
|
|
+ Long timeStamp = message.getTimeStamp();
|
|
|
|
|
+ Instant instant = Instant.ofEpochMilli(timeStamp);
|
|
|
|
|
+ LocalDateTime localDateTime = instant.atZone(ZoneId.systemDefault()).toLocalDateTime();
|
|
|
|
|
+ Label time = new Label(localDateTime.format(DateTimeFormatter.ISO_DATE_TIME));
|
|
|
|
|
+
|
|
|
|
|
+ //布局,样式
|
|
|
|
|
+ double width = 400;
|
|
|
|
|
+ double height = 50;
|
|
|
|
|
+ result.setPrefWidth(width);
|
|
|
|
|
+ result.setPrefHeight(height);
|
|
|
|
|
+ result.setStyle("-fx-background-color: #3C3F41;-fx-background-radius: 100;");
|
|
|
|
|
+ head.setPrefWidth(width);
|
|
|
|
|
+ head.setPrefHeight(height-15);
|
|
|
|
|
+ username.setPrefWidth(100);
|
|
|
|
|
+ username.setPrefHeight(height-35);
|
|
|
|
|
+ username.setAlignment(Pos.CENTER);
|
|
|
|
|
+ username.setTextFill(Paint.valueOf("#FFFFFF"));
|
|
|
|
|
+ mes.setPrefWidth(width-100);
|
|
|
|
|
+ mes.setPrefHeight(height-35);
|
|
|
|
|
+ mes.setAlignment(Pos.CENTER_LEFT);
|
|
|
|
|
+ mes.setTextFill(Paint.valueOf("#FFFFFF"));
|
|
|
|
|
+ time.setPrefWidth(width);
|
|
|
|
|
+ time.setPrefHeight(15);
|
|
|
|
|
+ time.setAlignment(Pos.CENTER);
|
|
|
|
|
+ time.setTextFill(Paint.valueOf("#FFFFFF"));
|
|
|
|
|
+ //组装
|
|
|
|
|
+ head.getChildren().add(username);
|
|
|
|
|
+ head.getChildren().add(mes);
|
|
|
|
|
+ result.getChildren().add(head);
|
|
|
|
|
+ result.getChildren().add(time);
|
|
|
|
|
+ return result;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 向用户列表添加用户
|
|
|
|
|
+ * @param username
|
|
|
|
|
+ * @description:
|
|
|
|
|
+ * @author: 杨逸
|
|
|
|
|
+ * @data:2025/09/25 20:11:22
|
|
|
|
|
+ * @since 1.0.0
|
|
|
|
|
+ */
|
|
|
|
|
+ public void addUser(String username){
|
|
|
|
|
+ ObservableList<String> items = userList.getItems();
|
|
|
|
|
+ Platform.runLater(()->{
|
|
|
|
|
+ //UI更新的操作需要在JavaFX线程中
|
|
|
|
|
+ items.add(username);
|
|
|
|
|
+ onlineLabel.setText("在线人数:"+items.size());
|
|
|
|
|
+ });
|
|
|
|
|
+ userList.setCellFactory(new Callback<ListView<String>, ListCell<String>>() {
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public ListCell<String> call(ListView<String> stringListView) {
|
|
|
|
|
+ //创建一个ListView中单元,使用匿名类实现自定义
|
|
|
|
|
+ return new ListCell<>(){
|
|
|
|
|
+ @Override
|
|
|
|
|
+ protected void updateItem(String name, boolean b) {
|
|
|
|
|
+ super.updateItem(name, b);
|
|
|
|
|
+ if (Objects.nonNull(name)) {
|
|
|
|
|
+ setText(name);
|
|
|
|
|
+ }
|
|
|
|
|
+ //给单元格添加右键菜单
|
|
|
|
|
+ setOnContextMenuRequested(event->{
|
|
|
|
|
+ ContextMenu contextMenu = new ContextMenu();
|
|
|
|
|
+ MenuItem item = new MenuItem("下线");
|
|
|
|
|
+ contextMenu.getItems().add(item);
|
|
|
|
|
+ contextMenu.show(this,event.getScreenX(),event.getScreenY());
|
|
|
|
|
+ item.setOnAction(event1->{
|
|
|
|
|
+ //下线提示
|
|
|
|
|
+ Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
|
|
|
|
|
+ alert.setTitle("提示");
|
|
|
|
|
+ alert.setHeaderText("确定要下线该用户吗?");
|
|
|
|
|
+ alert.setContentText("该操作不可逆");
|
|
|
|
|
+ alert.showAndWait().ifPresent(buttonType -> {
|
|
|
|
|
+ if (ButtonType.OK.equals(buttonType)) {
|
|
|
|
|
+ //下线用户
|
|
|
|
|
+ chatServer.logoutUser(name);
|
|
|
|
|
+ //删除用户信息
|
|
|
|
|
+ removeUser(name);
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+ });
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+ };
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 删除用户
|
|
|
|
|
+ * @param username
|
|
|
|
|
+ * @description:
|
|
|
|
|
+ * @author: 杨逸
|
|
|
|
|
+ * @data:2025/09/25 20:12:51
|
|
|
|
|
+ * @since 1.0.0
|
|
|
|
|
+ */
|
|
|
|
|
+ public void removeUser(String username){
|
|
|
|
|
+ ObservableList<String> items = userList.getItems();
|
|
|
|
|
+ if (items.contains(username)){
|
|
|
|
|
+ Platform.runLater((()->{
|
|
|
|
|
+ items.remove(username);
|
|
|
|
|
+ onlineLabel.setText("在线人数:"+items.size());
|
|
|
|
|
+ }));
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|