<template>
  <!-- MyCard 组件，可能是一个自定义的卡片组件 -->
  <MyCard>
    <!-- 当 columns 数组长度大于 0 时显示搜索表单 -->
    <div class="card table-search" v-if="columns.length">
      <!-- el-form 组件，用于创建表单 -->
      <el-form ref="formRef" :model="searchParam">
        <!-- Grid 组件，可能是一个用于布局的网格组件 -->
        <Grid
          ref="gridRef"
          :collapsed="collapsed"
          :gap="[20, 0]"
          :cols="searchCol"
        >
          <!-- 循环渲染 GridItem 组件，每个 GridItem 对应一个搜索表单字段 -->
          <GridItem
            v-for="(item, index) in columns"
            :key="item.prop"
            v-bind="getResponsive(item)"
            :index="index"
          >
            <!-- el-form-item 组件，用于创建表单字段 -->
            <el-form-item :label="`${item.label} :`">
              <!-- SearchFormItem 组件，用于渲染具体的搜索表单字段 -->
              <SearchFormItem :column="item" :searchParam="searchParam" />
            </el-form-item>
          </GridItem>
          <!-- 带有 suffix 标志的 GridItem 组件，用于放置操作按钮 -->
          <GridItem suffix>
            <div class="operation">
              <!-- 搜索按钮，点击时调用 search 方法 -->
              <el-button
                class="bg-blue clickSearchBtn"
                type="primary"
                :icon="Search"
                @click="search"
              >
                搜索
              </el-button>
              <!-- 重置按钮，点击时调用 reset 方法 -->
              <el-button :icon="Delete" @click="reset">重置</el-button>
              <!-- 展开/合并按钮，根据 collapsed 的值显示不同的文本和图标 -->
              <el-button
                v-if="showCollapse"
                link
                class="search-isOpen"
                @click="collapsed =!collapsed"
              >
                {{ collapsed? '展开' : '合并' }}
                <el-icon class="el-icon--right">
                  <component :is="collapsed? ArrowDown : ArrowUp"></component>
                </el-icon>
              </el-button>
            </div>
          </GridItem>
        </Grid>
      </el-form>
    </div>
  </MyCard>
</template>

<script setup lang="ts" name="SearchForm">
// 导入 Vue 相关的函数
import { computed, onMounted, ref } from 'vue'
// 导入 ProTable 组件的列配置接口
import { ColumnProps } from '@/components/ProTable/interface'
// 导入 Grid 组件的响应式断点接口
import { BreakPoint } from '@/components/Grid/interface'
// 导入 Element Plus 的图标组件
import { Delete, Search, ArrowDown, ArrowUp } from '@element-plus/icons-vue'
// 导入 SearchFormItem 组件
import SearchFormItem from './components/SearchFormItem.vue'
// 导入 Grid 组件
import Grid from '@/components/Grid/index.vue'
// 导入 GridItem 组件
import GridItem from '@/components/Grid/components/GridItem.vue'
// 导入 MyCard 组件
import MyCard from '../my-card/my-card.vue'

// 定义 ProTableProps 接口，描述组件的属性
interface ProTableProps {
  // 搜索配置列，可选，默认值为一个空数组
  columns?: ColumnProps[]
  // 搜索参数，可选，默认值为一个空对象
  searchParam?: { [key: string]: any }
  // 搜索列的布局配置，可以是一个数字或一个根据断点设置列数的对象
  searchCol: number | Record<BreakPoint, number>
  // 搜索方法，必传
  search: (params: any) => void
  // 重置方法，必传
  reset: (params: any) => void
}

// 使用 withDefaults 为组件属性设置默认值
const props = withDefaults(defineProps<ProTableProps>(), {
  columns: () => [],
  searchParam: () => ({})
})

// 定义一个函数，用于获取搜索列的响应式设置
const getResponsive = (item: ColumnProps) => {
  return {
    // 搜索列的跨度，从 item.search.span 获取，可选
    span: item.search?.span,
    // 搜索列的偏移量，从 item.search.offset 获取，可选，默认值为 0
    offset: item.search?.offset?? 0,
    // 不同断点下的响应式配置，从 item.search 中对应断点的属性获取，可选
    xs: item.search?.xs,
    sm: item.search?.sm,
    md: item.search?.md,
    lg: item.search?.lg,
    xl: item.search?.xl
  }
}

// 定义一个响应式变量，用于控制搜索项是否默认折叠
const collapsed = ref(true)

// 定义一个 ref，用于引用 Grid 组件
const gridRef = ref()
// 计算属性，获取当前的响应式断点
const breakPoint = computed<BreakPoint>(() => gridRef.value?.breakPoint)

// 计算属性，判断是否显示展开/合并按钮
const showCollapse = computed(() => {
  let show = false
  // 遍历 columns 数组，计算搜索列的总宽度
  props.columns.reduce((prev, current) => {
    prev +=
      (current.search![breakPoint.value]?.span?? current.search?.span?? 1) +
      (current.search![breakPoint.value]?.offset?? current.search?.offset?? 0)
    // 根据 searchCol 的类型判断是否显示展开/合并按钮
    if (typeof props.searchCol!== 'number') {
      if (prev >= props.searchCol[breakPoint.value]) show = true
    } else {
      if (prev > props.searchCol) show = true
    }
    return prev
  }, 0)
  return show
})
</script>
