mirror of
https://github.com/Tencent/tmagic-editor.git
synced 2026-07-15 15:51:07 +08:00
feat(table): 抽取 ActionPopconfirm 并优化 sub-actions 展开交互
将 Popconfirm 逻辑抽离为独立组件,ActionButton 内置 tooltip 支持,sub-actions 触发按钮改用箭头图标切换展开状态。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
78a1259665
commit
b183e71f64
@ -37,6 +37,7 @@
|
|||||||
"url": "https://github.com/Tencent/tmagic-editor.git"
|
"url": "https://github.com/Tencent/tmagic-editor.git"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@element-plus/icons-vue": "^2.3.2",
|
||||||
"lodash-es": "^4.17.21"
|
"lodash-es": "^4.17.21"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|||||||
@ -1,20 +1,26 @@
|
|||||||
<template>
|
<template>
|
||||||
<TMagicButton
|
<TMagicTooltip
|
||||||
v-show="visible"
|
:placement="action.tooltipPlacement || 'top'"
|
||||||
:class="btnClass"
|
:disabled="!Boolean(action.tooltip)"
|
||||||
link
|
:content="action.tooltip"
|
||||||
size="small"
|
|
||||||
:type="action.buttonType || 'primary'"
|
|
||||||
:icon="action.icon"
|
|
||||||
:disabled="disabled(action.disabled, row)"
|
|
||||||
@click="onClick"
|
|
||||||
>
|
>
|
||||||
<span v-html="formatter(action.text, row)"></span>
|
<TMagicButton
|
||||||
</TMagicButton>
|
v-show="visible"
|
||||||
|
:class="btnClass"
|
||||||
|
link
|
||||||
|
size="small"
|
||||||
|
:type="action.buttonType || 'primary'"
|
||||||
|
:icon="action.icon"
|
||||||
|
:disabled="disabled(action.disabled, row)"
|
||||||
|
@click="onClick"
|
||||||
|
>
|
||||||
|
<span v-html="formatter(action.text, row)"></span>
|
||||||
|
</TMagicButton>
|
||||||
|
</TMagicTooltip>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { TMagicButton } from '@tmagic/design';
|
import { TMagicButton, TMagicTooltip } from '@tmagic/design';
|
||||||
|
|
||||||
import { disabled, formatActionText as formatter } from './actionHelpers';
|
import { disabled, formatActionText as formatter } from './actionHelpers';
|
||||||
import { ColumnActionConfig } from './schema';
|
import { ColumnActionConfig } from './schema';
|
||||||
|
|||||||
44
packages/table/src/ActionPopconfirm.vue
Normal file
44
packages/table/src/ActionPopconfirm.vue
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
<template>
|
||||||
|
<TMagicPopconfirm
|
||||||
|
placement="top"
|
||||||
|
:width="action.popconfirmWidth"
|
||||||
|
:title="formatter(action.confirmText, row) || '确定执行此操作?'"
|
||||||
|
@confirm="onConfirm"
|
||||||
|
>
|
||||||
|
<template #reference>
|
||||||
|
<ActionButton :action="action" :row="row" :index="index" :btn-class="btnClass" :visible="visible" />
|
||||||
|
</template>
|
||||||
|
</TMagicPopconfirm>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { TMagicPopconfirm } from '@tmagic/design';
|
||||||
|
|
||||||
|
import ActionButton from './ActionButton.vue';
|
||||||
|
import { formatActionText as formatter } from './actionHelpers';
|
||||||
|
import { ColumnActionConfig } from './schema';
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
name: 'MTableActionPopconfirm',
|
||||||
|
});
|
||||||
|
|
||||||
|
const props = withDefaults(
|
||||||
|
defineProps<{
|
||||||
|
action: ColumnActionConfig;
|
||||||
|
row: any;
|
||||||
|
index: number;
|
||||||
|
btnClass?: string;
|
||||||
|
visible?: boolean;
|
||||||
|
}>(),
|
||||||
|
{
|
||||||
|
btnClass: 'action-btn',
|
||||||
|
visible: true,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
confirm: [action: ColumnActionConfig, row: any, index: number];
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const onConfirm = () => emit('confirm', props.action, props.row, props.index);
|
||||||
|
</script>
|
||||||
@ -1,24 +1,17 @@
|
|||||||
<template>
|
<template>
|
||||||
<template v-for="(action, actionIndex) in config.actions" :key="actionIndex">
|
<template v-for="(action, actionIndex) in config.actions" :key="actionIndex">
|
||||||
<TMagicPopconfirm
|
<ActionPopconfirm
|
||||||
v-if="action.popconfirm"
|
v-if="action.popconfirm"
|
||||||
placement="top"
|
:action="action"
|
||||||
:width="action.popconfirmWidth"
|
:row="row"
|
||||||
:title="formatter(action.confirmText, row) || '确定执行此操作?'"
|
:index="index"
|
||||||
@confirm="actionHandler(action, row, index)"
|
:visible="display(action.display, row) && !editState[index]"
|
||||||
>
|
@confirm="actionHandler"
|
||||||
<template #reference>
|
/>
|
||||||
<ActionButton
|
|
||||||
:action="action"
|
|
||||||
:row="row"
|
|
||||||
:index="index"
|
|
||||||
:visible="display(action.display, row) && !editState[index]"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
</TMagicPopconfirm>
|
|
||||||
|
|
||||||
<TMagicPopover
|
<TMagicPopover
|
||||||
v-else-if="action.type === 'sub-actions'"
|
v-else-if="action.type === 'sub-actions'"
|
||||||
|
v-model:visible="popoverVisible"
|
||||||
trigger="click"
|
trigger="click"
|
||||||
:placement="action.subActionConfig?.placement || 'bottom'"
|
:placement="action.subActionConfig?.placement || 'bottom'"
|
||||||
:width="action.subActionConfig?.popoverWidth"
|
:width="action.subActionConfig?.popoverWidth"
|
||||||
@ -26,66 +19,49 @@
|
|||||||
:destroy-on-close="action.subActionConfig?.popoverDestroyOnClose"
|
:destroy-on-close="action.subActionConfig?.popoverDestroyOnClose"
|
||||||
>
|
>
|
||||||
<template #reference>
|
<template #reference>
|
||||||
<ActionButton
|
<TMagicButton
|
||||||
:action="action"
|
v-show="action.subActionConfig?.items?.length && display(action.display, row) && !editState[index]"
|
||||||
:row="row"
|
class="action-btn"
|
||||||
:index="index"
|
link
|
||||||
:visible="display(action.display, row) && !editState[index]"
|
size="small"
|
||||||
/>
|
:type="action.buttonType || 'primary'"
|
||||||
|
:icon="popoverVisible ? ArrowDown : ArrowRight"
|
||||||
|
@click.stop="togglePopover"
|
||||||
|
></TMagicButton>
|
||||||
</template>
|
</template>
|
||||||
<div class="sub-actions">
|
<div class="sub-actions">
|
||||||
<template v-for="(subAction, subIndex) in action.subActionConfig?.items" :key="subIndex">
|
<template v-for="(subAction, subIndex) in action.subActionConfig?.items" :key="subIndex">
|
||||||
<TMagicPopconfirm
|
<ActionPopconfirm
|
||||||
v-if="subAction.popconfirm"
|
v-if="subAction.popconfirm"
|
||||||
placement="top"
|
:action="subAction"
|
||||||
:width="subAction.popconfirmWidth"
|
:row="row"
|
||||||
:title="formatter(subAction.confirmText, row) || '确定执行此操作?'"
|
:index="index"
|
||||||
@confirm="actionHandler(subAction, row, index)"
|
btn-class="sub-action-btn"
|
||||||
>
|
:visible="display(subAction.display, row)"
|
||||||
<template #reference>
|
@confirm="actionHandler"
|
||||||
<ActionButton
|
/>
|
||||||
:action="subAction"
|
|
||||||
:row="row"
|
|
||||||
:index="index"
|
|
||||||
btn-class="sub-action-btn"
|
|
||||||
:visible="display(subAction.display, row)"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
</TMagicPopconfirm>
|
|
||||||
|
|
||||||
<TMagicTooltip
|
<ActionButton
|
||||||
v-else
|
v-else
|
||||||
:placement="subAction.tooltipPlacement || 'top'"
|
:action="subAction"
|
||||||
:disabled="!Boolean(subAction.tooltip)"
|
:row="row"
|
||||||
:content="subAction.tooltip"
|
:index="index"
|
||||||
>
|
btn-class="sub-action-btn"
|
||||||
<ActionButton
|
:visible="display(subAction.display, row)"
|
||||||
:action="subAction"
|
@click="actionHandler"
|
||||||
:row="row"
|
/>
|
||||||
:index="index"
|
|
||||||
btn-class="sub-action-btn"
|
|
||||||
:visible="display(subAction.display, row)"
|
|
||||||
@click="actionHandler"
|
|
||||||
/>
|
|
||||||
</TMagicTooltip>
|
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</TMagicPopover>
|
</TMagicPopover>
|
||||||
|
|
||||||
<TMagicTooltip
|
<ActionButton
|
||||||
v-else
|
v-else
|
||||||
:placement="action.tooltipPlacement || 'top'"
|
:action="action"
|
||||||
:disabled="!Boolean(action.tooltip)"
|
:row="row"
|
||||||
:content="action.tooltip"
|
:index="index"
|
||||||
>
|
:visible="display(action.display, row) && !editState[index]"
|
||||||
<ActionButton
|
@click="actionHandler"
|
||||||
:action="action"
|
/>
|
||||||
:row="row"
|
|
||||||
:index="index"
|
|
||||||
:visible="display(action.display, row) && !editState[index]"
|
|
||||||
@click="actionHandler"
|
|
||||||
/>
|
|
||||||
</TMagicTooltip>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<TMagicButton
|
<TMagicButton
|
||||||
@ -109,12 +85,15 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import { ArrowDown, ArrowRight } from '@element-plus/icons-vue';
|
||||||
import { cloneDeep } from 'lodash-es';
|
import { cloneDeep } from 'lodash-es';
|
||||||
|
|
||||||
import { TMagicButton, tMagicMessage, TMagicPopconfirm, TMagicPopover, TMagicTooltip } from '@tmagic/design';
|
import { TMagicButton, tMagicMessage, TMagicPopover } from '@tmagic/design';
|
||||||
|
|
||||||
import ActionButton from './ActionButton.vue';
|
import ActionButton from './ActionButton.vue';
|
||||||
import { display, formatActionText as formatter } from './actionHelpers';
|
import { display } from './actionHelpers';
|
||||||
|
import ActionPopconfirm from './ActionPopconfirm.vue';
|
||||||
import { ColumnActionConfig, ColumnConfig } from './schema';
|
import { ColumnActionConfig, ColumnConfig } from './schema';
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
@ -138,6 +117,11 @@ const props = withDefaults(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const popoverVisible = ref(false);
|
||||||
|
const togglePopover = () => {
|
||||||
|
popoverVisible.value = !popoverVisible.value;
|
||||||
|
};
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
'after-action': [{ index: number }];
|
'after-action': [{ index: number }];
|
||||||
'after-action-cancel': [{ index: number }];
|
'after-action-cancel': [{ index: number }];
|
||||||
@ -192,15 +176,23 @@ defineExpose({
|
|||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style lang="scss">
|
||||||
.sub-actions {
|
.sub-actions {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 4px;
|
gap: 4px;
|
||||||
}
|
align-items: flex-start;
|
||||||
|
|
||||||
.sub-actions .sub-action-btn {
|
.sub-action-btn {
|
||||||
justify-content: flex-start;
|
width: 100%;
|
||||||
width: 100%;
|
}
|
||||||
|
|
||||||
|
.tmagic-design-button + .tmagic-design-button {
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tmagic-design-button {
|
||||||
|
justify-content: flex-start;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
3
pnpm-lock.yaml
generated
3
pnpm-lock.yaml
generated
@ -497,6 +497,9 @@ importers:
|
|||||||
|
|
||||||
packages/table:
|
packages/table:
|
||||||
dependencies:
|
dependencies:
|
||||||
|
'@element-plus/icons-vue':
|
||||||
|
specifier: ^2.3.2
|
||||||
|
version: 2.3.2(vue@3.5.38(typescript@6.0.3))
|
||||||
'@tmagic/design':
|
'@tmagic/design':
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:../design
|
version: link:../design
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user