fix(table): 行内编辑无法修改表单

This commit is contained in:
roymondchen 2025-12-25 19:16:17 +08:00
parent 9d4324dd6b
commit 98c2e2ff1f
4 changed files with 50 additions and 29 deletions

View File

@ -32,14 +32,16 @@
class="action-btn" class="action-btn"
v-show="editState[index]" v-show="editState[index]"
link link
type="primary" type="danger"
size="small" size="small"
@click="editState[index] = undefined" @click="cancel(index, config)"
>取消</TMagicButton >取消</TMagicButton
> >
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { cloneDeep } from 'lodash-es';
import { TMagicButton, tMagicMessage, TMagicTooltip } from '@tmagic/design'; import { TMagicButton, tMagicMessage, TMagicTooltip } from '@tmagic/design';
import { ColumnActionConfig, ColumnConfig } from './schema'; import { ColumnActionConfig, ColumnConfig } from './schema';
@ -65,7 +67,10 @@ const props = withDefaults(
}, },
); );
const emit = defineEmits(['after-action']); const emit = defineEmits<{
'after-action': [{ index: number }];
'after-action-cancel': [{ index: number }];
}>();
const display = (fuc: boolean | Function | undefined, row: any) => { const display = (fuc: boolean | Function | undefined, row: any) => {
if (typeof fuc === 'function') { if (typeof fuc === 'function') {
@ -97,7 +102,7 @@ const formatter = (fuc: string | Function | undefined, row: any) => {
const actionHandler = async (action: ColumnActionConfig, row: any, index: number) => { const actionHandler = async (action: ColumnActionConfig, row: any, index: number) => {
await action.before?.(row, index); await action.before?.(row, index);
if (action.type === 'edit') { if (action.type === 'edit') {
props.editState[index] = row; props.editState[index] = cloneDeep(row);
} else { } else {
await action.handler?.(row, index); await action.handler?.(row, index);
} }
@ -108,31 +113,31 @@ const save = async (index: number, config: ColumnConfig) => {
const action = config.actions?.find((item) => item.type === 'edit')?.action; const action = config.actions?.find((item) => item.type === 'edit')?.action;
if (!action) return; if (!action) return;
const data: any = {};
const row = props.editState[index];
props.columns
.filter((item) => item.type)
.forEach((column) => {
if (column.prop) {
data[column.prop] = row[column.prop];
}
});
const res: any = await action({ const res: any = await action({
data, data: props.editState[index],
index,
}); });
if (res) { if (res) {
if (res.ret === 0) { if (res.ret === 0) {
tMagicMessage.success('保存成功'); tMagicMessage.success('保存成功');
props.editState[index] = undefined; props.editState[index] = undefined;
emit('after-action'); emit('after-action', { index });
} else { } else {
tMagicMessage.error(res.msg || '保存失败'); tMagicMessage.error(res.msg || '保存失败');
} }
} else { } else {
props.editState[index] = undefined; props.editState[index] = undefined;
emit('after-action'); emit('after-action', { index });
} }
}; };
const cancel = async (index: number, config: ColumnConfig) => {
props.editState[index] = undefined;
const cancel = config.actions?.find((item) => item.type === 'edit')?.cancel;
if (cancel) {
await cancel({ index });
}
emit('after-action-cancel', { index });
};
</script> </script>

View File

@ -73,6 +73,7 @@ const props = withDefaults(
const emit = defineEmits([ const emit = defineEmits([
'sort-change', 'sort-change',
'after-action', 'after-action',
'after-action-cancel',
'select', 'select',
'select-all', 'select-all',
'selection-change', 'selection-change',
@ -102,6 +103,8 @@ const cellRender = (config: ColumnConfig, { row = {}, $index }: any) => {
rowkeyName: props.rowkeyName, rowkeyName: props.rowkeyName,
editState: editState.value, editState: editState.value,
columns: props.columns, columns: props.columns,
onAfterAction: (payload: { index: number }) => emit('after-action', payload),
onAfterActionCancel: (payload: { index: number }) => emit('after-action-cancel', payload),
}); });
} }
if (config.type === 'popover') { if (config.type === 'popover') {

View File

@ -2,15 +2,13 @@
<div v-if="config.type === 'index'"> <div v-if="config.type === 'index'">
{{ config.pageIndex && config.pageSize ? config.pageIndex * config.pageSize + index + 1 : index + 1 }} {{ config.pageIndex && config.pageSize ? config.pageIndex * config.pageSize + index + 1 : index + 1 }}
</div> </div>
<TMagicForm v-else-if="config.type && editState[index]" label-width="0" :model="editState[index]"> <MForm
<m-form-container v-else-if="(config.type || config.editInlineFormConfig) && editState[index]"
:prop="config.prop" label-width="0"
:rules="config.rules" :config="config.editInlineFormConfig ?? [config]"
:config="config" :init-values="editState[index]"
:name="config.prop" @change="formChangeHandler"
:model="editState[index]" ></MForm>
></m-form-container>
</TMagicForm>
<TMagicButton <TMagicButton
v-else-if="config.action === 'actionLink' && config.prop" v-else-if="config.action === 'actionLink' && config.prop"
@ -46,7 +44,10 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { TMagicButton, TMagicForm, TMagicTag, TMagicTooltip } from '@tmagic/design'; import { TMagicButton, TMagicTag, TMagicTooltip } from '@tmagic/design';
import { type ContainerChangeEventData, MForm } from '@tmagic/form';
import type { FormValue } from '@tmagic/form-schema';
import { setValueByKeyPath } from '@tmagic/utils';
import { ColumnConfig } from './schema'; import { ColumnConfig } from './schema';
import { formatter } from './utils'; import { formatter } from './utils';
@ -55,7 +56,7 @@ defineOptions({
name: 'MTableColumn', name: 'MTableColumn',
}); });
withDefaults( const props = withDefaults(
defineProps<{ defineProps<{
config: ColumnConfig; config: ColumnConfig;
editState?: any; editState?: any;
@ -67,4 +68,14 @@ withDefaults(
editState: () => ({}), editState: () => ({}),
}, },
); );
const formChangeHandler = (v: FormValue, eventData: ContainerChangeEventData) => {
if (eventData.changeRecords?.length) {
for (const record of eventData.changeRecords) {
if (record.propPath) {
setValueByKeyPath(record.propPath, record.value, props.editState[props.index]);
}
}
}
};
</script> </script>

View File

@ -31,7 +31,8 @@ export interface ColumnActionConfig {
handler?: (row: any, index: number) => Promise<any> | any; handler?: (row: any, index: number) => Promise<any> | any;
before?: (row: any, index: number) => Promise<void> | void; before?: (row: any, index: number) => Promise<void> | void;
after?: (row: any, index: number) => Promise<void> | void; after?: (row: any, index: number) => Promise<void> | void;
action?: (data: { data: any }) => Promise<void> | void; action?: (data: { data: any; index: number }) => Promise<void> | void;
cancel?: (data: { index: number }) => Promise<void> | void;
} }
export interface ColumnConfig<T = any> { export interface ColumnConfig<T = any> {
@ -52,6 +53,7 @@ export interface ColumnConfig<T = any> {
name?: string; name?: string;
showHeader?: boolean; showHeader?: boolean;
table?: ColumnConfig[]; table?: ColumnConfig[];
editInlineFormConfig?: FormConfig;
formatter?: 'datetime' | ((item: any, row: T, data: { index: number }) => any); formatter?: 'datetime' | ((item: any, row: T, data: { index: number }) => any);
popover?: { popover?: {
placement?: placement?: