/* === Import Template Management Page v2 === */
function PageOperationDataTemplate() {
  const [templates, setTemplates] = React.useState([]);
  const [showDrawer, setShowDrawer] = React.useState(false);
  const [editingTemplate, setEditingTemplate] = React.useState(null);
  const [showViewModal, setShowViewModal] = React.useState(false);
  const [viewingTemplate, setViewingTemplate] = React.useState(null);
  const [fileTypes, setFileTypes] = React.useState([]);
  const [dictCategories, setDictCategories] = React.useState([]);
  const [dictItems, setDictItems] = React.useState({});
  
  const [formData, setFormData] = React.useState({
    template_name: '',
    template_code: '',
    target_table_type: 'fixed',
    target_table: '',
    target_table_dict_category: '',
    target_table_dict_item: '',
    target_table_get_value: false,
    file_type: '',
    common_mappings: [],
    groups: [{ name: '组一', mappings: [] }]
  });

  const API_BASE = window.API_BASE;

  React.useEffect(() => {
    fetchTemplates();
    fetchFileTypes();
    fetchDictCategories();
  }, []);

  const fetchTemplates = async () => {
    try {
      const res = await fetch(`${API_BASE}/api/import/templates`);
      const json = await res.json();
      if (Array.isArray(json)) {
        setTemplates(json);
      } else if (json.data) {
        setTemplates(json.data);
      }
    } catch (err) {
      console.error('Failed to fetch templates:', err);
    }
  };

  const fetchFileTypes = async () => {
    try {
      const res = await fetch(`${API_BASE}/api/dict/item/select?category_code=loadfile-type`);
      const json = await res.json();
      console.log('File types response:', json);
      if (Array.isArray(json)) {
        const formattedTypes = json.map(item => ({
          value: item.value || item.code || item.id,
          label: item.label || item.name || item.value
        }));
        setFileTypes(formattedTypes);
      }
    } catch (err) {
      console.error('Failed to fetch file types:', err);
    }
  };

  const fetchDictCategories = async () => {
    try {
      const res = await fetch(`${API_BASE}/api/dict/category/tree`);
      const json = await res.json();
      if (Array.isArray(json)) {
        setDictCategories(json);
      }
    } catch (err) {
      console.error('Failed to fetch dict categories:', err);
    }
  };

  const flattenCategories = (nodes, level = 0, result = []) => {
    if (!Array.isArray(nodes)) return result;
    nodes.forEach(node => {
      result.push({
        code: node.code,
        name: node.name,
        level: level,
        indent: '　'.repeat(level)
      });
      if (node.children && node.children.length > 0) {
        flattenCategories(node.children, level + 1, result);
      }
    });
    return result;
  };

  const flatCategories = React.useMemo(() => {
    return flattenCategories(dictCategories);
  }, [dictCategories]);

  const fetchDictItems = async (categoryCode) => {
    if (dictItems[categoryCode]) return;
    try {
      const res = await fetch(`${API_BASE}/api/dict/item/select?category_code=${categoryCode}`);
      const json = await res.json();
      if (Array.isArray(json)) {
        setDictItems(prev => ({ ...prev, [categoryCode]: json }));
      }
    } catch (err) {
      console.error('Failed to fetch dict items:', err);
    }
  };

  const openCreateDrawer = () => {
    setEditingTemplate(null);
    setFormData({
      template_name: '',
      template_code: '',
      target_table_type: 'fixed',
      target_table: '',
      target_table_dict_category: '',
      target_table_dict_item: '',
      target_table_get_value: false,
      file_type: '',
      common_mappings: [createEmptyMapping()],
      groups: [{ name: '组一', mappings: [createEmptyMapping()] }]
    });
    setShowDrawer(true);
  };

  const createEmptyMapping = () => ({
    source_type: 'excel',
    source_value: '1',
    source_dict_category: '',
    source_dict_item: '',
    source_get_value: false,
    target_type: 'string',
    target_value: '',
    target_dict_category: '',
    target_dict_item: '',
    target_get_value: true,
    field_type: 'string',
    json_key: ''
  });

  const openEditDrawer = (template) => {
    setEditingTemplate(template);
    
    const commonMappings = template.common_mappings || [createEmptyMapping()];
    const groupsData = template.groups || [{ name: '组一', mappings: [createEmptyMapping()] }];
    
    // 预加载所有字典项
    const loadDictItems = () => {
      // 加载公共映射中的字典项
      commonMappings.forEach(mapping => {
        if (mapping.source_type === 'dict' && mapping.source_dict_category) {
          fetchDictItems(mapping.source_dict_category);
        }
        if (mapping.target_type === 'dict' && mapping.target_dict_category) {
          fetchDictItems(mapping.target_dict_category);
        }
      });
      
      // 加载分组映射中的字典项
      groupsData.forEach(group => {
        group.mappings.forEach(mapping => {
          if (mapping.source_type === 'dict' && mapping.source_dict_category) {
            fetchDictItems(mapping.source_dict_category);
          }
          if (mapping.target_type === 'dict' && mapping.target_dict_category) {
            fetchDictItems(mapping.target_dict_category);
          }
        });
      });
    };
    
    setFormData({
      template_name: template.template_name,
      template_code: template.template_code,
      target_table_type: template.target_table_type || 'fixed',
      target_table: template.target_table || '',
      target_table_dict_category: template.target_table_dict_category || '',
      target_table_dict_item: template.target_table_dict_item || '',
      target_table_get_value: template.target_table_get_value || false,
      file_type: template.file_type || '',
      common_mappings: commonMappings,
      groups: groupsData
    });
    
    setTimeout(loadDictItems, 0);
    setShowDrawer(true);
  };

  const handleDelete = async (templateCode) => {
    if (!confirm('确定要删除此模板吗？')) return;
    
    try {
      const res = await fetch(`${API_BASE}/api/import/template/${templateCode}`, {
        method: 'DELETE'
      });
      const json = await res.json();
      if (json.code === 200) {
        fetchTemplates();
      } else {
        alert('删除失败: ' + json.msg);
      }
    } catch (err) {
      console.error('Delete failed:', err);
      alert('删除失败');
    }
  };

  const handleView = (template) => {
    setViewingTemplate(template);
    setShowViewModal(true);
  };

  const handleCopy = async (template) => {
    const newTemplateCode = template.template_code + '_copy';
    const newTemplateName = template.template_name + '(副本)';
    
    const templateData = {
      template_name: newTemplateName,
      template_code: newTemplateCode,
      target_table_type: template.target_table_type || 'fixed',
      target_table: template.target_table || '',
      target_table_dict_category: template.target_table_dict_category || '',
      target_table_dict_item: template.target_table_dict_item || '',
      target_table_get_value: template.target_table_get_value || false,
      file_type: template.file_type || '',
      common_mappings: template.common_mappings || [],
      groups: template.groups || []
    };
    
    try {
      const res = await fetch(`${API_BASE}/api/import/template`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(templateData)
      });
      const json = await res.json();
      if (json.code === 200 || json.code === 0) {
        fetchTemplates();
      } else {
        alert('复制失败: ' + (json.msg || json.message || '未知错误'));
      }
    } catch (err) {
      console.error('Copy failed:', err);
      alert('复制失败');
    }
  };

  const handleRefresh = async (templateCode) => {
    if (!confirm('确定要刷新此模板的映射吗？这将根据当前字典数据重新验证映射配置。')) return;
    
    try {
      const res = await fetch(`${API_BASE}/api/import/template/${templateCode}/refresh`, {
        method: 'POST'
      });
      const json = await res.json();
      if (json.code === 200) {
        fetchTemplates();
        const data = json.data || {};
        const invalidList = data.invalid_mappings || [];
        if (invalidList.length > 0) {
          const details = invalidList.map((m, i) => {
            if (m.type === 'common') {
              return `${i + 1}. [公共映射] 类别: ${m.category}, 字典项: ${m.item}`;
            } else {
              return `${i + 1}. [${m.group}] 类别: ${m.category}, 字典项: ${m.item}`;
            }
          }).join('\n');
          alert(`刷新完成！\n发现 ${invalidList.length} 个无效映射：\n\n${details}`);
        } else {
          alert('刷新成功：所有映射都有效！');
        }
      } else {
        alert('刷新失败: ' + json.msg);
      }
    } catch (err) {
      console.error('Refresh failed:', err);
      alert('刷新失败');
    }
  };

  const addCommonMapping = () => {
    setFormData(prev => ({
      ...prev,
      common_mappings: [...prev.common_mappings, createEmptyMapping()]
    }));
  };

  const removeCommonMapping = (index) => {
    setFormData(prev => ({
      ...prev,
      common_mappings: prev.common_mappings.filter((_, i) => i !== index)
    }));
  };

  const updateCommonMapping = (index, field, value) => {
    setFormData(prev => {
      const newMappings = [...prev.common_mappings];
      newMappings[index] = { ...newMappings[index], [field]: value };
      return { ...prev, common_mappings: newMappings };
    });
  };

  const addGroup = () => {
    const newGroupName = `组${formData.groups.length + 1}`;
    setFormData(prev => ({
      ...prev,
      groups: [...prev.groups, { name: newGroupName, mappings: [createEmptyMapping()] }]
    }));
  };

  const removeGroup = (index) => {
    if (formData.groups.length <= 1) {
      alert('至少保留一个分组');
      return;
    }
    setFormData(prev => ({
      ...prev,
      groups: prev.groups.filter((_, i) => i !== index)
    }));
  };

  const copyGroup = (index) => {
    const groupToCopy = formData.groups[index];
    const copiedGroup = {
      name: groupToCopy.name + '(副本)',
      mappings: groupToCopy.mappings.map(m => ({ ...m }))
    };
    setFormData(prev => ({
      ...prev,
      groups: [
        ...prev.groups.slice(0, index + 1),
        copiedGroup,
        ...prev.groups.slice(index + 1)
      ]
    }));
  };

  const moveGroup = (fromIndex, toIndex) => {
    setFormData(prev => {
      const newGroups = [...prev.groups];
      const [removed] = newGroups.splice(fromIndex, 1);
      newGroups.splice(toIndex, 0, removed);
      return { ...prev, groups: newGroups };
    });
  };

  const updateGroupName = (index, name) => {
    setFormData(prev => {
      const newGroups = [...prev.groups];
      newGroups[index] = { ...newGroups[index], name };
      return { ...prev, groups: newGroups };
    });
  };

  const addGroupMapping = (groupIndex) => {
    setFormData(prev => {
      const newGroups = [...prev.groups];
      newGroups[groupIndex] = {
        ...newGroups[groupIndex],
        mappings: [...newGroups[groupIndex].mappings, createEmptyMapping()]
      };
      return { ...prev, groups: newGroups };
    });
  };

  const removeGroupMapping = (groupIndex, mappingIndex) => {
    setFormData(prev => {
      const newGroups = [...prev.groups];
      newGroups[groupIndex] = {
        ...newGroups[groupIndex],
        mappings: newGroups[groupIndex].mappings.filter((_, i) => i !== mappingIndex)
      };
      return { ...prev, groups: newGroups };
    });
  };

  const copyGroupMapping = (groupIndex, mappingIndex) => {
    setFormData(prev => {
      const newGroups = [...prev.groups];
      const mappingToCopy = newGroups[groupIndex].mappings[mappingIndex];
      const copiedMapping = { ...mappingToCopy };
      newGroups[groupIndex] = {
        ...newGroups[groupIndex],
        mappings: [
          ...newGroups[groupIndex].mappings.slice(0, mappingIndex + 1),
          copiedMapping,
          ...newGroups[groupIndex].mappings.slice(mappingIndex + 1)
        ]
      };
      return { ...prev, groups: newGroups };
    });
  };

  const moveGroupMapping = (groupIndex, fromIndex, toIndex) => {
    setFormData(prev => {
      const newGroups = [...prev.groups];
      const mappings = [...newGroups[groupIndex].mappings];
      const [removed] = mappings.splice(fromIndex, 1);
      mappings.splice(toIndex, 0, removed);
      newGroups[groupIndex] = {
        ...newGroups[groupIndex],
        mappings
      };
      return { ...prev, groups: newGroups };
    });
  };

  const copyCommonMapping = (index) => {
    setFormData(prev => {
      const mappingToCopy = prev.common_mappings[index];
      const copiedMapping = { ...mappingToCopy };
      return {
        ...prev,
        common_mappings: [
          ...prev.common_mappings.slice(0, index + 1),
          copiedMapping,
          ...prev.common_mappings.slice(index + 1)
        ]
      };
    });
  };

  const moveCommonMapping = (fromIndex, toIndex) => {
    setFormData(prev => {
      const mappings = [...prev.common_mappings];
      const [removed] = mappings.splice(fromIndex, 1);
      mappings.splice(toIndex, 0, removed);
      return { ...prev, common_mappings: mappings };
    });
  };

  const updateGroupMapping = (groupIndex, mappingIndex, field, value) => {
    setFormData(prev => {
      const newGroups = [...prev.groups];
      newGroups[groupIndex] = {
        ...newGroups[groupIndex],
        mappings: newGroups[groupIndex].mappings.map((m, i) => 
          i === mappingIndex ? { ...m, [field]: value } : m
        )
      };
      return { ...prev, groups: newGroups };
    });
  };

  const handleSave = async () => {
    if (!formData.template_name || !formData.template_code) {
      alert('请填写模板名称和模板编码');
      return;
    }

    if (!formData.file_type) {
      alert('请选择文件类型');
      return;
    }

    try {
      const url = editingTemplate 
        ? `${API_BASE}/api/import/template/${editingTemplate.template_code}`
        : `${API_BASE}/api/import/template`;
      const method = editingTemplate ? 'PUT' : 'POST';
      
      const res = await fetch(url, {
        method,
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(formData)
      });
      
      const json = await res.json();
      if (json.code === 200) {
        setShowDrawer(false);
        fetchTemplates();
      } else {
        alert('保存失败: ' + json.msg);
      }
    } catch (err) {
      console.error('Save failed:', err);
      alert('保存失败');
    }
  };

  const renderMappingCard = (mapping, index, onUpdate, onRemove, onCopy, onMove, groupIndex = null) => (
    <div 
      key={index} 
      className="template-mapping-card" 
      draggable 
      onDragStart={(e) => {
        e.dataTransfer.setData('index', index);
        e.dataTransfer.setData('groupIndex', groupIndex ?? 'common');
      }}
      onDragOver={(e) => e.preventDefault()}
      onDrop={(e) => {
        const fromIndex = parseInt(e.dataTransfer.getData('index'));
        const fromGroupIndex = e.dataTransfer.getData('groupIndex');
        if ((fromGroupIndex === 'common' && groupIndex === null) || 
            (fromGroupIndex !== 'common' && groupIndex !== null && fromGroupIndex === String(groupIndex))) {
          onMove?.(fromIndex, index);
        }
      }}
    >
      <div className="mapping-row-source">
        <div className="mapping-cell">
          <span className="mapping-cell-order">{index + 1}</span>
        </div>
        <div className="mapping-cell">
          <span className="mapping-cell-label">数据源</span>
          <select
            value={mapping.source_type}
            onChange={(e) => onUpdate(index, 'source_type', e.target.value)}
            className="mapping-select"
          >
            <option value="excel">Excel</option>
            <option value="string">固定值</option>
            <option value="dict">字典</option>
          </select>
        </div>
        
        {mapping.source_type === 'excel' && (
          <div className="mapping-cell">
            <input
              type="number"
              value={mapping.source_value}
              onChange={(e) => onUpdate(index, 'source_value', e.target.value)}
              className="mapping-input"
              placeholder="列号"
              min="1"
            />
          </div>
        )}
        
        {mapping.source_type === 'string' && (
          <div className="mapping-cell">
            <input
              type="text"
              value={mapping.source_value}
              onChange={(e) => onUpdate(index, 'source_value', e.target.value)}
              className="mapping-input"
              placeholder="固定值"
            />
          </div>
        )}
        
        {mapping.source_type === 'dict' && (
          <>
            <div className="mapping-cell">
              <select
                value={mapping.source_dict_category}
                onChange={(e) => {
                  onUpdate(index, 'source_dict_category', e.target.value);
                  onUpdate(index, 'source_dict_item', '');
                  fetchDictItems(e.target.value);
                }}
                className="mapping-select"
              >
                <option value="">选择字典分类</option>
                {flatCategories.map(cat => (
                  <option key={cat.code} value={cat.code}>{cat.indent}{cat.name}</option>
                ))}
              </select>
            </div>
            {mapping.source_dict_category && dictItems[mapping.source_dict_category] && (
              <div className="mapping-cell">
                <select
                  value={mapping.source_dict_item}
                  onChange={(e) => onUpdate(index, 'source_dict_item', e.target.value)}
                  className="mapping-select"
                >
                  <option value="">选择字典项</option>
                  {dictItems[mapping.source_dict_category].map(item => (
                    <option key={item.value} value={item.value}>{item.label}</option>
                  ))}
                </select>
              </div>
            )}
            <label className="mapping-checkbox">
              <input
                type="checkbox"
                checked={mapping.source_get_value}
                onChange={(e) => onUpdate(index, 'source_get_value', e.target.checked)}
              />
              取值
            </label>
          </>
        )}
        
        <div className="mapping-actions">
          <button className="btn-delete-mapping" onClick={() => onRemove(index)} title="删除此映射">
            ×
          </button>
        </div>
      </div>
      
      <div className="mapping-row-target">
        <div className="mapping-cell">
          <span className="mapping-cell-spacer"></span>
        </div>
        <div className="mapping-cell">
          <span className="mapping-cell-label">数据库</span>
          <select
            value={mapping.target_type}
            onChange={(e) => {
              onUpdate(index, 'target_type', e.target.value);
              onUpdate(index, 'target_dict_category', '');
              onUpdate(index, 'target_dict_item', '');
            }}
            className="mapping-select"
          >
            <option value="string">字段名</option>
            <option value="dict">字典</option>
          </select>
        </div>
        
        {mapping.target_type === 'string' && (
          <div className="mapping-cell">
            <input
              type="text"
              value={mapping.target_value}
              onChange={(e) => onUpdate(index, 'target_value', e.target.value)}
              className="mapping-input"
              placeholder="字段代码"
            />
          </div>
        )}
        
        {mapping.target_type === 'dict' && (
          <>
            <div className="mapping-cell">
              <select
                value={mapping.target_dict_category}
                onChange={(e) => {
                  onUpdate(index, 'target_dict_category', e.target.value);
                  onUpdate(index, 'target_dict_item', '');
                  fetchDictItems(e.target.value);
                }}
                className="mapping-select"
              >
                <option value="">选择字典分类</option>
                {flatCategories.map(cat => (
                  <option key={cat.code} value={cat.code}>{cat.indent}{cat.name}</option>
                ))}
              </select>
            </div>
            {mapping.target_dict_category && dictItems[mapping.target_dict_category] && (
              <div className="mapping-cell">
                <select
                  value={mapping.target_dict_item}
                  onChange={(e) => onUpdate(index, 'target_dict_item', e.target.value)}
                  className="mapping-select"
                >
                  <option value="">选择字典项</option>
                  {dictItems[mapping.target_dict_category].map(item => (
                    <option key={item.value} value={item.value}>{item.label}</option>
                  ))}
                </select>
              </div>
            )}
            <label className="mapping-checkbox">
              <input
                type="checkbox"
                checked={mapping.target_get_value}
                onChange={(e) => onUpdate(index, 'target_get_value', e.target.checked)}
              />
              取值
            </label>
          </>
        )}
        
        <div className="mapping-cell">
          <span className="mapping-cell-label">类型</span>
          <select
            value={mapping.field_type}
            onChange={(e) => onUpdate(index, 'field_type', e.target.value)}
            className="mapping-select"
          >
            <option value="string">string</option>
            <option value="date">date</option>
            <option value="number">number</option>
            <option value="json">json</option>
          </select>
        </div>
        
        {mapping.field_type === 'json' && (
          <div className="mapping-cell">
            <input
              type="text"
              value={mapping.json_key}
              onChange={(e) => onUpdate(index, 'json_key', e.target.value)}
              className="mapping-input"
              placeholder="JSON Key"
            />
          </div>
        )}
        
        <div className="mapping-cell mapping-actions">
          <button 
            className="btn-mapping-action btn-copy" 
            onClick={() => onCopy?.(index)} 
            title="复制映射"
          >
            <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
              <rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
              <path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>
            </svg>
          </button>
          <button 
            className="btn-mapping-action btn-delete" 
            onClick={() => onRemove(index)} 
            title="删除映射"
          >
            <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
              <path d="M3 6h18"></path>
              <path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6"></path>
              <path d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2"></path>
            </svg>
          </button>
        </div>
      </div>
    </div>
  );

  return (
    <div className="page-template">
      <div className="card">
        <div className="card-header">
          <h2>模板管理</h2>
          <button className="btn btn-primary" onClick={openCreateDrawer}>
            + 新建模板
          </button>
        </div>
        <div className="card-body">
          {templates.length > 0 ? (
            <div className="template-list">
              {templates.map(template => (
                <div key={template.template_code} className="template-item">
                  <div className="template-info">
                    <div className="template-name">{template.template_name}</div>
                    <div className="template-meta">
                      <span className="template-code">{template.template_code}</span>
                      <span className="template-type">{template.file_type}</span>
                    </div>
                    <div className="template-mapping">
                      公共字段: {template.common_mappings?.length || 0} | 
                      分组数: {template.groups?.length || 0}
                    </div>
                  </div>
                  <div className="template-actions">
                    <button className="btn btn-sm" onClick={() => handleView(template)}>
                      查看
                    </button>
                    <button className="btn btn-sm" onClick={() => openEditDrawer(template)}>
                      编辑
                    </button>
                    <button className="btn btn-sm" onClick={() => handleCopy(template)}>
                      复制
                    </button>
                    <button className="btn btn-sm" onClick={() => handleRefresh(template.template_code)}>
                      刷新
                    </button>
                    <button className="btn btn-sm btn-danger" onClick={() => handleDelete(template.template_code)}>
                      删除
                    </button>
                  </div>
                </div>
              ))}
            </div>
          ) : (
            <div className="coming-soon">
              <div className="coming-soon-icon">📋</div>
              <h3>暂无模板</h3>
              <p>点击上方按钮创建导入模板</p>
            </div>
          )}
        </div>
      </div>

      {showDrawer && (
        <div className="drawer-backdrop" onClick={() => setShowDrawer(false)}>
          <div className="drawer template-drawer-lg" onClick={(e) => e.stopPropagation()}>
            <div className="drawer-header">
              <div>
                <h3 className="drawer-title">{editingTemplate ? '编辑模板' : '新建模板'}</h3>
                <p className="drawer-sub">配置导入数据的字段映射关系</p>
              </div>
              <button className="drawer-close" onClick={() => setShowDrawer(false)}>×</button>
            </div>
            
            <div className="template-drawer-body">
              <div className="template-section">
                <div className="template-section-header">
                  <h4 className="template-section-title">基本信息</h4>
                </div>
                <div className="template-form-row">
                  <div className="template-form-group">
                    <label className="template-form-label">模板名称</label>
                    <input
                      type="text"
                      value={formData.template_name}
                      onChange={(e) => setFormData({...formData, template_name: e.target.value})}
                      className="template-form-input"
                      placeholder="请输入模板名称"
                    />
                  </div>
                  <div className="template-form-group">
                    <label className="template-form-label">模板编码</label>
                    <input
                      type="text"
                      value={formData.template_code}
                      onChange={(e) => setFormData({...formData, template_code: e.target.value})}
                      className="template-form-input"
                      placeholder="请输入模板编码"
                      disabled={!!editingTemplate}
                    />
                  </div>
                  <div className="template-form-group">
                    <label className="template-form-label">文件类型</label>
                    <select
                      value={formData.file_type}
                      onChange={(e) => setFormData({...formData, file_type: e.target.value})}
                      className="template-form-select"
                    >
                      <option value="">请选择</option>
                      {fileTypes.map(item => (
                        <option key={item.value} value={item.value}>{item.label}</option>
                      ))}
                    </select>
                  </div>
                </div>
                <div className="template-form-row">
                  <div className="template-form-group">
                    <label className="template-form-label">数据库表</label>
                    <div className="flex items-center gap-2">
                      <select
                        value={formData.target_table_type}
                        onChange={(e) => setFormData({...formData, target_table_type: e.target.value, target_table: '', target_table_dict_category: '', target_table_dict_item: ''})}
                        className="template-form-select"
                        style={{ width: '120px' }}
                      >
                        <option value="fixed">固定值</option>
                        <option value="dict">字典</option>
                      </select>
                      {formData.target_table_type === 'fixed' && (
                        <input
                          type="text"
                          value={formData.target_table}
                          onChange={(e) => setFormData({...formData, target_table: e.target.value})}
                          className="template-form-input"
                          placeholder="请输入目标表名"
                        />
                      )}
                      {formData.target_table_type === 'dict' && (
                        <>
                          <select
                            value={formData.target_table_dict_category}
                            onChange={(e) => {
                              setFormData({...formData, target_table_dict_category: e.target.value, target_table_dict_item: ''});
                              fetchDictItems(e.target.value);
                            }}
                            className="template-form-select"
                            style={{ width: '150px' }}
                          >
                            <option value="">选择字典分类</option>
                            {flatCategories.map(cat => (
                              <option key={cat.code} value={cat.code}>{cat.indent}{cat.name}</option>
                            ))}
                          </select>
                          {formData.target_table_dict_category && dictItems[formData.target_table_dict_category] && (
                            <select
                              value={formData.target_table_dict_item}
                              onChange={(e) => setFormData({...formData, target_table_dict_item: e.target.value})}
                              className="template-form-select"
                              style={{ width: '150px' }}
                            >
                              <option value="">选择字典项</option>
                              {dictItems[formData.target_table_dict_category].map(item => (
                                <option key={item.value} value={item.value}>{item.label}</option>
                              ))}
                            </select>
                          )}
                          <label className="mapping-checkbox">
                            <input
                              type="checkbox"
                              checked={formData.target_table_get_value}
                              onChange={(e) => setFormData({...formData, target_table_get_value: e.target.checked})}
                            />
                            取值
                          </label>
                        </>
                      )}
                    </div>
                  </div>
                </div>
              </div>

              <div className="template-section">
                <div className="template-section-header">
                  <div>
                    <h4 className="template-section-title">公共映射</h4>
                    <span className="template-section-desc">所有分组共享的字段</span>
                  </div>
                  <button className="btn-add" onClick={addCommonMapping}>
                    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
                      <line x1="12" y1="5" x2="12" y2="19"></line>
                      <line x1="5" y1="12" x2="19" y2="12"></line>
                    </svg>
                    添加映射
                  </button>
                </div>
                <div className="template-mapping-list">
                  {formData.common_mappings.map((mapping, index) => (
                    renderMappingCard(
                      mapping, 
                      index, 
                      updateCommonMapping, 
                      removeCommonMapping,
                      copyCommonMapping,
                      moveCommonMapping
                    )
                  ))}
                </div>
              </div>

              <div className="template-section">
                <div className="template-section-header">
                  <div>
                    <h4 className="template-section-title">明细映射</h4>
                    <span className="template-section-desc">每组+公共信息生成一条记录</span>
                  </div>
                  <button className="btn btn-primary" onClick={addGroup}>
                    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
                      <line x1="12" y1="5" x2="12" y2="19"></line>
                      <line x1="5" y1="12" x2="19" y2="12"></line>
                    </svg>
                    新增分组
                  </button>
                </div>
                <div className="template-groups">
                  {formData.groups.map((group, groupIndex) => (
                    <div 
                      key={groupIndex} 
                      className="template-group-card"
                      draggable
                      onDragStart={(e) => e.dataTransfer.setData('groupIndex', groupIndex)}
                      onDragOver={(e) => e.preventDefault()}
                      onDrop={(e) => {
                        const fromIndex = parseInt(e.dataTransfer.getData('groupIndex'));
                        if (fromIndex !== groupIndex) {
                          moveGroup(fromIndex, groupIndex);
                        }
                      }}
                    >
                      <div className="template-group-header">
                        <div className="template-group-header-left">
                          <div className="template-group-drag-handle" title="拖拽排序">
                            <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
                              <circle cx="12" cy="8" r="1.5"></circle>
                              <circle cx="12" cy="12" r="1.5"></circle>
                              <circle cx="12" cy="16" r="1.5"></circle>
                              <circle cx="16" cy="8" r="1.5"></circle>
                              <circle cx="16" cy="12" r="1.5"></circle>
                              <circle cx="16" cy="16" r="1.5"></circle>
                              <circle cx="8" cy="8" r="1.5"></circle>
                              <circle cx="8" cy="12" r="1.5"></circle>
                              <circle cx="8" cy="16" r="1.5"></circle>
                            </svg>
                          </div>
                          <input
                            type="text"
                            value={group.name}
                            onChange={(e) => updateGroupName(groupIndex, e.target.value)}
                            className="template-group-name-input"
                          />
                        </div>
                        <div className="template-actions">
                          <button className="btn-copy-group" onClick={() => copyGroup(groupIndex)} title="复制分组">
                            <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
                              <rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
                              <path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>
                            </svg>
                          </button>
                          {formData.groups.length > 1 && (
                            <button className="btn-delete-group" onClick={() => removeGroup(groupIndex)} title="删除分组">
                              <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
                                <path d="M3 6h18"></path>
                                <path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6"></path>
                                <path d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2"></path>
                              </svg>
                            </button>
                          )}
                        </div>
                      </div>
                      <div className="template-mapping-list">
                        {group.mappings.map((mapping, mappingIndex) => (
                          renderMappingCard(
                            mapping, 
                            mappingIndex, 
                            (idx, field, val) => updateGroupMapping(groupIndex, idx, field, val),
                            (idx) => removeGroupMapping(groupIndex, idx),
                            (idx) => copyGroupMapping(groupIndex, idx),
                            (fromIdx, toIdx) => moveGroupMapping(groupIndex, fromIdx, toIdx),
                            groupIndex
                          )
                        ))}
                      </div>
                      <button className="btn-add" onClick={() => addGroupMapping(groupIndex)}>
                        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
                          <line x1="12" y1="5" x2="12" y2="19"></line>
                          <line x1="5" y1="12" x2="19" y2="12"></line>
                        </svg>
                        添加映射
                      </button>
                    </div>
                  ))}
                </div>
              </div>
            </div>
            
            <div className="template-drawer-footer">
              <button className="btn btn-ghost" onClick={() => setShowDrawer(false)}>取消</button>
              <button className="btn btn-primary" onClick={handleSave}>保存</button>
            </div>
          </div>
        </div>
      )}

      {showViewModal && viewingTemplate && (
        <div className="view-panel-backdrop" onClick={() => setShowViewModal(false)}>
          <div className="view-panel" onClick={(e) => e.stopPropagation()}>
            <div className="view-panel-header">
              <div>
                <h3 className="view-panel-title">模板详情</h3>
                <p className="view-panel-sub">{viewingTemplate.template_name}</p>
              </div>
              <button className="view-panel-close" onClick={() => setShowViewModal(false)}>×</button>
            </div>
            <div className="view-panel-body">
              <div className="view-template-info">
                <div className="view-info-row">
                  <span className="view-label">模板编码：</span>
                  <span className="view-value">{viewingTemplate.template_code}</span>
                </div>
                <div className="view-info-row">
                  <span className="view-label">目标表：</span>
                  <span className="view-value">{viewingTemplate.target_table}</span>
                </div>
                <div className="view-info-row">
                  <span className="view-label">文件类型：</span>
                  <span className="view-value">{viewingTemplate.file_type}</span>
                </div>
              </div>
              
              <div className="view-section">
                <h4 className="view-section-title">公共映射</h4>
                <div className="view-json-card view-card-common">
                  <pre className="view-json-content">
                    {JSON.stringify(viewingTemplate.common_mappings || [], null, 2)}
                  </pre>
                </div>
              </div>
              
              <div className="view-section">
                <h4 className="view-section-title">分组配置</h4>
                <div className="view-groups">
                  {(viewingTemplate.groups || []).map((group, index) => (
                    <div key={index} className={`view-json-card view-card-group view-card-group-${(index % 3) + 1}`}>
                      <div className="view-group-header">分组 {index + 1}: {group.name || `组${index + 1}`}</div>
                      <pre className="view-json-content">
                        {JSON.stringify(group, null, 2)}
                      </pre>
                    </div>
                  ))}
                </div>
              </div>
            </div>
            <div className="view-panel-footer">
              <button className="btn btn-ghost" onClick={() => setShowViewModal(false)}>关闭</button>
            </div>
          </div>
        </div>
      )}
    </div>
  );
}