vue3+element实现复杂表单选中回显

html 复制代码
<template>
  <div>
    <el-card shadow="never">
      <el-form ref="queryDOM" :model="queryForm" label-width="80">
        <el-form-item label="客户简称" prop="customerShortName">
          <el-input clearable v-model="queryForm.customerShortName" class="max-w-260px" maxlength="6"></el-input>
          <el-checkbox class="ml-2" label="仅显示经营正常" v-model="queryForm.isNormal"></el-checkbox>
        </el-form-item>
        <div v-show="filteredSwtich">
          <el-form-item label="客户全称" prop="customerFullName">
            <company-complete v-model="queryForm.customerFullName" maxlength="40" class="max-w-260px" />
          </el-form-item>
          <el-form-item label="客户类别" prop="customerTypes">
            <el-checkbox-group v-model="queryForm.customerTypes">
              <el-checkbox v-for="item in crm_customer_type" :key="item.dictValue" :value="item.dictValue"
                :label="item.dictLabel"></el-checkbox>
            </el-checkbox-group>
          </el-form-item>
          <el-form-item label="级别" prop="customerLevels">
            <el-checkbox class="important-mr-4" v-model="checkAllLevels" :indeterminate="levelsIndeterminate"
              @change="handleCheckAllLevels">
              全选
            </el-checkbox>
            <el-checkbox-group class="contents" v-model="queryForm.customerLevels" @change="handleCheckedLevelsChange">
              <el-checkbox v-for="item in customer_level" :key="item.dictValue" :value="item.dictValue"
                :label="item.dictLabel"></el-checkbox>
            </el-checkbox-group>
          </el-form-item>
          <el-form-item label="行业" prop="industries">
            <el-checkbox class="important-mr-4" v-model="checkAllIndustries" :indeterminate="industriesIndeterminate"
              @change="handleCheckAllIndustries">
              全选
            </el-checkbox>
            <el-checkbox-group class="contents" v-model="queryForm.industries" @change="handleCheckedIndustriesChange">
              <el-checkbox v-for="item in customer_industry" :key="item.dictValue" :value="item.dictValue"
                :label="item.dictLabel"></el-checkbox>
            </el-checkbox-group>
          </el-form-item>
          <el-form-item label="所在地区" prop="address">
            <District v-model="queryForm.address" v-model:value="address" class="max-w-260px" />
          </el-form-item>
          <!-- <el-form-item label="商机" prop="industry">
            <el-checkbox class="ml-2" label="有赢单" v-model="queryForm.status"></el-checkbox>
          </el-form-item> -->
          <!-- <el-form-item label="需求\项目" prop="industry">
            <el-checkbox-group v-model="queryForm.customerType">
              <el-checkbox label="有进行中"></el-checkbox>
              <el-checkbox label="有已完成"></el-checkbox>
            </el-checkbox-group>
          </el-form-item> -->
          <el-form-item label="创建人" prop="createUserId">
            <user-dropdown v-model="queryForm.createUserId" class="max-w-260px" />
          </el-form-item>
          <el-form-item label="创建时间" prop="createTimePeriod">
            <el-date-picker v-model="queryForm.createTimePeriod" value-format="YYYY-MM-DD" type="daterange"
              @visible-change="e => { if (e) { queryForm.createTimePeriod = [] } }"
              class="max-w-260px"></el-date-picker>
          </el-form-item>
        </div>
        <div class="text-right">
          <el-button icon="Search" @click="searchData" type="primary" :loading="loading">搜索</el-button>
          <el-button icon="Refresh" @click="resetData" :loading="loading">重置</el-button>
          <el-button :icon="filteredSwtich ? 'ArrowUp' : 'ArrowDown'" @click="filteredSwtich = !filteredSwtich" text>
            {{ filteredSwtich ? "收起" : "展开" }}
          </el-button>
        </div>
      </el-form>
    </el-card>
    <el-card shadow="never" class="mt-5">
      <div class="fillter-tag">
        <strong v-show="filteredView.length">筛选:</strong>
        <el-tag disable-transitions class="mr-2" v-for="tag in filteredView" :key="tag.label" closable
          :title="tag.label" @close="removeFilteredTag(tag)">
          {{ tag.label }}
        </el-tag>
      </div>
      <cit-table :loading="tableLoading" :data="tableData" :total="dataTotal" :page-size="queryForm.pageSize"
        :current-page="queryForm.pageNum" @current-change="handleCurrentChange" @size-change="dataSizeChange">
        <template #columns>
          <el-table-column prop="customerFullName" label="客户全称" min-width="220">
            <template #default="scope">
              <router-link :to="'/customer/list/detail/' + scope.row.id">
                <el-button link type="primary">{{ scope.row.customerFullName }}</el-button>
              </router-link>
            </template>
          </el-table-column>
          <el-table-column prop="customerShortName" label="客户简称" />
          <el-table-column prop="customerType" label="客户类别">
            <template #default="scope">
              <dict-tag :options="crm_customer_type" :value="scope.row.customerType" />
            </template>
          </el-table-column>
          <el-table-column prop="operateStatus" label="经营情况">
            <template #default="scope">
              <dict-tag :options="customer_operate_status" :value="scope.row.operateStatus" />
            </template>
          </el-table-column>
          <el-table-column prop="customerLevel" label="级别">
            <template #default="scope">
              <dict-tag :options="customer_level" :value="scope.row.customerLevel" />
            </template>
          </el-table-column>
          <el-table-column prop="industry" label="行业">
            <template #default="scope">
              <dict-tag :options="customer_industry" :value="scope.row.industry" />
            </template>
          </el-table-column>
          <el-table-column prop="customerType" label="所在地址">
            <template #default="scope">
              {{ scope.row.districtName }} {{ scope.row.address }}
            </template>
          </el-table-column>
          <!-- <el-table-column prop="customerType" label="商机数(赢单)" sortable />
          <el-table-column prop="customerType" label="报障数" /> -->
        </template>
      </cit-table>
    </el-card>
  </div>
