<template>
	<div class="system-edit-role-container">
		<el-dialog title="权限配置" v-model="state.isShowDialog" draggable @opened="opened">
			<div class="custom-tree-node-container">
				<el-table :data="state.menuTableData" stripe row-key="permissionCode" border :expand-row-keys="state.expandRowKeys">
					<el-table-column width="180" label="菜单">
						<template #default="scope">
							<el-checkbox
								v-if="scope.row.children"
								:indeterminate="scope.row.indeterminate"
								v-model="scope.row.checked"
								@change="changeRowSelect(scope.row)"
								>{{ scope.row.pageName }}</el-checkbox
							>
							<el-checkbox v-else v-model="scope.row.checked" @change="changeRowSelect(scope.row)">{{ scope.row.pageName }}</el-checkbox>
						</template>
					</el-table-column>
					<el-table-column prop="children" label="按钮">
						<template #default="scope">
							<el-checkbox-group v-model="state.systemButtonArr" @change="handleCheckedBtnChange">
								<el-checkbox v-for="item in scope.row.buttonArr" :key="item.id" :label="item.permissionCode"
									><span v-if="showSetting">{{ item.permissionCode }}-{{ item.btnName }}</span>
									<span v-else>{{ item.btnName }}</span>
								</el-checkbox>
							</el-checkbox-group>
						</template>
					</el-table-column>
				</el-table>
			</div>
			<template #footer>
				<span class="dialog-footer">
					<el-button class="default-button"><el-checkbox v-model="state.checkedAll" @change="changeAllSelect">全选</el-checkbox></el-button>
					<el-button @click="onCancel" class="default-button">取 消</el-button>
					<el-button type="primary" @click="onSubmit">确 定</el-button>
				</span>
			</template>
		</el-dialog>
	</div>
</template>

<script setup lang="ts" name="systemEditRole">
import { reactive, onMounted, computed } from 'vue';
import { ElMessage } from 'element-plus';
import { storeToRefs } from 'pinia';
import { useUserInfo } from '/@/stores/userInfo';
import { getMenuList } from '/@/api/system/menu';
import { getRolePower, setRolePower } from '/@/api/system/roles';

// 定义子组件向父组件传值/事件
const emit = defineEmits(['updateList']);

// 定义变量内容
const state = reactive<any>({
	isShowDialog: false,
	menuTableData: <any>[],
	systemMenuArr: <any>[],
	systemButtonArr: <any>[],
	currentRow: {},
	checkedAll: false,
	expandRowKeys:[]
});
const storesUserInfo = useUserInfo();
const { userInfos } = storeToRefs(storesUserInfo);
// 打开弹窗
const openDialog = (row: any) => {
	state.currentRow = row;
	state.systemMenuArr = <any>[];
	state.systemButtonArr = <any>[];
	const loop = (data: any) => {
		data.forEach((item: any) => {
			item.checked = false;
			if (item.children && item.children.length) {
				loop(item.children);
			}
		});
	};
	loop(state.menuTableData);
	if (userInfos.value.authBtnList.includes('100205')) {
		getRolePower({ roleid: row.id }).then((res: any) => {
			state.systemMenuArr = res.result?.systemMenuArr ?? [];
			state.systemButtonArr = res.result?.systemButtonArr ?? [];
			const loop = (data: any) => {
				data.forEach((item: any) => {
					for (let i of state.systemMenuArr) {
						if (item.permissionCode === i) {
							item.checked = true;
							if (item.children && item.children.length) {
								loop(item.children);
							}
						}
					}
				});
			};
			loop(state.menuTableData);
			state.expandRowKeys = state.systemMenuArr;
			state.isShowDialog = true;
		});
	} else {
		ElMessage.warning('您没有获取角色权限的权限');
	}
};
// 检查是否全选
const opened = () => {
	const loopMenu = (data: any) => {
		return data.every((item: any) => {
			if (item.children && item.children.length) {
				loopMenu(item.children);
			}
			return item.checked;
		});
	};
	state.checkedAll = loopMenu(state.menuTableData);
};
// 关闭弹窗
const closeDialog = () => {
	state.isShowDialog = false;
};
// 取消
const onCancel = () => {
	closeDialog();
};
// 获取所有菜单
const getMenuListApi = () => {
	getMenuList().then((res: any) => {
		state.menuTableData = res?.result ?? [];
	});
};
// 开发环境不显示设置
const showSetting = computed(() => {
	return import.meta.env.VITE_MODE_NAME === 'development';
});

