From 3cd9f003ae893abe2483ab3ce0a62bfbd9fa8554 Mon Sep 17 00:00:00 2001
From: zs <zhousong@weben-smart.com>
Date: 周一, 05 5月 2025 18:04:15 +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