<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 { useTags } from '/nerv-base/store/modules/tags'; 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.type === 'noChildrenMenu') { // children.menus = []; // } else { // if (children.menus) children.menus = checkMenu(children.menus); // } 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 成功后同步菜单 // testTags.testEdit(2); routeStore.syncRoute(); } 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; min-height: 100%; height: 100%; background: #e5ebf0; } :deep(.ant-tree .ant-tree-treenode) { padding: 2px 0 4px 0; } .ns-page-header { margin-bottom: 0 !important; padding-top: 7px !important; padding-bottom: 7px !important; width: calc(100% + 32px); margin-left: -16px; background: #fff; font-size: 18px; .title { cursor: pointer; font-size: 18px !important; } } :deep(.ant-tree) { border-top: 16px solid #e5ebf0; padding: 16px 21px; background: #fff; height: calc(100% - 47px) !important; } </style>