C2CSetting State
介绍
C2CSettingState
是一个与个人设置相关的状态管理中心,专门用于管理 1v1(C2C)聊天设置的状态和操作。它提供了用户信息管理、聊天设置控制、好友关系查询等功能,是构建一对一聊天设置界面的核心工具。C2CSettingState
能够自动监听当前会话的变化,当进入 C2C 会话时自动获取对方用户信息和聊天设置,并提供便捷的操作方法来修改置顶、免打扰、备注等设置。属性列表
字段 | 类型 | 描述 |
userID | string | undefined | 对方用户的 ID |
nick | string | undefined | 对方用户的昵称 |
avatar | string | undefined | 对方用户的头像 URL |
signature | string | undefined | 对方用户的个性签名 |
remark | string | undefined | 对方用户的备注名称 |
isMuted | boolean | undefined | 是否设置为免打扰 |
isPinned | boolean | undefined | 是否置顶聊天 |
isContact | boolean | undefined | 是否为好友关系 |
setChatPinned | (value: boolean) => void | 设置聊天置顶状态的方法 |
setChatMuted | (value: boolean) => void | 设置免打扰状态的方法 |
setUserRemark | (remark: string) => void | 设置用户备注的方法 |
属性详情
userID
类型:
string | undefined
描述: 当前 C2C 会话中对方用户的唯一标识符。当没有 C2C 会话或正在加载时,该值为
undefined
。nick
类型:
string | undefined
描述: 对方用户的昵称。如果用户没有设置昵称或信息尚未加载,该值为
undefined
。avatar
类型:
string | undefined
描述: 对方用户的头像图片 URL。用于显示用户头像,如果用户没有设置头像或信息尚未加载,该值为
undefined
。signature
类型:
string | undefined
描述: 对方用户的个性签名。展示用户的个人状态或心情,如果用户没有设置签名或信息尚未加载,该值为
undefined
。remark
类型:
string | undefined
描述: 当前用户为对方设置的备注名称。备注名称通常优先于昵称显示,用于个性化标识好友。如果没有设置备注,该值为
undefined
。isMuted
类型:
boolean | undefined
描述: 当前会话是否设置为免打扰模式。当值为
true
时,不会收到该会话的消息推送通知;当值为 false
时,正常接收通知;当值为 undefined
时,状态尚未确定。isPinned
类型:
boolean | undefined
描述: 当前会话是否置顶显示。当值为
true
时,该会话会显示在会话列表的顶部;当值为 false
时,按正常顺序排列;当值为 undefined
时,状态尚未确定。isContact
类型:
boolean | undefined
描述: 对方用户是否为当前用户的好友。当值为
true
时,表示双方互为好友;当值为 false
时,表示不是好友关系;当值为 undefined
时,好友关系尚未查询完成。setChatPinned
类型:
(value: boolean) => void
描述: 设置聊天置顶状态的方法。传入
true
将会话置顶,传入 false
取消置顶。该方法会自动调用底层 API 并更新状态。setChatMuted
类型:
(value: boolean) => void
描述: 设置免打扰状态的方法。传入
true
开启免打扰,传入 false
关闭免打扰。该方法会自动调用底层 API 并更新状态。setUserRemark
类型:
(remark: string) => void
描述: 设置用户备注的方法。传入新的备注名称来更新对方用户的备注。该方法会自动调用好友服务 API 并更新状态。
使用示例
以下是一个完整的 C2CSettingPanel 组件示例,展示了如何使用各个字段来构建一个 C2C 聊天设置面板:
import React, { useState } from 'react';import { useC2CSettingState } from './states/C2CSettingState/C2CSettingState';interface C2CSettingPanelProps {className?: string;onClose?: () => void;}const C2CSettingPanel: React.FC<C2CSettingPanelProps> = ({ className, onClose }) => {const {userID,nick,avatar,signature,remark,isMuted,isPinned,isContact,setChatPinned,setChatMuted,setUserRemark,} = useC2CSettingState();const [isEditingRemark, setIsEditingRemark] = useState(false);const [remarkInput, setRemarkInput] = useState('');// 开始编辑备注const handleEditRemark = () => {setRemarkInput(remark || nick || '');setIsEditingRemark(true);};// 保存备注const handleSaveRemark = () => {if (remarkInput.trim() !== remark) {setUserRemark(remarkInput.trim());}setIsEditingRemark(false);};// 取消编辑备注const handleCancelEditRemark = () => {setIsEditingRemark(false);setRemarkInput('');};// 切换置顶状态const handleTogglePinned = () => {setChatPinned(!isPinned);};// 切换免打扰状态const handleToggleMuted = () => {setChatMuted(!isMuted);};if (!userID) {return (<div className={`c2c-setting-panel ${className || ''}`}><div className="no-conversation">请选择一个C2C会话</div></div>);}return (<div className={`c2c-setting-panel ${className || ''}`}>{/* 头部 */}<div className="panel-header"><h3>聊天设置</h3>{onClose && (<button className="close-btn" onClick={onClose}>×</button>)}</div>{/* 用户信息区域 */}<div className="user-info-section"><div className="user-avatar">{avatar ? (<img src={avatar} alt="用户头像" />) : (<div className="default-avatar">{nick?.charAt(0) || userID?.charAt(0) || '?'}</div>)}</div><div className="user-details"><div className="user-name">{remark || nick || userID}{remark && nick && remark !== nick && (<span className="original-nick">({nick})</span>)}</div><div className="user-id">ID: {userID}</div>{signature && (<div className="user-signature">{signature}</div>)}<div className="friend-status">{isContact === true && (<span className="friend-badge">好友</span>)}{isContact === false && (<span className="stranger-badge">陌生人</span>)}</div></div></div>{/* 备注设置 */}<div className="setting-section"><h4>备注设置</h4><div className="setting-item">{isEditingRemark ? (<div className="remark-edit"><inputtype="text"value={remarkInput}onChange={e => setRemarkInput(e.target.value)}placeholder="输入备注名称"className="remark-input"autoFocus/><div className="edit-actions"><button onClick={handleSaveRemark} className="save-btn">保存</button><button onClick={handleCancelEditRemark} className="cancel-btn">取消</button></div></div>) : (<div className="remark-display"><span className="remark-text">{remark || '未设置备注'}</span><button onClick={handleEditRemark} className="edit-btn">编辑</button></div>)}</div></div>{/* 聊天设置 */}<div className="setting-section"><h4>聊天设置</h4><div className="setting-item"><div className="setting-label"><span>置顶聊天</span><p className="setting-desc">置顶后该聊天将显示在列表顶部</p></div><div className="setting-control"><label className="toggle-switch"><inputtype="checkbox"checked={isPinned || false}onChange={handleTogglePinned}/><span className="slider"></span></label></div></div><div className="setting-item"><div className="setting-label"><span>消息免打扰</span><p className="setting-desc">开启后不会收到该聊天的推送通知</p></div><div className="setting-control"><label className="toggle-switch"><inputtype="checkbox"checked={isMuted || false}onChange={handleToggleMuted}/><span className="slider"></span></label></div></div></div>{/* 其他操作 */}<div className="setting-section"><h4>其他操作</h4><div className="action-buttons">{isContact && (<button className="action-btn delete-friend danger">删除好友</button>)}</div></div></div>);};export default C2CSettingPanel;
效果图如下图所示:

样式参考
.c2c-setting-panel {width: 300px;height: 100%;background: white;border-left: 1px solid #e5e5e5;display: flex;flex-direction: column;.no-conversation {flex: 1;display: flex;align-items: center;justify-content: center;color: #999;font-size: 14px;}.panel-header {display: flex;align-items: center;justify-content: space-between;padding: 15px 20px;border-bottom: 1px solid #e5e5e5;h3 {margin: 0;font-size: 16px;font-weight: 500;}.close-btn {background: none;border: none;font-size: 20px;cursor: pointer;color: #999;&:hover {color: #333;}}}.user-info-section {padding: 20px;border-bottom: 1px solid #f0f0f0;display: flex;gap: 15px;.user-avatar {flex-shrink: 0;img, .default-avatar {width: 60px;height: 60px;border-radius: 50%;}img {object-fit: cover;}.default-avatar {background: #e5e5e5;display: flex;align-items: center;justify-content: center;font-size: 24px;font-weight: 500;color: #999;}}.user-details {flex: 1;.user-name {font-size: 16px;font-weight: 500;margin-bottom: 5px;.original-nick {color: #999;font-weight: normal;margin-left: 5px;}}.user-id {font-size: 12px;color: #999;margin-bottom: 8px;}.user-signature {font-size: 14px;color: #666;margin-bottom: 8px;line-height: 1.4;}.friend-status {.friend-badge, .stranger-badge {display: inline-block;padding: 2px 6px;border-radius: 10px;font-size: 12px;}.friend-badge {background: #e8f5e8;color: #52c41a;}.stranger-badge {background: #fff2e8;color: #fa8c16;}}}}.setting-section {padding: 20px;border-bottom: 1px solid #f0f0f0;h4 {margin: 0 0 15px 0;font-size: 14px;font-weight: 500;color: #333;}.setting-item {display: flex;align-items: center;justify-content: space-between;margin-bottom: 15px;&:last-child {margin-bottom: 0;}.setting-label {flex: 1;span {font-size: 14px;color: #333;}.setting-desc {margin: 2px 0 0 0;font-size: 12px;color: #999;}}.setting-control {flex-shrink: 0;}}.remark-edit {width: 100%;.remark-input {width: 100%;padding: 8px 12px;border: 1px solid #d9d9d9;border-radius: 4px;font-size: 14px;margin-bottom: 10px;&:focus {outline: none;border-color: #1890ff;}}.edit-actions {display: flex;gap: 10px;button {flex: 1;padding: 6px 12px;border-radius: 4px;font-size: 12px;cursor: pointer;}.save-btn {background: #1890ff;color: white;border: none;&:hover {background: #40a9ff;}}.cancel-btn {background: white;color: #666;border: 1px solid #d9d9d9;&:hover {border-color: #40a9ff;color: #40a9ff;}}}}.remark-display {display: flex;align-items: center;justify-content: space-between;width: 100%;.remark-text {font-size: 14px;color: #333;}.edit-btn {background: none;border: none;color: #1890ff;font-size: 12px;cursor: pointer;&:hover {color: #40a9ff;}}}.action-buttons {display: flex;flex-direction: column;gap: 10px;.action-btn {padding: 10px;border: 1px solid #d9d9d9;border-radius: 4px;background: white;cursor: pointer;font-size: 14px;&:hover {border-color: #40a9ff;color: #40a9ff;}&.danger {border-color: #ff4d4f;color: #ff4d4f;&:hover {background: #ff4d4f;color: white;}}}}}// Toggle switch styles.toggle-switch {position: relative;display: inline-block;width: 44px;height: 24px;input {opacity: 0;width: 0;height: 0;}.slider {position: absolute;cursor: pointer;top: 0;left: 0;right: 0;bottom: 0;background-color: #ccc;transition: .4s;border-radius: 24px;&:before {position: absolute;content: "";height: 18px;width: 18px;left: 3px;bottom: 3px;background-color: white;transition: .4s;border-radius: 50%;}}input:checked + .slider {background-color: #1890ff;}input:checked + .slider:before {transform: translateX(20px);}}}
使用要点
这个示例展示了如何:
1. 用户信息展示 - 使用
userID
、nick
、avatar
、signature
等字段展示完整的用户信息。2. 好友关系标识 - 通过
isContact
字段显示好友状态。3. 备注管理 - 使用
remark
字段显示当前备注,通过 setUserRemark
方法修改备注。4. 聊天设置控制 - 使用
isPinned
和 isMuted
字段控制置顶和免打扰状态。5. 交互操作 - 通过
setChatPinned
和 setChatMuted
方法实现设置的切换。6. 状态处理 - 正确处理各字段的
undefined
状态,提供良好的用户体验。