<template>
	<el-dialog
		:title="`【${state.rowName}】权限配置`"
		v-model="state.dialogVisible"
		draggable
		@opened="opened"
		@close="close"
		append-to-body
		destroy-on-close
	>
		<div class="custom-tree-node-container" v-loading="state.loading">
			<el-row :gutter="10">
				<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
					展开/折叠：<el-switch
						v-model="state.menuExpand"
						@change="handleCheckedTreeExpand"
						inline-prompt
						active-text="折叠"
						inactive-text="展开"
					></el-switch>
				</el-col>
				<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
					全选/全不选：<el-switch
						v-model="state.menuNodeAll"
						@change="handleCheckedTreeNodeAll"
						inline-prompt
						active-text="全不选"
						inactive-text="全选"
					></el-switch>
				</el-col>
			</el-row>
			<div class="border-box">
				<el-input v-model="filterText" placeholder="权限名称" clearable />
				<el-tree
					class="tree-border mt20"
					:data="state.menuTableData"
					show-checkbox
					ref="menuRef"
					node-key="permissionCode"
					check-on-click-node
					check-strictly
					:expand-on-click-node="false"
					:props="{ label: 'pageName', children: 'children', class: customNodeClass }"
					:filter-node-method="filterNode"
				>
					<template #default="{ data }">
						<!--												<span>{{ data.pageName }}-{{ data.permissionCode }}</span>-->
						<span>
							{{ data.pageName }}
							({{ data.menuType === 1 ? '目录' : data.menuType === 2 ? '菜单' : data.menuType === 3 ? '按钮' : ' ' }})
						</span>
					</template>
				</el-tree>
			</div>
		</div>
		<template #footer>
			<span class="dialog-footer">
				<el-button @click="closeDialog" class="default-button">取 消</el-button>
				<el-button type="primary" @click="onSubmit" :loading="state.loading">确 定</el-button>
			</span>
		</template>
	</el-dialog>
</template>

<script setup lang="ts" name="rolePermission">
import { reactive, ref, watch } from 'vue';
import { ElMessage } from 'element-plus';
import { getMenuList } from '@/api/system/menu';
import { getRolePower, setRolePower } from '@/api/system/roles';

// 定义子组件向父组件传值/事件
const emit = defineEmits(['updateList']);
interface Tree {
	id: number;
	label: string;
	isPenultimate?: boolean;
	expanded: boolean;
	menuType?: number;
	pageName: string;
	children?: Tree[];
}

// 定义变量内容
const state = reactive<any>({
	dialogVisible: false, // 弹窗
	menuTableData: <EmptyArrayType>[], //所有菜单按钮
	systemMenuArr: <EmptyArrayType>[], // 选中的菜单
	currentRow: {}, // 当前行
	expandRowKeys: [], // 展开的行
	rowName: '', // 当前行名称
	menuExpand: false, // 展开
	menuNodeAll: false, // 全选
	loading: false, // 加载
});
const menuRef = ref<RefType>();
const customNodeClass = (data: Tree) => {
	if (data.menuType === 2) {
		return 'is-penultimate';
	}
	return null;
};
// 打开弹窗
const openDialog = (row: any) => {
	getMenuListApi();
	state.currentRow = row;
	state.systemMenuArr = <EmptyArrayType>[];
	state.menuExpand = false;
	state.menuNodeAll = false;
	state.rowName = row.displayName;
	state.loading = true;
	state.dialogVisible = true;
};
// 树形扁平化
const treeFlat = (source: any[]) => {
	let res: any = [];
	source.forEach((el) => {
		res.push(el);
		el.children && res.push(...treeFlat(el.children));
	});
	return res;
};
//  打开弹窗后查询已有权限
const opened = () => {
	getRolePower({ roleid: state.currentRow.id })
		.then((res: any) => {
			let arr: string[] = res.result?.systemMenuArr ?? [];
			arr = arr.map((v: any) => v.code);
			menuRef.value.setCheckedKeys(arr);
			const arr1 = treeFlat(state.menuTableData);
			if (arr.length === arr1.length) state.menuNodeAll = true;
			state.loading = false;
		})
		.catch(() => {
			state.loading = false;
		});
};

