From 3fbfefcf6bdbf35ac36d6e9b01aa75e2cff77ab6 Mon Sep 17 00:00:00 2001
From: zs <zhousong@weben-smart.com>
Date: 周三, 30 4月 2025 19:05:47 +0800
Subject: [PATCH] 查询

---
 HIAWms/web/src/components/TableFilter/TableFilter.tsx |  337 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 337 insertions(+), 0 deletions(-)

diff --git a/HIAWms/web/src/components/TableFilter/TableFilter.tsx b/HIAWms/web/src/components/TableFilter/TableFilter.tsx
new file mode 100644
index 0000000..588edec
--- /dev/null
+++ b/HIAWms/web/src/components/TableFilter/TableFilter.tsx
@@ -0,0 +1,337 @@
+import {
+  defineComponent,
+  ref,
+  computed,
+  onMounted,
+  watch,
+  onUnmounted,
+  Component,
+} from 'vue'
+import styles from './TableFilter.module.scss'
+import { CaretBottom } from '@element-plus/icons-vue'
+import IconButton from '@/components/IconButton/IconButton'
+
+import ElInput from 'element-plus/es/components/input/index'
+import ElSelect from 'element-plus/es/components/select/index'
+import Select from '@/components/Select/Select'
+import Option from '@/components/Select/Option'
+import Icon from '../Icon/Icon'
+import { FormPropsType, FormItemPropType, PropsType } from '../DyForm/DyForm.d'
+import isNil from 'lodash/isNil'
+import { useVModel } from '@vueuse/core'
+
+const formItemElementMap: Record<string, any> = {
+  input: ElInput,
+  select: Select,
+}
+
+const Type: Record<string, string> = {
+  select: 'select',
+}
+
+interface FieldMapType {
+  [key: string]: Array<{
+    label: string
+    value: string | number | boolean
+  }>
+}
+export default defineComponent({
+  name: '琛ㄦ牸绛涢��',
+  props: {
+    title: {
+      type: String,
+      default: '',
+    },
+    columns: {
+      type: Array,
+      default: () => [],
+    },
+    tableRef: {
+      type: Object,
+      default: null,
+    },
+    modelValue: {
+      type: Object,
+      default: null,
+    },
+    text: {
+      type: String,
+      default: '',
+    },
+    fieldMap: {
+      type: Object,
+      default: () => ({}),
+    },
+    options: {
+      type: Array,
+      default: () => [],
+    },
+    defaultOptions: {
+      type: Array,
+      default: () => [],
+    },
+  },
+  emits: ['update:modelValue', 'data', 'change'],
+  setup(props, { attrs, slots, emit }) {
+    const visible = ref(false)
+    const columnsFilter = ref<FormItemPropType>([])
+    const isDisabled = ref<boolean>(false)
+    const defaultData = ref({})
+    const data = ref({})
+    const optionMap = ref<Record<string, any>>({})
+    const form = computed({
+      get() {
+        return props.modelValue
+      },
+      set(v) {
+        emit('update:modelValue', v)
+      },
+    })
+
+    const formData = props.modelValue ? form : data
+    let flag = false
+    /**
+     * 娣诲姞绛涢�夋潯浠�
+     */
+    const onAddFilter = (evt?: Event) => {
+      if (!flag) {
+        evt?.stopPropagation()
+
+        let length = columnsFilter.value.length
+        for (let index = 0; index < props.columns.length; index++) {
+          const element: any = props.columns[index]
+          if (element.el && !columnsFilter.value.includes(element)) {
+            columnsFilter.value.push(element)
+            break
+          }
+        }
+        if (length === columnsFilter.value.length - 1) {
+          isDisabled.value = true
+        }
+      }
+    }
+
+    /**
+     * 閲嶇疆鎵�鏈夌姸鎬侊紝鍒濆鍖栬〃鏍�
+     *  */
+    const onReset = () => {
+      // columnsFilter.value = []
+      // Object.entries(defaultData.value).forEach(([key, value]) => {
+      //   formData.value[key] = value
+      // })
+      // onAddFilter()
+      // onSearchTable()
+    }
+    /**
+     * 鎵撳紑寮圭獥
+     */
+    const onListener = () => {
+      visible.value = false
+    }
+    /**
+     * 瀛愮粍浠剁偣鍑�
+     * @param evt
+     */
+    const onChildClick = async (evt: Event) => {
+      evt.stopPropagation()
+      await getOptions()
+      visible.value = true
+    }
+    /**
+     * 琛ㄦ牸鎼滅储
+     */
+    const onSearchTable = () => {
+      const tableRef =
+        props.tableRef && props.tableRef.value
+          ? props.tableRef.value
+          : props.tableRef
+      const data: Record<string, any> = { ...formData.value }
+
+      Object.entries(data).forEach(([key, value]) => {
+        if (value === null || value === undefined) {
+          data[key] = ''
+        }
+      })
+      if (tableRef) {
+        tableRef?.getList?.(data)
+      } else {
+        emit('data', data)
+        emit('change', data)
+      }
+    }
+    const hasFormData = computed(() => {
+      if (Object.keys(formData.value).length === 0) return false
+      return Object.entries(formData.value).every(([key, value]) => {
+        return value !== null && value !== undefined && value !== ''
+      })
+    })
+    /**
+     * 鍒濆鍖杁isabled鐘舵��
+     */
+    const initDisabled = () => {
+      const els = props.columns.filter((column: any) => column.el)
+      if (els.length <= 1) {
+        isDisabled.value = true
+      } else {
+        isDisabled.value = false
+      }
+    }
+
+    watch(
+      () => props.columns,
+      (val) => {
+        if (props.columns.length) {
+          onAddFilter()
+          initDisabled()
+          flag = true
+        }
+      },
+      {
+        immediate: true,
+        deep: true,
+      }
+    )
+
+    onMounted(() => {
+      if (props.columns.length) {
+        onAddFilter()
+        initDisabled()
+        flag = true
+      }
+      defaultData.value = { ...props.modelValue }
+      document.addEventListener('click', onListener)
+    })
+
+    onUnmounted(() => {
+      document.removeEventListener('click', onListener)
+    })
+
+    // const getOptions = async (
+    //   item: Record<string, any>,
+    //   $props: Record<string, any>
+    // ) => {
+    //   if (typeof item.options === 'function') {
+    //     return await item.options()
+    //   } else {
+    //     let options: any =
+    //       item.options || props.fieldMap?.[$props.item.prop] || []
+    //     if (props.defaultOptions.length) {
+    //       options = options.concat(props.defaultOptions)
+    //     }
+    //     return options
+    //   }
+    // }
+    const getOptions = async () => {
+      const columns = props.columns
+      for (let index = 0; index < columns.length; index++) {
+        const column: any = columns[index]
+        if (column.prop) {
+          let options: any[] = []
+          if (typeof column.options === 'function') {
+            options = await column.options()
+          } else {
+            options = column.options || props.fieldMap?.[column.prop] || []
+          }
+          if (props.defaultOptions.length) {
+            options = props.defaultOptions.concat(options)
+          }
+          optionMap.value[column.prop] = options
+        }
+      }
+    }
+
+    const onClickBtn = (evt: Event) => {
+      evt.stopPropagation()
+      flag = false
+      onAddFilter()
+    }
+
+    /**
+     * option
+     * @param $props
+     * @returns
+     */
+    const Column = ($props: any) => {
+      const column: Record<string, any> = $props.item
+      const options = optionMap.value[column.prop] || []
+      if (Type[column.el]) {
+        return options.map(
+          (el: {
+            label: string
+            description: string
+            value: string | number
+          }) => (
+            <Option
+              label={el.description || el.label}
+              value={el.value}
+            ></Option>
+          )
+        )
+      }
+      return null
+    }
+
+    return () => {
+      const icon = isDisabled.value ? 'icon_add2' : 'add-p'
+      return (
+        <div onClick={onChildClick}>
+          <el-popover
+            visible={visible.value}
+            placement="bottom-start"
+            width={212}
+            show-arrow={false}
+            popper-class={styles.popover}
+            persistent={false}
+            popper-style={{
+              marginTop: '-7px',
+              padding: '8px',
+            }}
+            trigger="click"
+            vSlots={{
+              reference: () => (
+                <span class={{ [styles.textColor]: hasFormData.value }}>
+                  {slots.default?.()}
+                </span>
+              ),
+            }}
+            onShow={onReset}
+          >
+            <div
+              class={styles.box}
+              onClick={(evt: Event) => {
+                evt.stopPropagation()
+              }}
+            >
+              {columnsFilter.value.map((column: any) => {
+                const Widget = formItemElementMap[column.el] || null
+                return Widget ? (
+                  <div class={styles.filter}>
+                    <span>{column.title}: </span>
+                    <Widget
+                      v-model={formData.value[column.prop]}
+                      style="width: 119px"
+                      size="small"
+                      placeholder={`${column.placeholder}`}
+                      onChange={onSearchTable}
+                      clearable
+                      teleported={false}
+                    >
+                      <Column item={column} />
+                    </Widget>
+                  </div>
+                ) : null
+              })}
+            </div>
+            <IconButton
+              onClick={onClickBtn}
+              icon={icon}
+              disabled={isDisabled.value}
+            >
+              {props.text}
+            </IconButton>
+          </el-popover>
+        </div>
+      )
+    }
+  },
+})

--
Gitblit v1.9.3