本组件二次封装iview和element的多个组件,可以在全局安装了Iview和element的项目或者局部引入了el-input/Select/Button/DatePicker/InputNumber的页面中自由使用。

目录

效果展示


从左到右分别是:属性名、组合条件拼接、删除条件、条件确认、校验信息提示

从上到下分别是:初始状态、七种条件拼接组合、增加条件按钮

功能描述

  1. 属性名和初始数据均可由父组件传参到子组件
  2. 点击“增加条件”可以增加一行条件组合
  3. 点击√确认组合,并启动校验,若校验不通过,在该行的右上角提示错误信息
  4. 点击×删除该行条件
  5. 共七种不同的条件拼接组合

结构代码

<template>
  <div class="add-condition">
    <span class="c-fix-title wt">{
  { attr_name }}</span>
    <Form ref="formAttr" :model="formAttr" :label-width="60" style="width: 100%">
      <FormItem v-for="(item, index) in formAttr.item" :key="index">
        <template v-if="item.status">
          <Row>
            <Col span="24">
              <Select v-model="item.seedim" style="width: 80px" @on-open-change="dim_change($event, item.seedim, index)" >
                <Option v-for="see_item in seedimList" :value="see_item.value" :key="see_item.value" >{
  { see_item.label }}</Option >
              </Select>
              <Select v-if="item.seedim !== 3" v-model="item.scompare" style="width: 80px" @on-open-change="scom_change($event, item.scompare, index)" >
                <Option v-for="j_item in judgeList" :value="j_item.value" :key="j_item.value" >{
  { j_item.label }}</Option >
              </Select>
              <InputNumber v-if="item.seedim !== 3 && item.scompare !== 7" :min="1" v-model="item.sNum" @on-blur="get_sNum(item.sNum, index)" ></InputNumber>
              <nToN v-if="item.seedim !== 3 && item.scompare === 7" :initNum="item.seerange" @func="see_setData($event, index)" :num-flag="1" ></nToN>
              <Select v-if="item.seedim !== 3" v-model="item.suffix" placeholder="统计维度" style="width: 120px; margin-left: 6px" @on-open-change="suffix_change($event, item.suffix, index)" >
                <Option v-for="suf_item in sufList" :value="suf_item.value" :key="suf_item.value" >{
  { suf_item.label }}</Option >
              </Select>
              <Select v-if="item.seedim === 3" v-model="item.selsuf" placeholder="统计维度" style="width: 140px" @on-open-change="selsuf_change($event, item.selsuf, index)" >
                <Option v-for="sel_item in selsufList" :value="sel_item.value" :key="sel_item.value" >{
  { sel_item.label }}</Option >
              </Select>
              <date-pick v-if="item.selsuf_type === 'time'" type="daterange" :value="item.datetime" :options="datetimeOption" confirm :clearable="false" :editable="false" split-panels :transfer="false" @on-change="handleDatetime($event, index)" @on-ok="confirmDatetime(index)" @on-clear="day_clear(index)" @on-clear-shortcut="clearShortCut" placement="bottom-start" placeholder="请选择查询日期范围" style="width: 200px" />
              <Select v-if="item.selsuf_type === 'num'" v-model="item.compare" style="width: 80px" @on-open-change="com_change($event, item.compare, index)" >
                <Option v-for="com_item in judgeList" :value="com_item.value" :key="com_item.value" >{
  { com_item.label }}</Option >
              </Select>
              <InputNumber v-if="item.selsuf_type === 'num' && item.compare !== 7" :max="10" :min="1" v-model="item.cNum" @on-blur="get_cNum(item.cNum, index)" ></InputNumber>
              <nToN v-if="item.selsuf_type === 'num' && item.compare === 7" :initNum="item.comrange" @func="com_setData($event, index)" :num-flag="1" ></nToN>
              <Button type="primary" icon="md-close" ghost :disabled="index === 0" @click="handleRemove(item, index)" ></Button>
              <Button type="primary" icon="md-checkmark" @click="handleConfirm(item, index)" ></Button>
              <span v-show="item.tip_show" class="tip-span">{
  { item.msg }}</span>
            </Col>
          </Row>
        </template>
      </FormItem>
      <FormItem>
        <Row style="margin-bottom: 0px">
          <Col span="3">
            <Button type="dashed" @click="handleAdd" icon="md-add">增加条件</Button>
          </Col>
        </Row>
      </FormItem>
    </Form>
    <Divider />
  </div>