const close = () => {
	filterText.value = '';
};
const filterText = ref('');
watch(filterText, (val) => {
	menuRef.value!.filter(val);
});
const filterNode = (value: string, data: Tree) => {
	if (!value) return true;
	return data.pageName.includes(value);
};

// 关闭弹窗
const closeDialog = () => {
	state.dialogVisible = false;
};
let newArr: string[] = [];
// 获取所有code
const getCode = (arr: any) => {
	if (!arr) return [];
	arr.forEach((v: any) => {
		newArr.push(v.permissionCode);
		if (v.children?.length) {
			getCode(v.children);
		}
	});
	return newArr;
};
// 递归筛选isHide为false并且不是公共权限的数据
const filterTree = (arr: any) => {
	return arr
		.filter((v: any) => !v.isHide || v.permissionCode === '999000')
		.map((v: any) => {
			if (v.children?.length) {
				return {
					...v,
					children: filterTree(v.children),
				};
			} else {
				return v;
			}
		});
};
// 获取所有菜单
const getMenuListApi = () => {
	getMenuList().then((res: any) => {
		state.menuTableData = filterTree(res?.result);
	});
};
/** 树权限（展开/折叠）*/
const handleCheckedTreeExpand = (value: boolean) => {
	for (let i = 0; i < state.menuTableData.length; i++) {
		menuRef.value.store.nodesMap[state.menuTableData[i].permissionCode].expanded = value;
	}
	// expandNodes(menuRef.value.root, value);
};
// 遍历树形数据，设置每一项的expanded属性，实现展开收起
/*const expandNodes = (node: any, value: boolean) => {
	node.expanded = value;
	for (let i = 0; i < node.childNodes.length; i++) {
		node.childNodes[i].expanded = value;
		if (node.childNodes[i].childNodes.length > 0) {
			expandNodes(node.childNodes[i], value);
		}
	}
};*/
/** 树权限（全选/全不选） */
const handleCheckedTreeNodeAll = (value: boolean) => {
	menuRef.value.setCheckedKeys(value ? getCode(state.menuTableData) : []);
};
// 保存
const onSubmit = () => {
	let systemMenuArr = menuRef.value.getCheckedNodes(); // 获取选中
	const halfCheck = [];
	/*let halfCheck = menuRef.value.getHalfCheckedNodes(); // 获取半选节点
  halfCheck = halfCheck.map((v: any) => {
    return {
      code: v.permissionCode,
      type: v.menuType,
    };
  });*/
	systemMenuArr = systemMenuArr.map((v: any) => {
		return {
			code: v.permissionCode,
			type: v.menuType,
		};
	});
	let req = {
		roleId: state.currentRow.id,
		roleCode: state.currentRow.name,
		systemMenuArr: [...systemMenuArr, ...halfCheck],
	};
	state.loading = true;
	setRolePower(req)
		.then(() => {
			ElMessage({
				message: '操作成功',
				type: 'success',
			});
			closeDialog();
			emit('updateList');
			state.loading = false;
		})
		.catch(() => {
			// 新增失败
			closeDialog();
			state.loading = false;
		});
};
// 暴露变量
defineExpose({
	openDialog,
	closeDialog,
});
</script>

<style scoped lang="scss">
:deep(.el-table td.el-table__cell div.cell) {
	display: flex;
	box-sizing: border-box;
	align-items: center;
}
.border-box {
	border: var(--el-border);
	border-radius: var(--el-border-radius-base);
	padding: 15px;
	margin-top: 15px;
}
:deep(.el-tree-node.is-expanded.is-penultimate > .el-tree-node__children) {
	display: flex;
	flex-direction: row;
	flex-wrap: wrap;
}
:deep(.is-penultimate > .el-tree-node__children > div) {
	width: 25%;
}
</style>
