4 changed files with 154 additions and 2 deletions
@ -0,0 +1,137 @@ |
|||
<script setup lang="ts"> |
|||
import type { MenuDto, UserFavoriteMenuDto } from '../../../types'; |
|||
|
|||
import { defineAsyncComponent, ref } from 'vue'; |
|||
|
|||
import { useVbenForm, useVbenModal } from '@vben/common-ui'; |
|||
import { useAppConfig } from '@vben/hooks'; |
|||
import { IconifyIcon } from '@vben/icons'; |
|||
import { $t } from '@vben/locales'; |
|||
|
|||
import { listToTree } from '@abp/core'; |
|||
import { message, TreeSelect } from 'ant-design-vue'; |
|||
|
|||
import { useMyFavoriteMenusApi } from '../../../api/useMyFavoriteMenusApi'; |
|||
import { useMyMenusApi } from '../../../api/useMyMenusApi'; |
|||
|
|||
const emits = defineEmits<{ |
|||
(event: 'change', data: UserFavoriteMenuDto): void; |
|||
}>(); |
|||
|
|||
const ColorPicker = defineAsyncComponent(() => |
|||
import('vue3-colorpicker').then((res) => { |
|||
import('vue3-colorpicker/style.css'); |
|||
return res.ColorPicker; |
|||
}), |
|||
); |
|||
|
|||
const availableMenus = ref<MenuDto[]>([]); |
|||
|
|||
const { getAllApi } = useMyMenusApi(); |
|||
const { createApi } = useMyFavoriteMenusApi(); |
|||
const { uiFramework } = useAppConfig(import.meta.env, import.meta.env.PROD); |
|||
|
|||
const [Form, formApi] = useVbenForm({ |
|||
schema: [ |
|||
{ |
|||
label: $t('workbench.content.favoriteMenu.select'), |
|||
fieldName: 'menuId', |
|||
component: 'TreeSelect', |
|||
rules: 'selectRequired', |
|||
}, |
|||
{ |
|||
label: $t('workbench.content.favoriteMenu.color'), |
|||
fieldName: 'color', |
|||
component: 'ColorPicker', |
|||
defaultValue: '#000000', |
|||
modelPropName: 'pureColor', |
|||
}, |
|||
{ |
|||
label: $t('workbench.content.favoriteMenu.alias'), |
|||
fieldName: 'aliasName', |
|||
component: 'Input', |
|||
}, |
|||
{ |
|||
label: $t('workbench.content.favoriteMenu.icon'), |
|||
fieldName: 'icon', |
|||
component: 'IconPicker', |
|||
}, |
|||
], |
|||
showDefaultActions: false, |
|||
handleSubmit: onSubmit, |
|||
commonConfig: { |
|||
colon: true, |
|||
componentProps: { |
|||
class: 'w-full', |
|||
}, |
|||
}, |
|||
}); |
|||
const [Modal, modalApi] = useVbenModal({ |
|||
async onConfirm() { |
|||
await formApi.validateAndSubmitForm(); |
|||
}, |
|||
async onOpenChange(isOpen) { |
|||
if (isOpen) { |
|||
await onInitMenus(); |
|||
} |
|||
}, |
|||
}); |
|||
|
|||
async function onInitMenus() { |
|||
const { items } = await getAllApi({ |
|||
framework: uiFramework, |
|||
}); |
|||
const menus = listToTree<MenuDto>(items, { id: 'id', pid: 'parentId' }); |
|||
availableMenus.value = menus; |
|||
} |
|||
|
|||
async function onSubmit(values: Record<string, any>) { |
|||
try { |
|||
modalApi.setState({ submitting: true }); |
|||
const menuDto = await createApi({ |
|||
framework: uiFramework, |
|||
menuId: values.menuId, |
|||
color: values.color, |
|||
icon: values.icon, |
|||
aliasName: values.aliasName, |
|||
}); |
|||
message.success($t('AbpUi.SavedSuccessfully')); |
|||
emits('change', menuDto); |
|||
modalApi.close(); |
|||
} finally { |
|||
modalApi.setState({ submitting: false }); |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<template> |
|||
<Modal :title="$t('workbench.content.favoriteMenu.manage')"> |
|||
<Form> |
|||
<template #color="slotProps"> |
|||
<div class="flex flex-row items-center"> |
|||
<ColorPicker v-bind="slotProps" format="hex" /> |
|||
<span>({{ slotProps.value }})</span> |
|||
</div> |
|||
</template> |
|||
<template #menuId="slotProps"> |
|||
<TreeSelect |
|||
allow-clear |
|||
class="w-full" |
|||
tree-icon |
|||
v-bind="slotProps" |
|||
:field-names="{ label: 'displayName', value: 'id' }" |
|||
:tree-data="availableMenus" |
|||
> |
|||
<template #title="item"> |
|||
<div class="flex flex-row items-center gap-1"> |
|||
<IconifyIcon v-if="item.meta?.icon" :icon="item.meta.icon" /> |
|||
<span>{{ item.displayName }}</span> |
|||
</div> |
|||
</template> |
|||
</TreeSelect> |
|||
</template> |
|||
</Form> |
|||
</Modal> |
|||
</template> |
|||
|
|||
<style scoped></style> |
|||
Loading…
Reference in new issue