重构数据库管理逻辑,简化用户数据库初始化流程。引入新的数据库管理类以支持动态数据库名称和用户状态管理。更新应用启动逻辑以确保在用户登录时正确初始化数据库。增强持久化数据恢复功能,确保用户数据的可靠性和一致性。
This commit is contained in:
@@ -1,5 +1,52 @@
|
||||
import { createPersistStore } from "@/store/createPersistStore";
|
||||
import { Toast } from "antd-mobile";
|
||||
import { databaseManager } from "@/utils/db";
|
||||
|
||||
const STORE_CACHE_KEYS = [
|
||||
"user-store",
|
||||
"app-store",
|
||||
"settings-store",
|
||||
"websocket-store",
|
||||
"ckchat-store",
|
||||
"wechat-storage",
|
||||
"contacts-storage",
|
||||
"message-storage",
|
||||
"customer-storage",
|
||||
];
|
||||
|
||||
const allStorages = (): Storage[] => {
|
||||
if (typeof window === "undefined") {
|
||||
return [];
|
||||
}
|
||||
const storages: Storage[] = [];
|
||||
try {
|
||||
storages.push(window.localStorage);
|
||||
} catch (error) {
|
||||
console.warn("无法访问 localStorage:", error);
|
||||
}
|
||||
try {
|
||||
storages.push(window.sessionStorage);
|
||||
} catch (error) {
|
||||
console.warn("无法访问 sessionStorage:", error);
|
||||
}
|
||||
return storages;
|
||||
};
|
||||
|
||||
const clearStoreCaches = () => {
|
||||
const storages = allStorages();
|
||||
if (!storages.length) {
|
||||
return;
|
||||
}
|
||||
STORE_CACHE_KEYS.forEach(key => {
|
||||
storages.forEach(storage => {
|
||||
try {
|
||||
storage.removeItem(key);
|
||||
} catch (error) {
|
||||
console.warn(`清理持久化数据失败: ${key}`, error);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
export interface User {
|
||||
id: number;
|
||||
@@ -28,7 +75,7 @@ interface UserState {
|
||||
setToken: (token: string) => void;
|
||||
setToken2: (token2: string) => void;
|
||||
clearUser: () => void;
|
||||
login: (token: string, userInfo: User) => void;
|
||||
login: (token: string, userInfo: User) => Promise<void>;
|
||||
login2: (token2: string) => void;
|
||||
logout: () => void;
|
||||
}
|
||||
@@ -39,12 +86,27 @@ export const useUserStore = createPersistStore<UserState>(
|
||||
token: null,
|
||||
token2: null,
|
||||
isLoggedIn: false,
|
||||
setUser: user => set({ user, isLoggedIn: true }),
|
||||
setUser: user => {
|
||||
set({ user, isLoggedIn: true });
|
||||
databaseManager.ensureDatabase(user.id).catch(error => {
|
||||
console.warn("Failed to initialize database for user:", error);
|
||||
});
|
||||
},
|
||||
setToken: token => set({ token }),
|
||||
setToken2: token2 => set({ token2 }),
|
||||
clearUser: () =>
|
||||
set({ user: null, token: null, token2: null, isLoggedIn: false }),
|
||||
login: (token, userInfo) => {
|
||||
clearUser: () => {
|
||||
databaseManager.closeCurrentDatabase().catch(error => {
|
||||
console.warn("Failed to close database on clearUser:", error);
|
||||
});
|
||||
clearStoreCaches();
|
||||
set({ user: null, token: null, token2: null, isLoggedIn: false });
|
||||
},
|
||||
login: async (token, userInfo) => {
|
||||
clearStoreCaches();
|
||||
|
||||
// 清除旧的双token缓存
|
||||
localStorage.removeItem("token2");
|
||||
|
||||
// 只将token存储到localStorage
|
||||
localStorage.setItem("token", token);
|
||||
|
||||
@@ -66,6 +128,11 @@ export const useUserStore = createPersistStore<UserState>(
|
||||
lastLoginIp: userInfo.lastLoginIp,
|
||||
lastLoginTime: userInfo.lastLoginTime,
|
||||
};
|
||||
try {
|
||||
await databaseManager.ensureDatabase(user.id);
|
||||
} catch (error) {
|
||||
console.error("Failed to initialize user database:", error);
|
||||
}
|
||||
set({ user, token, isLoggedIn: true });
|
||||
|
||||
Toast.show({ content: "登录成功", position: "top" });
|
||||
@@ -80,6 +147,10 @@ export const useUserStore = createPersistStore<UserState>(
|
||||
// 清除localStorage中的token
|
||||
localStorage.removeItem("token");
|
||||
localStorage.removeItem("token2");
|
||||
databaseManager.closeCurrentDatabase().catch(error => {
|
||||
console.warn("Failed to close user database on logout:", error);
|
||||
});
|
||||
clearStoreCaches();
|
||||
set({ user: null, token: null, token2: null, isLoggedIn: false });
|
||||
},
|
||||
}),
|
||||
@@ -92,7 +163,11 @@ export const useUserStore = createPersistStore<UserState>(
|
||||
isLoggedIn: state.isLoggedIn,
|
||||
}),
|
||||
onRehydrateStorage: () => state => {
|
||||
// console.log("User store hydrated:", state);
|
||||
if (state?.user?.id) {
|
||||
databaseManager.ensureDatabase(state.user!.id).catch(error => {
|
||||
console.warn("Failed to restore user database:", error);
|
||||
});
|
||||
}
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { createPersistStore } from "@/store/createPersistStore";
|
||||
import { Toast } from "antd-mobile";
|
||||
import { useUserStore } from "../user";
|
||||
import { useCkChatStore } from "@/store/module/ckchat/ckchat";
|
||||
import { useCustomerStore } from "@/store/module/weChat/customer";
|
||||
const { getAccountId } = useCkChatStore.getState();
|
||||
import { msgManageCore } from "./msgManage";
|
||||
// WebSocket消息类型
|
||||
@@ -52,6 +52,7 @@ interface WebSocketState {
|
||||
reconnectAttempts: number;
|
||||
reconnectTimer: NodeJS.Timeout | null;
|
||||
aliveStatusTimer: NodeJS.Timeout | null; // 客服用户状态查询定时器
|
||||
aliveStatusUnsubscribe: (() => void) | null;
|
||||
|
||||
// 方法
|
||||
connect: (config: Partial<WebSocketConfig>) => void;
|
||||
@@ -97,6 +98,7 @@ export const useWebSocketStore = createPersistStore<WebSocketState>(
|
||||
reconnectAttempts: 0,
|
||||
reconnectTimer: null,
|
||||
aliveStatusTimer: null,
|
||||
aliveStatusUnsubscribe: null,
|
||||
|
||||
// 连接WebSocket
|
||||
connect: (config: Partial<WebSocketConfig>) => {
|
||||
@@ -405,7 +407,7 @@ export const useWebSocketStore = createPersistStore<WebSocketState>(
|
||||
},
|
||||
|
||||
// 内部方法:处理连接关闭
|
||||
_handleClose: (event: CloseEvent) => {
|
||||
_handleClose: () => {
|
||||
const currentState = get();
|
||||
|
||||
// console.log("WebSocket连接关闭:", event.code, event.reason);
|
||||
@@ -431,7 +433,7 @@ export const useWebSocketStore = createPersistStore<WebSocketState>(
|
||||
},
|
||||
|
||||
// 内部方法:处理连接错误
|
||||
_handleError: (event: Event) => {
|
||||
_handleError: () => {
|
||||
// console.error("WebSocket连接错误:", event);
|
||||
|
||||
set({ status: WebSocketStatus.ERROR });
|
||||
@@ -477,42 +479,84 @@ export const useWebSocketStore = createPersistStore<WebSocketState>(
|
||||
// 先停止现有定时器
|
||||
currentState._stopAliveStatusTimer();
|
||||
|
||||
// 获取客服用户列表
|
||||
const { kfUserList } = useCkChatStore.getState();
|
||||
const requestAliveStatus = () => {
|
||||
const state = get();
|
||||
if (state.status !== WebSocketStatus.CONNECTED) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 如果没有客服用户,不启动定时器
|
||||
if (!kfUserList || kfUserList.length === 0) {
|
||||
return;
|
||||
}
|
||||
const { customerList } = useCustomerStore.getState();
|
||||
const { kfUserList } = useCkChatStore.getState();
|
||||
const targets =
|
||||
customerList && customerList.length > 0
|
||||
? customerList
|
||||
: kfUserList && kfUserList.length > 0
|
||||
? kfUserList
|
||||
: [];
|
||||
|
||||
if (targets.length > 0) {
|
||||
state.sendCommand("CmdRequestWechatAccountsAliveStatus", {
|
||||
wechatAccountIds: targets.map(v => v.id),
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// 尝试立即请求一次,如果客服列表尚未加载,后续定时器会继续检查
|
||||
requestAliveStatus();
|
||||
|
||||
const unsubscribeCustomer = useCustomerStore.subscribe(state => {
|
||||
if (
|
||||
get().status === WebSocketStatus.CONNECTED &&
|
||||
state.customerList &&
|
||||
state.customerList.length > 0
|
||||
) {
|
||||
requestAliveStatus();
|
||||
}
|
||||
});
|
||||
|
||||
const unsubscribeKf = useCkChatStore.subscribe(state => {
|
||||
if (
|
||||
get().status === WebSocketStatus.CONNECTED &&
|
||||
state.kfUserList &&
|
||||
state.kfUserList.length > 0
|
||||
) {
|
||||
requestAliveStatus();
|
||||
}
|
||||
});
|
||||
|
||||
// 启动定时器,每5秒查询一次
|
||||
const timer = setInterval(() => {
|
||||
const state = get();
|
||||
// 检查连接状态
|
||||
if (state.status === WebSocketStatus.CONNECTED) {
|
||||
const { kfUserList: currentKfUserList } = useCkChatStore.getState();
|
||||
if (currentKfUserList && currentKfUserList.length > 0) {
|
||||
state.sendCommand("CmdRequestWechatAccountsAliveStatus", {
|
||||
wechatAccountIds: currentKfUserList.map(v => v.id),
|
||||
});
|
||||
}
|
||||
requestAliveStatus();
|
||||
} else {
|
||||
// 如果连接断开,停止定时器
|
||||
state._stopAliveStatusTimer();
|
||||
}
|
||||
}, 5 * 1000);
|
||||
|
||||
set({ aliveStatusTimer: timer });
|
||||
set({
|
||||
aliveStatusTimer: timer,
|
||||
aliveStatusUnsubscribe: () => {
|
||||
unsubscribeCustomer();
|
||||
unsubscribeKf();
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
// 内部方法:停止客服状态查询定时器
|
||||
_stopAliveStatusTimer: () => {
|
||||
const currentState = get();
|
||||
|
||||
if (currentState.aliveStatusUnsubscribe) {
|
||||
currentState.aliveStatusUnsubscribe();
|
||||
}
|
||||
|
||||
if (currentState.aliveStatusTimer) {
|
||||
clearInterval(currentState.aliveStatusTimer);
|
||||
set({ aliveStatusTimer: null });
|
||||
}
|
||||
set({ aliveStatusTimer: null, aliveStatusUnsubscribe: null });
|
||||
},
|
||||
}),
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user