<!--suppress ALL -->
<template>
  <div class="menuContainer">
    <div class="topTree" :style="{height:(allHeight-142)+'px'}">
      <el-tree class="tree" :data="menus" @node-drop="handleDrop" draggable :allow-drop="allowDrop" :allow-drag="allowDrag" :render-content="renderContent" :highlight-current="true" :expand-on-click-node="true" node-key="id" default-expand-all></el-tree>
    </div>
    <el-row style="margin-left: 24px;margin-top:20px;">
      <el-button type="primary" v-if="!isCopy" @click="addRootMenu" style="width:98px;">添加</el-button>
      <span style="float:right" v-if="isCopy">
        <el-button size="mini" type="primary" @click="saveCopy(0)">粘贴到根</el-button>
        <el-button size="mini" type="danger" @click="isCopy=false">取消粘贴</el-button>
      </span>
    </el-row>

    <el-dialog :visible.sync="dialogVisible" title="添加菜单">
      <el-form :model="menu" ref="form" label-position="top" size="small">
        <el-form-item label="菜单名" prop="name" :rules="[{required: true, message: '请填写菜单名', trigger: 'blur'}]">
          <el-input v-model="menu.name"></el-input>
        </el-form-item>
        <el-form-item label="菜单地址" prop="href">
          <el-input v-model="menu.href"></el-input>
        </el-form-item>
        <el-form-item prop="icon">
          <template slot="label">
            图标
            <a href="https://fontawesome.com/icons?d=gallery&s=brands,solid&m=free" target="_blank" class="available-icons">查看所有可用图标</a>
          </template>
          <el-input v-model="icon">
            <template slot="append">
              <span ref="iconContainer" style="font-size: 18px">
                <i class="fas fa-"></i>
              </span>
            </template>
          </el-input>
        </el-form-item>
        <el-form-item label="手持机" prop="handheld">
          <el-select placeholder="手持机" size="small" v-model="menu.handheld" class="filter-item">
            <el-option label="N" value="N"></el-option>
            <el-option label="Y" value="Y"></el-option>
          </el-select>
        </el-form-item>
      </el-form>
      <div slot="footer">
        <el-button @click="dialogVisible = false" size="small">取消</el-button>
        <el-button type="primary" @click="addMenu" :loading="loading" size="small">保存</el-button>
      </div>
    </el-dialog>

    <el-dialog :visible.sync="roleShow" title="菜单权限" width="500px">
      <el-table :data="rowInfo" tooltip-effect="dark" border style="width: 100%">
        <el-table-column label="操作" width="50">
          <template slot-scope="scope">
            <el-checkbox v-model="scope.row.hasMenu" @change="handleSelectionChange(scope.row)"></el-checkbox>
          </template>
        </el-table-column>
        <el-table-column label="用户名" prop="name">
          <template slot-scope="scope">{{ scope.row.name }}</template>
        </el-table-column>
      </el-table>
    </el-dialog>
  </div>
</template>
<script>
import axios from 'axios'
import { mapState } from 'vuex'

