✨1. 实现功能
- 🌟添加条件进行数据筛选
- 根据筛选数据条件不同,显示不同的UI组件:包含
datetime
、select
、input
等 - 筛选完条件可继续添加与取消条件
- 当然可以在条件列表中进行直接删除,当删除完所有条件之后,回到添加条件页面
- 清空搜索条件直接回到添加条件页面
- 根据筛选数据条件不同,显示不同的UI组件:包含
✨2. 效果图
-
💖打开筛选条件弹窗💖
-
💖💖查看筛选条件不同的
UI
结构效果预览💖💖
-
💖💖💖继续添加和取消筛选条件效果💖💖💖
-
💖💖条件列表中直接删除条件效果💖💖
-
💖清空搜索条件效果💖
✨3. 组件代码
🌹1. 组件目录结构
2. 🍗 🍖添加条件页面
<script setup lang="ts">
import { ref } from 'vue'
import { NavData } from './constant'
import AddedCondition from './components/added-condition/index.vue'
defineOptions({
name: 'SearchClues',
})
const { token } = useAntdToken()
// 是否有搜索添加,判断显示筛选区域
const isNav = ref(true)
// 添加条件弹窗
const AddedConditionRef = ref()
function handleClick(i: number) {
if (i === 0) {
AddedConditionRef.value.handleOpen()
return
}
if (i === 1) {
console.log(1)
return
}
if (i === 2) {
console.log(2)
}
}
// 筛选条件判断
function handleIsPanel(v: boolean) {
isNav.value = !v
if (isNav.value && !v) {
isSearch.value = false
}
}
function handleSearch(list: any) {
console.log(list, 'handleSearch')
isSearch.value = true
}
// 是否搜索
const isSearch = ref<boolean>(false)
</script>
<template>
<div>
<a-card>
<div v-if="isNav" class="flex">
<div v-for="(nav, i) in NavData" :key="i" class="flex-center cursor-pointer m-ie-8" @click="handleClick(nav.i)">
<div class="flex-center p-2 b-rd-10 m-ie-2" :style="{ 'background-color': token?.colorPrimary }">
<img :src="nav.url" width="24" height="24" alt="">
</div>
<span>{{ nav.title }}</span>
</div>
</div>
<AddedCondition ref="AddedConditionRef" @handle-is-panel="handleIsPanel" @handle-search="handleSearch" />
</a-card>
<a-card class="m-t-5">
<div>
<h2>三步完成线索查找</h2>
<div>待完成</div>
</div>
</a-card>
</div>
</template>
<style lang="less" scoped></style>
🍀3. 选择条件-条件列表added-condition/index.vue
🍀
<script setup lang="ts">
import { createVNode, ref } from 'vue'
import { DownOutlined, ExclamationCircleOutlined, MinusCircleOutlined, PlusOutlined, UpOutlined } from '@ant-design/icons-vue'
import { Modal, message } from 'ant-design-vue'
import { JudgementCondition } from '../../constant'
import SelectCondition from './select-condition.vue'
import type { Condition } from '@/api/interface/getting-clues'
defineOptions({
name: 'AddedCondition',
})
const emit = defineEmits(['handleIsPanel', 'handleSearch', 'handleSave', 'handleClear'])
const selectionConditionRef = ref()
function handleOpen() {
selectionConditionRef.value.handleOpen()
}
// 是否有搜索添加,判断显示筛选区域
const isPanel = ref(false)
function handleOk(list: Condition.ConditionItem[]) {
conditionsList.value = list
isPanel.value = true
emit('handleIsPanel', isPanel.value)
}
/**
* @constant searchGeneralType 搜索条件总类型
* @constant conditionsList 搜索条件列表
*/
const searchGeneralType = ref('0')
const conditionsList = ref<Condition.ConditionItem[]>([])
// 获取下拉框数据
function getDefaultOptions(condition: Condition.ConditionItem) {
if (condition.type === 'SelectOption') {
return condition.keys?.map(item => (
JudgementCondition[item.key][item.value] || JudgementCondition.renderData.ifData
))[0]
}
else {
return JudgementCondition.type.operateState
}
}
// 获取多选条件下拉框数据
function getKeysOptions() {
return JudgementCondition.default.default
}
function handleDelete(index: number) {
conditionsList.value.splice(index, 1)
}
watch(() => conditionsList, (n) => {
if (n.value.length === 0) {
isPanel.value = false
emit('handleIsPanel', isPanel.value)
}
}, { deep: true })
// 筛选
function handleSearch() {
emit('handleSearch', conditionsList.value)
}
// 保存
const loading = ref<boolean>(false)
function handleSave() {
Modal.confirm({
title: '确认',
icon: createVNode(ExclamationCircleOutlined),
content: '确定要保存此筛选条件吗?',
onOk() {
loading.value = true
emit('handleSave', conditionsList.value)
setTimeout(() => {
message.success('保存成功')
loading.value = false
}, 1000)
},
onCancel() {
console.log('Cancel')
},
})
}
// 清空
function handleClear() {
Modal.confirm({
title: '确认',
icon: createVNode(ExclamationCircleOutlined),
content: '确定要清空筛选条件吗?',
onOk() {
conditionsList.value = []
emit('handleClear', conditionsList.value)
selectionConditionRef.value.reset()
},
onCancel() {
console.log('Cancel')
},
})
}
// 展开折叠
const isExpanded = ref<boolean>(true)
function handleCollapse() {
isExpanded.value = !isExpanded.value
}
defineExpose({
handleOpen,
handleSearch,
handleSave,
handleClear,
})
</script>
<template>
<div>
<div v-if="isPanel">
<div class="m-be-5">
<span class="w-16 inline-block">满足下列</span>
<a-select v-model:value="searchGeneralType" class="m-inline-2.5" style="width: 120px">
<a-select-option value="0">
所有
</a-select-option>
<a-select-option value="1">
任一
</a-select-option>
</a-select>
条件:
</div>
<div class="expandable-content" :class="{ expanded: isExpanded }">
<div
v-for="(condition, index) in conditionsList" :key="condition.value"
class="flex p-be-5 p-is-18.5 condition-box"
>
<a-input v-model:value="condition.label" disabled class="w-50" />
<template v-if="condition.type === 'DatePicker'">
<a-range-picker v-model:value="condition.keysDate" class="m-inline-2.5" />
</template>
<template v-else-if="condition.type === 'NumberRange'">
<a-input-number id="inputNumber" v-model:value="condition.keys[0].isSys" class="m-inline-2.5" />
</template>
<template v-else-if="condition.type === 'SelectOption'">
<div v-for="(keyItem, i) in condition.keys" :key="keyItem.key + i">
<a-select v-model:value="keyItem.isSys" class="m-inline-2.5" style="width: 180px">
<a-select-option v-for="item in getDefaultOptions(condition)" :key="item.value" :value="item.value">
{{ item.label }}
</a-select-option>
</a-select>
</div>
</template>
<template v-else>
<a-select v-model:value="condition.viewfilter" class="m-inline-2.5" style="width: 180px">
<a-select-option v-for="item in getDefaultOptions(condition)" :key="item.value" :value="item.value">
{{ item.label }}
</a-select-option>
</a-select>
<!-- TODO 这里是一个输入框,点击出弹窗选数据 -->
<a-select v-model:value="condition.keysMul" class="m-inline-2.5" style="width: 180px" mode="multiple">
<a-select-option v-for="item in getKeysOptions()" :key="item.value" :value="item.value">
{{ item.label }}
</a-select-option>
</a-select>
</template>
<MinusCircleOutlined style="color: #888" @click="handleDelete(index)" />
</div>
</div>
<a-button @click="selectionConditionRef.handleOpen">
<template #icon>
<PlusOutlined />
</template>
添加条件
</a-button>
<div class="flex justify-between m-t-5">
<div>
<a-button class="m-ie-6" type="primary" @click="handleSearch">
筛选
</a-button>
<a-button :loading="loading" @click="handleSave">
保存筛选条件
</a-button>
</div>
<a-button class="float-right" type="link" @click="handleClear">
清空
</a-button>
</div>
<a-divider>
<a-button type="link" @click="handleCollapse">
{{ isExpanded ? '收起' : '展开' }}
<component :is="isExpanded ? UpOutlined : DownOutlined" />
</a-button>
</a-divider>
</div>
<SelectCondition ref="selectionConditionRef" @handle-ok="handleOk" />
</div>
</template>
<style lang="less" scoped>
.condition-box {
position: relative;
&::before {
content: " ";
position: absolute;
left: 0;
top: -4px;
height: 100%;
width: 55px;
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADcAAAAoAQMAAABglfBLAAAABlBMVEXM09t2YyHaAAAAAXRSTlMAQObYZgAAABNJREFUGNNjYGBgcGCAgFGadBoAQZoKAavfri4AAAAASUVORK5CYII=) repeat;
}
&:last-child::before {
top: -4px;
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADcAAAAoCAYAAABaW2IIAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAACfSURBVHgB7dOxDcJQDIThs0lBQcEIRBQoBRIbEiYBNoEJXoFQaCBikBfDCFEUOXJ0X29Zf3GAg+frY5iAYsYYFxXjomJcVIyLinFRMS4qxkXFuKgYN4aU0hrOXOIEuBXL1QHOXOKy5ZPK4pyadgNHAieP5l2ryPH/8tJZ9+1zU6i21a68YiC3ze2rba0mpVm+970xg/tOiYiIiIiIaHo/tyUf6I0zVSMAAAAASUVORK5CYII=) top no-repeat;
}
}
.expandable-content {
max-height: 0;
overflow: hidden;
transition: all 0.5s cubic-bezier(0.4, 0, 0.2, 1);
opacity: 0;
transform: translateY(-20px);
margin-top: 0;
visibility: hidden;
&.expanded {
max-height: 1000px;
opacity: 1;
transform: translateY(0);
margin-top: 16px;
visibility: visible;
}
}
</style>
🌼4. 选择条件-选择条件弹窗组件added-condition/select-condition.vue
🌼
<script setup lang="ts">
import { reactive, ref } from 'vue'
import { hexToRgba } from '~@/utils/hexToRgba'
import { getConditionList } from '@/api/getting-clues/search-clues.ts'
import type { Condition } from '@/api/interface/getting-clues'
defineOptions({
name: 'SelectCondition',
})
const emit = defineEmits(['handleOk'])
const { token } = useAntdToken()
const message = useMessage()
const open = ref<boolean>(false)
function handleOpen() {
open.value = true
}
function handleCancel() {
open.value = false
}
function handleOk() {
if (state.selectedItemLabels.length === 0) {
message.error('请选择要添加的条件')
}
else {
emit('handleOk', state.selectedItemLabels)
open.value = false
}
}
// search
const searchValue = ref<string>('')
function onSearch(searchValue: string) {
console.log('use value', searchValue)
// console.log('or use this.value', searchValue.value);
}
// 条件列表
const conditionList = ref<Condition.ConditionItem[]>([])
getConditionList().then((res) => {
if (res.success) {
conditionList.value = res.data
}
})
// 主条件分类鼠标移入和选中效果
/**
* @constant hoveredMainIndices 鼠标移入的索引
* @constant selectedMainIndices 选中的索引
* @constant currentMainIndex 当前选中主条件index,用于获取子条件列表
* @constant hoveredItemIndices 选中的子条件索引
* @constant selectedItemIndices 当前选中的子条件
* @constant selectedItemLabels 选择的条件
*/
interface State {
hoveredMainIndices: Set<number>
selectedMainIndices: Set<number>
currentMainIndex: number
hoveredItemIndices: Set<number>
selectedItemIndices: Set<number>
selectedItemLabels: Condition.ConditionItem[]
}
const state = reactive<State>({
hoveredMainIndices: new Set(),
selectedMainIndices: new Set([0]),
currentMainIndex: 0,
hoveredItemIndices: new Set(),
selectedItemIndices: new Set(),
selectedItemLabels: [],
})
function handleMainClick(index: number) {
if (state.currentMainIndex === index) {
return
}
state.selectedMainIndices.clear()
state.selectedMainIndices.add(index)
state.currentMainIndex = index
}
function isMainSelected(index: number) {
return state.selectedMainIndices.has(index)
}
function handleMainHovered(index: number, isHovered: boolean) {
if (isHovered) {
state.hoveredMainIndices.add(index)
}
else {
state.hoveredMainIndices.delete(index)
}
}
function isMainHovered(index: number) {
return state.hoveredMainIndices.has(index)
}
function activeMainStyle(index: number) {
if (isMainSelected(index)) {
return {
color: token.value?.colorPrimary,
backgroundColor: hexToRgba(token.value?.colorPrimary, 0.05),
borderRight: `2px solid ${token.value?.colorPrimary}`,
}
}
else {
if (isMainHovered(index)) {
return {
backgroundColor: 'rgba(0, 0, 0, 0.06)',
}
}
}
}
// 子条件列表
const conditionChildrenList = computed(() => {
const c = conditionList.value.find((_, index) => state.currentMainIndex === index)
return c?.children || []
})
function handleItemClick(item: Condition.ConditionItem) {
const a = state.selectedItemLabels.find(i => i.value === item.value)
if (!a) {
if (state.selectedItemLabels.length === 10) {
return message.error('一次最多选择10项')
}
state.selectedItemLabels.push(item)
}
else {
state.selectedItemLabels = state.selectedItemLabels.filter(i => i.value !== item.value)
}
}
function isItemSelected(item: Condition.ConditionItem) {
return (state.selectedItemLabels.findIndex(i => i.value === item.value) !== -1)
}
function handleItemHovered(index: number, isHovered: boolean) {
if (isHovered) {
state.hoveredItemIndices.add(index)
}
else {
state.hoveredItemIndices.delete(index)
}
}
function isItemHovered(index: number) {
return state.hoveredItemIndices.has(index)
}
function activeItemStyle(index: number, item: Condition.ConditionItem) {
if (isItemSelected(item)) {
return {
color: '#ffffff',
backgroundColor: token.value?.colorPrimary,
}
}
else {
if (isItemHovered(index)) {
return {
color: token.value?.colorPrimary,
backgroundColor: hexToRgba(token.value?.colorPrimary, 0.05),
}
}
}
}
function reset() {
const initState: State = {
hoveredMainIndices: new Set(),
selectedMainIndices: new Set([0]),
currentMainIndex: 0,
hoveredItemIndices: new Set(),
selectedItemIndices: new Set(),
selectedItemLabels: [],
}
Object.assign(state, initState)
}
defineExpose({
handleOpen,
handleCancel,
reset,
})
</script>
<template>
<a-modal v-model:open="open" width="50vw" title="添加条件" @ok="handleOk">
<div>
<!-- search -->
<div>
<a-input-search
v-model:value="searchValue" class="w-full" placeholder="搜索条件名称" enter-button="搜索" size="large"
@search="onSearch"
/>
</div>
<!-- main wrapper -->
<div class="mt-5 flex">
<div class="w-1/5 h-[50vh] overflow-y-scroll scrollbar">
<div
v-for="(item, index) in conditionList" :key="index" class="p-2 m-r-1 lh-6 cursor-pointer"
:style="activeMainStyle(index)" @click="handleMainClick(index)" @mouseover="handleMainHovered(index, true)"
@mouseleave="handleMainHovered(index, false)"
>
{{ item.label }}
</div>
</div>
<div class="flex-1 p-l-8 h-[50vh] overflow-y-auto scrollbar">
<span
v-for="(item, index) in conditionChildrenList" :key="index"
class="inline-block m-2 p-inline-6 p-block-2 b-1 b-solid b-color-#e5e5e5 b-rd-2 cursor-pointer"
:style="activeItemStyle(index, item)" @click="handleItemClick(item)"
@mouseover="handleItemHovered(index, true)" @mouseleave="handleItemHovered(index, false)"
>
{{ item.label }}
</span>
</div>
</div>
</div>
<template #footer>
<div class="flex-between b-t-1 b-t-solid b-color-#e5e5e5 p-2">
<div>
已选择<span class="p-inline-1" :style="{ color: token?.colorPrimary }">{{ state.selectedItemLabels.length
}}</span>个条件(一次最多10个)
</div>
<div>
<a-button key="back" @click="handleCancel">
取消
</a-button>
<a-button key="submit" type="primary" @click="handleOk">
确定
</a-button>
</div>
</div>
</template>
</a-modal>
</template>
<style lang="less" scoped></style>
5. 🌿定义常量数据文件constant/index.ts
🌿
export const NavData = [
{
i: 0,
title: '添加条件',
url: 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBzdGFuZGFsb25lPSJubyI/PjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+PHN2ZyB0PSIxNzMzOTk3MzM3MjgwIiBjbGFzcz0iaWNvbiIgdmlld0JveD0iMCAwIDEwMjQgMTAyNCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHAtaWQ9IjQ2NTM1IiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgd2lkdGg9IjIwMCIgaGVpZ2h0PSIyMDAiPjxwYXRoIGQ9Ik01MTIgOTcuNTIzODFjMjI4LjkxMjc2MiAwIDQxNC40NzYxOSAxODUuNTYzNDI5IDQxNC40NzYxOSA0MTQuNDc2MTlzLTE4NS41NjM0MjkgNDE0LjQ3NjE5LTQxNC40NzYxOSA0MTQuNDc2MTlTOTcuNTIzODEgNzQwLjkxMjc2MiA5Ny41MjM4MSA1MTIgMjgzLjA4NzIzOCA5Ny41MjM4MSA1MTIgOTcuNTIzODF6IG0zNi41NzE0MjkgMTk1LjA0NzYxOWgtNzMuMTQyODU4djE4Mi44MzI3NjFMMjkyLjU3MTQyOSA0NzUuNDI4NTcxdjczLjE0Mjg1OGwxODIuODU3MTQyLTAuMDI0MzgxVjczMS40Mjg1NzFoNzMuMTQyODU4di0xODIuODU3MTQySDczMS40Mjg1NzF2LTczLjE0Mjg1OGgtMTgyLjg1NzE0MlYyOTIuNTcxNDI5eiIgcC1pZD0iNDY1MzYiIGZpbGw9IiNmZmZmZmYiPjwvcGF0aD48L3N2Zz4=',
},
{
i: 1,
title: '热门推荐',
url: 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBzdGFuZGFsb25lPSJubyI/PjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+PHN2ZyB0PSIxNzMzOTk2Mjc3MzUyIiBjbGFzcz0iaWNvbiIgdmlld0JveD0iMCAwIDEwMjQgMTAyNCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHAtaWQ9IjQzNjIwIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgd2lkdGg9IjIwMCIgaGVpZ2h0PSIyMDAiPjxwYXRoIGQ9Ik03NzAuMDE2IDMzMi43NjhsLTc3LjgyNCA3Ni44czAtMzA3LjItMjU5LjYxNi00MDkuNTY4YzAgMC0yNS45MiAyODEuNi0xNTUuNzQ0IDM4My45MzYtMTI5Ljc5MiAxMDIuNDY0LTM4OS40NCA0MDkuNTY4IDEyOS42OTYgNjM5Ljk2OCAwIDAtMjU5LjYxNi0yODEuNiA3Ny44MjQtNDg2LjMwNCAwIDAtMjUuOTIgMTAyLjMzNiAxMDMuODcyIDIwNC44IDEyOS44MjQgMTAyLjM2OCAwIDI4MS42IDAgMjgxLjZzNjIzLjAwOC0xNTMuNjMyIDE4MS43OTItNjkxLjIzMnoiIGZpbGw9IiNmZmZmZmYiIHAtaWQ9IjQzNjIxIj48L3BhdGg+PC9zdmc+',
},
{
i: 2,
title: '已保存的筛选条件',
url: 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBzdGFuZGFsb25lPSJubyI/PjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+PHN2ZyB0PSIxNzM0MDU5ODUyOTg5IiBjbGFzcz0iaWNvbiIgdmlld0JveD0iMCAwIDEwMjQgMTAyNCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHAtaWQ9IjU0MTQiIGlkPSJteF9uXzE3MzQwNTk4NTI5OTAiIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB3aWR0aD0iMjAwIiBoZWlnaHQ9IjIwMCI+PHBhdGggZD0iTTQyNi42NjY2NjcgNzI1LjMzMzMzM2gxNzAuNjY2NjY2djE3MC42NjY2NjdoLTE3MC42NjY2NjZ6IiBwLWlkPSI1NDE1IiBmaWxsPSIjZmZmZmZmIj48L3BhdGg+PHBhdGggZD0iTTg1OC40NTMzMzMgMzcxLjYyNjY2N2wtMjA2LjA4LTIwNi4wOEExMjggMTI4IDAgMCAwIDU2MS45MiAxMjhINDI2LjY2NjY2N3YyNTZoMjEzLjMzMzMzM2E0Mi42NjY2NjcgNDIuNjY2NjY3IDAgMCAxIDAgODUuMzMzMzMzSDM4NGE0Mi42NjY2NjcgNDIuNjY2NjY3IDAgMCAxLTQyLjY2NjY2Ny00Mi42NjY2NjZWMTI4SDI1NmExMjggMTI4IDAgMCAwLTEyOCAxMjh2NTEyYTEyOCAxMjggMCAwIDAgMTI4IDEyOGg4NS4zMzMzMzN2LTE3MC42NjY2NjdhODUuMzMzMzMzIDg1LjMzMzMzMyAwIDAgMSA4NS4zMzMzMzQtODUuMzMzMzMzaDE3MC42NjY2NjZhODUuMzMzMzMzIDg1LjMzMzMzMyAwIDAgMSA4NS4zMzMzMzQgODUuMzMzMzMzdjE3MC42NjY2NjdoODUuMzMzMzMzYTEyOCAxMjggMCAwIDAgMTI4LTEyOHYtMzA1LjkyYTEyOCAxMjggMCAwIDAtMzcuNTQ2NjY3LTkwLjQ1MzMzM3oiIHAtaWQ9IjU0MTYiIGZpbGw9IiNmZmZmZmYiPjwvcGF0aD48L3N2Zz4=',
},
]
export const JudgementCondition: { [key: string]: any } = {
type: {
operateState: [
{
value: 'text',
label: '等于任意一个',
},
{
value: 'select-eq',
label: '等于',
},
{
value: 'select-in',
label: '包含',
},
{
value: 'select-in-one',
label: '包含任意一个',
},
{
value: 'select-not',
label: '不包含',
},
],
},
renderData: {
existData: [
{
value: 0,
label: '无',
},
{
value: 1,
label: '有',
},
],
ifData: [
{
value: 0,
label: '否',
},
{
value: 1,
label: '是',
},
],
},
tag: {
inTag: [
{
value: 0,
label: '机械',
},
{
value: 1,
label: '器械',
},
{
value: 2,
label: '设备',
},
{
value: 1,
label: '重工',
},
],
},
// 所有的类别匹配不上走默认
default: {
default: [
{
value: 0,
label: '存续',
},
{
value: 1,
label: '在业',
},
],
},
}
🌴6. 类别json数据api/index.ts
🌴
// api 模拟接口
export function getConditionList(): Promise<ResData<Condition.ConditionItem[]>> {
return new Promise((resolve) => {
resolve(conditionList as unknown as ResData<Condition.ConditionItem[]>)
})
}
数据json
:
{
"errcode": 200,
"errmsg": "操作成功",
"data": [
{
"value": "extraHot",
"label": "常用",
"children": [
{
"value": "businessLocation",
"label": "企业所在地",
"children": null,
"type": "MultiSelect",
"keys": [
{
"key": "type",
"value": "area",
"isSys": 0
},
{
"key": "tag",
"value": "inTag",
"isSys": 0
}
],
"checked": true,
"alisKey": false,
"viewfilter": "text",
"tooltip": "",
"certificateFlag": true,
"normal": true,
"intellectualPropertyFlag": true,
"groupName": ""
},
{
"value": "mobile",
"label": "有无手机",
"children": null,
"type": "SelectOption",
"keys": [
{
"key": "renderData",
"value": "existData",
"isSys": 1
}
],
"checked": true,
"alisKey": false,
"viewfilter": "bool",
"tooltip": "",
"certificateFlag": true,
"normal": true,
"intellectualPropertyFlag": true,
"groupName": ""
},
{
"value": "operateState",
"label": "经营状态",
"children": null,
"type": "MultiSelect",
"keys": [
{
"key": "type",
"value": "operateState",
"isSys": 0
}
],
"checked": true,
"alisKey": false,
"viewfilter": "select-eq",
"tooltip": "",
"certificateFlag": true,
"normal": true,
"intellectualPropertyFlag": true,
"groupName": ""
},
{
"value": "companyName",
"label": "企业名称",
"children": null,
"type": "TextTags",
"keys": [
{
"key": "type",
"value": "companyName",
"isSys": 0
},
{
"key": "tag",
"value": "inTag",
"isSys": 0
}
],
"checked": true,
"alisKey": true,
"viewfilter": "text",
"tooltip": "",
"certificateFlag": true,
"normal": true,
"intellectualPropertyFlag": true,
"groupName": ""
}
],
"type": "",
"keys": [],
"checked": true,
"alisKey": false,
"viewfilter": "",
"tooltip": "",
"certificateFlag": true,
"normal": true,
"intellectualPropertyFlag": true,
"groupName": ""
},
{
"value": "industryInfo",
"label": "企业基本信息",
"children": [
{
"value": "foundTime",
"label": "成立日期",
"children": null,
"type": "DatePicker",
"keys": [],
"checked": true,
"alisKey": false,
"viewfilter": "timeRange",
"tooltip": "",
"certificateFlag": true,
"normal": true,
"intellectualPropertyFlag": true,
"groupName": "基本信息"
}
],
"type": "",
"keys": [],
"checked": true,
"alisKey": false,
"viewfilter": "",
"tooltip": "",
"certificateFlag": true,
"normal": true,
"intellectualPropertyFlag": true,
"groupName": ""
}
],
"success": true
}
💦7. 数据接口定义interface/index.ts
💦
import type { Dayjs } from 'dayjs'
export namespace Condition {
export interface ChildKeys {
key: string
value: string
isSys: number
}
export interface ConditionItem {
label: string
value: string
type: string
keys: ChildKeys[]
keysDate?: [Dayjs, Dayjs]
keysMul?: any[]
children: ConditionItem[]
checked: boolean
viewfilter: string
tooltip: string
[key: string]: any
}
}
❗️ 4. 封装实例缺点💦
-
added-condition.vue
文件内动态渲染UI组件代码
-
UI的结构是不可预知的,所以既然叫动态,那么就需要修改以为动态组件。。。