mirror of
https://github.com/fugary/simple-element-plus-template.git
synced 2025-12-09 20:37:48 +00:00
自动完成控件优化
This commit is contained in:
@@ -23,11 +23,11 @@
|
||||
* @property {boolean} disabled 是否禁用
|
||||
* @property {boolean} emptySearchEnabled 没有关键字时是否点击就开始搜索
|
||||
* @property {string} title popover标题
|
||||
* @property {string} autocompleteLabel 自动完成label
|
||||
* @property {string} placeholder placeholder占位符
|
||||
* @property {string} defaultLabel 自动完成默认label
|
||||
* @property {string} idKey id字段名
|
||||
* @property {string} labelKey label字段名
|
||||
* @property {number} debounceTime 防抖时间
|
||||
* @property {CommonPage} page 分页数据
|
||||
* @property {string} autocompleteWidth 宽度
|
||||
* @property {CommonSelectPageOption} selectPageConfig 分页
|
||||
* @property {Number} colSize 显示几列
|
||||
@@ -56,7 +56,11 @@ const props = defineProps({
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
autocompleteLabel: {
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
defaultLabel: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
@@ -76,10 +80,6 @@ const props = defineProps({
|
||||
type: String,
|
||||
default: '500px'
|
||||
},
|
||||
page: {
|
||||
type: Object,
|
||||
default: null
|
||||
},
|
||||
autocompleteConfig: {
|
||||
type: Object,
|
||||
required: true
|
||||
@@ -122,11 +122,11 @@ const props = defineProps({
|
||||
}
|
||||
})
|
||||
|
||||
const emit = defineEmits(['update:modelValue', 'onSelectData', 'update:page', 'update:autocompleteLabel'])
|
||||
const emit = defineEmits(['update:modelValue', 'onSelectData', 'update:defaultLabel'])
|
||||
// 关键字搜索
|
||||
const keywords = ref(props.autocompleteLabel)
|
||||
const keywords = ref(props.defaultLabel)
|
||||
// 上次搜索记录
|
||||
const lastAutocompleteLabel = ref(props.autocompleteLabel)
|
||||
const lastAutocompleteLabel = ref(props.defaultLabel)
|
||||
// 分页条
|
||||
const pageAttrs = { layout: 'total, prev, pager, next', small: true, background: true }
|
||||
const selectPageAttrs = { layout: 'prev, pager, next', small: true, background: true }
|
||||
@@ -137,9 +137,15 @@ const selectPageData = ref({})
|
||||
const selectPageTab = ref(null)
|
||||
const popoverVisible = ref(false)
|
||||
const autocompletePopover = ref()
|
||||
const pageConfig = useVModel(props, 'page', emit)
|
||||
const autoPage = ref({
|
||||
pageSize: 8,
|
||||
pageNumber: 1
|
||||
})
|
||||
const loadingData = ref(false)
|
||||
|
||||
const idProp = computed(() => props.autocompleteConfig?.idKey || props.idKey)
|
||||
const labelProp = computed(() => props.autocompleteConfig?.labelKey || props.labelKey)
|
||||
|
||||
const showSelectPage = computed(() => {
|
||||
return props.selectPageConfig && (!keywords.value || lastAutocompleteLabel.value === keywords.value)
|
||||
})
|
||||
@@ -148,10 +154,10 @@ const loadAutoDataList = (val) => {
|
||||
if (val || props.emptySearchEnabled) {
|
||||
popoverVisible.value = true
|
||||
loadingData.value = true
|
||||
props.autocompleteConfig.searchMethod(val, (result) => {
|
||||
props.autocompleteConfig.searchMethod({ query: val, page: autoPage.value }, (result) => {
|
||||
dataList.value = result.items || []
|
||||
if (props.page) {
|
||||
pageConfig.value = { ...result.page }
|
||||
if (result.page) {
|
||||
autoPage.value = { ...result.page }
|
||||
}
|
||||
loadingData.value = false
|
||||
})
|
||||
@@ -180,8 +186,8 @@ const onInputKeywords = debounce((input) => {
|
||||
popoverVisible.value = true
|
||||
loadSelectData()
|
||||
} else {
|
||||
if (input && pageConfig.value) {
|
||||
pageConfig.value = { ...pageConfig.value, pageNumber: 1 }
|
||||
if (input && autoPage.value) {
|
||||
autoPage.value = { ...autoPage.value, pageNumber: 1 }
|
||||
}
|
||||
loadAutoDataList(val)
|
||||
}
|
||||
@@ -211,7 +217,7 @@ watch(() => popoverVisible.value, (val) => {
|
||||
//* ********************数据选择*********************
|
||||
|
||||
const vModel = useVModel(props, 'modelValue', emit)
|
||||
const vAutocompleteLabel = useVModel(props, 'autocompleteLabel', emit)
|
||||
const vAutocompleteLabel = useVModel(props, 'defaultLabel', emit)
|
||||
|
||||
const onSelectData = (row) => {
|
||||
popoverVisible.value = false
|
||||
@@ -222,8 +228,8 @@ const onSelectData = (row) => {
|
||||
let label = ''
|
||||
let value = null
|
||||
if (row) {
|
||||
label = row[props.labelKey]
|
||||
value = props.useIdModel ? row[props.idKey] : row
|
||||
label = row[labelProp.value]
|
||||
value = props.useIdModel ? row[idProp.value] : row
|
||||
}
|
||||
keywords.value = label
|
||||
vAutocompleteLabel.value = label
|
||||
@@ -317,13 +323,13 @@ const selectPagePaginationChange = (tab, pageNumber) => {
|
||||
popper-class="common-autocomplete"
|
||||
placement="bottom-start"
|
||||
:width="autocompleteWidth"
|
||||
:title="title"
|
||||
:title="title||placeholder"
|
||||
>
|
||||
<template #reference>
|
||||
<el-input
|
||||
v-model="keywords"
|
||||
:clearable="clearable"
|
||||
:placeholder="title"
|
||||
:placeholder="placeholder||title"
|
||||
:disabled="disabled"
|
||||
:readonly="readonly"
|
||||
v-bind="inputAttrs"
|
||||
@@ -369,7 +375,7 @@ const selectPagePaginationChange = (tab, pageNumber) => {
|
||||
class="common-select-page-btn is-text"
|
||||
@click="onSelectData(colData)"
|
||||
>
|
||||
{{ colData[labelKey] }}
|
||||
{{ colData[labelProp] }}
|
||||
</el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
@@ -392,7 +398,7 @@ const selectPagePaginationChange = (tab, pageNumber) => {
|
||||
<common-table
|
||||
v-else
|
||||
ref="tableRef"
|
||||
v-model:page="pageConfig"
|
||||
v-model:page="autoPage"
|
||||
:loading="loadingData"
|
||||
:loading-text="loadingText"
|
||||
class="autocomplete-table"
|
||||
|
||||
@@ -42,8 +42,8 @@ const props = defineProps({
|
||||
})
|
||||
|
||||
const inputType = computed(() => {
|
||||
if (props.option.common) {
|
||||
return `common-${props.option.type}`
|
||||
if (props.option.type && props.option.type.startsWith('common-')) {
|
||||
return `${props.option.type}` // 自定义控件
|
||||
}
|
||||
return `el-${props.option.type || 'input'}`
|
||||
})
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
<script setup>
|
||||
import { computed, ref } from 'vue'
|
||||
import { ref, watch } from 'vue'
|
||||
import cloneDeep from 'lodash/cloneDeep'
|
||||
import { $i18nBundle } from '@/messages'
|
||||
import { useVModel } from '@vueuse/core'
|
||||
|
||||
/**
|
||||
* @typedef {FormProps} CommonFormProps
|
||||
@@ -64,7 +65,7 @@ const props = defineProps({
|
||||
}
|
||||
})
|
||||
|
||||
const rules = computed(() => {
|
||||
const initRules = () => {
|
||||
const ruleResult = {}
|
||||
props.options.forEach(option => {
|
||||
if (option.prop) {
|
||||
@@ -88,11 +89,26 @@ const rules = computed(() => {
|
||||
}
|
||||
}
|
||||
})
|
||||
console.info('==============rules', ruleResult)
|
||||
return ruleResult
|
||||
})
|
||||
}
|
||||
|
||||
defineEmits(['submitForm'])
|
||||
const rules = ref({})
|
||||
|
||||
const emit = defineEmits(['submitForm', 'update:model'])
|
||||
|
||||
const formModel = useVModel(props, 'model', emit)
|
||||
|
||||
watch(() => props.options, (options) => {
|
||||
console.info('=================options', options)
|
||||
options.forEach(option => {
|
||||
if (formModel.value && option.value) {
|
||||
formModel.value[option.prop] = option.value
|
||||
}
|
||||
})
|
||||
rules.value = initRules()
|
||||
}, { deep: true })
|
||||
|
||||
//= ============form暴露============//
|
||||
|
||||
const form = ref()
|
||||
|
||||
@@ -105,7 +121,7 @@ defineExpose({
|
||||
<template>
|
||||
<el-form
|
||||
ref="form"
|
||||
:model="model"
|
||||
:model="formModel"
|
||||
:rules="rules"
|
||||
:label-width="labelWidth"
|
||||
v-bind="$attrs"
|
||||
@@ -113,7 +129,7 @@ defineExpose({
|
||||
<common-form-control
|
||||
v-for="(option,index) in options"
|
||||
:key="index"
|
||||
:model="model"
|
||||
:model="formModel"
|
||||
:option="option"
|
||||
/>
|
||||
<el-form-item v-if="showButtons">
|
||||
|
||||
@@ -63,16 +63,16 @@ const selectIcon = icon => {
|
||||
<template>
|
||||
<label class="el-radio">
|
||||
<common-icon
|
||||
v-if="modelValue"
|
||||
:icon="modelValue"
|
||||
v-if="vModel"
|
||||
:icon="vModel"
|
||||
class="el-radio__input"
|
||||
/>
|
||||
<span
|
||||
v-if="modelValue"
|
||||
v-if="vModel"
|
||||
class="el-radio__label"
|
||||
>{{ modelValue }}</span>
|
||||
>{{ vModel }}</span>
|
||||
<el-button
|
||||
class="icon-select-button"
|
||||
:class="{'icon-select-button': !!vModel}"
|
||||
type="primary"
|
||||
:disabled="disabled||readonly"
|
||||
size="small"
|
||||
|
||||
Reference in New Issue
Block a user