page: 📄 路由查询
This commit is contained in:
parent
f3bdd89a44
commit
1eb1eced1b
|
@ -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 });
|
||||
};
|
||||
|
|
|
@ -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 });
|
||||
};
|
||||
|
|
|
@ -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 = [];
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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加父节点parentId,parentId取父节点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();
|
||||
}
|
||||
|
|
|
@ -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' }],
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue