阳江市网站建设_网站建设公司_移动端适配_seo优化
2025/12/19 20:04:13 网站建设 项目流程

设计目标

  • 即时通讯体验:实现类似微信的桌面即时通讯客户端与配套服务端,支持账号注册、登录、添加好友、单聊及离线消息等基础 IM 功能。
  • 良好用户体验:基于 Qt 自绘 UI,提供无边框窗口、阴影、圆角、拖拽移动窗口、平滑滚动条、点击动画、侧边栏按钮反馈等,使桌面端界面更现代、美观。
  • 稳定可靠的连接:客户端通过 QTcpSocket 与服务器通信,支持自动重连、心跳检测、错误信息提示、断线恢复等,保证在普通网络条件下的稳定性。
  • 可维护的数据管理:服务端以 JSON 文件持久化用户数据(账号、密码、联系人、聊天记录、好友申请、离线消息等),简化部署的同时便于调试和扩展。
  • 可扩展的架构:客户端和服务端都采用模块化设计(网络层 / UI 层、ServerManager / ClientManager / MessageHandler / HeartbeatMonitor 等),为后续扩展群聊、文件/图片消息、更多资料字段等功能预留空间。

功能描述

客户端(wechat

  • 账号注册

    • 通过 registerwindow 完成账号注册,校验账号、密码长度与两次输入一致性,强制勾选隐私政策。
    • 注册成功后,将昵称等基本资料写入本地 userdata/profile/<username>.json,并通过信号告知登录界面自动回填账号密码。
  • 登录与会话管理

    • LoginWindow 负责登录界面展示与交互,校验用户名/密码、用户协议勾选状态。
    • 在需要时自动连接到服务端(默认 localhost:8888),显示连接状态和错误信息。
    • 登录流程中带有“至少等待一定时间”的加载逻辑,避免瞬间闪过造成体验生硬。
    • 登录成功后通过信号通知 main.cpp,隐藏登录窗口并打开 chatwindow
  • 网络通信与会话恢复

    • NetworkManager 负责所有与服务端的 TCP 通信与 JSON 协议封装。
    • 支持:
      • 连接 / 断开服务器、错误处理。
      • 登录 / 注册请求与结果反馈。
      • 获取联系人列表、添加/删除联系人。
      • 好友申请的发送、接受/拒绝、列表获取。
      • 单聊消息发送、聊天记录获取。
      • 离线消息接收。
      • 资料更新广播(昵称等)。
    • 实现自动重连机制(指数退避、最大重连次数),在网络中断后尽量恢复连接并自动重新登录。
    • 所有消息以一行一条 JSON 的形式通过 \n 分隔,便于流式处理。
  • 主聊天界面与联系人管理

    • chatwindow 为主工作界面,包含:
      • 左侧联系人列表(自定义 contactwidget,呈现头像、昵称、最后一条消息、时间与未读数)。
      • 右侧消息列表(发送气泡 sendwidget、接收气泡 recvwidget)。
      • 底部输入框与发送按钮,支持 Enter 发送、Shift+Enter 换行。
      • 侧边工具栏(头像按钮、聊天/通讯录/设置等图标按钮),带有点击动画与高亮状态。
    • 支持:
      • 添加好友(通过 AddContactDialog 发送好友申请)。
      • 接收好友申请与红点提醒(FriendRequestDialog + badge)。
      • 查看联系人资料、删除联系人、删除本地聊天记录。
      • 本地头像管理与圆角裁剪显示(侧边栏头像、联系人头像、消息气泡头像)。
      • 根据本地 profile 与服务器昵称组合确定显示名。
    • 对滚动条、布局进行了大量细节优化(按像素滚动、自动隐藏滚动条、最大化/还原后强制刷新布局)以保证消息列表在各种尺寸下表现正常。
  • UI/交互优化

    • 所有主要窗口(MainWindowLoginWindowregisterwindowchatwindow)均采用无边框 + 透明背景 + 自定义拖拽逻辑。
    • 使用 QPropertyAnimationcontactwidget 点击提供缩放动画,强化交互反馈。
    • 通过事件过滤器、拖拽事件(拖入图片/文件时给出提示)等提升易用性。

服务端(wechat_server

  • 服务启动/停止与状态监控

    • MainWindow 提供服务端 GUI:
      • 设置监听端口、启动/停止服务器。
      • 显示在线客户端列表与在线人数。
      • 实时显示日志(颜色区分 INFO/WARNING/ERROR),支持清空。
      • 广播消息发送(服务端向所有在线客户端发送系统消息)。
      • 通过自定义无边框窗口实现拖拽、最小化/最大化/关闭等逻辑。
  • 连接与会话管理

    • ServerManager
      • 内部持有 QTcpServer,统一管理监听端口和新连接。
      • 管理 ClientManagerMessageHandlerHeartbeatMonitor 三大核心模块。
      • 处理新客户端连接/断开、维护 socket 缓冲区,并将带换行的 JSON 消息分包交给 MessageHandler
      • 负责启动/停止心跳检测及资源清理。
  • 客户端与用户数据管理

    • ClientManager
      • 管理在线客户端(ClientInfo):用户名、socket、IP、端口、登录时间、最后心跳时间、在线状态。
      • 管理持久化的用户数据(UserData):用户名、密码、昵称、注册时间、联系人列表、聊天记录、好友申请、离线消息、每个联系人的最后一条消息等。
      • 用户数据以 JSON 文件形式存储于 userdata/<username>.json
      • 功能包括:
        • 用户注册 / 登录验证。
        • 联系人增删与双向同步。
        • 聊天记录保存与裁剪(限制最大条数)。
        • 离线消息队列管理与清空。
        • 好友申请增删查、状态流转(pending/accepted/rejected)。
        • 资料更新(昵称)与统计信息(聊天记录数量、未处理好友申请数量等)。
        • 管理员操作:删除用户、清空聊天记录、修改密码等。
  • 消息分发与业务协议

    • MessageHandler 负责解析并处理所有来自客户端的 JSON 消息:
      • 登录 login:校验账号、密码;调用 ClientManager::addClient 维护在线表;返回联系人列表,并推送用户的离线消息;广播 userOnline 事件。
      • 注册 register:创建用户数据文件;校验用户名重复与昵称非空等。
      • 单聊消息 message
        • 保存发送方的聊天记录。
        • 接收方在线:即时推送 + 保存接收方聊天记录。
        • 接收方离线:写入离线消息 + 保存接收方聊天记录。
      • 心跳 heartbeat:更新最后心跳时间并回复心跳确认。
      • 获取联系人 getContacts:将联系人用户名、昵称、在线状态及最后一条消息封装为数组返回。
      • 获取聊天记录 getChatHistory:返回指定会话的全部历史消息。
      • 添加/删除联系人 addContact / removeContact:更新双方联系人列表,同时在删除时向对方推送 contactRemoved 通知。
      • 好友申请相关friendRequestacceptFriendRequestrejectFriendRequestgetFriendRequests,涵盖申请记录、互加好友、自动发送系统消息 “我通过了你的朋友验证请求,现在我们可以开始聊天了”、离线/在线通知等。
      • 更新资料 updateProfile:更新服务器端昵称并将 profileUpdated 广播给所有在线客户端。
      • 测试/帮助消息:处理简单 test/ping/测试 文本命令及错误 JSON 时的帮助提示。
  • 心跳与超时管理

    • HeartbeatMonitor(通过 ServerManager 持有)周期性检查每个客户端的最后心跳时间。
    • 当客户端超过设定超时时间未发送心跳时,触发超时信号并断开该连接,确保长时间无响应连接被清理。
  • 日志与用户管理 UI

    • Logger:单例日志模块,统一记录 Info/Warning/Error 日志,并向主界面发送信号以在文本框中展示。
    • UserManagerDialog
      • 可视化展示所有注册用户。
      • 显示昵称、注册时间、在线状态、联系人数量、聊天记录数量等信息。
      • 支持管理员删除用户、清空用户聊天记录、修改用户密码。

设计方案

通信与协议设计

  • 传输层:基于 QTcpSocket/QTcpServer 的长期 TCP 连接,适合实时消息推送。
  • 应用层协议
    • 消息体为 UTF-8 编码 JSON 文本,每条消息一行,以 \n 为分隔符。
    • 统一以 type 字段区分消息类型,部分消息还包含 successmessagedata 等字段。
    • 这种设计利于调试(可直接查看原始 JSON)和扩展(新增 type 即可)。

客户端整体设计

  • 单一 NetworkManager 实例共享:在 main.cpp 中创建 NetworkManager,并传入登录窗、注册窗、聊天窗构造函数,使所有 UI 层统一复用同一网络连接与状态。
  • UI 与业务解耦
    • UI 层(多个 QWidget+QDialog)只关心信号/槽接口,如 loginSuccesscontactsUpdatedchatMessageReceived 等。
    • 具体网络细节(重连、解析 JSON 等)完全封装在 NetworkManager 中。
  • 本地缓存与远端数据混合使用
    • 本地 userdata/profile 储存昵称、省份、头像等与服务器端 JSON 用户数据互为补充。
    • chatwindow 在绘制联系人列表时,优先使用本地 profile 的昵称,其次服务器返回的昵称,最后使用账号名。

服务端整体设计

  • 核心三层模块
    • ServerManager:对外提供“启动/停止服务器”的统一接口,同时持有其他核心组件。
    • ClientManager:负责“谁在线”和“用户是什么样”的问题;既维护在线客户端,又管理落盘用户数据。
    • MessageHandler:负责“收到消息要做什么”的问题;将所有业务逻辑放在一个集中位置,易于维护协议演进。
  • 数据持久化方案
    • 每个用户一个 JSON 文件,字段包含账号、密码、昵称、注册时间、联系人列表、聊天记录、好友申请、离线消息、与各联系人的最后一条消息。
    • 通过批量加载 + QApplication::processEvents 防止一次性读取过多文件卡顿 UI。
  • 管理员界面
    • 借助 UserManagerDialog 提供最基础的运维功能,简化调试与测试。

系统框架

客户端模块划分

  • 入口与窗口切换

    • main.cpp:创建 QApplicationNetworkManagerLoginWindowregisterwindowchatwindow,并通过 3D 翻转动画实现登录/注册切换。
  • 网络层

    • NetworkManager
      • 维护 QTcpSocket 与断线重连定时器。
      • 暴露高层接口:login / registerUser / fetchContacts / sendChatMessage / requestFriend / updateProfile 等。
      • 通过 handleMessage 将 JSON 消息映射到 Qt 信号,供 UI 层订阅。
  • 登录注册层

    • LoginWindow
      • 负责登录表单、错误提示、与服务器连接状态显示。
      • 触发 openRegisterRequestedloginSuccess 等信号。
    • registerwindow
      • 实现注册表单校验、注册逻辑、注册成功后本地 profile 写入、返回登录界面等。
  • 聊天与联系人管理

    • chatwindow
      • 管理联系人内存结构(ChatContact + QMap/QHash),以及对应的 contactwidget 实例映射。
      • 负责聊天消息列表、输入框交互、联系人右键菜单(查看资料 / 删除联系人 / 删除聊天记录)。
      • 管理好友申请红点、侧边栏按钮动画、窗口状态切换下的布局刷新的细节。
    • contactwidget / sendwidget / recvwidget
      • 以自定义控件形式封装单个联系人条目和单条消息气泡,统一控制样式与动画。
  • 资料与对话框

    • ProfileDialog:编辑个人资料(昵称、省份、头像),并与 NetworkManager 协作,将修改同步到服务器和联系人列表。
    • FriendRequestDialog:展示待处理好友申请列表,触发“接受/拒绝”操作。
    • AddContactDialog:输入好友账号,触发 requestFriend

服务端模块划分

  • 入口与主界面

    • main.cpp:创建 QApplication,显示服务端 MainWindow
    • MainWindow:负责服务控制 UI、日志显示、在线客户端列表、广播消息、用户管理入口等。
  • 连接与业务逻辑核心

    • ServerManager
      • 管理 QTcpServer 与新连接。
      • 持有 ClientManagerMessageHandlerHeartbeatMonitor
      • 内部维护每个 socket 的读缓冲区,负责基于行的消息拆包。
    • ClientManager
      • 维护在线客户端映射(username -> ClientInfo),以及所有用户持久化数据(username -> UserData)。
      • 提供一系列用于 MessageHandler 的业务方法(注册、登录验证、联系人管理、聊天记录和离线消息管理、好友申请状态管理等)。
    • MessageHandler
      • 将所有 JSON 消息按 type 分派到对应处理函数。
      • 在内部调用 ClientManager 的接口、通过 sendMessage 给客户端回复或广播。
    • HeartbeatMonitor
      • 周期性检查 ClientInfo::lastHeartbeat,对超时客户端断连。
  • 日志与管理员工具

    • Logger:集中记录运行时事件,并通过信号连接到 MainWindow 的日志文本框。
    • UserManagerDialog:管理员级别操作界面,操作 ClientManager 中的数据。

实现过程概要

  1. 基础通信与简单 UI

    • 首先搭建 Qt 客户端和服务端工程,完成 TCP 连接测试(如 test/ping 命令)。
    • 实现最小可用的登录/注册流程与基础聊天功能。
  2. 联系人与聊天记录管理

    • 在服务端引入 ClientManager,将用户数据以 JSON 文件落盘。
    • 按用户名维度维护联系人列表与聊天记录,客户端则实现联系人列表 UI 与聊天窗口。
  3. 完善协议与用户体验

    • 扩展 JSON 协议:添加 getContactsgetChatHistoryaddContactremoveContact 等类型。
    • 在客户端实现 NetworkManager::handleMessage 中对各类消息的解析与 UI 信号派发。
    • 调整 UI:无边框窗口、拖拽、圆角、阴影、按钮样式等。
  4. 好友申请与资料系统

    • 设计并实现好友申请流程(发送、接受、拒绝、查询),在服务端记录 friendRequests
    • 客户端增加好友申请对话框、红点提醒,服务端通过广播/推送消息同步状态。
    • 引入 ProfileDialog 与本地 profile/头像文件,增强个人与联系人显示效果。
  5. 稳定性与运维能力提升

    • 客户端增加断线自动重连与登录状态恢复逻辑;服务端增加 HeartbeatMonitor
    • 引入统一 Logger 以及颜色区分日志级别,便于问题排查。
    • 增加 UserManagerDialog,以 GUI 形式管理用户与聊天记录,辅助测试与维护。

心得体会与改进思考

  • 1)Qt 在桌面 IM 客户端中的优势

    • 借助 Qt 丰富的 UI 控件与信号/槽机制,可以较容易构建出跨平台的 IM 客户端界面。
    • 通过自绘与样式表,能做出比较接近原生微信的窗口风格(无边框、圆角、阴影、侧边栏图标等),提升用户观感。
  • 2)前后端协议清晰是演进的关键

    • 使用 JSON + type 字段的协议设计,结构清晰、易于调试,后续功能扩展(比如群聊、文件消息、@提醒)只需增加新的 type 与字段。
    • 客户端 NetworkManager 与服务端 MessageHandler 分别承担“协议封装/解析”,使 UI 与数据层关系自然清晰。
  • 3)长连接与可靠性的实践

    • 在客户端加入自动重连、心跳响应、错误文案提示,使得在不稳定网络下体验更平滑。
    • 服务端通过 HeartbeatMonitor 清理超时连接,并在 ServerManager 中谨慎处理 socket 状态、缓冲区与异常情况,有利于线上稳定性。
  • 4)文件型持久化的利与弊

    • 单用户单 JSON 文件的方式非常适合教学与个人项目:部署简单、可直接查看和编辑用户数据。
    • 当用户量或消息量增大时,JSON 读写与锁粒度需要进一步优化,甚至迁移到数据库(如 SQLite/MySQL)更合理。
  • 5)用户体验细节的重要性

    • 在登录/注册中加入“最少等待时间”、友好错误提示、勾选协议校验,使流程看起来更专业。
    • 对滚动条按像素滚动、自动隐藏、窗口大小变化时强制刷新布局等细节处理,让界面在多种分辨率下更自然。
    • 点击动画、按钮 hover/pressed 状态等微交互,对整体观感提升很大。
  • 6)后续可改进与扩展方向

    • 安全性:目前密码以明文存储在 JSON 中,后续应改为哈希(如 PBKDF2/bcrypt)并考虑 TLS 加密传输。
    • 消息类型扩展:图片/文件消息目前已有拖拽与剪贴板检测的基础,可以在协议层增加对应字段并在服务端做文件转发或 URL 分发。
    • 多终端同步:当前离线消息与资料更新已具备基本能力,可进一步扩展为多终端同时在线的状态同步策略。
    • 性能与架构升级:在用户规模增大时,引入数据库、分层服务(认证/消息/推送)甚至拆分为微服务,都有清晰的演进路径。

UI界面展示

登录界面

登录界面

注册界面

注册界面

聊天界面

聊天界面
聊天界面
聊天界面
聊天界面
聊天界面

服务端界面

服务端界面
服务端界面
服务端界面

一些细节控件的问题解决:

实现只在滚动时出现滚动条:
QSS 只能控制长什么样,不能“何时显示/隐藏”。
“滚动时显示,停一会儿自动隐藏”需要用代码配合:监听滚动条变化 → 显示滚动条 → 用 QTimer 延时再隐藏。
下面给你一个针对 contactList_2 的完整实现步骤。

  1. 头文件中新增成员和槽函数
    在 chatwindow.h 里:
#include <QTimer>#include <QScrollBar>

在 class chatwindow 里(public: / private: 区域补充):

private:    Ui::chatwindow *ui;    QTimer *m_scrollbarTimer;   // 控制滚动条自动隐藏的定时器private slots:    void onMessageListScrolled(int value);  // 滚动时触发    void hideMessageScrollbar();            // 超时隐藏滚动条
  1. 构造函数里初始化、连接信号
    在 chatwindow 构造函数中(ui->setupUi(this); 之后)加:
    // 1. 初始化定时器(比如 800ms 不再滚动就隐藏)
m_scrollbarTimer = new QTimer(this);m_scrollbarTimer->setInterval(800);m_scrollbarTimer->setSingleShot(true);// 2. 初始时先隐藏滚动条ui->contactList_2->verticalScrollBar()->hide();// 3. 监听滚动条的 valueChanged 信号(无论滚轮、拖动、代码滚动都会触发)connect(ui->contactList_2->verticalScrollBar(), &QScrollBar::valueChanged,        this, &chatwindow::onMessageListScrolled);// 4. 定时器超时后隐藏滚动条connect(m_scrollbarTimer, &QTimer::timeout,        this, &chatwindow::hideMessageScrollbar);
  1. 槽函数实现
    在 chatwindow.cpp 里实现这两个槽:
// 滚动发生时:显示滚动条,并重置计时器void chatwindow::onMessageListScrolled(int){    QScrollBar *sb = ui->contactList_2->verticalScrollBar();    if (!sb->isVisible()) {        sb->show();          // 滚动时让滑块出现    }    // 只要还在滚动,就不断重置计时器    m_scrollbarTimer->start();}// 一段时间没有滚动:隐藏滚动条void chatwindow::hideMessageScrollbar(){    ui->contactList_2->verticalScrollBar()->hide();}

解决窗口条目宽度每一行的 QListWidgetItem 宽度等于 contactList 的视口宽度

image

contactwidget *contwidget = new contactwidget;// 当前 contactList 可用的内容宽度(不含滚动条)
int rowWidth = ui->contactList->viewport()->width();// 把条目宽度设成“等于视口宽度”,高度用 contactwidget 自己的 height
tmpItem->setSizeHint(QSize(rowWidth, contwidget->sizeHint().height()));ui->contactList->setItemWidget(tmpItem, contwidget);

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询