<template>
  <div class="koi-flex">
    <KoiCard>
      <!-- 搜索条件 -->
      <el-form v-show="showSearch" :inline="true">
        <el-form-item label="角色名称" prop="roleName">
          <el-input
            placeholder="请输入角色名称"
            v-model="searchParams.roleName"
            clearable
            style="width: 240px"
            @keyup.enter.native="handleListPage"
          ></el-input>
        </el-form-item>
        <el-form-item label="角色状态" prop="status">
          <el-select
            placeholder="请选择角色状态"
            v-model="searchParams.status"
            clearable
            style="width: 240px"
            @keyup.enter.native="handleListPage"
          >
            <el-option label="启用" value="0" />
            <el-option label="停用" value="1" />
          </el-select>
        </el-form-item>
        <el-form-item label="角色编号" prop="roleKey">
          <el-input
            placeholder="请输入角色编号"
            v-model="searchParams.roleKey"
            clearable
            style="width: 240px"
            @keyup.enter.native="handleListPage"
          ></el-input>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" icon="search" plain v-throttle="handleSearch">搜索</el-button>
          <el-button type="danger" icon="refresh" plain v-debounce="resetSearch">重置</el-button>
        </el-form-item>
      </el-form>
      <!-- 表格头部按钮 -->
      <el-row :gutter="10">
        <el-col :span="1.5">
          <el-button type="primary" icon="plus" plain @click="handleAdd()">新增</el-button>
        </el-col>
<!--        <el-col :span="1.5">-->
<!--          <el-button type="success" icon="edit" plain @click="handleUpdate()" :disabled="single">修改</el-button>-->
<!--        </el-col>-->
        <el-col :span="1.5">
          <el-button type="danger" icon="delete" plain @click="handleDelete()" :disabled="multiple">删除</el-button>
        </el-col>
