FEAT => 本次更新项目为:

This commit is contained in:
超级老白兔
2025-08-29 15:29:48 +08:00
parent 49a94318ac
commit 8e177534f4
2 changed files with 129 additions and 69 deletions

View File

@@ -374,11 +374,11 @@
margin: 0 0 4px 0;
font-size: 12px;
color: #1890ff;
:global(.ant-input) {
font-size: 12px;
}
:global(.ant-btn) {
padding: 0;
width: 20px;

View File

@@ -42,16 +42,19 @@ import {
FileExcelOutlined,
FilePptOutlined,
PlayCircleFilled,
EditOutlined,
CheckOutlined,
} from "@ant-design/icons";
import { ChatRecord, ContractData, GroupData } from "@/pages/pc/ckbox/data";
import { ChatRecord, ContractData } from "@/pages/pc/ckbox/data";
import { clearUnreadCount, getMessages } from "@/pages/pc/ckbox/api";
import styles from "./ChatWindow.module.scss";
import { useWebSocketStore, WebSocketMessage } from "@/store/module/websocket";
import { formatWechatTime } from "@/utils/common";
const { Header, Content, Footer, Sider } = Layout;
const { TextArea } = Input;
interface ChatWindowProps {
contract: ContractData | GroupData;
contract: ContractData;
onSendMessage: (message: string) => void;
showProfile?: boolean;
onToggleProfile?: () => void;
@@ -71,6 +74,8 @@ const ChatWindow: React.FC<ChatWindowProps> = ({
const [pendingVideoRequests, setPendingVideoRequests] = useState<
Record<string, string>
>({});
const [isEditingRemark, setIsEditingRemark] = useState(false);
const [remarkValue, setRemarkValue] = useState(contract.conRemark || "");
const messagesEndRef = useRef<HTMLDivElement>(null);
useEffect(() => {
@@ -93,6 +98,12 @@ const ChatWindow: React.FC<ChatWindowProps> = ({
});
}, [contract.id]);
// 当contract变化时更新备注值
useEffect(() => {
setRemarkValue(contract.conRemark || "");
setIsEditingRemark(false);
}, [contract.conRemark]);
useEffect(() => {
// 只有在非视频加载操作时才自动滚动到底部
// 检查是否有视频正在加载中
@@ -779,59 +790,60 @@ const ChatWindow: React.FC<ChatWindowProps> = ({
);
};
const chatMenuItems = [
{
key: "profile",
icon: <UserOutlined />,
label: "查看资料",
},
{
key: "call",
icon: <PhoneOutlined />,
label: "语音通话",
},
{
key: "video",
icon: <VideoCameraOutlined />,
label: "视频通话",
},
{
key: "divider1",
type: "divider",
},
{
key: "pin",
label: "置顶聊天",
},
{
key: "mute",
label: "消息免打扰",
},
{
key: "divider2",
type: "divider",
},
{
key: "clear",
danger: true,
label: "清空聊天记录",
},
];
// 处理备注保存
const handleSaveRemark = () => {
// 这里应该调用API保存备注到后端
// 暂时只更新本地状态
messageApi.success("备注保存成功");
setIsEditingRemark(false);
// 更新contract对象中的备注实际项目中应该通过props回调或状态管理
};
// 处理取消编辑
const handleCancelEdit = () => {
setRemarkValue(contract.conRemark || "");
setIsEditingRemark(false);
};
const chatMenu = (
<Menu>
<Menu.Item key="profile" icon={<UserOutlined />}>
</Menu.Item>
<Menu.Item key="call" icon={<PhoneOutlined />}>
</Menu.Item>
<Menu.Item key="video" icon={<VideoCameraOutlined />}>
</Menu.Item>
<Menu.Divider />
<Menu.Item key="pin"></Menu.Item>
<Menu.Item key="mute"></Menu.Item>
<Menu.Divider />
<Menu.Item key="clear" danger>
</Menu.Item>
</Menu>
);
// 模拟联系人详细信息
const contractInfo = {
name: contract.name,
nickname: contract.nickname,
conRemark: remarkValue, // 使用当前编辑的备注值
alias: contract.alias,
wechatId: contract.wechatId,
avatar: contract.avatar,
phone: "13800138001",
email: "zhangsan@example.com",
department: "技术部",
position: "前端工程师",
company: "某某科技有限公司",
location: "北京市朝阳区",
joinDate: "2023-01-15",
phone: contract.phone || "-",
email: contract.email || "-",
department: contract.department || "-",
position: contract.position || "-",
company: contract.company || "-",
location: contract.location || "-",
joinDate: contract.joinDate || "-",
status: "在线",
tags: ["技术专家", "前端", "React"],
bio: "专注于前端开发热爱新技术擅长React、Vue等框架。",
tags: contract.labels,
bio: contract.bio || "-",
};
return (
@@ -849,17 +861,9 @@ const ChatWindow: React.FC<ChatWindowProps> = ({
contract.type === "group" ? <TeamOutlined /> : <UserOutlined />
}
/>
<div
className={styles.chatHeaderDetails}
style={{
display: "flex",
}}
>
<div className={styles.chatHeaderDetails}>
<div className={styles.chatHeaderName}>
{contract.name}
{contract.online && (
<span className={styles.chatHeaderOnlineStatus}>线</span>
)}
{contract.nickname || contract.name}
</div>
</div>
</div>
@@ -878,7 +882,7 @@ const ChatWindow: React.FC<ChatWindowProps> = ({
className={styles.headerButton}
/>
</Tooltip>
<Dropdown menu={{ items: chatMenuItems }} trigger={["click"]}>
<Dropdown overlay={chatMenu} trigger={["click"]}>
<Button
type="text"
icon={<MoreOutlined />}
@@ -1028,7 +1032,7 @@ const ChatWindow: React.FC<ChatWindowProps> = ({
{/* 右侧个人资料卡片 */}
{showProfile && (
<Sider width={280} className={styles.profileSider}>
<Sider width={330} className={styles.profileSider}>
<div className={styles.profileSiderContent}>
<div className={styles.profileHeader}>
<h3></h3>
@@ -1049,12 +1053,68 @@ const ChatWindow: React.FC<ChatWindowProps> = ({
icon={<UserOutlined />}
/>
<div className={styles.profileInfo}>
<h4>{contractInfo.name}</h4>
<p className={styles.profileStatus}>
<Badge status="success" text={contractInfo.status} />
</p>
<p className={styles.profilePosition}>
{contractInfo.position} · {contractInfo.department}
<Tooltip
title={contractInfo.nickname || contractInfo.name}
placement="top"
>
<h4 className={styles.profileNickname}>
{contractInfo.nickname || contractInfo.name}
</h4>
</Tooltip>
<div className={styles.profileRemark}>
{isEditingRemark ? (
<div
style={{
display: "flex",
alignItems: "center",
gap: "8px",
}}
>
<Input
value={remarkValue}
onChange={e => setRemarkValue(e.target.value)}
placeholder="请输入备注"
size="small"
style={{ flex: 1 }}
/>
<Button
type="text"
size="small"
icon={<CheckOutlined />}
onClick={handleSaveRemark}
style={{ color: "#52c41a" }}
/>
<Button
type="text"
size="small"
icon={<CloseOutlined />}
onClick={handleCancelEdit}
style={{ color: "#ff4d4f" }}
/>
</div>
) : (
<div
style={{
display: "flex",
alignItems: "center",
gap: "8px",
}}
>
<span>: {contractInfo.conRemark || "无"}</span>
<Button
type="text"
size="small"
icon={<EditOutlined />}
onClick={() => setIsEditingRemark(true)}
style={{ color: "#1890ff" }}
/>
</div>
)}
</div>
<p className={styles.profileWechatId}>
: {contractInfo.alias || contractInfo.wechatId}
</p>
</div>
</div>