You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

253 lines
7.9 KiB

<template>
<div class="menu-manage-content">
<a-page-header class="ns-page-header" title="栏目管理">
<template #extra>
<!-- todo 隐藏取消-->
<a-button type="primary" @click="submit">提交</a-button>
<a-button style="margin-left: 10px" @click="navigateBack">取消</a-button>
</template>
</a-page-header>
<ns-tree
v-model:expandedKeys="expandedKeys"
:tree-data="treeData"
:fieldNames="fieldNames"
:autoExpandParent="true"
:draggable="true"
@drop="drop">
<template #title="{ code: treeKey, label }">
<a-dropdown :trigger="['contextmenu']">
<span>{{ label }}</span>
<template #overlay>
<a-menu @click="({ key: menuKey }) => onContextMenuClick(treeKey, menuKey, label)">
<a-menu-item key="edit">编辑</a-menu-item>
</a-menu>
</template>
</a-dropdown>
</template>
</ns-tree>
</div>
<a-drawer
title="栏目编辑"
:width="500"
:visible="visible"
:body-style="{ paddingBottom: '80px' }"
:footer-style="{ textAlign: 'right' }"
@close="onClose">
<ns-form :schemas="formSchema" :model="formData" />
<a-button style="margin-right: 8px" @click="onClose">取消</a-button>
<a-button type="primary" @click="onEdit">提交</a-button>
</a-drawer>
</template>
<script lang="ts">
import { computed, defineComponent, reactive, ref, watch } from 'vue';
import { cloneDeep } from 'lodash-es';
import { dropMenu, RouteMenu, editMenuLabel } from '/nerv-base/router/helper/menu-helper';
import { message } from 'ant-design-vue';
import { useRouteStore } from '/nerv-base/store/modules/route';
import { storeToRefs } from 'pinia';
import { useNavigate } from '/nerv-lib/use/use-navigate';
import { appConfigStore } from '/nerv-base/store/modules/app-config';
export default defineComponent({
name: 'NsViewMenuManage',
components: {},
setup() {
const { routeModule } = storeToRefs(useRouteStore());
const routeStore = useRouteStore();
const visible = ref(false);
const onClose = () => {
visible.value = false;
};
const { navigateBack } = useNavigate();
const formData = reactive({
key: '',
className: '',
});
const formSchema = reactive([
{
field: 'className',
label: '栏目名称',
component: 'NsInput',
componentProps: {
placeholder: '请输入栏目名称',
rules: [
{
required: true,
message: '请输入栏目名称',
trigger: 'blur',
},
],
},
},
]);
/**
* 去除菜单里的最终子节点
* @param data
*/
function getTreeData(data: RouteMenu[]) {
const list = cloneDeep(data);
const _list: any = [];
list.forEach((module) => {
module.menus && (module.menus = checkMenu(module.menus));
if (module.code !== 'root') _list.push(module);
});
return _list;
}
function checkMenu(menus) {
menus.forEach((children) => {
if (children.route?.meta?.hideChildren) {
children.menus = [];
} else {
if (children.menus) children.menus = checkMenu(children.menus);
}
});
return menus;
}
const treeData = computed(() => {
return getTreeData(routeModule.value);
});
const expandedKeys = ref<string[]>([]);
const fieldNames = { children: 'menus', title: 'label', key: 'code' };
function drop(info) {
console.log('event', info);
const data = dropMenu(routeModule.value, info);
if (data.success === false) {
message.error(data.msg);
}
if (data.success === true) {
// 移动成功
}
}
const onContextMenuClick = (treeKey: string, menuKey: string | number, label: string) => {
switch (menuKey) {
case 'edit':
visible.value = true;
formData.key = treeKey;
formData.className = label;
break;
default:
message.error('无此操作');
}
console.log(`treeKey: ${treeKey}, menuKey: ${menuKey}`, label);
};
const onEdit = () => {
visible.value = false;
editMenuLabel(routeModule.value, formData.key, formData.className);
// console.log('formData.className', formData.key, formData.className);
};
//保存
function submit() {
//todo 提交给后端 routeModule.value 成功后同步菜单
const appConfig = appConfigStore();
const routeModuleObject: Recordable = {};
function loop(routeModule: ModuleMenu[]) {
for (let i = 0, j = routeModule.length; i < j; i++) {
routeModuleObject[routeModule[i].code] = routeModule[i];
routeModule[i].menus && loop(routeModule[i].menus);
}
}
loop(routeStore.routeModule);
routeStore.routeModuleObject = routeModuleObject;
function loopRoute(routeList) {
for (let i = 0, j = routeList.length; i < j; i++) {
const route = routeList[i];
!route.meta && (route.meta = {});
if (routeModuleObject[route.name] === undefined) {
console.error(`route ${route.name} is not in menu`);
return;
}
if (!route.meta.index || route.meta.index !== routeModuleObject[route.name].sort) {
route.meta.index = routeModuleObject[route.name].sort;
}
if (!route.meta.title || route.meta.title !== routeModuleObject[route.name].label) {
route.meta.title = routeModuleObject[route.name].label;
}
route.children && loopRoute(route.children);
}
}
loopRoute(routeStore.route);
routeStore.route.sort((a, b) => {
return a.meta?.index - b.meta?.index;
});
const initPcResource = { application: {}, menus: [] };
routeStore.routeModule.sort((a, b) => {
return a.route?.meta?.index - b.route?.meta?.index;
});
const info = JSON.parse(JSON.stringify(routeStore.routeModule));
initRouteMouleList(info);
function initRouteMouleList(info) {
info.forEach((item) => {
if (item.menus) {
initRouteMouleList(item.menus);
}
delete item.route;
});
}
initPcResource.application = appConfig.resourceInfo?.application as object;
// initPcResource.menus = appConfig.resourceInfo?.dealReosurceList
// ? appConfig.resourceInfo?.dealReosurceList(info)
// : info;
initPcResource.menus = info;
console.log('-----------', info);
allResoutceList.value = [];
info.forEach((item) => {
initResourceList(item);
});
// testTags.testEdit(2);
// routeStore.syncRoute();
}
const allResoutceList = ref([]);
const initResourceList = (info: object) => {
if (allResoutceList.value.findIndex((x) => x === info.code) === -1) {
allResoutceList.value.push(info.code);
if (info.menus && info.menus.length) {
info.menus.forEach((item: object) => {
initResourceList(item);
});
}
} else {
console.error(`${info.code}已存在,${info.label}`);
return;
}
};
return {
navigateBack,
expandedKeys,
fieldNames,
treeData,
drop,
onContextMenuClick,
visible,
onClose,
onEdit,
formSchema,
formData,
submit,
};
},
});
</script>
<style lang="less" scoped>
.menu-manage-content {
padding: 0 16px 16px 16px;
}
:deep(.ant-tree .ant-tree-treenode) {
padding: 2px 0 4px 0;
}
</style>