<template>
  <div>
    <el-card>
      <el-input v-model="roleQuery.roleName" size="small" style="width: 300px;" clearable :placeholder="$t('system.role.placeRoleName')" />
      <el-button size="small" type="primary" :loading="searchBtnLoading" style="margin-left: 10px;" @click="search()">{{ $t('system.role.search') }}</el-button>
      <el-button v-if="checkPermission(ROLE_PERMS.add)" size="small" type="primary" @click="openAddRoleDlg">{{ $t('system.role.addRole') }}</el-button>
    </el-card>

    <el-card style="margin-top: 10px;">
      <el-table v-loading="searchBtnLoading" :data="rolePage" size="small" border fit highlight-current-row>
        <el-table-column :label="$t('system.role.table.roleName')" prop="roleName" align="left" />
        <el-table-column :label="$t('system.role.table.description')" prop="description" align="left" />
        <el-table-column :label="$t('system.role.table.roleCode')" prop="roleCode" align="center" />
        <el-table-column :label="$t('system.role.table.operation')" align="center">
          <template slot-scope="scope">
            <el-button v-if="checkPermission(ROLE_PERMS.assign)" type="text" size="small" @click="getRolePermission(scope.row)">{{ $t('system.role.table.menuPerm') }}</el-button>
            <el-button v-if="checkPermission(ROLE_PERMS.modify)" type="text" size="small" @click="editRole(scope.row)">{{ $t('system.role.table.modify') }}</el-button>
            <el-button v-if="checkPermission(ROLE_PERMS.delete)" type="text" size="small" @click="deleteRole(scope.row.roleId)">{{ $t('system.role.table.delete') }}</el-button>
          </template>
        </el-table-column>
      </el-table>
      <el-pagination
        class="pagination"
        background
        :current-page.sync="roleQuery.pageNum"
        layout="total, prev, pager, next"
        :total="total"
        @current-change="changePage"
      />
    </el-card>

    <el-dialog
      :close-on-click-modal="false"
      :title="$t('system.role.roleDlg.title')"
      :visible.sync="addRoleDlgVisible"
      width="30%"
    >
      <el-form ref="addOrModifyRoleForm" :model="addOrModifyRoleForm">
        <el-form-item :label="$t('system.role.roleDlg.roleName')" prop="roleName" label-width="100px" :rules="[{required: true, message: $t('system.role.roleDlg.valid.roleName'), trigger: 'blur'}]">
          <el-input v-model="addOrModifyRoleForm.roleName" />
        </el-form-item>
        <el-form-item :label="$t('system.role.roleDlg.description')" prop="description" label-width="100px">
          <el-input v-model="addOrModifyRoleForm.description" />
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="addRoleDlgVisible = false">{{ $t('common.btn.cancel') }}</el-button>
        <el-button :loading="addOrModifyRoleBtnLoading" type="primary" @click="saveRole">{{ $t('common.btn.submit') }}</el-button>
      </div>
    </el-dialog>

    <el-dialog :close-on-click-modal="false" :title="$t('system.role.assignDlg.title')" :visible.sync="assignRolePermVisible" width="30%">
      <el-tree
        ref="tree"
        :data="permissionList"
        node-key="permId"
        :expand-on-click-node="false"
        :props="{ children: 'children',label: 'permName',disabled:'isDefault'}"
        style="max-height: 400px;overflow: auto"
      >
        <div slot-scope="{ node, data }" class="custom-tree-node">
          <div>
            <el-checkbox v-model="data.checked" class="perm-checkbox" @change="changePerm(data)" />
            <span>{{ node.label }}</span>
          </div>
        </div>
      </el-tree>
      <div slot="footer" class="dialog-footer">
        <el-button @click="assignRolePermVisible = false">{{ $t('common.btn.cancel') }}</el-button>
        <el-button :loading="assignRolePermBtnLoading" type="primary" @click="saveRolePermission">{{ $t('common.btn.submit') }}</el-button>
      </div>
    </el-dialog>
  </div>

</template>

<script>
import {
  getRolePage,
  addRole,
  assignRolePermission,
  deleteRole,
  editRole,
  getRolePermission
} from '../../../api/system/role'
import { getAllNotDefaultPermTree } from '../../../api/system/perm'
import permissionMixin from '../../../mixins/permission-mixin'
import { ROLE_PERMS } from '../../../permission/permission-system'
import { arrayToTree } from '../../../utils/array'

