# 通用批量导入组件使用指南

## 📦 组件位置
`/frontend/src/components/common/BatchImportDialog.tsx`

## 🎯 设计理念

这是一个高度可配置的通用批量导入组件，支持：
- ✅ 自定义字段定义
- ✅ 灵活的数据验证
- ✅ 层级关系（父子关系）
- ✅ 国际化支持
- ✅ 统一的用户体验

## 📖 使用示例

### 示例 1：部门批量导入（支持层级）

```typescript
import BatchImportDialog, { BatchImportConfig } from '@/components/common/BatchImportDialog';
import { batchCreateDepartments, CreateDepartmentDto } from '@/services/api/organization';

// 配置部门批量导入
const departmentImportConfig: BatchImportConfig<CreateDepartmentDto> = {
  moduleName: '部门',
  
  // 字段定义
  fields: [
    {
      key: 'name',
      label: () => t.organization?.deptMgmt?.batchImport?.template?.fields?.name || '部门名称',
      description: () => t.organization?.deptMgmt?.batchImport?.template?.fields?.nameDesc || '部门的显示名称',
      required: true,
    },
    {
      key: 'code',
      label: () => t.organization?.deptMgmt?.batchImport?.template?.fields?.code || '部门编码',
      description: () => t.organization?.deptMgmt?.batchImport?.template?.fields?.codeDesc || '部门的唯一编码',
      required: true,
      validate: (value) => {
        if (!/^[A-Z0-9_-]+$/.test(value)) {
          return '部门编码格式错误（只能包含大写字母、数字、下划线和连字符）';
        }
        return null;
      },
    },
    {
      key: 'parentCode',
      label: () => t.organization?.deptMgmt?.batchImport?.template?.fields?.parentCode || '上级部门编码',
      description: () => t.organization?.deptMgmt?.batchImport?.template?.fields?.parentCodeDesc || '如果是子部门，填写上级部门的编码',
      required: false,
    },
    {
      key: 'description',
      label: () => t.organization?.deptMgmt?.batchImport?.template?.fields?.description || '描述',
      required: false,
    },
    {
      key: 'order',
      label: () => t.organization?.deptMgmt?.batchImport?.template?.fields?.order || '排序',
      required: false,
      transform: (value) => value ? Number(value) : undefined,
    },
  ],
  
  // 模板示例数据
  templateData: [
    {
      name: '技术部',
      code: 'TECH',
      parentCode: '',
      description: '技术研发部门',
      order: 1,
    },
    {
      name: '前端组',
      code: 'TECH-FE',
      parentCode: 'TECH',
      description: '前端开发组',
      order: 1,
    },
  ],
  
  // 支持层级关系
  supportHierarchy: true,
  hierarchyConfig: {
    parentKey: 'parentCode',
    getParentIdentifier: (row) => row.parentCode,
    extractIdentifier: (item) => item.code,
  },
  
  // API 调用
  batchCreateFn: batchCreateDepartments,
  
  // 数据转换
  transformToApiFormat: (row, context) => ({
    name: row.name,
    code: row.code,
    parentId: context?.parentId || context?.currentOrganizationId,
    description: row.description,
    order: row.order,
  }),
  
  // 国际化配置
  i18n: {
    title: () => t.organization?.deptMgmt?.batchImport?.title || '批量创建部门',
    downloadTemplate: () => t.organization?.deptMgmt?.batchImport?.template?.downloaded || '模板已下载',
    uploadTitle: () => t.organization?.deptMgmt?.batchImport?.upload?.title || '上传Excel文件',
    uploadPlaceholder: () => t.organization?.deptMgmt?.batchImport?.upload?.placeholder || '点击选择文件',
    validData: () => t.organization?.deptMgmt?.batchImport?.validation?.validData || '有效数据',
    invalidData: () => t.organization?.deptMgmt?.batchImport?.validation?.invalidData || '无效数据',
    importSuccess: (count) => `批量导入成功！共创建 ${count} 个部门`,
    importPartial: (success, failed) => `导入完成：成功 ${success} 个，失败 ${failed} 个`,
    importFailed: () => '批量导入失败',
  },
};

// 在组件中使用
function DepartmentManagementPage() {
  const [showBatchImport, setShowBatchImport] = useState(false);
  const [currentOrganizationId, setCurrentOrganizationId] = useState<string>();

  return (
    <>
      <button onClick={() => setShowBatchImport(true)}>
        批量创建部门
      </button>

      <BatchImportDialog
        isOpen={showBatchImport}
        onClose={() => setShowBatchImport(false)}
        onSuccess={() => {
          loadDepartments();
          setShowBatchImport(false);
        }}
        config={departmentImportConfig}
        context={{ currentOrganizationId }}
      />
    </>
  );
}
```

### 示例 2：用户批量导入（简单导入，无层级）

