table_search.vue 9.14 KB
<script lang="ts" setup name="TableSearch">
import { computed, reactive, ref } from 'vue'
import { Search } from '@element-plus/icons-vue'
import type { FormInstance, FormRules } from 'element-plus'
import { debounce } from "@/utils/common"
const emits = defineEmits(["tableSearch", "toolFilterChange", "loadMore","remoteMethod","treeSelectLoad","selectChange","treeSelectNodeChange","treeSelectNodeClick"]);
const props = defineProps({
  itemList: {
    type: Array,
    default: []
  },
  formId: {
    type: String,
    default: '',
  },
  init: {
    type: Boolean,
    default: true
  }
})
const formRef = ref()
const formInline: any = computed(() => {
  let items = setFormFields(props.itemList);
  return reactive(items);
})
const formItemList: any = computed(() => {
  return reactive(props.itemList);
})
const resetForm = (formEl: FormInstance | undefined) => {
  if (!formEl) return
  formEl.resetFields()
  nextTick(() => {
    const form = formInline.value
    emits('tableSearch', form, true)
  })
}
defineExpose({
  formInline,
  formRef
})
const setFormFields = (list: any) => {
  let obj = {}
  list.map((item: any) => {
    obj[item.field] = item.default == undefined ? '' : item.default
    if (item.children) {
      obj = { ...obj, ...setFormFields(item.children) }
    }
  })
  return obj
}
const onSubmit = () => {
  const form = formInline.value
  emits('tableSearch', form)
}
const radioGroupChange = (val) => {
  emits('toolFilterChange', val, 'radio-group')
}
const loadMore = () => {
  emits('loadMore')
}
const treeSelectLoad = (node, resolve, item) => {
  emits("treeSelectLoad", node, resolve, item);
};
const selectChange = (val, row) => {
  const info = formInline.value;
  emits("selectChange", val, row, info);
};
const handleTreeSelectNodeChange = (node, item) => {
  emits("treeSelectNodeChange", node, item);
}
const handleTreeSelectNodeClick = (node, item)=>{
  emits("treeSelectNodeClick", node, item);
}
const inputChange = (val)=>{
  onSubmit()
}
onMounted(() => {
  props.init && onSubmit()
})
</script>