<!--        <el-col :span="1.5">-->
<!--          <el-button type="warning" icon="download" plain>导出</el-button>-->
<!--        </el-col>-->
        <KoiToolbar v-model:showSearch="showSearch" @refreshTable="handleListPage"></KoiToolbar>
      </el-row>

      <div class="h-20px"></div>
      <!-- 数据表格 -->
      <el-table
        v-loading="loading"
        border
        :data="tableList"
        empty-text="暂时没有数据哟"
        @selection-change="handleSelectionChange"
      >
        <el-table-column type="selection" width="55" align="center" />
        <el-table-column label="序号" prop="roleId" width="120px" align="center" type="index"></el-table-column>
        <el-table-column label="角色名称" prop="roleName" :show-overflow-tooltip="true" align="center"></el-table-column>
        <el-table-column label="角色编号" prop="roleKey" width="120px" align="center"></el-table-column>
        <el-table-column label="角色状态" prop="status" width="100px" align="center">
          <template #default="scope">
            <el-switch
              v-model="scope.row.status"
              active-text="启用"
              inactive-text="停用"
              active-value="0"
              inactive-value="1"
              :inline-prompt="true"
              @change="handleSwitch(scope.row)"
            >
            </el-switch>
          </template>
        </el-table-column>
        <el-table-column label="角色排序" prop="roleSort" width="100px" align="center"></el-table-column>
        <el-table-column label="角色备注" prop="remark" :show-overflow-tooltip="true" align="center"></el-table-column>
        <el-table-column label="创建时间" prop="createTime" width="180px" align="center"></el-table-column>
        <el-table-column label="操作" align="center" width="150" fixed="right">
          <template #default="{ row }">
            <el-tooltip content="修改" placement="top">
              <el-button
                type="primary"
                icon="Edit"
                circle
                plain
                @click="handleUpdate(row)"
                v-auth="['system:role:edit']"
              ></el-button>
            </el-tooltip>
            <el-tooltip content="数据权限" placement="top">
              <el-button
                type="primary"
                icon="Switch"
                circle
                plain
                @click="handleDataScope(row)"
                v-auth="['system:role:edit']"
              ></el-button>
            </el-tooltip>
            <el-tooltip content="删除" placement="top">
              <el-button
                type="danger"
                icon="Delete"
                circle
                plain
                @click="handleDelete(row)"
                v-auth="['system:role:remove']"
              ></el-button>
            </el-tooltip>
          </template>
        </el-table-column>
      </el-table>

      <div class="h-20px"></div>
      <!-- 分页 -->
      <Pagination :queryParams="searchParams" :total="total" :getList="handleListPage" />

      <!-- 分配菜单 -->
      <KoiDrawer
        ref="koiDrawerRef"
        :title="title"
        size="360"
        @koiConfirm="handleMenuConfirm"
        @koiCancel="handleMenuCancel"
        :loading="confirmLoading"
        cancelText="关闭"
      >
        <template #content>
          <div>
            <el-form ref="formRef" :rules="rules" :model="form" label-width="80px" status-icon>
              <el-form-item label="角色名称" prop="roleName">
                <el-input v-model="form.roleName" placeholder="请输入角色名称" clearable />
              </el-form-item>
            <el-form-item label="角色编号" prop="roleKey">
              <el-input v-model="form.roleKey" placeholder="请输入角色编号" clearable />
            </el-form-item>
              <el-form-item label="角色状态" prop="status">
                <el-select v-model="form.status" placeholder="请选择角色状态" style="width: 260px" clearable>
                  <el-option label="启用" value="0" />
                  <el-option label="停用" value="1" />
                </el-select>
              </el-form-item>
              <el-form-item label="角色排序" prop="roleSort">
                <el-input-number v-model="form.roleSort" style="width: 260px" clearable />
              </el-form-item>
              <el-form-item label="角色备注" prop="remark">
                <el-input v-model="form.remark" type="text" placeholder="请输入角色备注" />
              </el-form-item>
            </el-form>
            <el-tree
              ref="treeRef"
              :data="treeData"
              show-checkbox
              :default-expanded-keys="expandedKey"
              node-key="id"
              highlight-current
              :props="defaultProps"
            />
          </div>
        </template>
      </KoiDrawer>

      <!--分配权限-->
      <KoiDialog
        ref="koiDialogRef"
        :loading="confirmLoading"
        title="分配权限"
        :height="550"
        @koiCancel="cancelDataScope"
        @koiConfirm="submitDataScope"
      >
        <template #content>
          <el-form :model="form" label-width="80px">
            <el-form-item label="角色名称">
              <el-input v-model="form.roleName" :disabled="true" />
            </el-form-item>
            <el-form-item label="权限字符">
              <el-input v-model="form.roleKey" :disabled="true" />
            </el-form-item>
            <el-form-item label="权限范围">
              <el-select v-model="form.dataScope" @change="dataScopeSelectChange">
                <el-option
                  v-for="item in dataScopeOptions"
                  :key="item.value"
                  :label="item.label"
                  :value="item.value"
                ></el-option>
              </el-select>
            </el-form-item>
            <el-form-item label="数据权限" v-show="form.dataScope == 2">
<!--              <el-checkbox v-model="deptExpand" @change="handleCheckedTreeExpand($event, 'dept')">展开/折叠</el-checkbox>-->
<!--              <el-checkbox v-model="deptNodeAll" @change="handleCheckedTreeNodeAll($event, 'dept')">全选/全不选</el-checkbox>-->
<!--              <el-checkbox v-model="form.deptCheckStrictly" @change="handleCheckedTreeConnect($event, 'dept')">父子联动</el-checkbox>-->
              <el-tree
                class="tree-border"
                :data="deptOptions"
                show-checkbox
                default-expand-all
                ref="deptRef"
                node-key="id"
                :check-strictly="!form.deptCheckStrictly"
                empty-text="加载中，请稍候"
                :props="{ label: 'label', children: 'children' }"
              ></el-tree>
            </el-form-item>
          </el-form>
        </template>
      </KoiDialog>
    </KoiCard>
  </div>
