Live2d Test Env

【论术】封装大批量表单数据

大丈夫做人的道理,我便跟你说了,你也不会明白。 ————《倚天屠龙记》· 彭莹玉

项目需要:传入大批量表单数据,如图(图大向右划拉):

需求:初始时呈收缩态,表单&按钮在一行展示,展开后表单全部展示,按钮在表单下方

由于表单项过多,因而不得不考虑封装一个表单组件;

为了与原型需求一致,因而它要支持打开部分&展开全部功能;

为了此组件的健壮性,因而不得不考虑兼容多种表单类型;

为了使其在不同分辨率下有更好的效果,因而使用`el-row``el-col`布局组件。

期望:传入一些表单配置,然后根据传入的配置项来动态定义表单项,点击重置或者查询或者初始化时拿到对应的数据

看码:


// 条件筛选表单 <template>
  <div class="search-form-box">
    <el-form
      :inline="true"
      :model="searchForm"
      size="default"
      ref="searchFormRef"
      label-width="130px"
    >
      <el-row>
        <el-col :span="cond.span" v-for="cond in sliceCodList" :key="cond.id">
          <el-form-item
            :label="cond.label + ':'"
            :prop="cond.prop"
            class="flex-form-item"
          >
            <!-- 输入框 -->
            <el-input
              v-if="cond.type === 'input'"
              v-model="searchForm[cond.prop]"
              :placeholder="cond.placeholder || '请输入'"
              clearable
            />
            <!-- 下拉框 -->
            <el-select
              v-else-if="cond.type === 'select'"
              v-model="searchForm[cond.prop]"
              :placeholder="cond.placeholder"
              clearable
            >
              <el-option
                v-for="op in cond.optionList"
                :key="op.value"
                :label="op.label"
                :value="op.value"
              />
            </el-select>
            <!-- 日期组合 -->
            <el-date-picker
              v-else-if="cond.type === 'daterange'"
              v-model="searchForm[cond.prop]"
              type="daterange"
              start-placeholder="开始日期"
              end-placeholder="结束日期"
            />
            <!-- 日期时间 -->
            <el-date-picker
              v-else-if="cond.type === 'datetime'"
              v-model="searchForm[cond.prop]"
              type="datetime"
              placeholder="请选择日期时间"
              style="width: 100%"
            />
          </el-form-item>
        </el-col>
        <el-col :span="rSpanCount" class="el-col-wrapper">
          <el-form-item class="btn-group-item flex-end">
            <el-button  size="small" type="primary" @click="search">查询</el-button>
            <el-button  size="small" plain @click="reset">重置</el-button>
            <el-button type="text" @click="toggleFold">
              {{ conditionFold ? "展开" : "收起"
              }}<i
                :class="[conditionFold ? 'el-icon-bottom' : 'el-icon-top']"
              ></i
            ></el-button>
          </el-form-item>
        </el-col>
      </el-row>
    </el-form>
  </div>
</template>

