<template>
  <div>
    <div class="head-container">
      <el-input v-model="deptName" placeholder="请输入部门名称" clearable size="small" prefix-icon="el-icon-search" style="margin-bottom: 20px" />
    </div>

    <div class="head-container">
      <el-tree
        :data="deptOptions"
        :props="defaultProps"
        :expand-on-click-node="false"
        :filter-node-method="filterNode"
        ref="tree"
        node-key="id"
        default-expand-all
        highlight-current
        @node-click="handleNodeClick"
      >
        <span class="custom-tree-node" slot-scope="{ node, data }">
          <span>{{ node.label }}</span>
          <span class="tree-node-operations">
            <el-button
              type="text"
              size="mini"
              icon="el-icon-plus"
              @click.stop="() => handleAddDept(data)"
              v-hasPermi="['system:dept:add']"
              title="新增子部门"
            ></el-button>
            <el-button
              type="text"
              size="mini"
              icon="el-icon-edit"
              @click.stop="() => handleEditDept(data)"
              v-hasPermi="['system:dept:edit']"
              title="修改部门"
            ></el-button>
            <el-button
              v-if="data.parentId !== 0 && data.id !== 0"
              type="text"
              size="mini"
              icon="el-icon-delete"
              @click.stop="() => handleDeleteDept(data)"
              v-hasPermi="['system:dept:remove']"
              title="删除部门"
            ></el-button>
          </span>
        </span>
      </el-tree>
    </div>

    <!-- 添加或修改部门对话框 -->
    <el-dialog :title="deptTitle" :visible.sync="deptOpen" width="600px" append-to-body>
      <el-form ref="deptForm" :model="deptForm" :rules="deptRules" label-width="80px">
        <el-row>
          <el-col :span="24" v-if="deptForm.parentId !== 0">
            <el-form-item label="上级部门" prop="parentId">
              <treeselect v-model="deptForm.parentId" :options="deptOptionsForDialog" :normalizer="normalizer" placeholder="选择上级部门" />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="12">
            <el-form-item label="部门名称" prop="deptName">
              <el-input v-model="deptForm.deptName" placeholder="请输入部门名称" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="显示排序" prop="orderNum">
              <el-input-number v-model="deptForm.orderNum" controls-position="right" :min="0" />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="12">
            <el-form-item label="负责人" prop="leader">
              <el-input v-model="deptForm.leader" placeholder="请输入负责人" maxlength="20" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="联系电话" prop="phone">
              <el-input v-model="deptForm.phone" placeholder="请输入联系电话" maxlength="11" />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="12">
            <el-form-item label="邮箱" prop="email">
              <el-input v-model="deptForm.email" placeholder="请输入邮箱" maxlength="50" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="部门状态">
              <el-radio-group v-model="deptForm.status">
                <el-radio
                  v-for="dict in dict.type.sys_normal_disable"
                  :key="dict.value"
                  :label="dict.value"
                >{{dict.label}}</el-radio>
              </el-radio-group>
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button type="primary" @click="submitDeptForm">确 定</el-button>
        <el-button @click="cancelDept">取 消</el-button>
      </div>
    </el-dialog>
  </div>
</template>

<script>
import { listDept, getDept, delDept, addDept, updateDept, listDeptExcludeChild } from "@/api/system/dept"
import Treeselect from "@riophae/vue-treeselect"
import "@riophae/vue-treeselect/dist/vue-treeselect.css"

