|
@@ -1,275 +1,284 @@
|
|
|
<template>
|
|
|
- <el-select
|
|
|
- v-model="state.id"
|
|
|
- :disabled="props.disabled"
|
|
|
- :placeholder="props.placeholder"
|
|
|
- ref="selectRef"
|
|
|
- :clearable="props.clearable"
|
|
|
- @clear="clear"
|
|
|
- :filterable="props.filterable"
|
|
|
- :filter-method="filterMethod"
|
|
|
- >
|
|
|
- <template #default>
|
|
|
- <el-option hidden key="id" :value="state.id" :label="state.name"> </el-option>
|
|
|
- <el-tree
|
|
|
- node-key="id"
|
|
|
- :load="loadNode"
|
|
|
- lazy
|
|
|
- v-if="lazyShow"
|
|
|
- :props="treeProps"
|
|
|
- :filter-node-method="filterNode"
|
|
|
- @node-click="nodeClick"
|
|
|
- :default-expanded-keys="state.externalArr"
|
|
|
- v-loading="loading"
|
|
|
- highlight-current
|
|
|
- check-strictly
|
|
|
- ref="treeRef"
|
|
|
- :show-checkbox="props.showCheckbox"
|
|
|
- @check="checkChange"
|
|
|
- check-on-click-node
|
|
|
- :expand-on-click-node="expandOnClickNode"
|
|
|
- />
|
|
|
- <el-tree
|
|
|
- ref="treeRef"
|
|
|
- :data="state.treeData"
|
|
|
- node-key="id"
|
|
|
- v-else
|
|
|
- default-expand-all
|
|
|
- highlight-current
|
|
|
- :props="treeProps"
|
|
|
- v-loading="loading"
|
|
|
- :filter-node-method="filterNode"
|
|
|
- @node-click="nodeClick"
|
|
|
- check-strictly
|
|
|
- :show-checkbox="props.showCheckbox"
|
|
|
- @check="checkChange"
|
|
|
- check-on-click-node
|
|
|
- />
|
|
|
- </template>
|
|
|
- <template #footer v-if="props.showCheckbox">
|
|
|
- <div class="flex-end">
|
|
|
- <el-button type="primary" @click="chooseHotSpot" size="small">确定</el-button>
|
|
|
- <el-button @click="reset" size="small">重置</el-button>
|
|
|
- </div>
|
|
|
- </template>
|
|
|
- </el-select>
|
|
|
+ <el-select
|
|
|
+ v-model="state.id"
|
|
|
+ :disabled="props.disabled"
|
|
|
+ :placeholder="props.placeholder"
|
|
|
+ ref="selectRef"
|
|
|
+ :clearable="props.clearable"
|
|
|
+ @clear="clear"
|
|
|
+ :filterable="props.filterable"
|
|
|
+ :filter-method="filterMethod"
|
|
|
+ >
|
|
|
+ <template #default>
|
|
|
+ <el-option hidden key="id" :value="state.id" :label="state.name"> </el-option>
|
|
|
+ <el-tree
|
|
|
+ node-key="id"
|
|
|
+ :load="loadNode"
|
|
|
+ lazy
|
|
|
+ v-if="lazyShow"
|
|
|
+ :props="treeProps"
|
|
|
+ :filter-node-method="filterNode"
|
|
|
+ @node-click="nodeClick"
|
|
|
+ :default-expanded-keys="state.externalArr"
|
|
|
+ v-loading="loading"
|
|
|
+ highlight-current
|
|
|
+ check-strictly
|
|
|
+ ref="treeRef"
|
|
|
+ :show-checkbox="props.showCheckbox"
|
|
|
+ @check="checkChange"
|
|
|
+ check-on-click-node
|
|
|
+ :expand-on-click-node="expandOnClickNode"
|
|
|
+ />
|
|
|
+ <el-tree
|
|
|
+ ref="treeRef"
|
|
|
+ :data="state.treeData"
|
|
|
+ node-key="id"
|
|
|
+ v-else
|
|
|
+ default-expand-all
|
|
|
+ highlight-current
|
|
|
+ :props="treeProps"
|
|
|
+ v-loading="loading"
|
|
|
+ :filter-node-method="filterNode"
|
|
|
+ @node-click="nodeClick"
|
|
|
+ check-strictly
|
|
|
+ :show-checkbox="props.showCheckbox"
|
|
|
+ @check="checkChange"
|
|
|
+ check-on-click-node
|
|
|
+ />
|
|
|
+ </template>
|
|
|
+ <template #footer v-if="props.showCheckbox">
|
|
|
+ <div class="flex-end">
|
|
|
+ <el-button type="primary" @click="chooseHotSpot" size="small">确定</el-button>
|
|
|
+ <el-button @click="reset" size="small">重置</el-button>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </el-select>
|
|
|
</template>
|
|
|
<script setup lang="ts">
|
|
|
-import { computed, nextTick, onMounted, reactive, ref, watch } from "vue";
|
|
|
+import { computed, reactive, ref, watch } from 'vue';
|
|
|
import { removeDuplicate } from '@/utils/arrayOperation';
|
|
|
import { treeEventClass, treeEventClassSearch } from '@/api/auxiliary/eventClass';
|
|
|
|
|
|
const props = defineProps({
|
|
|
- modelValue: {
|
|
|
- type: [String, Array],
|
|
|
- default: () => '',
|
|
|
- },
|
|
|
- disabled: {
|
|
|
- type: Boolean,
|
|
|
- default: false,
|
|
|
- },
|
|
|
- placeholder: {
|
|
|
- type: String,
|
|
|
- default: '请选择',
|
|
|
- },
|
|
|
- externalArr: {
|
|
|
- // 外部传入的父级id数组 懒加载时使用
|
|
|
- type: Array,
|
|
|
- default: () => [],
|
|
|
- },
|
|
|
- showCheckbox: {
|
|
|
- // 是否显示多选
|
|
|
- type: Boolean,
|
|
|
- default: false,
|
|
|
- },
|
|
|
- clearable: {
|
|
|
- type: Boolean,
|
|
|
- default: false,
|
|
|
- },
|
|
|
- checkStrictly: {
|
|
|
- // 任意一级
|
|
|
- type: Boolean,
|
|
|
- default: false,
|
|
|
- },
|
|
|
- filterable: {
|
|
|
- type: Boolean,
|
|
|
- default: true,
|
|
|
- },
|
|
|
+ modelValue: {
|
|
|
+ type: [String, Array],
|
|
|
+ default: () => '',
|
|
|
+ },
|
|
|
+ disabled: {
|
|
|
+ type: Boolean,
|
|
|
+ default: false,
|
|
|
+ },
|
|
|
+ placeholder: {
|
|
|
+ type: String,
|
|
|
+ default: '请选择',
|
|
|
+ },
|
|
|
+ externalArr: {
|
|
|
+ // 外部传入的父级id数组 懒加载时使用
|
|
|
+ type: Array,
|
|
|
+ default: () => [],
|
|
|
+ },
|
|
|
+ showCheckbox: {
|
|
|
+ // 是否显示多选
|
|
|
+ type: Boolean,
|
|
|
+ default: false,
|
|
|
+ },
|
|
|
+ clearable: {
|
|
|
+ type: Boolean,
|
|
|
+ default: false,
|
|
|
+ },
|
|
|
+ checkStrictly: {
|
|
|
+ // 任意一级
|
|
|
+ type: Boolean,
|
|
|
+ default: false,
|
|
|
+ },
|
|
|
+ filterable: {
|
|
|
+ type: Boolean,
|
|
|
+ default: true,
|
|
|
+ },
|
|
|
} as any);
|
|
|
// 选择节点展开
|
|
|
const expandOnClickNode = computed(() => {
|
|
|
- return !props.checkStrictly;
|
|
|
+ return !props.checkStrictly;
|
|
|
});
|
|
|
const treeProps = computed(() => {
|
|
|
- return {
|
|
|
- label: 'eventFullName',
|
|
|
- children: 'children',
|
|
|
- isLeaf: 'hasChild',
|
|
|
- };
|
|
|
+ return {
|
|
|
+ label: 'eventFullName',
|
|
|
+ children: 'children',
|
|
|
+ isLeaf: 'hasChild',
|
|
|
+ };
|
|
|
});
|
|
|
|
|
|
const emit = defineEmits(['choose', 'update:modelValue', 'confirm']);
|
|
|
|
|
|
const state = reactive<any>({
|
|
|
- id: '',
|
|
|
- name: '',
|
|
|
- treeData: [],
|
|
|
- externalArr: [],
|
|
|
- external: [],
|
|
|
- checkedKeys: [],
|
|
|
- checkNodes: [],
|
|
|
+ id: '',
|
|
|
+ name: '',
|
|
|
+ treeData: [],
|
|
|
+ externalArr: [],
|
|
|
+ external: [],
|
|
|
+ checkedKeys: [],
|
|
|
+ checkNodes: [],
|
|
|
});
|
|
|
|
|
|
watch(
|
|
|
- () => props.externalArr,
|
|
|
- (val) => {
|
|
|
- if (val) {
|
|
|
- state.externalArr = val;
|
|
|
- }
|
|
|
- },
|
|
|
- { immediate: true }
|
|
|
+ () => props.externalArr,
|
|
|
+ (val) => {
|
|
|
+ if (val) {
|
|
|
+ state.externalArr = val;
|
|
|
+ }
|
|
|
+ },
|
|
|
+ { immediate: true }
|
|
|
);
|
|
|
|
|
|
const lazyShow = ref(true);
|
|
|
const loading = ref(false);
|
|
|
+const childValue = computed({
|
|
|
+ get: () => props.modelValue,
|
|
|
+ set: (val) => emit('update:modelValue', val),
|
|
|
+});
|
|
|
+watch(
|
|
|
+ () => props.modelValue,
|
|
|
+ (val) => {
|
|
|
+ childValue.value = val;
|
|
|
+ },
|
|
|
+ { immediate: true }
|
|
|
+);
|
|
|
// 懒加载
|
|
|
const treeRef = ref<RefType>();
|
|
|
const loadNode = async (node: any, resolve: any) => {
|
|
|
- await nextTick();
|
|
|
- if (node.isLeaf) return resolve([]);
|
|
|
- const { showCheckbox, modelValue } = props;
|
|
|
- try {
|
|
|
- loading.value = true;
|
|
|
- const { result } = await treeEventClass({ id: node.data.id ? node.data.id : null });
|
|
|
- resolve(result);
|
|
|
- state.id = modelValue;
|
|
|
- console.log('子组件',modelValue)
|
|
|
- if (showCheckbox) {
|
|
|
- treeRef.value.setCheckedKeys(modelValue);
|
|
|
- const nodes = treeRef.value.getCheckedNodes();
|
|
|
- state.name = nodes.map((item: any) => item.eventFullName).join(',') ?? '';
|
|
|
- } else {
|
|
|
- treeRef.value.setCurrentKey(modelValue);
|
|
|
- const currentNode = treeRef.value.getNode(modelValue);
|
|
|
- state.name = currentNode.data.eventFullName;
|
|
|
- }
|
|
|
- loading.value = false;
|
|
|
- } catch (e) {
|
|
|
- loading.value = false;
|
|
|
- }
|
|
|
+ if (node.isLeaf) return resolve([]);
|
|
|
+ const { showCheckbox } = props;
|
|
|
+ try {
|
|
|
+ loading.value = true;
|
|
|
+ const { result } = await treeEventClass({ id: node.data.id ? node.data.id : null });
|
|
|
+ resolve(result);
|
|
|
+ state.id = childValue.value;
|
|
|
+ if (showCheckbox) {
|
|
|
+ treeRef.value.setCheckedKeys(childValue.value);
|
|
|
+ const nodes = treeRef.value.getCheckedNodes();
|
|
|
+ state.name = nodes.map((item: any) => item.eventFullName).join(',') ?? '';
|
|
|
+ } else {
|
|
|
+ treeRef.value.setCurrentKey(childValue.value);
|
|
|
+ const currentNode = treeRef.value.getNode(childValue.value);
|
|
|
+ state.name = currentNode.data.eventFullName;
|
|
|
+ }
|
|
|
+ loading.value = false;
|
|
|
+ } catch (e) {
|
|
|
+ loading.value = false;
|
|
|
+ }
|
|
|
};
|
|
|
// 搜索
|
|
|
const filterMethod = (value: string) => {
|
|
|
- if (value) {
|
|
|
- lazyShow.value = false; //当输入框有值时关闭懒加载
|
|
|
- loading.value = true;
|
|
|
- treeEventClassSearch(value)
|
|
|
- .then((res) => {
|
|
|
- //获取后端搜索的数据 //selectMacTree是我自己的后端接口,你们换成自己的
|
|
|
- state.treeData.length = 0;
|
|
|
- state.treeData = res.result ?? [];
|
|
|
- treeRef.value!.filter(value);
|
|
|
- if (props.showCheckbox && state.checkedKeys.length) {
|
|
|
- treeRef.value.setCheckedKeys(state.checkedKeys);
|
|
|
- }
|
|
|
- if (props.modelValue) {
|
|
|
- setTimeout(() => {
|
|
|
- treeRef.value.setCurrentKey(props.modelValue);
|
|
|
- }, 100);
|
|
|
- }
|
|
|
- loading.value = false;
|
|
|
- })
|
|
|
- .catch((e) => {
|
|
|
- loading.value = false;
|
|
|
- });
|
|
|
- } else if (value == '' || value == ' ' || value == null) {
|
|
|
- lazyShow.value = true; // 懒加载树显示
|
|
|
- }
|
|
|
+ if (value) {
|
|
|
+ lazyShow.value = false; //当输入框有值时关闭懒加载
|
|
|
+ loading.value = true;
|
|
|
+ treeEventClassSearch(value)
|
|
|
+ .then((res) => {
|
|
|
+ //获取后端搜索的数据 //selectMacTree是我自己的后端接口,你们换成自己的
|
|
|
+ state.treeData.length = 0;
|
|
|
+ state.treeData = res.result ?? [];
|
|
|
+ treeRef.value!.filter(value);
|
|
|
+ if (props.showCheckbox && state.checkedKeys.length) {
|
|
|
+ treeRef.value.setCheckedKeys(state.checkedKeys);
|
|
|
+ }
|
|
|
+ if (childValue.value) {
|
|
|
+ setTimeout(() => {
|
|
|
+ treeRef.value.setCurrentKey(childValue.value);
|
|
|
+ }, 100);
|
|
|
+ }
|
|
|
+ loading.value = false;
|
|
|
+ })
|
|
|
+ .catch((e) => {
|
|
|
+ loading.value = false;
|
|
|
+ });
|
|
|
+ } else if (value == '' || value == ' ' || value == null) {
|
|
|
+ lazyShow.value = true; // 懒加载树显示
|
|
|
+ }
|
|
|
};
|
|
|
// 查询
|
|
|
const filterNode = (value: string, data: any) => {
|
|
|
- if (!value) return true;
|
|
|
- return data.hotSpotFullName.includes(value);
|
|
|
+ if (!value) return true;
|
|
|
+ return data.hotSpotFullName.includes(value);
|
|
|
};
|
|
|
// 单选
|
|
|
const selectRef = ref<RefType>();
|
|
|
const nodeClick = async (val: any, node: any) => {
|
|
|
- const { showCheckbox, checkStrictly } = props;
|
|
|
- if (showCheckbox) return;
|
|
|
- if (checkStrictly) {
|
|
|
- state.externalArr = [];
|
|
|
- state.external = [];
|
|
|
- state.externalArr = getParentId(node, state.external);
|
|
|
- state.name = val.eventFullName;
|
|
|
- state.id = val.id;
|
|
|
- emit('update:modelValue', val.id);
|
|
|
- emit('choose', { externalArr: state.externalArr, ...val });
|
|
|
- selectRef.value.blur();
|
|
|
- }
|
|
|
- if (!node?.isLeaf) return;
|
|
|
- state.externalArr = [];
|
|
|
- state.external = [];
|
|
|
- state.externalArr = getParentId(node, state.external);
|
|
|
- state.name = val.eventFullName;
|
|
|
- state.id = val.id;
|
|
|
- emit('update:modelValue', val.id);
|
|
|
- emit('choose', { externalArr: state.externalArr, ...val });
|
|
|
- selectRef.value.blur();
|
|
|
+ const { showCheckbox, checkStrictly } = props;
|
|
|
+ if (showCheckbox) return;
|
|
|
+ if (checkStrictly) {
|
|
|
+ state.externalArr = [];
|
|
|
+ state.external = [];
|
|
|
+ state.externalArr = getParentId(node, state.external);
|
|
|
+ state.name = val.eventFullName;
|
|
|
+ state.id = val.id;
|
|
|
+ emit('update:modelValue', val.id);
|
|
|
+ emit('choose', { externalArr: state.externalArr, ...val });
|
|
|
+ selectRef.value.blur();
|
|
|
+ }
|
|
|
+ if (!node?.isLeaf) return;
|
|
|
+ state.externalArr = [];
|
|
|
+ state.external = [];
|
|
|
+ state.externalArr = getParentId(node, state.external);
|
|
|
+ state.name = val.eventFullName;
|
|
|
+ state.id = val.id;
|
|
|
+ emit('update:modelValue', val.id);
|
|
|
+ emit('choose', { externalArr: state.externalArr, ...val });
|
|
|
+ selectRef.value.blur();
|
|
|
};
|
|
|
// 多选
|
|
|
const checkChange = (val: any, e: any) => {
|
|
|
- const { showCheckbox } = props;
|
|
|
- if (!showCheckbox) return;
|
|
|
- const current = treeRef.value.getNode(val);
|
|
|
- state.checkedKeys = e.checkedKeys;
|
|
|
- state.checkedNodes = e.checkedNodes;
|
|
|
- state.id = e.checkedKeys;
|
|
|
- state.name = e.checkedNodes.map((item: any) => item.eventFullName).join(',') ?? '';
|
|
|
- if (props.externalArr.length) {
|
|
|
- state.externalArr = props.externalArr.concat(getParentId(current, state.external));
|
|
|
- } else {
|
|
|
- state.externalArr = getParentId(current, state.external);
|
|
|
- }
|
|
|
- emit('choose', state.checkedKeys, state.checkedNodes, state.externalArr);
|
|
|
- emit('update:modelValue', e.checkedKeys);
|
|
|
+ const { showCheckbox } = props;
|
|
|
+ if (!showCheckbox) return;
|
|
|
+ const current = treeRef.value.getNode(val);
|
|
|
+ state.checkedKeys = e.checkedKeys;
|
|
|
+ state.checkedNodes = e.checkedNodes;
|
|
|
+ state.id = e.checkedKeys;
|
|
|
+ state.name = e.checkedNodes.map((item: any) => item.eventFullName).join(',') ?? '';
|
|
|
+ if (props.externalArr.length) {
|
|
|
+ state.externalArr = props.externalArr.concat(getParentId(current, state.external));
|
|
|
+ } else {
|
|
|
+ state.externalArr = getParentId(current, state.external);
|
|
|
+ }
|
|
|
+ emit('choose', state.checkedKeys, state.checkedNodes, state.externalArr);
|
|
|
+ emit('update:modelValue', e.checkedKeys);
|
|
|
};
|
|
|
// 多选确定
|
|
|
const chooseHotSpot = () => {
|
|
|
- emit('confirm', state.checkedKeys, state.checkedNodes, state.externalArr);
|
|
|
- selectRef.value.blur();
|
|
|
+ emit('confirm', state.checkedKeys, state.checkedNodes, state.externalArr);
|
|
|
+ selectRef.value.blur();
|
|
|
};
|
|
|
// 重置
|
|
|
const reset = () => {
|
|
|
- state.checkedKeys = [];
|
|
|
- treeRef.value.setCheckedKeys([]);
|
|
|
- state.name = '';
|
|
|
- emit('update:modelValue', []);
|
|
|
+ state.checkedKeys = [];
|
|
|
+ treeRef.value.setCheckedKeys([]);
|
|
|
+ state.name = '';
|
|
|
+ emit('update:modelValue', []);
|
|
|
};
|
|
|
// 递归查找父级Id
|
|
|
const getParentId = (val: any, arr: string[]) => {
|
|
|
- if (val.data.parentId) {
|
|
|
- arr.push(val.data.parentId);
|
|
|
- getParentId(val.parent, arr);
|
|
|
- }
|
|
|
- return removeDuplicate(arr);
|
|
|
+ if (val.data.parentId) {
|
|
|
+ arr.push(val.data.parentId);
|
|
|
+ getParentId(val.parent, arr);
|
|
|
+ }
|
|
|
+ return removeDuplicate(arr);
|
|
|
};
|
|
|
// 清空
|
|
|
const clear = () => {
|
|
|
- if (props.showCheckbox) {
|
|
|
- state.checkedKeys = [];
|
|
|
- treeRef.value.setCheckedKeys([]);
|
|
|
- state.name = '';
|
|
|
- state.id = [];
|
|
|
- emit('update:modelValue', []);
|
|
|
- } else {
|
|
|
- state.id = '';
|
|
|
- state.name = '';
|
|
|
- treeRef.value.setCurrentKey(null);
|
|
|
- emit('update:modelValue', '');
|
|
|
- }
|
|
|
+ if (props.showCheckbox) {
|
|
|
+ state.checkedKeys = [];
|
|
|
+ treeRef.value.setCheckedKeys([]);
|
|
|
+ state.name = '';
|
|
|
+ state.id = [];
|
|
|
+ emit('update:modelValue', []);
|
|
|
+ } else {
|
|
|
+ state.id = '';
|
|
|
+ state.name = '';
|
|
|
+ treeRef.value.setCurrentKey(null);
|
|
|
+ emit('update:modelValue', '');
|
|
|
+ }
|
|
|
};
|
|
|
defineExpose({
|
|
|
- reset,
|
|
|
- clear,
|
|
|
+ reset,
|
|
|
+ clear,
|
|
|
});
|
|
|
</script>
|