feat: 实现账户批量导出功能和界面优化
- 新增批量导出功能,支持text模式导出账户数据 - 添加导出弹窗,支持文本全选和文件下载 - 移动刷新按钮到全局位置,统一刷新账户和统计数据 - 在统计卡片中将已导出状态计入可用账户 - 创建自定义确认对话框替换系统confirm弹窗 - 统一按钮尺寸,修复刷新和上传按钮大小不一致 - 添加已导出状态的中文映射和样式 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
		
							
								
								
									
										127
									
								
								components/ui/confirm-dialog.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										127
									
								
								components/ui/confirm-dialog.tsx
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,127 @@ | ||||
| "use client"; | ||||
|  | ||||
| import { useState, useEffect } from 'react'; | ||||
| import { Button } from '@/components/ui/button'; | ||||
| import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from '@/components/ui/dialog'; | ||||
| import { AlertTriangle } from 'lucide-react'; | ||||
|  | ||||
| interface ConfirmDialogProps { | ||||
|   open: boolean; | ||||
|   onOpenChange: (open: boolean) => void; | ||||
|   title: string; | ||||
|   description: string; | ||||
|   confirmText?: string; | ||||
|   cancelText?: string; | ||||
|   variant?: 'default' | 'destructive'; | ||||
|   onConfirm: () => void; | ||||
|   onCancel?: () => void; | ||||
| } | ||||
|  | ||||
| export function ConfirmDialog({ | ||||
|   open, | ||||
|   onOpenChange, | ||||
|   title, | ||||
|   description, | ||||
|   confirmText = '确认', | ||||
|   cancelText = '取消', | ||||
|   variant = 'default', | ||||
|   onConfirm, | ||||
|   onCancel | ||||
| }: ConfirmDialogProps) { | ||||
|   const handleConfirm = () => { | ||||
|     onConfirm(); | ||||
|     onOpenChange(false); | ||||
|   }; | ||||
|  | ||||
|   const handleCancel = () => { | ||||
|     onCancel?.(); | ||||
|     onOpenChange(false); | ||||
|   }; | ||||
|  | ||||
|   return ( | ||||
|     <Dialog open={open} onOpenChange={onOpenChange}> | ||||
|       <DialogContent className="sm:max-w-[425px]"> | ||||
|         <DialogHeader> | ||||
|           <DialogTitle className="flex items-center gap-2"> | ||||
|             {variant === 'destructive' && ( | ||||
|               <AlertTriangle className="h-5 w-5 text-destructive" /> | ||||
|             )} | ||||
|             {title} | ||||
|           </DialogTitle> | ||||
|           <DialogDescription> | ||||
|             {description} | ||||
|           </DialogDescription> | ||||
|         </DialogHeader> | ||||
|         <DialogFooter> | ||||
|           <Button variant="outline" onClick={handleCancel}> | ||||
|             {cancelText} | ||||
|           </Button> | ||||
|           <Button  | ||||
|             variant={variant === 'destructive' ? 'destructive' : 'default'} | ||||
|             onClick={handleConfirm} | ||||
|           > | ||||
|             {confirmText} | ||||
|           </Button> | ||||
|         </DialogFooter> | ||||
|       </DialogContent> | ||||
|     </Dialog> | ||||
|   ); | ||||
| } | ||||
|  | ||||
| // Hook for easier usage | ||||
| export function useConfirmDialog() { | ||||
|   const [confirmDialog, setConfirmDialog] = useState<{ | ||||
|     open: boolean; | ||||
|     title: string; | ||||
|     description: string; | ||||
|     confirmText?: string; | ||||
|     cancelText?: string; | ||||
|     variant?: 'default' | 'destructive'; | ||||
|     onConfirm: () => void; | ||||
|     onCancel?: () => void; | ||||
|   }>({ | ||||
|     open: false, | ||||
|     title: '', | ||||
|     description: '', | ||||
|     onConfirm: () => {} | ||||
|   }); | ||||
|  | ||||
|   const showConfirm = (options: { | ||||
|     title: string; | ||||
|     description: string; | ||||
|     confirmText?: string; | ||||
|     cancelText?: string; | ||||
|     variant?: 'default' | 'destructive'; | ||||
|     onConfirm: () => void; | ||||
|     onCancel?: () => void; | ||||
|   }) => { | ||||
|     setConfirmDialog({ | ||||
|       ...options, | ||||
|       open: true | ||||
|     }); | ||||
|   }; | ||||
|  | ||||
|   const hideConfirm = () => { | ||||
|     setConfirmDialog(prev => ({ ...prev, open: false })); | ||||
|   }; | ||||
|  | ||||
|   const ConfirmDialogComponent = () => ( | ||||
|     <ConfirmDialog | ||||
|       open={confirmDialog.open} | ||||
|       onOpenChange={hideConfirm} | ||||
|       title={confirmDialog.title} | ||||
|       description={confirmDialog.description} | ||||
|       confirmText={confirmDialog.confirmText} | ||||
|       cancelText={confirmDialog.cancelText} | ||||
|       variant={confirmDialog.variant} | ||||
|       onConfirm={confirmDialog.onConfirm} | ||||
|       onCancel={confirmDialog.onCancel} | ||||
|     /> | ||||
|   ); | ||||
|  | ||||
|   return { | ||||
|     showConfirm, | ||||
|     hideConfirm, | ||||
|     ConfirmDialogComponent | ||||
|   }; | ||||
| } | ||||
		Reference in New Issue
	
	Block a user