</template>

<script setup name="CustomerListIndex">
/**
* @author        全易
* @time          2025-10-24 15:21:32 星期五
* @description   客户列表
* @example       
**/
import { getUserList } from "@/service/dictionarys.js";
import { customerList } from '../api/customer.js';
import filterLabels from './assets/filterLabels.json';







const instance = getCurrentInstance();
const filteredSwtich = ref(false); // 是否显示更多过滤条件

const {
  customer_operate_status,
  customer_level,
  crm_customer_type,
  customer_industry
} = instance.proxy.useDict(
  "customer_operate_status",
  "customer_level",
  "crm_customer_type",
  "customer_industry"
);

// 监听事件总线 [提交了客户信息]
eventBus?.on('customer-updata', () => {
  getData()
});


const { queryForm, tableData, dictionarys } = toRefs(reactive({
  queryForm: {
    pageNum: 1,
    pageSize: Number(import.meta.env.VITE_APP_DATA_SIZE),
    isNormal: true
  },
  tableData: [],
  dictionarys: {
    customer_level,
    crm_customer_type,
    customer_industry
  }
}));

// 赋值创建时间范围(用两个字段)
watch(() => queryForm.value.createTimePeriod, (time) => {
  queryForm.value.createTimeStart = time && time[0] || null;
  queryForm.value.createTimeEnd = time && time[1] || null;
});
// 所在地区字段重新定义(取最后一位)
watch(() => queryForm.value.address, (now) => {
  queryForm.value.districtCode = now && now[2] || null;
});

function getDictionarys() {
  // 平台用户
  getUserList().then((res) => {
    if (res.code === 200) {
      dictionarys.value.systemUsers = res.data;
    }
  })
}
getDictionarys()

/*  过滤条件回显  */
const address = ref([]);
const filteredView = computed(() => {
  let tags = []
  for (const item of filterLabels) {
    if (item.type === 'array') {
      queryForm.value[item.key]?.forEach((val, index) => {
        if (index !== 0) { return; }
        if (item.key === 'address') {
          tags.push({ type: item.key, data: queryForm.value[item.key], label: `${item.label} - ${address.value?.fullName}` })
        } else if (item.key === 'createTimePeriod') {
          tags.push({ type: item.key, data: queryForm.value[item.key], label: `${item.label} - ${queryForm.value?.createTimeStart} ~ ${queryForm.value?.createTimeEnd}` })
        } else {
          const dictionary = instance.proxy.selectDictLabel(dictionarys.value?.[item.dictionary], queryForm.value[item.key], { name: 'dictLabel', code: 'dictValue' })
          tags.push({ type: item.key, data: queryForm.value[item.key], label: `${item.label} - ${dictionary}` })
        }
      });
    } else if (item.type === 'string' && queryForm.value[item.key]) {
      if (item.key === 'createUserId') {
        const systemUserInfo = instance.proxy.selectDictLabel(dictionarys.value?.systemUsers, queryForm.value[item.key], { name: 'realName', code: 'id' })
        tags.push({ type: item.key, data: queryForm.value[item.key], label: `${item.label} - ${systemUserInfo}` })
      } else {
        tags.push({ type: item.key, data: queryForm.value[item.key], label: `${item.label} - ${queryForm.value[item.key]}` })
      }
    }
  }
  return tags
})

