vue:使用【3.0】:条件模块

发布时间:2024年01月15日

一、条件层级效果图

二、代码

<template>
  <ContentWrap>
    <!-- 添加条件分支:level1 -->
    <div class="btnBox" v-if="isEdit">
      <el-button type="primary" @click="add">添加条件分支</el-button>
    </div>

    <div v-if="tableList.length > 0" class="boxOne">
      <div class="title" v-for="(level1, index) in tableList" :key="level1.accountName">
        <!-- 返回科目:level2 -->
        <el-form-item :label="`${level1.accountName}`" label-width="80px">
          <el-select
            v-model="level1.conditionName"
            placeholder="请选择数据"
            :disabled="!isEdit"
            filterable
          >
            <el-option
              v-for="(item, index1) in titleList"
              :key="index1"
              :label="item.label"
              :value="item.value"
            />
          </el-select>
          <el-button
            link
            :icon="Delete"
            @click="handleDelete(index)"
            type="danger"
            class="ml-10px"
            v-if="isEdit"
          />
          <el-button link :icon="Plus" @click="handleAdd(level1)" v-if="isEdit" />
        </el-form-item>

        <!-- 条件设置:level3 -->
        <div class="boxTwo" v-if="level1.children?.length > 0">
          <!-- 此处可不展示 style="display: none" -->
          <div class="left">
            <div class="round" @click="handleRelation(level1)">
              {{ level1.relation }}
            </div>
            <div class="border"></div>
          </div>
          <div class="right">
            <div
              class="level1Right"
              v-for="(level2, level2Index) in level1.children"
              :key="level2Index"
            >
              <!-- 符号:or/AND -->
              <div class="left" v-if="level2.children?.length > 0">
                <div class="round" @click="handleLevelRelation(level2)">
                  {{ level2.relation }}
                </div>
                <div class="border"></div>
              </div>
              <div class="levelRight" v-if="level2.children?.length > 0">
                <div
                  class="mb-20px"
                  v-for="(level3, level3Index) in level2.children"
                  :key="level3Index"
                >
                  <el-row :gutter="20">
                    <!-- 字典表 -->
                    <el-col :span="5">
                      <el-form-item>
                        <el-select
                          v-model="level3.pName"
                          placeholder="请选择数据"
                          :disabled="!isEdit"
                        >
                          <el-option
                            v-for="(operator, index1) in operatorList"
                            :key="index1"
                            :label="operator.label"
                            :value="operator.value"
                          />
                        </el-select>
                      </el-form-item>
                    </el-col>
                    <!-- 数值类型 -->
                    <el-col :span="5">
                      <el-form-item>
                        <el-select
                          v-model="level3.pType"
                          :placeholder="t('common.inputText')"
                          :disabled="!isEdit"
                        >
                          <el-option
                            v-for="(accountType, index1) in accountTypeList"
                            :key="index1"
                            :label="accountType.label"
                            :value="accountType.value"
                          />
                        </el-select>
                      </el-form-item>
                    </el-col>
                    <!-- 运算符,根据数值类型显示 -->
                    <el-col :span="5">
                      <el-form-item>
                        <el-select
                          v-model="level3.pOption"
                          placeholder="请选择数据"
                          :disabled="level3.pType === '' || !isEdit"
                        >
                          <el-option
                            v-for="(kind, index1) in typeMap[level3.pType]"
                            :key="index1"
                            :label="kind.label"
                            :value="kind.value"
                          />
                        </el-select>
                      </el-form-item>
                    </el-col>
                    <!-- 值 -->
                    <el-col :span="6">
                      <el-form-item>
                        <el-input
                          placeholder="请输入"
                          v-model="level3.pValue"
                          :disabled="!isEdit"
                        />
                        <!-- <el-date-picker
                          v-if="level3.pType === '3'"
                          v-model="level3.pValue"
                          clearable
                          :placeholder="t('common.selectText')"
                          type="date"
                          value-format="YYYY-MM-DD"
                          :disabled="!isEdit"
                        />
                        <el-input
                          v-else
                          placeholder="请输入"
                          v-model="level3.pValue"
                          :disabled="!isEdit"
                        /> -->
                      </el-form-item>
                    </el-col>
                    <!-- 操作 -->
                    <el-col :span="3">
                      <el-form-item>
                        <el-button
                          link
                          :icon="Delete"
                          @click="handleRowDelete(level2, level3Index)"
                          type="danger"
                          class="ml-10px"
                          v-if="isEdit"
                        />
                        <el-button
                          link
                          :icon="Plus"
                          @click="handleRowAdd(level2, index)"
                          v-if="isEdit"
                        />
                      </el-form-item>
                    </el-col>
                  </el-row>
                </div>
                <div>
                  <el-button
                    link
                    :icon="Delete"
                    @click="handleNodeDelete(level1, level2Index)"
                    type="danger"
                    class="ml-10px"
                    v-if="isEdit"
                  />
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </ContentWrap>
</template>
<script lang="ts" setup>
import { Delete, Plus } from '@element-plus/icons-vue'
import * as apiType from '@/api/system/dict/dict.data.ts'

