123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153 |
- <template>
- <el-select :model-value="modelValue"
- @update:modelValue="emitSelect"
- class="basic-select-tree"
- ref="selectTreeRef"
- :clearable="clearable"
- :placeholder="placeholder"
- :disabled="disabled"
- :style="{width}"
- @clear="clearValue"
- popper-class="basic-select-tree-popper">
- <el-option :label="selectOption.label" :value="selectOption.value">
- <el-tree class="select-tree-option"
- :key="treeProps.value"
- ref="selectTree"
- :data="options"
- :props="treeProps"
- :node-key="treeProps.value"
- :default-expanded-keys="defaultExpandedKeys"
- :current-node-key="modelValue"
- :expand-on-click-node="false"
- @node-click="handleNodeClick">
- </el-tree>
- </el-option>
- </el-select>
- </template>
- <script>
- import { ElSelect, ElOption, ElTree } from 'element-plus'
- import { computed, ref, watchEffect } from 'vue'
- import { useFormInput, useOptions } from '@cip/components/hooks/form-input'
- import { formInputProps } from '../../form-input-props'
- export default {
- components: { ElSelect, ElOption, ElTree },
- props: formInputProps,
- emits: ['update:modelValue', 'update:otherValue'],
- setup (props, context) {
- const { width, ...formInput } = useFormInput(props, context)
- const { options } = useOptions(props, false, formInput.emitInput)
- const defaultExpandedKeys = ref([])
- const selectOption = ref({ label: '', value: '' })
- const selectTreeRef = ref()
- const emitSelect = (val) => {
- context.emit('update:modelValue', val)
- }
- const defaultProps = {
- value: 'value',
- label: 'label',
- children: 'children'
- }
- // tree组件配置
- const treeProps = computed(() => {
- return Object.assign({}, defaultProps, props.config?.treeProps, props.config?.optionProps)
- })
- const selectTree = ref()
- const formatOption = (data) => {
- const option = {}
- const keys = treeProps.value
- option.label = data[keys.label]
- option.value = data[keys.value]
- option.children = data[keys.children]
- return option
- }
- const findActiveOption = (treeData = []) => {
- const modelValue = props.modelValue
- for (let i = 0; i < treeData.length; i++) {
- const option = formatOption(treeData[i])
- if (option.value === modelValue) {
- selectOption.value = option
- return true
- }
- if (option.children?.length > 0) {
- const result = findActiveOption(option.children, modelValue)
- if (result) {
- defaultExpandedKeys.value.push(option.value)
- return result
- }
- }
- }
- }
- watchEffect(() => {
- const treeData = options.value
- defaultExpandedKeys.value = []
- findActiveOption(treeData)
- })
- // 切换选项
- const handleNodeClick = (data, node, treeInstance) => {
- const { isLeaf } = node
- if (!props.config.leafOnly || (props.config.leafOnly && isLeaf)) {
- selectOption.value.label = data[treeProps.value.label]
- selectOption.value.value = data[treeProps.value.value]
- context.emit('update:modelValue', selectOption.value.value)
- context.emit('update:otherValue', selectOption.value.label)
- defaultExpandedKeys.value = []
- // 选中时收回下拉框
- selectTreeRef.value.blur()
- } else {
- selectTree.value.setCurrentKey(props.modelValue)
- }
- }
- const clearValue = () => {
- formInput.emitModelValue(undefined)
- formInput.emitOtherValue(undefined)
- }
- return {
- ...formInput,
- selectTreeRef,
- emitSelect,
- options,
- defaultExpandedKeys,
- width,
- selectTree,
- treeProps,
- handleNodeClick,
- selectOption,
- clearValue
- }
- }
- }
- </script>
- <style lang="less" scope>
- .basic-select-tree{
- width: 100%;
- }
- .basic-select-tree-popper{
- .el-scrollbar .el-scrollbar__view .el-select-dropdown__item{
- height: auto;
- max-height: 274px;
- padding: 0;
- overflow: hidden;
- overflow-y: auto;
- }
- .el-select-dropdown__item.selected{
- font-weight: normal;
- }
- .el-tree-node__label{
- font-weight: normal;
- }
- }
- .select-tree-option {
- .el-tree-node__content{
- height: 32px;
- padding: 0 20px;
- }
- .is-current>.el-tree-node__content .el-tree-node__label{
- color: #409EFF;
- }
- }
- </style>
|