export default {
  name: "DeptTreeWithOperations",
  dicts: ['sys_normal_disable'],
  components: { Treeselect },
  props: {
    deptOptions: {
      type: Array,
      default: () => []
    },
    defaultProps: {
      type: Object,
      default: () => ({
        children: "children",
        label: "label"
      })
    }
  },
  data() {
    return {
      deptName: undefined,
      deptOpen: false, // 是否显示部门弹出层
      deptTitle: "", // 部门弹出层标题
      deptForm: {}, // 部门表单数据
      deptOptionsForDialog: [], // 部门对话框中的部门树选项
      // 部门表单校验
      deptRules: {
        parentId: [
          { required: true, message: "上级部门不能为空", trigger: "blur" }
        ],
        deptName: [
          { required: true, message: "部门名称不能为空", trigger: "blur" }
        ],
        orderNum: [
          { required: true, message: "显示排序不能为空", trigger: "blur" }
        ],
        email: [
          {
            type: "email",
            message: "请输入正确的邮箱地址",
            trigger: ["blur", "change"]
          }
        ],
        phone: [
          {
            pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/,
            message: "请输入正确的手机号码",
            trigger: "blur"
          }
        ]
      }
    }
  },
  watch: {
    // 根据名称筛选部门树
    deptName(val) {
      this.$refs.tree.filter(val)
    }
  },
  methods: {
    /** 转换部门数据结构 */
    normalizer(node) {
      if (node.children && !node.children.length) {
        delete node.children
      }
      return {
        id: node.deptId,
        label: node.deptName,
        children: node.children
      }
    },
    // 筛选节点
    filterNode(value, data) {
      if (!value) return true
      return data.label.indexOf(value) !== -1
    },
    // 节点单击事件
    handleNodeClick(data) {
      this.$emit('node-click', data)
    },
    /** 新增部门按钮操作 */
    handleAddDept(data) {
      this.resetDeptForm()
      this.deptForm.parentId = data.id
      this.deptOpen = true
      this.deptTitle = "添加部门"
      listDept().then(response => {
        this.deptOptionsForDialog = this.handleTree(response.data, "deptId")
      })
    },
    /** 修改部门按钮操作 */
    handleEditDept(data) {
      this.resetDeptForm()
      const deptId = data.id
      getDept(deptId).then(response => {
        this.deptForm = response.data
        this.deptOpen = true
        this.deptTitle = "修改部门"
        listDeptExcludeChild(deptId).then(response => {
          this.deptOptionsForDialog = this.handleTree(response.data, "deptId")
          if (this.deptOptionsForDialog.length == 0) {
            const noResultsOptions = { deptId: this.deptForm.parentId, deptName: this.deptForm.parentName, children: [] }
            this.deptOptionsForDialog.push(noResultsOptions)
          }
        })
      })
    },
    /** 删除部门按钮操作 */
    handleDeleteDept(data) {
      const deptName = data.label
      const deptId = data.id
      this.$modal.confirm('是否确认删除名称为"' + deptName + '"的数据项？').then(function() {
        return delDept(deptId)
      }).then(() => {
        this.$emit('dept-deleted')
        this.$modal.msgSuccess("删除成功")
      }).catch(() => {})
    },
    /** 部门表单重置 */
    resetDeptForm() {
      this.deptForm = {
        deptId: undefined,
        parentId: undefined,
        deptName: undefined,
        orderNum: undefined,
        leader: undefined,
        phone: undefined,
        email: undefined,
        status: "0"
      }
      this.resetForm("deptForm")
    },
    // 取消部门表单
    cancelDept() {
      this.deptOpen = false
      this.resetDeptForm()
    },
    /** 提交部门表单 */
    submitDeptForm() {
      this.$refs["deptForm"].validate(valid => {
        if (valid) {
          if (this.deptForm.deptId != undefined) {
            updateDept(this.deptForm).then(response => {
              this.$modal.msgSuccess("修改成功")
              this.deptOpen = false
              this.$emit('dept-updated')
            })
          } else {
            addDept(this.deptForm).then(response => {
              this.$modal.msgSuccess("新增成功")
              this.deptOpen = false
              this.$emit('dept-added')
            })
          }
        }
      })
    },
    // 工具方法：处理树形数据
    handleTree(data, id, parentId, children) {
      let config = {
        id: id || 'id',
        parentId: parentId || 'parentId',
        childrenList: children || 'children'
      }

      var childrenListMap = {}
      var nodeIds = {}
      var tree = []

      for (let d of data) {
        let parentId = d[config.parentId]
        if (childrenListMap[parentId] == null) {
          childrenListMap[parentId] = []
        }
        nodeIds[d[config.id]] = d
        childrenListMap[parentId].push(d)
      }

      for (let d of data) {
        let parentId = d[config.parentId]
        if (nodeIds[parentId] == null) {
          tree.push(d)
        }
      }

      for (let t of tree) {
        adaptToChildrenList(t)
      }

      function adaptToChildrenList(o) {
        if (childrenListMap[o[config.id]] !== null) {
          o[config.childrenList] = childrenListMap[o[config.id]]
        }
        if (o[config.childrenList]) {
          for (let c of o[config.childrenList]) {
            adaptToChildrenList(c)
          }
        }
      }
      return tree
    }
  }
}
</script>

<style scoped>
.custom-tree-node {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 14px;
  padding-right: 8px;
}

.tree-node-operations {
  display: none;
}

.custom-tree-node:hover .tree-node-operations {
  display: block;
}

.tree-node-operations .el-button {
  padding: 4px;
  margin-left: 2px;
}
</style>
