feat: 新增 GiEditTable 编辑表格组件(同步 GiDemo 更新)

This commit is contained in:
2024-10-27 19:51:35 +08:00
parent 26291a1e44
commit b46235b7ed
7 changed files with 414 additions and 126 deletions

View File

@@ -0,0 +1,121 @@
<template>
<div class="gi-edit-table">
<a-form ref="formRef" :model="form">
<a-table :data="form.tableData" :bordered="{ cell: true }" :pagination="false" v-bind="attrs">
<template #columns>
<a-table-column v-for="col in props.columns" :key="col.dataIndex" :title="col.title"
:data-index="col.dataIndex" :header-cell-class="headerCellClass(col)" v-bind="col.columnProps">
<template #cell="{ record, rowIndex, column }">
<a-form-item :field="`tableData[${rowIndex}].${col.dataIndex}`" :label-col-style="{ display: 'none' }"
:wrapper-col-props="{ span: 24 }" v-bind="col.formItemProps"
:rules="[{ required: col.required || false, message: getRuleMessage(col) }, ...(col.rules || [])]">
<template v-if="col.slotName">
<slot :name="col.dataIndex" v-bind="{ record, rowIndex, column }"></slot>
</template>
<component :is="`a-${col.type}`" v-else v-bind="getComponentBindProps(col)"
v-model="record[col.dataIndex]" :disabled="isDisabled({ row: record, rowIndex, col })">
</component>
</a-form-item>
</template>
</a-table-column>
</template>
</a-table>
</a-form>
</div>
</template>
<script lang='ts' setup generic="T extends TableData">
import type { TableData } from '@arco-design/web-vue'
import type { ColumnItem, Disabled } from './type'
defineOptions({ name: 'GiEditTable', inheritAttrs: false })
const props = withDefaults(defineProps<Props>(), {
cellDisabled: false
})
defineSlots<{
[propsName: string]: (props: { record: T, rowIndex: number, column: ColumnItem }) => void
}>()
interface Props {
columns: ColumnItem[]
data: T[]
cellDisabled?: Disabled<T>
}
const attrs = useAttrs()
const form = computed(() => ({ tableData: props.data }))
const formRef = useTemplateRef('formRef')
defineExpose({ formRef })
const headerCellClass = (col: ColumnItem) => {
return col.required ? 'gi_column_require' : ''
}
const getComponentBindProps = (col: ColumnItem) => {
const obj: Partial<ColumnItem['props'] & { placeholder: string }> = {}
if (col.type === 'input') {
obj.allowClear = true
obj.placeholder = `请输入${col.title}`
obj.maxLength = 50
}
if (col.type === 'input-number') {
obj.placeholder = `请输入${col.title}`
}
if (col.type === 'textarea') {
obj.allowClear = true
obj.placeholder = `填写${col.title}`
obj.maxLength = 200
}
if (col.type === 'select') {
obj.allowClear = true
obj.placeholder = `请选择${col.title}`
}
if (col.type === 'cascader') {
obj.allowClear = true
obj.placeholder = `请选择${col.title}`
}
if (col.type === 'tree-select') {
obj.allowClear = true
obj.placeholder = `请选择${col.title}`
}
if (col.type === 'date-picker') {
obj.placeholder = '请选择日期'
}
if (col.type === 'time-picker') {
obj.allowClear = true
obj.placeholder = `请选择时间`
}
return { ...obj, ...col.props }
}
const getRuleMessage = (col: ColumnItem) => {
if (['input', 'input-number'].includes(col.type ?? '')) {
return `请输入${col.title}`
}
if (['textarea'].includes(col.type ?? '')) {
return `请填写${col.title}`
}
if (['select', 'cascader', 'tree-select'].includes(col.type ?? '')) {
return `请选择${col.title}`
}
if (['date-picker'].includes(col.type ?? '')) {
return `请选择日期`
}
if (['time-picker'].includes(col.type ?? '')) {
return `请选择时间`
}
return ''
}
const isDisabled: Props['cellDisabled'] = (p) => {
if (typeof props?.cellDisabled === 'boolean') return props.cellDisabled
if (typeof props?.cellDisabled === 'function') return props.cellDisabled(p)
return false
}
</script>
<style lang='scss' scoped></style>

View File

@@ -0,0 +1,5 @@
import GiEditTable from './GiEditTable.vue'
export type * from './type'
export default GiEditTable

View File

@@ -0,0 +1,51 @@
import type * as A from '@arco-design/web-vue'
export interface ColumnItem {
type?:
| 'input'
| 'select'
| 'radio-group'
| 'checkbox-group'
| 'textarea'
| 'date-picker'
| 'year-picker'
| 'quarter-picker'
| 'week-picker'
| 'range-picker'
| 'month-picker'
| 'time-picker'
| 'color-picker'
| 'input-number'
| 'rate'
| 'switch'
| 'slider'
| 'cascader'
| 'tree-select'
| 'upload'
| ''
title: string
dataIndex: string
required?: boolean
rules?: A.FormItemInstance['$props']['rules'] // 表单校验规则
props?:
& A.InputInstance['$props']
& A.SelectInstance['$props']
& A.TextareaInstance['$props']
& A.DatePickerInstance['$props']
& A.TimePickerInstance['$props']
& A.RadioGroupInstance['$props']
& A.CheckboxGroupInstance['$props']
& A.InputNumberInstance['$props']
& A.RateInstance['$props']
& A.SwitchInstance['$props']
& A.SliderInstance['$props']
& A.CascaderInstance['$props']
& A.TreeSelectInstance['$props']
& A.UploadInstance['$props']
& A.AlertInstance['$props']
columnProps?: A.TableColumnInstance['$props']
formItemProps?: A.FormItemInstance['$props']
slotName?: string
}
export type Disabled<T> = boolean | ((e: { row: T, rowIndex: number, col: ColumnItem }) => boolean)

View File

@@ -22,6 +22,7 @@ declare module 'vue' {
GiCellTags: typeof import('./../components/GiCell/GiCellTags.vue')['default']
GiCodeView: typeof import('./../components/GiCodeView/index.vue')['default']
GiDot: typeof import('./../components/GiDot/index.tsx')['default']
GiEditTable: typeof import('./../components/GiEditTable/GiEditTable.vue')['default']
GiFlexibleBox: typeof import('./../components/GiFlexibleBox/index.vue')['default']
GiFooter: typeof import('./../components/GiFooter/index.vue')['default']
GiForm: typeof import('./../components/GiForm/src/GiForm.vue')['default']