</template>
  • formAttr.item:所有条件存放的数组
  • 包含组件库的子组件:nToN、date-pick
  • handleRemove:移除条件处理,第一条不可移除
  • handleConfirm:条件确认处理(包含校验)

逻辑代码

  methods: {
   
    handleAdd () {
   
      this.index++
      this.formAttr.item.push({
   
        index: this.index,
        status: 1,
        seedim: 1,
        seedim_label: '注册',
        scompare: 1,
        scompare_label: '>',
        sNum: 3,
        seerange: {
   
          minNum: '',
          maxNum: ''
        },
        seerange_content: '',
        suffix: '',
        suffix_label: '',
        selsuf_type: 'num',
        selsuf: '',
        selsuf_label: '',
        datetime: ['', ''],
        comDate: ['', ''],
        compare: 1,
        compare_label: '>',
        cNum: 3,
        comrange: {
   
          minNum: '',
          maxNum: ''
        },
        comrange_content: '',
        tip_show: false,
        msg: ''
      })
    },
    handleRemove (line, index) {
   
      this.formAttr.item[index].status = 0
      this.resObjArr = this.resObjArr.filter((item) => item.index !== line.index)
      if (this.resObjArr.length === 0) {
   
        this.$emit('getData', '不限', this.attr_name)
      } else {
   
        this.$emit('getData', this.resObjArr, this.attr_name)
      }
    },
    dim_change (open, seedim, idx) {
   
      if (!open) {
   
        var label = ''
        if (seedim !== 3) {
   
          label = this.seedimList.find((item) => item.value === seedim).label
        }
        this.formAttr.item[idx].seedim_label = label
      }
    },
    scom_change (open, scompare, idx) {
   
      if (!open) {
   
        var label = ''
        if (scompare !== 7) {
   
          label = this.judgeList.find((item) => item.value === scompare).label
        }
        this.formAttr.item[idx].scompare_label = label
      }
    },
    get_sNum (sNum, idx) {
   
      if (typeof sNum === 'number') {
   
      } else {
   
        this.$Message.info('这里有默认值哦~可以自行修改哦o(* ̄▽ ̄*)ブ')
        this.formAttr.item[idx].sNum = 1
      }
    },
    see_setData (data, idx) {
   
      var seeContent = ntnData_handle(data).content
      var seeRange = ntnData_handle(data).range
      this.formAttr.item[idx].seerange = seeRange
      this.formAttr.item[idx].seerange_content = seeContent
    },
    suffix_change (open, suffix, idx) {
   
      if (!open && typeof suffix === 'number') {
   
        var label = ''
        label = this.sufList.find((item) => item.value === suffix).label
        this.formAttr.item[idx].suffix_label = label
      }
    },
    selsuf_change (open, selsuf, idx) {
   
      if (!open) {
   
        var label = ''
        label = this.selsufList.find((item) => item.value === selsuf).label
        this.formAttr.item[idx].selsuf_label = label
        this.formAttr.item[idx].selsuf_type = label.includes('时间') ? 'time' : 'num'
      }
    },
    com_change (open, compare, idx) {
   
      if (!open) {
   
        var label = ''
        if (compare !== 7) {
   
          label = this.judgeList.find((item) => item.value === compare).label
        }
        this.formAttr.item[idx].compare_label = label
      }
    },
    get_cNum (cNum, idx) {
   
      if (typeof cNum === 'number') {
   
      } else {
   
        this.$Message.info('这里有默认值哦~可以自行修改哦o(* ̄▽ ̄*)ブ')
        this.formAttr.item[idx].cNum = 1
      }
    },
    com_setData (data, idx) {
   
      var comContent = ntnData_handle(data).content
      var comRange = ntnData_handle(data).range
      this.formAttr.item[idx].comrange = comRange
      this.formAttr.item[idx].comrange_content = comContent
    },
    handleConfirm (line, index) {
   
      this.data_handel_emit(line, index)
    },
    data_handel_emit (line, idx) {
   
      var resObj = {
   }
      var lineType
      // ------------验证------------
      if (line.seedim !== 3 && !line.suffix) {
   
        this.formAttr.item[idx].msg = 'Tips:您忘记选择统计维度了哦o(╥﹏╥)o'
        this.formAttr.item[idx].tip_show = true
      } else if (line.seedim === 3 && !line.selsuf) {
   
        this.formAttr.item[idx].msg = 'Tips:您忘记选择统计维度了哦o(╥﹏╥)o'
        this.formAttr.item[idx].tip_show = true
      } else if (
        line.seedim === 3 &&
        line.selsuf_type === 'time' &&
        line.comDate[0] === ''
      ) {
   
        this.formAttr.item[idx].msg = 'Tips:您忘记选择时间范围了哦o(╥﹏╥)o'
        this.formAttr.item[idx].tip_show = true
      } else if (line.scompare === 7 && line.seerange_content === '') {
   
        this.formAttr.item[idx].msg = 'Tips:您忘记输入范围了哦o(╥﹏╥)o'
        this.formAttr.item[idx].tip_show = true
      } else if (line.compare === 7 && line.comrange_content === '') {
   
        this.formAttr.item[idx].msg = 'Tips:您忘记输入范围了哦o(╥﹏╥)o'
        this.formAttr.item[idx].tip_show = true
      } else {
   
        // 验证通过
        if (this.formAttr.item[idx].tip_show) {
   
          this.formAttr.item[idx].tip_show = false
        }
        // ------------类型判断------------
        if (line.seedim !== 3 && line.scompare !== 7 && line.compare !== 7) {
   
          lineType = 111
        } else if (line.seedim !== 3 && line.scompare !== 7 && line.compare === 7) {
   
          lineType = 112
        } else if (line.seedim !== 3 && line.scompare === 7 && line.compare !== 7) {
   
          lineType = 121
        } else if (line.seedim !== 3 && line.scompare === 7 && line.compare === 7) {
   
          lineType = 122
        } else if (
          line.seedim === 3 &&
          line.selsuf_type === 'num' &&
          line.compare !== 7
        ) {
   
          lineType = 211
        } else if (
          line.seedim === 3 &&
          line.selsuf_type === 'num' &&
          line.compare === 7
        ) {
   
          lineType = 212
        } else if (line.seedim === 3 && line.selsuf_type === 'time') {
   
          lineType = 221
        }
        // ------------内容填充------------
        switch (lineType) {
   
          case 111:
            resObj.index = line.index
            resObj.content =
              line.seedim_label +
              line.scompare_label +
              line.sNum +
              line.suffix_label +
              line.compare_label +
              line.cNum
            resObj.val = {
   
              seedim: line.seedim,
              seedim_label: line.seedim_label,
              scompare: line.scompare,
              scompare_label: line.scompare_label,
              sNum: line.sNum,
              suffix: line.suffix,
              suffix_label: line.suffix_label,
              compare: line.compare,
              compare_label: line.compare_label,
              cNum: line.cNum
            }
            break
          case 112:
            resObj.index = line.index
            resObj.content =
              line.seedim_label +
              line.scompare_label +
              line.sNum +
              line.suffix_label +
              '范围在' +
              line.comrange_content
            resObj.val = {
   
              seedim: line.seedim,
              seedim_label: line.seedim_label,
              scompare: line.scompare,
              scompare_label: line.scompare_label,
              sNum: line.sNum,
              suffix: line.suffix,
              suffix_label: line.suffix_label,
              compare: line.compare,
              comrange: line.comrange,
              comrange_content: line.comrange_content
            }
            break
          case 121:
            resObj.index = line.index
            resObj.content =
              line.seedim_label +
              line.seerange_content +
              line.suffix_label +
              line.compare_label +
              line.cNum
            resObj.val = {
   
              seedim: line.seedim,
              seedim_label: line.seedim_label,
              scompare: line.scompare,
              seerange: line.seerange,
              seerange_content: line.seerange_content,
              suffix: line.suffix,
              suffix_label: line.suffix_label,
              compare: line.compare,
              compare_label: line.compare_label,
              cNum: line.cNum
            }
            break
          case 122:
            resObj.index = line.index
            resObj.content =
              line.seedim_label +
              line.seerange_content +
              line.suffix_label +
              '范围在' +
              line.comrange_content
            resObj.val = {
   
              seedim: line.seedim,
              seedim_label: line.seedim_label,
              scompare: line.scompare,
              seerange: line.seerange,
              seerange_content: line.seerange_content,
              suffix: line.suffix,
              suffix_label: line.suffix_label,
              compare: line.compare,
              comrange: line.comrange,
              comrange_content: line.comrange_content
            }
            break
          case 211:
            resObj.index = line.index
            resObj.content = line.selsuf_label + line.compare_label + line.cNum
            resObj.val = {
   
              seedim: line.seedim,
              selsuf: line.selsuf,
              selsuf_label: line.selsuf_label,
              compare: line.compare,
              compare_label: line.compare_label,
              cNum: line.cNum
            }
            break
          case 212:
            resObj.index = line.index
            resObj.content = line.selsuf_label + '范围在' + line.comrange_content
            resObj.val = {
   
              seedim: line.seedim,
              selsuf: line.selsuf,
              selsuf_label: line.selsuf_label,
              compare: line.compare,
              comrange: line.comrange,
              comrange_content: line.comrange_content
            }
            break
          case 221:
            resObj.index = line.index
            resObj.content =
              line.selsuf_label + '范围在' + line.comDate[0] + '至' + line.comDate[1]
            resObj.val = {
   
              seedim: line.seedim,
              selsuf: line.selsuf,
              selsuf_label: line.selsuf_label,
              datetime: line.datetime,
              comDate: line.comDate,
              selsuf_type: line.selsuf_type
            }
            break
        }
        if (
          !this.resObjArr.some(
            (item) => item.index === line.index && item.content === resObj.content
          )
        ) {
   
          this.resObjArr = this.resObjArr.filter((item) => item.index !== line.index)
          this.resObjArr.push(resObj)
          this.$emit('getData', this.resObjArr, this.attr_name)
        }
      }
      if (this.resObjArr.length === 0) {
   
        this.$emit('getData', '不限', this.attr_name)
      }
    },
    // 日期选择器
    handleDatetime (val, idx) {
   
      this.formAttr.item[idx].datetime = val
    },
    confirmDatetime (idx) {
   
      this.formAttr.item[idx].comDate = JSON.parse(
        JSON.stringify(this.formAttr.item[idx].datetime)
      )
    },
    day_clear (idx) {
   
      this.formAttr.item[idx].datetime = ['', '']
      this.formAttr.item[idx].comDate = JSON.parse(
        JSON.stringify(this.formAttr.item[idx].datetime)
      )
    },
    clearShortCut () {
   
      const shortCut = document.querySelectorAll('.ivu-picker-panel-shortcut')
      const len = shortCut.length
      for (let i = 0; i < len; i++) {
   
        shortCut[i].style.background = 'none'
      }
    }
  },
  created () {
   
    // 赋初值
    setTimeout(() => {
   
      if (!this.isCreate) {
   
        // 复制
        this.formAttr.item = this.initData
        this.index = this.formAttr.item.length
        let idx = 0
        this.formAttr.item.forEach((line) => {
   
          this.dim_change(false, line.seedim, idx)
          this.scom_change(false, line.scompare, idx)
          this.com_change(false, line.compare, idx)
          var line_copy = deepCopy(line)
          line_copy.seerange = commit_range_handle(line_copy.seerange)
          line_copy.comrange = commit_range_handle(line_copy.comrange)
          this.handleConfirm(line_copy, idx)
          idx++
        })
      }
    }, 1800)
  }
  • handleAdd:增加条件处理
  • data_handel_emit:校验及数据回传,校验信息存放在该条件的msg里面
  • 初始进入的时候如果isCreate为false则进行赋初值的处理
  • 其他大多是选择后数据同步到formAttr.item

