pm 5 месяцев назад
Родитель
Сommit
8d6e9f1815
1 измененных файлов с 294 добавлено и 555 удалено
  1. 294 555
      src/components/MenuForm.tsx

+ 294 - 555
src/components/MenuForm.tsx

@@ -1,9 +1,8 @@
 import React, { useState, useEffect, useImperativeHandle, forwardRef } from 'react';
-import { menuApi, MenuVO, MenuType, MenuStatus } from '../api/Menu';
+import { menuApi, MenuVO, MenuType } from '../api/Menu';
 import { handleTree, TreeNode } from '../utils/tree';
 import { toast } from 'sonner';
 import { 
-  Maximize2, HelpCircle, ChevronDown, Check, 
   FileText, Folder, Menu, Settings, User, Users, 
   Lock, Unlock, Search, Edit, Trash2, Plus, Minus, 
   CheckCircle, X, AlertTriangle, Info, Bell, MessageSquare, 
@@ -12,11 +11,8 @@ import {
   ShoppingBag, Package, Database, PieChart, BarChart3, 
   Grid3x3, List, Link2, Key, Wrench, Monitor, Server
 } from 'lucide-react';
-import { Input } from './ui/input';
-import { Label } from './ui/label';
-import { Switch } from './ui/switch';
-import { Popover, PopoverTrigger, PopoverContent } from './ui/popover';
-import { Tabs, TabsList, TabsTrigger } from './ui/tabs';
+import { Modal, Input, Button, Radio, TreeSelect, Popover, Space } from 'antd';
+import { QuestionCircleOutlined } from '@ant-design/icons';
 
 interface MenuNode extends Omit<MenuVO, 'id'>, Omit<TreeNode, 'id'> {
   id: number;
@@ -37,7 +33,6 @@ const MenuForm = forwardRef<MenuFormRef, MenuFormProps>(({ onSuccess }, ref) =>
   const [formType, setFormType] = useState<'create' | 'update'>('create');
   const [formLoading, setFormLoading] = useState(false);
   const [menuTree, setMenuTree] = useState<MenuNode[]>([]);
-  const [popoverOpen, setPopoverOpen] = useState(false);
   const [iconPickerOpen, setIconPickerOpen] = useState(false);
   const [formData, setFormData] = useState<MenuVO>({
     name: '',
@@ -208,24 +203,6 @@ const MenuForm = forwardRef<MenuFormRef, MenuFormProps>(({ onSuccess }, ref) =>
     }
   };
 
-  // 获取当前选中菜单的名称
-  const getSelectedMenuName = (): string => {
-    if (!formData.parentId || formData.parentId === 0) return '主类目';
-    
-    const findMenuName = (nodes: MenuNode[], targetId: number): string | null => {
-      for (const node of nodes) {
-        if (node.id === targetId) return node.name;
-        if (node.children) {
-          const found = findMenuName(node.children, targetId);
-          if (found) return found;
-        }
-      }
-      return null;
-    };
-    
-    return findMenuName(menuTree, formData.parentId) || '主类目';
-  };
-
   // ElementPlus 图标列表(显示 React 图标,保存 ElementPlus 格式)
   const elementPlusIcons = [
     { name: 'ep:document', label: '文档', icon: FileText },
@@ -277,549 +254,311 @@ const MenuForm = forwardRef<MenuFormRef, MenuFormProps>(({ onSuccess }, ref) =>
     { name: 'ep:database', label: '数据库', icon: Database },
   ];
 
-  // 递归渲染菜单树选项(自定义组件)
-  const renderMenuTreeOptions = (nodes: MenuNode[], level: number = 0, onSelect: (id: number) => void): React.ReactNode => {
-    return nodes.map(node => {
-      if (node.id === undefined || node.id === null) return null;
-      const idValue = node.id;
-      if (idValue === undefined) return null;
-      
-      const indentWidth = level * 20; 
-      const hasChildren = node.children && node.children.length > 0;
-      const isSelected = formData.parentId === idValue;
-      const isDisabled = node.id === formData.id;
-  
-      return (
-        <React.Fragment key={node.id}>
-          <div
-            onClick={() => {
-              if (!isDisabled) {
-                onSelect(idValue);
-              }
-            }}
-            className={`
-              flex items-center justify-between px-3 py-2 text-sm cursor-pointer
-              transition-colors select-none
-              ${isDisabled 
-                ? 'opacity-50 cursor-not-allowed' 
-                : 'hover:bg-blue-50 active:bg-blue-100'
-              }
-              ${isSelected 
-                ? 'bg-blue-50 text-blue-600 font-semibold' 
-                : 'text-gray-700'
-              }
-            `}
-            style={{ 
-              paddingLeft: `${12 + indentWidth}px`,
-            }}
-          >
-            {/* 文本区域:左侧层级线 + 菜单名 */}
-            <div className="flex items-center gap-1.5 flex-1 min-w-0">
-              {level > 0 && (
-                <span className="flex-shrink-0 text-gray-400 text-xs font-mono">│</span>
-              )}
-              <span className="flex-1 min-w-0 truncate">{node.name}</span>
-            </div>
-            {/* 自定义选中标记 */}
-            {isSelected && !isDisabled && (
-              <Check className="w-4 h-4 text-blue-600 ml-2 flex-shrink-0" />
-            )}
-          </div>
-          
-          {hasChildren && node.children && renderMenuTreeOptions(node.children, level + 1, onSelect)}
-        </React.Fragment>
-      );
-    }).filter(Boolean);
+  // 将菜单树转换为 TreeSelect 需要的格式
+  const convertToTreeSelectData = (nodes: MenuNode[]): any[] => {
+    return nodes.map(node => ({
+      title: node.name,
+      value: node.id,
+      key: node.id,
+      disabled: node.id === formData.id,
+      children: node.children ? convertToTreeSelectData(node.children) : undefined,
+    }));
   };
-  if (!dialogVisible) return null;
 
   return (
-    <div className="fixed inset-0 bg-black/50 backdrop-blur-sm flex items-center justify-center z-[9999] animate-in fade-in duration-200 p-4">
-      <div className="bg-white rounded-xl shadow-2xl w-full max-w-4xl animate-in zoom-in duration-200 relative z-[10000] max-h-[85vh] flex flex-col overflow-hidden">
-        {/* 弹窗标题 */}
-        <div className="px-5 py-3 border-b border-gray-200 flex items-center justify-between shrink-0">
-          <h3 className="text-base text-gray-900">{dialogTitle}</h3>
-          <div className="flex items-center gap-2">
-            <button className="p-2 hover:bg-gray-100 rounded-lg transition-colors">
-              <Maximize2 className="w-4 h-4 text-gray-600" />
-            </button>
-            <button
-              onClick={() => setDialogVisible(false)}
-              className="p-2 hover:bg-gray-100 rounded-lg transition-colors"
+    <Modal
+      title={dialogTitle}
+      open={dialogVisible}
+      onCancel={() => setDialogVisible(false)}
+      width={600}
+      footer={[
+        <Button key="cancel" onClick={() => setDialogVisible(false)}>
+          取消
+        </Button>,
+        <Button 
+          key="submit" 
+          type="primary" 
+          loading={formLoading}
+          onClick={submitForm}
+        >
+          确定
+        </Button>,
+      ]}
+      destroyOnClose
+    >
+      {formLoading && formType === 'update' ? (
+        <div className="py-6 text-center text-gray-500">加载中...</div>
+      ) : (
+        <div style={{ padding: '8px 0' }}>
+          {/* 上级菜单 */}
+          <div style={{ marginBottom: '16px', display: 'flex', alignItems: 'center', gap: '12px' }}>
+            <span className="text-sm text-gray-700" style={{ fontWeight: 500, minWidth: '80px', flexShrink: 0 }}>上级菜单</span>
+            <TreeSelect
+              style={{ flex: 1 }}
+              value={formData.parentId || 0}
+              treeData={convertToTreeSelectData(menuTree)}
+              placeholder="请选择上级菜单"
+              onChange={(value) => setFormData(prev => ({ ...prev, parentId: value as number }))}
+              disabled={!menuTree || menuTree.length === 0}
+              treeDefaultExpandAll
+            />
+          </div>
+
+          {/* 菜单名称 */}
+          <div style={{ marginBottom: '16px', display: 'flex', alignItems: 'center', gap: '12px' }}>
+            <span className="text-sm text-gray-700" style={{ fontWeight: 500, minWidth: '80px', flexShrink: 0 }}>
+              <span className="text-red-500 mr-1">*</span>
+              菜单名称
+            </span>
+            <Input
+              style={{ flex: 1 }}
+              value={formData.name}
+              onChange={(e) => setFormData(prev => ({ ...prev, name: e.target.value }))}
+              placeholder="请输入菜单名称"
+            />
+          </div>
+
+          {/* 菜单类型 */}
+          <div style={{ marginBottom: '16px', display: 'flex', alignItems: 'center', gap: '12px' }}>
+            <span className="text-sm text-gray-700" style={{ fontWeight: 500, minWidth: '80px', flexShrink: 0 }}>
+              <span className="text-red-500 mr-1">*</span>
+              菜单类型
+            </span>
+            <Radio.Group
+              value={formData.type}
+              onChange={(e) => {
+                setFormData(prev => ({ ...prev, type: e.target.value }));
+              }}
+              buttonStyle="solid"
+              optionType="button"
             >
-              <svg className="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
-                <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
-              </svg>
-            </button>
+              <Radio.Button value={MenuType.DIR}>目录</Radio.Button>
+              <Radio.Button value={MenuType.MENU}>菜单</Radio.Button>
+              <Radio.Button value={MenuType.BUTTON}>按钮</Radio.Button>
+            </Radio.Group>
           </div>
-        </div>
 
-        {/* 弹窗内容 */}
-        <div className="px-5 py-3 overflow-y-auto overflow-x-hidden flex-1 min-h-0">
-          {formLoading ? (
-            <div className="py-6 text-center text-gray-500">加载中...</div>
-          ) : (
-            <div className="grid grid-cols-2 gap-x-32 gap-y-2.5">
-           {/* 上级菜单 - 占满整行(优化版) */}
-<div className="col-span-2 grid grid-cols-[100px_1fr] items-center gap-3 min-h-[40px]">
-  <label className="text-sm text-gray-700 whitespace-nowrap">上级菜单</label>
-  {/* 外层包裹确保下拉容器定位正确 */}
-  <div className="relative w-full">
-    <Popover open={popoverOpen} onOpenChange={setPopoverOpen}>
-      <PopoverTrigger asChild>
-        <button
-          type="button"
-          disabled={!menuTree || menuTree.length === 0}
-          className="w-full h-[36px] bg-white border border-gray-200 focus:border-blue-400 focus:ring-2 focus:ring-blue-100 
-                    rounded-md transition-all outline-none px-3 text-left flex items-center justify-between
-                    disabled:opacity-50 disabled:cursor-not-allowed hover:border-gray-300"
-        >
-          <span className={formData.parentId === 0 ? 'text-gray-500' : 'text-gray-900'}>
-            {getSelectedMenuName()}
-          </span>
-          <ChevronDown className={`w-4 h-4 text-gray-400 transition-transform ${popoverOpen ? 'rotate-180' : ''}`} />
-        </button>
-      </PopoverTrigger>
-      <PopoverContent 
-        className="p-0 border-gray-200 shadow-md bg-white rounded-md"
-        align="start"
-        side="bottom"
-        sideOffset={4}
-        style={{ width: 'var(--radix-popover-trigger-width)' }}
-      >
-        <div 
-          className="max-h-[200px] overflow-y-auto"
-          style={{ maxHeight: '200px' }}
-        >
-          {/* 空数据兜底 */}
-          {!menuTree || menuTree.length === 0 ? (
-            <div className="px-3 py-2 text-sm text-gray-400">暂无可选菜单</div>
-          ) : (
-            renderMenuTreeOptions(menuTree, 0, (id: number) => {
-              setFormData(prev => ({ ...prev, parentId: id }));
-              setPopoverOpen(false);
-            })
-          )}
-        </div>
-      </PopoverContent>
-    </Popover>
-  </div>
-</div>
-
-              {/* 菜单名称 */}
-              <div className="grid grid-cols-[100px_1fr] items-center gap-3" style={{ marginRight: '30px' }}>
-                <label className="text-sm text-gray-700">
-                  <span className="text-red-500 mr-1">*</span>
-                  菜单名称
-                </label>
+          {/* 菜单图标 */}
+          {formData.type !== MenuType.BUTTON && (
+            <div style={{ marginBottom: '16px', display: 'flex', alignItems: 'center', gap: '12px' }}>
+              <span className="text-sm text-gray-700" style={{ fontWeight: 500, minWidth: '80px', flexShrink: 0 }}>菜单图标</span>
+              <Space.Compact style={{ flex: 1 }}>
                 <Input
-                  value={formData.name}
-                  onChange={(e) => setFormData(prev => ({ ...prev, name: e.target.value }))}
-                  placeholder="请输入菜单名称"
-                  className="bg-white border-gray-200 focus:border-blue-400 focus:ring-2 focus:ring-blue-100"
+                  value={formData.icon}
+                  onChange={(e) => setFormData(prev => ({ ...prev, icon: e.target.value }))}
+                  placeholder="请选择或输入图标名称(如:ep:document)"
                 />
-              </div>
-
-              {/* 菜单类型 */}
-              <div className="grid grid-cols-[100px_1fr] items-center gap-3">
-                <label className="text-sm text-gray-700">
-                  <span className="text-red-500 mr-1">*</span>
-                  菜单类型
-                </label>
-                <div className="flex gap-0">
-                  <button
-                    onClick={() => setFormData(prev => ({ ...prev, type: MenuType.DIR }))}
-                    className={`flex-1 px-3 py-1.5 text-xs border border-r-0 rounded-l-lg transition-all ${
-                      formData.type === MenuType.DIR
-                        ? 'bg-blue-500 text-white border-blue-500 z-10'
-                        : 'bg-white text-gray-700 border-gray-200 hover:bg-gray-50'
-                    }`}
-                  >
-                    目录
-                  </button>
-                  <button
-                    onClick={() => setFormData(prev => ({ ...prev, type: MenuType.MENU }))}
-                    className={`flex-1 px-3 py-1.5 text-xs border transition-all ${
-                      formData.type === MenuType.MENU
-                        ? 'bg-blue-500 text-white border-blue-500 z-10'
-                        : 'bg-white text-gray-700 border-gray-200 hover:bg-gray-50'
-                    }`}
-                  >
-                    菜单
-                  </button>
-                  <button
-                    onClick={() => setFormData(prev => ({ ...prev, type: MenuType.BUTTON }))}
-                    className={`flex-1 px-3 py-1.5 text-xs border border-l-0 rounded-r-lg transition-all ${
-                      formData.type === MenuType.BUTTON
-                        ? 'bg-blue-500 text-white border-blue-500 z-10'
-                        : 'bg-white text-gray-700 border-gray-200 hover:bg-gray-50'
-                    }`}
-                  >
-                    按钮
-                  </button>
-                </div>
-              </div>
-
-              {/* 菜单图标 */}
-              {formData.type !== MenuType.BUTTON && (
-                <div className="grid grid-cols-[100px_1fr] items-center gap-3" style={{ marginRight: '30px' }}>
-                  <label className="text-sm text-gray-700">菜单图标</label>
-                  <div className="flex items-center gap-2">
-                    <Input
-                      value={formData.icon}
-                      onChange={(e) => setFormData(prev => ({ ...prev, icon: e.target.value }))}
-                      placeholder="请选择或输入图标名称(如:ep:document)"
-                      className="bg-white border-gray-200 focus:border-blue-400 focus:ring-2 focus:ring-blue-100 flex-1"
-                    />
-                    <Popover open={iconPickerOpen} onOpenChange={setIconPickerOpen}>
-                      <PopoverTrigger asChild>
-                        <button
-                          type="button"
-                          className="px-3 h-[36px] bg-blue-500 text-white rounded-md hover:bg-blue-600 transition-colors text-sm whitespace-nowrap"
-                        >
-                          选择图标
-                        </button>
-                      </PopoverTrigger>
-                      <PopoverContent 
-                        className="w-[400px] p-3 border-gray-200 shadow-md bg-white rounded-md max-h-[85vh]"
-                        align="end"
-                        side="bottom"
-                        sideOffset={4}
+                <Popover
+                  content={
+                    <div style={{ width: 400 }}>
+                      <h4 style={{ marginBottom: 8, fontSize: 14, fontWeight: 600 }}>选择图标</h4>
+                      <div 
+                        style={{ 
+                          display: 'grid',
+                          gridTemplateColumns: 'repeat(8, 1fr)',
+                          gap: 6,
+                          maxHeight: 300,
+                          overflowY: 'auto'
+                        }}
                       >
-                        <div className="flex flex-col">
-                          <h4 className="text-sm font-semibold text-gray-700 mb-2">选择图标</h4>
-                          <div 
-                            className="grid gap-1.5 overflow-y-auto"
-                            style={{ 
-                              gridTemplateColumns: 'repeat(8, 1fr)',
-                              maxHeight: '300px',
-                              height: '300px'
-                            }}
-                          >
-                            {elementPlusIcons.map((iconItem) => {
-                              const IconComponent = iconItem.icon;
-                              const isSelected = formData.icon === iconItem.name;
-                              return (
-                                <div
-                                  key={iconItem.name}
-                                  onClick={() => {
-                                    setFormData(prev => ({ ...prev, icon: iconItem.name }));
-                                    setIconPickerOpen(false);
-                                  }}
-                                  className={`
-                                    flex items-center justify-center p-1.5 rounded cursor-pointer
-                                    transition-all border
-                                    ${isSelected
-                                      ? 'bg-blue-50 border-blue-500 shadow-sm'
-                                      : 'bg-white border-gray-200 hover:bg-gray-50 hover:border-blue-300'
-                                    }
-                                  `}
-                                  style={{ aspectRatio: '1' }}
-                                  title={`${iconItem.name} - ${iconItem.label}`}
-                                >
-                                  <IconComponent 
-                                    className={`
-                                      w-3.5 h-3.5
-                                      ${isSelected ? 'text-blue-600' : 'text-gray-600'}
-                                    `}
-                                  />
-                                </div>
-                              );
-                            })}
-                          </div>
-                        </div>
-                      </PopoverContent>
-                    </Popover>
-                  </div>
-                </div>
-              )}
-
-              {/* 路由地址 */}
-              {formData.type !== MenuType.BUTTON && (
-                <div className="grid grid-cols-[100px_1fr] items-center gap-3">
-                  <label className="text-sm text-gray-700 flex items-center gap-1">
-                    <span className="text-red-500">*</span>
-                    路由地址
-                    <HelpCircle className="w-3.5 h-3.5 text-gray-400" />
-                  </label>
-                  <Input
-                    value={formData.path}
-                    onChange={(e) => setFormData(prev => ({ ...prev, path: e.target.value }))}
-                    placeholder="请输入路由地址"
-                    className="bg-white border-gray-200 focus:border-blue-400 focus:ring-2 focus:ring-blue-100"
-                  />
-                </div>
-              )}
-
-              {/* 组件地址 */}
-              {formData.type === MenuType.MENU && (
-                <div className="grid grid-cols-[100px_1fr] items-center gap-3" style={{ marginRight: '30px' }}>
-                  <label className="text-sm text-gray-700">组件地址</label>
-                  <Input
-                    value={formData.component}
-                    onChange={(e) => setFormData(prev => ({ ...prev, component: e.target.value }))}
-                    placeholder="例如:system/user/index"
-                    className="bg-white border-gray-200 focus:border-blue-400 focus:ring-2 focus:ring-blue-100"
-                  />
-                </div>
-              )}
-
-              {/* 组件名字 */}
-              {formData.type === MenuType.MENU && (
-                <div className="grid grid-cols-[100px_1fr] items-center gap-3">
-                  <label className="text-sm text-gray-700">组件名字</label>
-                  <Input
-                    value={formData.componentName || ''}
-                    onChange={(e) => setFormData(prev => ({ ...prev, componentName: e.target.value }))}
-                    placeholder="例如:SystemUser"
-                    className="bg-white border-gray-200 focus:border-blue-400 focus:ring-2 focus:ring-blue-100"
-                  />
-                </div>
-              )}
-
-              {/* 权限标识 */}
-              {formData.type !== MenuType.DIR && (
-                <div className="grid grid-cols-[100px_1fr] items-center gap-3" style={{ marginRight: '30px' }}>
-                  <label className="text-sm text-gray-700 flex items-center gap-1">
-                    权限标识
-                    <HelpCircle className="w-3.5 h-3.5 text-gray-400" />
-                  </label>
-                  <Input
-                    value={formData.permission}
-                    onChange={(e) => setFormData(prev => ({ ...prev, permission: e.target.value }))}
-                    placeholder="请输入权限标识"
-                    className="bg-white border-gray-200 focus:border-blue-400 focus:ring-2 focus:ring-blue-100"
-                  />
-                </div>
-              )}
-
-              {/* 显示排序 */}
-              <div className="grid grid-cols-[100px_1fr] items-center gap-3" style={{ marginRight: '30px' }}>
-                <label className="text-sm text-gray-700">
-                  <span className="text-red-500 mr-1">*</span>
-                  显示排序
-                </label>
-                <Input
-                  type="number"
-                  value={formData.sort}
-                  onChange={(e) => setFormData(prev => ({ ...prev, sort: Number(e.target.value) || 0 }))}
-                  placeholder="请输入排序号"
-                  min={0}
-                  className="bg-white border-gray-200 focus:border-blue-400 focus:ring-2 focus:ring-blue-100"
-                />
-              </div>
-
-              {/* 菜单状态 */}
-              <div className="col-span-4 grid grid-cols-[100px_1fr] items-center gap-3" style={{ marginRight: '30px' }}>
-                <label className="text-sm text-gray-700">
-                  <span className="text-red-500 mr-1">*</span>
-                  菜单状态
-                </label>
-                <div className="flex gap-0">
-                  <button
-                    type="button"
-                    onClick={() => setFormData(prev => ({ ...prev, status: 0 }))}
-                    className={`flex-1 px-4 py-1.5 text-xs border rounded-l-lg transition-all flex items-center justify-center gap-1.5 ${
-                      Number(formData.status) === 0
-                        ? 'bg-blue-50 text-blue-700 border-blue-500'
-                        : 'bg-white text-gray-700 border-gray-200 hover:bg-gray-50'
-                    }`}
-                  >
-                    <div className={`w-3 h-3 rounded-full border-2 flex items-center justify-center ${
-                      Number(formData.status) === 0 ? 'border-blue-500 bg-blue-500' : 'border-gray-300 bg-white'
-                    }`}>
-                      {Number(formData.status) === 0 && (
-                        <div className="w-1.5 h-1.5 rounded-full bg-white"></div>
-                      )}
-                    </div>
-                    开启
-                  </button>
-                  <button
-                    type="button"
-                    onClick={() => setFormData(prev => ({ ...prev, status: 1 }))}
-                    className={`flex-1 px-4 py-1.5 text-xs border border-l-0 rounded-r-lg transition-all flex items-center justify-center gap-1.5 ${
-                      Number(formData.status) === 1
-                        ? 'bg-blue-50 text-blue-700 border-blue-500'
-                        : 'bg-white text-gray-700 border-gray-200 hover:bg-gray-50'
-                    }`}
-                  >
-                    <div className={`w-3 h-3 rounded-full border-2 flex items-center justify-center ${
-                      Number(formData.status) === 1 ? 'border-blue-500 bg-blue-500' : 'border-gray-300 bg-white'
-                    }`}>
-                      {Number(formData.status) === 1 && (
-                        <div className="w-1.5 h-1.5 rounded-full bg-white"></div>
-                      )}
-                    </div>
-                    关闭
-                  </button>
-                </div>
-              </div>
-
-              {/* 显示状态 */}
-              {formData.type !== MenuType.BUTTON && (
-                <div className="grid grid-cols-[100px_1fr] items-center gap-3" style={{ marginRight: '30px' }}>
-                  <label className="text-sm text-gray-700 flex items-center gap-1">
-                    显示状态
-                    <HelpCircle className="w-3.5 h-3.5 text-gray-400" />
-                  </label>
-                  <div className="flex gap-0">
-                    <button
-                      type="button"
-                      onClick={() => setFormData(prev => ({ ...prev, visible: true }))}
-                      className={`flex-1 px-4 py-1.5 text-xs border rounded-l-lg transition-all flex items-center justify-center gap-1.5 ${
-                        formData.visible === true
-                          ? 'bg-blue-50 text-blue-700 border-blue-500'
-                          : 'bg-white text-gray-700 border-gray-200 hover:bg-gray-50'
-                      }`}
-                    >
-                      <div className={`w-3 h-3 rounded-full border-2 flex items-center justify-center ${
-                        formData.visible === true ? 'border-blue-500 bg-blue-500' : 'border-gray-300 bg-white'
-                      }`}>
-                        {formData.visible === true && (
-                          <div className="w-1.5 h-1.5 rounded-full bg-white"></div>
-                        )}
+                        {elementPlusIcons.map((iconItem) => {
+                          const IconComponent = iconItem.icon;
+                          const isSelected = formData.icon === iconItem.name;
+                          return (
+                            <div
+                              key={iconItem.name}
+                              onClick={() => {
+                                setFormData(prev => ({ ...prev, icon: iconItem.name }));
+                                setIconPickerOpen(false);
+                              }}
+                              style={{
+                                display: 'flex',
+                                alignItems: 'center',
+                                justifyContent: 'center',
+                                padding: 6,
+                                borderRadius: 4,
+                                cursor: 'pointer',
+                                border: `1px solid ${isSelected ? '#1890ff' : '#d9d9d9'}`,
+                                backgroundColor: isSelected ? '#e6f7ff' : '#fff',
+                                aspectRatio: '1'
+                              }}
+                              title={`${iconItem.name} - ${iconItem.label}`}
+                            >
+                              <IconComponent 
+                                style={{ 
+                                  width: 14,
+                                  height: 14,
+                                  color: isSelected ? '#1890ff' : '#666'
+                                }}
+                              />
+                            </div>
+                          );
+                        })}
                       </div>
-                      显示
-                    </button>
-                    <button
-                      type="button"
-                      onClick={() => setFormData(prev => ({ ...prev, visible: false }))}
-                      className={`flex-1 px-4 py-1.5 text-xs border border-l-0 rounded-r-lg transition-all flex items-center justify-center gap-1.5 ${
-                        formData.visible === false
-                          ? 'bg-blue-50 text-blue-700 border-blue-500'
-                          : 'bg-white text-gray-700 border-gray-200 hover:bg-gray-50'
-                      }`}
-                    >
-                      <div className={`w-3 h-3 rounded-full border-2 flex items-center justify-center ${
-                        formData.visible === false ? 'border-blue-500 bg-blue-500' : 'border-gray-300 bg-white'
-                      }`}>
-                        {formData.visible === false && (
-                          <div className="w-1.5 h-1.5 rounded-full bg-white"></div>
-                        )}
-                      </div>
-                      隐藏
-                    </button>
-                  </div>
-                </div>
-              )}
-
-              {/* 总是显示 */}
-              {formData.type !== MenuType.BUTTON && (
-                <div className="grid grid-cols-[100px_1fr] items-center gap-3" style={{ marginRight: '30px' }}>
-                  <label className="text-sm text-gray-700 flex items-center gap-1">
-                    总是显示
-                    <HelpCircle className="w-3.5 h-3.5 text-gray-400" />
-                  </label>
-                  <div className="flex gap-0">
-                    <button
-                      type="button"
-                      onClick={() => setFormData(prev => ({ ...prev, alwaysShow: true }))}
-                      className={`flex-1 px-4 py-1.5 text-xs border rounded-l-lg transition-all flex items-center justify-center gap-1.5 ${
-                        (formData.alwaysShow ?? true) === true
-                          ? 'bg-blue-50 text-blue-700 border-blue-500'
-                          : 'bg-white text-gray-700 border-gray-200 hover:bg-gray-50'
-                      }`}
-                    >
-                      <div className={`w-3 h-3 rounded-full border-2 flex items-center justify-center ${
-                        (formData.alwaysShow ?? true) === true ? 'border-blue-500 bg-blue-500' : 'border-gray-300 bg-white'
-                      }`}>
-                        {(formData.alwaysShow ?? true) === true && (
-                          <div className="w-1.5 h-1.5 rounded-full bg-white"></div>
-                        )}
-                      </div>
-                      总是
-                    </button>
-                    <button
-                      type="button"
-                      onClick={() => setFormData(prev => ({ ...prev, alwaysShow: false }))}
-                      className={`flex-1 px-4 py-1.5 text-xs border border-l-0 rounded-r-lg transition-all flex items-center justify-center gap-1.5 ${
-                        (formData.alwaysShow ?? true) === false
-                          ? 'bg-blue-50 text-blue-700 border-blue-500'
-                          : 'bg-white text-gray-700 border-gray-200 hover:bg-gray-50'
-                      }`}
-                    >
-                      <div className={`w-3 h-3 rounded-full border-2 flex items-center justify-center ${
-                        (formData.alwaysShow ?? true) === false ? 'border-blue-500 bg-blue-500' : 'border-gray-300 bg-white'
-                      }`}>
-                        {(formData.alwaysShow ?? true) === false && (
-                          <div className="w-1.5 h-1.5 rounded-full bg-white"></div>
-                        )}
-                      </div>
-                      不是
-                    </button>
-                  </div>
-                </div>
-              )}
-
-              {/* 缓存状态 */}
-              {formData.type === MenuType.MENU && (
-                <div className="col-span-4 grid grid-cols-[100px_1fr] items-center gap-3" style={{ marginRight: '30px' }}>
-                  <label className="text-sm text-gray-700 flex items-center gap-1">
-                    缓存状态
-                    <HelpCircle className="w-3.5 h-3.5 text-gray-400" />
-                  </label>
-                  <div className="flex gap-0">
-                    <button
-                      type="button"
-                      onClick={() => setFormData(prev => ({ ...prev, keepAlive: true }))}
-                      className={`flex-1 px-4 py-1.5 text-xs border rounded-l-lg transition-all flex items-center justify-center gap-1.5 ${
-                        (formData.keepAlive ?? true) === true
-                          ? 'bg-blue-50 text-blue-700 border-blue-500'
-                          : 'bg-white text-gray-700 border-gray-200 hover:bg-gray-50'
-                      }`}
-                    >
-                      <div className={`w-3 h-3 rounded-full border-2 flex items-center justify-center ${
-                        (formData.keepAlive ?? true) === true ? 'border-blue-500 bg-blue-500' : 'border-gray-300 bg-white'
-                      }`}>
-                        {(formData.keepAlive ?? true) === true && (
-                          <div className="w-1.5 h-1.5 rounded-full bg-white"></div>
-                        )}
-                      </div>
-                      缓存
-                    </button>
-                    <button
-                      type="button"
-                      onClick={() => setFormData(prev => ({ ...prev, keepAlive: false }))}
-                      className={`flex-1 px-4 py-1.5 text-xs border border-l-0 rounded-r-lg transition-all flex items-center justify-center gap-1.5 ${
-                        (formData.keepAlive ?? true) === false
-                          ? 'bg-blue-50 text-blue-700 border-blue-500'
-                          : 'bg-white text-gray-700 border-gray-200 hover:bg-gray-50'
-                      }`}
-                    >
-                      <div className={`w-3 h-3 rounded-full border-2 flex items-center justify-center ${
-                        (formData.keepAlive ?? true) === false ? 'border-blue-500 bg-blue-500' : 'border-gray-300 bg-white'
-                      }`}>
-                        {(formData.keepAlive ?? true) === false && (
-                          <div className="w-1.5 h-1.5 rounded-full bg-white"></div>
-                        )}
-                      </div>
-                      不缓存
-                    </button>
-                  </div>
-                </div>
-              )}
+                    </div>
+                  }
+                  title="选择图标"
+                  trigger="click"
+                  open={iconPickerOpen}
+                  onOpenChange={setIconPickerOpen}
+                >
+                  <Button type="primary">选择图标</Button>
+                </Popover>
+              </Space.Compact>
+            </div>
+          )}
+
+          {/* 路由地址 */}
+          {formData.type !== MenuType.BUTTON && (
+            <div style={{ marginBottom: '16px', display: 'flex', alignItems: 'center', gap: '12px' }}>
+              <span className="text-sm text-gray-700 flex items-center gap-1" style={{ fontWeight: 500, minWidth: '80px', flexShrink: 0 }}>
+                <span className="text-red-500">*</span>
+                路由地址
+                <QuestionCircleOutlined style={{ fontSize: 14, color: '#999' }} />
+              </span>
+              <Input
+                style={{ flex: 1 }}
+                value={formData.path}
+                onChange={(e) => setFormData(prev => ({ ...prev, path: e.target.value }))}
+                placeholder="请输入路由地址"
+              />
+            </div>
+          )}
+
+          {/* 组件地址 */}
+          {formData.type === MenuType.MENU && (
+            <div style={{ marginBottom: '16px', display: 'flex', alignItems: 'center', gap: '12px' }}>
+              <span className="text-sm text-gray-700" style={{ fontWeight: 500, minWidth: '80px', flexShrink: 0 }}>组件地址</span>
+              <Input
+                style={{ flex: 1 }}
+                value={formData.component}
+                onChange={(e) => setFormData(prev => ({ ...prev, component: e.target.value }))}
+                placeholder="例如:system/user/index"
+              />
+            </div>
+          )}
+
+          {/* 组件名字 */}
+          {formData.type === MenuType.MENU && (
+            <div style={{ marginBottom: '16px', display: 'flex', alignItems: 'center', gap: '12px' }}>
+              <span className="text-sm text-gray-700" style={{ fontWeight: 500, minWidth: '80px', flexShrink: 0 }}>组件名字</span>
+              <Input
+                style={{ flex: 1 }}
+                value={formData.componentName || ''}
+                onChange={(e) => setFormData(prev => ({ ...prev, componentName: e.target.value }))}
+                placeholder="例如:SystemUser"
+              />
+            </div>
+          )}
+
+          {/* 权限标识 */}
+          {formData.type !== MenuType.DIR && (
+            <div style={{ marginBottom: '16px', display: 'flex', alignItems: 'center', gap: '12px' }}>
+              <span className="text-sm text-gray-700 flex items-center gap-1" style={{ fontWeight: 500, minWidth: '80px', flexShrink: 0 }}>
+                权限标识
+                <QuestionCircleOutlined style={{ fontSize: 14, color: '#999' }} />
+              </span>
+              <Input
+                style={{ flex: 1 }}
+                value={formData.permission}
+                onChange={(e) => setFormData(prev => ({ ...prev, permission: e.target.value }))}
+                placeholder="请输入权限标识"
+              />
             </div>
           )}
-        </div>
 
-        {/* 弹窗底部 */}
-        <div className="px-5 py-3 bg-gray-50/50 border-t border-gray-200 flex justify-end gap-2 rounded-b-xl shrink-0">
-          <button
-            onClick={() => setDialogVisible(false)}
-            className="px-4 py-2 text-sm text-gray-600 bg-white border border-gray-200 rounded-lg hover:bg-gray-50 transition-colors"
-          >
-            取消
-          </button>
-          <button
-            onClick={submitForm}
-            disabled={formLoading}
-            className="px-4 py-2 text-sm text-white bg-gradient-to-r from-blue-500 to-blue-600 rounded-lg hover:shadow-lg hover:shadow-blue-400/40 transition-all disabled:opacity-50 disabled:cursor-not-allowed"
-          >
-            {formLoading ? '提交中...' : '确定'}
-          </button>
+          {/* 显示排序 */}
+          <div style={{ marginBottom: '16px', display: 'flex', alignItems: 'center', gap: '12px' }}>
+            <span className="text-sm text-gray-700" style={{ fontWeight: 500, minWidth: '80px', flexShrink: 0 }}>
+              <span className="text-red-500 mr-1">*</span>
+              显示排序
+            </span>
+            <Input
+              style={{ flex: 1 }}
+              type="number"
+              value={formData.sort}
+              onChange={(e) => setFormData(prev => ({ ...prev, sort: Number(e.target.value) || 0 }))}
+              placeholder="请输入排序号"
+              min={0}
+            />
+          </div>
+
+          {/* 菜单状态 */}
+          <div style={{ marginBottom: '16px', display: 'flex', alignItems: 'center', gap: '12px' }}>
+            <span className="text-sm text-gray-700" style={{ fontWeight: 500, minWidth: '80px', flexShrink: 0 }}>
+              <span className="text-red-500 mr-1">*</span>
+              菜单状态
+            </span>
+            <Radio.Group
+              value={Number(formData.status)}
+              onChange={(e) => setFormData(prev => ({ ...prev, status: Number(e.target.value) }))}
+              buttonStyle="solid"
+              optionType="button"
+            >
+              <Radio.Button value={0}>开启</Radio.Button>
+              <Radio.Button value={1}>关闭</Radio.Button>
+            </Radio.Group>
+          </div>
+
+          {/* 显示状态 */}
+          {formData.type !== MenuType.BUTTON && (
+            <div style={{ marginBottom: '16px', display: 'flex', alignItems: 'center', gap: '12px' }}>
+              <span className="text-sm text-gray-700 flex items-center gap-1" style={{ fontWeight: 500, minWidth: '80px', flexShrink: 0 }}>
+                显示状态
+                <QuestionCircleOutlined style={{ fontSize: 14, color: '#999' }} />
+              </span>
+              <Radio.Group
+                value={formData.visible}
+                onChange={(e) => setFormData(prev => ({ ...prev, visible: e.target.value as boolean }))}
+                buttonStyle="solid"
+                optionType="button"
+              >
+                <Radio.Button value={true}>显示</Radio.Button>
+                <Radio.Button value={false}>隐藏</Radio.Button>
+              </Radio.Group>
+            </div>
+          )}
+
+          {/* 总是显示 */}
+          {formData.type !== MenuType.BUTTON && (
+            <div style={{ marginBottom: '16px', display: 'flex', alignItems: 'center', gap: '12px' }}>
+              <span className="text-sm text-gray-700 flex items-center gap-1" style={{ fontWeight: 500, minWidth: '80px', flexShrink: 0 }}>
+                总是显示
+                <QuestionCircleOutlined style={{ fontSize: 14, color: '#999' }} />
+              </span>
+              <Radio.Group
+                value={formData.alwaysShow ?? true}
+                onChange={(e) => setFormData(prev => ({ ...prev, alwaysShow: e.target.value as boolean }))}
+                buttonStyle="solid"
+                optionType="button"
+              >
+                <Radio.Button value={true}>总是</Radio.Button>
+                <Radio.Button value={false}>不是</Radio.Button>
+              </Radio.Group>
+            </div>
+          )}
+
+          {/* 缓存状态 */}
+          {formData.type === MenuType.MENU && (
+            <div style={{ marginBottom: '16px', display: 'flex', alignItems: 'center', gap: '12px' }}>
+              <span className="text-sm text-gray-700 flex items-center gap-1" style={{ fontWeight: 500, minWidth: '80px', flexShrink: 0 }}>
+                缓存状态
+                <QuestionCircleOutlined style={{ fontSize: 14, color: '#999' }} />
+              </span>
+              <Radio.Group
+                value={formData.keepAlive ?? true}
+                onChange={(e) => setFormData(prev => ({ ...prev, keepAlive: e.target.value as boolean }))}
+                buttonStyle="solid"
+                optionType="button"
+              >
+                <Radio.Button value={true}>缓存</Radio.Button>
+                <Radio.Button value={false}>不缓存</Radio.Button>
+              </Radio.Group>
+            </div>
+          )}
         </div>
-      </div>
-    </div>
+      )}
+    </Modal>
   );
 });