123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297 |
- <script setup lang="tsx">
- import { nextTick, ref } from 'vue';
- import { NButton, NPopconfirm, NTag } from 'naive-ui';
- import type { InternalRowData } from 'naive-ui/es/data-table/src/interface';
- import { yesOrNoRecord } from '@/constants/common';
- import { menuTypeRecord } from '@/constants/business';
- import { fetchAddMenu, fetchDelMenu, fetchEditMenu, fetchGetMenuList } from '@/service/api';
- import { useAppStore } from '@/store/modules/app';
- import { buildMenuTree } from '@/utils/zt';
- import { $t } from '@/locales';
- import SvgIcon from '@/components/custom/svg-icon.vue';
- import { useForm } from '@/components/zt/Form/hooks/useForm';
- import { type OperateType } from './modules/menu-operate-modal.vue';
- import { formSchems } from './modules/shared';
- const appStore = useAppStore();
- const checkedRowKeys = ref([]);
- const wrapperRef = ref<HTMLElement | null>(null);
- const menusData = ref([]);
- const loading = ref(false);
- const showModal = ref(false);
- const formLoading = ref(false);
- const [registerForm, { setFieldsValue, validate, getFieldsValue, updateSchema }] = useForm({
- schemas: formSchems,
- showSubmitButton: false,
- showAdvancedButton: false,
- showResetButton: false,
- labelWidth: 120,
- showActionButtonGroup: false,
- layout: 'horizontal',
- gridProps: {
- cols: '1 xl:4 s:1 l:3',
- itemResponsive: true
- },
- collapsedRows: 1
- });
- const colums: NaiveUI.TableColumn<InternalRowData>[] = [
- {
- type: 'selection',
- align: 'center',
- width: 48
- },
- {
- key: 'id',
- title: $t('page.manage.menu.id'),
- align: 'center'
- },
- {
- key: 'type',
- title: $t('page.manage.menu.menuType'),
- align: 'center',
- width: 80,
- render: (row: InternalRowData) => {
- const tagMap: Record<Api.SystemManage.MenuType, NaiveUI.ThemeColor> = {
- 0: 'default',
- 1: 'primary',
- 2: 'error'
- };
- const type = row.type as keyof typeof menuTypeRecord;
- const label = $t(menuTypeRecord[type]);
- return <NTag type={tagMap[type]}>{label}</NTag>;
- }
- },
- {
- key: 'name',
- title: $t('page.manage.menu.menuName'),
- align: 'center',
- minWidth: 120,
- render: (row: InternalRowData) => {
- return <span>{row.name}</span>;
- }
- },
- {
- key: 'icon',
- title: $t('page.manage.menu.icon'),
- align: 'center',
- width: 60,
- render: (row: InternalRowData) => {
- return (
- <div class="flex-center">
- <SvgIcon icon={String(row.icon)} class="text-icon" />
- </div>
- );
- }
- },
- {
- key: 'routeName',
- title: $t('page.manage.menu.routeName'),
- align: 'center',
- minWidth: 120
- },
- {
- key: 'url',
- title: $t('page.manage.menu.routePath'),
- align: 'center',
- minWidth: 120
- },
- {
- key: 'hideInMenu',
- title: $t('page.manage.menu.hideInMenu'),
- align: 'center',
- width: 80,
- render: (row: InternalRowData) => {
- const hide: CommonType.YesOrNo = row.hideInMenu ? 'Y' : 'N';
- const tagMap: Record<CommonType.YesOrNo, NaiveUI.ThemeColor> = {
- Y: 'error',
- N: 'default'
- };
- const label = $t(yesOrNoRecord[hide]);
- return <NTag type={tagMap[hide]}>{label}</NTag>;
- }
- },
- {
- key: 'parentId',
- title: $t('page.manage.menu.parentId'),
- width: 90,
- align: 'center'
- },
- {
- key: 'order',
- title: $t('page.manage.menu.order'),
- align: 'center',
- width: 60
- },
- {
- key: 'operate',
- title: $t('common.operate'),
- align: 'center',
- width: 230,
- fixed: 'right',
- render: (row: any) => (
- <div class="flex-center justify-end gap-8px">
- {row.type == '0' && (
- <NButton type="primary" ghost size="small" onClick={() => handleAddChildMenu(row)}>
- {$t('page.manage.menu.addChildMenu')}
- </NButton>
- )}
- <NButton type="primary" ghost size="small" onClick={() => handleEdit(row)}>
- {$t('common.edit')}
- </NButton>
- <NPopconfirm onPositiveClick={() => handleDelete(row.menuId)}>
- {{
- default: () => $t('common.confirmDelete'),
- trigger: () => (
- <NButton type="error" ghost size="small" loading={formLoading.value}>
- {$t('common.delete')}
- </NButton>
- )
- }}
- </NPopconfirm>
- </div>
- )
- }
- ];
- // const { checkedRowKeys, onBatchDeleted, onDeleted } = useTableOperate(data, 'id', getData);
- const operateType = ref<OperateType>('add');
- function handleAdd() {
- operateType.value = 'add';
- showModal.value = true;
- }
- async function handleBatchDelete() {
- // request
- console.log(checkedRowKeys.value);
- }
- async function handleDelete(id: number) {
- // request
- console.log(id);
- formLoading.value = true;
- await fetchDelMenu(id);
- init();
- formLoading.value = false;
- }
- function handleEdit(item: Api.SystemManage.Menu) {
- showModal.value = true;
- operateType.value = 'edit';
- nextTick(async () => {
- await setFieldsValue(item);
- updateSchema([{ field: 'type', componentProps: { disabled: true } }]);
- });
- }
- function handleAddChildMenu(item: any) {
- operateType.value = 'addChild';
- showModal.value = true;
- nextTick(() => {
- setFieldsValue({ parentId: item.menuId, url: item.url });
- });
- }
- async function getAllPages() {
- const { data } = await fetchGetMenuList();
- const menuData = buildMenuTree(data);
- menusData.value = menuData;
- }
- function init() {
- getAllPages();
- }
- // init
- init();
- async function handleSubmit() {
- await validate();
- formLoading.value = true;
- const form = getFieldsValue();
- if (operateType.value == 'add' || operateType.value == 'addChild') {
- await fetchAddMenu(form as Api.SystemManage.AddMenu);
- formLoading.value = false;
- showModal.value = false;
- init();
- } else {
- await fetchEditMenu(form as Api.SystemManage.AddMenu);
- formLoading.value = false;
- showModal.value = false;
- init();
- }
- }
- </script>
- <template>
- <div ref="wrapperRef" class="flex-col-stretch gap-16px overflow-hidden lt-sm:overflow-auto">
- <NCard :title="$t('page.manage.menu.title')" :bordered="false" size="small" class="card-wrapper sm:flex-1-hidden">
- <template #header-extra>
- <TableHeaderOperation
- :disabled-delete="checkedRowKeys.length === 0"
- :loading="loading"
- is-add
- @add="handleAdd"
- @delete="handleBatchDelete"
- @refresh="init"
- />
- </template>
- <NDataTable
- v-model:checked-row-keys="checkedRowKeys"
- :columns="colums"
- :data="menusData"
- size="small"
- :flex-height="!appStore.isMobile"
- :scroll-x="1088"
- :loading="loading"
- :row-key="row => row.menuId"
- remote
- class="sm:h-full"
- />
- <!--
- <MenuOperateModal
- v-model:visible="visible"
- :operate-type="operateType"
- :row-data="editingData"
- :all-pages="allPages"
- />
- -->
- <NModal v-model:show="showModal">
- <NCard class="w-800px">
- <template #header>
- <div>
- {{ operateType == 'add' ? '新增菜单' : operateType == 'addChild' ? '新增子菜单' : ' 编辑菜单' }}
- </div>
- </template>
- <BasicForm @register-form="registerForm">
- <template #parentId="{ model, field }">
- <NTreeSelect
- v-model:value="model[field]"
- :options="menusData"
- label-field="name"
- key-field="menuId"
- ></NTreeSelect>
- </template>
- </BasicForm>
- <template #footer>
- <div class="flex justify-end">
- <NButton class="mr-3" @click="showModal = false">取消</NButton>
- <NButton type="primary" :loading="formLoading" @click="handleSubmit">确定</NButton>
- </div>
- </template>
- </NCard>
- </NModal>
- </NCard>
- </div>
- </template>
- <style scoped></style>
|