XXXForm

效果展示

代码

XXXForm

<template>
  <div class="search-container">
    <el-form ref="formRef" class="form_is_hidden" :model="form" label-width="0">
      <el-row :gutter="20" class="search-row">
        <el-col
          v-for="item in shows.columns"
          :key="item.inputType + JSON.stringify(item.values)"
          :span="item.span || 6"
        >
          <div class="search-label">{{ item.label }}</div>
          <el-form-item v-bind="item.formItemAttrs || {}">
            <FormItem
              v-if="typeof item.values == 'string'"
              v-bind="item.inputAttrs || {}"
              v-model="form[item.values]"
              :input-type="item.inputType"
            />
            <FormItem
              v-else
              v-model:one="form[item.values[0]]"
              v-model:two="form[item.values[1]]"
              :input-type="item.inputType"
              v-bind="item.inputAttrs || {}"
            />
          </el-form-item>
        </el-col>
        <el-col :span="shows.btnsSpan" class="search-btn-container">
          <div v-if="shows.btnsSpan != 24" class="h-28px"></div>
          <div v-if="shows.btnsSpan == 24" class="h-2px"></div>
          <el-tooltip
            v-if="shows.collapsedBtn"
            :content="collapsed ? '收起' : '展开'"
            placement="top"
            trigger="hover"
          >
            <el-button class="coll" text bg type="info" @click="toggleCollapse">
              <!-- {{ collapsed ? '收起' : '展开' }} -->

              <el-icon class="form_is_hidden_icon">
                <DArrowRight v-if="!collapsed" />
                <DArrowLeft v-else />
              </el-icon>
            </el-button>
          </el-tooltip>
          <el-button text bg type="info" @click="resetForm">重置</el-button>
          <el-button type="primary" @click="search">查询</el-button>
          <div v-if="shows.btnsSpan == 24" class="h-18px"></div>
        </el-col>
      </el-row>
    </el-form>
  </div>
</template>
<script lang="ts" setup>
import { computed, ref } from 'vue';
import { useVModel } from '@vueuse/core';
import { SearchFormColum } from './type';
import FormItem from './formItem.vue';
import { DArrowRight, DArrowLeft } from '@element-plus/icons-vue';

const props = defineProps({
  columns: {
    type: Array,
    default: () => [],
  },
  collapse: {
    type: Boolean,
    default: false,
  },
  modelValue: {
    type: Object,
    default: () => {
      return {};
    },
  },
  resttForm: {
    type: Object,
    default: () => {
      return {};
    },
  },
});
const emit = defineEmits(['update:modelValue', 'search', 'reset']);
const collapsed = ref(props.collapse);
const form = useVModel(props, 'modelValue', emit);
const shows = computed(() => {
  const cols = props.columns as SearchFormColum;
  const spans = cols?.map((i) => i.span || 6).reduce((a, b) => a + b, 0);
  if (spans > 18) {
    if (!collapsed.value) {
      let spanss = 0;
      let index = 0;
      try {
        cols?.forEach((i, idx) => {
          if (spanss < 18) {
            if ((i.span || 6) + spanss > 18) {
              throw new Error('');
            }
            spanss += i.span || 6;
            index = idx;
          } else {
            throw new Error('');
          }
        });
      } catch (error) {
        // console.log('跳出循环');
      }

      return {
        columns: cols.filter((_i, idx) => idx <= index),
        btnsSpan: 24 - spanss,
        collapsedBtn: true,
      };
    } else {
      const spanss = cols
        ?.map((i) => i.span || 6)
        .reduce((a, b) => {
          if (a + b > 24) {
            return b;
          } else if (a + b == 24) {
            return 0;
          } else {
            return a + b;
          }
        }, 0);
      const btnsSpan = spanss > 18 ? 24 : 24 - spanss;

      return {
        columns: cols,
        btnsSpan,
        collapsedBtn: true,
      };
    }
  } else {
    return {
      columns: cols,
      btnsSpan: 24 - spans,
      collapsedBtn: false,
    };
  }
});
const search = () => {
  emit('search');
};
const resetForm = () => {
  const resett = { ...props.resttForm };
  form.value = resett;
  emit('reset');
};
const toggleCollapse = () => {
  collapsed.value = !collapsed.value;
};
</script>
<style lang="less" scoped>
.search-container {
  // margin-bottom: 20px;

  .form_is_hidden_icon {
    transform: rotate(90deg);
  }

  .search-btn-container {
    text-align: right;
  }

  .search-row {
    // transition: height 0.3s;
    overflow: hidden;
  }
  .search-label {
    font-size: 14px;
    color: var(--hiwork-global-color);
    padding-bottom: 8px;
  }
}
:deep(.el-button).coll {
  padding: 10px 12px !important;
}
</style>

