mirror of
https://github.com/farion1231/cc-switch.git
synced 2026-07-29 01:25:33 +08:00
395783e22a
* feat(ui): add color prop support to ProviderIcon component * feat(health): add stream check core functionality Add new stream-based health check module to replace model_test: - Add stream_check command layer with single and batch provider checks - Add stream_check DAO layer for config and log persistence - Add stream_check service layer with retry mechanism and health status evaluation - Add frontend HealthStatusIndicator component - Add frontend useStreamCheck hook This provides more comprehensive health checking capabilities. * refactor(health): replace model_test with stream_check Replace model_test module with stream_check across the codebase: - Remove model_test command and service modules - Update command registry in lib.rs to use stream_check commands - Update module exports in commands/mod.rs and services/mod.rs - Remove frontend useModelTest hook - Update stream_check command implementation This refactoring provides clearer naming and better separation of concerns. * refactor(db): clean up unused database tables and optimize schema Remove deprecated and unused database tables: - Remove proxy_usage table (replaced by proxy_request_logs) - Remove usage_daily_stats table (aggregation done on-the-fly) - Rename model_test_logs to stream_check_logs with updated schema - Remove related DAO methods for proxy_usage - Update usage_stats service to use proxy_request_logs only - Refactor usage_script to work with new schema This simplifies the database schema and removes redundant data storage. * refactor(ui): update frontend components for stream check Update frontend components to use stream check API: - Refactor ModelTestConfigPanel to use stream check config - Update API layer to use stream_check commands - Add HealthStatus type and StreamCheckResult interface - Update ProviderList to use new health check integration - Update AutoFailoverConfigPanel with stream check references - Improve UI layout and configuration options This completes the frontend migration from model_test to stream_check. * feat(health): add configurable test models and reasoning effort support Enhance stream check service with configurable test models: - Add claude_model, codex_model, gemini_model to StreamCheckConfig - Support reasoning effort syntax (model@level or model#level) - Parse and apply reasoning_effort for OpenAI-compatible models - Remove hardcoded model names from check functions - Add unit tests for model parsing logic - Remove obsolete model_test source files This allows users to customize which models are used for health checks.
186 lines
4.8 KiB
TypeScript
186 lines
4.8 KiB
TypeScript
import { CSS } from "@dnd-kit/utilities";
|
|
import { DndContext, closestCenter } from "@dnd-kit/core";
|
|
import {
|
|
SortableContext,
|
|
useSortable,
|
|
verticalListSortingStrategy,
|
|
} from "@dnd-kit/sortable";
|
|
import type { CSSProperties } from "react";
|
|
import type { Provider } from "@/types";
|
|
import type { AppId } from "@/lib/api";
|
|
import { useDragSort } from "@/hooks/useDragSort";
|
|
import { useStreamCheck } from "@/hooks/useStreamCheck";
|
|
import { ProviderCard } from "@/components/providers/ProviderCard";
|
|
import { ProviderEmptyState } from "@/components/providers/ProviderEmptyState";
|
|
|
|
interface ProviderListProps {
|
|
providers: Record<string, Provider>;
|
|
currentProviderId: string;
|
|
appId: AppId;
|
|
onSwitch: (provider: Provider) => void;
|
|
onEdit: (provider: Provider) => void;
|
|
onDelete: (provider: Provider) => void;
|
|
onDuplicate: (provider: Provider) => void;
|
|
onConfigureUsage?: (provider: Provider) => void;
|
|
onOpenWebsite: (url: string) => void;
|
|
onCreate?: () => void;
|
|
isLoading?: boolean;
|
|
isProxyRunning?: boolean; // 代理服务运行状态
|
|
isProxyTakeover?: boolean; // 代理接管模式(Live配置已被接管)
|
|
}
|
|
|
|
export function ProviderList({
|
|
providers,
|
|
currentProviderId,
|
|
appId,
|
|
onSwitch,
|
|
onEdit,
|
|
onDelete,
|
|
onDuplicate,
|
|
onConfigureUsage,
|
|
onOpenWebsite,
|
|
onCreate,
|
|
isLoading = false,
|
|
isProxyRunning = false, // 默认值为 false
|
|
isProxyTakeover = false, // 默认值为 false
|
|
}: ProviderListProps) {
|
|
const { sortedProviders, sensors, handleDragEnd } = useDragSort(
|
|
providers,
|
|
appId,
|
|
);
|
|
|
|
// 流式健康检查
|
|
const { checkProvider, isChecking } = useStreamCheck(appId);
|
|
|
|
const handleTest = (provider: Provider) => {
|
|
checkProvider(provider.id, provider.name);
|
|
};
|
|
|
|
if (isLoading) {
|
|
return (
|
|
<div className="space-y-3">
|
|
{[0, 1, 2].map((index) => (
|
|
<div
|
|
key={index}
|
|
className="h-28 w-full rounded-lg border border-dashed border-muted-foreground/40 bg-muted/40"
|
|
/>
|
|
))}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
if (sortedProviders.length === 0) {
|
|
return <ProviderEmptyState onCreate={onCreate} />;
|
|
}
|
|
|
|
return (
|
|
<DndContext
|
|
sensors={sensors}
|
|
collisionDetection={closestCenter}
|
|
onDragEnd={handleDragEnd}
|
|
>
|
|
<SortableContext
|
|
items={sortedProviders.map((provider) => provider.id)}
|
|
strategy={verticalListSortingStrategy}
|
|
>
|
|
<div
|
|
className="space-y-3 animate-slide-up"
|
|
style={{ animationDelay: "0.1s" }}
|
|
>
|
|
{sortedProviders.map((provider) => (
|
|
<SortableProviderCard
|
|
key={provider.id}
|
|
provider={provider}
|
|
isCurrent={provider.id === currentProviderId}
|
|
appId={appId}
|
|
onSwitch={onSwitch}
|
|
onEdit={onEdit}
|
|
onDelete={onDelete}
|
|
onDuplicate={onDuplicate}
|
|
onConfigureUsage={onConfigureUsage}
|
|
onOpenWebsite={onOpenWebsite}
|
|
onTest={handleTest}
|
|
isTesting={isChecking(provider.id)}
|
|
isProxyRunning={isProxyRunning}
|
|
isProxyTakeover={isProxyTakeover}
|
|
/>
|
|
))}
|
|
</div>
|
|
</SortableContext>
|
|
</DndContext>
|
|
);
|
|
}
|
|
|
|
interface SortableProviderCardProps {
|
|
provider: Provider;
|
|
isCurrent: boolean;
|
|
appId: AppId;
|
|
onSwitch: (provider: Provider) => void;
|
|
onEdit: (provider: Provider) => void;
|
|
onDelete: (provider: Provider) => void;
|
|
onDuplicate: (provider: Provider) => void;
|
|
onConfigureUsage?: (provider: Provider) => void;
|
|
onOpenWebsite: (url: string) => void;
|
|
onTest: (provider: Provider) => void;
|
|
isTesting: boolean;
|
|
isProxyRunning: boolean;
|
|
isProxyTakeover: boolean;
|
|
}
|
|
|
|
function SortableProviderCard({
|
|
provider,
|
|
isCurrent,
|
|
appId,
|
|
onSwitch,
|
|
onEdit,
|
|
onDelete,
|
|
onDuplicate,
|
|
onConfigureUsage,
|
|
onOpenWebsite,
|
|
onTest,
|
|
isTesting,
|
|
isProxyRunning,
|
|
isProxyTakeover,
|
|
}: SortableProviderCardProps) {
|
|
const {
|
|
setNodeRef,
|
|
attributes,
|
|
listeners,
|
|
transform,
|
|
transition,
|
|
isDragging,
|
|
} = useSortable({ id: provider.id });
|
|
|
|
const style: CSSProperties = {
|
|
transform: CSS.Transform.toString(transform),
|
|
transition,
|
|
};
|
|
|
|
return (
|
|
<div ref={setNodeRef} style={style}>
|
|
<ProviderCard
|
|
provider={provider}
|
|
isCurrent={isCurrent}
|
|
appId={appId}
|
|
onSwitch={onSwitch}
|
|
onEdit={onEdit}
|
|
onDelete={onDelete}
|
|
onDuplicate={onDuplicate}
|
|
onConfigureUsage={
|
|
onConfigureUsage ? (item) => onConfigureUsage(item) : () => undefined
|
|
}
|
|
onOpenWebsite={onOpenWebsite}
|
|
onTest={onTest}
|
|
isTesting={isTesting}
|
|
isProxyRunning={isProxyRunning}
|
|
isProxyTakeover={isProxyTakeover}
|
|
dragHandleProps={{
|
|
attributes,
|
|
listeners,
|
|
isDragging,
|
|
}}
|
|
/>
|
|
</div>
|
|
);
|
|
}
|