115 lines
3.3 KiB
TypeScript
115 lines
3.3 KiB
TypeScript
import type { ServerConfig } from '../types';
|
||
|
||
const STORAGE_KEY = 'mengya_monitor_servers';
|
||
|
||
export const loadServers = (): ServerConfig[] => {
|
||
try {
|
||
const stored = localStorage.getItem(STORAGE_KEY);
|
||
if (stored) {
|
||
const parsed = JSON.parse(stored);
|
||
// Ensure it's an array
|
||
if (Array.isArray(parsed)) {
|
||
return parsed;
|
||
}
|
||
}
|
||
} catch (error) {
|
||
console.error('Failed to load servers:', error);
|
||
}
|
||
return [];
|
||
};
|
||
|
||
export const saveServers = (servers: ServerConfig[]): void => {
|
||
try {
|
||
localStorage.setItem(STORAGE_KEY, JSON.stringify(servers));
|
||
} catch (error) {
|
||
console.error('Failed to save servers:', error);
|
||
}
|
||
};
|
||
|
||
export const addServer = (server: Omit<ServerConfig, 'id'>): ServerConfig => {
|
||
const servers = loadServers();
|
||
const newServer: ServerConfig = {
|
||
...server,
|
||
id: Date.now().toString(),
|
||
};
|
||
servers.push(newServer);
|
||
saveServers(servers);
|
||
return newServer;
|
||
};
|
||
|
||
export const updateServer = (id: string, updates: Partial<ServerConfig>): void => {
|
||
const servers = loadServers();
|
||
const index = servers.findIndex(s => s.id === id);
|
||
if (index !== -1) {
|
||
servers[index] = { ...servers[index], ...updates };
|
||
saveServers(servers);
|
||
}
|
||
};
|
||
|
||
export const removeServer = (id: string): void => {
|
||
const servers = loadServers();
|
||
const filtered = servers.filter(s => s.id !== id);
|
||
saveServers(filtered);
|
||
};
|
||
|
||
/**
|
||
* 导出服务器配置到剪贴板
|
||
* @returns Promise<string> 返回导出的 JSON 字符串
|
||
*/
|
||
export const exportServersToClipboard = async (): Promise<string> => {
|
||
const servers = loadServers();
|
||
const json = JSON.stringify(servers, null, 2);
|
||
|
||
try {
|
||
await navigator.clipboard.writeText(json);
|
||
return json;
|
||
} catch (error) {
|
||
console.error('Failed to copy to clipboard:', error);
|
||
throw new Error('无法复制到剪贴板,请检查浏览器权限');
|
||
}
|
||
};
|
||
|
||
/**
|
||
* 从剪贴板导入服务器配置
|
||
* @returns Promise<ServerConfig[]> 返回导入的服务器配置数组
|
||
*/
|
||
export const importServersFromClipboard = async (): Promise<ServerConfig[]> => {
|
||
try {
|
||
const text = await navigator.clipboard.readText();
|
||
const parsed = JSON.parse(text);
|
||
|
||
if (!Array.isArray(parsed)) {
|
||
throw new Error('无效的配置格式:必须是服务器配置数组');
|
||
}
|
||
|
||
// 验证每个配置项的基本结构
|
||
const validServers: ServerConfig[] = [];
|
||
for (const item of parsed) {
|
||
if (item && typeof item === 'object' &&
|
||
typeof item.name === 'string' &&
|
||
typeof item.url === 'string') {
|
||
// 为新导入的服务器生成新的 ID,避免 ID 冲突
|
||
validServers.push({
|
||
id: Date.now().toString() + Math.random().toString(36).substr(2, 9),
|
||
name: item.name,
|
||
url: item.url,
|
||
enabled: item.enabled !== undefined ? item.enabled : true,
|
||
});
|
||
}
|
||
}
|
||
|
||
if (validServers.length === 0) {
|
||
throw new Error('未找到有效的服务器配置');
|
||
}
|
||
|
||
return validServers;
|
||
} catch (error) {
|
||
if (error instanceof SyntaxError) {
|
||
throw new Error('无效的 JSON 格式');
|
||
}
|
||
if (error instanceof Error) {
|
||
throw error;
|
||
}
|
||
throw new Error('读取剪贴板失败,请检查浏览器权限');
|
||
}
|
||
}; |