</template>

<script setup lang="ts" name="role">
import {nextTick, onMounted, reactive, ref} from "vue";
import {koiMsgBox, koiMsgError, koiMsgWarning, koiNoticeError, koiNoticeSuccess} from "@/utils/koi.ts";
import {addRole, changeRoleStatus, delRole, getRole, listRole, updateRole, roleDeptTreeselect, dataScope} from "@/api/system/role/index.ts";
import {roleMenuTreeselect, treeselect} from "@/api/system/menu/index.ts";
import {ElMessageBox} from 'element-plus';
import useAuthStore from "@/stores/modules/auth.ts";

// 表格加载动画Loading
const loading = ref(false);
// 是否显示搜索表单[默认显示]
const showSearch = ref<boolean>(true); // 默认显示搜索条件
// 表格数据
const tableList = ref<any>([]);
// 查询参数
const searchParams = ref({
  pageNum: 1, // 第几页
  pageSize: 15, // 每页显示多少条
  roleName: "",
  status: "",
  roleKey: ""
});
const total = ref<number>(0);
const authStore = useAuthStore()
// 直接使用 computed 绑定 store 值
const rolesId = authStore.loginUser.rolesId
const role = authStore.roleList

/** 重置搜索参数 */
const resetSearchParams = () => {
  searchParams.value = {
    pageNum: 1,
    pageSize: 15,
    roleName: "",
    status: "",
    roleKey: ""
  };
};

/** 搜索 */
const handleSearch = () => {
  console.log("搜索");
  searchParams.value.pageNum = 1;
  handleListPage();
};

/** 重置 */
const resetSearch = () => {
  console.log("重置搜索");
  resetSearchParams();
  handleListPage();
};

/** @current-change：点击分页组件页码发生变化：例如：切换第2、3页 OR 上一页 AND 下一页 OR 跳转某一页 */
/** @size-change：点击分页组件下拉选择条数发生变化：例如：选择10条/页、20条/页等 */
// 分页查询，@current-change AND @size-change都会触发分页，调用后端分页接口
/** 数据表格 */
const handleListPage = async () => {
  try {
    loading.value = true;
    tableList.value = []; // 重置表格数据
    const res: any = await listRole(searchParams.value);
    if(role[0] === 'admin') {
      tableList.value = res.rows
    } else {
      tableList.value = res.rows?.filter((v: { roleId?: number }) => v.roleId !== rolesId) || [];
    }
    total.value = res.total;
    loading.value = false;
  } catch (error) {
    koiNoticeError("数据查询失败，请刷新重试");
  }
};

const ids = ref([]); // 选择数组
const single = ref<boolean>(true); // 非单个禁用
const multiple = ref<boolean>(true); // 非多个禁用

/** 是否多选 */
const handleSelectionChange = (selection: any) => {
  ids.value = selection.map((item: any) => item.roleId);
  single.value = selection.length != 1; // 单选
  multiple.value = !selection.length; // 多选
};

/** 添加 */
const handleAdd = () => {
  addGetTreeselect()
  // 打开对话框
  koiDrawerRef.value.koiOpen();
  // 重置表单
  resetForm();
  // 标题
  title.value = "角色添加";
  form.value.status = "0";
};

// 标题
const title = ref("角色管理");
// form表单Ref
const formRef = ref<any>();

// form表单
let form = ref<any>({
  roleId: undefined,
  roleName: undefined,
  roleKey: undefined,
  roleSort: 0,
  status: "0",
  menuIds: [],
  deptIds: [],
  menuCheckStrictly: true,
  deptCheckStrictly: true,
  remark: undefined,
  dataScope: '4'
});

