明树Git Lab

Commit 6aa0ed17 authored by yangyajing's avatar yangyajing

菜单管理

parent b6be8853
Pipeline #104447 passed with stage
in 13 seconds
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
"@element-plus/icons-vue": "^2.3.2", "@element-plus/icons-vue": "^2.3.2",
"@kjgl77/datav-vue3": "^1.7.4", "@kjgl77/datav-vue3": "^1.7.4",
"axios": "^1.13.2", "axios": "^1.13.2",
"crypto-js": "^4.2.0",
"decimal.js": "^10.6.0", "decimal.js": "^10.6.0",
"echarts": "^6.0.0", "echarts": "^6.0.0",
"echarts-map": "^3.0.1", "echarts-map": "^3.0.1",
...@@ -531,6 +532,12 @@ ...@@ -531,6 +532,12 @@
"node": ">=0.8" "node": ">=0.8"
} }
}, },
"node_modules/crypto-js": {
"version": "4.2.0",
"resolved": "https://registry.npmmirror.com/crypto-js/-/crypto-js-4.2.0.tgz",
"integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==",
"license": "MIT"
},
"node_modules/csstype": { "node_modules/csstype": {
"version": "3.2.3", "version": "3.2.3",
"license": "MIT" "license": "MIT"
......
...@@ -392,6 +392,7 @@ ...@@ -392,6 +392,7 @@
</el-form-item> </el-form-item>
</el-col> </el-col>
<!-- 表单操作按钮 --> <!-- 表单操作按钮 -->
<el-col :span="24">
<el-form-item v-if="config.showButtons !== false" class="form-buttons"> <el-form-item v-if="config.showButtons !== false" class="form-buttons">
<el-button <el-button
v-if="config.showSubmit !== false" v-if="config.showSubmit !== false"
...@@ -411,6 +412,7 @@ ...@@ -411,6 +412,7 @@
{{ btn.text }} {{ btn.text }}
</el-button> </el-button>
</el-form-item> </el-form-item>
</el-col>
</el-row> </el-row>
</el-form> </el-form>
......
...@@ -2,6 +2,7 @@ import axios from "axios"; ...@@ -2,6 +2,7 @@ import axios from "axios";
import { ElMessage } from "element-plus"; import { ElMessage } from "element-plus";
import windowConfig from "@/window"; import windowConfig from "@/window";
import { useUserStore } from "@/stores/user.js"; import { useUserStore } from "@/stores/user.js";
import { useRouter } from "vue-router";
axios.interceptors.request.use(function (config) { axios.interceptors.request.use(function (config) {
const userStore = useUserStore(); const userStore = useUserStore();
let token = userStore.authToken || sessionStorage.getItem("authToken") || ""; let token = userStore.authToken || sessionStorage.getItem("authToken") || "";
...@@ -27,7 +28,7 @@ axios.interceptors.response.use(response => { ...@@ -27,7 +28,7 @@ axios.interceptors.response.use(response => {
return Promise.reject(err); return Promise.reject(err);
}); });
export function $get ({ url, params = {}, callback }) { export function $get ({ url, params = {}, callback, error }) {
return axios({ return axios({
method: "get", method: "get",
url: windowConfig.baseUrl + url, url: windowConfig.baseUrl + url,
...@@ -36,11 +37,19 @@ export function $get ({ url, params = {}, callback }) { ...@@ -36,11 +37,19 @@ export function $get ({ url, params = {}, callback }) {
callback && callback(response.data); callback && callback(response.data);
return response; return response;
}).catch((err) => { }).catch((err) => {
ElMessage.error(err); console.log(err);
error && error(err);
ElMessage.error(err.msg || "操作失败");
if (err && err.response && err.response.status === 401) {
userStore.clearUserInfo();
router.replace("/login");
}
}); });
}; };
export function $post ({ url, data = {}, callback }) { export function $post ({ url, data = {}, callback, error }) {
const router = useRouter();
const userStore = useUserStore();
return axios.post(windowConfig.baseUrl + url, data).then((response) => { return axios.post(windowConfig.baseUrl + url, data).then((response) => {
if (response.code === 0) { if (response.code === 0) {
callback && callback(response.data); callback && callback(response.data);
...@@ -50,8 +59,10 @@ export function $post ({ url, data = {}, callback }) { ...@@ -50,8 +59,10 @@ export function $post ({ url, data = {}, callback }) {
return response; return response;
}).catch((err) => { }).catch((err) => {
console.log(err); console.log(err);
error && error(err);
ElMessage.error(err.msg || "操作失败"); ElMessage.error(err.msg || "操作失败");
if (err && err.response && err.response.status === 401) { if (err && err.response && err.response.status === 401) {
userStore.clearUserInfo();
router.replace("/login"); router.replace("/login");
} }
}); });
......
...@@ -25,43 +25,7 @@ ...@@ -25,43 +25,7 @@
<el-container> <el-container>
<!-- 侧边Aside --> <!-- 侧边Aside -->
<el-aside width="220px" class="city-aside"> <el-aside width="220px" class="city-aside">
<el-menu <left-menu></left-menu>
:default-active="$route.path"
active-text-color="#409EFF"
background-color="#1f313b"
text-color="#fff"
router
>
<template v-for="route in menuRoutes" :key="route.path">
<!-- 无子菜单的项目 -->
<el-menu-item
v-if="!route.children || route.children.length === 0"
:index="route.path"
>
<el-icon><component :is="route.meta?.icon || 'menu'" /></el-icon>
<span>{{ route.meta?.menuName || route.name }}</span>
</el-menu-item>
<!-- 有子菜单的项目 -->
<el-sub-menu v-else :index="route.path">
<template #title>
<el-icon
><component :is="route.meta?.icon || 'menu'"
/></el-icon>
<span>{{ route.meta?.menuName || route.name }}</span>
</template>
<template v-for="child in route.children" :key="child.path">
<el-menu-item v-if="child.meta?.showInMenu !== false"
:index="child.path"
style="padding-left: 20px !important"
>
<el-icon><component v-if="child.meta?.icon" :is="child.meta?.icon" /></el-icon>
<span>{{ child.meta?.menuName || child.name }}</span>
</el-menu-item>
</template>
</el-sub-menu>
</template>
</el-menu>
</el-aside> </el-aside>
<!-- 主内容Main --> <!-- 主内容Main -->
...@@ -76,6 +40,7 @@ ...@@ -76,6 +40,7 @@
import { computed, onMounted, getCurrentInstance } from "vue"; import { computed, onMounted, getCurrentInstance } from "vue";
import { useRouter, useRoute } from "vue-router"; import { useRouter, useRoute } from "vue-router";
import { useUserStore } from "@/stores/user.js"; import { useUserStore } from "@/stores/user.js";
import LeftMenu from "./leftMenu.vue";
const userStore = useUserStore(); const userStore = useUserStore();
const { proxy } = getCurrentInstance(); const { proxy } = getCurrentInstance();
...@@ -110,7 +75,7 @@ const handleLogout = () => { ...@@ -110,7 +75,7 @@ const handleLogout = () => {
url: "/api/user/logout", url: "/api/user/logout",
data: {}, data: {},
callback: (data) => { callback: (data) => {
userStore.clearUseInfo(); userStore.clearUserInfo();
router.replace("/login"); router.replace("/login");
} }
}) })
......
<template>
<el-menu
:default-active="$route.path"
router
>
<template v-for="item in menuList">
<template v-if="item.children && item.children.length">
<left-menu-item :key="item.id" :menuItem="item"></left-menu-item>
</template>
<template v-else>
<el-menu-item :key="item.id" :index="item.url">
<span>{{ item.name }}</span>
</el-menu-item>
</template>
</template>
</el-menu>
</template>
<script setup>
import LeftMenuItem from "./leftMenuItem.vue";
const menuList = sessionStorage.getItem("userInfo") ? JSON.parse(sessionStorage.getItem("userInfo")).menus : [];
</script>
<style lang="less"></style>
\ No newline at end of file
<template>
<el-sub-menu :index="menuItem.id">
<template #title>
<span>{{ menuItem.name }}</span>
</template>
<template v-for="(child, index) in menuItem.children" :key="index">
<left-menu-item v-if="child.children && child.children.length"></left-menu-item>
<el-menu-item v-else
:index="child.url"
>
<span>{{ child.name }}</span>
</el-menu-item>
</template>
</el-sub-menu>
</template>
<script setup>
import { defineProps } from 'vue';
const props = defineProps({
menuItem: {
type: Object,
default: {}
}
})
</script>
<style lang="less" scoped>
</style>
\ No newline at end of file
...@@ -9,11 +9,13 @@ export const useUserStore = defineStore('user', { ...@@ -9,11 +9,13 @@ export const useUserStore = defineStore('user', {
this.userInfo = data; this.userInfo = data;
this.authToken = data.token; this.authToken = data.token;
sessionStorage.setItem("authToken", data.token); sessionStorage.setItem("authToken", data.token);
sessionStorage.setItem("userInfo", JSON.stringify(data));
}, },
clearUserInfo () { clearUserInfo () {
this.userInfo = null; this.userInfo = null;
this.authToken = ""; this.authToken = "";
sessionStorage.removeItem("authToken"); sessionStorage.removeItem("authToken");
sessionStorage.removeItem("userInfo");
} }
} }
}) })
\ No newline at end of file
...@@ -49,6 +49,7 @@ import { ref, getCurrentInstance } from "vue"; ...@@ -49,6 +49,7 @@ import { ref, getCurrentInstance } from "vue";
import { useRouter } from "vue-router"; import { useRouter } from "vue-router";
import { User, Lock } from "@element-plus/icons-vue"; import { User, Lock } from "@element-plus/icons-vue";
import { useUserStore } from "@/stores/user.js"; import { useUserStore } from "@/stores/user.js";
import CryptoJS from "crypto-js";
const userStore = useUserStore(); const userStore = useUserStore();
const { proxy } = getCurrentInstance(); const { proxy } = getCurrentInstance();
...@@ -78,7 +79,9 @@ const handleLogin = async () => { ...@@ -78,7 +79,9 @@ const handleLogin = async () => {
if (valid) { if (valid) {
proxy.$post({ proxy.$post({
url: "/api/user/login", url: "/api/user/login",
data: loginForm.value, data: {
encryptLogStr: CryptoJS.AES.encrypt(`${loginForm.value.mobile},${loginForm.value.password}`, "GFG5w5AP0Ja2rNaa").toString()
},
callback: (data) => { callback: (data) => {
userStore.setUseInfo(data); userStore.setUseInfo(data);
router.replace("/"); router.replace("/");
......
<template> <template>
<div class="user-manage" v-loading="loading"> <div class="user-manage" v-loading="loading">
<div class="search-form">
<commonForm
v-model="searchForm"
:config="searchConfig"
:items="searchItems"
@submit="handleSearch"
@reset="handleReset"
/>
</div>
<div class="table-container"> <div class="table-container">
<common-table <common-table
:maxRows="10"
:rowHeight="40"
:data="tableData" :data="tableData"
:columns="tableColumns" :columns="tableColumns"
:total="total" :pagination="false"
:current-page="currentPage" :indent="30"
:page-size="pageSize"
:indent="10"
title="菜单管理"
:border="true" :border="true"
:tree-props="{ children: 'children', hasChildren: 'hasChildren' }" :tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
row-key="id" row-key="id"
default-expand-all default-expand-all
@size-change="handleSizeChange"
@current-page-change="handleCurrentPageChange"
> >
<template #header-actions> <template #header-actions>
<el-button type="primary" @click="handleAdd">新增 </el-button> <el-button type="primary" @click="handleAdd">新增 </el-button>
</template> </template>
<template #operations="{ row, index }"> <template #operations="{ row, index }">
<el-button type="text" size="small"> 新增 </el-button> <el-button v-if="!row.url" link type="primary" size="small" @click="addChildMenu(row, index)"> 新增子菜单 </el-button>
<el-button type="text" size="small" @click="handleEdit(row, index)"> <el-button link type="primary" size="small" @click="handleEdit(row, index)">
编辑 编辑
</el-button> </el-button>
<el-button type="text" size="small" @click="handleDelete(row, index)"> <el-button link type="primary" size="small" @click="handleDelete(row, index)">
删除 删除
</el-button> </el-button>
</template> </template>
...@@ -46,17 +30,28 @@ ...@@ -46,17 +30,28 @@
<el-dialog <el-dialog
v-model="dialogVisible" v-model="dialogVisible"
:title="dialogTitle" :title="dialogTitle"
width="800px" width="500px"
@close="handleDialogClose" @close="cancelMenuForm"
> >
<commonForm <el-form :model="menuFormData" ref="menuForm" :rules="menuRules" label-width="100">
v-model="userForm" <el-form-item label="项目名称" prop="name">
:config="formConfig" <el-input v-model="menuFormData.name" />
:items="formItems" </el-form-item>
:rules="formRules" <el-form-item label="排序">
@submit="handleFormSubmit" <el-input-number v-model="menuFormData.order" :min="0" :precision="0" :max="99999999999"
@reset="handleFormReset" controls-position="right"
/> />
</el-form-item>
<el-form-item label="路由地址">
<el-input v-model="menuFormData.url" />
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button @click="cancelMenuForm">取消</el-button>
<el-button type="primary" @click="saveMenuForm">保存</el-button>
</div>
</template>
</el-dialog> </el-dialog>
</div> </div>
</template> </template>
...@@ -69,502 +64,122 @@ import commonForm from "@/components/common/commonForm.vue"; ...@@ -69,502 +64,122 @@ import commonForm from "@/components/common/commonForm.vue";
import CommonTable from "@/components/common/commonTable.vue"; import CommonTable from "@/components/common/commonTable.vue";
import { da } from "element-plus/es/locales.mjs"; import { da } from "element-plus/es/locales.mjs";
// 模拟树形菜单数据
const mockMenuData = [
{
id: 1,
name: "系统管理",
code: "system",
app: "管理平台",
type: "目录",
icon: "Setting",
order: 1,
createdAt: "2024-01-01",
children: [
{
id: 11,
name: "用户管理",
code: "user",
app: "管理平台",
type: "菜单",
icon: "User",
order: 1,
createdAt: "2024-01-01",
children: [
{
id: 111,
name: "用户列表",
code: "user-list",
app: "管理平台",
type: "菜单",
icon: "List",
order: 1,
createdAt: "2024-01-01",
},
{
id: 112,
name: "用户详情",
code: "user-detail",
app: "管理平台",
type: "菜单",
icon: "Document",
order: 2,
createdAt: "2024-01-01",
},
],
},
{
id: 12,
name: "角色管理",
code: "role",
app: "管理平台",
type: "菜单",
icon: "UserFilled",
order: 2,
createdAt: "2024-01-01",
},
{
id: 13,
name: "菜单管理",
code: "menu",
app: "管理平台",
type: "菜单",
icon: "Menu",
order: 3,
createdAt: "2024-01-01",
},
],
},
{
id: 2,
name: "业务管理",
code: "business",
app: "业务平台",
type: "目录",
icon: "Briefcase",
order: 2,
createdAt: "2024-01-01",
children: [
{
id: 21,
name: "项目管理",
code: "project",
app: "业务平台",
type: "菜单",
icon: "FolderOpened",
order: 1,
createdAt: "2024-01-01",
},
{
id: 22,
name: "审批管理",
code: "approval",
app: "业务平台",
type: "菜单",
icon: "Select",
order: 2,
createdAt: "2024-01-01",
},
],
},
{
id: 3,
name: "数据统计",
code: "statistics",
app: "分析平台",
type: "目录",
icon: "DataAnalysis",
order: 3,
createdAt: "2024-01-01",
children: [
{
id: 31,
name: "报表中心",
code: "report",
app: "分析平台",
type: "菜单",
icon: "PieChart",
order: 1,
createdAt: "2024-01-01",
},
],
},
];
const { proxy } = getCurrentInstance(); const { proxy } = getCurrentInstance();
const loading = ref(false); const loading = ref(false);
// 数据转换函数 const menuForm = ref();
const convertToTreeData = (apiData) => { const menuRules = ref({
return apiData.map((item) => ({ name: [
value: item.id.toString(), { required: true, message: "请输入菜单名称", trigger: "blur" }
label: item.name, ]
children: item.children ? convertToTreeData(item.children) : [],
}));
};
// 查询表单数据
const searchForm = ref({
name: "",
mobile: "",
}); });
// 查询表单配置
const searchConfig = {
inline: true,
labelWidth: "80px",
showButtons: true,
submitText: "查询",
resetText: "重置",
};
// 查询表单项配置
const searchItems = [
{
type: "input",
prop: "name",
label: "菜单名称:",
placeholder: "请输入菜单名称",
clearable: true,
span: 8,
},
{
type: "input",
prop: "mobile",
label: "菜单编码:",
placeholder: "请输入菜单编码",
clearable: true,
span: 8,
},
];
// 表格数据 // 表格数据
const tableData = ref([]); const tableData = ref([]);
const total = ref(0);
const currentPage = ref(1);
const pageSize = ref(10);
// 表格列配置 // 表格列配置
const tableColumns = [ const tableColumns = [
{ {
prop: "name", prop: "name",
label: "菜单名称", label: "菜单名称",
width: 180,
tree: true, tree: true,
}, },
{ // {
prop: "code", // prop: "order",
label: "菜单编号", // label: "排序",
minWidth: 120, // align: "center",
}, // },
{
prop: "type",
label: "菜单类型",
minWidth: 100,
},
{
prop: "icon",
label: "菜单图标",
minWidth: 100,
},
{
prop: "order",
label: "排序",
minWidth: 80,
align: "center",
},
{
prop: "createdAt",
label: "创建时间",
width: 250,
align: "center",
},
{ {
prop: "operations", prop: "operations",
label: "操作", label: "操作",
width: 200, width: 180,
slot: "operations", slot: "operations",
fixed: "right", fixed: "right",
align: "center", align: "right"
}, },
]; ];
// 表格数据
// 对话框相关 const loadTableData = () => {
const dialogVisible = ref(false); loading.value = true;
const dialogTitle = ref("新增菜单"); proxy.$post({
const isEdit = ref(false); url: "/api/user/menu/treeMenu",
const editIndex = ref(-1); data: {},
callback: (data) => {
// 用户表单数据 tableData.value = data;
const userForm = ref({ loading.value = false;
name: "",
departs: [],
positions: [],
roles: [],
enable: "0",
});
// 用户表单配置
const formConfig = {
labelWidth: "100px",
showButtons: true,
submitText: "保存",
resetText: "取消",
};
// 用户表单项配置
const formItems = computed(() => [
{
type: "select",
prop: "name",
label: "父级菜单:",
placeholder: "请选择顶级菜单",
span: 12,
required: true,
rules: [{ required: true, message: "请选择顶级菜单", trigger: "blur" }],
},
{
type: "radio",
prop: "",
label: "菜单类型:",
span: 12,
options: [
{
label: "目录",
value: "1",
},
{
label: "菜单",
value: "0",
},
],
},
{
type: "input",
prop: "mobile",
label: "菜单名称:",
placeholder: "请输入菜单名称",
span: 12,
required: true,
rules: [{ required: true, message: "请输入菜单名称", trigger: "blur" }],
},
{
type: "input",
prop: "",
label: "菜单编号:",
placeholder: "请输入菜单编号",
span: 12,
required: true,
rules: [{ required: true, message: "请输入菜单编号", trigger: "blur" }],
},
{
type: "input",
prop: "",
label: "Vue组件:",
placeholder: "请输入Vue组件",
span: 12,
},
{
type: "input",
prop: "",
label: "路由名称:",
placeholder: "请输入路由名称",
span: 12,
},
{
type: "input",
prop: "",
label: "路由地址:",
placeholder: "请输入路由地址",
span: 12,
},
{
type: "input",
prop: "",
label: "排序:",
placeholder: "请输入排序",
span: 12,
},
{
type: "radio",
prop: "",
label: "显示状态:",
span: 12,
options: [
{ label: "显示", value: "0" },
{ label: "隐藏", value: "1" },
],
},
{
type: "radio",
prop: "",
label: "嵌套模式:",
span: 12,
options: [
{ label: "是", value: "0" },
{ label: "否", value: "1" },
],
}, },
{ error: (err) => {
type: "upload", loading.value = false;
prop: "", ElMessage.error("加载数据失败");
label: "菜单图标:",
span: 12,
}, },
]); });
// 表单验证规则
const formRules = {};
// 事件处理函数
const handleSearch = (formData) => {
currentPage.value = 1;
loadTableData();
};
const handleReset = () => {
searchForm.value = {
name: "",
mobile: "",
};
currentPage.value = 1;
loadTableData();
};
const handleSizeChange = (size) => {
pageSize.value = size;
currentPage.value = 1;
loadTableData();
}; };
const handleCurrentPageChange = (page) => { // 对话框相关
currentPage.value = page; const dialogVisible = ref(false);
loadTableData(); const dialogTitle = ref("");
};
// 新增用户 // 用户表单数据
const menuFormData = ref({});
// 新增菜单
const handleAdd = () => { const handleAdd = () => {
isEdit.value = false;
dialogTitle.value = "新增菜单"; dialogTitle.value = "新增菜单";
userForm.value = {
name: "",
departs: [],
positions: [],
roles: [],
enable: "0",
};
dialogVisible.value = true; dialogVisible.value = true;
}; };
let currentID = ref(); const addChildMenu = (row, index) => {
dialogTitle.value = "新增菜单";
menuFormData.value.parentId = row.id;
dialogVisible.value = true;
}
// 编辑 // 编辑
const handleEdit = (row, index) => { const handleEdit = (row, index) => {
isEdit.value = true; menuFormData.value = { ...row };
dialogTitle.value = "编辑用户"; dialogTitle.value = "编辑菜单";
editIndex.value = index;
// proxy.$post({
// url: "/api/user/manage/getUserInfo",
// data: { id: row.id },
// callback: (data) => {
// userForm.value = { ...data };
// currentID.value = data.id;
// },
// error: (err) => {
// ElMessage.error("编辑失败:", err);
// },
// });
dialogVisible.value = true; dialogVisible.value = true;
}; };
// 删除 // 删除
const handleDelete = async (row, index) => { const handleDelete = async (row, index) => {
try { ElMessageBox.confirm(`确定删除${row.name}?`, "提示", {
// await ElMessageBox.confirm(`确定要删除用户"${row.name}"吗?`, "提示", { confirmButtonText: "确定",
// confirmButtonText: "确定", cancelButtonText: "取消",
// cancelButtonText: "取消", type: "warning",
// type: "warning", }).then(() => {
// });
// proxy.$post({
// url: "/api/user/manage/deleteUser",
// data: { id: row.id },
// callback: (data) => {
// dialogVisible.value = false;
// loadTableData();
// ElMessage.success("删除成功");
// },
// error: (err) => {
// ElMessage.error("删除失败:", err);
// },
// });
// loadTableData();
} catch {}
};
const handleFormSubmit = (formData) => {
if (isEdit.value) {
// 编辑用户
const updateUser = {
...formData,
};
// proxy.$post({
// url: "/api/user/manage/updateUser",
// data: updateUser,
// callback: (data) => {
// dialogVisible.value = false;
// loadTableData();
// ElMessage.success("用户信息更新成功");
// },
// error: (err) => {
// ElMessage.error("用户信息更新失败:", err);
// },
// });
} else {
// 新增用户
const newUser = {
...formData,
};
// proxy.$post({
// url: "/api/user/manage/createUser",
// data: newUser,
// callback: (data) => {
// dialogVisible.value = false;
// loadTableData();
// ElMessage.success("用户添加成功");
// },
// error: (err) => {
// ElMessage.error("用户添加失败:", err);
// },
// });
}
};
const handleFormReset = () => {
dialogVisible.value = false;
};
const handleDialogClose = () => {
dialogVisible.value = false;
};
// 表格数据
const loadTableData = () => {
loading.value = true;
proxy.$post({ proxy.$post({
url: "/api/user/menu/treeMenu", url: "/api/user/menu/deleteMenu",
data: { data: { id: row.id },
...searchForm.value,
page: currentPage.value,
pageSize: pageSize.value,
},
callback: (data) => { callback: (data) => {
tableData.value = data; ElMessage.success("删除成功");
total.value = data.count; loadTableData();
loading.value = false;
}, },
error: (err) => { error: (err) => {
loading.value = false; ElMessage.error("删除失败:", err);
ElMessage.error("加载数据失败");
}, },
}); });
});
};
const saveMenuForm = () => {
menuForm.value.validate(valid => {
if (valid) {
let url = menuFormData.value.id ? "updateMenu" : "createMenu"
proxy.$post({
url: "/api/user/menu/" + url,
data: menuFormData.value,
callback: (data) => {
ElMessage.success(dialogTitle.value + "成功");
loadTableData();
cancelMenuForm();
}
})
}
});
};
const cancelMenuForm = () => {
menuForm.value.resetFields();
menuFormData.value = {};
dialogVisible.value = false;
}; };
onMounted(() => { onMounted(() => {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment