<template>
  <a-modal v-model:visible="props.visible" title="权限设置" width="500px" @cancel="dialogClose">
    <div>
      <a-checkbox v-model:checked="expandFlag" @change="handleExpand">展开/折叠</a-checkbox>
      <a-checkbox v-model:checked="checkedFlag" @change="handleSelectAll">全选/不全选</a-checkbox>
      <div>
        <a-tree
          :tree-data="menuTree"
          :fieldNames="{ children: 'children', title: 'name', key: 'id' }"
          :height="600"
          v-model:checkedKeys="checkedKeys"
          v-model:expandedKeys="expandedKeys"
          @check="onChangePermissionsTree"
          checkable
        />
      </div>
    </div>
    <template #footer>
      <span class="dialog-footer">
        <a-button @click="dialogClose">取消</a-button>
        <a-button :loading="subLoading" type="primary" @click="submit"> 确定 </a-button>
      </span>
    </template>
  </a-modal>
</template>
<script lang="ts" setup>
  import { getRoleMenuList, roleMenuSave } from '@/api/system/role';
  import { buildTree } from '@/utils/auth';
  import { message } from 'ant-design-vue';
  import { onMounted, ref } from 'vue';
  import { useLockFn } from '@/utils/useLockFn';
  import { isArray } from '@/utils/is';

  /**
   * 定义接收的参数
   */
  const props = defineProps({
    visible: {
      type: Boolean,
      required: true,
      default: false,
    },
    roleId: {
      type: Number,
      required: true,
      default: 0,
    },
  });

  /**
   * 定义参数变量
   */
  const emit = defineEmits(['success', 'update:visible']);
  const checkedFlag = ref(false);
  const expandFlag = ref(false);
  const allMenuIds = ref([]);
  const checkedKeys = ref([]);
  const expandedKeys = ref([]);
  const menuArray = ref<any[]>([]);
  const menuTree = ref<any[]>([]);

  /**
   * 执行扩展、收缩
   */
  const handleExpand = () => {
    if (expandFlag.value) {
      expandedKeys.value = allMenuIds.value;
    } else {
      expandedKeys.value = [];
    }
  };

  /**
   * 执行选中全部
   */
  const handleSelectAll = () => {
    if (checkedFlag.value) {
      checkedKeys.value = allMenuIds.value;
    } else {
      checkedKeys.value = [];
    }
  };

  /**
   * 执行提交表单
   */
  const handleSubmit = async () => {
    let keys = [];
    if (!isArray(checkedKeys.value)) {
      checkedKeys.value.checked.map((item) => {
        keys.push(item);
      });
      checkedKeys.value.halfChecked.map((item) => {
        keys.push(item);
      });
    } else {
      keys = checkedKeys.value;
    }
    await roleMenuSave({ menuIds: keys, roleId: props.roleId });
    message.success('操作成功');
    emit('update:visible', false);
    emit('success');
  };

  const { lockFn: submit } = useLockFn(handleSubmit);

  /**
   * 关闭窗体
   */
  const dialogClose = () => {
    emit('update:visible', false);
  };

  /**
   * 树结构选中发生变化
   * @param node 节点
   * @param event 事件
   */
  const onChangePermissionsTree = (node, event) => {
    checkedKeys.value = node;
  };

  /**
   * 设置表单数据
   */
  const setFormData = async () => {
    const data = await getRoleMenuList(props.roleId);
    menuTree.value = buildTree(data);
    menuArray.value = data;
    menuArray.value.map((item) => {
      allMenuIds.value.push(item.id);
    });
    const keys = checkTree(menuTree.value, 0, [], []);
    checkedKeys.value = { checked: keys.checkedIds, halfChecked: keys.halfCheckedIds };
  };

  /**
   * 选中树结构
   * @param nodes 节点
   * @param parentId 上级ID
   * @param checkedIds 选中ID集合
   * @param halfCheckedIds
   */
  function checkTree(nodes, parentId = null, checkedIds, halfCheckedIds) {
    nodes.forEach((node) => {
      let allChildrenChecked = true;
      let someChildrenChecked = false;

      // 检查子节点
      if (node.children && node.children.length > 0) {
        checkTree(node.children, node.id, checkedIds, halfCheckedIds); // 递归检查子节点

        // 遍历子节点来确定父节点的状态
        node.children.forEach((child) => {
          if (child.checked) {
            someChildrenChecked = true;
            // 如果子节点被选中，可能需要将子节点的ID也加入checkedIds（取决于需求）
            // 但通常我们只关心父节点和叶子节点的checked状态
            halfCheckedIds.push(child.id); // 可选，根据需要添加
          } else {
            allChildrenChecked = false;
          }
        });

        // 根据子节点的状态更新父节点的状态及数组
        if (allChildrenChecked) {
          // 如果所有子节点都选中，则父节点也被视为选中
          checkedIds.push(node.id);
        } else if (someChildrenChecked) {
          // 如果部分子节点选中，则父节点被视为半选
          halfCheckedIds.push(parentId || node.id); // parentId用于处理递归时的父节点
        }
        // 注意：如果所有子节点都未选中，则父节点不会被添加到任何数组中
        // 但如果业务需求是即使所有子节点都未选中，父节点也需要以某种方式被标记，
        // 你需要在这里添加额外的逻辑。
      } else {
        // 如果是叶子节点，直接根据其checked状态处理
        if (node.checked) {
          checkedIds.push(node.id);
        }
      }
    });
    return { checkedIds, halfCheckedIds };
  }

  /**
   * 钩子函数
   */
  onMounted(() => {
    setFormData();
  });
</script>
<style lang="less"></style>