formItem

<template>
  <component :is="currentCom" />
</template>
<script lang="tsx" setup>
// import cityCascader from './cityCascader';
import DateMonthPicker from './components/dateMonthPicker';
import DateRangePicker from './components/dateRangePicker';
import DateYearPicker from './components/dateYearPicker';
import Select from './components/select';
import CountryAutoComplete from './components/countryAutoComplete.vue';
import CountryAutoCompleteOne from './components/countryAutoCompleteOne.vue';
import HiInput from './components/hiInput.vue';
import { computed } from 'vue';
const props = defineProps({
  inputType: {
    type: String,
    default: 'input',
  },
});

const currentCom = computed(() => {
  switch (props.inputType) {
    case 'date':
      return DateRangePicker;
    case 'month':
      return DateMonthPicker;
    case 'year':
      return DateYearPicker;
    // case 'cascader':
    //   return cityCascader;
    case 'select':
      return Select;
    case 'countryAuto':
      return CountryAutoComplete;
    case 'countryAuto1':
      return CountryAutoCompleteOne;
    default:
      return HiInput;
  }
});
</script>

XXXInput

<template>
  <!-- hiInput -->
  <el-input v-model="modelValue" @blur="hBlur" />
</template>
<script setup>
import { computed } from 'vue';
const props = defineProps({
  modelValue: {
    type: String,
    default: '',
  },
});
const emit = defineEmits(['update:modelValue']);
const modelValue = computed({
  get() {
    return props.modelValue;
  },
  set(v) {
    emit('update:modelValue', v);
  },
});
const hBlur = () => {
  modelValue.value = modelValue.value.trim();
};
</script>
// dateRangePicker
import { ElDatePicker } from 'element-plus';
import { defineComponent, reactive, watchEffect } from 'vue';
import dayjs from 'dayjs';

export default defineComponent({
  props: {
    one: { type: String, default: () => '' },
    two: { type: String, default: () => '' },
    format: { type: String, default: () => '' },
  },
  emits: ['update:one', 'update:two'],
  // emits: {
  //   'update:one': (v: string) => true,
  //   'update:two': (v: string) => true,
  // },
  setup(props, { attrs, emit }) {
    const state = reactive({
      ivalue: [],
    });
    const updateValue = (
      v: (string | number | Date | dayjs.Dayjs | null | undefined)[],
    ) => {
      emit(
        'update:one',
        v ? dayjs(v[0]).format(props.format || 'YYYY-MM-DD') : '',
      );
      emit(
        'update:two',
        v ? dayjs(v[1]).format(props.format || 'YYYY-MM-DD') : '',
      );
    };
    watchEffect(() => {
      state.ivalue = [props.one, props.two] as any;
    });
    return () => (
      <ElDatePicker
        modelValue={state.ivalue as any}
        onUpdate:modelValue={updateValue}
        type='daterange'
        range-separator='-'
        start-placeholder='开始'
        end-placeholder='结束'
        {...attrs}
      />
    );
  },
});
// cityCascader
import { getLocationDetailInfo } from '@/axios/api';
import { ElCascader } from 'element-plus';
import { defineComponent, ref } from 'vue';

export default defineComponent((_p, { attrs }) => {
  const cityList = ref([]);

  getLocationDetailInfo().then((res) => {
    cityList.value = res.data;
  });

  return () => (
    <ElCascader
      {...attrs}
      placeholder='请选择省市区'
      style={'width: 100%'}
      props={{ children: 'child', value: 'name', label: 'name' }}
      options={cityList.value}
    />
  );
});

XXXInput,自己想要啥补充啥就行。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值