1// frontend-react/src/components/SideBarLeft/tabs/CharacterCard/CharacterCard.jsx
import React, { useState, useEffect, useRef, useCallback, memo } from 'react'; // ✅ 保留 useState 用于 exportFormat
import { useCharacterStore, useCharacterCardUIStore } from '../../../../Store/SideBarLeft'; // ✅ 新增
import useChatBoxStore from '../../../../Store/Mid/ChatBoxSlice';
import useWorldBookStore from '../../../../Store/SideBarLeft/WorldBookSlice'; // 引入世界书 Store
import useSideBarLeftStore from '../../../../Store/SideBarLeft/SideBarLeftSlice'; // ✅ 引入侧边栏 Store
import './CharacterCard.css';

// 优化的角色卡片项组件 - 使用 memo 和 useCallback
const CharacterItem = memo(({ character, isSelected, onSelect, showImages }) => {
  const handleImageError = useCallback((e) => {
    e.target.style.display = 'none';
    e.target.nextSibling.style.display = 'flex';
  }, []);

  const handleClick = useCallback(() => {
    onSelect(character);
  }, [onSelect, character]);

  const handleKeyDown = useCallback((e) => {
    if (e.key === 'Enter' || e.key === ' ') {
      e.preventDefault();
      onSelect(character);
    }
  }, [onSelect, character]);

  return (
    <div 
      className={`character-item ${isSelected ? 'selected' : ''} ${!showImages ? 'no-image' : ''}`}
      onClick={handleClick}
      onKeyDown={handleKeyDown}
      role="button"
      tabIndex={0}
    >
      {/* 角色头像 */}
      <div className="character-avatar-wrapper">
        {character.avatarPath ? (
          <img
            src={character.avatarPath}
            alt={character.name}
            className="character-avatar-img"
            onError={handleImageError}
            loading="lazy" // 懒加载图片
          />
        ) : null}
        <div className="character-avatar-placeholder" style={{ display: character.avatarPath ? 'none' : 'flex' }}>
          {character.name.charAt(0).toUpperCase()}
        </div>
      </div>

      {/* 角色信息 */}
      <div className="character-info">
        <div className="character-name">{character.name}</div>
        {character.description && (
          <div className="character-desc">{character.description.substring(0, 50)}...</div>
        )}
        {character.tags && character.tags.length > 0 && (
          <div className="character-tags">
            {character.tags.slice(0, 3).map((tag, index) => (
              <span key={`tag-${character.id}-${tag}-${index}`} className="tag">{tag}</span>
            ))}
          </div>
        )}
      </div>
    </div>
  );
}, (prevProps, nextProps) => {
  // 自定义比较函数，只在必要时重新渲染
  return prevProps.character.id === nextProps.character.id && 
         prevProps.isSelected === nextProps.isSelected &&
         prevProps.showImages === nextProps.showImages;
});

CharacterItem.displayName = 'CharacterItem';

