# useTable 与 search-form 组件兼容使用说明

## 概述

`useTable` Hook **完全兼容**自定义 `<search-form>` 组件。只需要将搜索表单的数据对象作为 `queryForm` 传入即可。

## 兼容原理

1. **`search-form` 组件**：只是一个表单包装器，接收 `model` prop 绑定到内部的 `el-form`
2. **`useTable` Hook**：接收 `queryForm` 对象，会自动将其合并到 API 请求参数中
3. **两者配合**：将 `search-form` 的 `model` 对象作为 `useTable` 的 `queryForm` 传入即可

## 改造示例

### 当前代码（手动管理）

```vue
<template>
  <!-- 搜索表单 -->
  <search-form 
    v-show="showSearch" 
    :model="search" 
    ref="searchFormRef"
    @keyup-enter="handleFilter(search)"
  >
    <!-- 表单项 -->
  </search-form>

  <!-- 表格 -->
  <el-table :data="tableData" v-loading="tableLoading">
    <!-- 表格列 -->
  </el-table>

  <!-- 分页 -->
  <pagination
    :current="page.currentPage"
    :size="page.pageSize"
    :total="page.total"
    @currentChange="currentChange"
    @sizeChange="handleSizeChange"
  />
</template>

<script setup lang="ts">
const search = reactive({
  deptCode: '',
  realName: '',
  teacherNo: '',
  // ... 其他字段
})

const tableData = ref([])
const tableLoading = ref(false)
const page = reactive({
  currentPage: 1,
  pageSize: 10,
  total: 0
})
const params = ref<any>({})

// 手动实现数据加载
const getList = (page: any) => {
  tableLoading.value = true
  fetchList(Object.assign({
    current: page.currentPage,
    size: page.pageSize
  }, params.value)).then((response: any) => {
    tableData.value = response.data.record.records
    page.total = response.data.record.total
    tableLoading.value = false
  })
}

// 手动实现分页
const currentChange = (val: number) => {
  page.currentPage = val
  getList(page)
}

const handleSizeChange = (val: number) => {
  page.pageSize = val
  page.currentPage = 1
  getList(page)
}

// 查询
const handleFilter = (param: any) => {
  params.value = { ...param }
  page.currentPage = 1
  getList(page)
}

onMounted(() => {
  getList(page)
})
</script>
```

### 改造后代码（使用 useTable）

```vue
<template>
  <!-- 搜索表单 - 保持不变 -->
  <search-form 
    v-show="showSearch" 
    :model="search" 
    ref="searchFormRef"
    @keyup-enter="handleFilter(search)"
  >
    <!-- 表单项 -->
  </search-form>

  <!-- 表格 - 使用 state.dataList 和 state.loading -->
  <el-table 
    :data="state.dataList" 
    v-loading="state.loading"
    :cell-style="tableStyle.cellStyle"
    :header-cell-style="tableStyle.headerCellStyle"
  >
    <!-- 表格列 -->
  </el-table>

  <!-- 分页 - 使用 state.pagination -->
  <pagination
    :current="state.pagination.current"
    :size="state.pagination.size"
    :total="state.pagination.total"
    @currentChange="currentChangeHandle"
    @sizeChange="sizeChangeHandle"
  />
</template>

<script setup lang="ts">
import { BasicTableProps, useTable } from '/@/hooks/table'
import { fetchList } from '/@/api/professional/teacherbase'

// 搜索表单数据 - 保持不变
const search = reactive({
  deptCode: '',
  realName: '',
  teacherNo: '',
  // ... 其他字段
})

// 额外参数（如 flag 等）
const params = ref<any>({})

// 配置 useTable
const state: BasicTableProps = reactive<BasicTableProps>({
  // 将 search 对象作为 queryForm
  queryForm: search,
  
  // 自定义 pageList 方法，合并额外参数
  pageList: async (queryParams: any) => {
    // 合并 search 和 params 中的额外参数
    return await fetchList({
      ...queryParams,
      ...params.value
    })
  },
  
  // 数据属性映射（根据后端返回结构调整）
  props: {
    item: 'record.records',  // 数据列表路径
    totalCount: 'record.total'  // 总数字段路径
  },
  
  // 数据加载完成后的回调
  onLoaded: async (state) => {
    // 数据转换逻辑
    state.dataList = convertDictData(state.dataList)
    
    // 其他处理逻辑（如 auditAll）
    // ...
  }
})

// 使用 useTable Hook
const {
  getDataList,
  currentChangeHandle,
  sizeChangeHandle,
  tableStyle,
  state
} = useTable(state)

// 查询方法 - 简化
const handleFilter = (param: any) => {
  // 更新额外参数
  params.value = { ...param }
  // 调用 getDataList 刷新数据（会自动跳转到第一页）
  getDataList()
}

// 重置查询
const resetQuery = () => {
  searchFormRef.value?.formRef?.resetFields()
  // 重置 search 对象
  Object.keys(search).forEach(key => {
    search[key] = ''
  })
  params.value = {}
  getDataList()
}

// 其他需要刷新表格的地方
const handelQuickSeach = (val: any) => {
  params.value.flag = val
  getDataList()  // 使用 getDataList 替代 getList(page)
}

const updateInoutFlag = (row: any, val: any) => {
  const updateParams = {"teacherNo": row.teacherNo, "inoutFlag": val}
  messageBox.confirm('确认操作?').then(() => {
    updateInout(updateParams).then((res: any) => {
      message.success("修改成功")
      getDataList(false)  // 刷新但保持当前页
    })
  })
}

// 数据转换函数（保持不变）
const convertDictData = (records: any[]) => {
  // ... 转换逻辑
  return records
}
</script>
```

