page: 📄 路由查询

This commit is contained in:
Bunny 2024-09-28 03:07:47 +08:00
parent f3bdd89a44
commit 1eb1eced1b
6 changed files with 225 additions and 241 deletions

View File

@ -1,37 +1,30 @@
import { http } from '@/api/service';
type Result = {
success: boolean;
data?: Array<any>;
};
import type { BaseResult } from '@/types/BaseResult';
type ResultTable = {
success: boolean;
data?: {
/** 列表数据 */
list: Array<any>;
/** 总条目数 */
total?: number;
/** 每页显示条目个数 */
pageSize?: number;
/** 当前页数 */
currentPage?: number;
};
/** 列表数据 */
list: Array<any>;
/** 总条目数 */
total?: number;
/** 每页显示条目个数 */
pageSize?: number;
/** 当前页数 */
pageNo?: number;
};
/** 获取系统管理-用户管理列表 */
export const getUserList = (data?: object) => {
return http.request<ResultTable>('post', '/user', { data });
return http.request<BaseResult<ResultTable>>('post', '/user', { data });
};
/** 系统管理-用户管理-获取所有角色列表 */
export const getAllRoleList = () => {
return http.request<Result>('get', '/list-all-role');
return http.request<any>('get', '/list-all-role');
};
/** 系统管理-用户管理-根据userId获取对应角色id列表userId用户id */
export const getRoleIds = (data?: object) => {
return http.request<Result>('post', '/list-role-ids', { data });
return http.request<any>('post', '/list-role-ids', { data });
};
/** 获取系统管理-角色管理列表 */
@ -40,13 +33,14 @@ export const getRoleList = (data?: object) => {
};
/** 获取系统管理-菜单管理列表 */
export const getMenuList = (data?: object) => {
return http.request<Result>('post', '/menu', { data });
export const getMenuList = (data?: any) => {
// /${data.page}/${data.limit}
return http.request<BaseResult<ResultTable>>('get', `router/getMenus`, { data });
};
/** 获取系统管理-部门管理列表 */
export const getDeptList = (data?: object) => {
return http.request<Result>('post', '/dept', { data });
return http.request<any>('post', '/dept', { data });
};
/** 获取系统监控-在线用户列表 */
@ -71,15 +65,15 @@ export const getSystemLogsList = (data?: object) => {
/** 获取系统监控-系统日志-根据 id 查日志详情 */
export const getSystemLogsDetail = (data?: object) => {
return http.request<Result>('post', '/system-logs-detail', { data });
return http.request<any>('post', '/system-logs-detail', { data });
};
/** 获取角色管理-权限-菜单权限 */
export const getRoleMenu = (data?: object) => {
return http.request<Result>('post', '/role-menu', { data });
return http.request<any>('post', '/role-menu', { data });
};
/** 获取角色管理-权限-菜单权限-根据角色 id 查对应菜单 */
export const getRoleMenuIds = (data?: object) => {
return http.request<Result>('post', '/role-menu-ids', { data });
return http.request<any>('post', '/role-menu-ids', { data });
};

View File

@ -53,6 +53,6 @@ export const refreshTokenApi = (data?: object) => {
* * 退
* @param data
*/
export const fetchLogOut = (data?: object) => {
return http.request<BaseResult<any>>('post', 'user/logOut', { data });
export const fetchLogout = (data?: object) => {
return http.request<BaseResult<any>>('post', 'user/logout', { data });
};

View File

@ -1,6 +1,6 @@
import { defineStore } from 'pinia';
import { resetRouter, router, routerArrays, storageLocal, store, type userType } from '../utils';
import { fetchLogin, fetchLogOut, fetchPostEmailCode, refreshTokenApi } from '@/api/v1/user';
import { fetchLogin, fetchLogout, fetchPostEmailCode, refreshTokenApi } from '@/api/v1/user';
import { useMultiTagsStoreHook } from '../multiTags';
import { type DataInfo, removeToken, setToken, userKey } from '@/utils/auth';
import { message } from '@/utils/message';
@ -58,7 +58,7 @@ export const useUserStore = defineStore({
*/
async logOut() {
// 登出
const result = await fetchLogOut();
const result = await fetchLogout();
if (result.code == 200) {
this.username = '';
this.roles = [];

View File

@ -1,6 +1,5 @@
<script lang="ts" setup>
import { ref } from 'vue';
import { useMenu } from './utils/hook';
import { onMounted, ref } from 'vue';
import { $t } from '@/plugins/i18n';
import { PureTableBar } from '@/components/TableBar';
import { useRenderIcon } from '@/components/ReIcon/src/hooks';
@ -9,6 +8,9 @@ import Delete from '@iconify-icons/ep/delete';
import EditPen from '@iconify-icons/ep/edit-pen';
import Refresh from '@iconify-icons/ep/refresh';
import AddFill from '@iconify-icons/ri/add-circle-line';
import { columns, dataList, handleDelete, handleSelectionChange, loading, onSearch, openDialog, resetForm } from '@/views/menu/utils/hook';
import form from '@/views/role/form.vue';
import PureTable from '@pureadmin/table';
defineOptions({
name: 'SystemMenu',
@ -16,12 +18,18 @@ defineOptions({
const formRef = ref();
const tableRef = ref();
const { form, loading, columns, dataList, onSearch, resetForm, openDialog, handleDelete, handleSelectionChange } = useMenu();
function onFullscreen() {
/**
* 全屏
*/
const onFullscreen = () => {
//
tableRef.value.setAdaptive();
}
};
onMounted(() => {
onSearch();
});
</script>
<template>

View File

@ -4,214 +4,196 @@ import { message } from '@/utils/message';
import { getMenuList } from '@/api/v1/system';
import { $t } from '@/plugins/i18n';
import { addDialog } from '@/components/BaseDialog';
import { h, onMounted, reactive, ref } from 'vue';
import { h, reactive, ref } from 'vue';
import type { FormItemProps } from '../utils/types';
import { useRenderIcon } from '@/components/ReIcon/src/hooks';
import { cloneDeep, deviceDetection, isAllEmpty } from '@pureadmin/utils';
export function useMenu() {
const form = reactive({
title: '',
});
export const form = reactive({
title: '',
});
const formRef = ref();
const dataList = ref([]);
const loading = ref(true);
export const formRef = ref();
export const dataList = ref([]);
export const loading = ref(true);
const getMenuType = (type, text = false) => {
switch (type) {
case 0:
return text ? '菜单' : 'primary';
case 1:
return text ? 'iframe' : 'warning';
case 2:
return text ? '外链' : 'danger';
case 3:
return text ? '按钮' : 'info';
}
};
const columns: TableColumnList = [
{
label: '菜单名称',
prop: 'title',
align: 'left',
cellRenderer: ({ row }) => (
<>
<span class='inline-block mr-1'>
{h(useRenderIcon(row.icon), {
style: { paddingTop: '1px' },
})}
</span>
<span>{$t(row.title)}</span>
</>
),
},
{
label: '菜单类型',
prop: 'menuType',
width: 100,
cellRenderer: ({ row, props }) => (
<el-tag size={props.size} type={getMenuType(row.menuType)} effect='plain'>
{getMenuType(row.menuType, true)}
</el-tag>
),
},
{
label: '路由路径',
prop: 'path',
},
{
label: '组件路径',
prop: 'component',
formatter: ({ path, component }) => (isAllEmpty(component) ? path : component),
},
{
label: '权限标识',
prop: 'auths',
},
{
label: '排序',
prop: 'rank',
width: 100,
},
{
label: '隐藏',
prop: 'showLink',
formatter: ({ showLink }) => (showLink ? '否' : '是'),
width: 100,
},
{
label: '操作',
fixed: 'right',
width: 210,
slot: 'operation',
},
];
function handleSelectionChange(val) {
console.log('handleSelectionChange', val);
export const getMenuType = (type, text = false) => {
switch (type) {
case 0:
return text ? '菜单' : 'primary';
case 1:
return text ? 'iframe' : 'warning';
case 2:
return text ? '外链' : 'danger';
case 3:
return text ? '按钮' : 'info';
}
};
function resetForm(formEl) {
if (!formEl) return;
formEl.resetFields();
onSearch();
}
export const columns: TableColumnList = [
{
label: '菜单名称',
prop: 'title',
align: 'left',
cellRenderer: ({ row }) => (
<>
<span class='inline-block mr-1'>
{h(useRenderIcon(row.icon), {
style: { paddingTop: '1px' },
})}
</span>
<span>{$t(row.title)}</span>
</>
),
},
{
label: '菜单类型',
prop: 'menuType',
width: 100,
cellRenderer: ({ row, props }) => (
<el-tag size={props.size} type={getMenuType(row.menuType)} effect='plain'>
{getMenuType(row.menuType, true)}
</el-tag>
),
},
{
label: '路由路径',
prop: 'path',
},
{
label: '组件路径',
prop: 'component',
formatter: ({ path, component }) => (isAllEmpty(component) ? path : component),
},
{
label: '权限标识',
prop: 'auths',
},
{
label: '排序',
prop: 'rank',
width: 100,
},
{
label: '隐藏',
prop: 'showLink',
formatter: ({ showLink }) => (showLink ? '否' : '是'),
width: 100,
},
{
label: '操作',
fixed: 'right',
width: 210,
slot: 'operation',
},
];
async function onSearch() {
loading.value = true;
const { data } = await getMenuList(); // 这里是返回一维数组结构前端自行处理成树结构返回格式要求唯一id加父节点parentIdparentId取父节点id
let newData = data;
if (!isAllEmpty(form.title)) {
// 前端搜索菜单名称
newData = newData.filter(item => $t(item.title).includes(form.title));
}
dataList.value = handleTree(newData); // 处理成树结构
setTimeout(() => {
loading.value = false;
}, 500);
}
function formatHigherMenuOptions(treeList) {
if (!treeList || !treeList.length) return;
const newTreeList = [];
for (let i = 0; i < treeList.length; i++) {
treeList[i].title = $t(treeList[i].title);
formatHigherMenuOptions(treeList[i].children);
newTreeList.push(treeList[i]);
}
return newTreeList;
}
function openDialog(title = '新增', row?: FormItemProps) {
addDialog({
title: `${title}菜单`,
props: {
formInline: {
menuType: row?.menuType ?? 0,
higherMenuOptions: formatHigherMenuOptions(cloneDeep(dataList.value)),
parentId: row?.parentId ?? 0,
title: row?.title ?? '',
name: row?.name ?? '',
path: row?.path ?? '',
component: row?.component ?? '',
rank: row?.rank ?? 99,
redirect: row?.redirect ?? '',
icon: row?.icon ?? '',
extraIcon: row?.extraIcon ?? '',
enterTransition: row?.enterTransition ?? '',
leaveTransition: row?.leaveTransition ?? '',
activePath: row?.activePath ?? '',
auths: row?.auths ?? '',
frameSrc: row?.frameSrc ?? '',
frameLoading: row?.frameLoading ?? true,
keepAlive: row?.keepAlive ?? false,
hiddenTag: row?.hiddenTag ?? false,
fixedTag: row?.fixedTag ?? false,
showLink: row?.showLink ?? true,
showParent: row?.showParent ?? false,
},
},
width: '45%',
draggable: true,
fullscreen: deviceDetection(),
fullscreenIcon: true,
closeOnClickModal: false,
contentRenderer: () => h(editForm, { ref: formRef, formInline: null }),
beforeSure: (done, { options }) => {
const FormRef = formRef.value.getRef();
const curData = options.props.formInline as FormItemProps;
function chores() {
message(`${title}了菜单名称为${$t(curData.title)}的这条数据`, {
type: 'success',
});
done(); // 关闭弹框
onSearch(); // 刷新表格数据
}
FormRef.validate(valid => {
if (valid) {
console.log('curData', curData);
// 表单规则校验通过
if (title === '新增') {
// 实际开发先调用新增接口,再进行下面操作
chores();
} else {
// 实际开发先调用修改接口,再进行下面操作
chores();
}
}
});
},
});
}
function handleDelete(row) {
message(`您删除了菜单名称为${$t(row.title)}的这条数据`, {
type: 'success',
});
onSearch();
}
onMounted(() => {
onSearch();
});
return {
form,
loading,
columns,
dataList,
/** 搜索 */
onSearch,
/** 重置 */
resetForm,
/** 新增、修改菜单 */
openDialog,
/** 删除菜单 */
handleDelete,
handleSelectionChange,
};
export function handleSelectionChange(val) {
console.log('handleSelectionChange', val);
}
export function resetForm(formEl) {
if (!formEl) return;
formEl.resetFields();
onSearch();
}
export async function onSearch() {
loading.value = true;
// 获取菜单数据
const result = await getMenuList();
if (result.code !== 200) message(result.message, { type: 'error' });
// 前端搜索菜单名称
if (!isAllEmpty(form.title)) {
result.data = result.data.filter(item => $t(item.title).includes(form.title));
}
// 处理成树结构
dataList.value = handleTree(result.data);
loading.value = false;
}
export function formatHigherMenuOptions(treeList) {
if (!treeList || !treeList.length) return;
const newTreeList = [];
for (let i = 0; i < treeList.length; i++) {
treeList[i].title = $t(treeList[i].title);
formatHigherMenuOptions(treeList[i].children);
newTreeList.push(treeList[i]);
}
return newTreeList;
}
export function openDialog(title = '新增', row?: FormItemProps) {
addDialog({
title: `${title}菜单`,
props: {
formInline: {
menuType: row?.menuType ?? 0,
higherMenuOptions: formatHigherMenuOptions(cloneDeep(dataList.value)),
parentId: row?.parentId ?? 0,
title: row?.title ?? '',
name: row?.name ?? '',
path: row?.path ?? '',
component: row?.component ?? '',
rank: row?.rank ?? 99,
redirect: row?.redirect ?? '',
icon: row?.icon ?? '',
extraIcon: row?.extraIcon ?? '',
enterTransition: row?.enterTransition ?? '',
leaveTransition: row?.leaveTransition ?? '',
activePath: row?.activePath ?? '',
auths: row?.auths ?? '',
frameSrc: row?.frameSrc ?? '',
frameLoading: row?.frameLoading ?? true,
keepAlive: row?.keepAlive ?? false,
hiddenTag: row?.hiddenTag ?? false,
fixedTag: row?.fixedTag ?? false,
showLink: row?.showLink ?? true,
showParent: row?.showParent ?? false,
},
},
width: '45%',
draggable: true,
fullscreen: deviceDetection(),
fullscreenIcon: true,
closeOnClickModal: false,
contentRenderer: () => h(editForm, { ref: formRef, formInline: null }),
beforeSure: (done, { options }) => {
const FormRef = formRef.value.getRef();
const curData = options.props.formInline as FormItemProps;
function chores() {
message(`${title}了菜单名称为${$t(curData.title)}的这条数据`, {
type: 'success',
});
done(); // 关闭弹框
onSearch(); // 刷新表格数据
}
FormRef.validate(valid => {
if (valid) {
console.log('curData', curData);
// 表单规则校验通过
if (title === '新增') {
// 实际开发先调用新增接口,再进行下面操作
chores();
} else {
// 实际开发先调用修改接口,再进行下面操作
chores();
}
}
});
},
});
}
export function handleDelete(row) {
message(`您删除了菜单名称为${$t(row.title)}的这条数据`, {
type: 'success',
});
onSearch();
}

View File

@ -1,10 +1,10 @@
import { reactive } from "vue";
import type { FormRules } from "element-plus";
import { reactive } from 'vue';
import type { FormRules } from 'element-plus';
/** 自定义表单规则校验 */
export const formRules = reactive(<FormRules>{
title: [{ required: true, message: "菜单名称为必填项", trigger: "blur" }],
name: [{ required: true, message: "路由名称为必填项", trigger: "blur" }],
path: [{ required: true, message: "路由路径为必填项", trigger: "blur" }],
auths: [{ required: true, message: "权限标识为必填项", trigger: "blur" }]
title: [{ required: true, message: '菜单名称为必填项', trigger: 'blur' }],
name: [{ required: true, message: '路由名称为必填项', trigger: 'blur' }],
path: [{ required: true, message: '路由路径为必填项', trigger: 'blur' }],
auths: [{ required: true, message: '权限标识为必填项', trigger: 'blur' }],
});