/** 清空表单数据 */
const resetForm = () => {
  // 等待 DOM 更新完成
  nextTick(() => {
    if (formRef.value) {
      // 重置该表单项，将其值重置为初始值，并移除校验结果
      formRef.value.resetFields();
    }
  });
  Object.assign(form.value, {
    roleId: undefined,
    roleName: undefined,
    roleKey: undefined,
    roleSort: 0,
    status: "0",
    menuIds: [],
    deptIds: [],
    menuCheckStrictly: true,
    deptCheckStrictly: true,
    remark: undefined,
    dataScope: '4'
  });
};

/** 表单规则 */
const rules = reactive({
  roleName: [{ required: true, message: "请输入角色名字", trigger: "blur" }],
  roleKey: [{ required: true, message: "请输入角色编号", trigger: "blur" }],
  status: [{ required: true, message: "请输入选择角色状态", trigger: "blur" }],
  roleSort: [{ required: true, message: "请输入排序号", trigger: "blur" }]
});

// 确定按钮是否显示Loading
const confirmLoading = ref(false);

/** 状态开关 */
const handleSwitch = (row: any) => {
  let text = row.status === "0" ? "启用" : "停用";

  ElMessageBox.confirm("确认要[" + text + "]-[" + row.roleName + "]角色吗？", '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning',
  })
    .then(() => {
      return changeRoleStatus(row.roleId, row.status);
    })
    .then(() => {
      koiNoticeSuccess("修改成功");
    })
    .catch(() => {
      row.status = row.status === '0' ? '1' : '0';
    });
};

/** 删除 */
const handleDelete = (row: any) => {
  const id = row.roleId || ids.value
  if (id == null || id == "") {
    koiMsgWarning("请选择需要删除的数据");
    return;
  }
  koiMsgBox("您确认需要删除角色名称[" + row.roleName + "]么？")
    .then(async () => {
      try {
        await delRole(id);
        koiNoticeSuccess("删除成功");
        handleListPage()
      } catch (error) {
        console.log(error);
        koiNoticeError("删除失败，请刷新重试");
      }
    })
    .catch(() => {
      koiMsgError("已取消");
    });
};

const koiDrawerRef = ref();
const treeRef = ref();
const treeData = ref<any>([]);

// 配置属性
const defaultProps = {
  children: "children",
  label: "label"
};
// 默认展开配置
const expandedKey = ref();

/** 查询所有菜单 */
const addGetTreeselect = async () => {
  const res: any = await treeselect()
  treeData.value = res.data;
}
/** 根据角色ID查询菜单树结构 */
const getRoleMenuTreeselect = (roleId:number) => {
  return roleMenuTreeselect(roleId).then(res => {
    treeData.value = res.menus;
    return res;
  });
}

/** 修改角色 */
const handleUpdate = async (row?: any) => {
  const roleId = row?.roleId ?? ids.value?.[0];
  if (!roleId) {
    koiMsgWarning("请选择需要分配菜单的数据");
    return;
  }
  title.value = "角色修改";
  // 打开抽屉
  koiDrawerRef.value.koiOpen();
  try {
    // 获取角色详情
    const res = await getRole(roleId);
    form.value = res.data;
    // 清空选中的菜单
    if (treeRef.value) {
      treeRef.value.setCheckedKeys([], false);
    }
    // 获取角色的菜单权限
    const roleMenu = await getRoleMenuTreeselect(roleId);
    if (roleMenu?.checkedKeys?.length) {
      await nextTick(); // 确保 UI 更新完成再操作
      treeRef.value?.setCheckedKeys(roleMenu.checkedKeys, true);
    }
  } catch (error) {
    console.error("获取角色信息或菜单权限失败:", error);
  }
};

