XXXForm组件

news2024/9/24 21:20:40

效果展示

2024-04-182.40.57-ezgif.com-video-to-gif-converter.gif

代码

XXXForm

<template>
  <div class="search-container">
    <el-form ref="formRef" class="form_is_hidden" :model="form" v-bind="formAttrs">
      <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"
        >
          <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">
          <el-form-item class="search-btn" label="1" label-width="0">
            <el-tooltip
              v-if="shows.collapsedBtn"
              :content="collapsed ? '收起' : '展开'"
              placement="top"
              trigger="hover"
            >
              <el-button class="coll" text bg type="info" @click="toggleCollapse">
  
                <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>

          </el-form-item>
        </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 {};
    },
  },
  formAttrs: {
    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 {
    .search-btn {
      :deep(.el-form-item__content) {
        justify-content: end;
      }

      :deep(.el-form-item__label) {
        color:transparent;
      }
    }
  }

  .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,自己想要啥补充啥就行。

使用

props

参数说明类型可选值默认值
columns配置表单展示项object[]--
collapse是否收起booleantrue/falsefalse
modelValueform 对象{}-{}
resttForm重制 form 默认值{}-{}
formAttrs支持 el 的 form 属性{}-{}
cloumns 说明
参数说明类型可选值默认值
inputType输入框类型string--
spanformitem 占用空间(参考el-col)number1-246
formItemAttrs继承 el 的 formitem 的 props + emit,配置formitem 像 el 一样。{}--
valuesform 中对应的 keystring/string[]--
inputAttrs继承 el 的 input 的 props + emit,配置 input 像 el 一样。也是拓展属性的地方。{}--

emit

方法名说明类型
update:modelValue更新 form 对象-
search搜索-
reset重制-

使用示例

searchFormC

import { defineComponent, ref } from 'vue';
//@ts-ignore
import SearchForm from '@/components/searchForm/index.vue';
export default defineComponent((_p, { attrs }) => {
  const columns = ref([
    {
      values: 'nickname',
      inputType: 'input',
      span: 6,
      inputAttrs: {
        placeholder: '请输入',
      },
      formItemAttrs: {
        label: '姓名',
        labelWidth: '80px',
      },
    },
    {
      values: 'country',
      inputType: 'countryAuto1',
      inputAttrs: {
        placeholder: '请输入',
      },
      formItemAttrs: {
        label: '国家',
        labelWidth: '80px',
      },
    },
    {
      values: 'email',
      inputType: 'input',
      span: 6,
      inputAttrs: {
        placeholder: '请输入',
      },
      formItemAttrs: {
        label: '邮箱',
        labelWidth: '80px',
      },
    },
    {
      values: 'employeeCode',
      inputType: 'input',
      span: 12,
      inputAttrs: {
        placeholder: '请输入',
      },
      formItemAttrs: {
        label: '员工编号',
        labelWidth: '80px',
      },
    },
    {
      values: ['createStartTime', 'createEndTime'],
      inputType: 'date',
      span: 12,
      inputAttrs: {
        format: 'YYYY-MM-DD',
        placeholder: '请输入',
      },
      formItemAttrs: {
        label: '创建时间',
        labelWidth: '80px',
      },
    },
  ]);
  return () => (
    <SearchForm {...attrs} columns={columns.value} collapse={false} formAttrs={{ labelPosition: 'left' }} />
  );
});

vue

<template>
  <SearchFormC v-model="form" @search="search" @reset="rest" />
</template>

<script setup lang="ts">
import SearchFormC from './components/searchFormC'
import { ref } from 'vue';
const form = ref({})

const search = () => {
  console.log(form.value)
}

const rest = () => {
  console.log(form.value)
}
</script>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1993215.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

一文带你快速了解——LVS负载均衡集群

前言&#xff1a; Internet的飞速发展给网络带宽和服务器带来巨大的挑战。从网络技术的发展来看&#xff0c;网络带宽的增长远高于处理器速度和内存访问速度的增长。对用硬件和软件方法实现高可伸缩、高可用网络服务的需求不断增长。针对高可伸缩、高可用网络服务的需求&#x…

.NET8使用VS2022打包Docker镜像

NET8使用VS2022打包Docker镜像 1. 项目中添加Docker支持文件2. 自定义镜像名称3. 发布Docker镜像3.1 安装Docker3.2 控制台切换到项目根目录,执行以下命令发布镜像 3.3 修改镜像名称4. 保存镜像到本地 1. 项目中添加Docker支持文件 2. 自定义镜像名称 项目文件PropertyGroup节…

软件功能测试步骤介绍,软件测试服务公司推荐

在当今软件开发日益复杂的环境中&#xff0c;软件功能测试显得尤为重要。功能测试是确保软件产品满足用户需求和规范要求的关键环节。它通过验证软件功能是否按预期运行&#xff0c;帮助发现潜在的问题&#xff0c;防止软件在上线后导致用户的不满及业务损失。随着市场竞争的加…

(el-Date-Picker)操作(不使用 ts):Element-plus 中 DatePicker 组件的使用及输出想要日期格式需求的解决过程

Ⅰ、Element-plus 提供的DatePicker日期选择器组件与想要目标情况的对比&#xff1a; 1、Element-plus 提供DatePicker组件情况&#xff1a; 其一、Element-ui 自提供的DatePicker代码情况为(示例的代码)&#xff1a; // Element-plus 提供的组件代码: <template><e…

【多线程-从零开始-捌】代码案例2—阻塞队列

什么是阻塞队列 阻塞队里是在普通的队列&#xff08;先进先出队列&#xff09;基础上&#xff0c;做出了扩充 线程安全 标准库中原有的队列 Queue 和其子类&#xff0c;默认都是线程不安全的 具有阻塞特性 如果队列为空&#xff0c;进行出队列操作&#xff0c;此时就会出现阻…

Java代码生成器EasyCode

Java代码生成器EasyCode 一、安装插件二、连接数据库后右键Generator生成代码 一、安装插件 在 IntelliJ IDEA 的插件市场中搜索 EasyCode&#xff0c;然后安装该插件 二、连接数据库后右键Generator生成代码 勇敢面对挑战&#xff0c;成功从不会远离坚持者。坚持不懈的努力…

八股之Java集合

Java 集合&#xff0c;也叫作容器&#xff0c;主要是由两大接口派生而来&#xff1a;一个是 Collection接口&#xff0c;主要用于存放单一元素&#xff1b;另一个是 Map 接口&#xff0c;主要用于存放键值对。对于Collection 接口&#xff0c;下面又有三个主要的子接口&#xf…

MongoDB学习笔记(三)

使用Python操作MongoDB: 使用管理员用户&#xff1a;

Python —— 基础

目录 变量与引用 数据类型 赋值、深浅拷贝 控制流结构 逻辑操作符 is 与 dir() 关键字&#xff08;Python 3.11 &#xff09; https://www.cnblogs.com/qianfanwaer/p/14783204.html 变量与引用 变量是原来存储数据的一个标识符&#xff0c;可被看作是内存的一个位置&…

【学习笔记】Day 7

一、进度概述 1、DL-FWI基础入门培训笔记 2、inversionnet_train 试运行——未成功 二、详情 1、InversionNet: 深度学习实现的反演 InversionNet构建了一个具有编码器-解码器结构的卷积神经网络&#xff0c;以模拟地震数据与地下速度结构的对应关系。 &#xff08;一…

Python,我来啦!!!融合多个框架语言。。

基于上次发布CSDN的自己一些想法 上次&#xff0c;从一个道友手中购买了一份轮子代码&#xff0c;主要用到的技术就是pythonmysql或sqliteflask框架&#xff0c;这里我做了二次开发。 新的改变 这里&#xff0c;我对该代码进行了一些功能拓展与语法支持&#xff0c;除了原有…

【OpenCV C++20 学习笔记】仿射变换-warpAffine, getRotationMatrix2D

仿射变换 原理概述得到仿射变换的方法 APIgetAffineTransform()函数warpAffine()函数getRotationMatrix2D()函数 示例 原理 概述 仿射变换是矩阵乘法&#xff08;线性变换&#xff09;和向量加法的结合。它包含了&#xff1a; 旋转&#xff08;线性变换&#xff09;转换&…

【递归 + 记忆化搜索优化】力扣494. 目标和

给你一个非负整数数组 nums 和一个整数 target 。 向数组中的每个整数前添加 ‘’ 或 ‘-’ &#xff0c;然后串联起所有整数&#xff0c;可以构造一个 表达式 &#xff1a; 例如&#xff0c;nums [2, 1] &#xff0c;可以在 2 之前添加 ‘’ &#xff0c;在 1 之前添加 ‘-…

立体连接模式下的传播与沟通:AI智能名片小程序的创新应用与深度剖析

摘要&#xff1a;在数字化浪潮的推动下&#xff0c;信息传播与沟通方式正经历着前所未有的变革。立体连接模式&#xff0c;作为这一变革的重要产物&#xff0c;通过整合物理空间、虚拟网络空间与社群心理空间的三维联动&#xff0c;实现了信息的深度传播与高效互动。AI智能名片…

Java新手指南:从菜鸟到编程大师的趣味之路-类和对象

这里是Themberfue 本章主要介绍的是Java最重要的面向对象&#xff08;OOP&#xff09;的基础 面向对象 Java是一门纯面向对象的语言&#xff0c;在面向对象的世界里&#xff0c;一切皆为对象。面向对象是解决问题的一种思想&#xff0c;主要依靠对象之间的交互完成一件事情。用…

MySQL --- 复合查询

目录 一、多表查询 二、自连接 三、子查询 1、单行子查询 2、多行子查询 3、多列子查询 4、在from后面使用子查询 四、合并查询 1、union 2、union all 五、内连接 六、外连接 1、左外连接 2、右外连接 一、多表查询 我们需要的数据往往会来自不同的表&#xf…

redis面试(十)锁释放

自动释放 首先锁的释放分为两种&#xff0c;一种是自动释放&#xff0c;加入说加锁的线程宕机了不在了&#xff0c;我们之前说过这个。 那这个线程中的对redis这个锁不断刷新过期时间的看门狗逻辑就没有了&#xff0c;所以这个锁最多等待30s的时间就会自动过期删除&#xff0c…

文件I/O第一天作业 2024.8.8

使用系统I/O实现Linux的cat命令 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <fcntl.h> #include <errno.h>int main(int argc, const char *argv[]) {if(argc < 2){printf("请输…

【笔试题面试题】IO类2 知识点汇总(笔试面试题)

书接上文&#xff0c;配上前文一起实用更加&#xff0c;持续更新&#xff0c;督促自己学习 目录 1、详细描述一下什么是IO以及标准IO和文件IO的区别&#xff08;补充&#xff09; 2、什么是死锁&#xff0c;如何避免死锁&#xff08;补充&#xff09; 3、为什么引入同步互斥…

NVIDIA Triton系列09-为服务器添加模型

NVIDIA Triton系列09-为服务器添加模型 B站&#xff1a;肆十二-的个人空间-肆十二-个人主页-哔哩哔哩视频 (bilibili.com) 博客&#xff1a;肆十二-CSDN博客 问答&#xff1a;(10 封私信 / 72 条消息) 肆十二 - 知乎 (zhihu.com) 前面已经用 https://github.com/triton-inferen…