feat: action buttons
parent
44c91c7417
commit
0dcfa13d3b
|
@ -0,0 +1,74 @@
|
|||
<script setup lang="ts">
|
||||
import type { ActionItem } from './types';
|
||||
|
||||
import { computed, type PropType, toRaw } from 'vue';
|
||||
|
||||
import { AccessControl } from '@vben/access';
|
||||
import { IconifyIcon } from '@vben/icons';
|
||||
import { isBoolean, isFunction, isString } from '@vben/utils';
|
||||
|
||||
import { Button } from 'ant-design-vue';
|
||||
|
||||
defineOptions({ name: 'ActionButtons' });
|
||||
|
||||
const props = defineProps({
|
||||
actions: {
|
||||
type: Array as PropType<ActionItem[]>,
|
||||
default: null,
|
||||
},
|
||||
});
|
||||
|
||||
function isIfShow(action: ActionItem): boolean {
|
||||
const ifShow = action.ifShow;
|
||||
|
||||
let isIfShow = true;
|
||||
|
||||
if (isBoolean(ifShow)) isIfShow = ifShow;
|
||||
|
||||
if (isFunction(ifShow)) isIfShow = ifShow(action);
|
||||
|
||||
return isIfShow;
|
||||
}
|
||||
|
||||
const getActions = computed(() => {
|
||||
return (toRaw(props.actions) || [])
|
||||
.filter((action) => {
|
||||
return isIfShow(action);
|
||||
})
|
||||
.map((action) => {
|
||||
return {
|
||||
...action,
|
||||
auth: isString(action.auth) ? Array.of(action.auth) : action.auth,
|
||||
};
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<template>
|
||||
<div class="flex">
|
||||
<template v-for="(action, index) in getActions" :key="index">
|
||||
<AccessControl :codes="action.auth" type="code">
|
||||
<Button class="mr-1 flex" v-bind="action" :key="index">
|
||||
<IconifyIcon
|
||||
v-if="action.preIcon"
|
||||
:class="{ 'mr-1': !!action.label }"
|
||||
:icon="action.preIcon"
|
||||
:size="14"
|
||||
/>
|
||||
{{ action.label }}
|
||||
<IconifyIcon
|
||||
v-if="action.postIcon"
|
||||
:class="{ 'mr-1': !!action.label }"
|
||||
:icon="action.postIcon"
|
||||
:size="14"
|
||||
/>
|
||||
</Button>
|
||||
</AccessControl>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
<style lang="less" scoped>
|
||||
.ant-btn-link {
|
||||
padding: 8px 4px;
|
||||
margin-left: 0;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,20 @@
|
|||
export enum IconEnum {
|
||||
ADD = 'ant-design:plus-outlined',
|
||||
ADD_FOLD = 'ant-design:folder-add-outlined',
|
||||
AUTH = 'ant-design:safety-certificate-outlined',
|
||||
DELETE = 'ant-design:delete-outlined',
|
||||
DOWNLOAD = 'ant-design:cloud-download-outlined',
|
||||
EDIT = 'clarity:note-edit-line',
|
||||
EXPORT = 'ant-design:vertical-align-bottom-outlined',
|
||||
IMPORT = 'ant-design:vertical-align-top-outlined',
|
||||
LOG = 'ant-design:exception-outlined',
|
||||
PASSWORD = 'ant-design:key-outlined',
|
||||
PREVIEW = 'ant-design:eye-outlined',
|
||||
RESET = 'ant-design:sync-outlined',
|
||||
SEARCH = 'ant-design:search-outlined',
|
||||
SEND = 'ant-design:send-outlined',
|
||||
SETTING = 'ant-design:setting-outlined',
|
||||
TEST = 'ant-design:deployment-unit-outlined',
|
||||
UPLOAD = 'ant-design:cloud-upload-outlined',
|
||||
VIEW = 'ant-design:file-search-outlined',
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
export { default as ActionButtons } from './action-buttons.vue';
|
||||
export * from './action-icon';
|
||||
export type * from './types';
|
|
@ -0,0 +1,11 @@
|
|||
import type { ButtonProps, TooltipProps } from 'ant-design-vue';
|
||||
|
||||
export interface ActionItem extends ButtonProps {
|
||||
color?: 'error' | 'success' | 'warning';
|
||||
preIcon?: string;
|
||||
postIcon?: string;
|
||||
label: string;
|
||||
auth?: string | string[];
|
||||
tooltip?: string | TooltipProps;
|
||||
ifShow?: ((...args: any[]) => boolean) | boolean;
|
||||
}
|
Loading…
Reference in New Issue