|
@@ -1,244 +1,221 @@
|
|
|
-<script lang="ts">
|
|
|
+<script setup lang="ts">
|
|
|
import { tableSelectProps, tableSelectEmits } from './props'
|
|
|
import { ElPopover } from 'element-plus'
|
|
|
import type { VxeTableInstance } from 'vxe-table'
|
|
|
-export default defineComponent({
|
|
|
- name: 'FsTableSelect',
|
|
|
- props: tableSelectProps,
|
|
|
- emits: tableSelectEmits,
|
|
|
- setup(props, { emit }) {
|
|
|
- // popover 实例
|
|
|
- const popoverRef = ref<InstanceType<typeof ElPopover>>()
|
|
|
- // 表格实例
|
|
|
- const tableRef = ref<VxeTableInstance<any>>()
|
|
|
- // 是否显示
|
|
|
- const visible = ref(false)
|
|
|
- // 选中展示的数据
|
|
|
- const selectLabel = ref<string | Array<any>>('')
|
|
|
- // 加载状态
|
|
|
- const loading = ref(false)
|
|
|
- // 表格数据
|
|
|
- const tableData = ref<any[]>([])
|
|
|
- // 页码
|
|
|
- const pageIndex = ref<number>(1)
|
|
|
|
|
|
- // 是否未选中
|
|
|
- const isEmpty = computed<boolean>(() => {
|
|
|
- if (!props.multiple) {
|
|
|
- return props.modelValue == null || props.modelValue === ''
|
|
|
- }
|
|
|
- return !Array.isArray(props.modelValue) || !props.modelValue.length
|
|
|
- })
|
|
|
+const emit = defineEmits(tableSelectEmits)
|
|
|
+const props = defineProps(tableSelectProps)
|
|
|
|
|
|
- // 是否需要清空图标
|
|
|
- const closeEnable = computed<boolean>(() => {
|
|
|
- return props.clearable && !props.disabled && !isEmpty.value
|
|
|
- })
|
|
|
+// popover 实例
|
|
|
+const popoverRef = ref<InstanceType<typeof ElPopover>>()
|
|
|
+// 表格实例
|
|
|
+const tableRef = ref<VxeTableInstance<any>>()
|
|
|
+// 是否显示
|
|
|
+const visible = ref(false)
|
|
|
+// 选中展示的数据
|
|
|
+const selectLabel = ref<string | Array<any>>('')
|
|
|
+// 加载状态
|
|
|
+const loading = ref(false)
|
|
|
+// 表格数据
|
|
|
+const tableData = ref<any[]>([])
|
|
|
+// 页码
|
|
|
+const pageIndex = ref<number>(1)
|
|
|
|
|
|
- // 多选显示的标签
|
|
|
- const currentValues = computed(() => {
|
|
|
- if (selectLabel.value == null) {
|
|
|
- return selectLabel.value ?? []
|
|
|
- }
|
|
|
- return selectLabel.value.slice(0, props.maxTagCount)
|
|
|
- })
|
|
|
- // 多选折叠的标签
|
|
|
- const omittedValues = computed(() => {
|
|
|
- if (selectLabel.value == null) {
|
|
|
- return []
|
|
|
- }
|
|
|
- return selectLabel.value.slice(props.maxTagCount)
|
|
|
- })
|
|
|
+// 是否未选中
|
|
|
+const isEmpty = computed<boolean>(() => {
|
|
|
+ if (!props.multiple) {
|
|
|
+ return props.modelValue == null || props.modelValue === ''
|
|
|
+ }
|
|
|
+ return !Array.isArray(props.modelValue) || !props.modelValue.length
|
|
|
+})
|
|
|
|
|
|
- onMounted(() => {
|
|
|
- if (props.initValue) {
|
|
|
- initValueChange(props.initValue)
|
|
|
- }
|
|
|
- })
|
|
|
+// 是否需要清空图标
|
|
|
+const closeEnable = computed<boolean>(() => {
|
|
|
+ return props.clearable && !props.disabled && !isEmpty.value
|
|
|
+})
|
|
|
|
|
|
- /* 打开弹窗 */
|
|
|
- const onFocus = (e: FocusEvent) => {
|
|
|
- if (props.automaticDropdown && !visible.value) {
|
|
|
- visible.value = true
|
|
|
- }
|
|
|
- emit('focus', e)
|
|
|
- }
|
|
|
+// 多选显示的标签
|
|
|
+const currentValues = computed(() => {
|
|
|
+ if (selectLabel.value == null) {
|
|
|
+ return selectLabel.value ?? []
|
|
|
+ }
|
|
|
+ return selectLabel.value.slice(0, props.maxTagCount)
|
|
|
+})
|
|
|
+// 多选折叠的标签
|
|
|
+const omittedValues = computed(() => {
|
|
|
+ if (selectLabel.value == null) {
|
|
|
+ return []
|
|
|
+ }
|
|
|
+ return selectLabel.value.slice(props.maxTagCount)
|
|
|
+})
|
|
|
|
|
|
- /* 关闭弹窗 */
|
|
|
- const onBlur = (e: FocusEvent) => {
|
|
|
- emit('blur', e)
|
|
|
- }
|
|
|
+onMounted(() => {
|
|
|
+ if (props.initValue) {
|
|
|
+ initValueChange(props.initValue)
|
|
|
+ }
|
|
|
+})
|
|
|
|
|
|
- /* 清除事件 */
|
|
|
- const onClear = () => {
|
|
|
- updateModelValue(props.multiple ? [] : null)
|
|
|
- selectLabel.value = ''
|
|
|
- // 取消表格全部选中
|
|
|
- tableRef.value?.clearCheckboxRow()
|
|
|
- emit('clear')
|
|
|
- }
|
|
|
+/* 打开弹窗 */
|
|
|
+const onFocus = (e: FocusEvent) => {
|
|
|
+ if (props.automaticDropdown && !visible.value) {
|
|
|
+ visible.value = true
|
|
|
+ }
|
|
|
+ emit('focus', e)
|
|
|
+}
|
|
|
|
|
|
- /* 单个清除事件 */
|
|
|
- const onItemClear = (item: any) => {
|
|
|
- const list = [...(selectLabel.value as Array<any>)]
|
|
|
- const index = list.findIndex(x => x[props.labelKey] === item[props.labelKey])
|
|
|
- list.splice(index, 1)
|
|
|
- selectLabel.value = list
|
|
|
+/* 关闭弹窗 */
|
|
|
+const onBlur = (e: FocusEvent) => {
|
|
|
+ emit('blur', e)
|
|
|
+}
|
|
|
|
|
|
- // 取消表格选中数据
|
|
|
- tableRef.value?.toggleCheckboxRow(item)
|
|
|
- updateModelValue(list.map(x => x[props.valueKey]))
|
|
|
- emit('item-clear', { item, list })
|
|
|
- }
|
|
|
+/* 清除事件 */
|
|
|
+const onClear = () => {
|
|
|
+ updateModelValue(props.multiple ? [] : null)
|
|
|
+ selectLabel.value = ''
|
|
|
+ // 取消表格全部选中
|
|
|
+ tableRef.value?.clearCheckboxRow()
|
|
|
+ emit('clear')
|
|
|
+}
|
|
|
|
|
|
- /* 表格单选事件 */
|
|
|
- const tableRadioChange = (data: any) => {
|
|
|
- selectLabel.value = data.row[props.labelKey]
|
|
|
- visible.value = false
|
|
|
- // 发出选择事件
|
|
|
- updateModelValue(data.row[props.valueKey])
|
|
|
- emit('change', data.row)
|
|
|
- }
|
|
|
+/* 单个清除事件 */
|
|
|
+const onItemClear = (item: any) => {
|
|
|
+ const list = [...(selectLabel.value as Array<any>)]
|
|
|
+ const index = list.findIndex(x => x[props.labelKey] === item[props.labelKey])
|
|
|
+ list.splice(index, 1)
|
|
|
+ selectLabel.value = list
|
|
|
|
|
|
- /* 表格多选择事件 */
|
|
|
- const tableCheckboxChange = (data: any) => {
|
|
|
- let result = []
|
|
|
- if (data.checked) {
|
|
|
- // 使用 Set 去重
|
|
|
- const uniqueArray = Array.from(
|
|
|
- new Set([...selectLabel.value, ...data.records].map((x: any) => JSON.stringify(x)))
|
|
|
- ).map((str: any) => JSON.parse(str))
|
|
|
- selectLabel.value = uniqueArray
|
|
|
- result = selectLabel.value.map(x => x[props.valueKey])
|
|
|
- } else {
|
|
|
- const selects = selectLabel.value as Array<any>
|
|
|
- const index = selects.findIndex(x => x[props.valueKey] === data.row[props.valueKey])
|
|
|
- selects?.splice(index, 1)
|
|
|
- result = selects.map(x => x[props.valueKey])
|
|
|
- }
|
|
|
- // 发出选择事件
|
|
|
- updateModelValue(result)
|
|
|
- emit('change', selectLabel.value)
|
|
|
- }
|
|
|
+ // 取消表格选中数据
|
|
|
+ tableRef.value?.toggleCheckboxRow(item)
|
|
|
+ updateModelValue(list.map(x => x[props.valueKey]))
|
|
|
+ emit('item-clear', { item, list })
|
|
|
+}
|
|
|
|
|
|
- /* initValue 改变 */
|
|
|
- const initValueChange = (value: any | Array<any>) => {
|
|
|
- if (props.initValue) {
|
|
|
- // 处理回显数据
|
|
|
- if (props.multiple) {
|
|
|
- selectLabel.value = value as Array<any>
|
|
|
- } else {
|
|
|
- selectLabel.value = value[props.labelKey] as any
|
|
|
- }
|
|
|
- updateModelValue(props.multiple ? value.map((x: any) => x[props.valueKey]) : value[props.valueKey])
|
|
|
- }
|
|
|
- }
|
|
|
+/* 表格单选事件 */
|
|
|
+const tableRadioChange = (data: any) => {
|
|
|
+ selectLabel.value = data.row[props.labelKey]
|
|
|
+ visible.value = false
|
|
|
+ // 发出选择事件
|
|
|
+ updateModelValue(data.row[props.valueKey])
|
|
|
+ emit('change', data.row)
|
|
|
+}
|
|
|
|
|
|
- /* 分页改变事件 */
|
|
|
- const paginationChange = (data: number) => {
|
|
|
- pageIndex.value = data
|
|
|
- request()
|
|
|
- }
|
|
|
+/* 表格多选择事件 */
|
|
|
+const tableCheckboxChange = (data: any) => {
|
|
|
+ let result = []
|
|
|
+ if (data.checked) {
|
|
|
+ // 使用 Set 去重
|
|
|
+ const uniqueArray = Array.from(
|
|
|
+ new Set([...selectLabel.value, ...data.records].map((x: any) => JSON.stringify(x)))
|
|
|
+ ).map((str: any) => JSON.parse(str))
|
|
|
+ selectLabel.value = uniqueArray
|
|
|
+ result = selectLabel.value.map(x => x[props.valueKey])
|
|
|
+ } else {
|
|
|
+ const selects = selectLabel.value as Array<any>
|
|
|
+ const index = selects.findIndex(x => x[props.valueKey] === data.row[props.valueKey])
|
|
|
+ selects?.splice(index, 1)
|
|
|
+ result = selects.map(x => x[props.valueKey])
|
|
|
+ }
|
|
|
+ // 发出选择事件
|
|
|
+ updateModelValue(result)
|
|
|
+ emit('change', selectLabel.value)
|
|
|
+}
|
|
|
|
|
|
- /* 重新加载表格 */
|
|
|
- const reload = (where: any) => {
|
|
|
- request(where)
|
|
|
+/* initValue 改变 */
|
|
|
+const initValueChange = (value: any | Array<any>) => {
|
|
|
+ if (props.initValue) {
|
|
|
+ // 处理回显数据
|
|
|
+ if (props.multiple) {
|
|
|
+ selectLabel.value = value as Array<any>
|
|
|
+ } else {
|
|
|
+ selectLabel.value = value[props.labelKey] as any
|
|
|
}
|
|
|
+ updateModelValue(props.multiple ? value.map((x: any) => x[props.valueKey]) : value[props.valueKey])
|
|
|
+ }
|
|
|
+}
|
|
|
|
|
|
- /* 表格请求完成 */
|
|
|
- const tableDone = () => {
|
|
|
- nextTick(() => {
|
|
|
- const newTableData = tableRef.value?.getTableData().tableData
|
|
|
- newTableData?.forEach(item => {
|
|
|
- if (props.multiple) {
|
|
|
- const temp =
|
|
|
- Array.isArray(selectLabel.value) &&
|
|
|
- selectLabel.value.find(x => x[props.valueKey] === item[props.valueKey])
|
|
|
- temp && tableRef.value?.setCheckboxRow(item, true)
|
|
|
- } else {
|
|
|
- const temp = item[props.valueKey] === props.modelValue
|
|
|
- temp && tableRef.value?.setRadioRow(item)
|
|
|
- }
|
|
|
- })
|
|
|
- })
|
|
|
- }
|
|
|
+/* 分页改变事件 */
|
|
|
+const paginationChange = (data: number) => {
|
|
|
+ pageIndex.value = data
|
|
|
+ request()
|
|
|
+}
|
|
|
|
|
|
- /* 请求数据 */
|
|
|
- const request = (where?: any) => {
|
|
|
- console.log(where)
|
|
|
- if (typeof props.tableConfig?.datasource === 'function') {
|
|
|
- loading.value = true
|
|
|
- if (where && where.pageIndex) {
|
|
|
- pageIndex.value = where.pageIndex
|
|
|
- }
|
|
|
- props.tableConfig
|
|
|
- .datasource({
|
|
|
- pageIndex: pageIndex.value,
|
|
|
- pageSize: props.tableConfig.pageSize,
|
|
|
- ...where
|
|
|
- })
|
|
|
- .then((res: any) => {
|
|
|
- tableData.value = res
|
|
|
- tableDone()
|
|
|
- })
|
|
|
- .catch((e: any) => {
|
|
|
- console.warn(e)
|
|
|
- })
|
|
|
- .finally(() => {
|
|
|
- loading.value = false
|
|
|
- })
|
|
|
+/* 重新加载表格 */
|
|
|
+const reload = (where: any) => {
|
|
|
+ request(where)
|
|
|
+}
|
|
|
+
|
|
|
+/* 表格请求完成 */
|
|
|
+const tableDone = () => {
|
|
|
+ nextTick(() => {
|
|
|
+ const newTableData = tableRef.value?.getTableData().tableData
|
|
|
+ newTableData?.forEach(item => {
|
|
|
+ if (props.multiple) {
|
|
|
+ const temp =
|
|
|
+ Array.isArray(selectLabel.value) && selectLabel.value.find(x => x[props.valueKey] === item[props.valueKey])
|
|
|
+ temp && tableRef.value?.setCheckboxRow(item, true)
|
|
|
} else {
|
|
|
- console.warn('tableConfig.datasource 必须为 Promise')
|
|
|
+ const temp = item[props.valueKey] === props.modelValue
|
|
|
+ temp && tableRef.value?.setRadioRow(item)
|
|
|
}
|
|
|
- }
|
|
|
- request()
|
|
|
+ })
|
|
|
+ })
|
|
|
+}
|
|
|
|
|
|
- /* 更新选中值 */
|
|
|
- const updateModelValue = (value: any) => {
|
|
|
- emit('update:modelValue', value)
|
|
|
+/* 请求数据 */
|
|
|
+const request = (where?: any) => {
|
|
|
+ if (typeof props.tableConfig?.datasource === 'function') {
|
|
|
+ loading.value = true
|
|
|
+ if (where && where.pageIndex) {
|
|
|
+ pageIndex.value = where.pageIndex
|
|
|
}
|
|
|
+ props.tableConfig
|
|
|
+ .datasource({
|
|
|
+ pageIndex: pageIndex.value,
|
|
|
+ pageSize: props.tableConfig.pageSize,
|
|
|
+ ...where
|
|
|
+ })
|
|
|
+ .then((res: any) => {
|
|
|
+ tableData.value = res
|
|
|
+ tableDone()
|
|
|
+ })
|
|
|
+ .catch((e: any) => {
|
|
|
+ console.warn(e)
|
|
|
+ })
|
|
|
+ .finally(() => {
|
|
|
+ loading.value = false
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+ console.warn('tableConfig.datasource 必须为 Promise')
|
|
|
+ }
|
|
|
+}
|
|
|
+request()
|
|
|
|
|
|
- /* 更新气泡位置 */
|
|
|
- watch(currentValues, () => {
|
|
|
- if (
|
|
|
- popoverRef.value &&
|
|
|
- popoverRef.value.popperRef &&
|
|
|
- popoverRef.value.popperRef.popperInstanceRef &&
|
|
|
- popoverRef.value.popperRef.popperInstanceRef.update
|
|
|
- ) {
|
|
|
- popoverRef.value.popperRef.popperInstanceRef.update()
|
|
|
- }
|
|
|
- })
|
|
|
+/* 更新选中值 */
|
|
|
+const updateModelValue = (value: any) => {
|
|
|
+ emit('update:modelValue', value)
|
|
|
+}
|
|
|
|
|
|
- watch(
|
|
|
- () => props.initValue,
|
|
|
- () => {
|
|
|
- initValueChange(props.initValue as object | Array<any>)
|
|
|
- }
|
|
|
- )
|
|
|
+/* 更新气泡位置 */
|
|
|
+watch(currentValues, () => {
|
|
|
+ if (
|
|
|
+ popoverRef.value &&
|
|
|
+ popoverRef.value.popperRef &&
|
|
|
+ popoverRef.value.popperRef.popperInstanceRef &&
|
|
|
+ popoverRef.value.popperRef.popperInstanceRef.update
|
|
|
+ ) {
|
|
|
+ popoverRef.value.popperRef.popperInstanceRef.update()
|
|
|
+ }
|
|
|
+})
|
|
|
|
|
|
- return {
|
|
|
- popoverRef,
|
|
|
- tableRef,
|
|
|
- selectLabel,
|
|
|
- visible,
|
|
|
- isEmpty,
|
|
|
- pageIndex,
|
|
|
- loading,
|
|
|
- currentValues,
|
|
|
- omittedValues,
|
|
|
- tableData,
|
|
|
- closeEnable,
|
|
|
- onFocus,
|
|
|
- onBlur,
|
|
|
- onClear,
|
|
|
- onItemClear,
|
|
|
- tableRadioChange,
|
|
|
- tableCheckboxChange,
|
|
|
- paginationChange,
|
|
|
- reload
|
|
|
- }
|
|
|
+watch(
|
|
|
+ () => props.initValue,
|
|
|
+ () => {
|
|
|
+ initValueChange(props.initValue as object | Array<any>)
|
|
|
}
|
|
|
+)
|
|
|
+
|
|
|
+defineExpose({
|
|
|
+ reload
|
|
|
})
|
|
|
</script>
|
|
|
|