defineOptions({ name: 'SettingTable' })
const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗
const emits = defineEmits(['success'])
const titleList = [
  { label: 'lemon', value: 1 },
  { label: 'orange', value: 2 },
  { label: 'apple', value: 3 },
  { label: 'banana', value: 4 },
  { label: 'mango', value: 5 },
  { label: 'cherry', value: 6 }
]
const operatorList = [
  { label: 'doudou1', value: 1 },
  { label: 'doudou2', value: 2 },
  { label: 'doudou3', value: 3 },
  { label: 'doudou4', value: 4 },
  { label: 'doudou5', value: 5 },
  { label: 'doudou6', value: 6 }
]
const accountTypeList = [
  {
    value: 1,
    label: '数值'
  },
  {
    value: 2,
    label: '字符串'
  },
  {
    value: 3,
    label: '日期'
  }
]
// 条件配置(数据类型:数值)
const numberConfig = [
  {
    value: 1,
    label: '>'
  },
  {
    value: 2,
    label: '>='
  },
  {
    value: 3,
    label: '<= '
  },
  {
    value: 4,
    label: '<'
  },
  {
    value: 5,
    label: '='
  },
  {
    value: 6,
    label: '!='
  }
]

// 条件配置(数据类型:字符串)
const stringConfig = [
  {
    value: 7,
    label: 'equals'
  },
  {
    value: 8,
    label: 'contains'
  },
  {
    value: 9,
    label: 'startsWith'
  },
  {
    value: 10,
    label: 'endsWith'
  },
  {
    value: 11,
    label: 'equals'
  },
  {
    value: 12,
    label: 'before'
  },
  {
    value: 13,
    label: 'after'
  }
]

// 条件配置(数据类型:日期)
const dateConfig = [
  {
    value: 11,
    label: 'YYYY-MM-DD'
  },
  {
    value: 12,
    label: ' YYYY-MM-DD HH:mm:ss'
  },
  {
    value: 13,
    label: 'YYYY-MM'
  }
]

interface AccountItem {
  accountCode?: string
  accountName?: string
  label?: string
  value?: string
}

interface ConditionItem {
  conditionName?: string
  children?: childrenItems[]
  accountName?: string
  relation?: string
}

interface itemProps {
  pName: string
  pType: string
  pOption: string
  pValue: string
}

interface childrenItems {
  relation?: string
  children?: itemProps[]
}

const props = defineProps({
  accountList: {
    type: Array as () => AccountItem[],
    required: true
  },
  chooseList: {
    type: Array as () => ConditionItem[],
    default: () => []
  },
  isEdit: {
    type: Boolean,
    default: false
  }
})
const chooseList = computed(() => {
  return props.chooseList
})

const tableList = ref<ConditionItem[]>([])
// 运算符
const typeMap = {
  '1': numberConfig,
  '2': stringConfig,
  '3': dateConfig
}

/** 第一步:【level1】添加条件分支:新增 */
const add = () => {
  console.log('第一步:')
  // 1、判断上面一条数据是否填写
  const lastItem = tableList.value[tableList.value.length - 1]
  if (lastItem !== undefined) {
    if (lastItem?.conditionName === '') {
      message.error(`返回科目规则需配置完整`)
      return
    }
    const hasAllValues = checkValues(lastItem.children)
    if (!hasAllValues) {
      message.error('请填写完整条件')
      return
    }
  }

  // 2、添加数据
  const result: ConditionItem = {
    accountName: '返回科目',
    conditionName: '',
    relation: 'AND',
    children: []
  }
  tableList.value.push(result)
  console.log('添加条件分支', tableList.value)
  emits('success', tableList.value)
}
// 外层:条件
const handleRelation = (item) => {
  console.log('外层', item)
  if (!props.isEdit) return
  item.relation = item.relation === 'AND' ? 'OR' : 'AND'
  console.log('????', tableList.value)
  emits('success', tableList.value)
}

