Commit e4c198a74bff60c220669670f8cf7edbe480c9c6

Authored by ww
1 parent 780254b8

feat: add AuthDropDown component usage more action drowdown menu

1 -<script lang="ts" setup></script> 1 +<script lang="ts" setup>
  2 + import { Dropdown, Menu, Popconfirm } from 'ant-design-vue';
  3 + import { computed, useSlots } from 'vue';
  4 + import Icon from '../Icon';
  5 + import { usePermission } from '/@/hooks/web/usePermission';
2 6
3 -<template> <div></div></template> 7 + export interface AuthDropDownProps {
  8 + dropMenuList: AuthDropMenuList[];
  9 + trigger?: ('contextmenu' | 'click' | 'hover')[];
  10 + }
  11 +
  12 + export interface AuthDropMenuList {
  13 + icon?: string;
  14 + event: string | number;
  15 + text: string;
  16 + disabled?: boolean;
  17 + divider?: boolean;
  18 + auth?: string;
  19 + onClick?: Fn;
  20 + popconfirm?: {
  21 + cancelText?: string;
  22 + okText?: string;
  23 + okType?: string;
  24 + title?: string;
  25 + icon?: string;
  26 + disabled?: boolean;
  27 + onCancel?: Fn;
  28 + onConfirm?: Fn;
  29 + onVisibleChange?: Fn;
  30 + };
  31 + }
  32 +
  33 + const props = defineProps<AuthDropDownProps>();
  34 +
  35 + const slot = useSlots();
  36 +
  37 + const { hasPermission } = usePermission();
  38 +
  39 + const getMenuList = computed(() => {
  40 + const { dropMenuList } = props;
  41 + return dropMenuList.filter((menu) => (menu.auth ? hasPermission(menu.auth) : true));
  42 + });
  43 +
  44 + const hasDefaultSlot = computed(() => {
  45 + return !!slot.default;
  46 + });
  47 +</script>
  48 +
  49 +<template>
  50 + <Dropdown :trigger="$props.trigger">
  51 + <template #overlay>
  52 + <Menu v-if="getMenuList.length">
  53 + <template v-for="item in getMenuList" :key="item.event">
  54 + <Menu.Divider v-if="item.divider" />
  55 + <Menu.Item v-if="!item.popconfirm" @click="item.onClick">
  56 + <span class="flex justify-center items-center">
  57 + <Icon :icon="item.icon" />
  58 + <span class="ml-2">{{ item.text }}</span>
  59 + </span>
  60 + </Menu.Item>
  61 + <Menu.Item v-if="item.popconfirm">
  62 + <Popconfirm v-bind="item.popconfirm">
  63 + <template v-if="item.popconfirm.icon" #icon>
  64 + <Icon :icon="item.popconfirm.icon" />
  65 + </template>
  66 + <span class="flex justify-center items-center">
  67 + <Icon :icon="item.icon" />
  68 + <span class="ml-2">{{ item.text }}</span>
  69 + </span>
  70 + </Popconfirm>
  71 + </Menu.Item>
  72 + </template>
  73 + </Menu>
  74 + </template>
  75 + <Icon
  76 + v-if="!hasDefaultSlot"
  77 + class="items-center justify-center"
  78 + icon="ant-design:ellipsis-outlined"
  79 + :class="!getMenuList.length ? '!text-gray-200 !cursor-not-allowed' : ''"
  80 + />
  81 + <slot name="default"></slot>
  82 + </Dropdown>
  83 +</template>
