FEAT => 本次更新项目为:
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user