Spaces:
Running
Running
import { defineStore } from 'pinia' | |
import { ref, watch } from 'vue' | |
import { useBackendStore } from './backend' | |
export const useDashboardStore = defineStore('dashboard', () => { | |
// 状态 | |
const status = ref({ | |
keyCount: 0, | |
modelCount: 0, | |
retryCount: 0, | |
last24hCalls: 0, | |
hourlyCalls: 0, | |
minuteCalls: 0 | |
}) | |
// 添加图表相关的时间序列数据 | |
const timeSeriesData = ref({ | |
calls: [], // API调用时间序列 | |
tokens: [] // Token使用时间序列 | |
}) | |
const config = ref({ | |
maxRequestsPerMinute: 0, | |
maxRequestsPerDayPerIp: 0, | |
currentTime: '', | |
fakeStreaming: false, | |
fakeStreamingInterval: 0, | |
randomString: false, | |
localVersion: '', | |
remoteVersion: '', | |
hasUpdate: false, | |
concurrentRequests: 0, | |
increaseConcurrentOnFailure: 0, | |
maxConcurrentRequests: 0, | |
maxRetryNum: 0, | |
searchPrompt: '', | |
maxEmptyResponses: 0 | |
}) | |
const apiKeyStats = ref([]) | |
const logs = ref([]) | |
const isRefreshing = ref(false) | |
const isConfigLoaded = ref(false) | |
// 添加模型相关状态 | |
const selectedModel = ref('all') | |
const availableModels = ref([]) | |
// 夜间模式状态 | |
const isDarkMode = ref(localStorage.getItem('darkMode') === 'true') | |
// 监听夜间模式变化,保存到localStorage | |
watch(isDarkMode, (newValue) => { | |
localStorage.setItem('darkMode', newValue) | |
applyDarkMode(newValue) | |
}) | |
// 应用夜间模式 | |
function applyDarkMode(isDark) { | |
if (isDark) { | |
document.documentElement.classList.add('dark-mode') | |
} else { | |
document.documentElement.classList.remove('dark-mode') | |
} | |
} | |
// 初始应用夜间模式 | |
applyDarkMode(isDarkMode.value) | |
// 获取仪表盘数据 | |
async function fetchDashboardData() { | |
if (isRefreshing.value) return // 防止重复请求 | |
const backendStore = useBackendStore() | |
isRefreshing.value = true | |
try { | |
const response = await backendStore.apiRequest('api/dashboard-data') | |
const data = await response.json() | |
updateDashboardData(data) | |
} catch (error) { | |
console.error('获取数据失败:', error) | |
// 如果是网络错误,可以显示错误状态 | |
throw error | |
} finally { | |
isRefreshing.value = false | |
} | |
} | |
// 更新仪表盘数据 | |
function updateDashboardData(data) { | |
// 更新状态数据 | |
status.value = { | |
keyCount: data.key_count || 0, | |
modelCount: data.model_count || 0, | |
retryCount: data.retry_count || 0, | |
last24hCalls: data.last_24h_calls || 0, | |
hourlyCalls: data.hourly_calls || 0, | |
minuteCalls: data.minute_calls || 0, | |
enableVertex: data.enable_vertex || false | |
} | |
// 更新时间序列数据 | |
if (data.calls_time_series) { | |
timeSeriesData.value.calls = data.calls_time_series | |
} | |
if (data.tokens_time_series) { | |
timeSeriesData.value.tokens = data.tokens_time_series | |
} | |
// 更新配置数据 | |
config.value = { | |
maxRequestsPerMinute: data.max_requests_per_minute || 0, | |
maxRequestsPerDayPerIp: data.max_requests_per_day_per_ip || 0, | |
currentTime: data.current_time || '', | |
fakeStreaming: data.fake_streaming || false, | |
fakeStreamingInterval: data.fake_streaming_interval || 0, | |
randomString: data.random_string || false, | |
randomStringLength: data.random_string_length || 0, | |
searchMode: data.search_mode || false, | |
searchPrompt: data.search_prompt || '', | |
localVersion: data.local_version || '', | |
remoteVersion: data.remote_version || '', | |
hasUpdate: data.has_update || false, | |
concurrentRequests: data.concurrent_requests || 0, | |
increaseConcurrentOnFailure: data.increase_concurrent_on_failure || 0, | |
maxConcurrentRequests: data.max_concurrent_requests || 0, | |
enableVertex: data.enable_vertex || false, | |
enableVertexExpress: data.enable_vertex_express || false, | |
vertexExpressApiKey: data.vertex_express_api_key || false, | |
googleCredentialsJson: data.google_credentials_json || false, | |
maxRetryNum: data.max_retry_num || 0, | |
maxEmptyResponses: data.max_empty_responses || 0 | |
} | |
// 更新API密钥统计 | |
if (data.api_key_stats) { | |
apiKeyStats.value = data.api_key_stats.map(stat => ({ | |
...stat, | |
// 确保model_stats的每个模型都有calls和tokens两个指标 | |
model_stats: Object.entries(stat.model_stats || {}).reduce((acc, [model, data]) => { | |
acc[model] = { | |
calls: typeof data === 'object' ? data.calls : data, // 兼容旧格式 | |
tokens: typeof data === 'object' ? data.tokens : 0 | |
} | |
return acc | |
}, {}) | |
})) | |
// 提取所有可用的模型 | |
const models = new Set(['all']) // 始终包含"全部"选项 | |
data.api_key_stats.forEach(stat => { | |
if (stat.model_stats) { | |
Object.keys(stat.model_stats).forEach(model => { | |
models.add(model) | |
}) | |
} | |
}) | |
availableModels.value = Array.from(models) | |
// 如果当前选择的模型不在可用模型列表中,重置为"all" | |
if (!availableModels.value.includes(selectedModel.value)) { | |
selectedModel.value = 'all' | |
} | |
} | |
// 更新日志 | |
if (data.logs) { | |
logs.value = data.logs | |
} | |
isConfigLoaded.value = true | |
} | |
// 设置选择的模型 | |
function setSelectedModel(model) { | |
selectedModel.value = model | |
} | |
// 切换夜间模式 | |
function toggleDarkMode() { | |
isDarkMode.value = !isDarkMode.value | |
} | |
// 切换Vertex AI配置 | |
async function toggleVertex() { | |
try { | |
const newValue = !config.value.enableVertex | |
await updateConfig('enableVertex', newValue, '123') // 使用默认密码 | |
// 更新本地状态 | |
config.value.enableVertex = newValue | |
} catch (error) { | |
console.error('切换Vertex AI失败:', error) | |
} | |
} | |
// 更新配置项 | |
async function updateConfig(key, value, password) { | |
const backendStore = useBackendStore() | |
try { | |
// 将驼峰命名转换为下划线命名 | |
const snakeCaseKey = key.replace(/[A-Z]/g, letter => `_${letter.toLowerCase()}`); | |
const response = await backendStore.apiRequest('api/update-config', { | |
method: 'POST', | |
body: JSON.stringify({ | |
key: snakeCaseKey, | |
value, | |
password | |
}) | |
}) | |
const data = await response.json() | |
return data | |
} catch (error) { | |
console.error('更新配置失败:', error) | |
throw error | |
} | |
} | |
return { | |
status, | |
config, | |
apiKeyStats, | |
logs, | |
isRefreshing, | |
timeSeriesData, // 导出时间序列数据 | |
fetchDashboardData, | |
selectedModel, | |
availableModels, | |
setSelectedModel, | |
isDarkMode, | |
toggleDarkMode, | |
updateConfig, | |
toggleVertex, | |
isConfigLoaded | |
} | |
}) |