Skip to content

Commit

Permalink
feat: select tree add path
Browse files Browse the repository at this point in the history
  • Loading branch information
aringlai committed Jul 20, 2023
1 parent 5790d52 commit e6aef64
Show file tree
Hide file tree
Showing 4 changed files with 4,654 additions and 4,403 deletions.
64 changes: 51 additions & 13 deletions components/select-tree/selectTree.vue
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,14 @@ export const selectTreeProps = {
string | number | Array<string | number>
>,
},
showPath: {
type: Boolean,
default: false
},
emitPath: {
type: Boolean,
default: false
},
} as const;
export type SelectTreeProps = ExtractPublicPropTypes<typeof selectTreeProps>;
Expand Down Expand Up @@ -222,6 +230,28 @@ export default defineComponent({
triggerRef(nodeList);
};
const getCurrentValueByKeys = (keys: TreeNodeKey[] = []) => {
if (props.multiple) {
const nodeValues: TreeNodeKey[] = [];
nodeList.value.forEach((value, key) => nodeValues.push(key))
// 兼容异步加载,未匹配到节点的情况
const notMatchedKeys = keys.filter(
(key) => !(nodeValues as TreeNodeKey[]).includes(key),
);
// 保持层级顺序不变
return [].concat(
notMatchedKeys,
nodeValues
.filter((key) => keys.includes(key))
.map((key) =>
props.emitPath ? [...(nodeList.value.get(key)?.indexPath) || []] : key,
),
);
} else {
return props.emitPath ? [...(nodeList.value.get(keys[0])?.indexPath || [])] : keys[0];
}
}
const treeSelectable = computed(() => !props.multiple);
const treeCheckable = computed(() => props.multiple);
const selectedKeys = computed(() => {
Expand All @@ -231,17 +261,17 @@ export default defineComponent({
});
const checkedKeys = computed(() => {
if (props.multiple) {
return currentValue.value;
return currentValue.value.map((item: [] | string) => Array.isArray(item) ? item[item.length - 1]: item);
}
return [];
});
watch(
() => props.checkStrictly,
[() => props.checkStrictly, () => props.emitPath],
() => {
if (props.multiple && props.cascade) {
updateCurrentValue([]);
}
const value: null | [] = props.multiple && props.cascade || props.emitPath ? [] : null
updateCurrentValue(value);
handleChange();
},
);
Expand All @@ -262,23 +292,19 @@ export default defineComponent({
if (innerDisabled.value) return;
filterText.value = '';
if (!props.multiple) {
updateCurrentValue(data.selectedKeys[0]);
isOpened.value = false;
} else {
updateCurrentValue(data.selectedKeys);
}
updateCurrentValue(getCurrentValueByKeys(data.selectedKeys));
handleChange();
};
const handleCheck = (data: CheckParams) => {
if (innerDisabled.value) return;
filterText.value = '';
if (!props.multiple) {
updateCurrentValue(data.checkedKeys[0]);
isOpened.value = false;
} else {
updateCurrentValue(data.checkedKeys);
}
updateCurrentValue(getCurrentValueByKeys(data.checkedKeys));
handleChange();
};
Expand All @@ -296,13 +322,25 @@ export default defineComponent({
};
const selectedOptions = computed(() => {
const values = props.multiple
let values = props.multiple
? currentValue.value
: [currentValue.value];
if (props.emitPath) { // 获取选中节点
values = values.map((item: TreeNodeKey[]) => item[item.length - 1]);
}
const nodeListValue = nodeList.value;
return values
.map((val: TreeNodeKey) => {
return nodeListValue.get(val);
const node = nodeListValue.get(val);
if (!node) return;
if (props.showPath) {
return {
...node,
label: node.indexPath?.map(item => nodeListValue.get(item).label).join('/')
}
} else {
return node;
}
})
.filter(Boolean);
});
Expand Down
4 changes: 4 additions & 0 deletions docs/.vitepress/components/selectTree/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ app.use(FSelectTree);

--NODATA

### 获取选中路径

--WITHPATH

--CODE

## SelectTree Props
Expand Down
79 changes: 79 additions & 0 deletions docs/.vitepress/components/selectTree/withPath.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
<template>
<FForm :labelWidth="160">
<FFormItem label="emitPath:">
<FRadioGroup v-model="emitPath">
<FRadio :value="false">false(默认)</FRadio>
<FRadio :value="true">true</FRadio>
</FRadioGroup>
</FFormItem>
<FFormItem label="showPath:">
<FRadioGroup v-model="showPath">
<FRadio :value="false">false(默认)</FRadio>
<FRadio :value="true">true</FRadio>
</FRadioGroup>
</FFormItem>
<FFormItem label="单选:">
<FSelectTree v-model="singleValue" :emitPath="emitPath" :showPath="showPath" :data="data"></FSelectTree>
</FFormItem>
<FFormItem label="modelValue:">
{{ singleValue }}
</FFormItem>
<FFormItem label="多选:">
<FSelectTree v-model="multipleValue" :emitPath="emitPath" :showPath="showPath" :data="data" cascade multiple checkStrictly="child"></FSelectTree>
</FFormItem>
<FFormItem label="modelValue:">
{{ multipleValue }}
</FFormItem>
</FForm>
</template>
<script>
import { ref } from 'vue';
function createData(level = 1, baseKey = '', prefix = null, suffix = null) {
if (!level) return undefined;
return Array.apply(null, { length: 2 }).map((_, index) => {
const key = '' + baseKey + level + index;
return {
label: createLabel(level),
value: key,
children: createData(level - 1, key, prefix, suffix),
prefix: prefix ? () => h(PictureOutlined) : null,
suffix: suffix ? () => h(PlusCircleOutlined) : null,
};
});
}
function createLabel(level) {
if (level === 4) return '道生一';
if (level === 3) return '一生二';
if (level === 2) return '二生三';
if (level === 1) return '三生万物';
}
export default {
setup() {
const data = ref([]);
const emitPath = ref(false);
const showPath = ref(false);
const singleValue = ref('');
const multipleValue = ref([]);
setTimeout(()=>{
data.value = createData(4);
})
return {
data,
singleValue,
multipleValue,
emitPath,
showPath
};
},
};
</script>
<style scoped>
.fes-select-tree {
width: 200px;
}
</style>
Loading

0 comments on commit e6aef64

Please sign in to comment.