1 <script setup lang="ts"> 1 <script setup lang="ts">
2 import { List, Card, Button, PaginationProps, Popover, Slider, Tooltip } from 'ant-design-vue'; 2 import { List, Card, Button, PaginationProps, Popover, Slider, Tooltip } from 'ant-design-vue';
3 - import { ReloadOutlined, AppstoreOutlined, EllipsisOutlined } from '@ant-design/icons-vue'; 3 + import { ReloadOutlined, AppstoreOutlined } from '@ant-design/icons-vue';
4 import { computed, onMounted, reactive, ref, unref } from 'vue'; 4 import { computed, onMounted, reactive, ref, unref } from 'vue';
5 import { OrganizationIdTree, useResetOrganizationTree } from '../../common/organizationIdTree'; 5 import { OrganizationIdTree, useResetOrganizationTree } from '../../common/organizationIdTree';
6 import { 6 import {
@@ -9,7 +9,6 @@ @@ -9,7 +9,6 @@
9 } from '/@/api/configuration/center/configurationCenter'; 9 } from '/@/api/configuration/center/configurationCenter';
10 import { ConfigurationCenterItemsModal } from '/@/api/configuration/center/model/configurationCenterModal'; 10 import { ConfigurationCenterItemsModal } from '/@/api/configuration/center/model/configurationCenterModal';
11 import { PageWrapper } from '/@/components/Page'; 11 import { PageWrapper } from '/@/components/Page';
12 - import { Dropdown } from '/@/components/Dropdown';  
13 import { BasicForm, useForm } from '/@/components/Form'; 12 import { BasicForm, useForm } from '/@/components/Form';
14 import { ConfigurationPermission, searchFormSchema } from './center.data'; 13 import { ConfigurationPermission, searchFormSchema } from './center.data';
15 import { useMessage } from '/@/hooks/web/useMessage'; 14 import { useMessage } from '/@/hooks/web/useMessage';
@@ -17,13 +16,13 @@ @@ -17,13 +16,13 @@
17 import { isDevMode } from '/@/utils/env'; 16 import { isDevMode } from '/@/utils/env';
18 import ConfigurationCenterDrawer from './ConfigurationCenterDrawer.vue'; 17 import ConfigurationCenterDrawer from './ConfigurationCenterDrawer.vue';
19 import { useDrawer } from '/@/components/Drawer'; 18 import { useDrawer } from '/@/components/Drawer';
20 - import { useSyncConfirm } from '/@/hooks/component/useSyncConfirm';  
21 import { getBoundingClientRect } from '/@/utils/domUtils'; 19 import { getBoundingClientRect } from '/@/utils/domUtils';
22 import configurationSrc from '/@/assets/icons/configuration.svg'; 20 import configurationSrc from '/@/assets/icons/configuration.svg';
23 import { cloneDeep } from 'lodash'; 21 import { cloneDeep } from 'lodash';
24 import { usePermission } from '/@/hooks/web/usePermission'; 22 import { usePermission } from '/@/hooks/web/usePermission';
25 import { useGlobSetting } from '/@/hooks/setting'; 23 import { useGlobSetting } from '/@/hooks/setting';
26 import { AuthIcon } from '/@/components/Widget'; 24 import { AuthIcon } from '/@/components/Widget';
  25 + import AuthDropDown from '/@/components/Widget/AuthDropDown.vue';
