# UserSelect 用户选择组件

## 功能特性

- ✅ 支持双栏选择器布局
- ✅ 支持搜索功能（左右两侧独立搜索）
- ✅ 三种操作方式：双击、勾选+按钮、全部按钮
- ✅ **支持滚动分页加载**（性能优化）
- ✅ 支持传入静态数据或API方法
- ✅ 完全封装的样式和逻辑

## Props 配置

| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| visible | Boolean | false | 控制弹窗显示/隐藏 |
| mode | 'add' \| 'remove' | 'add' | 选择模式 |
| title | String | '人员选择' | 弹窗标题 |
| leftTitle | String | '可选人员' | 左侧面板标题 |
| rightTitle | String | '已选人员' | 右侧面板标题 |
| availableUsers | UserVO[] | [] | 左区域静态数据 |
| initialTargetUsers | UserVO[] | [] | 初始已选人员 |
| loading | Boolean | false | 确认按钮加载状态 |
| **usePagination** | Boolean | false | **是否启用分页加载** |
| **fetchApi** | Function | undefined | **分页加载API方法** |
| **filterParams** | Object | {} | **API过滤参数** |
| **pageSize** | Number | 20 | **每页数量** |

## Events 事件

| 事件名 | 参数 | 说明 |
|--------|------|------|
| update:visible | (value: boolean) | 更新弹窗显示状态 |
| confirm | (users: UserVO[]) | 确认提交，返回选中的用户列表 |
| cancel | - | 取消操作 |

## 使用方式

### 方式一：传入静态数据（适合数据量少的场景）

```vue
<template>
  <UserSelect
    v-model:visible="showSelector"
    mode="add"
    title="选择用户"
    :available-users="allUsers"
    :initial-target-users="[]"
    @confirm="handleConfirm"
  />
</template>

<script setup lang="ts">
import { ref } from 'vue';
import { UserSelect } from '@/components';
import type { UserVO } from '@/types';

const showSelector = ref(false);
const allUsers = ref<UserVO[]>([]);

function handleConfirm(selectedUsers: UserVO[]) {
  console.log('选中的用户:', selectedUsers);
  showSelector.value = false;
}
</script>
```

### 方式二：使用分页加载（推荐，适合数据量大的场景）

```vue
<template>
  <UserSelect
    v-model:visible="showSelector"
    mode="add"
    title="选择用户"
    :use-pagination="true"
    :fetch-api="userApi.getUserPage"
    :filter-params="filterParams"
    :page-size="20"
    :loading="saving"
    @confirm="handleConfirm"
  />
</template>

<script setup lang="ts">
import { ref } from 'vue';
import { UserSelect } from '@/components';
import { userApi } from '@/apis/system';
import type { UserVO } from '@/types';

const showSelector = ref(false);
const saving = ref(false);
const filterParams = ref({
  // 可以添加额外的过滤条件
  status: 0
});

async function handleConfirm(selectedUsers: UserVO[]) {
  saving.value = true;
  try {
    // 处理业务逻辑
    for (const user of selectedUsers) {
      await someApi.addUser(user.id);
    }
    showSelector.value = false;
  } finally {
    saving.value = false;
  }
}
</script>
```

### 方式三：混合模式（添加模式用分页，删除模式用静态）

```vue
<template>
  <UserSelect
    v-model:visible="showSelector"
    :mode="selectorMode"
    :title="selectorMode === 'add' ? '添加人员' : '删除人员'"
    :available-users="selectorMode === 'remove' ? currentUsers : []"
    :use-pagination="selectorMode === 'add'"
    :fetch-api="selectorMode === 'add' ? userApi.getUserPage : undefined"
    :filter-params="filterParams"
    @confirm="handleConfirm"
  />
</template>

<script setup lang="ts">
import { ref } from 'vue';
import { UserSelect } from '@/components';
import { userApi } from '@/apis/system';
import type { UserVO } from '@/types';

const showSelector = ref(false);
const selectorMode = ref<'add' | 'remove'>('add');
const currentUsers = ref<UserVO[]>([]);
const filterParams = ref({});

function handleConfirm(selectedUsers: UserVO[]) {
  if (selectorMode.value === 'add') {
    // 添加用户逻辑
  } else {
    // 删除用户逻辑
  }
}
</script>
```

## API 方法要求

使用 `usePagination` 时，`fetchApi` 方法需要符合以下签名：

```typescript
async function fetchApi(
  pageParam: PageParam, 
  filter?: any
): Promise<ResultDomain<UserVO>>
```

### PageParam 类型

```typescript
interface PageParam {
  page: number;  // 当前页码（从1开始）
  size: number;  // 每页数量
}
```

### ResultDomain 类型

```typescript
interface ResultDomain<T> {
  success: boolean;
  message?: string;
  dataList?: T[];
  pageParam?: {
    totalElements: number;  // 总记录数
    // ... 其他分页信息
  };
}
```

## 特性说明

### 滚动分页加载

- 当启用 `usePagination` 时，左侧面板支持滚动加载更多数据
- 滚动到距离底部 50px 时自动加载下一页
- 显示加载状态和"已加载全部数据"提示
- 搜索时自动重置分页并重新加载

### 搜索功能

- **分页模式**：搜索关键词会传递给 API，在服务端进行过滤
- **静态模式**：搜索在前端进行过滤

### 数据过滤

组件会自动过滤掉右侧已选择的用户，避免重复选择。

## 性能优化建议

1. **数据量 < 100**：使用静态数据模式
2. **数据量 > 100**：使用分页加载模式
3. **数据量 > 1000**：使用分页加载 + 服务端搜索

## 注意事项

1. 使用分页模式时，`availableUsers` 会被忽略
2. 删除模式下通常使用静态数据（当前已分配的用户）
3. `filterParams` 支持传入额外的过滤条件，会合并到 API 请求中

