update: 菜单管理

This commit is contained in:
easy 2023-02-01 18:10:53 +08:00
parent 5c0c82e0d9
commit d4bf79f802
7 changed files with 215 additions and 81 deletions

View File

@ -15,3 +15,5 @@ export const getMenuInfo_api = (id:string) => server.get(`/menu/${id}`);
export const saveMenuInfo_api = (data: object) => server.patch(`/menu`, data);
// 新增菜单信息
export const addMenuInfo_api = (data: object) => server.post(`/menu`, data);
// 删除菜单信息
export const delMenuInfo_api = (id: string) => server.remove(`/menu/${id}`);

View File

@ -181,11 +181,18 @@
</a-form-item>
</a-form-item>
<a-form-item label="权限">
<PermissChoose :first-width="3" max-height="350px" v-model:value="form.data.permissions" />
<PermissChoose
:first-width="3"
max-height="350px"
v-model:value="form.data.permissions"
/>
</a-form-item>
</a-form>
<a-button type="primary" @click="clickSave" v-loading="saveLoading"
<a-button
type="primary"
@click="form.clickSave"
v-loading="form.saveLoading"
>保存</a-button
>
</a-card>
@ -215,14 +222,17 @@ import {
addMenuInfo_api,
} from '@/api/system/menu';
//
const route = useRoute();
const router = useRouter();
const routeParams = {
id: route.params.id === ':id' ? undefined : (route.params.id as string),
...route.query,
url: route.query.basePath,
parentId: route.query.pid,
};
//
const basicFormRef = ref<FormInstance>();
const permissFormRef = ref<FormInstance>();
const form = reactive({
@ -238,15 +248,18 @@ const form = reactive({
indirectMenus: [],
...routeParams,
} as formType,
treeData: [], //
assetsType: [] as assetType[], //
saveLoading: false,
init: () => {
//
routeParams.id &&
getMenuInfo_api(routeParams.id).then((resp) => {
form.data = resp.result as formType
getMenuInfo_api(routeParams.id).then((resp: any) => {
form.data = {
...(resp.result as formType),
accessSupport: resp.result.accessSupport.value,
};
});
//
getMenuTree_api({ paging: false }).then((resp: any) => {
@ -260,20 +273,7 @@ const form = reactive({
}));
});
},
});
form.init();
const ChooseIconRef = ref<any>(null);
const dialog = {
openDialog: () => {
ChooseIconRef.value && ChooseIconRef.value.openDialog();
},
confirm: (typeStr: string) => {
form.data.icon = typeStr || form.data.icon;
},
};
const saveLoading = ref<boolean>(false);
const clickSave = () => {
clickSave: () => {
if (!basicFormRef || !permissFormRef) return;
Promise.all([
basicFormRef.value?.validate(),
@ -281,8 +281,21 @@ const clickSave = () => {
])
.then(() => {
const api = routeParams.id ? saveMenuInfo_api : addMenuInfo_api;
saveLoading.value = true;
api(form.data)
form.saveLoading = true;
const accessSupportValue = form.data.accessSupport;
const params = {
...form.data,
accessSupport: {
value: accessSupportValue,
label:
accessSupportValue === 'unsupported'
? '不支持'
: accessSupportValue === 'support'
? '支持'
: '间接控制',
},
};
api(params)
.then((resp: any) => {
if (resp.status === 200) {
message.success('操作成功!');
@ -298,9 +311,22 @@ const clickSave = () => {
message.error('操作失败!');
}
})
.finally(() => (saveLoading.value = false));
.finally(() => (form.saveLoading = false));
})
.catch((err) => {});
},
});
form.init();
//
const ChooseIconRef = ref<any>(null);
const dialog = {
openDialog: () => {
ChooseIconRef.value && ChooseIconRef.value.openDialog();
},
confirm: (typeStr: string) => {
form.data.icon = typeStr || form.data.icon;
},
};
type formType = {
@ -314,6 +340,7 @@ type formType = {
accessSupport: string;
assetType: string | undefined;
indirectMenus: any[];
parentId?: string;
};
type assetType = {

View File

@ -5,6 +5,7 @@
:columns="table.columns"
model="TABLE"
:dataSource="table.tableData"
noPagination
>
<template #headerTitle>
<a-button
@ -33,7 +34,7 @@
type="link"
@click="() => dialog.openDialog('查看', slotProps)"
>
<edit-outlined />
<search-outlined />
</a-button>
</a-tooltip>
@ -41,7 +42,7 @@
title="确认删除"
ok-text="确定"
cancel-text="取消"
:disabled="slotProps.status"
@confirm="table.clickDel(slotProps)"
>
<a-tooltip>
<template #title>删除</template>
@ -55,7 +56,11 @@
</JTable>
<div class="dialog">
<ButtonAddDialog ref="dialogRef" @confirm="dialog.confirm" />
<ButtonAddDialog
ref="dialogRef"
@confirm="dialog.confirm"
:menu-info="menuInfo"
/>
</div>
</div>
</template>
@ -63,12 +68,14 @@
<script setup lang="ts">
import {
EditOutlined,
SearchOutlined,
DeleteOutlined,
PlusOutlined,
} from '@ant-design/icons-vue';
import ButtonAddDialog from '../components/ButtonAddDialog.vue';
import { getMenuInfo_api } from '@/api/system/menu';
import { getMenuInfo_api, saveMenuInfo_api } from '@/api/system/menu';
import { message } from 'ant-design-vue';
//
const route = useRoute();
@ -82,10 +89,14 @@ const dialogRef = ref<any>(null);
const dialog = {
//
openDialog: (mode: string, row?: object) => {
dialogRef.value && dialogRef.value.openDialog(mode, row);
dialogRef.value && dialogRef.value.openDialog(mode, { ...row });
},
confirm: () => {
table.getList();
},
confirm: () => {},
};
// -
const menuInfo = ref<any>({});
//
const table = reactive({
columns: [
@ -118,9 +129,23 @@ const table = reactive({
getList: () => {
routeParams.id &&
getMenuInfo_api(routeParams.id).then((resp: any) => {
menuInfo.value = resp.result;
table.tableData = resp.result.buttons as tableDataItem[];
});
},
clickDel: (row: tableDataItem) => {
const buttons = menuInfo.value.buttons.filter(
(item: tableDataItem) => item.id !== row.id,
);
const params = {
...menuInfo.value,
buttons,
};
saveMenuInfo_api(params).then(() => {
message.success('操作成功');
table.getList();
});
},
});
table.getList();
type tableDataItem = {

View File

@ -0,0 +1,16 @@
<template>
<div class="setting-container">
<a-card>
<h5>
<info-circle-outlined />
<span>基于系统源代码中的菜单数据配置系统菜单</span>
</h5>
</a-card>
</div>
</template>
<script setup lang="ts">
import { InfoCircleOutlined } from '@ant-design/icons-vue';
</script>
<style scoped></style>

View File

@ -4,8 +4,12 @@
:title="form.mode"
width="660px"
@ok="dialog.handleOk"
:maskClosable="false"
cancelText="取消"
okText="确定"
:confirmLoading="dialog.loading"
>
<a-form :model="form.data" class="basic-form">
<a-form :model="form.data" class="basic-form" ref="formRef">
<a-form-item
label="编码"
name="id"
@ -34,8 +38,23 @@
</a-form-item>
<a-form-item
label="权限"
:rules="[{ required: true, message: '请选择权限', validator: form.checkPermission, }]"
name="permissions"
:rules="[
{
required: true,
message: '请选择权限',
validator: form.checkPermission,
},
]"
>
<!-- <a-form-item-rest>
<PermissChoose
:first-width="8"
max-height="350px"
v-model:value="form.data.permissions"
:disabled="form.mode === '查看'"
/>
</a-form-item-rest> -->
<PermissChoose
:first-width="8"
max-height="350px"
@ -56,20 +75,56 @@
</template>
<script setup lang="ts">
import { FormInstance, message } from 'ant-design-vue';
import { Rule } from 'ant-design-vue/es/form';
import PermissChoose from '../components/PermissChoose.vue';
import { saveMenuInfo_api } from '@/api/system/menu';
const props = defineProps<{
menuInfo: {
buttons: formType[];
id: string;
};
}>();
const emits = defineEmits(['confirm']);
const dialog = reactive({
visible: false,
loading: false,
handleOk: () => {
props.menuInfo.id && formRef.value &&
formRef.value
.validate()
.then(() => {
const buttons = toRaw(props.menuInfo.buttons);
const button = buttons.find(
(item) => item.id === form.data.id,
);
if (button) {
Object.entries(form.data).forEach(([key, value]) => {
button[key] = value;
});
} else buttons.push({ ...form.data });
const params = {
...props.menuInfo,
buttons,
};
dialog.loading = true;
saveMenuInfo_api(params)
.then((resp) => {
dialog.changeVisible();
message.success('操作成功')
emits('confirm');
})
.finally(() => (dialog.loading = false));
})
.catch(() => {});
},
changeVisible: (mode?: string, formValue?: formType) => {
dialog.visible = !dialog.visible;
form.data = formValue || { ...initForm };
form.data = { ...initForm, ...formValue };
form.mode = mode || '';
console.log(1111111111, form.data);
formRef.value && formRef.value.clearValidate();
},
});
const initForm = {
@ -78,13 +133,14 @@ const initForm = {
permissions: [],
describe: '',
} as formType;
const formRef = ref<FormInstance>();
const form = reactive({
data: { ...initForm },
mode: '',
checkPermission: async (_rule: Rule, value: string[]) => {
if(!value || value.length < 1) return Promise.reject('请选择权限')
return Promise.resolve()
}
if (!value || value.length < 1) return Promise.reject('请选择权限');
return Promise.resolve();
},
});
//

View File

@ -46,12 +46,13 @@
<script setup lang="ts">
import { exportPermission_api } from '@/api/system/permission';
import { Form } from 'ant-design-vue';
Form.useInjectFormItemContext()
const props = defineProps<{
value: any[];
firstWidth: number;
maxHeight: string;
disabled: boolean;
disabled?: boolean;
}>();
const emits = defineEmits(['update:value']);
const searchValue = ref<string>('');
@ -131,18 +132,14 @@ const permission = reactive({
emits('update:value', newProp);
},
makeList: (checkedValue: any[], sourceList: any[]): permissionType[] => {
console.log(checkedValue);
const result = sourceList.map((item) => {
const checked = checkedValue.find(
const checked = checkedValue?.find(
(checkedItem) => checkedItem.permission === item.id,
);
const options = item.actions.map((actionItem: any) => ({
label: actionItem.name,
value: actionItem.action,
}));
console.log(item, checked);
return {
id: item.id,
name: item.name,
@ -150,7 +147,7 @@ const permission = reactive({
checkAll:
(checked &&
item.actions &&
checked?.actions.length === item.actions.length) ||
checked.actions.length === item.actions.length) ||
false,
indeterminate:
(checked &&
@ -183,6 +180,9 @@ type paramsType = {
<style lang="less" scoped>
.permission-choose-container {
.ant-input-affix-wrapper {
border-color: #d9d9d9 !important;
}
.permission-table {
margin-top: 12px;
font-size: 14px;

View File

@ -8,7 +8,6 @@
:request="table.getList"
model="TABLE"
:params="query.params"
>
<template #headerTitle>
<a-button
@ -17,7 +16,7 @@
style="margin-right: 10px"
><plus-outlined />新增</a-button
>
<a-button>菜单实例</a-button>
<a-button @click="router.push('/system/Menu/Setting')">菜单实例</a-button>
</template>
<template #createTime="slotProps">
{{ moment(slotProps.createTime).format('YYYY-MM-DD HH:mm:ss') }}
@ -39,7 +38,7 @@
<a-button
style="padding: 0"
type="link"
@click="table.toDetails(slotProps)"
@click="table.addChildren(slotProps)"
>
<plus-circle-outlined />
</a-button>
@ -50,7 +49,6 @@
ok-text="确定"
cancel-text="取消"
@confirm="table.clickDel(slotProps)"
:disabled="slotProps.status"
>
<a-tooltip>
<template #title>删除</template>
@ -66,13 +64,14 @@
</template>
<script setup lang="ts">
import { getMenuTree_api } from '@/api/system/menu';
import { getMenuTree_api, delMenuInfo_api } from '@/api/system/menu';
import {
SearchOutlined,
DeleteOutlined,
PlusOutlined,
PlusCircleOutlined
PlusCircleOutlined,
} from '@ant-design/icons-vue';
import { message } from 'ant-design-vue';
import moment from 'moment';
const router = useRouter();
@ -229,22 +228,32 @@ const table = reactive({
status: resp.status,
};
},
addChildren: (row: any) => {
console.log(row);
router.push(
`/system/Menu/detail/:id?pid=${row.id}&basePath=${
row.url || ''
}&sortIndex=${row.children.length + 1}`,
);
},
//
toDetails: (row: any) => {
router.push(
`/system/Menu/detail/${row.id || ':id'}?pid=${
row.pid || ''
}&basePath=${row.basePath || ''}&sortIndex=${table.total}`,
}&basePath=${row.url|| ''}&sortIndex=${table.total}`,
);
},
//
clickDel: (row: any) => {
// delPermission_api(row.id).then((resp: any) => {
// if (resp.status === 200) {
// tableRef.value?.reload();
// message.success('!');
// }
// });
console.log(row.id);
delMenuInfo_api(row.id).then((resp: any) => {
if (resp.status === 200) {
tableRef.value?.reload();
message.success('操作成功!');
}
});
},
//
refresh: () => {
@ -257,5 +266,4 @@ const table = reactive({
.menu-container {
padding: 24px;
}
</style>