27 26
28 const listColumn = ref(5); 27 const listColumn = ref(5);
29 28
@@ -131,10 +130,8 @@ @@ -131,10 +130,8 @@
131 window.open(`${configurationPrefix}/${isDev ? '?dev=1&' : '?'}configurationId=${record!.id}`); 130 window.open(`${configurationPrefix}/${isDev ? '?dev=1&' : '?'}configurationId=${record!.id}`);
132 }; 131 };
133 132
134 - const { createSyncConfirm } = useSyncConfirm();  
135 const handleDelete = async (record: ConfigurationCenterItemsModal) => { 133 const handleDelete = async (record: ConfigurationCenterItemsModal) => {
136 try { 134 try {
137 - await createSyncConfirm({ iconType: 'warning', content: '是否确认删除操作?' });  
138 await deleteConfigurationCenter([record.id]); 135 await deleteConfigurationCenter([record.id]);
139 createMessage.success('删除成功'); 136 createMessage.success('删除成功');
140 await getListData(); 137 await getListData();
@@ -237,7 +234,29 @@ @@ -237,7 +234,29 @@
237 @click="handleDesign(item)" 234 @click="handleDesign(item)"
238 /> 235 />
239 </Tooltip> 236 </Tooltip>
240 - <Dropdown 237 + <AuthDropDown
  238 + :dropMenuList="[
  239 + {
  240 + text: '编辑',
  241 + auth: ConfigurationPermission.UPDATE,
  242 + icon: 'clarity:note-edit-line',
  243 + event: '',
  244 + onClick: handleCreateOrUpdate.bind(null, item),
  245 + },
  246 + {
  247 + text: '删除',
  248 + auth: ConfigurationPermission.DELETE,
  249 + icon: 'ant-design:delete-outlined',
  250 + event: '',
  251 + popconfirm: {
  252 + title: '是否确认删除操作?',
  253 + onConfirm: handleDelete.bind(null, item),
  254 + },
  255 + },
  256 + ]"
  257 + :trigger="['hover']"
  258 + />
  259 + <!-- <Dropdown
241 :dropMenuList="[ 260 :dropMenuList="[
242 { 261 {
243 text: '编辑', 262 text: '编辑',
@@ -258,7 +277,7 @@ @@ -258,7 +277,7 @@
258 :trigger="['hover']" 277 :trigger="['hover']"
259 > 278 >
260 <EllipsisOutlined key="ellipsis" /> 279 <EllipsisOutlined key="ellipsis" />
261 - </Dropdown> 280 + </Dropdown> -->
262 </template> 281 </template>
263 <Card.Meta> 282 <Card.Meta>
264 <template #title> 283 <template #title>
@@ -2,7 +2,7 @@ @@ -2,7 +2,7 @@
2 import { PageWrapper } from '/@/components/Page'; 2 import { PageWrapper } from '/@/components/Page';
3 import { BasicForm, useForm } from '/@/components/Form'; 3 import { BasicForm, useForm } from '/@/components/Form';
4 import { List, Button, Tooltip, Card, PaginationProps, Image } from 'ant-design-vue'; 4 import { List, Button, Tooltip, Card, PaginationProps, Image } from 'ant-design-vue';
5 - import { ReloadOutlined, MoreOutlined } from '@ant-design/icons-vue'; 5 + import { ReloadOutlined } from '@ant-design/icons-vue';
6 import { computed, onMounted, reactive, ref, unref } from 'vue'; 6 import { computed, onMounted, reactive, ref, unref } from 'vue';
7 import { 7 import {
8 AuthIcon, 8 AuthIcon,
@@ -17,7 +17,6 @@ @@ -17,7 +17,6 @@
17 setDeviceProfileIsDefaultApi, 17 setDeviceProfileIsDefaultApi,
18 } from '/@/api/device/deviceConfigApi'; 18 } from '/@/api/device/deviceConfigApi';
19 import { ProfileRecord } from '/@/api/device/model/deviceConfigModel'; 19 import { ProfileRecord } from '/@/api/device/model/deviceConfigModel';
20 - import { Dropdown } from '/@/components/Dropdown';  
21 import { 20 import {
22 defaultObj, 21 defaultObj,
23 searchFormSchema, 22 searchFormSchema,
@@ -25,14 +24,13 @@ @@ -25,14 +24,13 @@
25 ProductPermission, 24 ProductPermission,
26 } from './device.profile.data'; 25 } from './device.profile.data';
27 import { useMessage } from '/@/hooks/web/useMessage'; 26 import { useMessage } from '/@/hooks/web/useMessage';
28 - import { useSyncConfirm } from '/@/hooks/component/useSyncConfirm';  
29 import DeviceProfileModal from './DeviceProfileModal.vue'; 27 import DeviceProfileModal from './DeviceProfileModal.vue';
30 import DeviceProfileDrawer from './DeviceProfileDrawer.vue'; 28 import DeviceProfileDrawer from './DeviceProfileDrawer.vue';
31 import { useModal } from '/@/components/Modal'; 29 import { useModal } from '/@/components/Modal';
32 import { useDrawer } from '/@/components/Drawer'; 30 import { useDrawer } from '/@/components/Drawer';
33 import productDefault from '/@/assets/icons/product-default.svg'; 31 import productDefault from '/@/assets/icons/product-default.svg';
34 - import { usePermission } from '/@/hooks/web/usePermission';  
35 import { useRoute } from 'vue-router'; 32 import { useRoute } from 'vue-router';
  33 + import AuthDropDown from '/@/components/Widget/AuthDropDown.vue';
36 34
37 defineProps<{ 35 defineProps<{
38 mode: EnumTableCardMode; 36 mode: EnumTableCardMode;
@@ -47,7 +45,6 @@ @@ -47,7 +45,6 @@
47 const IMAGE_FALLBACK = productDefault; 45 const IMAGE_FALLBACK = productDefault;
48 46
49 const { createMessage } = useMessage(); 47 const { createMessage } = useMessage();
50 - const { createSyncConfirm } = useSyncConfirm();  
51 48
52 const [register, { getFieldsValue, setFieldsValue }] = useForm({ 49 const [register, { getFieldsValue, setFieldsValue }] = useForm({
53 showAdvancedButton: true, 50 showAdvancedButton: true,
@@ -110,32 +107,6 @@ @@ -110,32 +107,6 @@
110 } 107 }
111 }; 108 };
112 109
113 - const { hasPermission } = usePermission();  
114 -  
115 - const getHasDeleteFlag = computed(() => {  
116 - return hasPermission(ProductPermission.DELETE);  
117 - });  
118 -  
119 - const getDropDownList = (record: ProfileRecord) => {  
120 - const list = [  
121 - {  
122 - text: '默认',  
123 - event: DropMenuEvent.SET_DEFAULT,  
124 - icon: 'ant-design:unordered-list-outlined',  
125 - onClick: handleSetDefault.bind(null, record),  
126 - },  
127 - ];  
128 - if (unref(getHasDeleteFlag)) {  
129 - list.push({  
130 - text: '删除',  
131 - event: DropMenuEvent.DELETE,  
132 - icon: 'ant-design:delete-outlined',  
133 - onClick: handleDelete.bind(null, [record.id]),  
134 - });  
135 - }  
136 - return list;  
137 - };  
138 -  
139 const handleModeChange = (mode: EnumTableCardMode) => { 110 const handleModeChange = (mode: EnumTableCardMode) => {
140 emit('changeMode', mode); 111 emit('changeMode', mode);
141 }; 112 };
@@ -172,7 +143,6 @@ @@ -172,7 +143,6 @@
172 143
173 const handleDelete = async (id: string[]) => { 144 const handleDelete = async (id: string[]) => {
174 try { 145 try {
175 - await createSyncConfirm({ iconType: 'warning', content: '是否确认删除操作?' });  
176 await deviceConfigDelete(id); 146 await deviceConfigDelete(id);
177 createMessage.success('删除成功'); 147 createMessage.success('删除成功');
178 await getDataSource(); 148 await getDataSource();
@@ -278,9 +248,28 @@ @@ -278,9 +248,28 @@
278 @click.stop="handleUpdate(item)" 248 @click.stop="handleUpdate(item)"
279 /> 249 />
280 </Tooltip> 250 </Tooltip>
281 - <Dropdown :trigger="['hover']" :drop-menu-list="getDropDownList(item)">  
282 - <MoreOutlined @click.stop class="transform rotate-90" />  
283 - </Dropdown> 251 + <AuthDropDown
  252 + @click.stop
  253 + :trigger="['hover']"
  254 + :drop-menu-list="[
  255 + {
  256 + text: '默认',
  257 + event: DropMenuEvent.SET_DEFAULT,
  258 + icon: 'ant-design:unordered-list-outlined',
  259 + onClick: handleSetDefault.bind(null, item),
  260 + },
  261 + {
  262 + text: '删除',
  263 + event: DropMenuEvent.DELETE,
  264 + auth: ProductPermission.DELETE,
  265 + icon: 'ant-design:delete-outlined',
  266 + popconfirm: {
  267 + title: '是否确认删除操作?',
  268 + onConfirm: handleDelete.bind(null, [item.id]),
  269 + },
  270 + },
  271 + ]"
  272 + />
284 </template> 273 </template>
285 <Card.Meta> 274 <Card.Meta>
286 <template #title> 275 <template #title>