<template>
  <el-form ref="formRef" :inline="true" :model="formInline" class="demo-form-inline" @submit.native.prevent>
    <template v-for="(item, index) in formItemList">
      <el-form-item v-if="item.visible ?? true" :key="'item_' + index"
        :class="{ 'width_auto': item.type == 'radio-button' }" :prop="item.field">
        <template v-if="item.type == 'select'">
          <el-select :class="{ 'is-multiple': item.multiple }" v-model="formInline[item.field]"
            :placeholder="item.placeholder" :clearable="item.clearable" :filterable="item.filterable" @change="(val) => selectChange(val, item)">
            <el-option v-for="opt in item.options" :label="item.props?.label ? opt[item.props.label] : opt.label" :value="item.props?.value ? opt[item.props.value] : opt.value" />
          </el-select>
        </template>
        <template v-else-if="item.type == 'input-select'">
          <el-input v-model.trim="formInline[item.field]" :placeholder="item.placeholder" class="input-with-select" :maxlength="item.maxlength ?? ''"
            :suffix-icon="Search">
            <template #prepend>
              <span v-for="child in item.children">
                <el-select v-model="formItemList[child.field]" :placeholder="child.placeholder"
                  :clearable="item.clearable" style="vertical-align: inherit;">
                  <el-option v-for="opts in child.options" :label="child.props?.label ? opts[item.props.label] : opts.label" :value="child.props?.value ? opts[item.props.value] : opts.value" />
                </el-select>
              </span>
            </template>
          </el-input>
        </template>
        <template v-else-if="item.type=='tree-select'">
          <div class="select_slots_panel">
            <div class="slot-prefix" v-for="child in item.children">
              <el-select v-model="formInline[child.field]" :placeholder="child.placeholder" @change="(val) => selectChange(val, child)" >
                <el-option v-for="cpt in child.options" :label="cpt.label" :value="cpt.value" />
              </el-select>
            </div>
            </div>
            <div class="slot-default">
                <el-tree-select
                v-model="formInline[item.field]"
                :data="item.options"
                :placeholder="item.placeholder"
                :clearable="item.clearable"
                :filterable="item.filterable"
                :disabled="item.disabled"
                :lazy="item.lazy ?? true"
                :check-strictly = "item.checkStrictly ?? false"
                :node-key="item.nodeKey ?? 'guid'"
                :load="(node, resolve) => treeSelectLoad(node, resolve, item)"
                :props="item.props"
                :multiple="item.multiple ?? false"
                :render-after-expand="true"
                :teleported="item.teleported ?? true"
                :default-expanded-keys="item.expandKeys"
                :collapse-tags-tooltip="item.collapseTagsTooltip ?? false"
                :collapse-tags="item.collapseTags ?? false"
                :max-collapse-tags="item.maxTags ?? 1"
                :show-checkbox="item.showCheckbox ?? false"
                @change="(val) => selectChange(val, item)"
                @current-change="(node) => handleTreeSelectNodeChange(node, item)"
                @node-click	= "(node)=>handleTreeSelectNodeClick(node, item)"
              >

                <!-- <template #default="{ node, data }">
                  <template v-if="item.getName">
                    <div
                      class="left-code"
                      style="
                        display: inline-flex;
                        font-size: 12px;
                        line-height: 21px;
                        margin-left: 4px;
                        overflow: hidden;
                        text-overflow: ellipsis;
                      "
                    >
                      {{ item.getName(data, node) }}
                    </div>
                  </template>
                  <span v-else>{{ data[item.props.label] }}</span>
                </template> -->
              </el-tree-select>
            </div>

        </template>
        <template v-else-if="item.type == 'date-time'">
          <el-date-picker v-model="formInline[item.field]" type="datetimerange" start-placeholder="开始时间"
            end-placeholder="结束时间" />
        </template>
        <template v-else-if="item.type == 'radio-button'">
          <el-radio-group v-model="formInline[item.field]" @change="radioGroupChange">
            <el-radio-button v-for="opts in item.options" :label="opts.label" />
          </el-radio-group>
        </template>
        <template v-else-if="item.type == 'select-slots'">
          <div class="select_slots_panel">
            <div class="slot-prefix" v-for="child in item.children">
              <el-select v-model="formInline[child.field]" :placeholder="child.placeholder">
                <el-option v-for="cpt in child.options" :label="cpt.label" :value="cpt.value" />
              </el-select>
            </div>
            <div class="slot-default">
              <el-select :class="{ 'is-multiple': item.multiple }" v-model="formInline[item.field]"
                :placeholder="item.placeholder" :multiple="item.multiple" collapse-tags collapse-tags-tooltip
                @change="(val) => selectChange(val, item)"
                :max-collapse-tags="3" :filterable="item.filterable" :clearable="item.clearable" v-loadmore="loadMore">
                <el-option v-for="opt in item.options" :label="opt.label" :value="opt.value" />
              </el-select>
            </div>
          </div>
        </template>
        <template v-else>
          <el-input v-model.trim="formInline[item.field]" :placeholder="item.placeholder" :clearable="item.clearable"
            @clear="inputChange" />
        </template>
      </el-form-item>
    </template>
    <el-form-item>
      <el-button type="primary" @click="onSubmit" v-preReClick>查询</el-button>
      <el-button @click="resetForm(formRef)" v-preReClick>清空</el-button>
    </el-form-item>
  </el-form>
</template>

<style lang="scss" scoped>
.el-form {
  :deep(.el-form-item) {
    margin-bottom: 8px;
    margin-right: 8px;

    .el-input__wrapper {
      width: 230px;

      &.el-date-editor {
        width: auto;

        .el-range-separator {
          // flex: unset;
        }
      }
    }

    .el-select {
      width: 140px;

      &.is-multiple {
        width: 400px;

      }
    }

    .select_item {
      width: 140px;
    }

    &.width_auto {
      width: auto;

      .el-select {
        width: 100%;
      }

      .select_item {
        width: 100%;
      }
    }

    .select_slots_panel {
      display: flex;

      .slot-prefix {
        margin-right: -1px;

        .el-input__wrapper {
          border-radius: var(--el-input-border-radius, var(--el-border-radius-base)) 0 0 var(--el-input-border-radius, var(--el-border-radius-base));
        }
      }

      .slot-default {
        .el-input__wrapper {
          border-radius: 0 var(--el-input-border-radius, var(--el-border-radius-base)) var(--el-input-border-radius, var(--el-border-radius-base)) 0;
        }
      }

    }

  }
}
</style>