提交之GitHub

This commit is contained in:
2026-02-08 23:58:00 +08:00
commit b4f25e99b1
43 changed files with 7926 additions and 0 deletions
+214
View File
@@ -0,0 +1,214 @@
package client.view.main;
import client.service.LocalData;
import client.view.MainPage;
import client.view.util.CircleCharIcon2;
import client.view.util.DesignToken;
import client.view.util.RoundedRectCharIcon;
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
// 群聊列表项组件
public class GroupListItem extends JPanel implements Comparable<String> {
private int unread;
private final String groupId;
JLabel icon;
JLabel badge;
JPanel centerPanel;
JLabel titleLabel;
JPanel rightPanel; // 用于放置徽章
/**
* 构造函数
*
* @param groupId 群聊ID
* @param title 群聊标题
* @param unread 未读消息数量
*/
public GroupListItem(String groupId, String title, int unread) {
this.groupId = groupId;
this.unread = unread;
// 设置布局管理器
setLayout(new BorderLayout(10, 0));
setBorder(BorderFactory.createEmptyBorder(8, 10, 8, 10));
setMaximumSize(new Dimension(Integer.MAX_VALUE, 70));
setPreferredSize(new Dimension(200, 70));
// 左侧图标
boolean isGroup = LocalData.get().getGroupData(groupId) != null;
if (isGroup) {
icon = new JLabel(new RoundedRectCharIcon(Color.decode(DesignToken.BUBBLE_COLOR_BLUE), Color.WHITE,
title.substring(0, 1).toUpperCase(), 40));
} else {
icon = new JLabel(new CircleCharIcon2(Color.ORANGE, Color.WHITE,
title.substring(0, 1).toUpperCase(), 40));
}
icon.setPreferredSize(new Dimension(40, 40));
// 中间区域 - 群聊标题
centerPanel = new JPanel(new GridLayout(1, 1));
titleLabel = new JLabel(title);
titleLabel.setFont(new Font(DesignToken.DEFAULT_FONT, Font.BOLD, 14));
centerPanel.add(titleLabel);
// 右侧区域 - 未读消息徽章
rightPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT, 0, 0));
rightPanel.setOpaque(false);
badge = new JLabel();
badge.setForeground(Color.WHITE);
badge.setBackground(Color.RED);
badge.setOpaque(true);
badge.setHorizontalAlignment(SwingConstants.CENTER);
badge.setFont(new Font("Microsoft YaHei", Font.BOLD, 10));
badge.setBorder(BorderFactory.createEmptyBorder(2, 6, 2, 6));
badge.setPreferredSize(new Dimension(20, 20));
updateBadge(); // 初始化徽章显示状态
rightPanel.add(badge);
// 组装
this.add(icon, BorderLayout.WEST);
this.add(centerPanel, BorderLayout.CENTER);
this.add(rightPanel, BorderLayout.EAST);
addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
enterGroup();
}
@Override
public void mouseEntered(MouseEvent e) {
setBackground(new Color(240, 240, 240)); // 悬停效果
}
@Override
public void mouseExited(MouseEvent e) {
setBackground(UIManager.getColor("Panel.background")); // 恢复原背景
}
@Override
public void mousePressed(MouseEvent e) {
setBackground(new Color(220, 220, 220)); // 点击效果
}
@Override
public void mouseReleased(MouseEvent e) {
if (contains(e.getPoint())) {
setBackground(new Color(240, 240, 240));
} else {
setBackground(UIManager.getColor("Panel.background"));
}
}
});
}
/**
* 更新徽章显示
*/
private void updateBadge() {
if (unread > 0) {
String badgeText = unread > 99 ? "99+" : String.valueOf(unread);
badge.setText(badgeText);
badge.setVisible(true);
// 根据文本长度调整徽章大小
FontMetrics fm = badge.getFontMetrics(badge.getFont());
int width = fm.stringWidth(badgeText) + 12;
badge.setPreferredSize(new Dimension(width, 20));
} else {
badge.setVisible(false);
}
}
/**
* 更新组件
* 将组件上对应的信息修改。
* newUnread 是加在原有的unread上的
*/
public void updateUI(String name, int newUnread) {
titleLabel.setText(name);
// 更新图标的首字母显示
boolean isGroup = LocalData.get().getGroupData(groupId) != null;
if (isGroup) {
icon.setIcon(new RoundedRectCharIcon(Color.decode(DesignToken.BUBBLE_COLOR_BLUE), Color.WHITE,
name.substring(0, 1).toUpperCase(), 40));
} else {
icon.setIcon(new CircleCharIcon2(Color.ORANGE, Color.WHITE,
name.substring(0, 1).toUpperCase(), 40));
}
unread += newUnread;
updateBadge();
}
/**
* 点击事件
* 当点击之后,使用UIUpdater来更新ContentView的UI
* 使得其加载新的群聊信息
* 清空unread为0
* UIUpdater在ContentView展示当前群聊信息的时候不会更新这个群聊的未读信息数量。
*/
public void enterGroup() {
unread = 0;
LocalData.get().setCurrentChatId(groupId);
updateBadge(); // 更新徽章显示
String name;
if (LocalData.get().getFriends().containsKey(groupId)) {
name = LocalData.get().getFriends().get(groupId);
} else {
name = LocalData.get().getGroupName(groupId);
}
updateUI(name, 0);
MainPage.get().exchangeToChatRoom(groupId);
if (LocalData.get().getGroupData(groupId) != null) {
System.out.println(
"进入群聊:" + groupId +
",人数:" + LocalData.get().getGroupData(groupId).getMemberCount() +
", 信息数量: " + LocalData.get().getChatMsg(groupId).size());
} else {
System.out.println("进入私聊:" + groupId);
}
MainPage.get().revalidate(); // 重新计算布局
MainPage.get().repaint();
}
/**
* 获取未读消息数量
*/
public int getUnread() {
return unread;
}
/**
* 获取群组ID
*/
public String getGroupId() {
return groupId;
}
/**
* 实现Comparable接口,用于排序
* 按照群组ID进行排序
*
* @param o 要比较的对象
* @return 比较结果
*/
@Override
public int compareTo(String o) {
return this.groupId.compareTo(o);
}
}