<template>
  <!-- 角色管理对话框 -->
  <el-dialog
    v-model="visible"
  :title="!dataForm.id ? '新增' : '修改'"
  :close-on-click-modal="false"
  >
  <!-- 表单 -->
  <el-form
    ref="dataFormRef"
  :model="dataForm"
  :rules="dataRule"
  label-width="80px"
  @keyup.enter="onSubmit()"
  >
  <!-- 角色名称输入框 -->
  <el-form-item
    label="角色名称"
    prop="roleName"
  >
  <el-input
    v-model="dataForm.roleName"
  placeholder="角色名称"
  />
  </el-form-item>

  <!-- 备注输入框 -->
  <el-form-item
    label="备注"
    prop="remark"
  >
  <el-input
    v-model="dataForm.remark"
  placeholder="备注"
  />
  </el-form-item>

  <!-- 授权菜单树 -->
  <el-form-item label="授权">
    <el-tree
      ref="menuListTreeRef"
    :data="menuList"
    :props="menuListTreeProps"
    node-key="menuId"
    show-checkbox
    />
  </el-form-item>
  </el-form>

  <!-- 对话框底部按钮组 -->
  <template #footer>
      <span class="dialog-footer">
        <el-button @click="visible = false">取消</el-button> <!-- 取消按钮 -->
        <el-button type="primary" @click="onSubmit()">确定</el-button> <!-- 确认按钮 -->
      </span>
  </template>
  </el-dialog>
</template>

<script setup>
import { ref, reactive, nextTick } from 'vue'
import { ElMessage } from 'element-plus' // 导入消息提示组件
import { treeDataTranslate } from '@/utils' // 导入树数据转换工具函数
import { Debounce } from '@/utils/debounce' // 导入防抖函数

// 定义事件发射器
const emit = defineEmits(['refreshDataList'])

// 临时key，用于解决tree半选中状态项不能传给后台接口问题，待优化
const tempKey = -666666

// 控制对话框显示状态的响应式变量
const visible = ref(false)

// 存储菜单列表的响应式变量
const menuList = ref([])

// 定义菜单树的属性映射
const menuListTreeProps = {
  label: 'name',                             // 树节点标签对应的属性名
  children: 'children'                       // 子节点数组对应的属性名
}

// 表单数据模型，使用reactive定义以使其成为响应式的
const dataForm = reactive({
  id: 0,                                     // 角色ID，默认为0表示新增
  roleName: '',                             // 角色名称
  remark: ''                                // 备注
})

// 表单验证规则，使用reactive定义以使其成为响应式的
const dataRule = reactive({
  roleName: [                               // 验证规则：角色名称
    { required: true, message: '角色名称不能为空', trigger: 'blur' }, // 必填项
    { pattern: /\s\S+|\S+\s|\S/, message: '请输入正确的角色名称', trigger: 'blur' } // 正则表达式验证
  ],
  remark: [                                 // 验证规则：备注
    { required: false, pattern: /\s\S+|\S+\s|\S/, message: '输入格式有误', trigger: 'blur' } // 可选，正则表达式验证
  ]
})

// 引用表单实例
const dataFormRef = ref(null)

// 引用菜单树实例
const menuListTreeRef = ref(null)

/**
 * 初始化方法，接收可选的角色ID参数
 * @param id 角色ID（可选）
 */
const init = (id) => {
  dataForm.id = id || 0 // 如果提供了id，则设置为编辑模式；否则设置为新增模式

  // 获取菜单列表并初始化对话框
  http({
    url: http.adornUrl('/sys/menu/table'),   // API端点
    method: 'get',                           // 请求方式
    params: http.adornParams()               // 请求参数
  })
    .then(({ data }) => {
      menuList.value = treeDataTranslate(data, 'menuId', 'parentId') // 将菜单数据转换为树形结构
    })
    .then(() => {
      visible.value = true // 显示对话框
      return nextTick() // 等待DOM更新
    })
    .then(() => {
      dataFormRef.value?.resetFields() // 重置表单数据
      menuListTreeRef.value?.setCheckedKeys([]) // 清除菜单树的选择状态
    })
    .then(() => {
      if (dataForm.id) { // 如果是编辑模式，则获取角色详情
        http({
          url: http.adornUrl(`/sys/role/info/${dataForm.id}`), // API端点
          method: 'get',                                       // 请求方式
          params: http.adornParams()                          // 请求参数
        })
          .then(({ data }) => {
            dataForm.roleName = data.roleName // 设置角色名称
            dataForm.remark = data.remark     // 设置备注

            // 处理菜单授权数据，移除临时key
            const idx = data.menuIdList.indexOf(tempKey)
            if (idx !== -1) {
              data.menuIdList.splice(idx, data.menuIdList.length - idx)
            }

            // 设置菜单树的已选节点
            menuListTreeRef.value?.setCheckedKeys(data.menuIdList)
          })
      }
    })
}

// 将init方法暴露出去，以便父组件调用
defineExpose({ init })

/**
 * 提交表单方法
 */
const onSubmit = Debounce(() => { // 使用防抖函数防止快速点击多次提交
  dataFormRef.value?.validate((valid) => { // 验证表单
    if (valid) { // 如果表单验证通过
      http({
        url: http.adornUrl('/sys/role'),   // API端点
        method: dataForm.id ? 'put' : 'post', // 如果有id则是编辑操作，否则为新增操作
        data: http.adornData({
          roleId: dataForm.id || undefined, // 角色ID，新增时不发送
          roleName: dataForm.roleName,     // 角色名称
          remark: dataForm.remark,         // 备注
          // 收集菜单树的选中和半选中的节点ID
          menuIdList: [].concat(
            menuListTreeRef.value?.getCheckedKeys(),
            [tempKey],
            menuListTreeRef.value?.getHalfCheckedKeys()
          )
        })
      })
        .then(() => {
          ElMessage({
            message: '操作成功',
            type: 'success',
            duration: 1500,
            onClose: () => {
              visible.value = false // 关闭对话框
              emit('refreshDataList') // 发射刷新事件通知父组件刷新数据列表
            }
          })
        })
    }
  })
})
</script>
