mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-02-12 02:37:45 +08:00
feat: 增加对非数组值的处理,优化数组、文件和标签渲染器
This commit is contained in:
@@ -58,6 +58,10 @@ function StringRenderer({ value, className }: { value: string; className?: strin
|
|||||||
}
|
}
|
||||||
|
|
||||||
function ArrayRenderer({ value, className }: { value: unknown[]; className?: string }) {
|
function ArrayRenderer({ value, className }: { value: unknown[]; className?: string }) {
|
||||||
|
if (!Array.isArray(value)) {
|
||||||
|
return <FieldRenderer value={value} type="auto" className={className} />;
|
||||||
|
}
|
||||||
|
|
||||||
if (value.length === 0) {
|
if (value.length === 0) {
|
||||||
return <span className="text-muted-foreground italic">Empty</span>;
|
return <span className="text-muted-foreground italic">Empty</span>;
|
||||||
}
|
}
|
||||||
@@ -98,6 +102,10 @@ function ObjectRenderer({ value, className }: { value: Record<string, unknown>;
|
|||||||
}
|
}
|
||||||
|
|
||||||
function FilesRenderer({ value, className }: { value: Array<{ path: string }>; className?: string }) {
|
function FilesRenderer({ value, className }: { value: Array<{ path: string }>; className?: string }) {
|
||||||
|
if (!Array.isArray(value)) {
|
||||||
|
return <FieldRenderer value={value} type="auto" className={className} />;
|
||||||
|
}
|
||||||
|
|
||||||
if (value.length === 0) {
|
if (value.length === 0) {
|
||||||
return <span className="text-muted-foreground italic">No files</span>;
|
return <span className="text-muted-foreground italic">No files</span>;
|
||||||
}
|
}
|
||||||
@@ -118,6 +126,10 @@ function FilesRenderer({ value, className }: { value: Array<{ path: string }>; c
|
|||||||
}
|
}
|
||||||
|
|
||||||
function TagsRenderer({ value, className }: { value: string[]; className?: string }) {
|
function TagsRenderer({ value, className }: { value: string[]; className?: string }) {
|
||||||
|
if (!Array.isArray(value)) {
|
||||||
|
return <FieldRenderer value={value} type="auto" className={className} />;
|
||||||
|
}
|
||||||
|
|
||||||
if (value.length === 0) {
|
if (value.length === 0) {
|
||||||
return <span className="text-muted-foreground italic">No tags</span>;
|
return <span className="text-muted-foreground italic">No tags</span>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import {
|
|||||||
RefreshCw,
|
RefreshCw,
|
||||||
} from 'lucide-react';
|
} from 'lucide-react';
|
||||||
import { Button } from '@/components/ui/Button';
|
import { Button } from '@/components/ui/Button';
|
||||||
import { TabsNavigation, type TabItem } from '@/components/ui/TabsNavigation';
|
import { TabsNavigation } from '@/components/ui/TabsNavigation';
|
||||||
import {
|
import {
|
||||||
ProviderList,
|
ProviderList,
|
||||||
ProviderModal,
|
ProviderModal,
|
||||||
@@ -25,7 +25,7 @@ import {
|
|||||||
ManageModelsModal,
|
ManageModelsModal,
|
||||||
} from '@/components/api-settings';
|
} from '@/components/api-settings';
|
||||||
import { ConfigSync } from '@/components/shared';
|
import { ConfigSync } from '@/components/shared';
|
||||||
import { useProviders, useEndpoints, useModelPools, useCliSettings } from '@/hooks/useApiSettings';
|
import { useProviders, useEndpoints, useModelPools, useCliSettings, useSyncApiConfig } from '@/hooks/useApiSettings';
|
||||||
import { useNotifications } from '@/hooks/useNotifications';
|
import { useNotifications } from '@/hooks/useNotifications';
|
||||||
|
|
||||||
// Tab type definitions
|
// Tab type definitions
|
||||||
@@ -35,6 +35,7 @@ export function ApiSettingsPage() {
|
|||||||
const { formatMessage } = useIntl();
|
const { formatMessage } = useIntl();
|
||||||
const { success, error } = useNotifications();
|
const { success, error } = useNotifications();
|
||||||
const [activeTab, setActiveTab] = useState<TabType>('providers');
|
const [activeTab, setActiveTab] = useState<TabType>('providers');
|
||||||
|
const syncMutation = useSyncApiConfig();
|
||||||
|
|
||||||
// Get providers, endpoints, model pools, and CLI settings data
|
// Get providers, endpoints, model pools, and CLI settings data
|
||||||
const { providers } = useProviders();
|
const { providers } = useProviders();
|
||||||
@@ -170,10 +171,19 @@ export function ApiSettingsPage() {
|
|||||||
|
|
||||||
// Sync to CodexLens handler
|
// Sync to CodexLens handler
|
||||||
const handleSyncToCodexLens = async (providerId: string) => {
|
const handleSyncToCodexLens = async (providerId: string) => {
|
||||||
|
const providerName = providers.find((p) => p.id === providerId)?.name ?? providerId;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// TODO: Implement actual sync API call
|
const result = await syncMutation.mutateAsync();
|
||||||
// For now, just show a success message
|
const messageParts = [
|
||||||
success(formatMessage({ id: 'apiSettings.messages.configSynced' }));
|
providerName,
|
||||||
|
result.yamlPath ?? result.message,
|
||||||
|
].filter(Boolean);
|
||||||
|
|
||||||
|
success(
|
||||||
|
formatMessage({ id: 'apiSettings.messages.configSynced' }),
|
||||||
|
messageParts.length > 0 ? messageParts.join('\n') : undefined
|
||||||
|
);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
error(formatMessage({ id: 'apiSettings.providers.saveError' }));
|
error(formatMessage({ id: 'apiSettings.providers.saveError' }));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import {
|
|||||||
Package,
|
Package,
|
||||||
Home,
|
Home,
|
||||||
Folder,
|
Folder,
|
||||||
|
FolderOpen,
|
||||||
Calendar,
|
Calendar,
|
||||||
File,
|
File,
|
||||||
ArrowUpCircle,
|
ArrowUpCircle,
|
||||||
@@ -36,6 +37,7 @@ import { Input } from '@/components/ui/Input';
|
|||||||
import { Badge } from '@/components/ui/Badge';
|
import { Badge } from '@/components/ui/Badge';
|
||||||
import { ThemeSelector } from '@/components/shared/ThemeSelector';
|
import { ThemeSelector } from '@/components/shared/ThemeSelector';
|
||||||
import { useTheme } from '@/hooks';
|
import { useTheme } from '@/hooks';
|
||||||
|
import { toast } from 'sonner';
|
||||||
import { useConfigStore, selectCliTools, selectDefaultCliTool, selectUserPreferences } from '@/stores/configStore';
|
import { useConfigStore, selectCliTools, selectDefaultCliTool, selectUserPreferences } from '@/stores/configStore';
|
||||||
import type { CliToolConfig, UserPreferences } from '@/types/store';
|
import type { CliToolConfig, UserPreferences } from '@/types/store';
|
||||||
import { cn } from '@/lib/utils';
|
import { cn } from '@/lib/utils';
|
||||||
@@ -60,9 +62,6 @@ import {
|
|||||||
const ENV_FILE_TOOLS = new Set(['gemini', 'qwen', 'opencode']);
|
const ENV_FILE_TOOLS = new Set(['gemini', 'qwen', 'opencode']);
|
||||||
/** Tools that use --settings for Claude CLI settings file */
|
/** Tools that use --settings for Claude CLI settings file */
|
||||||
const SETTINGS_FILE_TOOLS = new Set(['claude']);
|
const SETTINGS_FILE_TOOLS = new Set(['claude']);
|
||||||
/** Tools that don't need any config file */
|
|
||||||
const NO_CONFIG_FILE_TOOLS = new Set(['codex']);
|
|
||||||
|
|
||||||
function getConfigFileType(toolId: string): 'envFile' | 'settingsFile' | 'none' {
|
function getConfigFileType(toolId: string): 'envFile' | 'settingsFile' | 'none' {
|
||||||
if (ENV_FILE_TOOLS.has(toolId)) return 'envFile';
|
if (ENV_FILE_TOOLS.has(toolId)) return 'envFile';
|
||||||
if (SETTINGS_FILE_TOOLS.has(toolId)) return 'settingsFile';
|
if (SETTINGS_FILE_TOOLS.has(toolId)) return 'settingsFile';
|
||||||
@@ -874,18 +873,13 @@ export function SettingsPage() {
|
|||||||
throw new Error(`HTTP ${res.status}`);
|
throw new Error(`HTTP ${res.status}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Show success notification via a brief visual indicator
|
toast.success(formatMessage({ id: 'settings.cliTools.configSaved' }), {
|
||||||
const toast = document.createElement('div');
|
description: toolId,
|
||||||
toast.className = 'fixed bottom-4 right-4 z-50 bg-green-600 text-white px-4 py-2 rounded-lg shadow-lg text-sm animate-in fade-in slide-in-from-bottom-2';
|
});
|
||||||
toast.textContent = formatMessage({ id: 'settings.cliTools.configSaved' });
|
|
||||||
document.body.appendChild(toast);
|
|
||||||
setTimeout(() => toast.remove(), 3000);
|
|
||||||
} catch {
|
} catch {
|
||||||
const toast = document.createElement('div');
|
toast.error(formatMessage({ id: 'settings.cliTools.configSaveError' }), {
|
||||||
toast.className = 'fixed bottom-4 right-4 z-50 bg-red-600 text-white px-4 py-2 rounded-lg shadow-lg text-sm animate-in fade-in slide-in-from-bottom-2';
|
description: toolId,
|
||||||
toast.textContent = formatMessage({ id: 'settings.cliTools.configSaveError' });
|
});
|
||||||
document.body.appendChild(toast);
|
|
||||||
setTimeout(() => toast.remove(), 4000);
|
|
||||||
} finally {
|
} finally {
|
||||||
setSavingTools((prev) => {
|
setSavingTools((prev) => {
|
||||||
const next = new Set(prev);
|
const next = new Set(prev);
|
||||||
|
|||||||
@@ -43,6 +43,13 @@ const defaultCliTools: Record<string, CliToolConfig> = {
|
|||||||
tags: [],
|
tags: [],
|
||||||
type: 'builtin',
|
type: 'builtin',
|
||||||
},
|
},
|
||||||
|
opencode: {
|
||||||
|
enabled: true,
|
||||||
|
primaryModel: 'opencode/glm-4.7-free',
|
||||||
|
secondaryModel: 'opencode/glm-4.7-free',
|
||||||
|
tags: [],
|
||||||
|
type: 'builtin',
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
// Default API endpoints
|
// Default API endpoints
|
||||||
|
|||||||
Reference in New Issue
Block a user