|
@@ -0,0 +1,270 @@
|
|
|
+<template>
|
|
|
+ <div class="hui-flex hui-content">
|
|
|
+ <div class="hui-flex-box hui-flex hui-table">
|
|
|
+ <div class="hui-content-insert">
|
|
|
+ <el-button type="primary" size="small" @click="insert(-1)">新增主菜单</el-button>
|
|
|
+ </div>
|
|
|
+ <div class="hui-flex-box">
|
|
|
+ <el-table ref="elTable" :data="tableData" row-key="id" border height="100%">
|
|
|
+ <el-table-column prop="title" label="菜单名称" width="180">
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column prop="iconClass" label="菜单图标" width="180">
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column prop="index" label="菜单URL">
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="操作" width="180" align="center">
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <div class="hui-table-operation">
|
|
|
+ <span class="table-operation" v-if="scope.row.isMenu === '1'"
|
|
|
+ @click="insert(scope.row.id)">新增</span>
|
|
|
+ <span class="table-operation" @click="update(scope.row)">编辑</span>
|
|
|
+ <span class="table-operation" @click="deleteItem(scope.row.id)">删除</span>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="排序" align="center" width="50">
|
|
|
+ <template>
|
|
|
+ <i class="el-icon-rank handle"></i>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <template slot="empty">
|
|
|
+ <el-empty description="暂无数据"></el-empty>
|
|
|
+ </template>
|
|
|
+ </el-table>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <el-dialog :close-on-click-modal="false" title="菜单" :visible.sync="dialogVisible" width="900px"
|
|
|
+ :append-to-body="true">
|
|
|
+ <edit v-if="dialogVisible" :updateData="updateData" ref="mainForm" @callback="dialogVisible = false"
|
|
|
+ @sure="sure">
|
|
|
+ </edit>
|
|
|
+ </el-dialog>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+ import {
|
|
|
+ getMenuList,
|
|
|
+ insertMenu,
|
|
|
+ updateMenu
|
|
|
+ } from '@/api/system'
|
|
|
+ import edit from '@/components/work/system/main/edit'
|
|
|
+ import {
|
|
|
+ setComment
|
|
|
+ } from '@/uitls/auth';
|
|
|
+ import Sortable from 'sortablejs'
|
|
|
+ export default {
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ tableData: [],
|
|
|
+ comment: [],
|
|
|
+ dialogVisible: false,
|
|
|
+ tableId: 1,
|
|
|
+ nowDataId: -1,
|
|
|
+ updateData: {},
|
|
|
+ menuData: {},
|
|
|
+ type: ''
|
|
|
+ }
|
|
|
+ },
|
|
|
+ mounted() {
|
|
|
+ this.init();
|
|
|
+ this.initRowDrop();
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ init(type) {
|
|
|
+ getMenuList().then(res => {
|
|
|
+ if (res.state) {
|
|
|
+ if (!res.data || res.data.length === 0) return;
|
|
|
+ this.menuData = res.data[1];
|
|
|
+ this.tableData = JSON.parse(this.menuData.data);
|
|
|
+ this.comment = [];
|
|
|
+ this.testIndex(this.tableData);
|
|
|
+ this.testComment(this.tableData);
|
|
|
+ if (type === 'reload') {
|
|
|
+ this.$store.dispatch('app/changeMenuData', this.tableData);
|
|
|
+ setComment(JSON.stringify(this.comment));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ })
|
|
|
+ },
|
|
|
+ initRowDrop() {
|
|
|
+ const elTable = this.$refs.elTable.$el.querySelector('.el-table__body-wrapper tbody');
|
|
|
+ Sortable.create(elTable, {
|
|
|
+ animation: 150,
|
|
|
+ handle: '.handle', // 拖拽手柄(整行可拖拽)
|
|
|
+ ghostClass: 'sortable-ghost', // 拖拽占位符样式
|
|
|
+ onEnd: (evt) => {
|
|
|
+ const {
|
|
|
+ oldIndex,
|
|
|
+ newIndex,
|
|
|
+ item
|
|
|
+ } = evt;
|
|
|
+ // 获取被拖拽行的原始数据
|
|
|
+ const draggedElement = item.__vue__?.row;
|
|
|
+ if (!draggedElement) return;
|
|
|
+ // 递归查找节点及其父级
|
|
|
+ const findNode = (data, id, parent = null) => {
|
|
|
+ for (let i = 0; i < data.length; i++) {
|
|
|
+ if (data[i].id === id) return {
|
|
|
+ node: data[i],
|
|
|
+ parent,
|
|
|
+ index: i
|
|
|
+ };
|
|
|
+ if (data[i].children) {
|
|
|
+ const result = findNode(data[i].children, id, data[i]);
|
|
|
+ if (result) return result;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ };
|
|
|
+ // 获取被拖拽节点的信息
|
|
|
+ const draggedInfo = findNode(this.tableData, draggedElement.id);
|
|
|
+ if (!draggedInfo) return;
|
|
|
+
|
|
|
+ // 获取目标位置(通过 newIndex 直接定位)
|
|
|
+ const getTargetParentAndIndex = (data, targetIndex) => {
|
|
|
+ let flatData = [];
|
|
|
+ const flatten = (nodes, parent = null) => {
|
|
|
+ nodes.forEach(node => {
|
|
|
+ flatData.push({
|
|
|
+ node,
|
|
|
+ parent
|
|
|
+ });
|
|
|
+ if (node.children) flatten(node.children, node);
|
|
|
+ });
|
|
|
+ };
|
|
|
+ flatten(data);
|
|
|
+ return flatData[targetIndex];
|
|
|
+ };
|
|
|
+
|
|
|
+ const targetInfo = getTargetParentAndIndex(this.tableData, newIndex);
|
|
|
+ if (!targetInfo) return;
|
|
|
+
|
|
|
+ // 从原位置移除
|
|
|
+ if (!draggedInfo.parent) {
|
|
|
+ this.tableData.splice(draggedInfo.index, 1);
|
|
|
+ } else {
|
|
|
+ draggedInfo.parent.children.splice(draggedInfo.index, 1);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ // 插入到新位置(作为同级或子级)
|
|
|
+ const targetParent = targetInfo.parent || {
|
|
|
+ children: this.tableData
|
|
|
+ }; // 根节点的父级为 null
|
|
|
+ const targetSiblingIndex = targetParent.children.indexOf(targetInfo.node);
|
|
|
+
|
|
|
+ if (targetSiblingIndex !== -1) {
|
|
|
+ targetParent.children.splice(targetSiblingIndex, 0, draggedInfo.node);
|
|
|
+ } else {
|
|
|
+ if (!targetInfo.node.children) {
|
|
|
+ this.$set(targetInfo.node, 'children', []);
|
|
|
+ }
|
|
|
+ targetInfo.node.children.push(draggedInfo.node);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 强制更新视图
|
|
|
+ this.$set(this, 'tableData', [...this.tableData]);
|
|
|
+ this.dropSuccess();
|
|
|
+ }
|
|
|
+ });
|
|
|
+ },
|
|
|
+ testIndex(tableData) {
|
|
|
+ for (let i = 0; i < tableData.length; i++) {
|
|
|
+ if (tableData[i].id + 1 > this.tableId) this.tableId = tableData[i].id + 1;
|
|
|
+ if (tableData[i].children) this.testIndex(tableData[i].children);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ testComment(item, id, form) {
|
|
|
+ if (id == -1) return item.push(form);
|
|
|
+ if (this.type == 'delete') {
|
|
|
+ let index = item.findIndex(node => node.id == id);
|
|
|
+ if (index > -1) item.splice(index, 1);
|
|
|
+ }
|
|
|
+ for (let i = 0; i < item.length; i++) {
|
|
|
+ if (item[i].id == id) {
|
|
|
+ if (this.type == 'insert') {
|
|
|
+ if (!item[i].children) item[i].children = [];
|
|
|
+ item[i].children.push(form);
|
|
|
+ } else if (this.type == 'update') {
|
|
|
+ item[i] = form;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (item[i].index && this.comment.filter(node => node == item[i].index).length == 0) this.comment.push(
|
|
|
+ item[i].index);
|
|
|
+ if (item[i].children) this.testComment(item[i].children, id, form);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ insert(id) {
|
|
|
+ this.type = 'insert';
|
|
|
+ this.nowDataId = id;
|
|
|
+ this.updateData = {};
|
|
|
+ this.dialogVisible = true;
|
|
|
+ },
|
|
|
+ update(item) {
|
|
|
+ this.type = 'update';
|
|
|
+ this.nowDataId = item.id;
|
|
|
+ this.updateData = JSON.parse(JSON.stringify(item));
|
|
|
+ this.dialogVisible = true;
|
|
|
+ },
|
|
|
+ deleteItem(id) {
|
|
|
+ this.type = 'delete';
|
|
|
+ this.nowDataId = id;
|
|
|
+ this.updateData = {};
|
|
|
+ this.sure();
|
|
|
+ },
|
|
|
+ sure() {
|
|
|
+ let obj = JSON.parse(JSON.stringify(this.tableData));
|
|
|
+ this.comment = [];
|
|
|
+ this.testComment(obj, this.nowDataId, this.returnForm());
|
|
|
+ this.menuData.id ? updateMenu({
|
|
|
+ id: this.menuData.id,
|
|
|
+ data: JSON.stringify(obj),
|
|
|
+ comment: JSON.stringify(this.comment)
|
|
|
+ }).then(this.successFunc) : insertMenu({
|
|
|
+ data: JSON.stringify(obj),
|
|
|
+ comment: JSON.stringify(this.comment)
|
|
|
+ }).then(this.successFunc);
|
|
|
+ },
|
|
|
+ dropSuccess() {
|
|
|
+ let obj = JSON.parse(JSON.stringify(this.tableData));
|
|
|
+ this.comment = [];
|
|
|
+ this.testComments(obj);
|
|
|
+ updateMenu({
|
|
|
+ id: this.menuData.id,
|
|
|
+ data: JSON.stringify(obj),
|
|
|
+ comment: JSON.stringify(this.comment)
|
|
|
+ }).then(this.successFunc)
|
|
|
+ },
|
|
|
+ testComments(item) {
|
|
|
+ for (let i = 0; i < item.length; i++) {
|
|
|
+ if (item[i].index && this.comment.filter(node => node == item[i].index).length == 0) this.comment.push(
|
|
|
+ item[i].index);
|
|
|
+ if (item[i].children) this.testComment(item[i].children);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ returnForm() {
|
|
|
+ if (this.type == 'delete') return {};
|
|
|
+ if (!this.$refs.mainForm) return {};
|
|
|
+ let form = this.$refs.mainForm.sureIncrease();
|
|
|
+ if (this.type == 'insert') form['id'] = this.tableId;
|
|
|
+ return form;
|
|
|
+ },
|
|
|
+ successFunc(res) {
|
|
|
+ if (res.state) {
|
|
|
+ this.$message({
|
|
|
+ type: 'success',
|
|
|
+ message: '操作成功'
|
|
|
+ })
|
|
|
+ this.init('reload');
|
|
|
+ this.dialogVisible = false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ components: {
|
|
|
+ edit
|
|
|
+ },
|
|
|
+ }
|
|
|
+</script>
|
|
|
+
|
|
|
+<style lang="scss"></style>
|