组件应用

<addCondition
   attr_name="登录"
   :initData="init_login_state"
   :isCreate="login_create"
   @getData="addC_get"
/>

import addCondition from '@/components/addCondition'

components: {
   
    addCondition 
}

data () {
   
    return {
   
        init_login_state: deepCopy(init_form),
        login_create: true
    }
}
  • import引入——>组件注册——>使用
  • 父——>子传参:attr_name属性名、initData初始条件数组、isCreate创建还是赋初值

事件钩子

// 拿到选择的条件数组
addC_get (resObjArr, attr_name) {
   
      var content
      var obj
      if (resObjArr === '不限') {
   
        content = '不限'
        obj = {
   
          nolimit: true
        }
      } else {
   
        const arr_c = []
        const arr_v = []
        resObjArr.forEach((item) => {
   
          arr_c.push(item.content)
          arr_v.push(item.val)
        })
        content = arr_c.join(',')
        obj = arr_v
      }
      this.previewAttr.some((item) => {
   
        if (item.attr_name === attr_name + ':') {
   
          item.attr_content = content
        }
      })
      switch (attr_name) {
   
        case '登录':
          this.groupObj.user_behavior.login_state = obj
          break
      }
    }
  • addC_get :拿到选择的条件数组

github

完整代码点击这里