/* ---------- 删除filteredView标签 ---------- */
function removeFilteredTag(tag) {
  for (const item of filterLabels) {
    if (item.key === tag.type) {
      if (Array.isArray(queryForm.value[item.key])) {
        queryForm.value[item.key] = [];
      } else {
        queryForm.value[item.key] = null;
      }
      break;
    }
  }
}

// 级别全选
const checkAllLevels = ref(false)
const levelsIndeterminate = ref(false)
watch(() => queryForm.value.customerLevels, (now) => {
  const checkedCount = now?.length || 0;
  const totalCount = customer_level.value?.length || 0;
  if (checkedCount === 0) {
    // 无选
    checkAllLevels.value = false;
    levelsIndeterminate.value = false;
  } else if (checkedCount === totalCount) {
    // 全选
    checkAllLevels.value = true;
    levelsIndeterminate.value = false;
  } else {
    // 半选
    checkAllLevels.value = false;
    levelsIndeterminate.value = true;
  }
});
const handleCheckAllLevels = (val) => {
  queryForm.value.customerLevels = val ? customer_level.value.map(item => item.dictValue) : []
}
const handleCheckedLevelsChange = (value) => {
  const checkedCount = value.length;
  checkAllLevels.value = checkedCount === customer_level.value.length
  levelsIndeterminate.value = checkedCount > 0 && checkedCount < customer_level.value.length
}
// 行业全选
const checkAllIndustries = ref(false)
const industriesIndeterminate = ref(false)
watch(() => queryForm.value.industries, (now) => {
  const checkedCount = now?.length || 0;
  const totalCount = customer_industry.value?.length || 0;
  if (checkedCount === 0) {
    // 无选
    checkAllIndustries.value = false;
    industriesIndeterminate.value = false;
  } else if (checkedCount === totalCount) {
    // 全选
    checkAllIndustries.value = true;
    industriesIndeterminate.value = false;
  } else {
    // 半选
    checkAllIndustries.value = false;
    industriesIndeterminate.value = true;
  }
});
const handleCheckAllIndustries = (val) => {
  queryForm.value.industries = val ? customer_industry.value.map(item => item.dictValue) : []
}
const handleCheckedIndustriesChange = (value) => {
  const checkedCount = value.length;
  checkAllIndustries.value = checkedCount === customer_industry.value.length
  industriesIndeterminate.value = checkedCount > 0 && checkedCount < customer_industry.value.length
}

// 获取数据
const dataTotal = ref(0);
const tableLoading = ref(false);
function getData() {
  tableLoading.value = true;
  tableData.value = [];
  customerList(queryForm.value).then((res) => {
    if (res.code === 200) {
      dataTotal.value = res.data.total;
      tableData.value = res.data.list;
    }
  }).finally(() => {
    tableLoading.value = false;
  })
}
getData()

// 翻页
function handleCurrentChange(now) {
  queryForm.value.pageNum = now;
  getData()
}
// 页量
function dataSizeChange(size) {
  queryForm.value.pageSize = size;
  getData()
}
// 过滤数据
function searchData() {
  queryForm.value.pageNum = 1;
  getData()
}

// 重置条件
async function resetData() {
  instance.proxy.$refs.queryDOM.resetFields()
  await nextTick()
  getData()
}


</script>

<style scoped>
.fillter-tag {
  white-space: nowrap;
  overflow-y: auto;
}
</style>
相关推荐
小笔学长2 小时前
Mixin 模式:灵活组合对象功能
开发语言·javascript·项目实战·前端开发·mixin模式
我是人机不吃鸭梨2 小时前
Flutter 桌面端开发终极指南(2025版):构建跨平台企业级应用的完整解决方案
开发语言·javascript·人工智能·flutter·架构
Gogym2 小时前
解决vue axios提交日期,服务器接收少一天的问题
前端·javascript·vue.js
淘源码d2 小时前
上门家政源码,基于Java/SpringBoot和Uniapp的全栈家政预约平台,支持多端适配(小程序/H5/APP)
java·vue.js·源码·家政·家政小程序源码·上门家政·家政平台
韭菜炒大葱2 小时前
LangChain 二:输出结果定制与历史管理能力详解
前端·langchain·openai
明月_清风2 小时前
不止是代码堆放:带你全面掌握 Monorepo 核心技术与选型
前端
Aliex_git2 小时前
Vue2 - Watch 侦听器源码理解
前端·javascript·vue.js·笔记·学习
你疯了抱抱我2 小时前
【QQ】空间说说批量删除脚本(不用任何额外插件,打开F12控制台即可使用)
开发语言·前端·javascript
进击的野人2 小时前
Vuex 详解:现代 Vue.js 应用的状态管理方案
前端·vue.js·前端框架