/** 保存 */
const handleMenuConfirm = async () => {
  if (!formRef.value) return;
  confirmLoading.value = true;
  (formRef.value as any).validate(async (valid: any) => {
    if (valid) {
      form.value.menuIds = getCheckedKeys() // 获取选中菜单
      if (form.value.roleId != null && form.value.roleId != "") {
        try {
          await updateRole(form.value);
          koiNoticeSuccess("修改成功");
          confirmLoading.value = false;
          resetForm();
          handleListPage();
          koiDrawerRef.value.koiClose();
        } catch (error) {
          confirmLoading.value = false;
          koiNoticeError("修改失败，请刷新重试");
        }
      } else {
        try {
          await addRole(form.value);
          koiNoticeSuccess("添加成功");
          confirmLoading.value = false;
          resetForm();
          handleListPage();
          koiDrawerRef.value.koiClose();
        } catch (error) {
          console.log(error);
          confirmLoading.value = false;
          koiNoticeError("添加失败，请刷新重试");
        }
      }
    } else {
      koiMsgError("验证失败，请检查填写内容");
      confirmLoading.value = false;
    }
  });
};

const deptOptions = ref()
const koiDialogRef = ref()
const deptRef = ref()
/** 数据范围选项*/
const dataScopeOptions = ref([
  { value: "2", label: "自定数据权限" },
  { value: "3", label: "本部门数据权限" },
  { value: "4", label: "本部门及以下数据权限" },
  { value: "5", label: "仅本人数据权限" }
])

/** 选择角色权限范围触发 */
const dataScopeSelectChange = (value) => {
  if (value !== "2") {
    deptRef.value.setCheckedKeys([]);
  }
}

/** 分配数据权限操作 */
const handleDataScope = (row) => {
  resetForm()
  const deptTreeSelect = getDeptTree(row.roleId);
  getRole(row.roleId).then(response => {
    form.value = response.data;
    koiDialogRef.value.koiOpen()
    nextTick(() => {
      deptTreeSelect.then(res => {
        nextTick(() => {
          if (deptRef.value) {
            deptRef.value.setCheckedKeys(res.checkedKeys);
          }
        });
      });
    });
  });
}

/** 根据角色ID查询部门树结构 */
const getDeptTree = (roleId)  => {
  return roleDeptTreeselect(roleId).then(res => {
    deptOptions.value = res.depts;
    return res;
  });
}

const cancelDataScope = () => {
  koiDialogRef.value.koiClose();
}

// 确定分配权限
const submitDataScope = () => {
  if (form.value.roleId != undefined) {
    form.value.deptIds = getDeptAllCheckedKeys();
    dataScope(form.value).then(res => {
      if(res.code === 200) {
        koiNoticeSuccess('修改成功')
        cancelDataScope()
        handleListPage();
      }
    });
  }
}

/** 所有部门节点数据 */
const getDeptAllCheckedKeys = () => {
  // 目前被选中的部门节点
  let checkedKeys = deptRef.value.getCheckedKeys();
  // 半选中的部门节点
  let halfCheckedKeys = deptRef.value.getHalfCheckedKeys();
  checkedKeys.unshift.apply(checkedKeys, halfCheckedKeys);
  return checkedKeys;
}

const getCheckedKeys = () => {
  // 获取选择的keys
  const checkedKeys = treeRef.value?.getCheckedKeys();
  // console.log("选择",checkedKeys)
  // 获取半选的keys(即保存选择子节点的父节点[父节点下的子节点并没有选择完])
  const halfCheckKeys = treeRef.value?.getHalfCheckedKeys();
  // console.log("半选",halfCheckKeys)
  // 组合成最后的keys
  return halfCheckKeys.concat(checkedKeys)
}

/** 取消 */
const handleMenuCancel = () => {
  koiDrawerRef.value.koiClose();
  resetForm()
};

onMounted(() => {
  // 获取表格数据
  handleListPage();
  if(role[0] === 'admin') {
    dataScopeOptions.value.unshift({
    value: "1", label: "全部数据权限"
    })
  }
})
</script>

<style lang="scss" scoped></style>
