Commit e4c198a74bff60c220669670f8cf7edbe480c9c6
1 parent
780254b8
feat: add AuthDropDown component usage more action drowdown menu
Showing
3 changed files
with
132 additions
and
44 deletions
| 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> |