186 lines
5.0 KiB
TypeScript
186 lines
5.0 KiB
TypeScript
import { computed, defineComponent, h, ref } from 'vue';
|
|
import type { Component, PropType } from 'vue';
|
|
import { ElButton, ElPopover, ElTooltip } from 'element-plus';
|
|
import { $t } from '@/locales';
|
|
|
|
export type BusinessTableAction = {
|
|
key: string;
|
|
label: string;
|
|
buttonType?: 'primary' | 'success' | 'warning' | 'danger' | 'info';
|
|
icon?: Component;
|
|
disabled?: boolean;
|
|
onClick: () => void | Promise<void>;
|
|
};
|
|
|
|
export default defineComponent({
|
|
name: 'BusinessTableActionCell',
|
|
props: {
|
|
actions: {
|
|
type: Array as PropType<BusinessTableAction[]>,
|
|
required: true
|
|
},
|
|
variant: {
|
|
type: String as PropType<'button' | 'icon'>,
|
|
default: 'button'
|
|
}
|
|
},
|
|
setup(props) {
|
|
const popoverVisible = ref(false);
|
|
|
|
const directActions = computed(() => {
|
|
if (props.variant === 'icon') {
|
|
return props.actions;
|
|
}
|
|
|
|
if (props.actions.length <= 2) {
|
|
return props.actions;
|
|
}
|
|
|
|
return props.actions.slice(0, 1);
|
|
});
|
|
|
|
const moreActions = computed(() => {
|
|
if (props.variant === 'icon') {
|
|
return [];
|
|
}
|
|
|
|
if (props.actions.length <= 2) {
|
|
return [];
|
|
}
|
|
|
|
return props.actions.slice(1);
|
|
});
|
|
|
|
async function handleAction(action: BusinessTableAction) {
|
|
if (action.disabled) {
|
|
return;
|
|
}
|
|
|
|
popoverVisible.value = false;
|
|
await action.onClick();
|
|
}
|
|
|
|
function renderIcon(action: BusinessTableAction) {
|
|
if (!action.icon) return null;
|
|
|
|
return h(action.icon, { class: 'business-table-action-icon' });
|
|
}
|
|
|
|
function renderButtonAction(action: BusinessTableAction) {
|
|
return (
|
|
<ElButton
|
|
key={action.key}
|
|
plain
|
|
size="small"
|
|
type={action.buttonType}
|
|
disabled={action.disabled}
|
|
class="business-table-action-button"
|
|
onClick={() => handleAction(action)}
|
|
>
|
|
{action.label}
|
|
</ElButton>
|
|
);
|
|
}
|
|
|
|
function renderIconAction(action: BusinessTableAction) {
|
|
return (
|
|
<ElTooltip key={action.key} content={action.label} placement="top">
|
|
<ElButton
|
|
link
|
|
size="small"
|
|
type={action.buttonType}
|
|
disabled={action.disabled}
|
|
class="business-table-action-icon-button"
|
|
aria-label={action.label}
|
|
onClick={() => handleAction(action)}
|
|
>
|
|
{renderIcon(action)}
|
|
</ElButton>
|
|
</ElTooltip>
|
|
);
|
|
}
|
|
|
|
function renderMenuButton(action: BusinessTableAction) {
|
|
if (props.variant === 'icon') {
|
|
return (
|
|
<ElButton
|
|
key={action.key}
|
|
link
|
|
size="small"
|
|
type={action.buttonType}
|
|
disabled={action.disabled}
|
|
class="business-table-action-menu__link"
|
|
onClick={() => handleAction(action)}
|
|
>
|
|
<span class="business-table-action-menu__item">
|
|
{renderIcon(action)}
|
|
<span>{action.label}</span>
|
|
</span>
|
|
</ElButton>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<ElButton
|
|
key={action.key}
|
|
plain
|
|
size="small"
|
|
type={action.buttonType}
|
|
disabled={action.disabled}
|
|
class="business-table-action-menu__button"
|
|
onClick={() => handleAction(action)}
|
|
>
|
|
{action.label}
|
|
</ElButton>
|
|
);
|
|
}
|
|
|
|
return () => (
|
|
<div class="business-table-action-cell" onClick={event => event.stopPropagation()}>
|
|
{directActions.value.map(action =>
|
|
props.variant === 'icon' ? renderIconAction(action) : renderButtonAction(action)
|
|
)}
|
|
|
|
{moreActions.value.length > 0 && (
|
|
<ElPopover
|
|
v-model:visible={popoverVisible.value}
|
|
placement="bottom-end"
|
|
trigger="click"
|
|
width={120}
|
|
show-arrow={false}
|
|
>
|
|
{{
|
|
reference: () => (
|
|
<ElButton
|
|
link={props.variant === 'icon'}
|
|
plain={props.variant !== 'icon'}
|
|
size="small"
|
|
class={
|
|
props.variant === 'icon' ? 'business-table-action-icon-button' : 'business-table-action-button'
|
|
}
|
|
aria-label={$t('common.more')}
|
|
onClick={event => event.stopPropagation()}
|
|
>
|
|
{props.variant === 'icon' ? (
|
|
<icon-mdi-dots-horizontal class="business-table-action-icon" />
|
|
) : (
|
|
<span class="inline-flex items-center gap-4px">
|
|
{$t('common.more')}
|
|
<icon-mdi-chevron-down class="text-14px" />
|
|
</span>
|
|
)}
|
|
</ElButton>
|
|
),
|
|
default: () => (
|
|
<div class="business-table-action-menu">
|
|
{moreActions.value.map(action => renderMenuButton(action))}
|
|
</div>
|
|
)
|
|
}}
|
|
</ElPopover>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|
|
});
|