mirror of
https://github.com/continew-org/continew-admin-ui.git
synced 2025-11-03 02:57:09 +08:00
feat: 新增 GiEditTable 编辑表格组件(同步 GiDemo 更新)
This commit is contained in:
121
src/components/GiEditTable/GiEditTable.vue
Normal file
121
src/components/GiEditTable/GiEditTable.vue
Normal 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>
|
||||
5
src/components/GiEditTable/index.ts
Normal file
5
src/components/GiEditTable/index.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import GiEditTable from './GiEditTable.vue'
|
||||
|
||||
export type * from './type'
|
||||
|
||||
export default GiEditTable
|
||||
51
src/components/GiEditTable/type.ts
Normal file
51
src/components/GiEditTable/type.ts
Normal 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)
|
||||
1
src/types/components.d.ts
vendored
1
src/types/components.d.ts
vendored
@@ -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']
|
||||
|
||||
Reference in New Issue
Block a user