wip: Table改版中
This commit is contained in:
@@ -31,7 +31,7 @@ export type {
|
||||
FormProps,
|
||||
PlaceholderModel,
|
||||
InputPasswordComponentProps,
|
||||
CheckboxButtonComponentProps
|
||||
TreeSelectComponentProps
|
||||
} from './src/types'
|
||||
|
||||
export interface FormExpose {
|
||||
|
||||
@@ -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 () => (
|
||||
|
||||
@@ -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文档
|
||||
|
||||
@@ -112,6 +112,7 @@ const getProps = computed(() => {
|
||||
|
||||
const setProps = (props: SearchProps = {}) => {
|
||||
mergeProps.value = Object.assign(unref(mergeProps), props)
|
||||
// @ts-ignore
|
||||
outsideProps.value = props
|
||||
}
|
||||
|
||||
|
||||
@@ -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 ? (
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user