2024-04-23 13:12:02 +08:00

152 lines
3.5 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { ref, reactive, computed, watch, onMounted, inject } from 'vue'
import { isEqual, isPlainObject, debounce } from 'lodash'
import { getDataByPath } from '/admin/components/catchForm/support'
import { $selectData, $global } from '/admin/components/catchForm/config/symbol'
const useSelect = (props, emits) => {
const selectData = inject($selectData)
const { request } = inject($global)
const selectVal = computed({
get() {
return props.modelValue
},
set(val) {
emits('update:modelValue', val)
}
})
const currentOptions = ref([])
const loading = ref(false)
const isMax = ref(false)
const stateParams = reactive({
pageNum: 1,
pageSize: 10
// filters: {},
})
const fetchData = debounce(async () => {
if (isMax.value || !props.api) return
const { url, method, data, dataPath } = props.api
loading.value = true
let res = null
if (method === 'get') {
res = await request.get(url, data)
} else {
res = await request.post(url, data)
}
const resData = getDataByPath(res, dataPath)
if (resData.length !== stateParams.pageSize) {
isMax.value = true
}
const resDataParse = resData.map(item => {
if (isPlainObject(item)) {
return item
}
return { label: item, value: item }
})
currentOptions.value = [...currentOptions.value, ...resDataParse]
stateParams.pageNum++
loading.value = false
}, 300)
onMounted(() => {
const { mode, options } = props
if (mode === 'static') {
currentOptions.value = options
isMax.value = true
}
if (mode === 'remote') {
fetchData()
}
})
watch(
() => props.api,
(newVal, oldVal) => {
// bug这里发生只api内存地址变化实际api无变化也会触发监听。暂时使用深层对比解决
if (!isEqual(newVal, oldVal)) {
currentOptions.value = []
isMax.value = false
stateParams.pageNum = 1
fetchData()
}
}
)
watch(currentOptions, newVal => {
const { autoSelectedFirst, modelValue, valueKey, multiple, sort } = props
// 自动选中第一项
if (autoSelectedFirst && newVal.length && !modelValue?.length) {
const firstValue = multiple ? [newVal[0][valueKey]] : newVal[0][valueKey]
emits('update:modelValue', firstValue)
selectChange(firstValue)
}
if (sort) {
currentOptions.value = currentOptions.value.sort((a, b) => a.value - b.value)
}
})
watch(
() => props.options,
newVal => {
if (props.mode === 'static') {
currentOptions.value = newVal
}
}
)
watch(
() => props.mode,
newVal => {
if (newVal === 'static') {
currentOptions.value = props.options
}
if (newVal === 'remote') {
currentOptions.value = []
fetchData()
}
}
)
const selectChange = val => {
const { valueKey, multiple, name } = props
let valueData = {}
if (multiple) {
// 多选就过滤出vals对应的源数据
valueData = currentOptions.value.filter(item => {
return val.includes(item[valueKey])
})
} else {
// 单选找到单项对应的源数据
valueData = currentOptions.value.find(item => item[valueKey] === val)
}
// 如果接到了selectData给顶级组件保存当前值对应得数据源
if (selectData) {
selectData[name] = valueData
}
emits('onChangeSelect', selectData)
}
return { selectVal, selectChange, currentOptions, loading, fetchData, isMax }
}
export default useSelect