关于基础项目搭建以及菜单导航组件可以查看之前的介绍!
路由配置
首先创建一个菜单管理页面来进行菜单管理
const routes = [
{
path: "/",
name: "layout",
component: Layout,
meta: { title: "主页" },
},
{
path: "/system",
name: "system",
component: Layout,
meta: { title: "系统管理" },
children: [
{
path: "/menu",
name: "menu",
component: () => import("@/views/system/menu/index.vue"),
meta: { title: "菜单管理" },
},
],
},
];
此时在 Sidebar 组件中可以通过路由方法获取到整个路由树:
import { useRouter } from "vue-router";
const router = useRouter();
const routers = computed(() => router.options.routes);
同时 Layout 组件需要路由改造一下
<template>
<el-container>
<el-aside width="200px">
<sidebar />
</el-aside>
<el-main>
<RouterView />
</el-main>
</el-container>
</template>
此时渲染结果为:
菜单管理
准备基础页面结构
<!--菜单管理-->
<script setup lang="ts" name="Menu">
enum menuTypeEnum {
catalog = "1",
Menu = "2",
Button = "3",
}
interface MenuType {
id: string;
name: string;
path: string;
code: string;
type: menuTypeEnum;
}
const tableData = [];
const onOpenRole = () => {};
const onOpenMenu = () => {};
const onAddClick = (menu: MenuType) => {};
const onEditClick = (menu: MenuType) => {};
const onDeleteClick = (id: string) => {};
</script>
<template>
<el-container>
<el-header height="40">
<el-button @click="onOpenMenu">新增</el-button>
<el-button @click="onOpenRole">角色授权</el-button>
</el-header>
<el-main>
<el-table border :data="tableData" row-key="id">
<el-table-column type="selection" align="center" />
<el-table-column type="index" label="序号" align="center" width="90" />
<el-table-column label="菜单名称" prop="name" />
<el-table-column label="菜单路径" align="center" prop="path" />
<el-table-column label="组件路径" align="center" prop="code" />
<el-table-column label="菜单类型" align="center" prop="type">
<template v-slot="scope">
<span>{{scope.row.type === "1" ? "目录" : scope.row.type === "2" ? "菜单" : "按钮" }}</span>
</template>
</el-table-column>
<el-table-column label="操作">
<template v-slot="scope">
<el-button type="text" @click="onAddClick(scope.row)">新增</el-button>
<el-button type="text" @click="onEditClick(scope.row)">编辑</el-button>
<el-button type="text" @click="onDeleteClick(scope.row.id)">删除</el-button>
</template>
</el-table-column>
</el-table>
</el-main>
</el-container>
</template>
<style scoped lang="scss"></style>
页面显示:
菜单新增
<el-dialog v-model="isOpenMenu" title="新增/编辑">
<el-form :model="menuForm" label-width="80px">
<el-form-item :label="menuForm.type !== '3' ? '菜单名称' : '按钮名称'">
<el-input v-model="menuForm.name" />
</el-form-item>
<el-form-item v-if="menuForm.type !== '3'" label="菜单路径">
<el-input v-model="menuForm.path" />
</el-form-item>
<el-form-item v-if="menuForm.type !== '3'" label="组件路径">
<el-input v-model="menuForm.code" />
</el-form-item>
<el-form-item v-if="menuForm.type === '3'" label="按钮编码">
<el-input v-model="menuForm.code" />
</el-form-item>
<el-form-item label="菜单类型">
<el-select v-model="menuForm.type">
<el-option label="目录" :value="menuTypeEnum.Catalog" />
<el-option label="菜单" :value="menuTypeEnum.Menu" />
<el-option label="按钮" :value="menuTypeEnum.Button" />
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onSubmitMenu">提交</el-button>
<el-button @click="onCloseMenu">取消</el-button>
</el-form-item>
</el-form>
</el-dialog>
class Menu implements MenuType {
constructor(data: Partial<MenuType> = {}) {
this.id = data.id ?? "";
this.code = data.code ?? "";
this.name = data.name ?? "";
this.path = data.path ?? "";
this.pid = data.pid ?? -1;
this.type = data.type ?? menuTypeEnum.Catalog;
}
code: string;
id: number | "";
name: string;
path: string;
pid: number;
type: menuTypeEnum;
}
const menuForm = ref<MenuType>();
const isOpenMenu = ref(false);
const onOpenMenu = () => {
menuForm.value = new Menu();
isOpenMenu.value = true;
};
const onSubmitMenu = () => {};
const onCloseMenu = () => {
isOpenMenu.value = false;
};
同样子节点新增和编辑:
const onAddClick = (menu: MenuType) => {
menuForm.value = new Menu({ pid: menu.id as number });
isOpenMenu.value = true;
};
const onEditClick = (menu: MenuType) => {
menuForm.value = new Menu(menu);
isOpenMenu.value = true;
};
json-server
json-server 可以快速帮助我们进行接口 mock
1. 安装依赖
npm install -D json-server
2. 创建 JSON 数据
在 __json_server_mock__ 文件夹下创建 db.json 文件, 并配置
{
"system-menu": {}
}
3. 启动命令
在 package.json 中 scripts 命令中配置
"json-server": "json-server ./__json_server_mock__/db.json --port=3669 --watch"
4. 接口封装
import axios from "axios";
const service = axios.create({
baseURL: "http://localhost:3669/", // url = base url + request url
timeout: 5000, // request timeout
});
const get = (url: string, params: any) => service.get(url, { params });
const post = (url: string, params: any) => service.post(url, params);
const deletes = (url: string, id: string) => service.delete(`${url}/${id}`);
const put = (url: string, params: { id: string; [k: string]: any }) =>
service.put(`${url}/${params.id}`, params);
export default {
get,
post,
deletes,
put,
};
5. 调用接口
import { ref } from "vue";
import server from "@/api/index";
const MENU_URL = "system-menu";
const tableData = ref<MenuType[]>();
const getTableData = () => {
server.get(MENU_URL).then((res) => {
tableData.value = res.data;
});
};
const onDeleteClick = (id: string) => {
server.deletes(MENU_URL, id).then(() => {
getTableData();
});
};
const onSubmitMenu = () => {
const axiosFn = menuForm.value.id ? server.put : server.post;
axiosFn(MENU_URL, menuForm.value).then(() => {
onCloseMenu();
getTableData();
});
};
至此实现了对菜单的增删改查