## 关键改造点

### 1. 导入 useTable

```typescript
import { BasicTableProps, useTable } from '/@/hooks/table'
```

### 2. 配置 state

```typescript
const state: BasicTableProps = reactive<BasicTableProps>({
  queryForm: search,  // 将 search 对象作为 queryForm
  pageList: fetchList,  // 或自定义方法
  props: {
    item: 'record.records',
    totalCount: 'record.total'
  }
})
```

### 3. 处理额外参数

如果查询时需要额外的参数（如 `params.value.flag`），有两种方式：

#### 方式一：自定义 pageList 方法（推荐）

```typescript
const params = ref<any>({})

const state: BasicTableProps = reactive<BasicTableProps>({
  queryForm: search,
  pageList: async (queryParams: any) => {
    // 合并额外参数
    return await fetchList({
      ...queryParams,
      ...params.value  // 合并额外参数
    })
  }
})
```

#### 方式二：在 onLoaded 中处理

```typescript
const state: BasicTableProps = reactive<BasicTableProps>({
  queryForm: search,
  pageList: fetchList,
  onLoaded: async (state) => {
    // 可以在这里处理数据转换等逻辑
  }
})
```

### 4. 替换数据引用

| 原代码 | 改造后 |
|--------|--------|
| `tableData` | `state.dataList` |
| `tableLoading` | `state.loading` |
| `page.currentPage` | `state.pagination.current` |
| `page.pageSize` | `state.pagination.size` |
| `page.total` | `state.pagination.total` |

### 5. 替换方法调用

| 原代码 | 改造后 |
|--------|--------|
| `getList(page)` | `getDataList()` 或 `getDataList(false)` |
| `currentChange(val)` | `currentChangeHandle(val)` |
| `handleSizeChange(val)` | `sizeChangeHandle(val)` |

### 6. 处理数据转换

如果需要在数据加载后进行转换，使用 `onLoaded` 回调：

```typescript
const state: BasicTableProps = reactive<BasicTableProps>({
  queryForm: search,
  pageList: fetchList,
  onLoaded: async (state) => {
    // 字典数据转换
    state.dataList = convertDictData(state.dataList)
    
    // 处理 auditAll 等逻辑
    // 注意：需要在 API 响应中获取，或通过其他方式处理
  }
})
```

## 完整改造示例（针对当前页面）

