mirror of
https://github.com/farion1231/cc-switch.git
synced 2026-07-27 16:26:16 +08:00
636a1e2c60
Add icon customization support to provider management interface: ## Type System Updates ### Provider Interface (src/types.ts) - Add optional `icon` field for icon name (e.g., "openai", "anthropic") - Add optional `iconColor` field for hex color (e.g., "#00A67E") ### Form Schema (src/lib/schemas/provider.ts) - Extend providerSchema with icon and iconColor optional fields - Maintain backward compatibility with existing providers ## UI Components ### ProviderCard (src/components/providers/ProviderCard.tsx) - Display ProviderIcon alongside provider name - Add icon container with hover animation effect - Adjust layout spacing for icon placement - Update translate offsets for action buttons ### BasicFormFields (src/components/providers/forms/BasicFormFields.tsx) - Add icon preview section showing current selection - Implement fullscreen icon picker dialog - Auto-apply default color from icon metadata on selection - Display provider name and icon status in preview ### AddProviderDialog & EditProviderDialog - Pass icon fields through form submission - Preserve icon data during provider updates This enables users to visually distinguish providers in the list with custom icons, improving UX for multi-provider setups.
61 lines
1.8 KiB
TypeScript
61 lines
1.8 KiB
TypeScript
import { z } from "zod";
|
||
|
||
/**
|
||
* 解析 JSON 语法错误,提取位置信息
|
||
*/
|
||
function parseJsonError(error: unknown): string {
|
||
if (!(error instanceof SyntaxError)) {
|
||
return "配置 JSON 格式错误";
|
||
}
|
||
|
||
const message = error.message;
|
||
|
||
// 提取位置信息:Chrome/V8: "Unexpected token ... in JSON at position 123"
|
||
const positionMatch = message.match(/at position (\d+)/i);
|
||
if (positionMatch) {
|
||
const position = parseInt(positionMatch[1], 10);
|
||
return `JSON 格式错误:${message.split(" in JSON")[0]}(位置:${position})`;
|
||
}
|
||
|
||
// Firefox: "JSON.parse: unexpected character at line 1 column 23"
|
||
const lineColumnMatch = message.match(/line (\d+) column (\d+)/i);
|
||
if (lineColumnMatch) {
|
||
const line = lineColumnMatch[1];
|
||
const column = lineColumnMatch[2];
|
||
return `JSON 格式错误:第 ${line} 行,第 ${column} 列`;
|
||
}
|
||
|
||
// 通用情况:提取关键错误信息
|
||
const cleanMessage = message
|
||
.replace(/^JSON\.parse:\s*/i, "")
|
||
.replace(/^Unexpected\s+/i, "意外的 ")
|
||
.replace(/token/gi, "符号")
|
||
.replace(/Expected/gi, "预期");
|
||
|
||
return `JSON 格式错误:${cleanMessage}`;
|
||
}
|
||
|
||
export const providerSchema = z.object({
|
||
name: z.string().min(1, "请填写供应商名称"),
|
||
websiteUrl: z.string().url("请输入有效的网址").optional().or(z.literal("")),
|
||
notes: z.string().optional(),
|
||
settingsConfig: z
|
||
.string()
|
||
.min(1, "请填写配置内容")
|
||
.superRefine((value, ctx) => {
|
||
try {
|
||
JSON.parse(value);
|
||
} catch (error) {
|
||
ctx.addIssue({
|
||
code: z.ZodIssueCode.custom,
|
||
message: parseJsonError(error),
|
||
});
|
||
}
|
||
}),
|
||
// 图标配置
|
||
icon: z.string().optional(),
|
||
iconColor: z.string().optional(),
|
||
});
|
||
|
||
export type ProviderFormData = z.infer<typeof providerSchema>;
|