feat(数据库): 添加消息列表数据接口和表

refactor(聊天会话): 根据选中客服过滤会话列表

fix(聊天窗口): 移除重复的未读消息清除逻辑

refactor(侧边栏): 统一联系人点击处理逻辑

chore: 删除无用的数据库测试文件
This commit is contained in:
超级老白兔
2025-09-01 10:24:15 +08:00
parent 5437a47e37
commit 64c75772bb
8 changed files with 54 additions and 199 deletions

View File

@@ -36,7 +36,7 @@ import {
StarOutlined, StarOutlined,
} from "@ant-design/icons"; } from "@ant-design/icons";
import { ChatRecord, ContractData, weChatGroup } from "@/pages/pc/ckbox/data"; import { ChatRecord, ContractData, weChatGroup } from "@/pages/pc/ckbox/data";
import { clearUnreadCount, getMessages } from "@/pages/pc/ckbox/api"; import { getMessages } from "@/pages/pc/ckbox/api";
import styles from "./ChatWindow.module.scss"; import styles from "./ChatWindow.module.scss";
import { useWebSocketStore, WebSocketMessage } from "@/store/module/websocket"; import { useWebSocketStore, WebSocketMessage } from "@/store/module/websocket";
import { formatWechatTime } from "@/utils/common"; import { formatWechatTime } from "@/utils/common";
@@ -68,30 +68,27 @@ const ChatWindow: React.FC<ChatWindowProps> = ({
>({}); >({});
const messagesEndRef = useRef<HTMLDivElement>(null); const messagesEndRef = useRef<HTMLDivElement>(null);
const getKfSelectedUser = useCkChatStore(state => state.getKfSelectedUser());
useEffect(() => { useEffect(() => {
clearUnreadCount([contract.id]).then(() => { setLoading(true);
setLoading(true); const params: any = {
const params: any = { wechatAccountId: contract.wechatAccountId,
wechatAccountId: contract.wechatAccountId, From: 1,
From: 1, To: +new Date() + 1000,
To: +new Date() + 1000, Count: 100,
Count: 100, olderData: true,
olderData: true, };
}; if (contract.groupId == 1) {
if (contract.groupId == 1) { params.wechatFriendId = contract.id;
params.wechatFriendId = contract.id; } else {
} else { params.wechatChatroomId = contract.id;
params.wechatChatroomId = contract.id; }
} getMessages(params)
getMessages(params) .then(msg => {
.then(msg => { setMessages(msg);
setMessages(msg); })
}) .finally(() => {
.finally(() => { setLoading(false);
setLoading(false); });
});
});
}, [contract.id]); }, [contract.id]);
useEffect(() => { useEffect(() => {

View File

@@ -7,13 +7,13 @@ import { formatWechatTime } from "@/utils/common";
interface MessageListProps { interface MessageListProps {
chatSessions: ContractData[] | weChatGroup[]; chatSessions: ContractData[] | weChatGroup[];
currentChat: ContractData | weChatGroup; currentChat: ContractData | weChatGroup;
onChatSelect: (chat: ContractData | weChatGroup) => void; onContactClick: (chat: ContractData | weChatGroup) => void;
} }
const MessageList: React.FC<MessageListProps> = ({ const MessageList: React.FC<MessageListProps> = ({
chatSessions, chatSessions,
currentChat, currentChat,
onChatSelect, onContactClick,
}) => { }) => {
return ( return (
<div className={styles.messageList}> <div className={styles.messageList}>
@@ -25,7 +25,7 @@ const MessageList: React.FC<MessageListProps> = ({
className={`${styles.messageItem} ${ className={`${styles.messageItem} ${
currentChat?.id === session.id ? styles.active : "" currentChat?.id === session.id ? styles.active : ""
}`} }`}
onClick={() => onChatSelect(session)} onClick={() => onContactClick(session)}
> >
<div className={styles.messageInfo}> <div className={styles.messageInfo}>
<Badge count={session.unreadCount} size="small"> <Badge count={session.unreadCount} size="small">

View File

@@ -10,13 +10,12 @@ import { ContractData, weChatGroup } from "@/pages/pc/ckbox/data";
import WechatFriends from "./WechatFriends"; import WechatFriends from "./WechatFriends";
import MessageList from "./MessageList/index"; import MessageList from "./MessageList/index";
import styles from "./SidebarMenu.module.scss"; import styles from "./SidebarMenu.module.scss";
import { getChatSessions } from "@/store/module/ckchat/ckchat"; import { useCkChatStore } from "@/store/module/ckchat/ckchat";
interface SidebarMenuProps { interface SidebarMenuProps {
contracts: ContractData[] | weChatGroup[]; contracts: ContractData[] | weChatGroup[];
currentChat: ContractData | weChatGroup; currentChat: ContractData | weChatGroup;
onContactClick: (contract: ContractData | weChatGroup) => void; onContactClick: (contract: ContractData | weChatGroup) => void;
onChatSelect: (chat: ContractData | weChatGroup) => void;
loading?: boolean; loading?: boolean;
} }
@@ -24,10 +23,9 @@ const SidebarMenu: React.FC<SidebarMenuProps> = ({
contracts, contracts,
currentChat, currentChat,
onContactClick, onContactClick,
onChatSelect,
loading = false, loading = false,
}) => { }) => {
const chatSessions = getChatSessions(); const chatSessions = useCkChatStore(state => state.getChatSessions());
const [searchText, setSearchText] = useState(""); const [searchText, setSearchText] = useState("");
const [activeTab, setActiveTab] = useState("chats"); const [activeTab, setActiveTab] = useState("chats");
@@ -145,7 +143,7 @@ const SidebarMenu: React.FC<SidebarMenuProps> = ({
return ( return (
<MessageList <MessageList
chatSessions={getFilteredSessions()} chatSessions={getFilteredSessions()}
onChatSelect={onChatSelect} onContactClick={onContactClick}
currentChat={currentChat} currentChat={currentChat}
/> />
); );

View File

@@ -16,22 +16,6 @@ const VerticalUserList: React.FC = () => {
}; };
const kfUserList = useCkChatStore(state => state.kfUserList); const kfUserList = useCkChatStore(state => state.kfUserList);
const kfSelected = useCkChatStore(state => state.kfSelected); const kfSelected = useCkChatStore(state => state.kfSelected);
const [kefuList, setKefuList] = useState([]);
// // 获取客服列表数据
// useEffect(() => {
// const fetchKfUserList = async () => {
// try {
// const data = await getkfUserList();
// setKefuList(data || []);
// } catch (error) {
// console.error("获取客服列表失败:", error);
// setKefuList([]);
// }
// };
// fetchKfUserList();
// }, [getkfUserList]);
return ( return (
<div className={styles.verticalUserList}> <div className={styles.verticalUserList}>
<div <div

View File

@@ -10,6 +10,7 @@ import styles from "./index.module.scss";
import { addChatSession } from "@/store/module/ckchat/ckchat"; import { addChatSession } from "@/store/module/ckchat/ckchat";
const { Header, Content, Sider } = Layout; const { Header, Content, Sider } = Layout;
import { chatInitAPIdata } from "./main"; import { chatInitAPIdata } from "./main";
import { clearUnreadCount } from "@/pages/pc/ckbox/api";
import { import {
KfUserListData, KfUserListData,
weChatGroup, weChatGroup,
@@ -57,9 +58,13 @@ const CkboxPage: React.FC = () => {
}); });
}, []); }, []);
//开始开启聊天
const handleContactClick = (contract: ContractData | weChatGroup) => { const handleContactClick = (contract: ContractData | weChatGroup) => {
addChatSession(contract); clearUnreadCount([contract.id]).then(() => {
setCurrentChat(contract); contract.unreadCount = 0;
addChatSession(contract);
setCurrentChat(contract);
});
}; };
const handleSendMessage = async (message: string) => { const handleSendMessage = async (message: string) => {
@@ -107,7 +112,6 @@ const CkboxPage: React.FC = () => {
contracts={contracts} contracts={contracts}
currentChat={currentChat} currentChat={currentChat}
onContactClick={handleContactClick} onContactClick={handleContactClick}
onChatSelect={setCurrentChat}
loading={loading} loading={loading}
/> />
</Sider> </Sider>

View File

@@ -16,7 +16,7 @@ export const useCkChatStore = createPersistStore<CkChatState>(
chatSessions: [], //聊天会话 chatSessions: [], //聊天会话
kfUserList: [], //客服列表 kfUserList: [], //客服列表
newContractList: [], //联系人分组 newContractList: [], //联系人分组
kfSelected: 0, kfSelected: 0, //选中的客服
//客服列表 //客服列表
asyncKfUserList: async data => { asyncKfUserList: async data => {
set({ kfUserList: data }); set({ kfUserList: data });
@@ -80,7 +80,13 @@ export const useCkChatStore = createPersistStore<CkChatState>(
// 获取聊天会话 // 获取聊天会话
getChatSessions: () => { getChatSessions: () => {
const state = useCkChatStore.getState(); const state = useCkChatStore.getState();
return state.chatSessions; if (state.kfSelected != 0) {
return state.chatSessions.filter(
item => item.wechatAccountId === state.kfSelected,
);
} else {
return state.chatSessions;
}
}, },
// 添加聊天会话 // 添加聊天会话
addChatSession: (session: ContractData | weChatGroup) => { addChatSession: (session: ContractData | weChatGroup) => {

View File

@@ -1,146 +0,0 @@
/**
* 数据库版本升级测试脚本
* 用于验证数据库版本升级逻辑是否正常工作
*/
import { db } from "./db";
// 重置数据库(完全删除并重新创建)
export async function resetDatabase() {
try {
console.log("开始重置数据库...");
// 关闭数据库连接
if (db.isOpen()) {
db.close();
}
// 删除数据库
await db.delete();
console.log("旧数据库已删除");
// 重新打开数据库(这会创建新的数据库)
await db.open();
console.log("数据库重置成功!");
console.log("当前数据库版本:", db.verno);
console.log("数据库名称:", db.name);
return {
success: true,
version: db.verno,
tables: db.tables.map(table => table.name),
message: "数据库重置成功",
};
} catch (error) {
console.error("数据库重置失败:", error);
return {
success: false,
error: error instanceof Error ? error.message : String(error),
message: "数据库重置失败",
};
}
}
// 测试数据库初始化和版本升级
export async function testDatabaseUpgrade() {
try {
console.log("开始测试数据库初始化...");
// 首先尝试正常打开数据库
try {
await db.open();
} catch (upgradeError) {
// 如果遇到升级错误,尝试重置数据库
if (
upgradeError.message &&
upgradeError.message.includes("primary key")
) {
console.log("检测到主键冲突,尝试重置数据库...");
const resetResult = await resetDatabase();
if (!resetResult.success) {
throw new Error(`数据库重置失败: ${resetResult.error}`);
}
} else {
throw upgradeError;
}
}
console.log("数据库初始化成功!");
console.log("当前数据库版本:", db.verno);
console.log("数据库名称:", db.name);
// 检查表是否存在
const tables = db.tables.map(table => table.name);
console.log("数据库表:", tables);
// 测试基本操作
const testData = {
tenantId: 1, // 修正为number类型
wechatId: "test-wechat-id",
nickname: "测试用户",
alias: "测试别名",
};
// 测试创建数据
const userId = await db.kfUsers.add({
...testData,
id: 0, // 添加必需的id字段
currentDeviceId: 0,
isDeleted: false,
deleteTime: "",
groupId: 0,
memo: "", // 备注信息
wechatVersion: "",
labels: [],
lastUpdateTime: new Date().toISOString(), // 修复语法错误,使用字符串类型
serverId: "test-server-id-001", // 提供有意义的测试值
// 移除不属于KfUserListData接口的字段
signature: "",
bindQQ: "",
bindEmail: "",
bindMobile: "",
bindWeixin: "",
bindAlipay: "",
bindTaobao: "",
bindJd: "",
bindDouyin: "",
bindKuaishou: "",
bindBilibili: "",
avatar: "",
gender: 0,
region: "",
createTime: new Date().toISOString(), // 使用字符串类型
});
console.log("创建测试用户成功ID:", userId);
// 测试查询数据
const user = await db.kfUsers.get(userId);
console.log("查询测试用户:", user);
// 清理测试数据
await db.kfUsers.delete(userId);
console.log("清理测试数据完成");
return {
success: true,
version: db.verno,
tables: tables,
message: "数据库版本升级测试通过",
};
} catch (error) {
console.error("数据库测试失败:", error);
return {
success: false,
error: error instanceof Error ? error.message : String(error),
message: "数据库版本升级测试失败",
};
}
}
// 如果直接运行此文件,执行测试
if (typeof window === "undefined") {
testDatabaseUpgrade().then(result => {
console.log("测试结果:", result);
});
}

View File

@@ -57,12 +57,24 @@ export interface NewContactListData {
weChatGroup: weChatGroup[]; weChatGroup: weChatGroup[];
} }
// 消息列表数据接口
export interface MessageListData extends Omit<ContractData, "id"> {
serverId: number | string; // 服务器ID作为主键
id?: number; // 接口数据的原始ID字段
wechatAccountId: number; // 微信账号ID
chatroomAvatar?: string; // 群头像
chatroomName?: string; // 群名称
chatroomId?: number; // 群ID
[key: string]: any;
}
// 数据库类 // 数据库类
class CunkebaoDatabase extends Dexie { class CunkebaoDatabase extends Dexie {
kfUsers!: Table<KfUserWithServerId>; kfUsers!: Table<KfUserWithServerId>;
weChatGroup!: Table<weChatGroupServerId>; weChatGroup!: Table<weChatGroupServerId>;
contracts!: Table<ContractWithServerId>; contracts!: Table<ContractWithServerId>;
newContractList!: Table<NewContactListData>; newContractList!: Table<NewContactListData>;
messageList!: Table<MessageListData>;
constructor() { constructor() {
super("CunkebaoDatabase"); super("CunkebaoDatabase");