Browse Source

修改fs-table-select 问题

XueNing 9 months ago
parent
commit
7840a5a364

+ 66 - 45
src/components/FsTableSelect/index.vue

@@ -1,13 +1,42 @@
 <script setup lang="ts">
-import { tableSelectProps, tableSelectEmits } from './props'
+import type { TableSelectProps } from './props'
+import { tableSelectEmits } from './props'
 import { ElPopover } from 'element-plus'
 import type { VxeTableInstance } from 'vxe-table'
-// ToDo: emit => emits
-// ToDo: modelvalue => {key, value}
-// 提供一个转换数据的方法 transformData 默认json => string
-// 提交数据转换 submitData => json
-const emit = defineEmits(tableSelectEmits)
-const props = defineProps(tableSelectProps)
+
+const emits = defineEmits(tableSelectEmits)
+const props = withDefaults(defineProps<TableSelectProps>(), {
+  modelValue: '',
+  size: 'default',
+  clearable: true,
+  valueKey: 'id',
+  labelKey: 'name',
+  placement: 'bottom-start',
+  placeholder: '请选择',
+  popperWidth: 560,
+  tagType: 'info',
+  maxTagCount: 5
+})
+
+/* 格式化提交数据 */
+const transformData = (value: any) => {
+  let result = ''
+  if (value) {
+    if (Array.isArray(value)) {
+      result = value
+        .map(item => {
+          return JSON.stringify({
+            [props.valueKey]: item[props.valueKey],
+            [props.labelKey]: item[props.labelKey]
+          })
+        })
+        .join(',')
+    } else {
+      result = JSON.stringify({ [props.valueKey]: value[props.valueKey], [props.labelKey]: value[props.labelKey] })
+    }
+  }
+  return result
+}
 
 // popover 实例
 const popoverRef = ref<InstanceType<typeof ElPopover>>()
@@ -23,13 +52,12 @@ const loading = ref(false)
 const tableData = ref<any[]>([])
 // 页码
 const pageIndex = ref<number>(1)
+// 总数
+const tableTotal = ref<number>(0)
 
 // 是否未选中
 const isEmpty = computed<boolean>(() => {
-  if (!props.multiple) {
-    return !!props.modelValue
-  }
-  return !Array.isArray(props.modelValue) || !props.modelValue.length
+  return props.modelValue == null || props.modelValue === ''
 })
 
 // 是否需要清空图标
@@ -52,28 +80,23 @@ const omittedValues = computed(() => {
   return selectLabel.value.slice(props.maxTagCount)
 })
 
-onMounted(() => {
-  initValueChange(props.initValue)
-})
-
 /* 打开弹窗 */
 const onFocus = (e: FocusEvent) => {
-  visible.value = true
-  emit('focus', e)
+  emits('focus', e)
 }
 
 /* 关闭弹窗 */
 const onBlur = (e: FocusEvent) => {
-  emit('blur', e)
+  emits('blur', e)
 }
 
 /* 清除事件 */
 const onClear = () => {
-  updateModelValue(props.multiple ? [] : null)
+  updateModelValue('')
   selectLabel.value = ''
   // 取消表格全部选中
   tableRef.value?.clearCheckboxRow()
-  emit('clear')
+  emits('clear')
 }
 
 /* 单个清除事件 */
@@ -85,8 +108,8 @@ const onItemClear = (item: any) => {
 
   // 取消表格选中数据
   tableRef.value?.toggleCheckboxRow(item)
-  updateModelValue(list.map(x => x[props.valueKey]))
-  emit('item-clear', { item, list })
+  updateModelValue(list)
+  emits('item-clear', { item, list })
 }
 
 /* 表格单选事件 */
@@ -94,41 +117,43 @@ const tableRadioChange = (data: any) => {
   selectLabel.value = data.row[props.labelKey]
   visible.value = false
   // 发出选择事件
-  updateModelValue(data.row[props.valueKey])
-  emit('change', data.row)
+  updateModelValue(data.row)
+  emits('change', data.row)
 }
 
 /* 表格多选择事件 */
 const tableCheckboxChange = (data: any) => {
-  let result = []
+  let result: Array<any> = []
   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])
+    result = uniqueArray
   } 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])
+    result = selects
   }
   // 发出选择事件
   updateModelValue(result)
-  emit('change', selectLabel.value)
+  emits('change', selectLabel.value)
 }
 
 /* initValue 改变 */
 const initValueChange = (value: any) => {
+  // 如果是字符串,则解析成对象
+  value = typeof value === 'string' ? JSON.parse(value) : value
   if (props.initValue) {
     // 处理回显数据
     if (props.multiple) {
-      selectLabel.value = value as Array<any>
+      selectLabel.value = value
     } else {
-      selectLabel.value = value[props.labelKey] as any
+      selectLabel.value = value[props.labelKey] as string
     }
-    updateModelValue(props.multiple ? value.map((x: any) => x[props.valueKey]) : value[props.valueKey])
+    updateModelValue(value)
   }
 }
 
