feat: add provider duplicate functionality in edit mode

Add a duplicate button next to the drag handle in edit mode that allows users to quickly copy existing provider configurations.

- Add Copy icon button in ProviderCard next to drag handle
- Implement handleDuplicateProvider in App.tsx with deep cloning
- Copy all provider settings (settingsConfig, websiteUrl, category, meta)
- Auto-generate new ID and timestamp, omit sortIndex for natural sorting
- Append " copy" to duplicated provider name
- Add i18n support (zh: "复制", en: "Duplicate")
- Wire onDuplicate callback through ProviderList to ProviderCard

The duplicated provider will appear below the original provider in the list, sorted by creation time.
This commit is contained in:
Jason
2025-10-24 11:56:18 +08:00
parent 07787a2ee1
commit fb0dc5b186
5 changed files with 48 additions and 5 deletions

View File

@@ -20,6 +20,7 @@ interface ProviderListProps {
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;
@@ -34,6 +35,7 @@ export function ProviderList({
onSwitch,
onEdit,
onDelete,
onDuplicate,
onConfigureUsage,
onOpenWebsite,
onCreate,
@@ -82,6 +84,7 @@ export function ProviderList({
onSwitch={onSwitch}
onEdit={onEdit}
onDelete={onDelete}
onDuplicate={onDuplicate}
onConfigureUsage={onConfigureUsage}
onOpenWebsite={onOpenWebsite}
/>
@@ -100,6 +103,7 @@ interface SortableProviderCardProps {
onSwitch: (provider: Provider) => void;
onEdit: (provider: Provider) => void;
onDelete: (provider: Provider) => void;
onDuplicate: (provider: Provider) => void;
onConfigureUsage?: (provider: Provider) => void;
onOpenWebsite: (url: string) => void;
}
@@ -112,6 +116,7 @@ function SortableProviderCard({
onSwitch,
onEdit,
onDelete,
onDuplicate,
onConfigureUsage,
onOpenWebsite,
}: SortableProviderCardProps) {
@@ -139,6 +144,7 @@ function SortableProviderCard({
onSwitch={onSwitch}
onEdit={onEdit}
onDelete={onDelete}
onDuplicate={onDuplicate}
onConfigureUsage={
onConfigureUsage ? (item) => onConfigureUsage(item) : () => undefined
}