<script>
export default {
  // import引入的组件
  components: {},
  props: {
    // 传入的表单项
    conditionList: {
      type: Array,
      default: () => [],
    },
  },
  data() {
    return {
      conditionFold: true, //是否折叠 默认折叠
      initConditionFoldLen: 3, //初始化时展示的项 也可以在外部传入
      searchForm: {},  //初始搜索项,在拿到值的时候要将数据进行合并
    };
  },
  computed: {
    // 是否展示按钮
    showFoldBtn() {
      return this.conditionList.length > this.initConditionFoldLen;
    },
    // 计算剩余空间以保证24等分响应式
    rSpanCount() {
      let totalSpan = 0;
      if (this.initConditionFoldLen > 0) {
        if (!this.conditionFold) {
          totalSpan = this.conditionList.reduce((prev, next) => {
            return prev + next.span;
          }, 0);
        } else {
          const sliceCondList = this.conditionList.slice(
            0,
            this.initConditionFoldLen
          );
          totalSpan = sliceCondList.reduce((prev, next) => {
            return prev + next.span;
          }, 0);
        }
      } else {
        totalSpan = this.conditionList.reduce((prev, next) => {
          return prev + next.span;
        }, 0);
      }
      return 24 - (totalSpan % 24);
    },
    // 根据是否折叠和初始展示项来展示当前表单
    sliceCodList() {
      return this.conditionList.slice(
        0,
        this.conditionFold
          ? this.initConditionFoldLen
          : this.conditionList.length
      );
    },
  },
  //  方法集合
  methods: {
    toggleFold() {
      this.conditionFold = !this.conditionFold;
    },

    search() {
      this.$emit(`search`, this.searchForm);
    },
    reset() {
      this.$refs.searchFormRef.resetFields();
      this.$emit(`search`, this.searchForm);
    },
  },
  created() {
    // 获取到父组件传入的表单配置后,配置本组件的表单项
    this.conditionList.forEach((item) => {
      let baseVal;
      // 如果有`defaultVal`项
      if (item.defaultVal) {
        baseVal = item.defaultVal;
      } else {
        // 初始化
        baseVal = item.type === "datetimerange" ? [] : "";
      }
      // 收集表单配置数组的`prop`项作为表单的`key`
      this.$set(this.searchForm, item.prop, baseVal);
    });
    // 初始化时发送至父组件以完成一次请求
     this.$emit(`search`, this.searchForm);
  },
};
</script>
<style lang="sass" scoped>
.search-form-box {
  box-sizing: border-box;
  box-shadow: var(--el-box-shadow-light);
  background-color: #fff;
  border-radius: 4px;
  padding: 12px;
  margin-bottom: 12px;

  .flex-form-item {
    display: flex;
    align-items: center;
  }

  .el-col-wrapper {
    display: flex;

    .btn-group-item {
      flex: 1;
      display: flex;

      :deep(.el-form-item__content) {
        flex: 1;
        display: flex;
        align-items: center;
      }

      &.flex-end {
        :deep(.el-form-item__content) {
          justify-content: flex-end;
        }
      }
    }
  }
}
</style>



// 父组件 
<template>
<SearchForm :conditionList="conditionList" @search="getForm" />
</template> 




import {
  conditionList as conditionListMsg,
  personalHeaderColumns,
  identityMap,
} from "../../config";


data(){
return {
    conditionList: Object.freeze(conditionListMsg), // 传入的表单数据
}
}
// 配置文件 config.js

// 条件表单字段   这里的key需要跟后端写的一 一对应
export const identityMap = {
  staffName: "姓名",
  idCard: "身份证",
  staffUnit: "单位",
  oneOffice: "一级部门",
  twoOffice: "二级部门",
  father: "父亲",
  mother: "母亲",
  mate: "配偶",
  elderBrother: "哥哥",
  youngerBrother: "弟弟",
  elderSister: "姐姐",
  youngerSister: "妹妹",
  son: "儿子",
  daughter: "女儿",
  goodFather: "岳父",
  goodMother: "岳母",
  other: "其他亲属",
  openFirm: "本人在外开设或投资公司情况",
  outFirm: "亲属在外开设或投资公司情况",
  inFirm: "本人从事的第二职业情况",
};

const identityList = Object.entries(identityMap);
export const conditionList = identityList.map((item, index) => {
  const [prop, label] = item;
  return {
    id: index + 1,
    type: "input",
    prop,
    label,
    span: 6,
  };
});


// 人员管理的表头 不包括操作项,(埋坑 打工笔记3或4再写)
export const personalHeaderColumns = identityList.map((item) => {
  const [prop, label] = item;
  return {
    label,
    prop,
    toolTip: true,
    align: "center",
    minWidth: "200px",
  };
});

这样就实现了上述功能,v2/v3在开发上并没有太大区别,因而暂且不表。
以上。

posted @ 2025-01-06 17:41  致爱丽丝  阅读(23)  评论(0)    收藏  举报