export default {
  name: 'RoleManagement',
  mixins: [permissionMixin],
  data() {
    return {
      roleQuery: {
        roleName: '',
        pageNum: 1
      },
      rolePage: [],
      searchBtnLoading: false,
      addRoleDlgVisible: false,
      addOrModifyRoleForm: {
        roleId: null,
        roleName: null,
        description: null
      },
      addOrModifyRoleBtnLoading: false,
      assignRolePermVisible: false,
      assignRolePermBtnLoading: false,
      assignPermForm: {
        roleId: null,
        permIds: []
      },
      permissionList: [],
      metaPermissionList: [],
      total: 0,
      ROLE_PERMS
    }
  },
  mounted() {
    this.search()
  },
  methods: {
    search() {
      this.roleQuery.pageNum = 1
      this.searchRole(this.roleQuery)
    },
    searchRole(query) {
      this.searchBtnLoading = true
      getRolePage(query).then(res => {
        this.rolePage = res.result.list
        this.total = Number(res.result.total)
        this.searchBtnLoading = false
      }, () => {
        this.searchBtnLoading = false
      })
    },
    changePage(page) {
      this.roleQuery.pageNum = page
      this.searchRole(this.roleQuery)
    },
    openAddRoleDlg() {
      if (this.$refs.addOrModifyRoleForm !== undefined) {
        this.$refs.addOrModifyRoleForm.resetFields()
      }
      this.addOrModifyRoleForm = {
        roleId: null,
        roleName: null,
        description: null
      }
      this.addRoleDlgVisible = true
    },
    saveRole() {
      this.$refs.addOrModifyRoleForm.validate((valid) => {
        if (valid) {
          this.addOrModifyRoleBtnLoading = true
          if (this.addOrModifyRoleForm.roleId) {
            editRole(this.addOrModifyRoleForm).then(res => {
              this.$message.success(this.$t('common.operationOk'))
              this.searchRole(this.roleQuery)
              this.addOrModifyRoleBtnLoading = false
              this.addRoleDlgVisible = false
            }, () => {
              this.addOrModifyRoleBtnLoading = false
            })
          } else {
            addRole(this.addOrModifyRoleForm).then(res => {
              this.$message.success(this.$t('common.operationOk'))
              this.searchRole(this.roleQuery)
              this.addOrModifyRoleBtnLoading = false
              this.addRoleDlgVisible = false
            }, () => {
              this.addOrModifyRoleBtnLoading = false
            })
          }
        }
      })
    },
    editRole(role) {
      this.openAddRoleDlg()
      this.addOrModifyRoleForm.roleId = role.roleId
      this.addOrModifyRoleForm.roleName = role.roleName
      this.addOrModifyRoleForm.description = role.description
    },
    deleteRole(roleId) {
      this.$confirm(this.$t('system.role.deleteRoleTip'), this.$t('common.tip'), { type: 'error' }).then(() => {
        deleteRole({ roleId }).then(res => {
          this.$message.success(this.$t('common.operationOk'))
          this.searchRole(this.roleQuery)
        })
      }, () => {
      })
    },
    getRolePermission(role) {
      this.assignPermForm.roleId = role.roleId
      this.assignPermForm.permIds = []
      return Promise.all([this.getAllPermission(), getRolePermission(role.roleId)]).then(vals => {
        this.metaPermissionList.forEach(item => {
          item.checked = vals[1].result.some(i => i.permId === item.permId)
        })
        this.permissionList = arrayToTree(this.metaPermissionList, 'permId', 'parentId')
        this.openAssignRolePermDlg()
      }, () => {
      })
    },
    getAllPermission() {
      return getAllNotDefaultPermTree().then(res => {
        let permList = res.result.map(item => {
          item.checked = false
          return item
        })
        this.metaPermissionList = JSON.parse(JSON.stringify(permList))
        // this.permissionList = arrayToTree(res.data, 'permId', 'parentId')
      }, () => {
      })
    },
    openAssignRolePermDlg() {
      this.assignRolePermVisible = true
    },
    getCheckedPermIds(list) {
      list.forEach(item => {
        if (item.checked) {
          this.assignPermForm.permIds.push(item.permId)
        }
        if (item.children) {
          this.getCheckedPermIds(item.children)
        }
      })
    },
    saveRolePermission() {
      this.assignRolePermBtnLoading = true
      this.assignPermForm.permIds = []
      this.getCheckedPermIds(this.permissionList)
      assignRolePermission({ roleId: this.assignPermForm.roleId, permIds: this.assignPermForm.permIds }).then(res => {
        this.$message.success(this.$t('common.operationOk'))
        this.assignRolePermBtnLoading = false
        this.assignRolePermVisible = false
      }, () => {
        this.assignRolePermBtnLoading = false
      })
    },
    changePerm(data) {
      this.setParentPerm(this.permissionList, data)
      this.setChildrenPerm(data)
    },
    setParentPerm(list = [], data) {
      let parentPerm
      list.forEach(item => {
        if (item.permId === data.parentId) {
          parentPerm = item
          parentPerm.checked = parentPerm.checked ? parentPerm.checked : data.checked
          if (parentPerm.parentId) {
            this.setParentPerm(this.permissionList, parentPerm)
          }
        } else {
          this.setParentPerm(item.children, data)
        }
      })
    },
    setChildrenPerm(data) {
      if (!data.children) return
      data.children.forEach(item => {
        item.checked = data.checked
        this.setChildrenPerm(item)
      })
    }
  }
}
</script>
<style lang="scss" scoped="">
.perm-checkbox {
  margin-right: 10px;
}
</style>