const CharacterCard = () => {
  const {
    characters,
    selectedCharacter,
    isLoading,
    error,
    characterChats,
    fetchCharacters,
    selectCharacter,
    deleteCharacter,
    exportCharacterAsPng,
    fetchCharacterChats
  } = useCharacterStore();

  // ✅ 从 CharacterCardUIStore 获取 UI 状态
  const {
    filterTags,
    isEditing,
    editForm,
    currentPage,
    pageSize,
    toggleFilterTag,
    removeFilterTag,
    clearAllFilters,
    startEditing,
    cancelEditing,
    updateEditForm,
    setCurrentPage,
    setPageSize,
    nextPage,
    prevPage
  } = useCharacterCardUIStore();

  // 引入世界书 Store
  const { worldBooks, fetchWorldBooks } = useWorldBookStore();

  const [exportFormat, setExportFormat] = useState('png'); // 导出格式: 'png' 或 'json'
  const [showImages, setShowImages] = useState(true); // ✅ 是否显示图片
  const fileInputRef = useRef(null);
  const clickTimeoutRef = useRef(null);

  // 加载角色列表和世界书列表
  useEffect(() => {
    fetchCharacters();
    fetchWorldBooks(); // 加载世界书列表
    
    // 清理函数
    return () => {
      if (clickTimeoutRef.current) {
        clearTimeout(clickTimeoutRef.current);
      }
    };
  }, []);

  // 获取所有唯一的 tags
  const allTags = [...new Set(characters.flatMap(char => char.tags || []))];

  // 过滤角色（支持多标签交集筛选）
  const filteredCharacters = React.useMemo(() => {
    if (filterTags.length === 0) return characters;
    
    // 分离包含和排除标签
    const includeTags = filterTags
      .filter(f => f.startsWith('include:'))
      .map(f => f.substring(8));
    
    const excludeTags = filterTags
      .filter(f => f.startsWith('exclude:'))
      .map(f => f.substring(8));
    
    return characters.filter(char => {
      const charTags = char.tags || [];
      
      // 检查是否包含所有必须的标签（交集）
      const hasAllInclude = includeTags.every(tag => charTags.includes(tag));
      
      // 检查是否不包含所有排除的标签
      const hasNoExclude = excludeTags.every(tag => !charTags.includes(tag));
      
      return hasAllInclude && hasNoExclude;
    });
  }, [characters, filterTags]);

  // ✅ 计算当前页和总页数
  const totalPages = Math.ceil(filteredCharacters.length / pageSize) || 1;
  const startIndex = (currentPage - 1) * pageSize;
  const endIndex = startIndex + pageSize;
  const currentPageCharacters = filteredCharacters.slice(startIndex, endIndex);

  // 处理导入文件
  const handleImport = async (event) => {
    const file = event.target.files[0];
    if (!file) return;

    try {
      const { importCharacter } = useCharacterStore.getState();
      await importCharacter(file);
      
      // 清空文件输入
      if (fileInputRef.current) {
        fileInputRef.current.value = '';
      }
    } catch (err) {
      console.error('导入失败:', err);
    }
  };

  // 触发文件选择
  const triggerImport = () => {
    fileInputRef.current?.click();
  };

  // 新建角色
  const handleCreate = async () => {
    const name = prompt('请输入角色名称:');
    if (!name) return;

    // ✅ 询问历史记录模式
    const historyMode = prompt(
      '请选择历史记录模式:\n' +
      '1. 全量模式（保留所有消息）\n' +
      '2. 总结模式（定期总结历史）\n' +
      '3. RAG模式（需要API配置，选择后不可取消）\n\n' +
      '请输入数字 (1/2/3):'
    );
    
    let mode = 'full';
    if (historyMode === '2') mode = 'summary';
    else if (historyMode === '3') mode = 'rag';
    
    if (mode === 'rag') {
      const confirm = window.confirm(
        '⚠️ RAG模式需要配置API，且选择后不可取消。\n' +
        '是否继续？'
      );
      if (!confirm) return;
    }

    try {
      const { createCharacter } = useCharacterStore.getState();
      await createCharacter({
        name,
        description: '',
        personality: '',
        scenario: '',
        first_mes: '',
        mes_example: '',
        categories: [],
        tags: [],
        historyMode: mode  // ✅ 添加历史记录模式
      });
    } catch (err) {
      console.error('创建失败:', err);
    }
  };

  // 删除角色
  const handleDelete = async (name) => {
    if (!confirm(`确定要删除角色 "${name}" 吗？这将删除所有聊天记录！`)) {
      return;
    }

    try {
      await deleteCharacter(name);
      
      // ✅ 删除成功后自动切换到角色分页
      const { setActiveTab } = useSideBarLeftStore.getState();
      setActiveTab('character');
      
      console.log('[CharacterCard] 角色已删除，已切换到角色分页');
    } catch (err) {
      console.error('删除失败:', err);
    }
  };

  // 导出角色
  const handleExport = async (name, format = 'png') => {
    try {
      if (format === 'json') {
        // JSON导出：获取角色数据并下载
        const response = await fetch(`/api/characters/${encodeURIComponent(name)}`);
        if (!response.ok) throw new Error('获取角色数据失败');
        
        const characterData = await response.json();
        
        // 创建JSON文件并下载
        const dataStr = JSON.stringify(characterData, null, 2);
        const dataBlob = new Blob([dataStr], { type: 'application/json' });
        const url = window.URL.createObjectURL(dataBlob);
        const a = document.createElement('a');
        a.href = url;
        a.download = `${name}.json`;
        document.body.appendChild(a);
        a.click();
        window.URL.revokeObjectURL(url);
        document.body.removeChild(a);
        
        console.log('JSON导出成功');
      } else {
        // PNG导出：调用后端API
        const response = await fetch(`/api/characters/${encodeURIComponent(name)}/export/png`, {
          method: 'POST'
        });
        
        if (!response.ok) throw new Error('导出PNG失败');
        
        // 下载文件
        const blob = await response.blob();
        const url = window.URL.createObjectURL(blob);
        const a = document.createElement('a');
        a.href = url;
        a.download = `${name}.png`;
        document.body.appendChild(a);
        a.click();
        window.URL.revokeObjectURL(url);
        document.body.removeChild(a);
        
        console.log('PNG导出成功');
      }
    } catch (err) {
      console.error('导出失败:', err);
      alert('导出失败: ' + err.message);
    }
  };

  // ✅ 复制角色
  const handleDuplicate = async (character) => {
    if (!character) return;
    
    const newName = prompt(`复制角色 "${character.name}"\n请输入新角色名称:`, `${character.name} - 副本`);
    if (!newName) return;
    
    // ✅ 询问历史记录模式
    const historyMode = prompt(
      '请选择历史记录模式:\n' +
      '1. 全量模式（保留所有消息）\n' +
      '2. 总结模式（定期总结历史）\n' +
      '3. RAG模式（需要API配置，选择后不可取消）\n\n' +
      '请输入数字 (1/2/3):'
    );
    
    let mode = 'full';
    if (historyMode === '2') mode = 'summary';
    else if (historyMode === '3') mode = 'rag';
    
    if (mode === 'rag') {
      const confirm = window.confirm(
        '⚠️ RAG模式需要配置API，且选择后不可取消。\n' +
        '是否继续？'
      );
      if (!confirm) return;
    }
    
    try {
      const { createCharacter } = useCharacterStore.getState();
      
      // 复制角色数据（排除聊天记录）
      await createCharacter({
        name: newName,
        description: character.description || '',
        personality: character.personality || '',
        scenario: character.scenario || '',
        first_mes: character.first_mes || '',
        mes_example: character.mes_example || '',
        categories: character.categories || [],
        tags: character.tags || [],
        worldInfoId: character.worldInfoId || null,
        tableHeaders: character.tableHeaders || [],
        tableDefaults: character.tableDefaults || {},
        tableMaintenancePrompt: character.tableMaintenancePrompt || null,
        imageGenerationPrompt: character.imageGenerationPrompt || null,
        historyMode: mode  // ✅ 使用新选择的历史记录模式
      });
      
      console.log(`[CharacterCard] 角色已复制: ${character.name} -> ${newName}`);
    } catch (err) {
      console.error('复制失败:', err);
      alert('复制失败: ' + err.message);
    }
  };

  // 选择角色并切换到该角色的最后聊天记录
  const handleSelectCharacter = useCallback(async (character) => {
    console.log('[CharacterCard] 点击角色:', character.name);
    
    // 清除之前的定时器，防止重复点击
    if (clickTimeoutRef.current) {
      clearTimeout(clickTimeoutRef.current);
    }
    
    // 设置防抖，避免快速连续点击
    clickTimeoutRef.current = setTimeout(async () => {
      // 使用 requestAnimationFrame 优化UI响应
      requestAnimationFrame(async () => {
        selectCharacter(character);
        
        // 进入编辑模式
        startEditing(character); // ✅ 使用 store 方法
        
        // 获取该角色的聊天列表，并自动切换到最后一个聊天
        try {
          const response = await fetch(`/api/chat/${encodeURIComponent(character.name)}`);
          if (response.ok) {
            const chats = await response.json();
            if (chats.length > 0) {
              // 有聊天记录，切换到最后一个
              const lastChat = chats[chats.length - 1].chat_name;
              
              // 先设置角色和聊天，这会触发 ChatBoxStore 的监听器自动加载聊天历史
              useChatBoxStore.getState().setChatBoxRoleAndChat(character.name, lastChat);
              
              console.log(`[CharacterCard] 已切换到角色 ${character.name} 的聊天: ${lastChat}`);
            } else {
              // 没有聊天记录，只设置角色，不创建聊天文件
              // 聊天文件将在用户发送第一条消息时创建
              console.log(`[CharacterCard] 角色 ${character.name} 没有聊天，等待用户发送第一条消息...`);
              
              // 只设置角色，不设置聊天（currentChat 为 null）
              // ChatBox 会显示开场白（临时消息），但不会保存到文件
              useChatBoxStore.getState().setChatBoxRoleAndChat(character.name, null);
            }
          }
        } catch (error) {
          console.error('[CharacterCard] 获取聊天列表失败:', error);
        }
        
        console.log('[CharacterCard] 已进入编辑模式');
      });
    }, 50); // 50ms 防抖延迟
  }, [selectCharacter]);

  // 退出编辑模式
  const handleCancelEdit = () => {
    cancelEditing(); // ✅ 使用 store 方法
  };

  // 保存编辑
  const handleSaveEdit = async () => {
    if (!editForm || !selectedCharacter) return;
    
    try {
      const { updateCharacter } = useCharacterStore.getState();
      await updateCharacter(selectedCharacter.name, editForm);
      cancelEditing(); // ✅ 使用 store 方法
    } catch (err) {
      console.error('保存失败:', err);
      alert('保存失败: ' + err.message);
    }
  };

  // 处理表单字段变化
  const handleFormChange = (field, value) => {
    updateEditForm(field, value); // ✅ 使用 store 方法
  };

  // 自动调整 textarea 高度
  const autoResizeTextarea = (e) => {
    const textarea = e.target;
    textarea.style.height = 'auto'; // 重置高度
    textarea.style.height = Math.min(textarea.scrollHeight, 300) + 'px'; // 设置新高度，最大300px
  };

  return (
    <div className="character-card-content">
      {/* 标题栏 */}
      <div className="tab-header">
        <span className="title-text">角色卡</span>
      </div>

      {/* 操作按钮 */}
      <div className="tab-actions">
        <button className="action-btn" onClick={handleCreate}>+ 新建</button>
        <button className="action-btn" onClick={triggerImport}>📥 导入</button>
        {/* ✅ 切换图片显示 */}
        <button 
          className={`action-btn ${showImages ? '' : 'active'}`} 
          onClick={() => setShowImages(!showImages)}
          title={showImages ? '隐藏图片' : '显示图片'}
        >
          {showImages ? '🖼️' : '🚫'}
        </button>
        <input
          ref={fileInputRef}
          type="file"
          accept=".png,.json"
          style={{ display: 'none' }}
          onChange={handleImport}
        />
      </div>

      {/* Tag 筛选器 */}
      {allTags.length > 0 && (
        <div className="tag-filter">
          <button
            className={`tag-btn ${filterTags.length === 0 ? 'active' : ''}`}
            onClick={clearAllFilters}
          >
            全部
          </button>
          {allTags.map(tag => {
            // 判断当前标签的状态
            let status = 'none'; // none, include, exclude
            const includeFilter = `include:${tag}`;
            const excludeFilter = `exclude:${tag}`;
            
            if (filterTags.includes(includeFilter)) {
              status = 'include';
            } else if (filterTags.includes(excludeFilter)) {
              status = 'exclude';
            }
            
            return (
              <button
                key={tag}
                className={`tag-btn tag-${status}`}
                onClick={() => toggleFilterTag(tag)}
                title={
                  status === 'include' ? '包含该标签（再次点击排除）' : 
                  status === 'exclude' ? '排除该标签（再次点击取消）' : 
                  '筛选包含该标签的角色'
                }
              >
                {status === 'exclude' && <span className="tag-prefix">¬</span>}
                {tag}
              </button>
            );
          })}
        </div>
      )}
      
      {/* 当前筛选条件显示 */}
      {filterTags.length > 0 && (
        <div className="active-filters" style={{
          display: 'flex',
          flexWrap: 'wrap',
          gap: '4px',
          padding: '4px 6px',
          alignItems: 'center'
        }}>
          <span style={{ fontSize: '11px', color: 'var(--color-text-secondary)', marginRight: '4px' }}>
            筛选中:
          </span>
          {filterTags.map((filter) => {
            const mode = filter.startsWith('include:') ? 'include' : 'exclude';
            const tag = filter.substring(filter.indexOf(':') + 1);
            return (
              <span
                key={`filter-${mode}-${tag}`}
                className={`active-filter-tag active-filter-${mode}`}
                style={{
                  display: 'inline-flex',
                  alignItems: 'center',
                  gap: '4px',
                  padding: '2px 8px',
                  borderRadius: '12px',
                  fontSize: '10px',
                  background: mode === 'include' ? 'rgba(16, 185, 129, 0.2)' : 'rgba(239, 68, 68, 0.2)',
                  border: `1px solid ${mode === 'include' ? '#10b981' : '#ef4444'}`,
                  color: mode === 'include' ? '#10b981' : '#ef4444'
                }}
              >
                {mode === 'exclude' && '¬'}
                {tag}
                <button
                  onClick={() => removeFilterTag(tag)}
                  style={{
                    background: 'none',
                    border: 'none',
                    color: 'inherit',
                    cursor: 'pointer',
                    padding: '0 2px',
                    fontSize: '12px',
                    lineHeight: 1
                  }}
                  title="移除筛选"
                >
                  ×
                </button>
              </span>
            );
          })}
        </div>
      )}

      {/* 错误提示 */}
      {error && (
        <div className="error-message">
          {error}
        </div>
      )}

      {/* 加载状态 */}
      {isLoading && (
        <div className="loading-message">
          加载中...
        </div>
      )}

      {/* 编辑模式 */}
      {isEditing && selectedCharacter && editForm && (
        <div className="character-edit-panel">
          {/* 悬浮工具栏 */}
          <div className="floating-toolbar">
            <div className="toolbar-content">
              <div className="toolbar-left">
                <span className="edit-title">编辑: {selectedCharacter.name}</span>
              </div>
              <div className="toolbar-actions">
                <select 
                  className="export-format-selector"
                  value={exportFormat}
                  onChange={(e) => setExportFormat(e.target.value)}
                  title="选择导出格式"
                >
                  <option value="png">🖼️ PNG</option>
                  <option value="json">📄 JSON</option>
                </select>
                {/* ✅ 复制角色按钮 */}
                <button 
                  className="toolbar-btn duplicate" 
                  onClick={() => handleDuplicate(selectedCharacter)} 
                  title="复制角色"
                >
                  📋
                </button>
                <button className="toolbar-btn export" onClick={() => handleExport(selectedCharacter.name, exportFormat)} title="导出角色卡">
                  📤
                </button>
                <button className="toolbar-btn delete" onClick={() => handleDelete(selectedCharacter.name)} title="删除角色">
                  🗑️
                </button>
                <button className="toolbar-btn save" onClick={handleSaveEdit} title="保存更改">
                  💾
                </button>
                <button className="toolbar-btn cancel" onClick={handleCancelEdit} title="返回列表">
                  ←
                </button>
              </div>
            </div>
            {/* 小球指示器 */}
            <div className="toolbar-indicator">
              <span className="indicator-icon">⚙️</span>
            </div>
          </div>
          
          <div className="edit-form">
            <div className="form-group">
              <label>角色名称</label>
              <input
                type="text"
                value={editForm.name}
                onChange={(e) => handleFormChange('name', e.target.value)}
                placeholder="角色名称"
              />
              <small className="form-hint">💡 提示：修改角色名将同步重命名文件夹和所有相关引用</small>
            </div>
            
            <div className="form-group">
              <label>描述</label>
              <textarea
                value={editForm.description}
                onChange={(e) => {
                  handleFormChange('description', e.target.value);
                  autoResizeTextarea(e);
                }}
                onInput={autoResizeTextarea}
                placeholder="角色描述"
                rows={6}
              />
            </div>
            
            <div className="form-group">
              <label>性格</label>
              <textarea
                value={editForm.personality}
                onChange={(e) => {
                  handleFormChange('personality', e.target.value);
                  autoResizeTextarea(e);
                }}
                onInput={autoResizeTextarea}
                placeholder="角色性格"
                rows={3}
              />
            </div>
            
            <div className="form-group">
              <label>场景</label>
              <textarea
                value={editForm.scenario}
                onChange={(e) => {
                  handleFormChange('scenario', e.target.value);
                  autoResizeTextarea(e);
                }}
                onInput={autoResizeTextarea}
                placeholder="场景设定"
                rows={3}
              />
            </div>
            
            <div className="form-group">
              <label>开场白</label>
              <textarea
                value={editForm.first_mes}
                onChange={(e) => {
                  handleFormChange('first_mes', e.target.value);
                  autoResizeTextarea(e);
                }}
                onInput={autoResizeTextarea}
                placeholder="第一条消息"
                rows={4}
              />
            </div>
            
            <div className="form-group">
              <label>对话示例</label>
              <textarea
                value={editForm.mes_example}
                onChange={(e) => {
                  handleFormChange('mes_example', e.target.value);
                  autoResizeTextarea(e);
                }}
                onInput={autoResizeTextarea}
                placeholder="对话示例"
                rows={4}
              />
            </div>
            
            <div className="form-group">
              <label>标签 (用逗号分隔)</label>
              <input
                type="text"
                value={editForm.tags.join(', ')}
                onChange={(e) => handleFormChange('tags', e.target.value.split(',').map(t => t.trim()).filter(t => t))}
                placeholder="标签1, 标签2, 标签3"
              />
            </div>
            
            <div className="form-group">
              <label>绑定世界书</label>
              <select
                value={editForm.worldInfoId || ''}
                onChange={(e) => handleFormChange('worldInfoId', e.target.value || null)}
              >
                <option key="none" value="">不绑定</option>
                {worldBooks.map(book => (
                  <option key={`worldbook-${book.id}`} value={book.id}>
                    {book.name}
                  </option>
                ))}
              </select>
              <small className="form-hint">💡 选择后，该角色将自动加载绑定的世界书内容</small>
            </div>
            
            {/* ✅ 历史记录总结设置 */}
            <div className="form-group">
              <label>历史记录模式</label>
              <select
                value={editForm.historyMode || 'full'}
                onChange={(e) => handleFormChange('historyMode', e.target.value)}
              >
                <option key="full" value="full">全量模式（保留所有消息）</option>
                <option key="summary" value="summary">总结模式（定期总结历史）</option>
                <option key="rag" value="rag" disabled={editForm.historyMode === 'rag'}>
                  RAG模式（需要API配置，选择后不可取消）
                </option>
              </select>
              <small className="form-hint">
                 全量模式：保留所有消息 | 总结模式：自动总结旧消息 | RAG模式：向量检索（需配置API）
              </small>
            </div>
            
            {/* ✅ 总结配置（仅在summary模式下显示） */}
            {(editForm.historyMode === 'summary' || editForm.summaryConfig) && (
              <div className="form-group">
                <label>总结配置</label>
                <div className="summary-config-grid">
                  <div className="summary-config-item">
                    <label>总结间隔（条）</label>
                    <input
                      type="number"
                      min="2"
                      value={editForm.summaryConfig?.interval || 10}
                      onChange={(e) => {
                        const config = editForm.summaryConfig || {};
                        handleFormChange('summaryConfig', {
                          ...config,
                          interval: Number(e.target.value)
                        });
                      }}
                    />
                  </div>
                  <div className="summary-config-item">
                    <label>保留最近楼层</label>
                    <input
                      type="number"
                      min="1"
                      value={editForm.summaryConfig?.recentFloorsToKeep || 5}
                      onChange={(e) => {
                        const config = editForm.summaryConfig || {};
                        handleFormChange('summaryConfig', {
                          ...config,
                          recentFloorsToKeep: Number(e.target.value)
                        });
                      }}
                    />
                  </div>
                  <div className="summary-config-item full-width">
                    <label>
                      <input
                        type="checkbox"
                        checked={editForm.summaryConfig?.includeUserInput !== false}
                        onChange={(e) => {
                          const config = editForm.summaryConfig || {};
                          handleFormChange('summaryConfig', {
                            ...config,
                            includeUserInput: e.target.checked
                          });
                        }}
                      />
                      总结时包含用户输入
                    </label>
                  </div>
                  <div className="summary-config-item full-width">
                    <label>总结提示词</label>
                    <textarea
                      value={editForm.summaryConfig?.summaryPrompt || '请总结以下对话内容，保留关键信息和上下文。'}
                      onChange={(e) => {
                        const config = editForm.summaryConfig || {};
                        handleFormChange('summaryConfig', {
                          ...config,
                          summaryPrompt: e.target.value
                        });
                      }}
                      rows={3}
                      placeholder="请输入总结提示词"
                    />
                  </div>
                </div>
                <small className="form-hint">
                  💡 总结间隔：AI回复达到此数量时触发总结 | 保留楼层：最近X条不总结
                </small>
              </div>
            )}
            
            <div className="form-group">
              <label>动态表格数据 (SillyTavern 关键字机制)</label>
              <input
                type="text"
                value={Object.entries(editForm.tableDefaults || {}).map(([k, v]) => `${k}:${v}`).join(';')}
                onChange={(e) => {
                  // 解析格式：key1:value1;key2:value2,key3:value3
                  // 支持分隔符：分号、逗号
                  const entries = e.target.value
                    .split(/[;,]/)
                    .map(pair => pair.trim())
                    .filter(pair => pair !== '')
                    .map(pair => {
                      const [key, ...valueParts] = pair.split(':');
                      const value = valueParts.join(':').trim(); // 支持值中包含冒号
                      return { key: key.trim(), value };
                    })
                    .filter(({ key, value }) => key && value !== undefined);
                  
                  // 构建 tableDefaults 对象
                  const tableDefaults = {};
                  const tableHeaders = [];
                  
                  entries.forEach(({ key, value }) => {
                    tableHeaders.push(key);
                    // 尝试转换为数字
                    const numValue = Number(value);
                    tableDefaults[key] = isNaN(numValue) ? value : numValue;
                  });
                  
                  handleFormChange('tableHeaders', tableHeaders);
                  handleFormChange('tableDefaults', tableDefaults);
                }}
                placeholder="力量:80;敏捷:65;智力:90;HP:100"
              />
              <small className="form-hint">格式：key:value，用分号或逗号分隔。例如：力量:80;敏捷:65,HP:100</small>
            </div>
          </div>
        </div>
      )}

      {/* 角色卡片列表 */}
      {!isLoading && !isEditing && (
        <>
          <div className="character-list">
            {currentPageCharacters.length === 0 ? (
              <div className="empty-message">
                {filterTags.length > 0 ? '没有符合筛选的角色' : '暂无角色，请导入或创建'}
              </div>
            ) : (
              currentPageCharacters.map(char => (
                <CharacterItem
                  key={char.id}
                  character={char}
                  isSelected={selectedCharacter?.id === char.id}
                  onSelect={handleSelectCharacter}
                  showImages={showImages}
                />
              ))
            )}
          </div>
          
          {/* 分页控件 */}
          {totalPages > 1 && (
            <div className="pagination-controls">
              <button 
                className="pagination-btn"
                onClick={prevPage} // ✅ 使用 store 方法
                disabled={currentPage === 1}
              >
                上一页
              </button>
              
              <span className="pagination-info">
                第 {currentPage} / {totalPages} 页
              </span>
              
              <button 
                className="pagination-btn"
                onClick={nextPage} // ✅ 使用 store 方法
                disabled={currentPage === totalPages}
              >
                下一页
              </button>
              
              <select 
                className="page-size-selector"
                value={pageSize}
                onChange={(e) => setPageSize(Number(e.target.value))} // ✅ 使用 store 方法
              >
                <option key="8" value={8}>8条/页</option>
                <option key="12" value={12}>12条/页</option>
                <option key="20" value={20}>20条/页</option>
                <option key="50" value={50}>50条/页</option>
              </select>
            </div>
          )}
        </>
      )}
    </div>
  );
};

export default CharacterCard;