```typescript
// 1. 导入 useTable
import { BasicTableProps, useTable } from '/@/hooks/table'

// 2. 搜索表单数据（保持不变）
const search = reactive({
  deptCode: '',
  secDeptCode: '',
  tied: '',
  realName: '',
  teacherNo: '',
  retireDate: '',
  pfTitleId: '',
  stationDutyLevelId: '',
  politicsStatus: '',
  teacherCate: '',
  inoutFlag: ''
})

// 3. 额外参数（用于 flag 等）
const params = ref<any>({})

// 4. 配置 useTable
const state: BasicTableProps = reactive<BasicTableProps>({
  queryForm: search,  // 将 search 作为 queryForm
  
  // 自定义 pageList，合并额外参数
  pageList: async (queryParams: any) => {
    // 合并 search 和 params
    const mergedParams = {
      ...queryParams,
      ...params.value,
      tied: search.tied  // 如果需要特殊处理
    }
    return await fetchList(mergedParams)
  },
  
  // 数据属性映射
  props: {
    item: 'record.records',
    totalCount: 'record.total'
  },
  
  // 数据加载完成回调
  onLoaded: async (state) => {
    // 字典数据转换
    state.dataList = convertDictData(state.dataList)
    
    // 注意：auditAll 需要从 API 响应中获取
    // 如果 API 返回在 response.data.auditAll，需要特殊处理
  }
})

// 5. 使用 useTable
const {
  getDataList,
  currentChangeHandle,
  sizeChangeHandle,
  tableStyle,
  state
} = useTable(state)

// 6. 查询方法（简化）
const handleFilter = (param: any) => {
  params.value = { ...param }
  getDataList()  // 自动跳转到第一页
}

// 7. 重置查询
const resetQuery = () => {
  searchFormRef.value?.formRef?.resetFields()
  Object.keys(search).forEach(key => {
    search[key] = ''
  })
  params.value = {}
  getDataList()
}

// 8. 快速查询
const handelQuickSeach = (val: any) => {
  params.value.flag = val
  getDataList()
}

// 9. 其他需要刷新的地方
const updateInoutFlag = (row: any, val: any) => {
  const updateParams = {"teacherNo": row.teacherNo, "inoutFlag": val}
  messageBox.confirm('确认操作?').then(() => {
    updateInout(updateParams).then((res: any) => {
      message.success("修改成功")
      getDataList(false)  // 保持当前页
    })
  })
}
```

## 注意事项

### 1. API 响应结构

如果 API 返回结构是 `response.data.record.records`，需要配置 `props`：

```typescript
props: {
  item: 'record.records',
  totalCount: 'record.total'
}
```

### 2. 额外参数处理

如果查询时需要额外的参数（不在 `search` 对象中），使用自定义 `pageList` 方法合并：

```typescript
pageList: async (queryParams: any) => {
  return await fetchList({
    ...queryParams,
    ...params.value,  // 额外参数
    // 或其他特殊参数
  })
}
```

### 3. 数据转换

如果需要在数据加载后进行转换，使用 `onLoaded` 回调：

```typescript
onLoaded: async (state) => {
  state.dataList = convertDictData(state.dataList)
}
```

### 4. 特殊响应字段

如果 API 响应中有特殊字段（如 `auditAll`），需要在 `onLoaded` 中处理，或者自定义 `pageList` 方法：

```typescript
pageList: async (queryParams: any) => {
  const response = await fetchList({
    ...queryParams,
    ...params.value
  })
  
  // 处理特殊字段
  if (response.data.auditAll == '0') {
    auditAll.value = false
  } else {
    auditAll.value = true
  }
  
  return response
}
```

### 5. 初始化数据加载

`useTable` 默认会在 `onMounted` 时自动加载数据。如果不需要自动加载，设置：

```typescript
const state: BasicTableProps = reactive<BasicTableProps>({
  queryForm: search,
  pageList: fetchList,
  createdIsNeed: false  // 禁用自动加载
})

// 手动调用
onMounted(() => {
  init()
  loadSearchDictData()
  getDataList()  // 手动加载
})
```

## 优势总结

使用 `useTable` 后：

1. ✅ **代码量减少**：不需要手动管理 `tableData`、`tableLoading`、`page`
2. ✅ **自动状态管理**：loading、分页、数据自动管理
3. ✅ **统一方法**：`getDataList()` 统一刷新数据
4. ✅ **兼容性好**：完全兼容自定义 `search-form` 组件
5. ✅ **灵活扩展**：支持自定义 `pageList`、`onLoaded` 等回调

## 总结

**`useTable` 完全兼容自定义 `<search-form>` 组件**，只需要：

1. 将 `search` 对象作为 `queryForm` 传入
2. 使用 `state.dataList`、`state.loading`、`state.pagination` 替代手动管理的状态
3. 使用 `getDataList()` 替代 `getList(page)`
4. 使用 `currentChangeHandle`、`sizeChangeHandle` 替代手动分页方法

如果有额外参数或特殊处理，使用自定义 `pageList` 方法或 `onLoaded` 回调即可。

