wip: Table改版中

This commit is contained in:
kailong321200875
2023-07-09 20:29:44 +08:00
parent f8ffbd1e61
commit 002d03a0ad
11 changed files with 497 additions and 277 deletions

View File

@@ -31,7 +31,7 @@ export type {
FormProps,
PlaceholderModel,
InputPasswordComponentProps,
CheckboxButtonComponentProps
TreeSelectComponentProps
} from './src/types'
export interface FormExpose {

View File

@@ -1,6 +1,14 @@
<script lang="tsx">
import { PropType, defineComponent, ref, computed, unref, watch, onMounted } from 'vue'
import { ElForm, ElFormItem, ElRow, ElCol } from 'element-plus'
import {
ElForm,
ElFormItem,
ElRow,
ElCol,
FormRules,
ComponentSize
// FormItemProp
} from 'element-plus'
import { componentMap } from './helper/componentMap'
import { propTypes } from '@/utils/propTypes'
import { getSlot } from '@/utils/tsxHelper'
@@ -47,7 +55,7 @@ export default defineComponent({
isCol: propTypes.bool.def(true),
// 表单数据对象
model: {
type: Object as PropType<Recordable>,
type: Object as PropType<any>,
default: () => ({})
},
// 是否自动设置placeholder
@@ -55,7 +63,30 @@ export default defineComponent({
// 是否自定义内容
isCustom: propTypes.bool.def(false),
// 表单label宽度
labelWidth: propTypes.oneOfType([String, Number]).def('auto')
labelWidth: propTypes.oneOfType([String, Number]).def('auto'),
rules: {
type: Object as PropType<FormRules>,
default: () => ({})
},
labelPosition: propTypes.oneOf(['left', 'right', 'top']).def('right'),
labelSuffix: propTypes.string.def(''),
hideRequiredAsterisk: propTypes.bool.def(false),
requireAsteriskPosition: propTypes.oneOf(['left', 'right']).def('left'),
showMessage: propTypes.bool.def(true),
inlineMessage: propTypes.bool.def(false),
statusIcon: propTypes.bool.def(false),
validateOnRuleChange: propTypes.bool.def(true),
size: {
type: String as PropType<ComponentSize>,
default: 'small'
},
disabled: propTypes.bool.def(false),
scrollToError: propTypes.bool.def(false),
scrollToErrorOffset: propTypes.oneOfType([Boolean, Object]).def(undefined)
// onValidate: {
// type: Function as PropType<(prop: FormItemProp, isValid: boolean, message: string) => void>,
// default: () => {}
// }
},
emits: ['register'],
setup(props, { slots, expose, emit }) {
@@ -93,6 +124,7 @@ export default defineComponent({
const setProps = (props: FormProps = {}) => {
mergeProps.value = Object.assign(unref(mergeProps), props)
// @ts-ignore
outsideProps.value = props
}
@@ -336,7 +368,7 @@ export default defineComponent({
delete props[key]
}
}
return props
return props as FormProps
}
return () => (

View File

@@ -17,8 +17,7 @@ import {
DatePickerProps,
FormItemProps as ElFormItemProps,
FormProps as ElFormProps,
TextareaProps,
CheckboxButtonProps
ISelectProps
} from 'element-plus'
import { IEditorConfig } from '@wangeditor/editor'
import { CSSProperties } from 'vue'
@@ -121,55 +120,7 @@ export interface SelectOption {
[key: string]: any
}
export interface SelectComponentProps {
multiple?: boolean
disabled?: boolean
valueKey?: string
size?: ComponentSize
clearable?: boolean
collapseTags?: boolean
collapseTagsTooltip?: number
multipleLimit?: number
name?: string
effect?: string
autocomplete?: string
placeholder?: string
filterable?: boolean
allowCreate?: boolean
filterMethod?: (query: string, item: any) => boolean
remote?: boolean
remoteMethod?: (query: string) => void
remoteShowSuffix?: boolean
loading?: boolean
loadingText?: string
noMatchText?: string
noDataText?: string
popperClass?: string
reserveKeyword?: boolean
defaultFirstOption?: boolean
popperAppendToBody?: boolean
teleported?: boolean
persistent?: boolean
automaticDropdown?: boolean
clearIcon?: string | JSX.Element | null
fitInputWidth?: boolean
suffixIcon?: string | JSX.Element | null
tagType?: 'success' | 'info' | 'warning' | 'danger'
validateEvent?: boolean
placement?:
| 'top'
| 'top-start'
| 'top-end'
| 'bottom'
| 'bottom-start'
| 'bottom-end'
| 'left'
| 'left-start'
| 'left-end'
| 'right'
| 'right-start'
| 'right-end'
maxCollapseTags?: number
export interface SelectComponentProps extends Omit<Partial<ISelectProps>, 'options'> {
/**
* 数据源的字段别名
*/
@@ -400,25 +351,6 @@ export interface CheckboxGroupComponentProps extends Partial<CheckboxGroupProps>
style?: CSSProperties
}
export interface CheckboxButtonComponentProps extends Partial<CheckboxButtonProps> {
options?: CheckboxOption[]
/**
* 数据源的字段别名
*/
props?: {
label?: string
value?: string
disabled?: string
}
on?: {
change?: (value: string | number | boolean) => void
}
slots?: {
default?: (...args: any[]) => JSX.Element[] | null
}
style?: CSSProperties
}
export interface DividerComponentProps extends Partial<DividerProps> {
on?: {
change?: (value: number) => void
@@ -573,6 +505,70 @@ export interface FormItemProps extends Partial<ElFormItemProps> {
}
}
export interface TreeSelectComponentProps
extends Omit<Partial<SelectComponentProps>, 'props' | 'on' | 'slots'> {
data?: any[]
emptyText?: string
nodeKey?: string
props?: {
children?: string
label?: string | ((...args: any[]) => string)
disabled?: string | ((...args: any[]) => string)
isLeaf?: string | ((...args: any[]) => string)
class?: string | ((...args: any[]) => string)
}
renderAfterExpand?: boolean
load?: (...args: any[]) => Promise<any>
renderContent?: (...args: any[]) => JSX.Element | null
highlightCurrent?: boolean
defaultExpandAll?: boolean
expandOnClickNode?: boolean
checkOnClickNode?: boolean
autoExpandParent?: boolean
defaultExpandedKeys?: any[]
showCheckbox?: boolean
checkStrictly?: boolean
defaultCheckedKeys?: any[]
currentNodeKey?: string | number
filterNodeMethod?: (...args: any[]) => boolean
accordion?: boolean
indent?: number
icon?: string | ((...args: any[]) => JSX.Element | null)
lazy?: boolean
draggable?: boolean
allowDrag?: (...args: any[]) => boolean
allowDrop?: (...args: any[]) => boolean
on?: {
change?: (value: string | number | boolean | Object) => void
visibleChange?: (visible: boolean) => void
removeTag?: (tag: any) => void
clear?: () => void
blur?: (event: FocusEvent) => void
focus?: (event: FocusEvent) => void
nodeClick?: (...args: any[]) => void
nodeContextMenu?: (...args: any[]) => void
checkChange?: (...args: any[]) => void
check?: (...args: any[]) => void
currentChange?: (...args: any[]) => void
nodeExpand?: (...args: any[]) => void
nodeCollapse?: (...args: any[]) => void
nodeDragStart?: (...args: any[]) => void
nodeDragEnter?: (...args: any[]) => void
nodeDragLeave?: (...args: any[]) => void
nodeDragOver?: (...args: any[]) => void
nodeDragEnd?: (...args: any[]) => void
nodeDrop?: (...args: any[]) => void
}
slots?: {
default?: (...args: any[]) => JSX.Element | null
optionGroupDefault?: (item: SelectOption) => JSX.Element
optionDefault?: (option: SelectOption) => JSX.Element | null
prefix?: (...args: any[]) => JSX.Element | null
empty?: (...args: any[]) => JSX.Element | null
}
style?: CSSProperties
}
export interface FormSchema {
/**
* 唯一标识
@@ -610,7 +606,7 @@ export interface FormSchema {
| DateTimePickerComponentProps
| TimePickerComponentProps
| InputPasswordComponentProps
| CheckboxButtonComponentProps
| TreeSelectComponentProps
/**
* formItem组件属性具体可以查看element-plus文档

View File

@@ -112,6 +112,7 @@ const getProps = computed(() => {
const setProps = (props: SearchProps = {}) => {
mergeProps.value = Object.assign(unref(mergeProps), props)
// @ts-ignore
outsideProps.value = props
}

View File

@@ -1,11 +1,11 @@
<script lang="tsx">
import { ElTable, ElTableColumn, ElPagination } from 'element-plus'
import { ElTable, ElTableColumn, ElPagination, ComponentSize, ElTooltipProps } from 'element-plus'
import { defineComponent, PropType, ref, computed, unref, watch, onMounted } from 'vue'
import { propTypes } from '@/utils/propTypes'
import { setIndex } from './helper'
import { getSlot } from '@/utils/tsxHelper'
import type { TableProps, TableColumn, TableSlotDefault, Pagination, TableSetProps } from './types'
import type { TableProps, TableColumn, Pagination, TableSetProps } from './types'
import { set } from 'lodash-es'
import { CSSProperties } from 'vue'
export default defineComponent({
name: 'Table',
@@ -45,10 +45,137 @@ export default defineComponent({
data: {
type: Array as PropType<Recordable[]>,
default: () => []
}
},
height: propTypes.oneOfType([Number, String]),
maxHeight: propTypes.oneOfType([Number, String]),
stripe: propTypes.bool.def(false),
border: propTypes.bool.def(false),
size: {
type: String as PropType<ComponentSize>,
validator: (v: ComponentSize) => ['medium', 'small', 'mini'].includes(v)
},
fit: propTypes.bool.def(true),
showHeader: propTypes.bool.def(true),
highlightCurrentRow: propTypes.bool.def(false),
currentRowKey: propTypes.oneOfType([Number, String]),
// row-class-name, 类型为 (row: Recordable, rowIndex: number) => string | string
rowClassName: {
type: [Function, String] as PropType<(row: Recordable, rowIndex: number) => string | string>,
default: ''
},
rowStyle: {
type: [Function, Object] as PropType<
(row: Recordable, rowIndex: number) => Recordable | CSSProperties
>,
default: () => undefined
},
cellClassName: {
type: [Function, String] as PropType<
(row: Recordable, column: any, rowIndex: number) => string | string
>,
default: ''
},
cellStyle: {
type: [Function, Object] as PropType<
(row: Recordable, column: any, rowIndex: number) => Recordable | CSSProperties
>,
default: () => undefined
},
headerRowClassName: {
type: [Function, String] as PropType<(row: Recordable, rowIndex: number) => string | string>,
default: ''
},
headerRowStyle: {
type: [Function, Object] as PropType<
(row: Recordable, rowIndex: number) => Recordable | CSSProperties
>,
default: () => undefined
},
headerCellClassName: {
type: [Function, String] as PropType<
(row: Recordable, column: any, rowIndex: number) => string | string
>,
default: ''
},
headerCellStyle: {
type: [Function, Object] as PropType<
(row: Recordable, column: any, rowIndex: number) => Recordable | CSSProperties
>,
default: () => undefined
},
rowKey: {
type: [Function, String] as PropType<(row: Recordable) => string | string>,
default: () => 'id'
},
emptyText: propTypes.string.def('No Data'),
defaultExpandAll: propTypes.bool.def(false),
expandRowKeys: {
type: Array as PropType<string[]>,
default: () => []
},
defaultSort: {
type: Object as PropType<{ prop: string; order: string }>,
default: () => ({})
},
tooltipEffect: {
type: String as PropType<'dark' | 'light'>,
default: 'dark'
},
tooltipOptions: {
type: Object as PropType<
Pick<
ElTooltipProps,
| 'effect'
| 'enterable'
| 'hideAfter'
| 'offset'
| 'placement'
| 'popperClass'
| 'popperOptions'
| 'showAfter'
| 'showArrow'
>
>,
default: () => ({
enterable: true,
placement: 'top',
showArrow: true,
hideAfter: 200,
popperOptions: { strategy: 'fixed' }
})
},
showSummary: propTypes.bool.def(false),
sumText: propTypes.string.def('Sum'),
summaryMethod: {
type: Function as PropType<(param: { columns: any[]; data: any[] }) => any[]>,
default: () => undefined
},
spanMethod: {
type: Function as PropType<
(param: { row: any; column: any; rowIndex: number; columnIndex: number }) => any[]
>,
default: () => undefined
},
selectOnIndeterminate: propTypes.bool.def(true),
indent: propTypes.number.def(16),
lazy: propTypes.bool.def(false),
load: {
type: Function as PropType<(row: Recordable, treeNode: any, resolve: Function) => void>,
default: () => undefined
},
treeProps: {
type: Object as PropType<{ hasChildren: string; children: string; label: string }>,
default: () => ({ hasChildren: 'hasChildren', children: 'children', label: 'label' })
},
tableLayout: {
type: String as PropType<'auto' | 'fixed'>,
default: 'fixed'
},
scrollbarAlwaysOn: propTypes.bool.def(false),
flexible: propTypes.bool.def(false)
},
emits: ['update:pageSize', 'update:currentPage', 'register'],
setup(props, { attrs, slots, emit, expose }) {
setup(props, { attrs, emit, expose }) {
const elTableRef = ref<ComponentRef<typeof ElTable>>()
// 注册
@@ -74,7 +201,7 @@ export default defineComponent({
const setProps = (props: TableProps = {}) => {
mergeProps.value = Object.assign(unref(mergeProps), props)
outsideProps.value = props
outsideProps.value = { ...props } as any
}
const setColumn = (columnProps: TableSetProps[], columnsChildren?: TableColumn[]) => {
@@ -186,6 +313,22 @@ export default defineComponent({
return columnsChildren.map((v) => {
const props = { ...v } as any
if (props.children) delete props.children
const children = v.children
const slots = {
default: (...args: any[]) => {
if (props?.slots?.default) {
return slots.default(args)
} else if (children && children.length) {
return renderTreeTableColumn(children)
}
}
}
if (props?.slots?.header) {
slots['header'] = (...args: any[]) => props.slots.header(args)
}
return (
<ElTableColumn
showOverflowTooltip={showOverflowTooltip}
@@ -194,17 +337,7 @@ export default defineComponent({
{...props}
prop={v.field}
>
{{
default: (data: TableSlotDefault) =>
v.children && v.children.length
? renderTableColumn(v.children)
: // @ts-ignore
getSlot(slots, v.field, data) ||
v?.formatter?.(data.row, data.column, data.row[v.field], data.$index) ||
data.row[v.field],
// @ts-ignore
header: getSlot(slots, `${v.field}-header`)
}}
{slots}
</ElTableColumn>
)
})
@@ -241,6 +374,22 @@ export default defineComponent({
} else {
const props = { ...v } as any
if (props.children) delete props.children
const children = v.children
const slots = {
default: (...args: any[]) => {
if (props?.slots?.default) {
return slots.default(args)
} else if (children && children.length) {
return renderTreeTableColumn(children)
}
}
}
if (props?.slots?.header) {
slots['header'] = (...args: any[]) => props.slots.header(args)
}
return (
<ElTableColumn
showOverflowTooltip={showOverflowTooltip}
@@ -249,17 +398,7 @@ export default defineComponent({
{...props}
prop={v.field}
>
{{
default: (data: TableSlotDefault) =>
v.children && v.children.length
? renderTreeTableColumn(v.children)
: // @ts-ignore
getSlot(slots, v.field, data) ||
v?.formatter?.(data.row, data.column, data.row[v.field], data.$index) ||
data.row[v.field],
// @ts-ignore
header: () => getSlot(slots, `${v.field}-header`) || v.label
}}
{slots}
</ElTableColumn>
)
}
@@ -270,16 +409,13 @@ export default defineComponent({
return () => (
<div v-loading={unref(getProps).loading}>
<ElTable
// @ts-ignore
ref={elTableRef}
data={unref(getProps).data}
onSelection-change={selectionChange}
{...unref(getBindValue)}
>
{{
default: () => renderTableColumn(),
// @ts-ignore
append: () => getSlot(slots, 'append')
default: () => renderTableColumn()
}}
</ElTable>
{unref(getProps).pagination ? (

View File

@@ -1,9 +1,10 @@
import { TableProps as ElTableProps } from 'element-plus'
export interface TableColumn {
field: string
label?: string
children?: TableColumn[]
slots?: {
defalut?: (...args: any[]) => JSX.Element | null
default?: (...args: any[]) => JSX.Element | JSX.Element[] | null
header?: (...args: any[]) => JSX.Element | null
}
index?: number | ((index: number) => number)
@@ -65,7 +66,7 @@ export interface TableSetProps {
value: any
}
export interface TableProps {
export interface TableProps extends Omit<Partial<ElTableProps<any[]>>, 'data'> {
pageSize?: number
currentPage?: number
// 是否多选
@@ -87,6 +88,4 @@ export interface TableProps {
// 表头对齐方式
headerAlign?: 'left' | 'center' | 'right'
data?: Recordable
expand?: boolean
[key: string]: any
}