export default {
  created() {
    this.getData();
  },
  data() {
    return {
      dialogVisible: false,
      curr: null,
      loading: false,
      menus: [],
      menu: {
        name: '',
        href: '',
        icon: '',
        handheld: 'N',
      },
      icon: '',
      roleShow: false,
      rowInfo: [],
      editMenuId: 0,
      isCopy: false,
      copyJson: {}
    }
  },
  computed: {
    ...mapState(['allHeight']),
  },
  methods: {
    addRootMenu() {
      this.menu = {
        parentId: 0,
        name: '',
        href: '',
        icon: 'bars',
        handheld: 'N',
      };
      this.icon = 'bars';
      if (this.menus && this.menus.length > 0) {
        this.menu.sort = this.menus[this.menus.length - 1].sort + 1;
      } else {
        this.menu.sort = 1;
      }
      this.dialogVisible = true;
      setTimeout(() => {
        this.showIcon('bars');
      }, 100)
    },
    showAddDialog(node, data) {
      this.menu = {
        parentId: node.data.id,
        name: '',
        href: '',
        icon: null,
        handheld: 'N',
      };
      this.icon = '';
      if (node.childNodes && node.childNodes.length > 0) {
        this.menu.sort = node.childNodes[node.childNodes.length - 1].data.sort + 1;
      } else {
        this.menu.sort = 1;
      }
      this.dialogVisible = true;
      setTimeout(() => {
        this.showIcon('');
      }, 100)
    },
    showEditDialog(node, data) {
      const getIconName = icon => {
        let iconName = '';
        if (icon) {
          iconName = icon.replace('fas ', '').replace('fab ', '').replace('fa-', '');
        }
        return iconName || null;
      }
      let iconName = getIconName(data.icon);
      this.menu = {
        id: data.id,
        name: data.name,
        href: data.href,
        icon: iconName,
        handheld: data.handheld,
      };
      this.icon = iconName;
      this.dialogVisible = true;
      setTimeout(() => {
        this.showIcon(iconName);
      }, 100)
    },
    addMenu() {
      this.$refs.form.validate(valid => {
        if (valid) {
          this.loading = true;
          this.$http.post({
            url: this.menu.id ? '/sysMenu/update' : '/sysMenu/save',
            data: this.menu
          }).then(res => {
            this.loading = false;
            if (res.success) {
              this.$message.success('添加成功')
              this.dialogVisible = false;
              this.getData();
            } else {
              this.$message.warning('添加失败')
            }
          })
        }
      });
    },
    remove(node, data) {
      this.$confirm('确定删除菜单？', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'error'
      }).then(() => {
        this.$http.post({
          url: '/sysMenu/del',
          data: {
            id: data.id
          }
        }).then(res => {
          if (res.success) {
            this.$message.success('删除成功');
            this.getData();
          } else {
            this.$message.error('删除失败');
          }
        })
      }).catch(() => {
      });
    },
    moveUp(node, data) {
      const formData = d => {
        let formData = new FormData();
        for (let key in d) {
          if (d.hasOwnProperty(key)) {
            formData.append(key, d[key]);
          }
        }
        return formData;
      }
      if (node.previousSibling) {
        axios.all([axios.post(this.$baseUrl + '/sysMenu/update', formData({
          id: node.data.id,
          sort: node.previousSibling.data.sort
        })), axios.post(this.$baseUrl + '/sysMenu/update', formData({
          id: node.previousSibling.data.id,
          sort: node.data.sort
        }))]).then(axios.spread((acct, perms) => {
          this.getData();
        }));
      }
    },
    moveDown(node, data) {
      const formData = d => {
        let formData = new FormData();
        for (let key in d) {
          if (d.hasOwnProperty(key)) {
            formData.append(key, d[key]);
          }
        }
        return formData;
      }
      if (node.nextSibling) {
        axios.all([axios.post(this.$baseUrl + '/sysMenu/update', formData({
          id: node.data.id,
          sort: node.nextSibling.data.sort
        })), axios.post(this.$baseUrl + '/sysMenu/update', formData({
          id: node.nextSibling.data.id,
          sort: node.data.sort
        }))]).then(axios.spread((acct, perms) => {
          this.getData();
        }));
      }
    },
    copy(node, data) {
      this.isCopy = true
      this.copyJson = data
    },
    showRole(node, data) {
      this.$http.get({
        url: '/sysRole/all',
        data: {
          menuId: data.id
        }
      }).then(res => {
        if (res.success) {
          res.data.forEach(item => {
            if (item.menuFlag > 0) {
              item.hasMenu = true
            }
            else {
              item.hasMenu = false
            }
          })
          this.rowInfo = res.data
          this.roleShow = true
          this.editMenuId = data.id
          // setTimeout(() => {
          //     res.data.forEach(item => {
          //         if (item.menuFlag > 0) {
          //             this.$refs.multipleTable.toggleRowSelection(item);
          //         }
          //     })
          // }, 500)
        }
      })
    },
    handleSelectionChange(row) {
      console.log(row)
      var data = row
      var menuIds = row.menuIds ? row.menuIds.split(',') : []

      if (row.hasMenu) {
        menuIds.push(this.editMenuId)
      }
      else {
        menuIds = this.clearList(this.editMenuId.toString(), menuIds)

      }

      data.menuIds = menuIds.join(',')

      this.$http.post({
        url: '/sysRole/update',
        data: {
          id: data.id,
          menuIds: data.menuIds
        }
      }).then(res => {
        if (res.success) {
          this.menus = res.data
        }
      })

    },
    clearList(id, list) {
      for (var i = 0; i < list.length; i++) {
        if (list[i] == id) {
          list.splice(i, 1)
        }
      }
      return list

    },
    getData() {
      this.$http.get({
        url: '/sysMenu/menuTree'
      }).then(res => {
        if (res.success) {
          this.menus = res.data
        }
      })
    },
    saveCopy(data) {
      var formData = { ...this.copyJson }
      if (data == 0) {
        formData.parentId = 0
      }
      else {
        formData.parentId = data.id
      }
      console.log(JSON.stringify(formData))
      axios.post('/sysMenu/copy', formData).then(res => {
        if (res.status === 200) {
          if (res.data.success) {
            this.getData()
            this.isCopy = false
          }
        }
      }).catch(e => {
      })

    },
    renderContent(h, { node, data, store }) {
      return this.isCopy ? (
        <span class="custom-tree-node" >
          <span>{data.name}</span>
          <span class="url">{data.href}</span>
          <span class="">
            <el-button size="mini" type="primary" on-click={(e) => { this.saveCopy(data), e.stopPropagation() }} class="up">粘贴</el-button>
          </span>
        </span >
      ) : (
          <span class="custom-tree-node" >
            <span class="name">{data.name}</span>
            <span class="url">{data.href}</span>
            <span class="opt">
              <el-button size="mini" plain on-click={(e) => { this.showRole(node, data), e.stopPropagation() }} >权限</el-button>
              <el-button size="mini" type="primary" plain on-click={(e) => { this.moveUp(node, data), e.stopPropagation() }} class="up">上移</el-button>
              <el-button size="mini" type="primary" plain on-click={(e) => { this.moveDown(node, data), e.stopPropagation() }}>下移</el-button>
              <el-button size="mini" type="warning" plain on-click={(e) => { this.showEditDialog(node, data), e.stopPropagation() }}>编辑</el-button>
              <el-button size="mini" type="success" plain on-click={(e) => { this.showAddDialog(node, data), e.stopPropagation() }}>添加</el-button>
              <el-button size="mini" type="danger" plain on-click={(e) => { this.remove(node, data), e.stopPropagation() }}>删除</el-button>
              <el-button size="mini" plain on-click={(e) => { this.copy(node, data), e.stopPropagation() }} class="up">复制</el-button>
            </span>
          </span >
        );
    },
    showIcon(val) {
      if (!this.$refs.iconContainer) return;
      if (FontAwesome.icon({ prefix: 'fas', iconName: val })) {
        this.$refs.iconContainer.innerHTML = '';
        let i = document.createElement('i');
        i.className = 'fas fa-' + val;
        this.$refs.iconContainer.append(i);
        FontAwesome.dom.i2svg();
        this.menu.icon = 'fas fa-' + val;
      } else if (FontAwesome.icon({ prefix: 'fab', iconName: val })) {
        this.$refs.iconContainer.innerHTML = '';
        let i = document.createElement('i');
        i.className = 'fab fa-' + val;
        this.$refs.iconContainer.append(i);
        FontAwesome.dom.i2svg();
        this.menu.icon = 'fab fa-' + val;
      } else {
        this.$refs.iconContainer.innerHTML = '';
        let i = document.createElement('i');
        i.className = 'fab fa-' + val;
        this.$refs.iconContainer.append(i);
        FontAwesome.dom.i2svg();
        this.menu.icon = '';
      }
    },
    handleDrop(draggingNode, dropNode, dropType, ev) {
      switch (dropType) {
        case 'inner':
          this.updateParent(draggingNode.data.id, dropNode ? dropNode.data.id : 0)
          break;
        case 'before':
          this.updateParent(draggingNode.data.id, dropNode ? dropNode.data.parentId : 0)
          break;
        case 'after':
          this.updateParent(draggingNode.data.id, dropNode ? dropNode.data.parentId : 0)
          break;
        default:
          break;
      }
    },
    allowDrop(draggingNode, dropNode, type) {
      if (type == 'inner' && dropNode.data.href) {
        return false;
      }
      else {
        return true;
      }
    },
    allowDrag(draggingNode) {
      if (draggingNode.data.canMove == 'Y') {
        return true
      }
      else {
        return false
      }
    },
    updateParent(id, parentId) {
      if (parentId == id) {
        this.getData()
        return
      }
      this.$http.post({
        url: '/sysMenu/update',
        data: {
          parentId: parentId,
          id: id
        }
      }).then(res => {
        if (res.success) {
          this.getData()
        }
      })
    }
  },
  watch: {
    icon(val) {
      this.showIcon(val);
    }
  }
}
</script>
<style lang="less">
.menuContainer {
  background-color: #fff;
  padding: 20px;
  border-radius: 4px;
}
.topTree {
  overflow: auto;
  // padding-bottom: 20px;
  border: 1px solid #f2f4f5;
}
.custom-tree-node {
  overflow: hidden;
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 14px;
  padding-right: 8px;
  .name {
    min-width: 200px;
  }
  .url {
    flex-grow: 1;
    text-align: right;
    margin-right: 20px;
    color: #999;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .opt {
    opacity: 0;
    min-width: 452px;
  }
}

.custom-tree-node:hover {
  .opt {
    opacity: 1;
  }
}

.available-icons {
  color: #409eff;
  text-decoration: none;
  &:hover {
    color: #409eff;
    text-decoration: none;
  }
}
</style>
