<template>
  <popup
    v-model="showDialog"
    :title="popupTitle"
    width="500px"
    :close-on-click-modal="false"
    :confirmLoading="isLoading"
    @confirm="handleSubmit"
  >
    <el-scrollbar max-height="500px" class="px-3 mx-[-12px]">
      <el-form ref="formRef" :model="formData" :rules="formRules" label-width="80px" v-loading="isLoading">
        <el-form-item label="角色名称" prop="name">
          <el-input v-model="formData.name" placeholder="请输入角色名称" clearable />
        </el-form-item>
        <el-form-item label="备注" prop="desc">
          <el-input
            v-model="formData.desc"
            type="textarea"
            :autosize="{ minRows: 2, maxRows: 4 }"
            placeholder="请输入备注"
            maxlength="200"
            show-word-limit
          />
        </el-form-item>
        <el-form-item label="排序" prop="sort">
          <el-input-number v-model="formData.sort" :min="0" />
        </el-form-item>
        <el-form-item label="权限" prop="menu_id">
          <div class="w-full flex flex-wrap items-center">
            <el-checkbox label="展开/折叠" @change="handleExpand" />
            <el-checkbox label="全选/不全选" @change="handleSelectAll" />
            <el-checkbox v-model="checkStrictly" label="父子联动" />
          </div>
          <el-tree
            class="w-full mt-1"
            ref="treeRef"
            :data="menuTreeData"
            node-key="id"
            :props="{ label: 'name', children: 'children' }"
            show-checkbox
            :check-strictly="!checkStrictly"
          />
        </el-form-item>
      </el-form>
    </el-scrollbar>
  </popup>
</template>

<script setup lang="ts">
import type { FormInstance, ElTree, CheckboxValueType } from 'element-plus'
import { menuOptions } from '@/api/permission/menu'
import { roleAdd, roleEdit } from '@/api/permission/role'

// 定义组件事件
const emit = defineEmits<{
  (event: 'success'): void
}>()

// 表单引用
const formRef = shallowRef<FormInstance>()
// 树组件引用
const treeRef = shallowRef<InstanceType<typeof ElTree>>()
// 模式：add=新增，edit=编辑
const mode = ref<'add' | 'edit'>('add')
// 加载状态
const isLoading = ref(false)
// 是否显示弹窗
const showDialog = ref(false)
// 初始表单数据
const initialFormData = {
  id: '',
  name: '',
  desc: '',
  sort: 0,
  menu_id: []
}
// 表单数据
const formData = reactive<Record<string, any>>({ ...initialFormData })
// 表单验证规则
const formRules = reactive({
  name: [
    {
      required: true,
      message: '请输入角色名称',
      trigger: ['blur', 'change']
    }
  ]
})
// 弹窗标题
const popupTitle = computed(() => {
  return mode.value == 'edit' ? '编辑角色' : '新增角色'
})
// 父子联动
const checkStrictly = ref(true)
// 菜单数据
const menuTreeData = ref<any[]>([])

// 打开弹窗
const open = (type: 'add' | 'edit' = 'add') => {
  mode.value = type
  showDialog.value = true
}
// 设置表单数据
const setFormData = async (row?: Record<string, any>) => {
  resetForm()
  await getOptions()
  if (!row) return
  Object.keys(formData).forEach((key: string) => {
    if (row[key] != undefined) formData[key] = row[key]
  })
  setCheckedKeys()
}
// 表单重置
const resetForm = () => {
  Object.assign(formData, initialFormData)
  formRef.value?.resetFields()
}
// 获取菜单选项
const getOptions = async () => {
  isLoading.value = true
  const data = await menuOptions()
  menuTreeData.value = data || []
  isLoading.value = false
}
// 设置菜单选中项
const setCheckedKeys = () => {
  nextTick(() => {
    formData.menu_id.forEach((v: number) => {
      nextTick(() => {
        treeRef.value!.setChecked(v, true, false)
      })
    })
  })
}
// 获取部门选项选中状态
const getDeptAllCheckedKeys = () => {
  const checkedKeys = treeRef.value?.getCheckedKeys() || []
  const halfCheckedKeys = treeRef.value?.getHalfCheckedKeys() || []
  checkedKeys?.unshift.apply(checkedKeys, halfCheckedKeys)
  return checkedKeys
}
// 展开/折叠节点
const handleExpand = (value: CheckboxValueType) => {
  const treeList = menuTreeData.value
  for (let i = 0; i < treeList.length; i++) {
    const node = treeRef.value?.store?.nodesMap?.[treeList[i].id]
    if (node) node.expanded = Boolean(value)
  }
}
// 全选/不全选
const handleSelectAll = (value: CheckboxValueType) => {
  treeRef.value?.setCheckedNodes(value ? menuTreeData.value : [])
}
// 提交表单
const handleSubmit = () => {
  formRef.value?.validate(async (valid) => {
    if (valid) {
      isLoading.value = true
      formData.menu_id = getDeptAllCheckedKeys()
      const submitEvent = mode.value === 'edit' ? roleEdit : roleAdd
      submitEvent(formData)
        .then(() => {
          isLoading.value = false
          showDialog.value = false
          ElMessage.success('操作成功')
          emit('success')
        })
        .catch(() => {
          isLoading.value = false
        })
    }
  })
}

onMounted(() => {
  getOptions()
})

defineExpose({
  open,
  setFormData
})
</script>
