vben
2023-04-06 553ee9c7aed3c679c4d00d1c1c6278b8578020d5
提交 | 用户 | age
116a1f 1 <template>
808012 2   <div :class="[prefixCls, getAlign]" @click="onCellClick">
9c2f3f 3     <template v-for="(action, index) in getActions" :key="`${index}-${action.label}`">
7b7694 4       <Tooltip v-if="action.tooltip" v-bind="getTooltip(action.tooltip)">
5fab26 5         <PopConfirmButton v-bind="action">
db7254 6           <Icon :icon="action.icon" :class="{ 'mr-1': !!action.label }" v-if="action.icon" />
dc51e6 7           <template v-if="action.label">{{ action.label }}</template>
5fab26 8         </PopConfirmButton>
9       </Tooltip>
7b7694 10       <PopConfirmButton v-else v-bind="action">
db7254 11         <Icon :icon="action.icon" :class="{ 'mr-1': !!action.label }" v-if="action.icon" />
dc51e6 12         <template v-if="action.label">{{ action.label }}</template>
7b7694 13       </PopConfirmButton>
cdf0a6 14       <Divider
V 15         type="vertical"
b1cb86 16         class="action-divider"
7593ef 17         v-if="divider && index < getActions.length - 1"
cdf0a6 18       />
116a1f 19     </template>
2e11ea 20     <Dropdown
V 21       :trigger="['hover']"
22       :dropMenuList="getDropdownList"
23       popconfirm
21c771 24       v-if="dropDownActions && getDropdownList.length > 0"
2e11ea 25     >
9edc28 26       <slot name="more"></slot>
116a1f 27       <a-button type="link" size="small" v-if="!$slots.more">
V 28         <MoreOutlined class="icon-more" />
29       </a-button>
30     </Dropdown>
31   </div>
32 </template>
33 <script lang="ts">
a07ab6 34   import { defineComponent, PropType, computed, toRaw, unref } from 'vue';
391da9 35   import { MoreOutlined } from '@ant-design/icons-vue';
73654b 36   import { Divider, Tooltip, TooltipProps } from 'ant-design-vue';
553ee9 37   import Icon from '/@/components/Icon/index';
18ad1b 38   import { ActionItem, TableActionType } from '/@/components/Table';
116a1f 39   import { PopConfirmButton } from '/@/components/Button';
V 40   import { Dropdown } from '/@/components/Dropdown';
41   import { useDesign } from '/@/hooks/web/useDesign';
42   import { useTableContext } from '../hooks/useTableContext';
6afee4 43   import { usePermission } from '/@/hooks/web/usePermission';
5fab26 44   import { isBoolean, isFunction, isString } from '/@/utils/is';
391da9 45   import { propTypes } from '/@/utils/propTypes';
116a1f 46   import { ACTION_COLUMN_FLAG } from '../const';
391da9 47
116a1f 48   export default defineComponent({
V 49     name: 'TableAction',
5fab26 50     components: { Icon, PopConfirmButton, Divider, Dropdown, MoreOutlined, Tooltip },
116a1f 51     props: {
V 52       actions: {
53         type: Array as PropType<ActionItem[]>,
54         default: null,
55       },
56       dropDownActions: {
57         type: Array as PropType<ActionItem[]>,
58         default: null,
59       },
60       divider: propTypes.bool.def(true),
18ad1b 61       outside: propTypes.bool,
808012 62       stopButtonPropagation: propTypes.bool.def(false),
116a1f 63     },
V 64     setup(props) {
65       const { prefixCls } = useDesign('basic-table-action');
cdf0a6 66       let table: Partial<TableActionType> = {};
18ad1b 67       if (!props.outside) {
V 68         table = useTableContext();
69       }
70
6afee4 71       const { hasPermission } = usePermission();
5a3861 72       function isIfShow(action: ActionItem): boolean {
Z 73         const ifShow = action.ifShow;
74
75         let isIfShow = true;
76
77         if (isBoolean(ifShow)) {
78           isIfShow = ifShow;
79         }
80         if (isFunction(ifShow)) {
81           isIfShow = ifShow(action);
82         }
83         return isIfShow;
84       }
85
116a1f 86       const getActions = computed(() => {
6afee4 87         return (toRaw(props.actions) || [])
Z 88           .filter((action) => {
5a3861 89             return hasPermission(action.auth) && isIfShow(action);
6afee4 90           })
Z 91           .map((action) => {
92             const { popConfirm } = action;
93             return {
334a0e 94               getPopupContainer: () => unref((table as any)?.wrapRef) ?? document.body,
6afee4 95               type: 'link',
Z 96               size: 'small',
97               ...action,
98               ...(popConfirm || {}),
99               onConfirm: popConfirm?.confirm,
100               onCancel: popConfirm?.cancel,
101               enable: !!popConfirm,
102             };
103           });
116a1f 104       });
V 105
e15b4f 106       const getDropdownList = computed((): any[] => {
4806ac 107         const list = (toRaw(props.dropDownActions) || []).filter((action) => {
西 108           return hasPermission(action.auth) && isIfShow(action);
109         });
110         return list.map((action, index) => {
111           const { label, popConfirm } = action;
112           return {
113             ...action,
114             ...popConfirm,
115             onConfirm: popConfirm?.confirm,
116             onCancel: popConfirm?.cancel,
117             text: label,
118             divider: index < list.length - 1 ? props.divider : false,
119           };
120         });
116a1f 121       });
V 122
123       const getAlign = computed(() => {
18ad1b 124         const columns = (table as TableActionType)?.getColumns?.() || [];
116a1f 125         const actionColumn = columns.find((item) => item.flag === ACTION_COLUMN_FLAG);
V 126         return actionColumn?.align ?? 'left';
127       });
128
7b7694 129       function getTooltip(data: string | TooltipProps): TooltipProps {
a07ab6 130         return {
334a0e 131           getPopupContainer: () => unref((table as any)?.wrapRef) ?? document.body,
a07ab6 132           placement: 'bottom',
133           ...(isString(data) ? { title: data } : data),
134         };
7b7694 135       }
5fab26 136
808012 137       function onCellClick(e: MouseEvent) {
138         if (!props.stopButtonPropagation) return;
9b8f16 139         const path = e.composedPath() as HTMLElement[];
140         const isInButton = path.find((ele) => {
141           return ele.tagName?.toUpperCase() === 'BUTTON';
142         });
143         isInButton && e.stopPropagation();
808012 144       }
145
5fab26 146       return { prefixCls, getActions, getDropdownList, getAlign, onCellClick, getTooltip };
116a1f 147     },
V 148   });
149 </script>
150 <style lang="less">
151   @prefix-cls: ~'@{namespace}-basic-table-action';
152
153   .@{prefix-cls} {
154     display: flex;
155     align-items: center;
156
b1cb86 157     .action-divider {
V 158       display: table;
159     }
160
116a1f 161     &.left {
V 162       justify-content: flex-start;
163     }
164
165     &.center {
166       justify-content: center;
167     }
168
169     &.right {
170       justify-content: flex-end;
171     }
172
173     button {
174       display: flex;
175       align-items: center;
176
177       span {
178         margin-left: 0 !important;
179       }
180     }
181
db7254 182     button.ant-btn-circle {
183       span {
184         margin: auto !important;
185       }
186     }
187
116a1f 188     .ant-divider,
V 189     .ant-divider-vertical {
190       margin: 0 2px;
191     }
192
193     .icon-more {
194       transform: rotate(90deg);
195
196       svg {
197         font-size: 1.1em;
198         font-weight: 700;
199       }
200     }
201   }
202 </style>