feat: 添加权限配置页面
This commit is contained in:
@@ -1,3 +1,4 @@
|
|||||||
export * from './device';
|
export * from './device';
|
||||||
export * from './global';
|
export * from './global';
|
||||||
|
export * from './permission';
|
||||||
export * from './station';
|
export * from './station';
|
||||||
|
|||||||
1
src/components/permission/index.ts
Normal file
1
src/components/permission/index.ts
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export * from './permission-config-modal';
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
import type { ComponentInstance } from 'vue';
|
||||||
|
import PermissionConfigModal from './permission-config-modal.vue';
|
||||||
|
|
||||||
|
export type PermissionConfigModalProps = ComponentInstance<typeof PermissionConfigModal>['$props'];
|
||||||
|
|
||||||
|
export { PermissionConfigModal };
|
||||||
@@ -0,0 +1,263 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import {
|
||||||
|
deletePermissionApi,
|
||||||
|
detailBaseEmployeeApi,
|
||||||
|
pagePermissionApi,
|
||||||
|
savePermissionApi,
|
||||||
|
type BaseEmployeeResultVO,
|
||||||
|
type NdmPermissionResultVO,
|
||||||
|
type NdmPermissionSaveVO,
|
||||||
|
type Station,
|
||||||
|
} from '@/apis';
|
||||||
|
import { PERMISSION_TYPE_NAMES, type PermissionType } from '@/enums';
|
||||||
|
import { useStationStore } from '@/stores';
|
||||||
|
import { parseErrorFeedback } from '@/utils';
|
||||||
|
import { useMutation } from '@tanstack/vue-query';
|
||||||
|
import { objectEntries } from '@vueuse/core';
|
||||||
|
import { isCancel } from 'axios';
|
||||||
|
import { cloneDeep, groupBy } from 'es-toolkit';
|
||||||
|
import { NButton, NCheckbox, NDataTable, NFlex, NModal, NText, type DataTableColumn, type DataTableColumns } from 'naive-ui';
|
||||||
|
import { storeToRefs } from 'pinia';
|
||||||
|
import { computed, h, ref, toRefs } from 'vue';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 为避免修改权限记录而带来复杂的状态管理,引入 `action` 字段
|
||||||
|
*
|
||||||
|
* - `save`:新增权限
|
||||||
|
* - `delete`:删除权限
|
||||||
|
*
|
||||||
|
* 修改权限的过程中会对本地的权限列表进行修改:
|
||||||
|
* - 当勾选权限时,在本地新增一条权限,`action` 为 `save`
|
||||||
|
* - 当取消勾选权限时,如果该权限来自服务器,则将`action` 改为 `delete`,否则直接删除权限记录
|
||||||
|
*
|
||||||
|
* 最后,保存权限时,只需要遍历本地权限列表:
|
||||||
|
* - 如果 `action` 为 `save`,则调用 `savePermissionApi` 新增权限
|
||||||
|
* - 如果 `action` 为 `delete`,则调用 `deletePermissionApi` 删除权限
|
||||||
|
*/
|
||||||
|
type PermissionAction = 'save' | 'delete';
|
||||||
|
|
||||||
|
type NdmPermissionSaveOrResultVO = NdmPermissionSaveVO | NdmPermissionResultVO;
|
||||||
|
|
||||||
|
type NdmPermissionExtendedSaveVO = NdmPermissionSaveVO & { action?: PermissionAction };
|
||||||
|
|
||||||
|
type NdmPermissionExtendedResultVO = NdmPermissionResultVO & { action?: PermissionAction };
|
||||||
|
|
||||||
|
type NdmPermissionExtendedSaveOrResultVO = NdmPermissionExtendedSaveVO | NdmPermissionExtendedResultVO;
|
||||||
|
|
||||||
|
const omitActionField = (extendedSaveOrResultVO: NdmPermissionExtendedSaveOrResultVO) => {
|
||||||
|
const copy = cloneDeep(extendedSaveOrResultVO);
|
||||||
|
delete copy.action;
|
||||||
|
const saveOrResultVO = copy as NdmPermissionSaveOrResultVO;
|
||||||
|
return saveOrResultVO;
|
||||||
|
};
|
||||||
|
|
||||||
|
const isSaveVO = (saveOrResultVO: NdmPermissionSaveOrResultVO): saveOrResultVO is NdmPermissionSaveVO => {
|
||||||
|
return !('id' in saveOrResultVO);
|
||||||
|
};
|
||||||
|
|
||||||
|
const isResultVO = (saveOrResultVO: NdmPermissionSaveOrResultVO): saveOrResultVO is NdmPermissionResultVO => {
|
||||||
|
return 'id' in saveOrResultVO;
|
||||||
|
};
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
employeeId?: string;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const stationStore = useStationStore();
|
||||||
|
const { stations } = storeToRefs(stationStore);
|
||||||
|
|
||||||
|
const show = defineModel<boolean>('show', { default: false });
|
||||||
|
|
||||||
|
const { employeeId } = toRefs(props);
|
||||||
|
|
||||||
|
const abortController = ref<AbortController>(new AbortController());
|
||||||
|
|
||||||
|
const employee = ref<BaseEmployeeResultVO>();
|
||||||
|
const { mutateAsync: getEmployeeAsync } = useMutation({
|
||||||
|
mutationFn: async () => {
|
||||||
|
abortController.value.abort();
|
||||||
|
abortController.value = new AbortController();
|
||||||
|
|
||||||
|
if (!employeeId.value) return;
|
||||||
|
|
||||||
|
const signal = abortController.value.signal;
|
||||||
|
|
||||||
|
const data = await detailBaseEmployeeApi(employeeId.value, { signal });
|
||||||
|
return data;
|
||||||
|
},
|
||||||
|
onSuccess: (data) => {
|
||||||
|
if (!data) return;
|
||||||
|
employee.value = data;
|
||||||
|
},
|
||||||
|
onError: (error) => {
|
||||||
|
if (isCancel(error)) return;
|
||||||
|
console.error(error);
|
||||||
|
const errorFeedback = parseErrorFeedback(error);
|
||||||
|
window.$message.error(errorFeedback);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const permissions = ref<Record<Station['code'], NdmPermissionExtendedSaveOrResultVO[]>>({});
|
||||||
|
const { mutate: getPermissions, isPending: permissionsLoading } = useMutation({
|
||||||
|
mutationFn: async () => {
|
||||||
|
abortController.value.abort();
|
||||||
|
abortController.value = new AbortController();
|
||||||
|
|
||||||
|
if (!employeeId.value) return;
|
||||||
|
|
||||||
|
const signal = abortController.value.signal;
|
||||||
|
|
||||||
|
const data = await pagePermissionApi(
|
||||||
|
{
|
||||||
|
model: {
|
||||||
|
employeeId: employeeId.value,
|
||||||
|
},
|
||||||
|
extra: {},
|
||||||
|
current: 1,
|
||||||
|
size: Object.keys(PERMISSION_TYPE_NAMES).length * stations.value.length,
|
||||||
|
sort: 'id',
|
||||||
|
order: 'ascending',
|
||||||
|
},
|
||||||
|
{ signal },
|
||||||
|
);
|
||||||
|
|
||||||
|
return data;
|
||||||
|
},
|
||||||
|
onSuccess: (data) => {
|
||||||
|
if (!data) return;
|
||||||
|
const { records } = data;
|
||||||
|
permissions.value = groupBy(records, (record) => record.stationCode ?? '');
|
||||||
|
},
|
||||||
|
onError: (error) => {
|
||||||
|
if (isCancel(error)) return;
|
||||||
|
console.error(error);
|
||||||
|
const errorFeedback = parseErrorFeedback(error);
|
||||||
|
window.$message.error(errorFeedback);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const onUpdatePermissionChecked = (checked: boolean, stationCode: Station['code'], permissionType: PermissionType) => {
|
||||||
|
if (!employeeId.value) return;
|
||||||
|
if (checked) {
|
||||||
|
// 勾选时,新增一条权限记录,`action` 为 `save`
|
||||||
|
if (!permissions.value[stationCode]) permissions.value[stationCode] = [];
|
||||||
|
permissions.value[stationCode].push({ employeeId: employeeId.value, stationCode, type: permissionType, action: 'save' });
|
||||||
|
} else {
|
||||||
|
if (!permissions.value[stationCode]) return;
|
||||||
|
// 取消勾选时,先找到所有该类型的权限并遍历,
|
||||||
|
// 如果权限来自数据库(即有 `id` 字段),则将其 `action` 设为 `delete`,
|
||||||
|
// 否则直接从权限记录中移除
|
||||||
|
const targets = permissions.value[stationCode].filter((permission) => permission.type === permissionType);
|
||||||
|
for (const permission of targets) {
|
||||||
|
if (isResultVO(permission)) {
|
||||||
|
permission.action = 'delete';
|
||||||
|
} else {
|
||||||
|
permissions.value[stationCode].splice(permissions.value[stationCode].indexOf(permission), 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const tableColumns = computed<DataTableColumns<Station>>(() => {
|
||||||
|
return [
|
||||||
|
{ title: '车站编号', key: 'code', align: 'center', width: 120 },
|
||||||
|
{ title: '车站名称', key: 'name', align: 'center', width: 360 },
|
||||||
|
// 「权限」列
|
||||||
|
...objectEntries(PERMISSION_TYPE_NAMES).map<DataTableColumn<Station>>(([permissionType, title]) => ({
|
||||||
|
title: title,
|
||||||
|
key: permissionType,
|
||||||
|
align: 'center',
|
||||||
|
render: (rowData) => {
|
||||||
|
const { code: stationCode } = rowData;
|
||||||
|
return h(NCheckbox, {
|
||||||
|
// 如果权限记录中存在该权限且 `action` 不为 `delete`,则处于勾选状态
|
||||||
|
checked: !!(permissions.value[stationCode] ?? []).find((permission) => permission.type === permissionType && permission.action !== 'delete'),
|
||||||
|
// 改变勾选状态
|
||||||
|
onUpdateChecked: (checked) => onUpdatePermissionChecked(checked, stationCode, permissionType),
|
||||||
|
});
|
||||||
|
},
|
||||||
|
})),
|
||||||
|
];
|
||||||
|
});
|
||||||
|
|
||||||
|
const { mutate: savePermissions, isPending: permissionsSaving } = useMutation({
|
||||||
|
mutationFn: async () => {
|
||||||
|
abortController.value.abort();
|
||||||
|
abortController.value = new AbortController();
|
||||||
|
|
||||||
|
const signal = abortController.value.signal;
|
||||||
|
|
||||||
|
// 遍历所有的权限记录,根据 `action` 进行保存或删除
|
||||||
|
for (const stationPermissions of Object.values(permissions.value)) {
|
||||||
|
for (const permission of stationPermissions) {
|
||||||
|
const saveOrResultVO = omitActionField(permission);
|
||||||
|
if (permission.action === 'save' && isSaveVO(saveOrResultVO)) {
|
||||||
|
await savePermissionApi(saveOrResultVO, { signal });
|
||||||
|
}
|
||||||
|
if (permission.action === 'delete' && isResultVO(saveOrResultVO)) {
|
||||||
|
const id = saveOrResultVO.id;
|
||||||
|
if (!id) continue;
|
||||||
|
await deletePermissionApi([id], { signal });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onSuccess: () => {
|
||||||
|
window.$message.success('权限配置保存成功');
|
||||||
|
getPermissions();
|
||||||
|
},
|
||||||
|
onError: (error) => {
|
||||||
|
if (isCancel(error)) return;
|
||||||
|
console.error(error);
|
||||||
|
const errorFeedback = parseErrorFeedback(error);
|
||||||
|
window.$message.error(errorFeedback);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const onAfterEnter = () => {
|
||||||
|
getEmployeeAsync().then(() => getPermissions());
|
||||||
|
};
|
||||||
|
|
||||||
|
const onAfterLeave = () => {
|
||||||
|
employee.value = undefined;
|
||||||
|
permissions.value = {};
|
||||||
|
};
|
||||||
|
|
||||||
|
const onClose = () => {
|
||||||
|
abortController.value.abort();
|
||||||
|
show.value = false;
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<NModal
|
||||||
|
v-model:show="show"
|
||||||
|
preset="card"
|
||||||
|
style="width: 100vw; height: 100vh"
|
||||||
|
:content-style="{ height: '100%', overflow: 'hidden' }"
|
||||||
|
:close-on-esc="false"
|
||||||
|
:mask-closable="false"
|
||||||
|
:auto-focus="false"
|
||||||
|
@after-enter="onAfterEnter"
|
||||||
|
@after-leave="onAfterLeave"
|
||||||
|
@close="onClose"
|
||||||
|
>
|
||||||
|
<template #header>
|
||||||
|
<span>{{ `配置权限 - ${employee?.realName ?? ''}` }}</span>
|
||||||
|
</template>
|
||||||
|
<template #default>
|
||||||
|
<NDataTable flex-height style="height: 100%" :columns="tableColumns" :data="stations" :loading="permissionsLoading" :single-line="false" />
|
||||||
|
</template>
|
||||||
|
<template #footer>
|
||||||
|
<NText depth="3" style="font-size: smaller">*未勾选任何权限的用户将被认为拥有所有权限</NText>
|
||||||
|
</template>
|
||||||
|
<template #action>
|
||||||
|
<NFlex justify="end">
|
||||||
|
<NButton size="small" @click="onClose">取消</NButton>
|
||||||
|
<NButton type="primary" size="small" :loading="permissionsSaving" @click="() => savePermissions()">保存</NButton>
|
||||||
|
</NFlex>
|
||||||
|
</template>
|
||||||
|
</NModal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped lang="scss"></style>
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
export * from './alarm-type';
|
export * from './alarm-type';
|
||||||
export * from './device-type';
|
export * from './device-type';
|
||||||
export * from './fault-level';
|
export * from './fault-level';
|
||||||
|
export * from './permission-type';
|
||||||
|
|||||||
13
src/enums/permission-type.ts
Normal file
13
src/enums/permission-type.ts
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
export const PERMISSION_TYPE_LITERALS = {
|
||||||
|
VIEW: 'VIEW',
|
||||||
|
OPERATION: 'OPERATION',
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
export type PermissionType = keyof typeof PERMISSION_TYPE_LITERALS;
|
||||||
|
|
||||||
|
export const PERMISSION_TYPE_NAMES = {
|
||||||
|
[PERMISSION_TYPE_LITERALS.VIEW]: '查看',
|
||||||
|
[PERMISSION_TYPE_LITERALS.OPERATION]: '操作',
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
export type PermissionTypeEnum = typeof PERMISSION_TYPE_NAMES;
|
||||||
@@ -6,7 +6,7 @@ import { useAlarmStore, useSettingStore, useUserStore } from '@/stores';
|
|||||||
import { parseErrorFeedback } from '@/utils';
|
import { parseErrorFeedback } from '@/utils';
|
||||||
import { useIsFetching, useIsMutating, useMutation } from '@tanstack/vue-query';
|
import { useIsFetching, useIsMutating, useMutation } from '@tanstack/vue-query';
|
||||||
import { isCancel } from 'axios';
|
import { isCancel } from 'axios';
|
||||||
import { ChevronDownIcon, ChevronsLeftIcon, ChevronsRightIcon, ComputerIcon, LogOutIcon, LogsIcon, MapPinIcon, SettingsIcon, SirenIcon } from 'lucide-vue-next';
|
import { ChevronDownIcon, ChevronsLeftIcon, ChevronsRightIcon, ComputerIcon, KeyIcon, LogOutIcon, LogsIcon, MapPinIcon, SettingsIcon, SirenIcon } from 'lucide-vue-next';
|
||||||
import {
|
import {
|
||||||
NBadge,
|
NBadge,
|
||||||
NButton,
|
NButton,
|
||||||
@@ -106,6 +106,12 @@ const menuOptions: MenuOption[] = [
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
label: () => h(RouterLink, { to: '/permission' }, { default: () => '权限管理' }),
|
||||||
|
key: '/permission',
|
||||||
|
show: userStore.isLamp,
|
||||||
|
icon: renderIcon(KeyIcon),
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const dropdownOptions: DropdownOption[] = [
|
const dropdownOptions: DropdownOption[] = [
|
||||||
|
|||||||
184
src/pages/permission-page.vue
Normal file
184
src/pages/permission-page.vue
Normal file
@@ -0,0 +1,184 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { pageBaseEmployeeApi, type BaseEmployeePageQuery, type BaseEmployeeResultVO } from '@/apis';
|
||||||
|
import { PermissionConfigModal } from '@/components';
|
||||||
|
import { parseErrorFeedback } from '@/utils';
|
||||||
|
import { useMutation } from '@tanstack/vue-query';
|
||||||
|
import { isCancel } from 'axios';
|
||||||
|
import { KeyIcon } from 'lucide-vue-next';
|
||||||
|
import { NButton, NDataTable, NFlex, NForm, NFormItemGi, NGrid, NGridItem, NInput, type DataTableColumns, type DataTableRowData, type PaginationProps } from 'naive-ui';
|
||||||
|
import { h, onBeforeUnmount, onMounted, reactive, ref, watch } from 'vue';
|
||||||
|
|
||||||
|
interface SearchFields extends BaseEmployeePageQuery {}
|
||||||
|
|
||||||
|
const searchFields = ref<SearchFields>({});
|
||||||
|
const resetSearchFields = () => {
|
||||||
|
searchFields.value = {
|
||||||
|
realName: '',
|
||||||
|
};
|
||||||
|
};
|
||||||
|
const getModelFields = (): BaseEmployeePageQuery => {
|
||||||
|
return {
|
||||||
|
realName: searchFields.value.realName,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const searchFieldsChanged = ref(false);
|
||||||
|
watch(searchFields, () => {
|
||||||
|
searchFieldsChanged.value = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
const showPermissionConfigModal = ref(false);
|
||||||
|
const selectedEmployeeId = ref('');
|
||||||
|
|
||||||
|
const tableColumns: DataTableColumns<BaseEmployeeResultVO> = [
|
||||||
|
{ title: '姓名', key: 'realName', align: 'center' },
|
||||||
|
{ title: '创建时间', key: 'createdTime', align: 'center' },
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
key: 'action',
|
||||||
|
align: 'center',
|
||||||
|
width: 150,
|
||||||
|
render: (rowData) => {
|
||||||
|
return h(
|
||||||
|
NButton,
|
||||||
|
{
|
||||||
|
secondary: true,
|
||||||
|
type: 'info',
|
||||||
|
size: 'small',
|
||||||
|
onClick: () => {
|
||||||
|
const { id } = rowData;
|
||||||
|
if (!id) return;
|
||||||
|
selectedEmployeeId.value = id;
|
||||||
|
showPermissionConfigModal.value = true;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: () => h(KeyIcon),
|
||||||
|
default: () => '配置权限',
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const tableData = ref<DataTableRowData[]>([]);
|
||||||
|
|
||||||
|
const DEFAULT_PAGE_SIZE = 10;
|
||||||
|
const pagination = reactive<PaginationProps>({
|
||||||
|
showSizePicker: true,
|
||||||
|
page: 1,
|
||||||
|
pageSize: DEFAULT_PAGE_SIZE,
|
||||||
|
pageSizes: [5, 10, 20, 50, 80, 100],
|
||||||
|
itemCount: 0,
|
||||||
|
prefix: ({ itemCount }) => {
|
||||||
|
return h('div', {}, { default: () => `共${itemCount}条` });
|
||||||
|
},
|
||||||
|
onUpdatePage: (page: number) => {
|
||||||
|
pagination.page = page;
|
||||||
|
getTableData();
|
||||||
|
},
|
||||||
|
onUpdatePageSize: (pageSize: number) => {
|
||||||
|
pagination.pageSize = pageSize;
|
||||||
|
pagination.page = 1;
|
||||||
|
getTableData();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const abortController = ref(new AbortController());
|
||||||
|
|
||||||
|
const { mutate: getTableData, isPending: tableLoading } = useMutation({
|
||||||
|
mutationFn: async () => {
|
||||||
|
abortController.value.abort();
|
||||||
|
abortController.value = new AbortController();
|
||||||
|
|
||||||
|
const signal = abortController.value.signal;
|
||||||
|
|
||||||
|
const res = await pageBaseEmployeeApi(
|
||||||
|
{
|
||||||
|
model: getModelFields(),
|
||||||
|
extra: {},
|
||||||
|
current: pagination.page ?? 1,
|
||||||
|
size: pagination.pageSize ?? DEFAULT_PAGE_SIZE,
|
||||||
|
order: 'descending',
|
||||||
|
sort: 'id',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
signal,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
return res;
|
||||||
|
},
|
||||||
|
onSuccess: (res) => {
|
||||||
|
const { records, size, total } = res;
|
||||||
|
pagination.pageSize = parseInt(size);
|
||||||
|
pagination.itemCount = parseInt(total);
|
||||||
|
tableData.value = records;
|
||||||
|
},
|
||||||
|
onError: (error) => {
|
||||||
|
if (isCancel(error)) return;
|
||||||
|
console.error(error);
|
||||||
|
const errorFeedback = parseErrorFeedback(error);
|
||||||
|
window.$message.error(errorFeedback);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const onClickReset = () => {
|
||||||
|
resetSearchFields();
|
||||||
|
pagination.page = 1;
|
||||||
|
pagination.pageSize = DEFAULT_PAGE_SIZE;
|
||||||
|
pagination.itemCount = 0;
|
||||||
|
getTableData();
|
||||||
|
};
|
||||||
|
const onClickQuery = () => {
|
||||||
|
if (searchFieldsChanged.value) {
|
||||||
|
pagination.page = 1;
|
||||||
|
pagination.pageSize = DEFAULT_PAGE_SIZE;
|
||||||
|
searchFieldsChanged.value = false;
|
||||||
|
}
|
||||||
|
getTableData();
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
getTableData();
|
||||||
|
});
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
abortController.value.abort();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<NFlex vertical :size="0" style="height: 100%">
|
||||||
|
<!-- 查询面板 -->
|
||||||
|
<NForm style="flex: 0 0 auto; padding: 8px">
|
||||||
|
<NGrid cols="3" :x-gap="24">
|
||||||
|
<NFormItemGi span="1" label="姓名" label-placement="left">
|
||||||
|
<NInput v-model:value="searchFields.realName" />
|
||||||
|
</NFormItemGi>
|
||||||
|
</NGrid>
|
||||||
|
<!-- 操作按钮 -->
|
||||||
|
<NGrid :cols="1">
|
||||||
|
<NGridItem>
|
||||||
|
<NFlex>
|
||||||
|
<NButton @click="onClickReset">重置</NButton>
|
||||||
|
<NButton type="primary" :loading="tableLoading" @click="onClickQuery">查询</NButton>
|
||||||
|
</NFlex>
|
||||||
|
</NGridItem>
|
||||||
|
</NGrid>
|
||||||
|
</NForm>
|
||||||
|
|
||||||
|
<!-- 数据表格工具栏 -->
|
||||||
|
<NFlex align="center" style="padding: 8px; flex: 0 0 auto">
|
||||||
|
<div style="font-size: medium">用户权限列表</div>
|
||||||
|
<NFlex style="margin-left: auto">
|
||||||
|
<!-- <NButton type="primary" :loading="exporting" @click="() => exportTableData()">导出</NButton> -->
|
||||||
|
</NFlex>
|
||||||
|
</NFlex>
|
||||||
|
|
||||||
|
<!-- 数据表格 -->
|
||||||
|
<NDataTable remote :columns="tableColumns" :data="tableData" :pagination="pagination" :loading="tableLoading" :single-line="false" flex-height style="height: 100%; padding: 8px; flex: 1 1 auto" />
|
||||||
|
</NFlex>
|
||||||
|
|
||||||
|
<PermissionConfigModal v-model:show="showPermissionConfigModal" :employee-id="selectedEmployeeId" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped lang="scss"></style>
|
||||||
@@ -47,6 +47,15 @@ const router = createRouter({
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'permission',
|
||||||
|
component: () => import('@/pages/permission-page.vue'),
|
||||||
|
beforeEnter: () => {
|
||||||
|
const userStore = useUserStore();
|
||||||
|
if (userStore.isLamp) return true;
|
||||||
|
return { path: '/404' };
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: '/:pathMatch(.*)*',
|
path: '/:pathMatch(.*)*',
|
||||||
component: () => import('@/pages/not-found-page.vue'),
|
component: () => import('@/pages/not-found-page.vue'),
|
||||||
|
|||||||
Reference in New Issue
Block a user