@@ -138,11 +163,6 @@ const paginationChange = (data: number) => {
   request()
 }
 
-/* 重新加载表格 ToDo:直接使用request */
-const reload = (where: any) => {
-  request(where)
-}
-
 /* 表格请求完成 */
 const tableDone = () => {
   nextTick(() => {
@@ -153,7 +173,7 @@ const tableDone = () => {
           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
+        const temp = item[props.valueKey] === (props.modelValue && JSON.parse(props.modelValue)[props.valueKey])
         temp && tableRef.value?.setRadioRow(item)
       }
     })
@@ -175,6 +195,7 @@ const request = (where?: any) => {
         ...where
       })
       .then((res: any) => {
+        tableTotal.value = res.total || res.totalCount
         tableData.value = res.infos || res.list || res.records || res.data || res.info
         tableDone()
       })
@@ -192,7 +213,7 @@ request()
 
 /* 更新选中值 */
 const updateModelValue = (value: any) => {
-  emit('update:modelValue', value)
+  emits('update:modelValue', props.transformData ? props.transformData(value) : transformData(value))
 }
 
 /* 更新气泡位置 */
@@ -210,12 +231,13 @@ watch(currentValues, () => {
 watch(
   () => props.initValue,
   () => {
-    initValueChange(props.initValue as object | Array<any>)
-  }
+    initValueChange(props.initValue)
+  },
+  { immediate: true }
 )
 
 defineExpose({
-  reload
+  request
 })
 </script>
 
@@ -240,7 +262,6 @@ defineExpose({
           :placeholder="multiple && !isEmpty ? '' : placeholder"
           :readonly="true"
           :validateEvent="false"
-          :autocomplete="autocomplete"
           :modelValue="multiple ? '' : selectLabel"
           @focus="onFocus"
           @blur="onBlur"
@@ -303,14 +324,14 @@ defineExpose({
         </template>
       </vxe-column>
     </vxe-table>
-    <div class="table-select-pagination" v-if="tableConfig.total">
+    <div class="table-select-pagination" v-if="tableTotal">
       <el-pagination
         background
         layout="total, prev, pager, next, jumper"
         size="small"
         :pager-count="5"
-        :page-size="tableConfig.pageSize"
-        :total="tableConfig.total"
+        :page-size="tableConfig && tableConfig.pageSize"
+        :total="tableTotal"
         v-model:current-page="pageIndex"
         @current-change="paginationChange"
       />

+ 21 - 61
src/components/FsTableSelect/props.ts

@@ -1,84 +1,44 @@
 /* eslint-disable @typescript-eslint/no-unused-vars */
 import type { InputProps, PopoverProps, TagProps } from 'element-plus'
-import type { PropType } from 'vue'
 import type { TableConfig } from './types'
 
-export const tableSelectProps = {
+export interface TableSelectProps {
   // 绑定值
-  modelValue: {
-    type: [String, Number, Array],
-    default: ''
-  },
+  modelValue: any
   // 是否多选
-  multiple: Boolean,
+  multiple?: boolean
   // 是否禁用
-  disabled: Boolean,
+  disabled?: boolean
   // 尺寸
-  size: {
-    type: String as PropType<InputProps['size']>,
-    default: 'default'
-  },
+  size?: InputProps['size']
   // 是否支持清除
-  clearable: {
-    type: Boolean,
-    default: true
-  },
-  // input 的 autocomplete 属性
-  autocomplete: String,
+  clearable?: boolean
   // value 的属性名
-  valueKey: {
-    type: String,
-    default: 'id'
-  },
+  valueKey?: string
   // label 的属性名
-  labelKey: {
-    type: String,
-    default: 'name'
-  },
+  labelKey?: string
   // 回显数据,用于后端分页显示
-  initValue: [Object, Array],
+  initValue?: string | object
   // 气泡位置
-  placement: {
-    type: String as PropType<PopoverProps['placement']>,
-    default: 'bottom-start'
-  },
+  placement?: PopoverProps['placement']
   // 占位符
-  placeholder: {
-    type: String,
-    default: '请选择'
-  },
+  placeholder?: string
   // popover 宽度
-  popperWidth: {
-    type: [String, Number],
-    default: 560
-  },
-  // popover 样式
-  popperClass: String,
-  // popover 配置项
-  popperOptions: Object as PropType<PopoverProps['popperOptions']>,
+  popperWidth?: number | string
+  // 自定义 popper 类名
+  popperClass?: string
+  // popper 配置项
+  popperOptions?: PopoverProps['popperOptions']
   // 表格配置
-  tableConfig: {
-    type: Object as PropType<TableConfig>,
-    default: {
-      columns: [],
-      loading: false,
-      total: 0 // total || totalCount
-    }
-  },
+  tableConfig?: TableConfig
   // tag 类型
-  tagType: {
-    type: String as PropType<TagProps['type']>,
-    default: 'info'
-  },
+  tagType?: TagProps['type']
   // 最多显示多少个tag
-  maxTagCount: {
-    type: Number,
-    default: 5
-  }
+  maxTagCount?: number
+  // 自定义数据转换方法
+  transformData?: Function
 }
 
-export type TableSelectProps = ExtractPropTypes<typeof tableSelectProps>
-
 /**
  * 事件
  */

+ 1 - 1
src/components/FsTableSelect/types/index.ts

@@ -1,7 +1,7 @@
 /* 多选选中数据文本 */
 export interface TableConfig {
   // 表格列
-  column: Array<TableColumn>
+  column?: Array<TableColumn>
   // 表格数据
   datasource: (...args: any) => Promise<any>
   // 总数

+ 14 - 10
src/views/tableSelect/base.vue

@@ -4,18 +4,21 @@ import type { TableConfig } from '@/components/FsTableSelect/types'
 
 const data = ref('')
 
-const datas = ref([])
+const datas = ref('')
 
 const request = function ({ pageIndex }: any) {
   return new Promise(resolve => {
     setTimeout(() => {
-      const data = [
-        { name: '张三' + pageIndex, sex: '男', id: '' + pageIndex + 1 },
-        { name: '李四' + pageIndex, sex: '女', id: '' + pageIndex + 2 },
-        { name: '王五' + pageIndex, sex: '男', id: '' + pageIndex + 3 },
-        { name: '赵六' + pageIndex, sex: '女', id: '' + pageIndex + 4 },
-        { name: '张三' + pageIndex, sex: '男', id: '' + pageIndex + 5 }
-      ]
+      const data = {
+        list: [
+          { name: '张三' + pageIndex, sex: '男', id: '' + pageIndex + 1 },
+          { name: '李四' + pageIndex, sex: '女', id: '' + pageIndex + 2 },
+          { name: '王五' + pageIndex, sex: '男', id: '' + pageIndex + 3 },
+          { name: '赵六' + pageIndex, sex: '女', id: '' + pageIndex + 4 },
+          { name: '张三' + pageIndex, sex: '男', id: '' + pageIndex + 5 }
+        ],
+        total: 10
+      }
       resolve(data)
     }, 1500)
   })
@@ -41,7 +44,6 @@ const tableConfig: TableConfig = {
     }
   ],
   datasource: request,
-  total: 100,
   pageSize: 5
 }
 </script>
@@ -51,11 +53,12 @@ const tableConfig: TableConfig = {
     <el-row :gutter="15">
       <el-col :span="6">
         <el-form-item label="单选">
-          <fs-table-select v-model="data" :tableConfig="tableConfig">
+          <fs-table-select v-model="data" :tableConfig="tableConfig" automaticDropdown>
             <template #sex="{ row }">
               <el-tag size="small">{{ row.sex }}</el-tag>
             </template>
           </fs-table-select>
+          选中数据: {{ data }}
         </el-form-item>
       </el-col>
       <el-col :span="6">
@@ -65,6 +68,7 @@ const tableConfig: TableConfig = {
               <el-tag size="small">{{ row.sex }}</el-tag>
             </template>
           </fs-table-select>
+          选中数据: {{ datas }}
         </el-form-item>
       </el-col>
     </el-row>

+ 11 - 8
src/views/tableSelect/search.vue

@@ -3,7 +3,7 @@ import FsTableSelect from '@/components/FsTableSelect/index.vue'
 import type { TableConfig } from '@/components/FsTableSelect/types'
 
 const data = ref('')
-const datas = ref([])
+const datas = ref('')
 
 const initValue = ref({})
 const initValue2 = ref<Array<any>>([])
@@ -13,13 +13,16 @@ const current = ref(null)
 const request = function ({ pageIndex }: any) {
   return new Promise(resolve => {
     setTimeout(() => {
-      const data = [
-        { name: '张三', sex: '男', id: '' + pageIndex + 1 },
-        { name: '李四', sex: '女', id: '' + pageIndex + 2 },
-        { name: '王五', sex: '男', id: '' + pageIndex + 3 },
-        { name: '赵六', sex: '女', id: '' + pageIndex + 4 },
-        { name: '张三', sex: '男', id: '' + pageIndex + 5 }
-      ]
+      const data = {
+        total: 20,
+        list: [
+          { name: '张三' + pageIndex, sex: '男', id: '' + pageIndex + 1 },
+          { name: '李四' + pageIndex, sex: '女', id: '' + pageIndex + 2 },
+          { name: '王五' + pageIndex, sex: '男', id: '' + pageIndex + 3 },
+          { name: '赵六' + pageIndex, sex: '女', id: '' + pageIndex + 4 },
+          { name: '张三' + pageIndex, sex: '男', id: '' + pageIndex + 5 }
+        ]
+      }
       resolve(data)
     }, 500)
   })