mirror of
https://github.com/continew-org/continew-admin-ui.git
synced 2025-11-10 14:57:09 +08:00
feat: 优化 GiForm(同步 GiDemo 更新)
This commit is contained in:
@@ -1,12 +1,16 @@
|
||||
<template>
|
||||
<div class="gi-edit-table">
|
||||
<a-form ref="formRef" :model="form">
|
||||
<a-form ref="formRef" scroll-to-first-error :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"
|
||||
v-for="col in props.columns" :key="col.dataIndex" :data-index="col.dataIndex"
|
||||
:header-cell-class="headerCellClass(col)" v-bind="col.columnProps" :title="col.title"
|
||||
>
|
||||
<template #title>
|
||||
<component :is="col?.columnProps?.title" v-if="typeof col?.columnProps?.title === 'function'"></component>
|
||||
<template v-else>{{ col?.columnProps?.title || col.title }}</template>
|
||||
</template>
|
||||
<template #cell="{ record, rowIndex, column }">
|
||||
<a-form-item
|
||||
:field="`tableData[${rowIndex}].${col.dataIndex}`" :label-col-style="{ display: 'none' }"
|
||||
@@ -25,21 +29,31 @@
|
||||
</template>
|
||||
</a-table-column>
|
||||
</template>
|
||||
<template #tr="{ record, rowIndex }">
|
||||
<tr class="gi-edit-table-tr" @dblclick="emit('tr-dblclick', { record, rowIndex })"></tr>
|
||||
</template>
|
||||
<template #td="{ record, column, rowIndex }">
|
||||
<td class="gi-edit-table-td" @dblclick="emit('td-dblclick', { record, column, rowIndex })"></td>
|
||||
</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 { TableColumnData, TableData } from '@arco-design/web-vue'
|
||||
import type { ColumnItem, Disabled } from './type'
|
||||
|
||||
defineOptions({ name: 'GiEditTable', inheritAttrs: false })
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
cellDisabled: false,
|
||||
})
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'tr-dblclick', value: { record: any, rowIndex: number }): void
|
||||
(e: 'td-dblclick', value: { record: any, rowIndex: number, column: TableColumnData }): void
|
||||
}>()
|
||||
|
||||
defineSlots<{
|
||||
[propsName: string]: (props: { record: T, rowIndex: number, column: ColumnItem }) => void
|
||||
}>()
|
||||
@@ -55,64 +69,41 @@ const attrs = useAttrs()
|
||||
const form = computed(() => ({ tableData: props.data }))
|
||||
|
||||
const formRef = useTemplateRef('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 ConfigMap = new Map<ColumnItem['type'], Partial<Omit<ColumnItem['props'], 'placeholder'> & { placeholder?: string | string[] }>>([
|
||||
['input', { allowClear: true, placeholder: `请输入${col.title}`, maxLength: 50 }],
|
||||
['input-number', { placeholder: `请输入${col.title}` }],
|
||||
['textarea', { allowClear: false, placeholder: `请填写${col.title}`, maxLength: 200 }],
|
||||
['input-tag', { allowClear: true, placeholder: `请输入${col.title}` }],
|
||||
['mention', { allowClear: true, placeholder: `请输入${col.title}` }],
|
||||
['select', { allowClear: true, placeholder: `请选择${col.title}` }],
|
||||
['tree-select', { allowClear: true, placeholder: `请选择${col.title}` }],
|
||||
['cascader', { allowClear: true, placeholder: `请选择${col.title}` }],
|
||||
['radio-group', {}],
|
||||
['checkbox-group', {}],
|
||||
['date-picker', { allowClear: true, placeholder: '请选择日期' }],
|
||||
['time-picker', { allowClear: true, placeholder: '请选择时间' }],
|
||||
])
|
||||
// 获取默认配置
|
||||
const defaultProps = ConfigMap.get(col.type) || {}
|
||||
// 合并默认配置和自定义配置
|
||||
return { ...defaultProps, ...col.props }
|
||||
}
|
||||
|
||||
const getRuleMessage = (col: ColumnItem) => {
|
||||
if (['input', 'input-number'].includes(col.type ?? '')) {
|
||||
if (['input', 'input-number', 'input-tag', 'mention'].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 ''
|
||||
return `请选择${col.title}`
|
||||
}
|
||||
|
||||
const isDisabled: Props['cellDisabled'] = (p) => {
|
||||
@@ -120,6 +111,7 @@ const isDisabled: Props['cellDisabled'] = (p) => {
|
||||
if (typeof props?.cellDisabled === 'function') return props.cellDisabled(p)
|
||||
return false
|
||||
}
|
||||
|
||||
defineExpose({ formRef })
|
||||
</script>
|
||||
|
||||
|
||||
@@ -1,49 +1,69 @@
|
||||
import type * as A from '@arco-design/web-vue'
|
||||
import type { VNode } from 'vue'
|
||||
|
||||
export type ColumnItemType =
|
||||
| 'input'
|
||||
| 'input-number'
|
||||
| 'input-tag'
|
||||
| 'textarea'
|
||||
| 'select'
|
||||
| 'tree-select'
|
||||
| 'radio-group'
|
||||
| 'checkbox-group'
|
||||
| 'date-picker'
|
||||
| 'year-picker'
|
||||
| 'quarter-picker'
|
||||
| 'month-picker'
|
||||
| 'week-picker'
|
||||
| 'time-picker'
|
||||
| 'range-picker'
|
||||
| 'color-picker'
|
||||
| 'rate'
|
||||
| 'switch'
|
||||
| 'slider'
|
||||
| 'cascader'
|
||||
| 'upload'
|
||||
| 'auto-complete'
|
||||
| 'mention'
|
||||
| ''
|
||||
|
||||
export type ComponentProps =
|
||||
& A.InputInstance['$props']
|
||||
& A.InputNumberInstance['$props']
|
||||
& A.InputTagInstance['$props']
|
||||
& A.TextareaInstance['$props']
|
||||
& A.SelectInstance['$props']
|
||||
& A.TreeSelectInstance['$props']
|
||||
& A.RadioGroupInstance['$props']
|
||||
& A.CheckboxGroupInstance['$props']
|
||||
& A.DatePickerInstance['$props']
|
||||
& A.YearPickerInstance['$props']
|
||||
& A.QuarterPickerInstance['$props']
|
||||
& A.MonthPickerInstance['$props']
|
||||
& A.WeekPickerInstance['$props']
|
||||
& A.TimePickerInstance['$props']
|
||||
& A.RangePickerInstance['$props']
|
||||
& A.ColorPickerInstance['$props']
|
||||
& A.RateInstance['$props']
|
||||
& A.SwitchInstance['$props']
|
||||
& A.SliderInstance['$props']
|
||||
& A.CascaderInstance['$props']
|
||||
& A.UploadInstance['$props']
|
||||
& A.AutoCompleteInstance['$props']
|
||||
& A.MentionInstance['$props']
|
||||
|
||||
interface ColumnItemProps extends Partial<Omit<ComponentProps, 'placeholder'>> {
|
||||
placeholder?: string | string[]
|
||||
}
|
||||
|
||||
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'
|
||||
| ''
|
||||
type?: ColumnItemType
|
||||
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']
|
||||
props?: ColumnItemProps
|
||||
columnProps?: Partial<Omit<A.TableColumnInstance['$props'], 'title'>> & { title?: string | (() => VNode) }
|
||||
formItemProps?: A.FormItemInstance['$props']
|
||||
slotName?: string
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user