```typescript
import BatchImportDialog, { BatchImportConfig } from '@/components/common/BatchImportDialog';
import { batchCreateUsers, CreateUserDto } from '@/services/api/users';

const userImportConfig: BatchImportConfig<CreateUserDto> = {
  moduleName: '用户',
  
  fields: [
    {
      key: 'username',
      label: '用户名',
      description: '登录用户名，唯一标识',
      required: true,
    },
    {
      key: 'email',
      label: '邮箱',
      description: '用户邮箱地址',
      required: true,
      validate: (value) => {
        if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value)) {
          return '邮箱格式不正确';
        }
        return null;
      },
    },
    {
      key: 'displayName',
      label: '显示名称',
      description: '用户显示名称',
      required: true,
    },
    {
      key: 'phone',
      label: '手机号',
      required: false,
    },
    {
      key: 'departmentCode',
      label: '部门编码',
      description: '所属部门的编码',
      required: false,
    },
  ],
  
  templateData: [
    {
      username: 'zhangsan',
      email: 'zhangsan@example.com',
      displayName: '张三',
      phone: '13800138000',
      departmentCode: 'TECH',
    },
  ],
  
  // 不支持层级关系
  supportHierarchy: false,
  
  batchCreateFn: batchCreateUsers,
  
  transformToApiFormat: (row) => ({
    username: row.username,
    email: row.email,
    displayName: row.displayName,
    phone: row.phone,
    departmentCode: row.departmentCode,
  }),
  
  i18n: {
    title: '批量导入用户',
    downloadTemplate: '模板已下载',
    uploadTitle: '上传Excel文件',
    uploadPlaceholder: '点击选择文件',
    validData: '有效数据',
    invalidData: '无效数据',
    importSuccess: (count) => `批量导入成功！共创建 ${count} 个用户`,
    importPartial: (success, failed) => `导入完成：成功 ${success} 个，失败 ${failed} 个`,
    importFailed: '批量导入失败',
  },
};
```

### 示例 3：岗位批量导入

```typescript
const positionImportConfig: BatchImportConfig<CreatePositionDto> = {
  moduleName: '岗位',
  
  fields: [
    {
      key: 'name',
      label: '岗位名称',
      required: true,
    },
    {
      key: 'code',
      label: '岗位编码',
      required: true,
      validate: (value) => {
        if (!/^[A-Z_]+$/.test(value)) {
          return '岗位编码只能包含大写字母和下划线';
        }
        return null;
      },
    },
    {
      key: 'level',
      label: '职级',
      description: '职级范围 1-20',
      required: false,
      transform: (value) => value ? Number(value) : undefined,
      validate: (value) => {
        if (value && (value < 1 || value > 20)) {
          return '职级范围必须在 1-20 之间';
        }
        return null;
      },
    },
    {
      key: 'description',
      label: '描述',
      required: false,
    },
  ],
  
  templateData: [
    {
      name: '高级工程师',
      code: 'SENIOR_ENGINEER',
      level: 15,
      description: '资深技术专家',
    },
  ],
  
  supportHierarchy: false,
  
  batchCreateFn: batchCreatePositions,
  
  transformToApiFormat: (row) => ({
    name: row.name,
    code: row.code,
    level: row.level,
    description: row.description,
  }),
  
  i18n: {
    title: '批量创建岗位',
    downloadTemplate: '模板已下载',
    uploadTitle: '上传Excel文件',
    uploadPlaceholder: '点击选择文件',
    validData: '有效数据',
    invalidData: '无效数据',
    importSuccess: (count) => `批量导入成功！共创建 ${count} 个岗位`,
    importPartial: (success, failed) => `导入完成：成功 ${success} 个，失败 ${failed} 个`,
    importFailed: '批量导入失败',
  },
};
```

## 🔧 配置说明

### ExcelFieldConfig

| 属性 | 类型 | 说明 |
|------|------|------|
| `key` | `string` | 字段唯一标识 |
| `label` | `string \| () => string` | 显示标签，支持国际化函数 |
| `description` | `string \| () => string` | 字段描述（可选） |
| `required` | `boolean` | 是否必填 |
| `validate` | `(value, row) => string \| null` | 自定义验证函数 |
| `transform` | `(value) => any` | 数据类型转换函数 |

### BatchImportConfig

| 属性 | 类型 | 说明 |
|------|------|------|
| `moduleName` | `string` | 模块名称，用于文件名 |
| `fields` | `ExcelFieldConfig[]` | 字段配置数组 |
| `templateData` | `any[]` | 模板示例数据 |
| `supportHierarchy` | `boolean` | 是否支持层级关系 |
| `hierarchyConfig` | `object` | 层级关系配置（可选） |
| `batchCreateFn` | `function` | 批量创建 API 函数 |
| `transformToApiFormat` | `function` | 数据转换函数 |
| `i18n` | `object` | 国际化文本配置 |

## ✨ 特性

### 1. 灵活的字段配置
- 支持必填/可选字段
- 自定义验证规则
- 数据类型转换

### 2. 层级关系支持
- 自动处理父子关系
- 两阶段创建（先父后子）
- 智能关联父级ID

### 3. 国际化支持
- 所有文本支持国际化
- 支持函数形式动态获取文本

### 4. 统一的用户体验
- 一致的界面设计
- 统一的交互流程
- 标准的错误处理

### 5. 实时验证反馈
- 上传时即时解析
- 清晰的有效/无效数据展示
- 详细的错误原因说明

## 🎯 优势

1. **代码复用** - 一次开发，多处使用
2. **易于维护** - 集中管理，统一升级
3. **类型安全** - 完整的 TypeScript 支持
4. **高度可配置** - 满足各种业务场景
5. **一致体验** - 所有批量导入界面统一

## 📝 注意事项

1. **字段顺序**：`fields` 数组的顺序决定了 Excel 列的顺序
2. **必填标记**：必填字段会在列标题后添加 `*` 标记
3. **验证时机**：数据验证在文件解析时进行
4. **层级关系**：支持最多两层的父子关系（可扩展）
5. **错误处理**：建议在 `batchCreateFn` 中处理业务异常

## 🚀 未来扩展

可以考虑增加以下功能：
- [ ] 支持多级层级关系（3层以上）
- [ ] 支持字段间的依赖验证
- [ ] 支持导入前预览
- [ ] 支持导入失败后下载错误报告
- [ ] 支持增量导入（更新已存在的记录）

