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