增加审批组件
This commit is contained in:
parent
fa6f700998
commit
ab89ebe994
@ -98,30 +98,44 @@ function FormExample() {
|
||||
|
||||
## 图标分类
|
||||
|
||||
组件内置了以下分类:
|
||||
组件内置了以下分类,每个分类都有代表性图标:
|
||||
|
||||
- **常用** - 常用业务图标
|
||||
- **文件与文档** - 文件相关图标
|
||||
- **用户与团队** - 用户管理图标
|
||||
- **开发与代码** - 开发工具图标
|
||||
- **数据与存储** - 数据库、存储图标
|
||||
- **网络与服务** - 网络、服务器图标
|
||||
- **时间与日历** - 时间、日期图标
|
||||
- **操作与控制** - 操作按钮图标
|
||||
- **通知与提醒** - 通知相关图标
|
||||
- **编辑与格式** - 编辑工具图标
|
||||
- **导航与箭头** - 导航、箭头图标
|
||||
- **状态与标记** - 状态指示图标
|
||||
| 分类 | 图标 | 说明 |
|
||||
|------|------|------|
|
||||
| 全部 | 📐 | 显示所有可用图标 |
|
||||
| 常用 | ✨ | 常用业务图标 |
|
||||
| 文件与文档 | 📄 | 文件相关图标 |
|
||||
| 用户与团队 | 👥 | 用户管理图标 |
|
||||
| 开发与代码 | 💻 | 开发工具图标 |
|
||||
| 数据与存储 | 💾 | 数据库、存储图标 |
|
||||
| 网络与服务 | 🖥️ | 网络、服务器图标 |
|
||||
| 时间与日历 | 📅 | 时间、日期图标 |
|
||||
| 操作与控制 | 🎛️ | 操作按钮图标 |
|
||||
| 通知与提醒 | 🔔 | 通知相关图标 |
|
||||
| 编辑与格式 | ✏️ | 编辑工具图标 |
|
||||
| 导航与箭头 | 🧭 | 导航、箭头图标 |
|
||||
| 状态与标记 | ✅ | 状态指示图标 |
|
||||
|
||||
### 分类标签特性
|
||||
|
||||
- 🎨 每个分类都有代表性图标,视觉更直观
|
||||
- 📱 响应式设计:移动端仅显示图标,桌面端显示图标+文字
|
||||
- 🔄 自动布局:标签自动换行,左对齐排列
|
||||
- ✨ 高亮显示:当前选中的分类会高亮显示
|
||||
|
||||
## 自定义配置
|
||||
|
||||
如需添加或修改分类,可编辑 `src/config/lucideIcons.ts` 文件:
|
||||
|
||||
```ts
|
||||
export const ICON_CATEGORIES = {
|
||||
'自定义分类': [
|
||||
'Icon1', 'Icon2', 'Icon3'
|
||||
],
|
||||
export const ICON_CATEGORIES: Record<string, IconCategory> = {
|
||||
'custom': {
|
||||
name: '自定义分类',
|
||||
icon: 'Star', // 分类的代表性图标
|
||||
icons: [
|
||||
'Icon1', 'Icon2', 'Icon3'
|
||||
]
|
||||
},
|
||||
// ... 其他分类
|
||||
};
|
||||
```
|
||||
|
||||
@ -8,7 +8,7 @@ import {
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
||||
import { Search } from "lucide-react";
|
||||
import { Search, LayoutGrid } from "lucide-react";
|
||||
import { searchLucideIcons, ICON_CATEGORIES } from '@/config/lucideIcons';
|
||||
import DynamicIcon from '@/components/DynamicIcon';
|
||||
|
||||
@ -55,14 +55,14 @@ const LucideIconSelect: React.FC<LucideIconSelectProps> = ({
|
||||
|
||||
return (
|
||||
<Dialog open={open} onOpenChange={onOpenChange}>
|
||||
<DialogContent className="max-w-4xl max-h-[85vh] overflow-y-auto">
|
||||
<DialogHeader>
|
||||
<DialogContent className="max-w-4xl h-[750px] max-h-[90vh] flex flex-col">
|
||||
<DialogHeader className="flex-shrink-0">
|
||||
<DialogTitle>选择图标</DialogTitle>
|
||||
</DialogHeader>
|
||||
|
||||
<div className="space-y-4">
|
||||
<div className="space-y-4 flex-1 flex flex-col overflow-hidden">
|
||||
{/* 搜索框 */}
|
||||
<div className="relative">
|
||||
<div className="relative flex-shrink-0">
|
||||
<Search className="absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" />
|
||||
<Input
|
||||
placeholder="搜索图标名称..."
|
||||
@ -73,46 +73,67 @@ const LucideIconSelect: React.FC<LucideIconSelectProps> = ({
|
||||
</div>
|
||||
|
||||
{/* 分类标签 */}
|
||||
<Tabs value={category} onValueChange={setCategory}>
|
||||
<TabsList className="w-full flex-wrap h-auto">
|
||||
<TabsTrigger value="all" className="text-xs">全部 ({iconList.length})</TabsTrigger>
|
||||
{Object.keys(ICON_CATEGORIES).map((cat) => (
|
||||
<TabsTrigger key={cat} value={cat} className="text-xs">
|
||||
{cat}
|
||||
<Tabs value={category} onValueChange={setCategory} className="flex-1 flex flex-col overflow-hidden">
|
||||
<TabsList className="w-full flex-wrap h-auto justify-start gap-1 p-1 bg-muted flex-shrink-0">
|
||||
<TabsTrigger
|
||||
value="all"
|
||||
className="flex items-center gap-1.5 text-xs data-[state=active]:bg-background"
|
||||
>
|
||||
<LayoutGrid className="h-3.5 w-3.5" />
|
||||
<span>全部</span>
|
||||
<span className="text-muted-foreground">({iconList.length})</span>
|
||||
</TabsTrigger>
|
||||
{Object.entries(ICON_CATEGORIES).map(([key, cat]) => (
|
||||
<TabsTrigger
|
||||
key={key}
|
||||
value={key}
|
||||
className="flex items-center gap-1.5 text-xs data-[state=active]:bg-background"
|
||||
title={cat.name}
|
||||
>
|
||||
<DynamicIcon name={cat.icon} className="h-3.5 w-3.5" />
|
||||
<span className="hidden sm:inline">{cat.name}</span>
|
||||
</TabsTrigger>
|
||||
))}
|
||||
</TabsList>
|
||||
|
||||
<TabsContent value={category} className="mt-4">
|
||||
{/* 图标网格 */}
|
||||
<div className="grid grid-cols-8 gap-2 max-h-[400px] overflow-y-auto p-2 border rounded-md">
|
||||
{iconList.length > 0 ? (
|
||||
iconList.map(({ name, component: Icon }) => (
|
||||
<Button
|
||||
key={name}
|
||||
variant={value === name ? "default" : "outline"}
|
||||
className="h-20 flex flex-col items-center justify-center gap-2 p-2"
|
||||
onClick={() => handleSelect(name)}
|
||||
title={name}
|
||||
>
|
||||
<Icon className="h-6 w-6" />
|
||||
<span className="text-[10px] truncate w-full text-center">
|
||||
{name}
|
||||
</span>
|
||||
</Button>
|
||||
))
|
||||
) : (
|
||||
<div className="col-span-8 text-center py-8 text-muted-foreground">
|
||||
未找到匹配的图标
|
||||
</div>
|
||||
)}
|
||||
<TabsContent value={category} className="mt-4 flex-1 overflow-hidden">
|
||||
{/* 图标网格 - 固定高度 */}
|
||||
<div className="h-full overflow-y-auto p-2 border rounded-md bg-background">
|
||||
<div className="grid grid-cols-8 gap-2">
|
||||
{iconList.length > 0 ? (
|
||||
iconList.map(({ name, component: Icon }) => (
|
||||
<Button
|
||||
key={name}
|
||||
variant={value === name ? "default" : "outline"}
|
||||
className="h-20 flex flex-col items-center justify-center gap-2 p-2"
|
||||
onClick={() => handleSelect(name)}
|
||||
title={name}
|
||||
>
|
||||
<Icon className="h-6 w-6" />
|
||||
<span className="text-[10px] truncate w-full text-center">
|
||||
{name}
|
||||
</span>
|
||||
</Button>
|
||||
))
|
||||
) : (
|
||||
<div className="col-span-8 text-center py-16 text-muted-foreground">
|
||||
<div className="flex flex-col items-center gap-3">
|
||||
<Search className="h-12 w-12 opacity-20" />
|
||||
<p className="text-sm">未找到匹配的图标</p>
|
||||
<p className="text-xs text-muted-foreground/70">
|
||||
尝试其他关键词或浏览分类
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
|
||||
{/* 当前选中 */}
|
||||
{value && (
|
||||
<div className="flex items-center gap-2 p-3 border rounded-md bg-muted/50">
|
||||
<div className="flex items-center gap-2 p-3 border rounded-md bg-muted/50 flex-shrink-0">
|
||||
<span className="text-sm text-muted-foreground">当前选中:</span>
|
||||
<div className="flex items-center gap-2">
|
||||
<DynamicIcon name={value} className="h-5 w-5" />
|
||||
|
||||
@ -20,58 +20,116 @@ export const getLucideIcon = (iconName: string): LucideIcon | null => {
|
||||
return (icons[iconName as keyof typeof icons] as LucideIcon) || null;
|
||||
};
|
||||
|
||||
/**
|
||||
* 图标分类配置
|
||||
* 每个分类包含名称、代表性图标和图标列表
|
||||
*/
|
||||
export interface IconCategory {
|
||||
name: string;
|
||||
icon: string;
|
||||
icons: string[];
|
||||
}
|
||||
|
||||
/**
|
||||
* 常用图标分类
|
||||
*/
|
||||
export const ICON_CATEGORIES = {
|
||||
'常用': [
|
||||
'FolderKanban', 'Workflow', 'Settings', 'Users', 'Calendar',
|
||||
'Clock', 'Database', 'Server', 'Cloud', 'Package'
|
||||
],
|
||||
'文件与文档': [
|
||||
'File', 'FileText', 'Folder', 'FolderOpen', 'Files',
|
||||
'FileJson', 'FileCode', 'FilePlus', 'FileEdit'
|
||||
],
|
||||
'用户与团队': [
|
||||
'User', 'Users', 'UserPlus', 'UserCheck', 'UserCog',
|
||||
'Shield', 'ShieldCheck', 'Contact'
|
||||
],
|
||||
'开发与代码': [
|
||||
'Code', 'Terminal', 'GitBranch', 'Github', 'GitFork',
|
||||
'GitCommit', 'GitPullRequest', 'Bug', 'Braces'
|
||||
],
|
||||
'数据与存储': [
|
||||
'Database', 'HardDrive', 'Save', 'Download', 'Upload',
|
||||
'Archive', 'Package', 'Inbox', 'FolderSync'
|
||||
],
|
||||
'网络与服务': [
|
||||
'Server', 'Cloud', 'CloudDownload', 'CloudUpload', 'Globe',
|
||||
'Wifi', 'Zap', 'Activity', 'TrendingUp'
|
||||
],
|
||||
'时间与日历': [
|
||||
'Calendar', 'CalendarDays', 'Clock', 'Timer', 'AlarmClock',
|
||||
'History', 'CalendarCheck', 'CalendarPlus'
|
||||
],
|
||||
'操作与控制': [
|
||||
'Play', 'Pause', 'Stop', 'RotateCw', 'RefreshCw',
|
||||
'Power', 'Settings', 'Sliders', 'ToggleLeft'
|
||||
],
|
||||
'通知与提醒': [
|
||||
'Bell', 'BellRing', 'MessageSquare', 'Mail', 'Inbox',
|
||||
'AlertCircle', 'AlertTriangle', 'Info', 'CheckCircle'
|
||||
],
|
||||
'编辑与格式': [
|
||||
'Edit', 'Edit2', 'Edit3', 'Pencil', 'Trash2',
|
||||
'Copy', 'Clipboard', 'Scissors', 'FileEdit'
|
||||
],
|
||||
'导航与箭头': [
|
||||
'ArrowRight', 'ArrowLeft', 'ArrowUp', 'ArrowDown', 'ChevronRight',
|
||||
'ChevronLeft', 'ChevronUp', 'ChevronDown', 'Home', 'Menu'
|
||||
],
|
||||
'状态与标记': [
|
||||
'Check', 'CheckCircle', 'CheckCircle2', 'X', 'XCircle',
|
||||
'AlertCircle', 'AlertTriangle', 'HelpCircle', 'Plus', 'Minus'
|
||||
]
|
||||
export const ICON_CATEGORIES: Record<string, IconCategory> = {
|
||||
'common': {
|
||||
name: '常用',
|
||||
icon: 'Sparkles',
|
||||
icons: [
|
||||
'FolderKanban', 'Workflow', 'Settings', 'Users', 'Calendar',
|
||||
'Clock', 'Database', 'Server', 'Cloud', 'Package'
|
||||
]
|
||||
},
|
||||
'file': {
|
||||
name: '文件与文档',
|
||||
icon: 'FileText',
|
||||
icons: [
|
||||
'File', 'FileText', 'Folder', 'FolderOpen', 'Files',
|
||||
'FileJson', 'FileCode', 'FilePlus', 'FileEdit'
|
||||
]
|
||||
},
|
||||
'user': {
|
||||
name: '用户与团队',
|
||||
icon: 'Users',
|
||||
icons: [
|
||||
'User', 'Users', 'UserPlus', 'UserCheck', 'UserCog',
|
||||
'Shield', 'ShieldCheck', 'Contact'
|
||||
]
|
||||
},
|
||||
'code': {
|
||||
name: '开发与代码',
|
||||
icon: 'Code',
|
||||
icons: [
|
||||
'Code', 'Terminal', 'GitBranch', 'Github', 'GitFork',
|
||||
'GitCommit', 'GitPullRequest', 'Bug', 'Braces'
|
||||
]
|
||||
},
|
||||
'data': {
|
||||
name: '数据与存储',
|
||||
icon: 'Database',
|
||||
icons: [
|
||||
'Database', 'HardDrive', 'Save', 'Download', 'Upload',
|
||||
'Archive', 'Package', 'Inbox', 'FolderSync'
|
||||
]
|
||||
},
|
||||
'network': {
|
||||
name: '网络与服务',
|
||||
icon: 'Server',
|
||||
icons: [
|
||||
'Server', 'Cloud', 'CloudDownload', 'CloudUpload', 'Globe',
|
||||
'Wifi', 'Zap', 'Activity', 'TrendingUp'
|
||||
]
|
||||
},
|
||||
'time': {
|
||||
name: '时间与日历',
|
||||
icon: 'Calendar',
|
||||
icons: [
|
||||
'Calendar', 'CalendarDays', 'Clock', 'Timer', 'AlarmClock',
|
||||
'History', 'CalendarCheck', 'CalendarPlus'
|
||||
]
|
||||
},
|
||||
'control': {
|
||||
name: '操作与控制',
|
||||
icon: 'Sliders',
|
||||
icons: [
|
||||
'Play', 'Pause', 'Stop', 'RotateCw', 'RefreshCw',
|
||||
'Power', 'Settings', 'Sliders', 'ToggleLeft'
|
||||
]
|
||||
},
|
||||
'notification': {
|
||||
name: '通知与提醒',
|
||||
icon: 'Bell',
|
||||
icons: [
|
||||
'Bell', 'BellRing', 'MessageSquare', 'Mail', 'Inbox',
|
||||
'AlertCircle', 'AlertTriangle', 'Info', 'CheckCircle'
|
||||
]
|
||||
},
|
||||
'edit': {
|
||||
name: '编辑与格式',
|
||||
icon: 'Edit',
|
||||
icons: [
|
||||
'Edit', 'Edit2', 'Edit3', 'Pencil', 'Trash2',
|
||||
'Copy', 'Clipboard', 'Scissors', 'FileEdit'
|
||||
]
|
||||
},
|
||||
'navigation': {
|
||||
name: '导航与箭头',
|
||||
icon: 'Navigation',
|
||||
icons: [
|
||||
'ArrowRight', 'ArrowLeft', 'ArrowUp', 'ArrowDown', 'ChevronRight',
|
||||
'ChevronLeft', 'ChevronUp', 'ChevronDown', 'Home', 'Menu'
|
||||
]
|
||||
},
|
||||
'status': {
|
||||
name: '状态与标记',
|
||||
icon: 'CheckCircle2',
|
||||
icons: [
|
||||
'Check', 'CheckCircle', 'CheckCircle2', 'X', 'XCircle',
|
||||
'AlertCircle', 'AlertTriangle', 'HelpCircle', 'Plus', 'Minus'
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@ -87,8 +145,10 @@ export const searchLucideIcons = (searchTerm: string, category?: string) => {
|
||||
|
||||
// 按分类过滤
|
||||
if (category && category !== 'all') {
|
||||
const categoryIcons = ICON_CATEGORIES[category as keyof typeof ICON_CATEGORIES] || [];
|
||||
filtered = allIcons.filter(icon => categoryIcons.includes(icon.name));
|
||||
const categoryData = ICON_CATEGORIES[category];
|
||||
if (categoryData) {
|
||||
filtered = allIcons.filter(icon => categoryData.icons.includes(icon.name));
|
||||
}
|
||||
}
|
||||
|
||||
// 按搜索词过滤
|
||||
|
||||
Loading…
Reference in New Issue
Block a user