// 选择表格(全选)
const changeAllSelect = (val: any) => {
	const loop = (data: any) => {
		data.forEach((item: any) => {
			item.checked = val;
			if ('indeterminate' in item) {
				item.indeterminate = false;
			}
			if (item.buttonArr && item.buttonArr.length) {
				item.buttonArr.forEach((item: any) => {
					if (val) {
						state.systemButtonArr.push(item.permissionCode);
					} else {
						for (let i in state.systemButtonArr) {
							if (state.systemButtonArr[i] === item.permissionCode) {
								state.systemButtonArr.splice(i, 1);
							}
						}
					}
				});
			}
			state.systemButtonArr = Array.from(new Set(state.systemButtonArr));
			if (item.children && item.children.length) {
				loop(item.children);
			}
		});
	};
	loop(state.menuTableData);
};
const find = (v: any, list: any[]) => {
	let data;
	(list || []).map((i) => {
		if (i.id === v) {
			data = i;
		} else {
			const child = find(v, i.children);
			if (child) {
				data = child;
			}
		}
	});
	return data;
};
// 选择表格(表格行选择)
const changeRowSelect = (val: any) => {
	const loopBtn = (data: any, checked = val.checked) => {
		data.forEach((item: any) => {
			if (checked) {
				state.systemButtonArr.push(item.permissionCode);
			} else {
				for (let i in state.systemButtonArr) {
					if (state.systemButtonArr[i] === item.permissionCode) {
						state.systemButtonArr.splice(i, 1);
					}
				}
			}
			if (item.buttonArr && item.buttonArr.length) {
				loopBtn(item.buttonArr);
			}
		});
	};
	const loop = (data: any) => {
		data.forEach((item: any) => {
			item.checked = val.checked;
			if (item.children && item.children.length) {
				loop(item.children);
			}
			if (item.buttonArr && item.buttonArr.length) {
				loopBtn(item.buttonArr);
			}
		});
	};
	state.systemButtonArr = Array.from(new Set(state.systemButtonArr));
	if (val.buttonArr && val.buttonArr.length) {
		loopBtn(val.buttonArr);
	}
	if (val.children && val.children.length) {
		loop(val.children);
		if ('indeterminate' in val) {
			val.indeterminate = false;
		}
	} else {
		let checkedLeg = 0;
		const loop = (data: any) => {
			data.forEach((item: any) => {
				if (item.id === val.parentId) {
					// 获取当前父级下子级选中条数
					const leg = item.children.length;
					checkedLeg = item.children.filter((ss: any) => ss.checked).length;
					// 根据条数改变父级的indeterminate和checked
					if (checkedLeg === 0) {
						item.indeterminate = false;
						item.checked = false;
					} else if (checkedLeg < leg) {
						item.indeterminate = true;
						item.checked = false;
					} else if (checkedLeg === leg) {
						item.indeterminate = false;
						item.checked = true;
					}

					const currentI: any = find(item.parentId, state.menuTableData);
					if (currentI) {
						let checkedLeg1 = 0;
						const leg1 = currentI.children.length;
						checkedLeg1 = item.children.filter((ss: any) => ss.checked).length;
						// 根据条数改变父级的indeterminate和checked
						if (checkedLeg1 === 0) {
							currentI.indeterminate = false;
						} else if (checkedLeg < leg1) {
							currentI.indeterminate = true;
						} else if (checkedLeg === leg1) {
							currentI.indeterminate = false;
						}
					}
					return;
				}
				if (item.children && item.children.length) {
					loop(item.children);
				}
			});
		};
		loop(state.menuTableData);
	}
	// 判断是否全部选择了,改变全选框的样式
	let flag = true;
	state.menuTableData.some((item: any) => {
		if (!item.checked) {
			flag = false;
			return;
		}
	});
	state.checkedAll = flag;
};
// 选择按钮
const handleCheckedBtnChange = (value: string[]) => {
	state.systemButtonArr = value;
};
// 点击提交选中的表格
const handleSelectTable = () => {
	let selectedCodes = <any>[];
	const loop = (data: any) => {
		data.forEach((item: any) => {
			if (item.checked || item.indeterminate) {
				selectedCodes.push(item.permissionCode);
				if (item.children) {
					loop(item.children);
				}
			}
		});
	};
	loop(state.menuTableData);
	return selectedCodes;
};
// 保存
const onSubmit = () => {
	let req = {
		roleId: state.currentRow.id,
		roleCode: state.currentRow.name,
		systemMenuArr: handleSelectTable(),
		systemButtonArr: state.systemButtonArr,
	};
	setRolePower(req)
		.then(() => {
			ElMessage({
				message: '操作成功',
				type: 'success',
			});
			closeDialog();
			emit('updateList');
		})
		.catch(() => {
			// 新增失败
			closeDialog();
		});
};
onMounted(() => {
	getMenuListApi();
});
// 暴露变量
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;
}
</style>
