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
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>
|
|
|