function checkValues(data) {
  for (const item of data) {
    if (item.pName === '' || item.pType === '' || item.pOption === '' || item.pValue === '') {
      return false
    }
    if (item.children && item.children.length > 0) {
      const hasAllFields = checkValues(item.children)
      if (!hasAllFields) {
        return false
      }
    }
  }
  return true
}

/** 第二步:【level2】返回科目:新增、删除、条件关系 */
// 新增
const handleAdd = (item) => {
  console.log('第二步:', item)
  // 1、判断上面一条数据是否填写
  if (item?.conditionName === '') {
    message.error('请选择提成科目!')
    return
  }
  // 2、判断上条数据是否填写完整
  const lastItem = item.children[item.children.length - 1]
  if (lastItem !== undefined) {
    if (lastItem.children?.length > 0) {
      const hasAllValues = checkFields(lastItem)
      if (!hasAllValues) {
        message.error('请填写完整条件')
        return
      }
    }
  } else {
    if (lastItem?.children?.length == 0) {
      message.error('请填写完整条件')
      return
    }
  }

  // 3、添加数据
  const result: itemProps = {
    pName: '',
    pType: '',
    pOption: '',
    pValue: ''
  }
  item.children.push({
    relation: 'AND',
    children: [result]
  })
  console.log('科目添加条件:新增', tableList.value)
  emits('success', tableList.value)
}
// 删除
const handleDelete = (index) => {
  console.log('第一步:科目添加条件:删除', tableList.value)
  tableList.value.splice(index, 1)
  emits('success', tableList.value)
}
// 条件关系
const handleLevelRelation = (item) => {
  console.log('里层')
  if (!props.isEdit) return
  item.relation = item.relation === 'AND' ? 'OR' : 'AND'
  emits('success', tableList.value)
}

// 判断数组中的每个对象的 pName、pType、pOption、pValue 字段是否都有值
function checkFields(data) {
  for (const item of data.children) {
    if (item.pName === '' || item.pType === '' || item.pOption === '' || item.pValue === '') {
      return false
    }
  }
  return true
}

/** 第三步:行内添加 */
const handleRowAdd = (item, index: number) => {
  console.log('第三步:新增行', item, index)
  // 1、判断上面一条数据是否填写
  const arr = item.children
  const lastItem = arr.length > 0 ? arr[arr.length - 1] : null
  console.log('lastItem', lastItem)
  if (
    lastItem.pName === '' ||
    lastItem.pType === '' ||
    lastItem.pOption === '' ||
    lastItem.pValue === ''
  ) {
    message.error(`返回科目规则需配置完整!`)
    return
  }
  // 2、添加数据
  const result: itemProps = {
    pName: '',
    pType: '',
    pOption: '',
    pValue: ''
  }
  item.children.push(result)
  console.log('tableList', tableList.value)
  emits('success', tableList.value)
}
const handleRowDelete = (item, index?: number) => {
  item.children.splice(index, 1)
  console.log('????', tableList.value)
  emits('success', tableList.value)
}

/** 第四步:删除节点 */
const handleNodeDelete = (item, index) => {
  item.children.splice(index, 1)
  emits('success', tableList.value)
}

onMounted(() => {
  tableList.value = chooseList.value // 初始化赋值
})

watch(
  () => props.chooseList,
  (val) => {
    tableList.value = val
  }
)
</script>

<style lang="scss" scoped>
.title {
  padding: 10px 0;
}
.btnBox {
  display: flex;
  justify-content: flex-end;
}
.boxTwo {
  display: flex;
  justify-content: space-between;
  margin-top: 10px;
  .left {
    display: flex;
    align-items: center;
    position: relative;
    .round {
      width: 30px;
      height: 30px;
      border-radius: 50%;
      background-color: white;
      border: 1px solid black;
      font-size: 14px;
      color: black;
      margin: auto;
      position: relative;
      z-index: 3;
      text-align: center;
    }
    .border {
      position: absolute;
      left: 50%;
      top: 0;
      bottom: 0;
      border-left: 1px solid black;
    }
  }
  .right {
    flex: 1;
    padding: 10px;
  }
  .level1Right {
    display: flex;
    margin-bottom: 10px;
  }
  .levelRight {
    flex: 1;
    padding: 10px 10px 0 10px;
    display: block;
  }
}
</style>

文章来源:https://blog.csdn.net/u013592575/article/details/135596751
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。