2025-10-23 12:55:57 +08:00
|
|
|
|
import { create } from "zustand";
|
|
|
|
|
|
import { persist } from "zustand/middleware";
|
2025-11-14 18:23:54 +08:00
|
|
|
|
import { ChatSession } from "@/utils/db";
|
|
|
|
|
|
import { Message, MessageState, SessionsUpdater } from "./message.data";
|
|
|
|
|
|
|
|
|
|
|
|
const computeSortKey = (session: ChatSession) => {
|
|
|
|
|
|
const isTop = session.config?.top ? 1 : 0;
|
|
|
|
|
|
const timestamp = new Date(session.lastUpdateTime || new Date()).getTime();
|
|
|
|
|
|
const displayName = (
|
|
|
|
|
|
session.conRemark ||
|
|
|
|
|
|
session.nickname ||
|
|
|
|
|
|
(session as any).wechatId ||
|
|
|
|
|
|
""
|
|
|
|
|
|
).toLowerCase();
|
|
|
|
|
|
|
|
|
|
|
|
return `${isTop}|${timestamp}|${displayName}`;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const normalizeSessions = (sessions: ChatSession[]) => {
|
|
|
|
|
|
if (!Array.isArray(sessions)) {
|
|
|
|
|
|
return [];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return [...sessions]
|
|
|
|
|
|
.map(session => ({
|
|
|
|
|
|
...session,
|
|
|
|
|
|
sortKey: computeSortKey(session),
|
|
|
|
|
|
}))
|
|
|
|
|
|
.sort((a, b) => b.sortKey.localeCompare(a.sortKey));
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const resolveUpdater = (
|
|
|
|
|
|
updater: SessionsUpdater,
|
|
|
|
|
|
previous: ChatSession[],
|
|
|
|
|
|
): ChatSession[] => {
|
|
|
|
|
|
if (typeof updater === "function") {
|
|
|
|
|
|
return updater(previous);
|
|
|
|
|
|
}
|
|
|
|
|
|
return updater;
|
|
|
|
|
|
};
|
2025-10-23 17:02:33 +08:00
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 会话列表状态管理Store
|
|
|
|
|
|
* 职责:只管理状态,不存储会话列表数据
|
|
|
|
|
|
* 数据存储在:组件state + IndexedDB
|
|
|
|
|
|
*/
|
2025-10-23 12:55:57 +08:00
|
|
|
|
export const useMessageStore = create<MessageState>()(
|
|
|
|
|
|
persist(
|
|
|
|
|
|
(set, get) => ({
|
2025-10-23 17:02:33 +08:00
|
|
|
|
// ==================== 新增状态管理 ====================
|
|
|
|
|
|
loading: false,
|
|
|
|
|
|
refreshing: false,
|
|
|
|
|
|
lastRefreshTime: null,
|
2025-10-23 20:42:29 +08:00
|
|
|
|
hasLoadedOnce: false,
|
2025-10-23 17:02:33 +08:00
|
|
|
|
|
|
|
|
|
|
setLoading: (loading: boolean) => set({ loading }),
|
|
|
|
|
|
setRefreshing: (refreshing: boolean) => set({ refreshing }),
|
2025-10-23 20:42:29 +08:00
|
|
|
|
setHasLoadedOnce: (loaded: boolean) => set({ hasLoadedOnce: loaded }),
|
|
|
|
|
|
resetLoadState: () =>
|
|
|
|
|
|
set({
|
|
|
|
|
|
hasLoadedOnce: false,
|
|
|
|
|
|
loading: false,
|
|
|
|
|
|
refreshing: false,
|
2025-11-14 18:23:54 +08:00
|
|
|
|
sessions: [],
|
2025-10-23 20:42:29 +08:00
|
|
|
|
}),
|
2025-10-23 17:02:33 +08:00
|
|
|
|
|
|
|
|
|
|
// ==================== 保留原有接口(向后兼容) ====================
|
|
|
|
|
|
messageList: [],
|
|
|
|
|
|
currentMessage: null,
|
|
|
|
|
|
updateMessageList: (messageList: Message[]) => set({ messageList }),
|
2025-10-23 12:55:57 +08:00
|
|
|
|
updateCurrentMessage: (message: Message) =>
|
2025-10-23 17:02:33 +08:00
|
|
|
|
set({ currentMessage: message }),
|
2025-10-23 12:55:57 +08:00
|
|
|
|
updateMessageStatus: (messageId: number, status: string) =>
|
|
|
|
|
|
set({
|
|
|
|
|
|
messageList: get().messageList.map(message =>
|
|
|
|
|
|
message.id === messageId ? { ...message, status } : message,
|
|
|
|
|
|
),
|
2025-10-23 17:02:33 +08:00
|
|
|
|
}),
|
2025-11-14 18:23:54 +08:00
|
|
|
|
|
|
|
|
|
|
// ==================== 会话数据接口 ====================
|
|
|
|
|
|
sessions: [],
|
|
|
|
|
|
setSessions: (updater: SessionsUpdater) =>
|
|
|
|
|
|
set(state => ({
|
|
|
|
|
|
sessions: normalizeSessions(resolveUpdater(updater, state.sessions)),
|
|
|
|
|
|
lastRefreshTime: new Date().toISOString(),
|
|
|
|
|
|
})),
|
|
|
|
|
|
upsertSession: (session: ChatSession) =>
|
|
|
|
|
|
set(state => {
|
|
|
|
|
|
const next = [...state.sessions];
|
|
|
|
|
|
const index = next.findIndex(
|
|
|
|
|
|
s => s.id === session.id && s.type === session.type,
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
if (index > -1) {
|
|
|
|
|
|
next[index] = session;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
next.push(session);
|
|
|
|
|
|
}
|
|
|
|
|
|
return {
|
|
|
|
|
|
sessions: normalizeSessions(next),
|
|
|
|
|
|
lastRefreshTime: new Date().toISOString(),
|
|
|
|
|
|
};
|
|
|
|
|
|
}),
|
|
|
|
|
|
removeSessionById: (sessionId: number, type: ChatSession["type"]) =>
|
|
|
|
|
|
set(state => ({
|
|
|
|
|
|
sessions: normalizeSessions(
|
|
|
|
|
|
state.sessions.filter(
|
|
|
|
|
|
s => !(s.id === sessionId && s.type === type),
|
|
|
|
|
|
),
|
|
|
|
|
|
),
|
|
|
|
|
|
lastRefreshTime: new Date().toISOString(),
|
|
|
|
|
|
})),
|
|
|
|
|
|
clearSessions: () =>
|
|
|
|
|
|
set({
|
|
|
|
|
|
sessions: [],
|
|
|
|
|
|
lastRefreshTime: new Date().toISOString(),
|
|
|
|
|
|
}),
|
2025-10-23 12:55:57 +08:00
|
|
|
|
}),
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "message-storage",
|
|
|
|
|
|
partialize: state => ({
|
2025-10-23 17:02:33 +08:00
|
|
|
|
// 只持久化必要的状态,不持久化数据
|
|
|
|
|
|
lastRefreshTime: state.lastRefreshTime,
|
2025-10-23 20:42:29 +08:00
|
|
|
|
hasLoadedOnce: state.hasLoadedOnce,
|
2025-10-23 17:02:33 +08:00
|
|
|
|
// 保留原有持久化字段(向后兼容)
|
2025-10-23 12:55:57 +08:00
|
|
|
|
messageList: [],
|
|
|
|
|
|
currentMessage: null,
|
|
|
|
|
|
}),
|
|
|
|
|
|
},
|
|
|
|
|
|
),
|
|
|
|
|
|
);
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 更新当前选中的消息
|
|
|
|
|
|
* @param message 消息
|
|
|
|
|
|
* @returns void
|
|
|
|
|
|
*/
|
|
|
|
|
|
export const updateCurrentMessage = (message: Message) =>
|
|
|
|
|
|
useMessageStore.getState().updateCurrentMessage(message);
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 更新消息列表
|
|
|
|
|
|
* @param messageList 消息列表
|
|
|
|
|
|
* @returns void
|
|
|
|
|
|
*/
|
|
|
|
|
|
export const updateMessageList = (messageList: Message[]) =>
|
|
|
|
|
|
useMessageStore.getState().updateMessageList(messageList);
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取当前选中的消息
|
|
|
|
|
|
* @returns Message | null
|
|
|
|
|
|
*/
|
|
|
|
|
|
export const getCurrentMessage = () =>
|
|
|
|
|
|
useMessageStore.getState().currentMessage;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 更新消息状态
|
|
|
|
|
|
* @param messageId 消息ID
|
|
|
|
|
|
* @param status 状态
|
|
|
|
|
|
* @returns void
|
|
|
|
|
|
*/
|
|
|
|
|
|
export const updateMessageStatus = (messageId: number, status: string) =>
|
|
|
|
|
|
useMessageStore.getState().updateMessageStatus(messageId, status);
|
2025-10-23 17:02:33 +08:00
|
|
|
|
|
|
|
|
|
|
// ==================== 新增导出函数 ====================
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 设置加载状态
|
|
|
|
|
|
* @param loading 加载状态
|
|
|
|
|
|
*/
|
|
|
|
|
|
export const setLoading = (loading: boolean) =>
|
|
|
|
|
|
useMessageStore.getState().setLoading(loading);
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 设置同步状态
|
|
|
|
|
|
* @param refreshing 同步状态
|
|
|
|
|
|
*/
|
|
|
|
|
|
export const setRefreshing = (refreshing: boolean) =>
|
|
|
|
|
|
useMessageStore.getState().setRefreshing(refreshing);
|
|
|
|
|
|
|
2025-10-23 20:42:29 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 设置已加载标识
|
|
|
|
|
|
* @param loaded 是否已加载
|
|
|
|
|
|
*/
|
|
|
|
|
|
export const setHasLoadedOnce = (loaded: boolean) =>
|
|
|
|
|
|
useMessageStore.getState().setHasLoadedOnce(loaded);
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 重置加载状态(用于登出或切换用户)
|
|
|
|
|
|
*/
|
|
|
|
|
|
export const resetLoadState = () => useMessageStore.getState().resetLoadState();
|